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