The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mpr/mpr_mapping.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 2d733e3ebf1a9be3c5d72c3c20c8f5a7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.