]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - sys/dev/mps/mps_mapping.c
Copy stable/10@r272459 to releng/10.1 as part of
[FreeBSD/releng/10.1.git] / sys / dev / mps / mps_mapping.c
1 /*-
2  * Copyright (c) 2011, 2012 LSI Corp.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * LSI MPT-Fusion Host Adapter FreeBSD
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 /* TODO Move headers to mpsvar */
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/kthread.h>
41 #include <sys/taskqueue.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 #include <sys/sysctl.h>
45 #include <sys/eventhandler.h>
46 #include <sys/uio.h>
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <dev/mps/mpi/mpi2_type.h>
50 #include <dev/mps/mpi/mpi2.h>
51 #include <dev/mps/mpi/mpi2_ioc.h>
52 #include <dev/mps/mpi/mpi2_sas.h>
53 #include <dev/mps/mpi/mpi2_cnfg.h>
54 #include <dev/mps/mpi/mpi2_init.h>
55 #include <dev/mps/mpi/mpi2_tool.h>
56 #include <dev/mps/mps_ioctl.h>
57 #include <dev/mps/mpsvar.h>
58 #include <dev/mps/mps_mapping.h>
59
60 /**
61  * _mapping_clear_entry - Clear a particular mapping entry.
62  * @map_entry: map table entry
63  *
64  * Returns nothing.
65  */
66 static inline void
67 _mapping_clear_map_entry(struct dev_mapping_table *map_entry)
68 {
69         map_entry->physical_id = 0;
70         map_entry->device_info = 0;
71         map_entry->phy_bits = 0;
72         map_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
73         map_entry->dev_handle = 0;
74         map_entry->channel = -1;
75         map_entry->id = -1;
76         map_entry->missing_count = 0;
77         map_entry->init_complete = 0;
78         map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
79 }
80
81 /**
82  * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
83  * @enc_entry: enclosure table entry
84  *
85  * Returns nothing.
86  */
87 static inline void
88 _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
89 {
90         enc_entry->enclosure_id = 0;
91         enc_entry->start_index = MPS_MAPTABLE_BAD_IDX;
92         enc_entry->phy_bits = 0;
93         enc_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
94         enc_entry->enc_handle = 0;
95         enc_entry->num_slots = 0;
96         enc_entry->start_slot = 0;
97         enc_entry->missing_count = 0;
98         enc_entry->removal_flag = 0;
99         enc_entry->skip_search = 0;
100         enc_entry->init_complete = 0;
101 }
102
103 /**
104  * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
105  * @sc: per adapter object
106  * @enc_entry: enclosure table entry
107  *
108  * Returns 0 for success, non-zero for failure.
109  */
110 static int
111 _mapping_commit_enc_entry(struct mps_softc *sc,
112     struct enc_mapping_table *et_entry)
113 {
114         Mpi2DriverMap0Entry_t *dpm_entry;
115         struct dev_mapping_table *mt_entry;
116         Mpi2ConfigReply_t mpi_reply;
117         Mpi2DriverMappingPage0_t config_page;
118
119         if (!sc->is_dpm_enable)
120                 return 0;
121
122         memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
123         memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
124             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
125         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
126             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
127         dpm_entry += et_entry->dpm_entry_num;
128         dpm_entry->PhysicalIdentifier.Low =
129             ( 0xFFFFFFFF & et_entry->enclosure_id);
130         dpm_entry->PhysicalIdentifier.High =
131             ( et_entry->enclosure_id >> 32);
132         mt_entry = &sc->mapping_table[et_entry->start_index];
133         dpm_entry->DeviceIndex = htole16(mt_entry->id);
134         dpm_entry->MappingInformation = et_entry->num_slots;
135         dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
136         dpm_entry->MappingInformation |= et_entry->missing_count;
137         dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
138         dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
139         dpm_entry->Reserved1 = 0;
140
141         memcpy(&config_page.Entry, (u8 *)dpm_entry,
142             sizeof(Mpi2DriverMap0Entry_t));
143         if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
144             et_entry->dpm_entry_num)) {
145                 printf("%s: write of dpm entry %d for enclosure failed\n",
146                     __func__, 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  * @enc_entry: enclosure table entry
166  *
167  * Returns 0 for success, non-zero for failure.
168  */
169
170 static int
171 _mapping_commit_map_entry(struct mps_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         memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
182         memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
183             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
184         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
185             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
186         dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
187         dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
188             mt_entry->physical_id);
189         dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
190         dpm_entry->DeviceIndex = htole16(mt_entry->id);
191         dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
192         dpm_entry->PhysicalBitsMapping = 0;
193         dpm_entry->Reserved1 = 0;
194         dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
195         memcpy(&config_page.Entry, (u8 *)dpm_entry,
196             sizeof(Mpi2DriverMap0Entry_t));
197         if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
198             mt_entry->dpm_entry_num)) {
199                 printf("%s: write of dpm entry %d for device failed\n",
200                     __func__, mt_entry->dpm_entry_num);
201                 dpm_entry->MappingInformation = le16toh(dpm_entry->
202                     MappingInformation);
203                 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
204                 return -1;
205         }
206
207         dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
208         dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
209         return 0;
210 }
211
212 /**
213  * _mapping_get_ir_maprange - get start and end index for IR map range.
214  * @sc: per adapter object
215  * @start_idx: place holder for start index
216  * @end_idx: place holder for end index
217  *
218  * The IR volumes can be mapped either at start or end of the mapping table
219  * this function gets the detail of where IR volume mapping starts and ends
220  * in the device mapping table
221  *
222  * Returns nothing.
223  */
224 static void
225 _mapping_get_ir_maprange(struct mps_softc *sc, u32 *start_idx, u32 *end_idx)
226 {
227         u16 volume_mapping_flags;
228         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
229
230         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
231             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
232         if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
233                 *start_idx = 0;
234                 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
235                         *start_idx = 1;
236         } else
237                 *start_idx = sc->max_devices - sc->max_volumes;
238         *end_idx = *start_idx + sc->max_volumes - 1;
239 }
240
241 /**
242  * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
243  * @sc: per adapter object
244  * @enc_id: enclosure logical identifier
245  *
246  * Returns the index of enclosure entry on success or bad index.
247  */
248 static u8
249 _mapping_get_enc_idx_from_id(struct mps_softc *sc, u64 enc_id,
250     u64 phy_bits)
251 {
252         struct enc_mapping_table *et_entry;
253         u8 enc_idx = 0;
254
255         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
256                 et_entry = &sc->enclosure_table[enc_idx];
257                 if ((et_entry->enclosure_id == le64toh(enc_id)) &&
258                     (!et_entry->phy_bits || (et_entry->phy_bits &
259                     le32toh(phy_bits))))
260                         return enc_idx;
261         }
262         return MPS_ENCTABLE_BAD_IDX;
263 }
264
265 /**
266  * _mapping_get_enc_idx_from_handle - get enclosure index from handle
267  * @sc: per adapter object
268  * @enc_id: enclosure handle
269  *
270  * Returns the index of enclosure entry on success or bad index.
271  */
272 static u8
273 _mapping_get_enc_idx_from_handle(struct mps_softc *sc, u16 handle)
274 {
275         struct enc_mapping_table *et_entry;
276         u8 enc_idx = 0;
277
278         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
279                 et_entry = &sc->enclosure_table[enc_idx];
280                 if (et_entry->missing_count)
281                         continue;
282                 if (et_entry->enc_handle == handle)
283                         return enc_idx;
284         }
285         return MPS_ENCTABLE_BAD_IDX;
286 }
287
288 /**
289  * _mapping_get_high_missing_et_idx - get missing enclosure index
290  * @sc: per adapter object
291  *
292  * Search through the enclosure table and identifies the enclosure entry
293  * with high missing count and returns it's index
294  *
295  * Returns the index of enclosure entry on success or bad index.
296  */
297 static u8
298 _mapping_get_high_missing_et_idx(struct mps_softc *sc)
299 {
300         struct enc_mapping_table *et_entry;
301         u8 high_missing_count = 0;
302         u8 enc_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
303
304         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
305                 et_entry = &sc->enclosure_table[enc_idx];
306                 if ((et_entry->missing_count > high_missing_count) &&
307                     !et_entry->skip_search) {
308                         high_missing_count =  et_entry->missing_count;
309                         high_idx = enc_idx;
310                 }
311         }
312         return high_idx;
313 }
314
315 /**
316  * _mapping_get_high_missing_mt_idx - get missing map table index
317  * @sc: per adapter object
318  *
319  * Search through the map table and identifies the device entry
320  * with high missing count and returns it's index
321  *
322  * Returns the index of map table entry on success or bad index.
323  */
324 static u32
325 _mapping_get_high_missing_mt_idx(struct mps_softc *sc)
326 {
327         u32 map_idx, high_idx = MPS_ENCTABLE_BAD_IDX;
328         u8 high_missing_count = 0;
329         u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
330         struct dev_mapping_table *mt_entry;
331         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
332
333         start_idx = 0;
334         start_idx_ir = 0;
335         end_idx_ir = 0;
336         end_idx = sc->max_devices;
337         if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
338                 start_idx = 1;
339         if (sc->ir_firmware) {
340                 _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
341                 if (start_idx == start_idx_ir)
342                         start_idx = end_idx_ir + 1;
343                 else
344                         end_idx = start_idx_ir;
345         }
346         mt_entry = &sc->mapping_table[start_idx];
347         for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
348                 if (mt_entry->missing_count > high_missing_count) {
349                         high_missing_count =  mt_entry->missing_count;
350                         high_idx = map_idx;
351                 }
352         }
353         return high_idx;
354 }
355
356 /**
357  * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
358  * @sc: per adapter object
359  * @wwid: world wide unique ID of the volume
360  *
361  * Returns the index of map table entry on success or bad index.
362  */
363 static u32
364 _mapping_get_ir_mt_idx_from_wwid(struct mps_softc *sc, u64 wwid)
365 {
366         u32 start_idx, end_idx, map_idx;
367         struct dev_mapping_table *mt_entry;
368
369         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
370         mt_entry = &sc->mapping_table[start_idx];
371         for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
372                 if (mt_entry->physical_id == wwid)
373                         return map_idx;
374
375         return MPS_MAPTABLE_BAD_IDX;
376 }
377
378 /**
379  * _mapping_get_mt_idx_from_id - get map table index from a device ID
380  * @sc: per adapter object
381  * @dev_id: device identifer (SAS Address)
382  *
383  * Returns the index of map table entry on success or bad index.
384  */
385 static u32
386 _mapping_get_mt_idx_from_id(struct mps_softc *sc, u64 dev_id)
387 {
388         u32 map_idx;
389         struct dev_mapping_table *mt_entry;
390
391         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
392                 mt_entry = &sc->mapping_table[map_idx];
393                 if (mt_entry->physical_id == dev_id)
394                         return map_idx;
395         }
396         return MPS_MAPTABLE_BAD_IDX;
397 }
398
399 /**
400  * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
401  * @sc: per adapter object
402  * @wwid: volume device handle
403  *
404  * Returns the index of map table entry on success or bad index.
405  */
406 static u32
407 _mapping_get_ir_mt_idx_from_handle(struct mps_softc *sc, u16 volHandle)
408 {
409         u32 start_idx, end_idx, map_idx;
410         struct dev_mapping_table *mt_entry;
411
412         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
413         mt_entry = &sc->mapping_table[start_idx];
414         for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
415                 if (mt_entry->dev_handle == volHandle)
416                         return map_idx;
417
418         return MPS_MAPTABLE_BAD_IDX;
419 }
420
421 /**
422  * _mapping_get_mt_idx_from_handle - get map table index from handle
423  * @sc: per adapter object
424  * @dev_id: device handle
425  *
426  * Returns the index of map table entry on success or bad index.
427  */
428 static u32
429 _mapping_get_mt_idx_from_handle(struct mps_softc *sc, u16 handle)
430 {
431         u32 map_idx;
432         struct dev_mapping_table *mt_entry;
433
434         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
435                 mt_entry = &sc->mapping_table[map_idx];
436                 if (mt_entry->dev_handle == handle)
437                         return map_idx;
438         }
439         return MPS_MAPTABLE_BAD_IDX;
440 }
441
442 /**
443  * _mapping_get_free_ir_mt_idx - get first free index for a volume
444  * @sc: per adapter object
445  *
446  * Search through mapping table for free index for a volume and if no free
447  * index then looks for a volume with high mapping index
448  *
449  * Returns the index of map table entry on success or bad index.
450  */
451 static u32
452 _mapping_get_free_ir_mt_idx(struct mps_softc *sc)
453 {
454         u8 high_missing_count = 0;
455         u32 start_idx, end_idx, map_idx;
456         u32 high_idx = MPS_MAPTABLE_BAD_IDX;
457         struct dev_mapping_table *mt_entry;
458
459         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
460
461         mt_entry = &sc->mapping_table[start_idx];
462         for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
463                 if (!(mt_entry->device_info & MPS_MAP_IN_USE))
464                         return map_idx;
465
466         mt_entry = &sc->mapping_table[start_idx];
467         for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
468                 if (mt_entry->missing_count > high_missing_count) {
469                         high_missing_count = mt_entry->missing_count;
470                         high_idx = map_idx;
471                 }
472         }
473         return high_idx;
474 }
475
476 /**
477  * _mapping_get_free_mt_idx - get first free index for a device
478  * @sc: per adapter object
479  * @start_idx: offset in the table to start search
480  *
481  * Returns the index of map table entry on success or bad index.
482  */
483 static u32
484 _mapping_get_free_mt_idx(struct mps_softc *sc, u32 start_idx)
485 {
486         u32 map_idx, max_idx = sc->max_devices;
487         struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
488         u16 volume_mapping_flags;
489
490         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
491             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
492         if (sc->ir_firmware && (volume_mapping_flags ==
493             MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
494                 max_idx -= sc->max_volumes;
495         for (map_idx  = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
496                 if (!(mt_entry->device_info & (MPS_MAP_IN_USE |
497                     MPS_DEV_RESERVED)))
498                         return map_idx;
499
500         return MPS_MAPTABLE_BAD_IDX;
501 }
502
503 /**
504  * _mapping_get_dpm_idx_from_id - get DPM index from ID
505  * @sc: per adapter object
506  * @id: volume WWID or enclosure ID or device ID
507  *
508  * Returns the index of DPM entry on success or bad index.
509  */
510 static u16
511 _mapping_get_dpm_idx_from_id(struct mps_softc *sc, u64 id, u32 phy_bits)
512 {
513         u16 entry_num;
514         uint64_t PhysicalIdentifier;
515         Mpi2DriverMap0Entry_t *dpm_entry;
516
517         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
518             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
519         PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
520         PhysicalIdentifier = (PhysicalIdentifier << 32) | 
521             dpm_entry->PhysicalIdentifier.Low;
522         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
523             dpm_entry++)
524                 if ((id == PhysicalIdentifier) &&
525                     (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
526                     (phy_bits & dpm_entry->PhysicalBitsMapping)))
527                         return entry_num;
528
529         return MPS_DPM_BAD_IDX;
530 }
531
532
533 /**
534  * _mapping_get_free_dpm_idx - get first available DPM index
535  * @sc: per adapter object
536  *
537  * Returns the index of DPM entry on success or bad index.
538  */
539 static u32
540 _mapping_get_free_dpm_idx(struct mps_softc *sc)
541 {
542         u16 entry_num;
543
544         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
545                 if (!sc->dpm_entry_used[entry_num])
546                         return entry_num;
547         }
548         return MPS_DPM_BAD_IDX;
549 }
550
551 /**
552  * _mapping_update_ir_missing_cnt - Updates missing count for a volume
553  * @sc: per adapter object
554  * @map_idx: map table index of the volume
555  * @element: IR configuration change element
556  * @wwid: IR volume ID.
557  *
558  * Updates the missing count in the map table and in the DPM entry for a volume
559  *
560  * Returns nothing.
561  */
562 static void
563 _mapping_update_ir_missing_cnt(struct mps_softc *sc, u32 map_idx,
564     Mpi2EventIrConfigElement_t *element, u64 wwid)
565 {
566         struct dev_mapping_table *mt_entry;
567         u8 missing_cnt, reason = element->ReasonCode;
568         u16 dpm_idx;
569         Mpi2DriverMap0Entry_t *dpm_entry;
570
571         if (!sc->is_dpm_enable)
572                 return;
573         mt_entry = &sc->mapping_table[map_idx];
574         if (reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) {
575                 mt_entry->missing_count = 0;
576         } else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
577                 mt_entry->missing_count = 0;
578                 mt_entry->init_complete = 0;
579         } else if ((reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED) ||
580             (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)) {
581                 if (!mt_entry->init_complete) {
582                         if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
583                                 mt_entry->missing_count++;
584                         else
585                                 mt_entry->init_complete = 1;
586                 }
587                 if (!mt_entry->missing_count)
588                         mt_entry->missing_count++;
589                 mt_entry->dev_handle = 0;
590         }
591
592         dpm_idx = mt_entry->dpm_entry_num;
593         if (dpm_idx == MPS_DPM_BAD_IDX) {
594                 if ((reason == MPI2_EVENT_IR_CHANGE_RC_ADDED) ||
595                     (reason == MPI2_EVENT_IR_CHANGE_RC_REMOVED))
596                         dpm_idx = _mapping_get_dpm_idx_from_id(sc,
597                             mt_entry->physical_id, 0);
598                 else if (reason == MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED)
599                         return;
600         }
601         if (dpm_idx != MPS_DPM_BAD_IDX) {
602                 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
603                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
604                 dpm_entry += dpm_idx;
605                 missing_cnt = dpm_entry->MappingInformation &
606                     MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
607                 if ((mt_entry->physical_id ==
608                     le64toh((u64)dpm_entry->PhysicalIdentifier.High |
609                     dpm_entry->PhysicalIdentifier.Low)) && (missing_cnt ==
610                     mt_entry->missing_count))
611                         mt_entry->init_complete = 1;
612         } else {
613                 dpm_idx = _mapping_get_free_dpm_idx(sc);
614                 mt_entry->init_complete = 0;
615         }
616
617         if ((dpm_idx != MPS_DPM_BAD_IDX) && !mt_entry->init_complete) {
618                 mt_entry->init_complete = 1;
619                 mt_entry->dpm_entry_num = dpm_idx;
620                 dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
621                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
622                 dpm_entry += dpm_idx;
623                 dpm_entry->PhysicalIdentifier.Low =
624                     (0xFFFFFFFF & mt_entry->physical_id);
625                 dpm_entry->PhysicalIdentifier.High =
626                     (mt_entry->physical_id >> 32);
627                 dpm_entry->DeviceIndex = map_idx;
628                 dpm_entry->MappingInformation = mt_entry->missing_count;
629                 dpm_entry->PhysicalBitsMapping = 0;
630                 dpm_entry->Reserved1 = 0;
631                 sc->dpm_flush_entry[dpm_idx] = 1;
632                 sc->dpm_entry_used[dpm_idx] = 1;
633         } else if (dpm_idx == MPS_DPM_BAD_IDX) {
634                 printf("%s: no space to add entry in DPM table\n", __func__);
635                 mt_entry->init_complete = 1;
636         }
637 }
638
639 /**
640  * _mapping_add_to_removal_table - mark an entry for removal
641  * @sc: per adapter object
642  * @handle: Handle of enclosures/device/volume
643  *
644  * Adds the handle or DPM entry number in removal table.
645  *
646  * Returns nothing.
647  */
648 static void
649 _mapping_add_to_removal_table(struct mps_softc *sc, u16 handle,
650     u16 dpm_idx)
651 {
652         struct map_removal_table *remove_entry;
653         u32 i;
654         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
655
656         remove_entry = sc->removal_table;
657
658         for (i = 0; i < sc->max_devices; i++, remove_entry++) {
659                 if (remove_entry->dev_handle || remove_entry->dpm_entry_num !=
660                     MPS_DPM_BAD_IDX)
661                         continue;
662                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
663                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
664                         if (dpm_idx)
665                                 remove_entry->dpm_entry_num = dpm_idx;
666                         if (remove_entry->dpm_entry_num == MPS_DPM_BAD_IDX)
667                                 remove_entry->dev_handle = handle;
668                 } else if ((ioc_pg8_flags &
669                     MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
670                     MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING)
671                         remove_entry->dev_handle = handle;
672                 break;
673         }
674
675 }
676
677 /**
678  * _mapping_update_missing_count - Update missing count for a device
679  * @sc: per adapter object
680  * @topo_change: Topology change event entry
681  *
682  * Search through the topology change list and if any device is found not
683  * responding it's associated map table entry and DPM entry is updated
684  *
685  * Returns nothing.
686  */
687 static void
688 _mapping_update_missing_count(struct mps_softc *sc,
689     struct _map_topology_change *topo_change)
690 {
691         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
692         u8 entry;
693         struct _map_phy_change *phy_change;
694         u32 map_idx;
695         struct dev_mapping_table *mt_entry;
696         Mpi2DriverMap0Entry_t *dpm_entry;
697
698         for (entry = 0; entry < topo_change->num_entries; entry++) {
699                 phy_change = &topo_change->phy_details[entry];
700                 if (!phy_change->dev_handle || (phy_change->reason !=
701                     MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
702                         continue;
703                 map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
704                     dev_handle);
705                 phy_change->is_processed = 1;
706                 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
707                         printf("%s: device is already removed from mapping "
708                             "table\n", __func__);
709                         continue;
710                 }
711                 mt_entry = &sc->mapping_table[map_idx];
712                 if (!mt_entry->init_complete) {
713                         if (mt_entry->missing_count < MPS_MAX_MISSING_COUNT)
714                                 mt_entry->missing_count++;
715                         else
716                                 mt_entry->init_complete = 1;
717                 }
718                 if (!mt_entry->missing_count)
719                         mt_entry->missing_count++;
720                 _mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
721                 mt_entry->dev_handle = 0;
722
723                 if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
724                     MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
725                     sc->is_dpm_enable && !mt_entry->init_complete &&
726                     mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
727                         dpm_entry =
728                             (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
729                             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
730                         dpm_entry += mt_entry->dpm_entry_num;
731                         dpm_entry->MappingInformation = mt_entry->missing_count;
732                         sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
733                 }
734                 mt_entry->init_complete = 1;
735         }
736 }
737
738 /**
739  * _mapping_find_enc_map_space -find map table entries for enclosure
740  * @sc: per adapter object
741  * @et_entry: enclosure entry
742  *
743  * Search through the mapping table defragment it and provide contiguous
744  * space in map table for a particular enclosure entry
745  *
746  * Returns start index in map table or bad index.
747  */
748 static u32
749 _mapping_find_enc_map_space(struct mps_softc *sc,
750     struct enc_mapping_table *et_entry)
751 {
752         u16 vol_mapping_flags;
753         u32 skip_count, end_of_table, map_idx, enc_idx;
754         u16 num_found;
755         u32 start_idx = MPS_MAPTABLE_BAD_IDX;
756         struct dev_mapping_table *mt_entry;
757         struct enc_mapping_table *enc_entry;
758         unsigned char done_flag = 0, found_space;
759         u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
760
761         skip_count = sc->num_rsvd_entries;
762         num_found = 0;
763
764         vol_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
765             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
766
767         if (!sc->ir_firmware)
768                 end_of_table = sc->max_devices;
769         else if (vol_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING)
770                 end_of_table = sc->max_devices;
771         else
772                 end_of_table = sc->max_devices - sc->max_volumes;
773
774         for (map_idx = (max_num_phy_ids + skip_count);
775             map_idx < end_of_table; map_idx++) {
776                 mt_entry = &sc->mapping_table[map_idx];
777                 if ((et_entry->enclosure_id == mt_entry->physical_id) &&
778                     (!mt_entry->phy_bits || (mt_entry->phy_bits &
779                     et_entry->phy_bits))) {
780                         num_found += 1;
781                         if (num_found == et_entry->num_slots) {
782                                 start_idx = (map_idx - num_found) + 1;
783                                 return start_idx;
784                         }
785                 } else
786                         num_found = 0;
787         }
788         for (map_idx = (max_num_phy_ids + skip_count);
789             map_idx < end_of_table; map_idx++) {
790                 mt_entry = &sc->mapping_table[map_idx];
791                 if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
792                         num_found += 1;
793                         if (num_found == et_entry->num_slots) {
794                                 start_idx = (map_idx - num_found) + 1;
795                                 return start_idx;
796                         }
797                 } else
798                         num_found = 0;
799         }
800
801         while (!done_flag) {
802                 enc_idx = _mapping_get_high_missing_et_idx(sc);
803                 if (enc_idx == MPS_ENCTABLE_BAD_IDX)
804                         return MPS_MAPTABLE_BAD_IDX;
805                 enc_entry = &sc->enclosure_table[enc_idx];
806                 /*VSP FIXME*/
807                 enc_entry->skip_search = 1;
808                 mt_entry = &sc->mapping_table[enc_entry->start_index];
809                 for (map_idx = enc_entry->start_index; map_idx <
810                     (enc_entry->start_index + enc_entry->num_slots); map_idx++,
811                     mt_entry++)
812                         mt_entry->device_info  &= ~MPS_DEV_RESERVED;
813                 found_space = 0;
814                 for (map_idx = (max_num_phy_ids +
815                     skip_count); map_idx < end_of_table; map_idx++) {
816                         mt_entry = &sc->mapping_table[map_idx];
817                         if (!(mt_entry->device_info & MPS_DEV_RESERVED)) {
818                                 num_found += 1;
819                                 if (num_found == et_entry->num_slots) {
820                                         start_idx = (map_idx - num_found) + 1;
821                                         found_space = 1;
822                                 }
823                         } else
824                                 num_found = 0;
825                 }
826
827                 if (!found_space)
828                         continue;
829                 for (map_idx = start_idx; map_idx < (start_idx + num_found);
830                     map_idx++) {
831                         enc_entry = sc->enclosure_table;
832                         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
833                             enc_idx++, enc_entry++) {
834                                 if (map_idx < enc_entry->start_index ||
835                                     map_idx > (enc_entry->start_index +
836                                     enc_entry->num_slots))
837                                         continue;
838                                 if (!enc_entry->removal_flag) {
839                                         enc_entry->removal_flag = 1;
840                                         _mapping_add_to_removal_table(sc, 0,
841                                             enc_entry->dpm_entry_num);
842                                 }
843                                 mt_entry = &sc->mapping_table[map_idx];
844                                 if (mt_entry->device_info &
845                                     MPS_MAP_IN_USE) {
846                                         _mapping_add_to_removal_table(sc,
847                                             mt_entry->dev_handle, 0);
848                                         _mapping_clear_map_entry(mt_entry);
849                                 }
850                                 if (map_idx == (enc_entry->start_index +
851                                     enc_entry->num_slots - 1))
852                                         _mapping_clear_enc_entry(et_entry);
853                         }
854                 }
855                 enc_entry = sc->enclosure_table;
856                 for (enc_idx = 0; enc_idx < sc->num_enc_table_entries;
857                     enc_idx++, enc_entry++) {
858                         if (!enc_entry->removal_flag) {
859                                 mt_entry = &sc->mapping_table[enc_entry->
860                                     start_index];
861                                 for (map_idx = enc_entry->start_index; map_idx <
862                                     (enc_entry->start_index +
863                                     enc_entry->num_slots); map_idx++,
864                                     mt_entry++)
865                                         mt_entry->device_info |=
866                                             MPS_DEV_RESERVED;
867                                 et_entry->skip_search = 0;
868                         }
869                 }
870                 done_flag = 1;
871         }
872         return start_idx;
873 }
874
875 /**
876  * _mapping_get_dev_info -get information about newly added devices
877  * @sc: per adapter object
878  * @topo_change: Topology change event entry
879  *
880  * Search through the topology change event list and issues sas device pg0
881  * requests for the newly added device and reserved entries in tables
882  *
883  * Returns nothing
884  */
885 static void
886 _mapping_get_dev_info(struct mps_softc *sc,
887     struct _map_topology_change *topo_change)
888 {
889         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
890         Mpi2ConfigReply_t mpi_reply;
891         Mpi2SasDevicePage0_t sas_device_pg0;
892         u8 entry, enc_idx, phy_idx;
893         u32 map_idx, index, device_info;
894         struct _map_phy_change *phy_change, *tmp_phy_change;
895         uint64_t sas_address;
896         struct enc_mapping_table *et_entry;
897         struct dev_mapping_table *mt_entry;
898         u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
899         int rc;
900
901         for (entry = 0; entry < topo_change->num_entries; entry++) {
902                 phy_change = &topo_change->phy_details[entry];
903                 if (phy_change->is_processed || !phy_change->dev_handle ||
904                     phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED)
905                         continue;
906                 if (mps_config_get_sas_device_pg0(sc, &mpi_reply,
907                     &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
908                     phy_change->dev_handle)) {
909                         phy_change->is_processed = 1;
910                         continue;
911                 }
912
913                 device_info = le32toh(sas_device_pg0.DeviceInfo);
914                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
915                     MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
916                         if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
917                             (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
918                                 rc = mpssas_get_sas_address_for_sata_disk(sc,
919                                     &sas_address, phy_change->dev_handle,
920                                     device_info);
921                                 if (rc) {
922                                         printf("%s: failed to compute the "
923                                             "hashed SAS Address for SATA "
924                                             "device with handle 0x%04x\n",
925                                             __func__, phy_change->dev_handle);
926                                         sas_address =
927                                             sas_device_pg0.SASAddress.High;
928                                         sas_address = (sas_address << 32) |
929                                             sas_device_pg0.SASAddress.Low;
930                                 }
931                                 mps_dprint(sc, MPS_MAPPING,
932                                     "SAS Address for SATA device = %jx\n",
933                                     sas_address);
934                         } else {
935                                 sas_address =
936                                         sas_device_pg0.SASAddress.High;
937                                 sas_address = (sas_address << 32) |
938                                         sas_device_pg0.SASAddress.Low;
939                         }
940                 } else {
941                         sas_address = sas_device_pg0.SASAddress.High;
942                         sas_address = (sas_address << 32) |
943                            sas_device_pg0.SASAddress.Low;
944                 }
945                 phy_change->physical_id = sas_address;
946                 phy_change->slot = le16toh(sas_device_pg0.Slot);
947                 phy_change->device_info =
948                     le32toh(sas_device_pg0.DeviceInfo);
949
950                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
951                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
952                         enc_idx = _mapping_get_enc_idx_from_handle(sc,
953                             topo_change->enc_handle);
954                         if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
955                                 phy_change->is_processed = 1;
956                                 printf("%s: failed to add the device with "
957                                     "handle 0x%04x because the enclosure is "
958                                     "not in the mapping table\n", __func__,
959                                     phy_change->dev_handle);
960                                 continue;
961                         }
962                         if (!((phy_change->device_info &
963                             MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
964                             (phy_change->device_info &
965                             (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
966                             MPI2_SAS_DEVICE_INFO_STP_TARGET |
967                             MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
968                                 phy_change->is_processed = 1;
969                                 continue;
970                         }
971                         et_entry = &sc->enclosure_table[enc_idx];
972                         if (et_entry->start_index != MPS_MAPTABLE_BAD_IDX)
973                                 continue;
974                         if (!topo_change->exp_handle) {
975                                 map_idx = sc->num_rsvd_entries;
976                                 et_entry->start_index = map_idx;
977                         } else {
978                                 map_idx = _mapping_find_enc_map_space(sc,
979                                     et_entry);
980                                 et_entry->start_index = map_idx;
981                                 if (et_entry->start_index ==
982                                     MPS_MAPTABLE_BAD_IDX) {
983                                         phy_change->is_processed = 1;
984                                         for (phy_idx = 0; phy_idx <
985                                             topo_change->num_entries;
986                                             phy_idx++) {
987                                                 tmp_phy_change =
988                                                     &topo_change->phy_details
989                                                     [phy_idx];
990                                                 if (tmp_phy_change->reason ==
991                                                     add_code)
992                                                         tmp_phy_change->
993                                                             is_processed = 1;
994                                         }
995                                         break;
996                                 }
997                         }
998                         mt_entry = &sc->mapping_table[map_idx];
999                         for (index = map_idx; index < (et_entry->num_slots
1000                             + map_idx); index++, mt_entry++) {
1001                                 mt_entry->device_info = MPS_DEV_RESERVED;
1002                                 mt_entry->physical_id = et_entry->enclosure_id;
1003                                 mt_entry->phy_bits = et_entry->phy_bits;
1004                         }
1005                 }
1006         }
1007 }
1008
1009 /**
1010  * _mapping_set_mid_to_eid -set map table data from enclosure table
1011  * @sc: per adapter object
1012  * @et_entry: enclosure entry
1013  *
1014  * Returns nothing
1015  */
1016 static inline void
1017 _mapping_set_mid_to_eid(struct mps_softc *sc,
1018     struct enc_mapping_table *et_entry)
1019 {
1020         struct dev_mapping_table *mt_entry;
1021         u16 slots = et_entry->num_slots, map_idx;
1022         u32 start_idx = et_entry->start_index;
1023         if (start_idx != MPS_MAPTABLE_BAD_IDX) {
1024                 mt_entry = &sc->mapping_table[start_idx];
1025                 for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
1026                         mt_entry->physical_id = et_entry->enclosure_id;
1027         }
1028 }
1029
1030 /**
1031  * _mapping_clear_removed_entries - mark the entries to be cleared
1032  * @sc: per adapter object
1033  *
1034  * Search through the removal table and mark the entries which needs to be
1035  * flushed to DPM and also updates the map table and enclosure table by
1036  * clearing the corresponding entries.
1037  *
1038  * Returns nothing
1039  */
1040 static void
1041 _mapping_clear_removed_entries(struct mps_softc *sc)
1042 {
1043         u32 remove_idx;
1044         struct map_removal_table *remove_entry;
1045         Mpi2DriverMap0Entry_t *dpm_entry;
1046         u8 done_flag = 0, num_entries, m, i;
1047         struct enc_mapping_table *et_entry, *from, *to;
1048         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1049
1050         if (sc->is_dpm_enable) {
1051                 remove_entry = sc->removal_table;
1052                 for (remove_idx = 0; remove_idx < sc->max_devices;
1053                     remove_idx++, remove_entry++) {
1054                         if (remove_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1055                                 dpm_entry = (Mpi2DriverMap0Entry_t *)
1056                                     ((u8 *) sc->dpm_pg0 +
1057                                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1058                                 dpm_entry += remove_entry->dpm_entry_num;
1059                                 dpm_entry->PhysicalIdentifier.Low = 0;
1060                                 dpm_entry->PhysicalIdentifier.High = 0;
1061                                 dpm_entry->DeviceIndex = 0;
1062                                 dpm_entry->MappingInformation = 0;
1063                                 dpm_entry->PhysicalBitsMapping = 0;
1064                                 sc->dpm_flush_entry[remove_entry->
1065                                     dpm_entry_num] = 1;
1066                                 sc->dpm_entry_used[remove_entry->dpm_entry_num]
1067                                     = 0;
1068                                 remove_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1069                         }
1070                 }
1071         }
1072         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1073             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1074                 num_entries = sc->num_enc_table_entries;
1075                 while (!done_flag) {
1076                         done_flag = 1;
1077                         et_entry = sc->enclosure_table;
1078                         for (i = 0; i < num_entries; i++, et_entry++) {
1079                                 if (!et_entry->enc_handle && et_entry->
1080                                     init_complete) {
1081                                         done_flag = 0;
1082                                         if (i != (num_entries - 1)) {
1083                                                 from = &sc->enclosure_table
1084                                                     [i+1];
1085                                                 to = &sc->enclosure_table[i];
1086                                                 for (m = i; m < (num_entries -
1087                                                     1); m++, from++, to++) {
1088                                                         _mapping_set_mid_to_eid
1089                                                             (sc, to);
1090                                                         *to = *from;
1091                                                 }
1092                                                 _mapping_clear_enc_entry(to);
1093                                                 sc->num_enc_table_entries--;
1094                                                 num_entries =
1095                                                     sc->num_enc_table_entries;
1096                                         } else {
1097                                                 _mapping_clear_enc_entry
1098                                                     (et_entry);
1099                                                 sc->num_enc_table_entries--;
1100                                                 num_entries =
1101                                                     sc->num_enc_table_entries;
1102                                         }
1103                                 }
1104                         }
1105                 }
1106         }
1107 }
1108
1109 /**
1110  * _mapping_add_new_device -Add the new device into mapping table
1111  * @sc: per adapter object
1112  * @topo_change: Topology change event entry
1113  *
1114  * Search through the topology change event list and updates map table,
1115  * enclosure table and DPM pages for for the newly added devices.
1116  *
1117  * Returns nothing
1118  */
1119 static void
1120 _mapping_add_new_device(struct mps_softc *sc,
1121     struct _map_topology_change *topo_change)
1122 {
1123         u8 enc_idx, missing_cnt, is_removed = 0;
1124         u16 dpm_idx;
1125         u32 search_idx, map_idx;
1126         u32 entry;
1127         struct dev_mapping_table *mt_entry;
1128         struct enc_mapping_table *et_entry;
1129         struct _map_phy_change *phy_change;
1130         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1131         Mpi2DriverMap0Entry_t *dpm_entry;
1132         uint64_t temp64_var;
1133         u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1134         u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
1135         u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1136
1137         for (entry = 0; entry < topo_change->num_entries; entry++) {
1138                 phy_change = &topo_change->phy_details[entry];
1139                 if (phy_change->is_processed)
1140                         continue;
1141                 if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
1142                     !phy_change->dev_handle) {
1143                         phy_change->is_processed = 1;
1144                         continue;
1145                 }
1146                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1147                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1148                         enc_idx = _mapping_get_enc_idx_from_handle
1149                             (sc, topo_change->enc_handle);
1150                         if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1151                                 phy_change->is_processed = 1;
1152                                 printf("%s: failed to add the device with "
1153                                     "handle 0x%04x because the enclosure is "
1154                                     "not in the mapping table\n", __func__,
1155                                     phy_change->dev_handle);
1156                                 continue;
1157                         }
1158                         et_entry = &sc->enclosure_table[enc_idx];
1159                         if (et_entry->start_index == MPS_MAPTABLE_BAD_IDX) {
1160                                 phy_change->is_processed = 1;
1161                                 if (!sc->mt_full_retry) {
1162                                         sc->mt_add_device_failed = 1;
1163                                         continue;
1164                                 }
1165                                 printf("%s: failed to add the device with "
1166                                     "handle 0x%04x because there is no free "
1167                                     "space available in the mapping table\n",
1168                                     __func__, phy_change->dev_handle);
1169                                 continue;
1170                         }
1171                         map_idx = et_entry->start_index + phy_change->slot -
1172                             et_entry->start_slot;
1173                         mt_entry = &sc->mapping_table[map_idx];
1174                         mt_entry->physical_id = phy_change->physical_id;
1175                         mt_entry->channel = 0;
1176                         mt_entry->id = map_idx;
1177                         mt_entry->dev_handle = phy_change->dev_handle;
1178                         mt_entry->missing_count = 0;
1179                         mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
1180                         mt_entry->device_info = phy_change->device_info |
1181                             (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1182                         if (sc->is_dpm_enable) {
1183                                 dpm_idx = et_entry->dpm_entry_num;
1184                                 if (dpm_idx == MPS_DPM_BAD_IDX)
1185                                         dpm_idx = _mapping_get_dpm_idx_from_id
1186                                             (sc, et_entry->enclosure_id,
1187                                              et_entry->phy_bits);
1188                                 if (dpm_idx == MPS_DPM_BAD_IDX) {
1189                                         dpm_idx = _mapping_get_free_dpm_idx(sc);
1190                                         if (dpm_idx != MPS_DPM_BAD_IDX) {
1191                                                 dpm_entry =
1192                                                     (Mpi2DriverMap0Entry_t *)
1193                                                     ((u8 *) sc->dpm_pg0 +
1194                                                      hdr_sz);
1195                                                 dpm_entry += dpm_idx;
1196                                                 dpm_entry->
1197                                                     PhysicalIdentifier.Low =
1198                                                     (0xFFFFFFFF &
1199                                                     et_entry->enclosure_id);
1200                                                 dpm_entry->
1201                                                     PhysicalIdentifier.High =
1202                                                     ( et_entry->enclosure_id
1203                                                      >> 32);
1204                                                 dpm_entry->DeviceIndex =
1205                                                     (U16)et_entry->start_index;
1206                                                 dpm_entry->MappingInformation =
1207                                                         et_entry->num_slots;
1208                                                 dpm_entry->MappingInformation
1209                                                     <<= map_shift;
1210                                                 dpm_entry->PhysicalBitsMapping
1211                                                     = et_entry->phy_bits;
1212                                                 et_entry->dpm_entry_num =
1213                                                     dpm_idx;
1214                 /* FIXME Do I need to set the dpm_idxin mt_entry too */
1215                                                 sc->dpm_entry_used[dpm_idx] = 1;
1216                                                 sc->dpm_flush_entry[dpm_idx] =
1217                                                     1;
1218                                                 phy_change->is_processed = 1;
1219                                         } else {
1220                                                 phy_change->is_processed = 1;
1221                                                 mps_dprint(sc, MPS_INFO, "%s: "
1222                                                     "failed to add the device "
1223                                                     "with handle 0x%04x to "
1224                                                     "persistent table because "
1225                                                     "there is no free space "
1226                                                     "available\n", __func__,
1227                                                     phy_change->dev_handle);
1228                                         }
1229                                 } else {
1230                                         et_entry->dpm_entry_num = dpm_idx;
1231                                         mt_entry->dpm_entry_num = dpm_idx;
1232                                 }
1233                         }
1234                         /* FIXME Why not mt_entry too? */
1235                         et_entry->init_complete = 1;
1236                 } else if ((ioc_pg8_flags &
1237                     MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1238                     MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1239                         map_idx = _mapping_get_mt_idx_from_id
1240                             (sc, phy_change->physical_id);
1241                         if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1242                                 search_idx = sc->num_rsvd_entries;
1243                                 if (topo_change->exp_handle)
1244                                         search_idx += max_num_phy_ids;
1245                                 map_idx = _mapping_get_free_mt_idx(sc,
1246                                     search_idx);
1247                         }
1248                         if (map_idx == MPS_MAPTABLE_BAD_IDX) {
1249                                 map_idx = _mapping_get_high_missing_mt_idx(sc);
1250                                 if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1251                                         mt_entry = &sc->mapping_table[map_idx];
1252                                         if (mt_entry->dev_handle) {
1253                                                 _mapping_add_to_removal_table
1254                                                     (sc, mt_entry->dev_handle,
1255                                                      0);
1256                                                 is_removed = 1;
1257                                         }
1258                                         mt_entry->init_complete = 0;
1259                                 }
1260                         }
1261                         if (map_idx != MPS_MAPTABLE_BAD_IDX) {
1262                                 mt_entry = &sc->mapping_table[map_idx];
1263                                 mt_entry->physical_id = phy_change->physical_id;
1264                                 mt_entry->channel = 0;
1265                                 mt_entry->id = map_idx;
1266                                 mt_entry->dev_handle = phy_change->dev_handle;
1267                                 mt_entry->missing_count = 0;
1268                                 mt_entry->device_info = phy_change->device_info
1269                                     | (MPS_DEV_RESERVED | MPS_MAP_IN_USE);
1270                         } else {
1271                                 phy_change->is_processed = 1;
1272                                 if (!sc->mt_full_retry) {
1273                                         sc->mt_add_device_failed = 1;
1274                                         continue;
1275                                 }
1276                                 printf("%s: failed to add the device with "
1277                                     "handle 0x%04x because there is no free "
1278                                     "space available in the mapping table\n",
1279                                     __func__, phy_change->dev_handle);
1280                                 continue;
1281                         }
1282                         if (sc->is_dpm_enable) {
1283                                 if (mt_entry->dpm_entry_num !=
1284                                     MPS_DPM_BAD_IDX) {
1285                                         dpm_idx = mt_entry->dpm_entry_num;
1286                                         dpm_entry = (Mpi2DriverMap0Entry_t *)
1287                                             ((u8 *)sc->dpm_pg0 + hdr_sz);
1288                                         dpm_entry += dpm_idx;
1289                                         missing_cnt = dpm_entry->
1290                                             MappingInformation &
1291                                             MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1292                                         temp64_var = dpm_entry->
1293                                             PhysicalIdentifier.High;
1294                                         temp64_var = (temp64_var << 32) |
1295                                            dpm_entry->PhysicalIdentifier.Low;
1296                                         if ((mt_entry->physical_id ==
1297                                             temp64_var) && !missing_cnt)
1298                                                 mt_entry->init_complete = 1;
1299                                 } else {
1300                                         dpm_idx = _mapping_get_free_dpm_idx(sc);
1301                                         mt_entry->init_complete = 0;
1302                                 }
1303                                 if (dpm_idx != MPS_DPM_BAD_IDX &&
1304                                     !mt_entry->init_complete) {
1305                                         mt_entry->init_complete = 1;
1306                                         mt_entry->dpm_entry_num = dpm_idx;
1307                                         dpm_entry = (Mpi2DriverMap0Entry_t *)
1308                                             ((u8 *)sc->dpm_pg0 + hdr_sz);
1309                                         dpm_entry += dpm_idx;
1310                                         dpm_entry->PhysicalIdentifier.Low =
1311                                             (0xFFFFFFFF &
1312                                             mt_entry->physical_id);
1313                                         dpm_entry->PhysicalIdentifier.High =
1314                                             (mt_entry->physical_id >> 32);
1315                                         dpm_entry->DeviceIndex = (U16) map_idx;
1316                                         dpm_entry->MappingInformation = 0;
1317                                         dpm_entry->PhysicalBitsMapping = 0;
1318                                         sc->dpm_entry_used[dpm_idx] = 1;
1319                                         sc->dpm_flush_entry[dpm_idx] = 1;
1320                                         phy_change->is_processed = 1;
1321                                 } else if (dpm_idx == MPS_DPM_BAD_IDX) {
1322                                                 phy_change->is_processed = 1;
1323                                                 mps_dprint(sc, MPS_INFO, "%s: "
1324                                                     "failed to add the device "
1325                                                     "with handle 0x%04x to "
1326                                                     "persistent table because "
1327                                                     "there is no free space "
1328                                                     "available\n", __func__,
1329                                                     phy_change->dev_handle);
1330                                 }
1331                         }
1332                         mt_entry->init_complete = 1;
1333                 }
1334
1335                 phy_change->is_processed = 1;
1336         }
1337         if (is_removed)
1338                 _mapping_clear_removed_entries(sc);
1339 }
1340
1341 /**
1342  * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
1343  * @sc: per adapter object
1344  *
1345  * Returns nothing
1346  */
1347 static void
1348 _mapping_flush_dpm_pages(struct mps_softc *sc)
1349 {
1350         Mpi2DriverMap0Entry_t *dpm_entry;
1351         Mpi2ConfigReply_t mpi_reply;
1352         Mpi2DriverMappingPage0_t config_page;
1353         u16 entry_num;
1354
1355         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
1356                 if (!sc->dpm_flush_entry[entry_num])
1357                         continue;
1358                 memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
1359                 memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
1360                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1361                 dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
1362                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1363                 dpm_entry += entry_num;
1364                 dpm_entry->MappingInformation = htole16(dpm_entry->
1365                     MappingInformation);
1366                 dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
1367                 dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
1368                     PhysicalBitsMapping);
1369                 memcpy(&config_page.Entry, (u8 *)dpm_entry,
1370                     sizeof(Mpi2DriverMap0Entry_t));
1371                 /* TODO-How to handle failed writes? */
1372                 if (mps_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
1373                     entry_num)) {
1374                         printf("%s: write of dpm entry %d for device failed\n",
1375                              __func__, entry_num);
1376                 } else
1377                         sc->dpm_flush_entry[entry_num] = 0;
1378                 dpm_entry->MappingInformation = le16toh(dpm_entry->
1379                     MappingInformation);
1380                 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
1381                 dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
1382                     PhysicalBitsMapping);
1383         }
1384 }
1385
1386 /**
1387  * _mapping_allocate_memory- allocates the memory required for mapping tables
1388  * @sc: per adapter object
1389  *
1390  * Allocates the memory for all the tables required for host mapping
1391  *
1392  * Return 0 on success or non-zero on failure.
1393  */
1394 int
1395 mps_mapping_allocate_memory(struct mps_softc *sc)
1396 {
1397         uint32_t dpm_pg0_sz;
1398
1399         sc->mapping_table = malloc((sizeof(struct dev_mapping_table) *
1400             sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1401         if (!sc->mapping_table)
1402                 goto free_resources;
1403
1404         sc->removal_table = malloc((sizeof(struct map_removal_table) *
1405             sc->max_devices), M_MPT2, M_ZERO|M_NOWAIT);
1406         if (!sc->removal_table)
1407                 goto free_resources;
1408
1409         sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) *
1410             sc->max_enclosures), M_MPT2, M_ZERO|M_NOWAIT);
1411         if (!sc->enclosure_table)
1412                 goto free_resources;
1413
1414         sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries),
1415             M_MPT2, M_ZERO|M_NOWAIT);
1416         if (!sc->dpm_entry_used)
1417                 goto free_resources;
1418
1419         sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries),
1420             M_MPT2, M_ZERO|M_NOWAIT);
1421         if (!sc->dpm_flush_entry)
1422                 goto free_resources;
1423
1424         dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1425             (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1426
1427         sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPT2, M_ZERO|M_NOWAIT);
1428         if (!sc->dpm_pg0) {
1429                 printf("%s: memory alloc failed for dpm page; disabling dpm\n",
1430                     __func__);
1431                 sc->is_dpm_enable = 0;
1432         }
1433
1434         return 0;
1435
1436 free_resources:
1437         free(sc->mapping_table, M_MPT2);
1438         free(sc->removal_table, M_MPT2);
1439         free(sc->enclosure_table, M_MPT2);
1440         free(sc->dpm_entry_used, M_MPT2);
1441         free(sc->dpm_flush_entry, M_MPT2);
1442         free(sc->dpm_pg0, M_MPT2);
1443         printf("%s: device initialization failed due to failure in mapping "
1444             "table memory allocation\n", __func__);
1445         return -1;
1446 }
1447
1448 /**
1449  * mps_mapping_free_memory- frees the memory allocated for mapping tables
1450  * @sc: per adapter object
1451  *
1452  * Returns nothing.
1453  */
1454 void
1455 mps_mapping_free_memory(struct mps_softc *sc)
1456 {
1457         free(sc->mapping_table, M_MPT2);
1458         free(sc->removal_table, M_MPT2);
1459         free(sc->enclosure_table, M_MPT2);
1460         free(sc->dpm_entry_used, M_MPT2);
1461         free(sc->dpm_flush_entry, M_MPT2);
1462         free(sc->dpm_pg0, M_MPT2);
1463 }
1464
1465
1466 static void
1467 _mapping_process_dpm_pg0(struct mps_softc *sc)
1468 {
1469         u8 missing_cnt, enc_idx;
1470         u16 slot_id, entry_num, num_slots;
1471         u32 map_idx, dev_idx, start_idx, end_idx;
1472         struct dev_mapping_table *mt_entry;
1473         Mpi2DriverMap0Entry_t *dpm_entry;
1474         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1475         u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
1476         struct enc_mapping_table *et_entry;
1477         u64 physical_id;
1478         u32 phy_bits = 0;
1479
1480         if (sc->ir_firmware)
1481                 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1482
1483         dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
1484             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1485         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 
1486             dpm_entry++) {
1487                 physical_id = dpm_entry->PhysicalIdentifier.High;
1488                 physical_id = (physical_id << 32) | 
1489                     dpm_entry->PhysicalIdentifier.Low;
1490                 if (!physical_id) {
1491                         sc->dpm_entry_used[entry_num] = 0;
1492                         continue;
1493                 }
1494                 sc->dpm_entry_used[entry_num] = 1;
1495                 dpm_entry->MappingInformation = le16toh(dpm_entry->
1496                     MappingInformation);
1497                 missing_cnt = dpm_entry->MappingInformation &
1498                     MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
1499                 dev_idx = le16toh(dpm_entry->DeviceIndex);
1500                 phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
1501                 if (sc->ir_firmware && (dev_idx >= start_idx) &&
1502                     (dev_idx <= end_idx)) {
1503                         mt_entry = &sc->mapping_table[dev_idx];
1504                         mt_entry->physical_id = dpm_entry->PhysicalIdentifier.High;
1505                         mt_entry->physical_id = (mt_entry->physical_id << 32) |
1506                             dpm_entry->PhysicalIdentifier.Low;
1507                         mt_entry->channel = MPS_RAID_CHANNEL;
1508                         mt_entry->id = dev_idx;
1509                         mt_entry->missing_count = missing_cnt;
1510                         mt_entry->dpm_entry_num = entry_num;
1511                         mt_entry->device_info = MPS_DEV_RESERVED;
1512                         continue;
1513                 }
1514                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1515                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1516                         if (dev_idx <  (sc->num_rsvd_entries +
1517                             max_num_phy_ids)) {
1518                                 slot_id = 0;
1519                                 if (ioc_pg8_flags &
1520                                     MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
1521                                         slot_id = 1;
1522                                 num_slots = max_num_phy_ids;
1523                         } else {
1524                                 slot_id = 0;
1525                                 num_slots = dpm_entry->MappingInformation &
1526                                     MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
1527                                 num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1528                         }
1529                         enc_idx = sc->num_enc_table_entries;
1530                         if (enc_idx >= sc->max_enclosures) {
1531                                 printf("%s: enclosure entries exceed max "
1532                                     "enclosures of %d\n", __func__,
1533                                     sc->max_enclosures);
1534                                 break;
1535                         }
1536                         sc->num_enc_table_entries++;
1537                         et_entry = &sc->enclosure_table[enc_idx];
1538                         physical_id = dpm_entry->PhysicalIdentifier.High;
1539                         et_entry->enclosure_id = (physical_id << 32) |
1540                             dpm_entry->PhysicalIdentifier.Low;
1541                         et_entry->start_index = dev_idx;
1542                         et_entry->dpm_entry_num = entry_num;
1543                         et_entry->num_slots = num_slots;
1544                         et_entry->start_slot = slot_id;
1545                         et_entry->missing_count = missing_cnt;
1546                         et_entry->phy_bits = phy_bits;
1547
1548                         mt_entry = &sc->mapping_table[dev_idx];
1549                         for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
1550                             map_idx++, mt_entry++) {
1551                                 if (mt_entry->dpm_entry_num !=
1552                                     MPS_DPM_BAD_IDX) {
1553                                         printf("%s: conflict in mapping table "
1554                                             "for enclosure %d\n", __func__,
1555                                             enc_idx);
1556                                         break;
1557                                 }
1558                                 physical_id = dpm_entry->PhysicalIdentifier.High;
1559                                 mt_entry->physical_id = (physical_id << 32) |
1560                                     dpm_entry->PhysicalIdentifier.Low;
1561                                 mt_entry->phy_bits = phy_bits;
1562                                 mt_entry->channel = 0;
1563                                 mt_entry->id = dev_idx;
1564                                 mt_entry->dpm_entry_num = entry_num;
1565                                 mt_entry->missing_count = missing_cnt;
1566                                 mt_entry->device_info = MPS_DEV_RESERVED;
1567                         }
1568                 } else if ((ioc_pg8_flags &
1569                     MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1570                     MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1571                         map_idx = dev_idx;
1572                         mt_entry = &sc->mapping_table[map_idx];
1573                         if (mt_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
1574                                 printf("%s: conflict in mapping table for "
1575                                     "device %d\n", __func__, map_idx);
1576                                 break;
1577                         }
1578                         physical_id = dpm_entry->PhysicalIdentifier.High;
1579                         mt_entry->physical_id = (physical_id << 32) |
1580                             dpm_entry->PhysicalIdentifier.Low;
1581                         mt_entry->phy_bits = phy_bits;
1582                         mt_entry->channel = 0;
1583                         mt_entry->id = dev_idx;
1584                         mt_entry->missing_count = missing_cnt;
1585                         mt_entry->dpm_entry_num = entry_num;
1586                         mt_entry->device_info = MPS_DEV_RESERVED;
1587                 }
1588         } /*close the loop for DPM table */
1589 }
1590
1591 /*
1592  * mps_mapping_check_devices - start of the day check for device availabilty
1593  * @sc: per adapter object
1594  * @sleep_flag: Flag indicating whether this function can sleep or not
1595  *
1596  * Returns nothing.
1597  */
1598 void
1599 mps_mapping_check_devices(struct mps_softc *sc, int sleep_flag)
1600 {
1601         u32 i;
1602 /*      u32 cntdn, i;
1603         u32 timeout = 60;*/
1604         struct dev_mapping_table *mt_entry;
1605         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1606         struct enc_mapping_table *et_entry;
1607         u32 start_idx, end_idx;
1608
1609         /* We need to ucomment this when this function is called
1610          * from the port enable complete */
1611 #if 0
1612         sc->track_mapping_events = 0;
1613         cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
1614         do {
1615                 if (!sc->pending_map_events)
1616                         break;
1617                 if (sleep_flag == CAN_SLEEP)
1618                         pause("mps_pause", (hz/1000));/* 1msec sleep */
1619                 else
1620                         DELAY(500); /* 500 useconds delay */
1621         } while (--cntdn);
1622
1623
1624         if (!cntdn)
1625                 printf("%s: there are %d"
1626                     " pending events after %d seconds of delay\n",
1627                     __func__, sc->pending_map_events, timeout);
1628 #endif
1629         sc->pending_map_events = 0;
1630
1631         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1632             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
1633                 et_entry = sc->enclosure_table;
1634                 for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
1635                         if (!et_entry->init_complete) {
1636                                 if (et_entry->missing_count <
1637                                     MPS_MAX_MISSING_COUNT) {
1638                                         et_entry->missing_count++;
1639                                         if (et_entry->dpm_entry_num !=
1640                                             MPS_DPM_BAD_IDX)
1641                                                 _mapping_commit_enc_entry(sc,
1642                                                     et_entry);
1643                                 }
1644                                 et_entry->init_complete = 1;
1645                         }
1646                 }
1647                 if (!sc->ir_firmware)
1648                         return;
1649                 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
1650                 mt_entry = &sc->mapping_table[start_idx];
1651                 for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
1652                         if (mt_entry->device_info & MPS_DEV_RESERVED
1653                             && !mt_entry->physical_id)
1654                                 mt_entry->init_complete = 1;
1655                         else if (mt_entry->device_info & MPS_DEV_RESERVED) {
1656                                 if (!mt_entry->init_complete) {
1657                                         if (mt_entry->missing_count <
1658                                             MPS_MAX_MISSING_COUNT) {
1659                                                 mt_entry->missing_count++;
1660                                                 if (mt_entry->dpm_entry_num !=
1661                                                     MPS_DPM_BAD_IDX)
1662                                                 _mapping_commit_map_entry(sc,
1663                                                     mt_entry);
1664                                         }
1665                                         mt_entry->init_complete = 1;
1666                                 }
1667                         }
1668                 }
1669         } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
1670             MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
1671                 mt_entry = sc->mapping_table;
1672                 for (i = 0; i < sc->max_devices; i++, mt_entry++) {
1673                         if (mt_entry->device_info & MPS_DEV_RESERVED
1674                             && !mt_entry->physical_id)
1675                                 mt_entry->init_complete = 1;
1676                         else if (mt_entry->device_info & MPS_DEV_RESERVED) {
1677                                 if (!mt_entry->init_complete) {
1678                                         if (mt_entry->missing_count <
1679                                             MPS_MAX_MISSING_COUNT) {
1680                                                 mt_entry->missing_count++;
1681                                                 if (mt_entry->dpm_entry_num !=
1682                                                     MPS_DPM_BAD_IDX)
1683                                                 _mapping_commit_map_entry(sc,
1684                                                     mt_entry);
1685                                         }
1686                                         mt_entry->init_complete = 1;
1687                                 }
1688                         }
1689                 }
1690         }
1691 }
1692
1693
1694 /**
1695  * mps_mapping_is_reinit_required - check whether event replay required
1696  * @sc: per adapter object
1697  *
1698  * Checks the per ioc flags and decide whether reinit of events required
1699  *
1700  * Returns 1 for reinit of ioc 0 for not.
1701  */
1702 int mps_mapping_is_reinit_required(struct mps_softc *sc)
1703 {
1704         if (!sc->mt_full_retry && sc->mt_add_device_failed) {
1705                 sc->mt_full_retry = 1;
1706                 sc->mt_add_device_failed = 0;
1707                 _mapping_flush_dpm_pages(sc);
1708                 return 1;
1709         }
1710         sc->mt_full_retry = 1;
1711         return 0;
1712 }
1713
1714 /**
1715  * mps_mapping_initialize - initialize mapping tables
1716  * @sc: per adapter object
1717  *
1718  * Read controller persitant mapping tables into internal data area.
1719  *
1720  * Return 0 for success or non-zero for failure.
1721  */
1722 int
1723 mps_mapping_initialize(struct mps_softc *sc)
1724 {
1725         uint16_t volume_mapping_flags, dpm_pg0_sz;
1726         uint32_t i;
1727         Mpi2ConfigReply_t mpi_reply;
1728         int error;
1729         uint8_t retry_count;
1730         uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1731
1732         /* The additional 1 accounts for the virtual enclosure
1733          * created for the controller
1734          */
1735         sc->max_enclosures = sc->facts->MaxEnclosures + 1;
1736         sc->max_expanders = sc->facts->MaxSasExpanders;
1737         sc->max_volumes = sc->facts->MaxVolumes;
1738         sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
1739         sc->pending_map_events = 0;
1740         sc->num_enc_table_entries = 0;
1741         sc->num_rsvd_entries = 0;
1742         sc->num_channels = 1;
1743         sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
1744         sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
1745         sc->track_mapping_events = 0;
1746         
1747         if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
1748                 sc->is_dpm_enable = 0;
1749
1750         if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
1751                 sc->num_rsvd_entries = 1;
1752
1753         volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
1754             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
1755         if (sc->ir_firmware && (volume_mapping_flags ==
1756             MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
1757                 sc->num_rsvd_entries += sc->max_volumes;
1758
1759         error = mps_mapping_allocate_memory(sc);
1760         if (error)
1761                 return (error);
1762
1763         for (i = 0; i < sc->max_devices; i++)
1764                 _mapping_clear_map_entry(sc->mapping_table + i);
1765
1766         for (i = 0; i < sc->max_enclosures; i++)
1767                 _mapping_clear_enc_entry(sc->enclosure_table + i);
1768
1769         for (i = 0; i < sc->max_devices; i++) {
1770                 sc->removal_table[i].dev_handle = 0;
1771                 sc->removal_table[i].dpm_entry_num = MPS_DPM_BAD_IDX;
1772         }
1773
1774         memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
1775         memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
1776
1777         if (sc->is_dpm_enable) {
1778                 dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
1779                     (sc->max_dpm_entries *
1780                      sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
1781                 retry_count = 0;
1782
1783 retry_read_dpm:
1784                 if (mps_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
1785                     dpm_pg0_sz)) {
1786                         printf("%s: dpm page read failed; disabling dpm\n",
1787                             __func__);
1788                         if (retry_count < 3) {
1789                                 retry_count++;
1790                                 goto retry_read_dpm;
1791                         }
1792                         sc->is_dpm_enable = 0;
1793                 }
1794         }
1795
1796         if (sc->is_dpm_enable)
1797                 _mapping_process_dpm_pg0(sc);
1798
1799         sc->track_mapping_events = 1;
1800         return 0;
1801 }
1802
1803 /**
1804  * mps_mapping_exit - clear mapping table and associated memory
1805  * @sc: per adapter object
1806  *
1807  * Returns nothing.
1808  */
1809 void
1810 mps_mapping_exit(struct mps_softc *sc)
1811 {
1812         _mapping_flush_dpm_pages(sc);
1813         mps_mapping_free_memory(sc);
1814 }
1815
1816 /**
1817  * mps_mapping_get_sas_id - assign a target id for sas device
1818  * @sc: per adapter object
1819  * @sas_address: sas address of the device
1820  * @handle: device handle
1821  *
1822  * Returns valid ID on success or BAD_ID.
1823  */
1824 unsigned int
1825 mps_mapping_get_sas_id(struct mps_softc *sc, uint64_t sas_address, u16 handle)
1826 {
1827         u32 map_idx;
1828         struct dev_mapping_table *mt_entry;
1829
1830         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
1831                 mt_entry = &sc->mapping_table[map_idx];
1832                 if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
1833                     sas_address)
1834                         return mt_entry->id;
1835         }
1836
1837         return MPS_MAP_BAD_ID;
1838 }
1839
1840 /**
1841  * mps_mapping_get_sas_id_from_handle - find a target id in mapping table using
1842  * only the dev handle.  This is just a wrapper function for the local function
1843  * _mapping_get_mt_idx_from_handle.
1844  * @sc: per adapter object
1845  * @handle: device handle
1846  *
1847  * Returns valid ID on success or BAD_ID.
1848  */
1849 unsigned int
1850 mps_mapping_get_sas_id_from_handle(struct mps_softc *sc, u16 handle)
1851 {
1852         return (_mapping_get_mt_idx_from_handle(sc, handle));
1853 }
1854
1855 /**
1856  * mps_mapping_get_raid_id - assign a target id for raid device
1857  * @sc: per adapter object
1858  * @wwid: world wide identifier for raid volume
1859  * @handle: device handle
1860  *
1861  * Returns valid ID on success or BAD_ID.
1862  */
1863 unsigned int
1864 mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid, u16 handle)
1865 {
1866         u32 map_idx;
1867         struct dev_mapping_table *mt_entry;
1868
1869         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
1870                 mt_entry = &sc->mapping_table[map_idx];
1871                 if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
1872                     wwid)
1873                         return mt_entry->id;
1874         }
1875
1876         return MPS_MAP_BAD_ID;
1877 }
1878
1879 /**
1880  * mps_mapping_get_raid_id_from_handle - find raid device in mapping table
1881  * using only the volume dev handle.  This is just a wrapper function for the
1882  * local function _mapping_get_ir_mt_idx_from_handle.
1883  * @sc: per adapter object
1884  * @volHandle: volume device handle
1885  *
1886  * Returns valid ID on success or BAD_ID.
1887  */
1888 unsigned int
1889 mps_mapping_get_raid_id_from_handle(struct mps_softc *sc, u16 volHandle)
1890 {
1891         return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
1892 }
1893
1894 /**
1895  * mps_mapping_enclosure_dev_status_change_event - handle enclosure events
1896  * @sc: per adapter object
1897  * @event_data: event data payload
1898  *
1899  * Return nothing.
1900  */
1901 void
1902 mps_mapping_enclosure_dev_status_change_event(struct mps_softc *sc,
1903     Mpi2EventDataSasEnclDevStatusChange_t *event_data)
1904 {
1905         u8 enc_idx, missing_count;
1906         struct enc_mapping_table *et_entry;
1907         Mpi2DriverMap0Entry_t *dpm_entry;
1908         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1909         u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
1910         u8 update_phy_bits = 0;
1911         u32 saved_phy_bits;
1912         uint64_t temp64_var;
1913
1914         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
1915             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
1916                 goto out;
1917
1918         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
1919             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
1920
1921         if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
1922                 if (!event_data->NumSlots) {
1923                         printf("%s: enclosure with handle = 0x%x reported 0 "
1924                             "slots\n", __func__,
1925                             le16toh(event_data->EnclosureHandle));
1926                         goto out;
1927                 }
1928                 temp64_var = event_data->EnclosureLogicalID.High;
1929                 temp64_var = (temp64_var << 32) |
1930                     event_data->EnclosureLogicalID.Low;
1931                 enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
1932                     event_data->PhyBits);
1933                 if (enc_idx != MPS_ENCTABLE_BAD_IDX) {
1934                         et_entry = &sc->enclosure_table[enc_idx];
1935                         if (et_entry->init_complete &&
1936                             !et_entry->missing_count) {
1937                                 printf("%s: enclosure %d is already present "
1938                                     "with handle = 0x%x\n",__func__, enc_idx,
1939                                     et_entry->enc_handle);
1940                                 goto out;
1941                         }
1942                         et_entry->enc_handle = le16toh(event_data->
1943                             EnclosureHandle);
1944                         et_entry->start_slot = le16toh(event_data->StartSlot);
1945                         saved_phy_bits = et_entry->phy_bits;
1946                         et_entry->phy_bits |= le32toh(event_data->PhyBits);
1947                         if (saved_phy_bits != et_entry->phy_bits)
1948                                 update_phy_bits = 1;
1949                         if (et_entry->missing_count || update_phy_bits) {
1950                                 et_entry->missing_count = 0;
1951                                 if (sc->is_dpm_enable &&
1952                                     et_entry->dpm_entry_num !=
1953                                     MPS_DPM_BAD_IDX) {
1954                                         dpm_entry += et_entry->dpm_entry_num;
1955                                         missing_count =
1956                                             (u8)(dpm_entry->MappingInformation &
1957                                             MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
1958                                         if (!et_entry->init_complete && (
1959                                             missing_count || update_phy_bits)) {
1960                                                 dpm_entry->MappingInformation
1961                                                     = et_entry->num_slots;
1962                                                 dpm_entry->MappingInformation
1963                                                     <<= map_shift;
1964                                                 dpm_entry->PhysicalBitsMapping
1965                                                     = et_entry->phy_bits;
1966                                                 sc->dpm_flush_entry[et_entry->
1967                                                     dpm_entry_num] = 1;
1968                                         }
1969                                 }
1970                         }
1971                 } else {
1972                         enc_idx = sc->num_enc_table_entries;
1973                         if (enc_idx >= sc->max_enclosures) {
1974                                 printf("%s: enclosure can not be added; "
1975                                     "mapping table is full\n", __func__);
1976                                 goto out;
1977                         }
1978                         sc->num_enc_table_entries++;
1979                         et_entry = &sc->enclosure_table[enc_idx];
1980                         et_entry->enc_handle = le16toh(event_data->
1981                             EnclosureHandle);
1982                         et_entry->enclosure_id = event_data->
1983                             EnclosureLogicalID.High;
1984                         et_entry->enclosure_id = ( et_entry->enclosure_id << 
1985                             32) | event_data->EnclosureLogicalID.Low;
1986                         et_entry->start_index = MPS_MAPTABLE_BAD_IDX;
1987                         et_entry->dpm_entry_num = MPS_DPM_BAD_IDX;
1988                         et_entry->num_slots = le16toh(event_data->NumSlots);
1989                         et_entry->start_slot = le16toh(event_data->StartSlot);
1990                         et_entry->phy_bits = le32toh(event_data->PhyBits);
1991                 }
1992                 et_entry->init_complete = 1;
1993         } else if (event_data->ReasonCode ==
1994             MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
1995                 enc_idx = _mapping_get_enc_idx_from_handle(sc,
1996                     le16toh(event_data->EnclosureHandle));
1997                 if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
1998                         printf("%s: cannot unmap enclosure %d because it has "
1999                             "already been deleted", __func__, enc_idx);
2000                         goto out;
2001                 }
2002                 et_entry = &sc->enclosure_table[enc_idx];
2003                 if (!et_entry->init_complete) {
2004                         if (et_entry->missing_count < MPS_MAX_MISSING_COUNT)
2005                                 et_entry->missing_count++;
2006                         else
2007                                 et_entry->init_complete = 1;
2008                 }
2009                 if (!et_entry->missing_count)
2010                         et_entry->missing_count++;
2011                 if (sc->is_dpm_enable && !et_entry->init_complete &&
2012                     et_entry->dpm_entry_num != MPS_DPM_BAD_IDX) {
2013                         dpm_entry += et_entry->dpm_entry_num;
2014                         dpm_entry->MappingInformation = et_entry->num_slots;
2015                         dpm_entry->MappingInformation <<= map_shift;
2016                         dpm_entry->MappingInformation |=
2017                             et_entry->missing_count;
2018                         sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
2019                 }
2020                 et_entry->init_complete = 1;
2021         }
2022
2023 out:
2024         _mapping_flush_dpm_pages(sc);
2025         if (sc->pending_map_events)
2026                 sc->pending_map_events--;
2027 }
2028
2029 /**
2030  * mps_mapping_topology_change_event - handle topology change events
2031  * @sc: per adapter object
2032  * @event_data: event data payload
2033  *
2034  * Returns nothing.
2035  */
2036 void
2037 mps_mapping_topology_change_event(struct mps_softc *sc,
2038     Mpi2EventDataSasTopologyChangeList_t *event_data)
2039 {
2040         struct _map_topology_change topo_change;
2041         struct _map_phy_change *phy_change;
2042         Mpi2EventSasTopoPhyEntry_t *event_phy_change;
2043         u8 i, num_entries;
2044
2045         topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
2046         topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
2047         num_entries = event_data->NumEntries;
2048         topo_change.num_entries = num_entries;
2049         topo_change.start_phy_num = event_data->StartPhyNum;
2050         topo_change.num_phys = event_data->NumPhys;
2051         topo_change.exp_status = event_data->ExpStatus;
2052         event_phy_change = event_data->PHY;
2053         topo_change.phy_details = NULL;
2054
2055         if (!num_entries)
2056                 goto out;
2057         phy_change = malloc(sizeof(struct _map_phy_change) * num_entries,
2058             M_MPT2, M_NOWAIT|M_ZERO);
2059         topo_change.phy_details = phy_change;
2060         if (!phy_change)
2061                 goto out;
2062         for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
2063                 phy_change->dev_handle = le16toh(event_phy_change->
2064                     AttachedDevHandle);
2065                 phy_change->reason = event_phy_change->PhyStatus &
2066                     MPI2_EVENT_SAS_TOPO_RC_MASK;
2067         }
2068         _mapping_update_missing_count(sc, &topo_change);
2069         _mapping_get_dev_info(sc, &topo_change);
2070         _mapping_clear_removed_entries(sc);
2071         _mapping_add_new_device(sc, &topo_change);
2072
2073 out:
2074         free(topo_change.phy_details, M_MPT2);
2075         _mapping_flush_dpm_pages(sc);
2076         if (sc->pending_map_events)
2077                 sc->pending_map_events--;
2078 }
2079
2080 /**
2081  * _mapping_check_update_ir_mt_idx - Check and update IR map table index
2082  * @sc: per adapter object
2083  * @event_data: event data payload
2084  * @evt_idx: current event index
2085  * @map_idx: current index and the place holder for new map table index
2086  * @wwid_table: world wide name for volumes in the element table
2087  *
2088  * pass through IR events and find whether any events matches and if so
2089  * tries to find new index if not returns failure
2090  *
2091  * Returns 0 on success and 1 on failure
2092  */
2093 static int
2094 _mapping_check_update_ir_mt_idx(struct mps_softc *sc,
2095     Mpi2EventDataIrConfigChangeList_t *event_data, int evt_idx, u32 *map_idx,
2096     u64 *wwid_table)
2097 {
2098         struct dev_mapping_table *mt_entry;
2099         u32 st_idx, end_idx, mt_idx = *map_idx;
2100         u8 match = 0;
2101         Mpi2EventIrConfigElement_t *element;
2102         u16 element_flags;
2103         int i;
2104
2105         mt_entry = &sc->mapping_table[mt_idx];
2106         _mapping_get_ir_maprange(sc, &st_idx, &end_idx);
2107 search_again:
2108         match = 0;
2109         for (i = evt_idx + 1; i < event_data->NumElements; i++) {
2110                 element = (Mpi2EventIrConfigElement_t *)
2111                     &event_data->ConfigElement[i];
2112                 element_flags = le16toh(element->ElementFlags);
2113                 if ((element_flags &
2114                     MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) !=
2115                     MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT)
2116                         continue;
2117                 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2118                     element->ReasonCode ==
2119                     MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2120                         if (mt_entry->physical_id == wwid_table[i]) {
2121                                 match = 1;
2122                                 break;
2123                         }
2124                 }
2125         }
2126
2127         if (match) {
2128                 do {
2129                         mt_idx++;
2130                         if (mt_idx > end_idx)
2131                                 return 1;
2132                         mt_entry = &sc->mapping_table[mt_idx];
2133                 } while (mt_entry->device_info & MPS_MAP_IN_USE);
2134                 goto search_again;
2135         }
2136         *map_idx = mt_idx;
2137         return 0;
2138 }
2139
2140 /**
2141  * mps_mapping_ir_config_change_event - handle IR config change list events
2142  * @sc: per adapter object
2143  * @event_data: event data payload
2144  *
2145  * Returns nothing.
2146  */
2147 void
2148 mps_mapping_ir_config_change_event(struct mps_softc *sc,
2149     Mpi2EventDataIrConfigChangeList_t *event_data)
2150 {
2151         Mpi2EventIrConfigElement_t *element;
2152         int i;
2153         u64 *wwid_table;
2154         u32 map_idx, flags;
2155         struct dev_mapping_table *mt_entry;
2156         u16 element_flags;
2157         u8 log_full_error = 0;
2158
2159         wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPT2,
2160             M_NOWAIT | M_ZERO);
2161         if (!wwid_table)
2162                 goto out;
2163         element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
2164         flags = le32toh(event_data->Flags);
2165         for (i = 0; i < event_data->NumElements; i++, element++) {
2166                 element_flags = le16toh(element->ElementFlags);
2167                 if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
2168                     (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
2169                     (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
2170                     && (element->ReasonCode !=
2171                         MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
2172                         continue;
2173                 if ((element_flags &
2174                     MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
2175                     MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
2176                         mps_config_get_volume_wwid(sc,
2177                             le16toh(element->VolDevHandle), &wwid_table[i]);
2178                         map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2179                             wwid_table[i]);
2180                         if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2181                                 mt_entry = &sc->mapping_table[map_idx];
2182                                 mt_entry->device_info |= MPS_MAP_IN_USE;
2183                         }
2184                 }
2185         }
2186         if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
2187                 goto out;
2188         else {
2189                 element = (Mpi2EventIrConfigElement_t *)&event_data->
2190                     ConfigElement[0];
2191                 for (i = 0; i < event_data->NumElements; i++, element++) {
2192                         if (element->ReasonCode ==
2193                             MPI2_EVENT_IR_CHANGE_RC_ADDED ||
2194                             element->ReasonCode ==
2195                             MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
2196                                 map_idx = _mapping_get_ir_mt_idx_from_wwid
2197                                     (sc, wwid_table[i]);
2198                                 if (map_idx != MPS_MAPTABLE_BAD_IDX) {
2199                                         mt_entry = &sc->mapping_table[map_idx];
2200                                         mt_entry->channel = MPS_RAID_CHANNEL;
2201                                         mt_entry->id = map_idx;
2202                                         mt_entry->dev_handle = le16toh
2203                                             (element->VolDevHandle);
2204                                         mt_entry->device_info =
2205                                             MPS_DEV_RESERVED | MPS_MAP_IN_USE;
2206                                         _mapping_update_ir_missing_cnt(sc,
2207                                             map_idx, element, wwid_table[i]);
2208                                         continue;
2209                                 }
2210                                 map_idx = _mapping_get_free_ir_mt_idx(sc);
2211                                 if (map_idx == MPS_MAPTABLE_BAD_IDX)
2212                                         log_full_error = 1;
2213                                 else if (i < (event_data->NumElements - 1)) {
2214                                         log_full_error =
2215                                             _mapping_check_update_ir_mt_idx
2216                                             (sc, event_data, i, &map_idx,
2217                                              wwid_table);
2218                                 }
2219                                 if (log_full_error) {
2220                                         printf("%s: no space to add the RAID "
2221                                             "volume with handle 0x%04x in "
2222                                             "mapping table\n", __func__, le16toh
2223                                             (element->VolDevHandle));
2224                                         continue;
2225                                 }
2226                                 mt_entry = &sc->mapping_table[map_idx];
2227                                 mt_entry->physical_id = wwid_table[i];
2228                                 mt_entry->channel = MPS_RAID_CHANNEL;
2229                                 mt_entry->id = map_idx;
2230                                 mt_entry->dev_handle = le16toh(element->
2231                                     VolDevHandle);
2232                                 mt_entry->device_info = MPS_DEV_RESERVED |
2233                                     MPS_MAP_IN_USE;
2234                                 mt_entry->init_complete = 0;
2235                                 _mapping_update_ir_missing_cnt(sc, map_idx,
2236                                     element, wwid_table[i]);
2237                         } else if (element->ReasonCode ==
2238                             MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
2239                                 map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
2240                                     wwid_table[i]);
2241                                 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2242                                         printf("%s: failed to remove a volume "
2243                                             "because it has already been "
2244                                             "removed\n", __func__);
2245                                         continue;
2246                                 }
2247                                 _mapping_update_ir_missing_cnt(sc, map_idx,
2248                                     element, wwid_table[i]);
2249                         } else if (element->ReasonCode ==
2250                             MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
2251                                 map_idx = _mapping_get_mt_idx_from_handle(sc,
2252                                     le16toh(element->VolDevHandle));
2253                                 if (map_idx == MPS_MAPTABLE_BAD_IDX) {
2254                                         printf("%s: failed to remove volume "
2255                                             "with handle 0x%04x because it has "
2256                                             "already been removed\n", __func__,
2257                                             le16toh(element->VolDevHandle));
2258                                         continue;
2259                                 }
2260                                 mt_entry = &sc->mapping_table[map_idx];
2261                                 _mapping_update_ir_missing_cnt(sc, map_idx,
2262                                     element, mt_entry->physical_id);
2263                         }
2264                 }
2265         }
2266
2267 out:
2268         _mapping_flush_dpm_pages(sc);
2269         free(wwid_table, M_MPT2);
2270         if (sc->pending_map_events)
2271                 sc->pending_map_events--;
2272 }