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