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  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 /* TODO Move headers to mprvar */
   34 #include <sys/types.h>
   35 #include <sys/param.h>
   36 #include <sys/lock.h>
   37 #include <sys/mutex.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/malloc.h>
   41 #include <sys/kthread.h>
   42 #include <sys/taskqueue.h>
   43 #include <sys/bus.h>
   44 #include <sys/endian.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/eventhandler.h>
   47 #include <sys/uio.h>
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 #include <dev/mpr/mpi/mpi2_type.h>
   51 #include <dev/mpr/mpi/mpi2.h>
   52 #include <dev/mpr/mpi/mpi2_ioc.h>
   53 #include <dev/mpr/mpi/mpi2_sas.h>
   54 #include <dev/mpr/mpi/mpi2_pci.h>
   55 #include <dev/mpr/mpi/mpi2_cnfg.h>
   56 #include <dev/mpr/mpi/mpi2_init.h>
   57 #include <dev/mpr/mpi/mpi2_tool.h>
   58 #include <dev/mpr/mpr_ioctl.h>
   59 #include <dev/mpr/mprvar.h>
   60 #include <dev/mpr/mpr_mapping.h>
   61 
   62 /**
   63  * _mapping_clear_map_entry - Clear a particular mapping entry.
   64  * @map_entry: map table entry
   65  *
   66  * Returns nothing.
   67  */
   68 static inline void
   69 _mapping_clear_map_entry(struct dev_mapping_table *map_entry)
   70 {
   71         map_entry->physical_id = 0;
   72         map_entry->device_info = 0;
   73         map_entry->phy_bits = 0;
   74         map_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
   75         map_entry->dev_handle = 0;
   76         map_entry->id = -1;
   77         map_entry->missing_count = 0;
   78         map_entry->init_complete = 0;
   79         map_entry->TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
   80 }
   81 
   82 /**
   83  * _mapping_clear_enc_entry - Clear a particular enclosure table entry.
   84  * @enc_entry: enclosure table entry
   85  *
   86  * Returns nothing.
   87  */
   88 static inline void
   89 _mapping_clear_enc_entry(struct enc_mapping_table *enc_entry)
   90 {
   91         enc_entry->enclosure_id = 0;
   92         enc_entry->start_index = MPR_MAPTABLE_BAD_IDX;
   93         enc_entry->phy_bits = 0;
   94         enc_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
   95         enc_entry->enc_handle = 0;
   96         enc_entry->num_slots = 0;
   97         enc_entry->start_slot = 0;
   98         enc_entry->missing_count = 0;
   99         enc_entry->removal_flag = 0;
  100         enc_entry->skip_search = 0;
  101         enc_entry->init_complete = 0;
  102 }
  103 
  104 /**
  105  * _mapping_commit_enc_entry - write a particular enc entry in DPM page0.
  106  * @sc: per adapter object
  107  * @enc_entry: enclosure table entry
  108  *
  109  * Returns 0 for success, non-zero for failure.
  110  */
  111 static int
  112 _mapping_commit_enc_entry(struct mpr_softc *sc,
  113     struct enc_mapping_table *et_entry)
  114 {
  115         Mpi2DriverMap0Entry_t *dpm_entry;
  116         struct dev_mapping_table *mt_entry;
  117         Mpi2ConfigReply_t mpi_reply;
  118         Mpi2DriverMappingPage0_t config_page;
  119 
  120         if (!sc->is_dpm_enable)
  121                 return 0;
  122 
  123         memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
  124         memcpy(&config_page.Header, (u8 *) sc->dpm_pg0,
  125             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
  126         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
  127             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
  128         dpm_entry += et_entry->dpm_entry_num;
  129         dpm_entry->PhysicalIdentifier.Low =
  130             ( 0xFFFFFFFF & et_entry->enclosure_id);
  131         dpm_entry->PhysicalIdentifier.High =
  132             ( et_entry->enclosure_id >> 32);
  133         mt_entry = &sc->mapping_table[et_entry->start_index];
  134         dpm_entry->DeviceIndex = htole16(mt_entry->id);
  135         dpm_entry->MappingInformation = et_entry->num_slots;
  136         dpm_entry->MappingInformation <<= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
  137         dpm_entry->MappingInformation |= et_entry->missing_count;
  138         dpm_entry->MappingInformation = htole16(dpm_entry->MappingInformation);
  139         dpm_entry->PhysicalBitsMapping = htole32(et_entry->phy_bits);
  140         dpm_entry->Reserved1 = 0;
  141 
  142         mpr_dprint(sc, MPR_MAPPING, "%s: Writing DPM entry %d for enclosure.\n",
  143             __func__, et_entry->dpm_entry_num);
  144         memcpy(&config_page.Entry, (u8 *)dpm_entry,
  145             sizeof(Mpi2DriverMap0Entry_t));
  146         if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
  147             et_entry->dpm_entry_num)) {
  148                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Write of DPM "
  149                     "entry %d for enclosure failed.\n", __func__,
  150                     et_entry->dpm_entry_num);
  151                 dpm_entry->MappingInformation = le16toh(dpm_entry->
  152                     MappingInformation);
  153                 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
  154                 dpm_entry->PhysicalBitsMapping =
  155                     le32toh(dpm_entry->PhysicalBitsMapping);
  156                 return -1;
  157         }
  158         dpm_entry->MappingInformation = le16toh(dpm_entry->
  159             MappingInformation);
  160         dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
  161         dpm_entry->PhysicalBitsMapping =
  162             le32toh(dpm_entry->PhysicalBitsMapping);
  163         return 0;
  164 }
  165 
  166 /**
  167  * _mapping_commit_map_entry - write a particular map table entry in DPM page0.
  168  * @sc: per adapter object
  169  * @mt_entry: mapping table entry
  170  *
  171  * Returns 0 for success, non-zero for failure.
  172  */
  173 
  174 static int
  175 _mapping_commit_map_entry(struct mpr_softc *sc,
  176     struct dev_mapping_table *mt_entry)
  177 {
  178         Mpi2DriverMap0Entry_t *dpm_entry;
  179         Mpi2ConfigReply_t mpi_reply;
  180         Mpi2DriverMappingPage0_t config_page;
  181 
  182         if (!sc->is_dpm_enable)
  183                 return 0;
  184 
  185         /*
  186          * It's possible that this Map Entry points to a BAD DPM index. This
  187          * can happen if the Map Entry is a for a missing device and the DPM
  188          * entry that was being used by this device is now being used by some
  189          * new device. So, check for a BAD DPM index and just return if so.
  190          */
  191         if (mt_entry->dpm_entry_num == MPR_DPM_BAD_IDX) {
  192                 mpr_dprint(sc, MPR_MAPPING, "%s: DPM entry location for target "
  193                     "%d is invalid. DPM will not be written.\n", __func__,
  194                     mt_entry->id);
  195                 return 0;
  196         }
  197 
  198         memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
  199         memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
  200             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
  201         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *) sc->dpm_pg0 +
  202             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
  203         dpm_entry = dpm_entry + mt_entry->dpm_entry_num;
  204         dpm_entry->PhysicalIdentifier.Low = (0xFFFFFFFF &
  205             mt_entry->physical_id);
  206         dpm_entry->PhysicalIdentifier.High = (mt_entry->physical_id >> 32);
  207         dpm_entry->DeviceIndex = htole16(mt_entry->id);
  208         dpm_entry->MappingInformation = htole16(mt_entry->missing_count);
  209         dpm_entry->PhysicalBitsMapping = 0;
  210         dpm_entry->Reserved1 = 0;
  211         memcpy(&config_page.Entry, (u8 *)dpm_entry,
  212             sizeof(Mpi2DriverMap0Entry_t));
  213 
  214         mpr_dprint(sc, MPR_MAPPING, "%s: Writing DPM entry %d for target %d.\n",
  215             __func__, mt_entry->dpm_entry_num, mt_entry->id);
  216         if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
  217             mt_entry->dpm_entry_num)) {
  218                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Write of DPM "
  219                     "entry %d for target %d failed.\n", __func__,
  220                     mt_entry->dpm_entry_num, mt_entry->id);
  221                 dpm_entry->MappingInformation = le16toh(dpm_entry->
  222                     MappingInformation);
  223                 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
  224                 return -1;
  225         }
  226 
  227         dpm_entry->MappingInformation = le16toh(dpm_entry->MappingInformation);
  228         dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
  229         return 0;
  230 }
  231 
  232 /**
  233  * _mapping_get_ir_maprange - get start and end index for IR map range.
  234  * @sc: per adapter object
  235  * @start_idx: place holder for start index
  236  * @end_idx: place holder for end index
  237  *
  238  * The IR volumes can be mapped either at start or end of the mapping table
  239  * this function gets the detail of where IR volume mapping starts and ends
  240  * in the device mapping table
  241  *
  242  * Returns nothing.
  243  */
  244 static void
  245 _mapping_get_ir_maprange(struct mpr_softc *sc, u32 *start_idx, u32 *end_idx)
  246 {
  247         u16 volume_mapping_flags;
  248         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
  249 
  250         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
  251             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
  252         if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
  253                 *start_idx = 0;
  254                 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
  255                         *start_idx = 1;
  256         } else
  257                 *start_idx = sc->max_devices - sc->max_volumes;
  258         *end_idx = *start_idx + sc->max_volumes - 1;
  259 }
  260 
  261 /**
  262  * _mapping_get_enc_idx_from_id - get enclosure index from enclosure ID
  263  * @sc: per adapter object
  264  * @enc_id: enclosure logical identifier
  265  *
  266  * Returns the index of enclosure entry on success or bad index.
  267  */
  268 static u8
  269 _mapping_get_enc_idx_from_id(struct mpr_softc *sc, u64 enc_id,
  270     u64 phy_bits)
  271 {
  272         struct enc_mapping_table *et_entry;
  273         u8 enc_idx = 0;
  274 
  275         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
  276                 et_entry = &sc->enclosure_table[enc_idx];
  277                 if ((et_entry->enclosure_id == le64toh(enc_id)) &&
  278                     (!et_entry->phy_bits || (et_entry->phy_bits &
  279                     le32toh(phy_bits))))
  280                         return enc_idx;
  281         }
  282         return MPR_ENCTABLE_BAD_IDX;
  283 }
  284 
  285 /**
  286  * _mapping_get_enc_idx_from_handle - get enclosure index from handle
  287  * @sc: per adapter object
  288  * @enc_id: enclosure handle
  289  *
  290  * Returns the index of enclosure entry on success or bad index.
  291  */
  292 static u8
  293 _mapping_get_enc_idx_from_handle(struct mpr_softc *sc, u16 handle)
  294 {
  295         struct enc_mapping_table *et_entry;
  296         u8 enc_idx = 0;
  297 
  298         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
  299                 et_entry = &sc->enclosure_table[enc_idx];
  300                 if (et_entry->missing_count)
  301                         continue;
  302                 if (et_entry->enc_handle == handle)
  303                         return enc_idx;
  304         }
  305         return MPR_ENCTABLE_BAD_IDX;
  306 }
  307 
  308 /**
  309  * _mapping_get_high_missing_et_idx - get missing enclosure index
  310  * @sc: per adapter object
  311  *
  312  * Search through the enclosure table and identifies the enclosure entry
  313  * with high missing count and returns it's index
  314  *
  315  * Returns the index of enclosure entry on success or bad index.
  316  */
  317 static u8
  318 _mapping_get_high_missing_et_idx(struct mpr_softc *sc)
  319 {
  320         struct enc_mapping_table *et_entry;
  321         u8 high_missing_count = 0;
  322         u8 enc_idx, high_idx = MPR_ENCTABLE_BAD_IDX;
  323 
  324         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++) {
  325                 et_entry = &sc->enclosure_table[enc_idx];
  326                 if ((et_entry->missing_count > high_missing_count) &&
  327                     !et_entry->skip_search) {
  328                         high_missing_count = et_entry->missing_count;
  329                         high_idx = enc_idx;
  330                 }
  331         }
  332         return high_idx;
  333 }
  334 
  335 /**
  336  * _mapping_get_high_missing_mt_idx - get missing map table index
  337  * @sc: per adapter object
  338  *
  339  * Search through the map table and identifies the device entry
  340  * with high missing count and returns it's index
  341  *
  342  * Returns the index of map table entry on success or bad index.
  343  */
  344 static u32
  345 _mapping_get_high_missing_mt_idx(struct mpr_softc *sc)
  346 {
  347         u32 map_idx, high_idx = MPR_MAPTABLE_BAD_IDX;
  348         u8 high_missing_count = 0;
  349         u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
  350         struct dev_mapping_table *mt_entry;
  351         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
  352 
  353         start_idx = 0;
  354         start_idx_ir = 0;
  355         end_idx_ir = 0;
  356         end_idx = sc->max_devices;
  357         if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
  358                 start_idx = 1;
  359         if (sc->ir_firmware) {
  360                 _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
  361                 if (start_idx == start_idx_ir)
  362                         start_idx = end_idx_ir + 1;
  363                 else
  364                         end_idx = start_idx_ir;
  365         }
  366         mt_entry = &sc->mapping_table[start_idx];
  367         for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
  368                 if (mt_entry->missing_count > high_missing_count) {
  369                         high_missing_count =  mt_entry->missing_count;
  370                         high_idx = map_idx;
  371                 }
  372         }
  373         return high_idx;
  374 }
  375 
  376 /**
  377  * _mapping_get_ir_mt_idx_from_wwid - get map table index from volume WWID
  378  * @sc: per adapter object
  379  * @wwid: world wide unique ID of the volume
  380  *
  381  * Returns the index of map table entry on success or bad index.
  382  */
  383 static u32
  384 _mapping_get_ir_mt_idx_from_wwid(struct mpr_softc *sc, u64 wwid)
  385 {
  386         u32 start_idx, end_idx, map_idx;
  387         struct dev_mapping_table *mt_entry;
  388 
  389         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
  390         mt_entry = &sc->mapping_table[start_idx];
  391         for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
  392                 if (mt_entry->physical_id == wwid)
  393                         return map_idx;
  394 
  395         return MPR_MAPTABLE_BAD_IDX;
  396 }
  397 
  398 /**
  399  * _mapping_get_mt_idx_from_id - get map table index from a device ID
  400  * @sc: per adapter object
  401  * @dev_id: device identifer (SAS Address)
  402  *
  403  * Returns the index of map table entry on success or bad index.
  404  */
  405 static u32
  406 _mapping_get_mt_idx_from_id(struct mpr_softc *sc, u64 dev_id)
  407 {
  408         u32 map_idx;
  409         struct dev_mapping_table *mt_entry;
  410 
  411         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
  412                 mt_entry = &sc->mapping_table[map_idx];
  413                 if (mt_entry->physical_id == dev_id)
  414                         return map_idx;
  415         }
  416         return MPR_MAPTABLE_BAD_IDX;
  417 }
  418 
  419 /**
  420  * _mapping_get_ir_mt_idx_from_handle - get map table index from volume handle
  421  * @sc: per adapter object
  422  * @wwid: volume device handle
  423  *
  424  * Returns the index of map table entry on success or bad index.
  425  */
  426 static u32
  427 _mapping_get_ir_mt_idx_from_handle(struct mpr_softc *sc, u16 volHandle)
  428 {
  429         u32 start_idx, end_idx, map_idx;
  430         struct dev_mapping_table *mt_entry;
  431 
  432         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
  433         mt_entry = &sc->mapping_table[start_idx];
  434         for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++)
  435                 if (mt_entry->dev_handle == volHandle)
  436                         return map_idx;
  437 
  438         return MPR_MAPTABLE_BAD_IDX;
  439 }
  440 
  441 /**
  442  * _mapping_get_mt_idx_from_handle - get map table index from handle
  443  * @sc: per adapter object
  444  * @dev_id: device handle
  445  *
  446  * Returns the index of map table entry on success or bad index.
  447  */
  448 static u32
  449 _mapping_get_mt_idx_from_handle(struct mpr_softc *sc, u16 handle)
  450 {
  451         u32 map_idx;
  452         struct dev_mapping_table *mt_entry;
  453 
  454         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
  455                 mt_entry = &sc->mapping_table[map_idx];
  456                 if (mt_entry->dev_handle == handle)
  457                         return map_idx;
  458         }
  459         return MPR_MAPTABLE_BAD_IDX;
  460 }
  461 
  462 /**
  463  * _mapping_get_free_ir_mt_idx - get first free index for a volume
  464  * @sc: per adapter object
  465  *
  466  * Search through mapping table for free index for a volume and if no free
  467  * index then looks for a volume with high mapping index
  468  *
  469  * Returns the index of map table entry on success or bad index.
  470  */
  471 static u32
  472 _mapping_get_free_ir_mt_idx(struct mpr_softc *sc)
  473 {
  474         u8 high_missing_count = 0;
  475         u32 start_idx, end_idx, map_idx;
  476         u32 high_idx = MPR_MAPTABLE_BAD_IDX;
  477         struct dev_mapping_table *mt_entry;
  478 
  479         /*
  480          * The IN_USE flag should be clear if the entry is available to use.
  481          * This flag is cleared on initialization and and when a volume is
  482          * deleted. All other times this flag should be set. If, for some
  483          * reason, a free entry cannot be found, look for the entry with the
  484          * highest missing count just in case there is one.
  485          */
  486         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
  487         mt_entry = &sc->mapping_table[start_idx];
  488         for (map_idx = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
  489                 if (!(mt_entry->device_info & MPR_MAP_IN_USE))
  490                         return map_idx;
  491 
  492                 if (mt_entry->missing_count > high_missing_count) {
  493                         high_missing_count = mt_entry->missing_count;
  494                         high_idx = map_idx;
  495                 }
  496         }
  497 
  498         if (high_idx == MPR_MAPTABLE_BAD_IDX) {
  499                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Could not find a "
  500                     "free entry in the mapping table for a Volume. The mapping "
  501                     "table is probably corrupt.\n", __func__);
  502         }
  503         
  504         return high_idx;
  505 }
  506 
  507 /**
  508  * _mapping_get_free_mt_idx - get first free index for a device
  509  * @sc: per adapter object
  510  * @start_idx: offset in the table to start search
  511  *
  512  * Returns the index of map table entry on success or bad index.
  513  */
  514 static u32
  515 _mapping_get_free_mt_idx(struct mpr_softc *sc, u32 start_idx)
  516 {
  517         u32 map_idx, max_idx = sc->max_devices;
  518         struct dev_mapping_table *mt_entry = &sc->mapping_table[start_idx];
  519         u16 volume_mapping_flags;
  520 
  521         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
  522             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
  523         if (sc->ir_firmware && (volume_mapping_flags ==
  524             MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING))
  525                 max_idx -= sc->max_volumes;
  526 
  527         for (map_idx  = start_idx; map_idx < max_idx; map_idx++, mt_entry++)
  528                 if (!(mt_entry->device_info & (MPR_MAP_IN_USE |
  529                     MPR_DEV_RESERVED)))
  530                         return map_idx;
  531 
  532         return MPR_MAPTABLE_BAD_IDX;
  533 }
  534 
  535 /**
  536  * _mapping_get_dpm_idx_from_id - get DPM index from ID
  537  * @sc: per adapter object
  538  * @id: volume WWID or enclosure ID or device ID
  539  *
  540  * Returns the index of DPM entry on success or bad index.
  541  */
  542 static u16
  543 _mapping_get_dpm_idx_from_id(struct mpr_softc *sc, u64 id, u32 phy_bits)
  544 {
  545         u16 entry_num;
  546         uint64_t PhysicalIdentifier;
  547         Mpi2DriverMap0Entry_t *dpm_entry;
  548 
  549         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
  550             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
  551         PhysicalIdentifier = dpm_entry->PhysicalIdentifier.High;
  552         PhysicalIdentifier = (PhysicalIdentifier << 32) | 
  553             dpm_entry->PhysicalIdentifier.Low;
  554         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++,
  555             dpm_entry++)
  556                 if ((id == PhysicalIdentifier) &&
  557                     (!phy_bits || !dpm_entry->PhysicalBitsMapping ||
  558                     (phy_bits & dpm_entry->PhysicalBitsMapping)))
  559                         return entry_num;
  560 
  561         return MPR_DPM_BAD_IDX;
  562 }
  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                         } else {
 1192                                 mpr_dprint(sc, MPR_INFO, "SAS Address for SATA "
 1193                                     "device = %jx\n", sas_address);
 1194                         }
 1195                 }
 1196 
 1197                 phy_change->physical_id = sas_address;
 1198                 phy_change->slot = le16toh(sas_device_pg0.Slot);
 1199                 phy_change->device_info = device_info;
 1200 
 1201                 /*
 1202                  * When using Enc/Slot mapping, if this device is an enclosure
 1203                  * make sure that all of its slots can fit into the mapping
 1204                  * table.
 1205                  */
 1206                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 1207                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 1208                         /*
 1209                          * The enclosure should already be in the enclosure
 1210                          * table due to the Enclosure Add event. If not, just
 1211                          * continue, nothing can be done.
 1212                          */
 1213                         enc_idx = _mapping_get_enc_idx_from_handle(sc,
 1214                             topo_change->enc_handle);
 1215                         if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
 1216                                 phy_change->is_processed = 1;
 1217                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 1218                                     "failed to add the device with handle "
 1219                                     "0x%04x because the enclosure is not in "
 1220                                     "the mapping table\n", __func__,
 1221                                     phy_change->dev_handle);
 1222                                 continue;
 1223                         }
 1224                         if (!((phy_change->device_info &
 1225                             MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
 1226                             (phy_change->device_info &
 1227                             (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
 1228                             MPI2_SAS_DEVICE_INFO_STP_TARGET |
 1229                             MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))) {
 1230                                 phy_change->is_processed = 1;
 1231                                 continue;
 1232                         }
 1233                         et_entry = &sc->enclosure_table[enc_idx];
 1234 
 1235                         /*
 1236                          * If the enclosure already has a start_index, it's been
 1237                          * mapped, so go to the next Topo change.
 1238                          */
 1239                         if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX)
 1240                                 continue;
 1241 
 1242                         /*
 1243                          * If the Expander Handle is 0, the devices are direct
 1244                          * attached. In that case, the start_index must be just 
 1245                          * after the reserved entries. Otherwise, find space in
 1246                          * the mapping table for the enclosure's devices.
 1247                          */ 
 1248                         if (!topo_change->exp_handle) {
 1249                                 map_idx = sc->num_rsvd_entries;
 1250                                 et_entry->start_index = map_idx;
 1251                         } else {
 1252                                 map_idx = _mapping_find_enc_map_space(sc,
 1253                                     et_entry);
 1254                                 et_entry->start_index = map_idx;
 1255 
 1256                                 /*
 1257                                  * If space cannot be found to hold all of the
 1258                                  * enclosure's devices in the mapping table,
 1259                                  * there's no need to continue checking the
 1260                                  * other devices in this event. Set all of the
 1261                                  * phy_details for this event (if the change is
 1262                                  * for an add) as already processed because none
 1263                                  * of these devices can be added to the mapping
 1264                                  * table.
 1265                                  */
 1266                                 if (et_entry->start_index ==
 1267                                     MPR_MAPTABLE_BAD_IDX) {
 1268                                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
 1269                                             "%s: failed to add the enclosure "
 1270                                             "with ID 0x%016jx because there is "
 1271                                             "no free space available in the "
 1272                                             "mapping table for all of the "
 1273                                             "enclosure's devices.\n", __func__,
 1274                                             (uintmax_t)et_entry->enclosure_id);
 1275                                         phy_change->is_processed = 1;
 1276                                         for (phy_idx = 0; phy_idx <
 1277                                             topo_change->num_entries;
 1278                                             phy_idx++) {
 1279                                                 tmp_phy_change =
 1280                                                     &topo_change->phy_details
 1281                                                     [phy_idx];
 1282                                                 if (tmp_phy_change->reason ==
 1283                                                     add_code)
 1284                                                         tmp_phy_change->
 1285                                                             is_processed = 1;
 1286                                         }
 1287                                         break;
 1288                                 }
 1289                         }
 1290 
 1291                         /*
 1292                          * Found space in the mapping table for this enclosure.
 1293                          * Initialize each mapping table entry for the
 1294                          * enclosure.
 1295                          */
 1296                         mpr_dprint(sc, MPR_MAPPING, "%s: Initialize %d map "
 1297                             "entries for the enclosure, starting at map index "
 1298                             " %d.\n", __func__, et_entry->num_slots, map_idx);
 1299                         mt_entry = &sc->mapping_table[map_idx];
 1300                         for (index = map_idx; index < (et_entry->num_slots
 1301                             + map_idx); index++, mt_entry++) {
 1302                                 mt_entry->device_info = MPR_DEV_RESERVED;
 1303                                 mt_entry->physical_id = et_entry->enclosure_id;
 1304                                 mt_entry->phy_bits = et_entry->phy_bits;
 1305                                 mt_entry->missing_count = 0;
 1306                         }
 1307                 }
 1308         }
 1309 }
 1310 
 1311 /**
 1312  * _mapping_get_pcie_dev_info -get information about newly added PCIe devices
 1313  * @sc: per adapter object
 1314  * @topo_change: Topology change event entry
 1315  *
 1316  * Searches through the PCIe topology change event list and issues PCIe device
 1317  * pg0 requests for the newly added PCIe device. If the device is in an
 1318  * enclosure, search for available space in the enclosure mapping table for the
 1319  * device and reserve that space.
 1320  *
 1321  * Returns nothing
 1322  */
 1323 static void
 1324 _mapping_get_pcie_dev_info(struct mpr_softc *sc,
 1325     struct _map_pcie_topology_change *topo_change)
 1326 {
 1327         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 1328         Mpi2ConfigReply_t mpi_reply;
 1329         Mpi26PCIeDevicePage0_t pcie_device_pg0;
 1330         u8 entry, enc_idx, port_idx;
 1331         u32 map_idx, index;
 1332         struct _map_port_change *port_change, *tmp_port_change;
 1333         uint64_t pcie_wwid;
 1334         struct enc_mapping_table *et_entry;
 1335         struct dev_mapping_table *mt_entry;
 1336         u8 add_code = MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED;
 1337 
 1338         for (entry = 0; entry < topo_change->num_entries; entry++) {
 1339                 port_change = &topo_change->port_details[entry];
 1340                 if (port_change->is_processed || !port_change->dev_handle ||
 1341                     port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED)
 1342                         continue;
 1343                 if (mpr_config_get_pcie_device_pg0(sc, &mpi_reply,
 1344                     &pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE,
 1345                     port_change->dev_handle)) {
 1346                         port_change->is_processed = 1;
 1347                         continue;
 1348                 }
 1349 
 1350                 pcie_wwid = pcie_device_pg0.WWID.High;
 1351                 pcie_wwid = (pcie_wwid << 32) | pcie_device_pg0.WWID.Low;
 1352                 port_change->physical_id = pcie_wwid;
 1353                 port_change->slot = le16toh(pcie_device_pg0.Slot);
 1354                 port_change->device_info = le32toh(pcie_device_pg0.DeviceInfo);
 1355 
 1356                 /*
 1357                  * When using Enc/Slot mapping, if this device is an enclosure
 1358                  * make sure that all of its slots can fit into the mapping
 1359                  * table.
 1360                  */
 1361                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 1362                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 1363                         /*
 1364                          * The enclosure should already be in the enclosure
 1365                          * table due to the Enclosure Add event. If not, just
 1366                          * continue, nothing can be done.
 1367                          */
 1368                         enc_idx = _mapping_get_enc_idx_from_handle(sc,
 1369                             topo_change->enc_handle);
 1370                         if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
 1371                                 port_change->is_processed = 1;
 1372                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 1373                                     "failed to add the device with handle "
 1374                                     "0x%04x because the enclosure is not in "
 1375                                     "the mapping table\n", __func__,
 1376                                     port_change->dev_handle);
 1377                                 continue;
 1378                         }
 1379                         if (!(port_change->device_info &
 1380                             MPI26_PCIE_DEVINFO_NVME)) {
 1381                                 port_change->is_processed = 1;
 1382                                 continue;
 1383                         }
 1384                         et_entry = &sc->enclosure_table[enc_idx];
 1385 
 1386                         /*
 1387                          * If the enclosure already has a start_index, it's been
 1388                          * mapped, so go to the next Topo change.
 1389                          */
 1390                         if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX)
 1391                                 continue;
 1392 
 1393                         /*
 1394                          * If the Switch Handle is 0, the devices are direct
 1395                          * attached. In that case, the start_index must be just 
 1396                          * after the reserved entries. Otherwise, find space in
 1397                          * the mapping table for the enclosure's devices.
 1398                          */ 
 1399                         if (!topo_change->switch_dev_handle) {
 1400                                 map_idx = sc->num_rsvd_entries;
 1401                                 et_entry->start_index = map_idx;
 1402                         } else {
 1403                                 map_idx = _mapping_find_enc_map_space(sc,
 1404                                     et_entry);
 1405                                 et_entry->start_index = map_idx;
 1406 
 1407                                 /*
 1408                                  * If space cannot be found to hold all of the
 1409                                  * enclosure's devices in the mapping table,
 1410                                  * there's no need to continue checking the
 1411                                  * other devices in this event. Set all of the
 1412                                  * port_details for this event (if the change is
 1413                                  * for an add) as already processed because none
 1414                                  * of these devices can be added to the mapping
 1415                                  * table.
 1416                                  */
 1417                                 if (et_entry->start_index ==
 1418                                     MPR_MAPTABLE_BAD_IDX) {
 1419                                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
 1420                                             "%s: failed to add the enclosure "
 1421                                             "with ID 0x%016jx because there is "
 1422                                             "no free space available in the "
 1423                                             "mapping table for all of the "
 1424                                             "enclosure's devices.\n", __func__,
 1425                                             (uintmax_t)et_entry->enclosure_id);
 1426                                         port_change->is_processed = 1;
 1427                                         for (port_idx = 0; port_idx <
 1428                                             topo_change->num_entries;
 1429                                             port_idx++) {
 1430                                                 tmp_port_change =
 1431                                                     &topo_change->port_details
 1432                                                     [port_idx];
 1433                                                 if (tmp_port_change->reason ==
 1434                                                     add_code)
 1435                                                         tmp_port_change->
 1436                                                             is_processed = 1;
 1437                                         }
 1438                                         break;
 1439                                 }
 1440                         }
 1441 
 1442                         /*
 1443                          * Found space in the mapping table for this enclosure.
 1444                          * Initialize each mapping table entry for the
 1445                          * enclosure.
 1446                          */
 1447                         mpr_dprint(sc, MPR_MAPPING, "%s: Initialize %d map "
 1448                             "entries for the enclosure, starting at map index "
 1449                             " %d.\n", __func__, et_entry->num_slots, map_idx);
 1450                         mt_entry = &sc->mapping_table[map_idx];
 1451                         for (index = map_idx; index < (et_entry->num_slots
 1452                             + map_idx); index++, mt_entry++) {
 1453                                 mt_entry->device_info = MPR_DEV_RESERVED;
 1454                                 mt_entry->physical_id = et_entry->enclosure_id;
 1455                                 mt_entry->phy_bits = et_entry->phy_bits;
 1456                                 mt_entry->missing_count = 0;
 1457                         }
 1458                 }
 1459         }
 1460 }
 1461 
 1462 /**
 1463  * _mapping_set_mid_to_eid -set map table data from enclosure table
 1464  * @sc: per adapter object
 1465  * @et_entry: enclosure entry
 1466  *
 1467  * Returns nothing
 1468  */
 1469 static inline void
 1470 _mapping_set_mid_to_eid(struct mpr_softc *sc,
 1471     struct enc_mapping_table *et_entry)
 1472 {
 1473         struct dev_mapping_table *mt_entry;
 1474         u16 slots = et_entry->num_slots, map_idx;
 1475         u32 start_idx = et_entry->start_index;
 1476 
 1477         if (start_idx != MPR_MAPTABLE_BAD_IDX) {
 1478                 mt_entry = &sc->mapping_table[start_idx];
 1479                 for (map_idx = 0; map_idx < slots; map_idx++, mt_entry++)
 1480                         mt_entry->physical_id = et_entry->enclosure_id;
 1481         }
 1482 }
 1483 
 1484 /**
 1485  * _mapping_clear_removed_entries - mark the entries to be cleared
 1486  * @sc: per adapter object
 1487  *
 1488  * Search through the removal table and mark the entries which needs to be
 1489  * flushed to DPM and also updates the map table and enclosure table by
 1490  * clearing the corresponding entries.
 1491  *
 1492  * Returns nothing
 1493  */
 1494 static void
 1495 _mapping_clear_removed_entries(struct mpr_softc *sc)
 1496 {
 1497         u32 remove_idx;
 1498         struct map_removal_table *remove_entry;
 1499         Mpi2DriverMap0Entry_t *dpm_entry;
 1500         u8 done_flag = 0, num_entries, m, i;
 1501         struct enc_mapping_table *et_entry, *from, *to;
 1502         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 1503 
 1504         if (sc->is_dpm_enable) {
 1505                 remove_entry = sc->removal_table;
 1506                 for (remove_idx = 0; remove_idx < sc->max_devices;
 1507                     remove_idx++, remove_entry++) {
 1508                         if (remove_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
 1509                                 dpm_entry = (Mpi2DriverMap0Entry_t *)
 1510                                     ((u8 *) sc->dpm_pg0 +
 1511                                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
 1512                                 dpm_entry += remove_entry->dpm_entry_num;
 1513                                 dpm_entry->PhysicalIdentifier.Low = 0;
 1514                                 dpm_entry->PhysicalIdentifier.High = 0;
 1515                                 dpm_entry->DeviceIndex = 0;
 1516                                 dpm_entry->MappingInformation = 0;
 1517                                 dpm_entry->PhysicalBitsMapping = 0;
 1518                                 sc->dpm_flush_entry[remove_entry->
 1519                                     dpm_entry_num] = 1;
 1520                                 sc->dpm_entry_used[remove_entry->dpm_entry_num]
 1521                                     = 0;
 1522                                 remove_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
 1523                         }
 1524                 }
 1525         }
 1526 
 1527         /*
 1528          * When using Enc/Slot mapping, if a new enclosure was added and old
 1529          * enclosure space was needed, the enclosure table may now have gaps
 1530          * that need to be closed. All enclosure mappings need to be contiguous
 1531          * so that space can be reused correctly if available.
 1532          */
 1533         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 1534             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 1535                 num_entries = sc->num_enc_table_entries;
 1536                 while (!done_flag) {
 1537                         done_flag = 1;
 1538                         et_entry = sc->enclosure_table;
 1539                         for (i = 0; i < num_entries; i++, et_entry++) {
 1540                                 if (!et_entry->enc_handle && et_entry->
 1541                                     init_complete) {
 1542                                         done_flag = 0;
 1543                                         if (i != (num_entries - 1)) {
 1544                                                 from = &sc->enclosure_table
 1545                                                     [i+1];
 1546                                                 to = &sc->enclosure_table[i];
 1547                                                 for (m = i; m < (num_entries -
 1548                                                     1); m++, from++, to++) {
 1549                                                         _mapping_set_mid_to_eid
 1550                                                             (sc, to);
 1551                                                         *to = *from;
 1552                                                 }
 1553                                                 _mapping_clear_enc_entry(to);
 1554                                                 sc->num_enc_table_entries--;
 1555                                                 num_entries =
 1556                                                     sc->num_enc_table_entries;
 1557                                         } else {
 1558                                                 _mapping_clear_enc_entry
 1559                                                     (et_entry);
 1560                                                 sc->num_enc_table_entries--;
 1561                                                 num_entries =
 1562                                                     sc->num_enc_table_entries;
 1563                                         }
 1564                                 }
 1565                         }
 1566                 }
 1567         }
 1568 }
 1569 
 1570 /**
 1571  * _mapping_add_new_device -Add the new device into mapping table
 1572  * @sc: per adapter object
 1573  * @topo_change: Topology change event entry
 1574  *
 1575  * Search through the topology change event list and update map table,
 1576  * enclosure table and DPM pages for the newly added devices.
 1577  *
 1578  * Returns nothing
 1579  */
 1580 static void
 1581 _mapping_add_new_device(struct mpr_softc *sc,
 1582     struct _map_topology_change *topo_change)
 1583 {
 1584         u8 enc_idx, missing_cnt, is_removed = 0;
 1585         u16 dpm_idx;
 1586         u32 search_idx, map_idx;
 1587         u32 entry;
 1588         struct dev_mapping_table *mt_entry;
 1589         struct enc_mapping_table *et_entry;
 1590         struct _map_phy_change *phy_change;
 1591         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 1592         Mpi2DriverMap0Entry_t *dpm_entry;
 1593         uint64_t temp64_var;
 1594         u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
 1595         u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
 1596         u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
 1597 
 1598         for (entry = 0; entry < topo_change->num_entries; entry++) {
 1599                 phy_change = &topo_change->phy_details[entry];
 1600                 if (phy_change->is_processed)
 1601                         continue;
 1602                 if (phy_change->reason != MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED ||
 1603                     !phy_change->dev_handle) {
 1604                         phy_change->is_processed = 1;
 1605                         continue;
 1606                 }
 1607                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 1608                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 1609                         enc_idx = _mapping_get_enc_idx_from_handle
 1610                             (sc, topo_change->enc_handle);
 1611                         if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
 1612                                 phy_change->is_processed = 1;
 1613                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 1614                                     "failed to add the device with handle "
 1615                                     "0x%04x because the enclosure is not in "
 1616                                     "the mapping table\n", __func__,
 1617                                     phy_change->dev_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                         /*
 1712                          * Get the mapping table index for this device. If it's
 1713                          * not in the mapping table yet, find a free entry if
 1714                          * one is available. If there are no free entries, look
 1715                          * for the entry that has the highest missing count. If
 1716                          * none of that works to find an entry in the mapping
 1717                          * table, there is a problem. Log a message and just
 1718                          * continue on.
 1719                          */
 1720                         map_idx = _mapping_get_mt_idx_from_id
 1721                             (sc, phy_change->physical_id);
 1722                         if (map_idx == MPR_MAPTABLE_BAD_IDX) {
 1723                                 search_idx = sc->num_rsvd_entries;
 1724                                 if (topo_change->exp_handle)
 1725                                         search_idx += max_num_phy_ids;
 1726                                 map_idx = _mapping_get_free_mt_idx(sc,
 1727                                     search_idx);
 1728                         }
 1729 
 1730                         /*
 1731                          * If an entry will be used that has a missing device,
 1732                          * clear its entry from  the DPM in the controller.
 1733                          */
 1734                         if (map_idx == MPR_MAPTABLE_BAD_IDX) {
 1735                                 map_idx = _mapping_get_high_missing_mt_idx(sc);
 1736                                 if (map_idx != MPR_MAPTABLE_BAD_IDX) {
 1737                                         mt_entry = &sc->mapping_table[map_idx];
 1738                                         _mapping_add_to_removal_table(sc,
 1739                                             mt_entry->dpm_entry_num);
 1740                                         is_removed = 1;
 1741                                         mt_entry->init_complete = 0;
 1742                                 }
 1743                         }
 1744                         if (map_idx != MPR_MAPTABLE_BAD_IDX) {
 1745                                 mt_entry = &sc->mapping_table[map_idx];
 1746                                 mt_entry->physical_id = phy_change->physical_id;
 1747                                 mt_entry->id = map_idx;
 1748                                 mt_entry->dev_handle = phy_change->dev_handle;
 1749                                 mt_entry->missing_count = 0;
 1750                                 mt_entry->device_info = phy_change->device_info
 1751                                     | (MPR_DEV_RESERVED | MPR_MAP_IN_USE);
 1752                         } else {
 1753                                 phy_change->is_processed = 1;
 1754                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 1755                                     "failed to add the device with handle "
 1756                                     "0x%04x because there is no free space "
 1757                                     "available in the mapping table\n",
 1758                                     __func__, phy_change->dev_handle);
 1759                                 continue;
 1760                         }
 1761                         if (sc->is_dpm_enable) {
 1762                                 if (mt_entry->dpm_entry_num !=
 1763                                     MPR_DPM_BAD_IDX) {
 1764                                         dpm_idx = mt_entry->dpm_entry_num;
 1765                                         dpm_entry = (Mpi2DriverMap0Entry_t *)
 1766                                             ((u8 *)sc->dpm_pg0 + hdr_sz);
 1767                                         dpm_entry += dpm_idx;
 1768                                         missing_cnt = dpm_entry->
 1769                                             MappingInformation &
 1770                                             MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
 1771                                         temp64_var = dpm_entry->
 1772                                             PhysicalIdentifier.High;
 1773                                         temp64_var = (temp64_var << 32) |
 1774                                            dpm_entry->PhysicalIdentifier.Low;
 1775 
 1776                                         /*
 1777                                          * If the Mapping Table's info is not
 1778                                          * the same as the DPM entry, clear the
 1779                                          * init_complete flag so that it's
 1780                                          * updated.
 1781                                          */
 1782                                         if ((mt_entry->physical_id ==
 1783                                             temp64_var) && !missing_cnt)
 1784                                                 mt_entry->init_complete = 1;
 1785                                         else
 1786                                                 mt_entry->init_complete = 0;
 1787                                 } else {
 1788                                         dpm_idx = _mapping_get_free_dpm_idx(sc);
 1789                                         mt_entry->init_complete = 0;
 1790                                 }
 1791                                 if (dpm_idx != MPR_DPM_BAD_IDX &&
 1792                                     !mt_entry->init_complete) {
 1793                                         mt_entry->dpm_entry_num = dpm_idx;
 1794                                         dpm_entry = (Mpi2DriverMap0Entry_t *)
 1795                                             ((u8 *)sc->dpm_pg0 + hdr_sz);
 1796                                         dpm_entry += dpm_idx;
 1797                                         dpm_entry->PhysicalIdentifier.Low =
 1798                                             (0xFFFFFFFF &
 1799                                             mt_entry->physical_id);
 1800                                         dpm_entry->PhysicalIdentifier.High =
 1801                                             (mt_entry->physical_id >> 32);
 1802                                         dpm_entry->DeviceIndex = (U16) map_idx;
 1803                                         dpm_entry->MappingInformation = 0;
 1804                                         dpm_entry->PhysicalBitsMapping = 0;
 1805                                         sc->dpm_entry_used[dpm_idx] = 1;
 1806                                         sc->dpm_flush_entry[dpm_idx] = 1;
 1807                                         phy_change->is_processed = 1;
 1808                                 } else if (dpm_idx == MPR_DPM_BAD_IDX) {
 1809                                         phy_change->is_processed = 1;
 1810                                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
 1811                                             "%s: failed to add the device with "
 1812                                             "handle 0x%04x to persistent table "
 1813                                             "because there is no free space "
 1814                                             "available\n", __func__,
 1815                                             phy_change->dev_handle);
 1816                                 }
 1817                         }
 1818                         mt_entry->init_complete = 1;
 1819                 }
 1820 
 1821                 phy_change->is_processed = 1;
 1822         }
 1823         if (is_removed)
 1824                 _mapping_clear_removed_entries(sc);
 1825 }
 1826 
 1827 /**
 1828  * _mapping_add_new_pcie_device -Add the new PCIe device into mapping table
 1829  * @sc: per adapter object
 1830  * @topo_change: Topology change event entry
 1831  *
 1832  * Search through the PCIe topology change event list and update map table,
 1833  * enclosure table and DPM pages for the newly added devices.
 1834  *
 1835  * Returns nothing
 1836  */
 1837 static void
 1838 _mapping_add_new_pcie_device(struct mpr_softc *sc,
 1839     struct _map_pcie_topology_change *topo_change)
 1840 {
 1841         u8 enc_idx, missing_cnt, is_removed = 0;
 1842         u16 dpm_idx;
 1843         u32 search_idx, map_idx;
 1844         u32 entry;
 1845         struct dev_mapping_table *mt_entry;
 1846         struct enc_mapping_table *et_entry;
 1847         struct _map_port_change *port_change;
 1848         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 1849         Mpi2DriverMap0Entry_t *dpm_entry;
 1850         uint64_t temp64_var;
 1851         u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
 1852         u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
 1853         u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
 1854 
 1855         for (entry = 0; entry < topo_change->num_entries; entry++) {
 1856                 port_change = &topo_change->port_details[entry];
 1857                 if (port_change->is_processed)
 1858                         continue;
 1859                 if (port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED ||
 1860                     !port_change->dev_handle) {
 1861                         port_change->is_processed = 1;
 1862                         continue;
 1863                 }
 1864                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 1865                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 1866                         enc_idx = _mapping_get_enc_idx_from_handle
 1867                             (sc, topo_change->enc_handle);
 1868                         if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
 1869                                 port_change->is_processed = 1;
 1870                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 1871                                     "failed to add the device with handle "
 1872                                     "0x%04x because the enclosure is not in "
 1873                                     "the mapping table\n", __func__,
 1874                                     port_change->dev_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                         /*
 1969                          * Get the mapping table index for this device. If it's
 1970                          * not in the mapping table yet, find a free entry if
 1971                          * one is available. If there are no free entries, look
 1972                          * for the entry that has the highest missing count. If
 1973                          * none of that works to find an entry in the mapping
 1974                          * table, there is a problem. Log a message and just
 1975                          * continue on.
 1976                          */
 1977                         map_idx = _mapping_get_mt_idx_from_id
 1978                             (sc, port_change->physical_id);
 1979                         if (map_idx == MPR_MAPTABLE_BAD_IDX) {
 1980                                 search_idx = sc->num_rsvd_entries;
 1981                                 if (topo_change->switch_dev_handle)
 1982                                         search_idx += max_num_phy_ids;
 1983                                 map_idx = _mapping_get_free_mt_idx(sc,
 1984                                     search_idx);
 1985                         }
 1986 
 1987                         /*
 1988                          * If an entry will be used that has a missing device,
 1989                          * clear its entry from  the DPM in the controller.
 1990                          */
 1991                         if (map_idx == MPR_MAPTABLE_BAD_IDX) {
 1992                                 map_idx = _mapping_get_high_missing_mt_idx(sc);
 1993                                 if (map_idx != MPR_MAPTABLE_BAD_IDX) {
 1994                                         mt_entry = &sc->mapping_table[map_idx];
 1995                                         _mapping_add_to_removal_table(sc,
 1996                                             mt_entry->dpm_entry_num);
 1997                                         is_removed = 1;
 1998                                         mt_entry->init_complete = 0;
 1999                                 }
 2000                         }
 2001                         if (map_idx != MPR_MAPTABLE_BAD_IDX) {
 2002                                 mt_entry = &sc->mapping_table[map_idx];
 2003                                 mt_entry->physical_id =
 2004                                     port_change->physical_id;
 2005                                 mt_entry->id = map_idx;
 2006                                 mt_entry->dev_handle = port_change->dev_handle;
 2007                                 mt_entry->missing_count = 0;
 2008                                 mt_entry->device_info =
 2009                                     port_change->device_info |
 2010                                     (MPR_DEV_RESERVED | MPR_MAP_IN_USE);
 2011                         } else {
 2012                                 port_change->is_processed = 1;
 2013                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 2014                                     "failed to add the device with handle "
 2015                                     "0x%04x because there is no free space "
 2016                                     "available in the mapping table\n",
 2017                                     __func__, port_change->dev_handle);
 2018                                 continue;
 2019                         }
 2020                         if (sc->is_dpm_enable) {
 2021                                 if (mt_entry->dpm_entry_num !=
 2022                                     MPR_DPM_BAD_IDX) {
 2023                                         dpm_idx = mt_entry->dpm_entry_num;
 2024                                         dpm_entry = (Mpi2DriverMap0Entry_t *)
 2025                                             ((u8 *)sc->dpm_pg0 + hdr_sz);
 2026                                         dpm_entry += dpm_idx;
 2027                                         missing_cnt = dpm_entry->
 2028                                             MappingInformation &
 2029                                             MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
 2030                                         temp64_var = dpm_entry->
 2031                                             PhysicalIdentifier.High;
 2032                                         temp64_var = (temp64_var << 32) |
 2033                                            dpm_entry->PhysicalIdentifier.Low;
 2034 
 2035                                         /*
 2036                                          * If the Mapping Table's info is not
 2037                                          * the same as the DPM entry, clear the
 2038                                          * init_complete flag so that it's
 2039                                          * updated.
 2040                                          */
 2041                                         if ((mt_entry->physical_id ==
 2042                                             temp64_var) && !missing_cnt)
 2043                                                 mt_entry->init_complete = 1;
 2044                                         else
 2045                                                 mt_entry->init_complete = 0;
 2046                                 } else {
 2047                                         dpm_idx = _mapping_get_free_dpm_idx(sc);
 2048                                         mt_entry->init_complete = 0;
 2049                                 }
 2050                                 if (dpm_idx != MPR_DPM_BAD_IDX &&
 2051                                     !mt_entry->init_complete) {
 2052                                         mt_entry->dpm_entry_num = dpm_idx;
 2053                                         dpm_entry = (Mpi2DriverMap0Entry_t *)
 2054                                             ((u8 *)sc->dpm_pg0 + hdr_sz);
 2055                                         dpm_entry += dpm_idx;
 2056                                         dpm_entry->PhysicalIdentifier.Low =
 2057                                             (0xFFFFFFFF &
 2058                                             mt_entry->physical_id);
 2059                                         dpm_entry->PhysicalIdentifier.High =
 2060                                             (mt_entry->physical_id >> 32);
 2061                                         dpm_entry->DeviceIndex = (U16) map_idx;
 2062                                         dpm_entry->MappingInformation = 0;
 2063                                         dpm_entry->PhysicalBitsMapping = 0;
 2064                                         sc->dpm_entry_used[dpm_idx] = 1;
 2065                                         sc->dpm_flush_entry[dpm_idx] = 1;
 2066                                         port_change->is_processed = 1;
 2067                                 } else if (dpm_idx == MPR_DPM_BAD_IDX) {
 2068                                         port_change->is_processed = 1;
 2069                                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
 2070                                             "%s: failed to add the device with "
 2071                                             "handle 0x%04x to persistent table "
 2072                                             "because there is no free space "
 2073                                             "available\n", __func__,
 2074                                             port_change->dev_handle);
 2075                                 }
 2076                         }
 2077                         mt_entry->init_complete = 1;
 2078                 }
 2079 
 2080                 port_change->is_processed = 1;
 2081         }
 2082         if (is_removed)
 2083                 _mapping_clear_removed_entries(sc);
 2084 }
 2085 
 2086 /**
 2087  * _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
 2088  * @sc: per adapter object
 2089  *
 2090  * Returns nothing
 2091  */
 2092 static void
 2093 _mapping_flush_dpm_pages(struct mpr_softc *sc)
 2094 {
 2095         Mpi2DriverMap0Entry_t *dpm_entry;
 2096         Mpi2ConfigReply_t mpi_reply;
 2097         Mpi2DriverMappingPage0_t config_page;
 2098         u16 entry_num;
 2099 
 2100         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
 2101                 if (!sc->dpm_flush_entry[entry_num])
 2102                         continue;
 2103                 memset(&config_page, 0, sizeof(Mpi2DriverMappingPage0_t));
 2104                 memcpy(&config_page.Header, (u8 *)sc->dpm_pg0,
 2105                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
 2106                 dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
 2107                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
 2108                 dpm_entry += entry_num;
 2109                 dpm_entry->MappingInformation = htole16(dpm_entry->
 2110                     MappingInformation);
 2111                 dpm_entry->DeviceIndex = htole16(dpm_entry->DeviceIndex);
 2112                 dpm_entry->PhysicalBitsMapping = htole32(dpm_entry->
 2113                     PhysicalBitsMapping);
 2114                 memcpy(&config_page.Entry, (u8 *)dpm_entry,
 2115                     sizeof(Mpi2DriverMap0Entry_t));
 2116                 /* TODO-How to handle failed writes? */
 2117                 mpr_dprint(sc, MPR_MAPPING, "%s: Flushing DPM entry %d.\n",
 2118                     __func__, entry_num);
 2119                 if (mpr_config_set_dpm_pg0(sc, &mpi_reply, &config_page,
 2120                     entry_num)) {
 2121                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Flush of "
 2122                             "DPM entry %d for device failed\n", __func__,
 2123                             entry_num);
 2124                 } else
 2125                         sc->dpm_flush_entry[entry_num] = 0;
 2126                 dpm_entry->MappingInformation = le16toh(dpm_entry->
 2127                     MappingInformation);
 2128                 dpm_entry->DeviceIndex = le16toh(dpm_entry->DeviceIndex);
 2129                 dpm_entry->PhysicalBitsMapping = le32toh(dpm_entry->
 2130                     PhysicalBitsMapping);
 2131         }
 2132 }
 2133 
 2134 /**
 2135  * _mapping_allocate_memory- allocates the memory required for mapping tables
 2136  * @sc: per adapter object
 2137  *
 2138  * Allocates the memory for all the tables required for host mapping
 2139  *
 2140  * Return 0 on success or non-zero on failure.
 2141  */
 2142 int
 2143 mpr_mapping_allocate_memory(struct mpr_softc *sc)
 2144 {
 2145         uint32_t dpm_pg0_sz;
 2146 
 2147         sc->mapping_table = malloc((sizeof(struct dev_mapping_table) *
 2148             sc->max_devices), M_MPR, M_ZERO|M_NOWAIT);
 2149         if (!sc->mapping_table)
 2150                 goto free_resources;
 2151 
 2152         sc->removal_table = malloc((sizeof(struct map_removal_table) *
 2153             sc->max_devices), M_MPR, M_ZERO|M_NOWAIT);
 2154         if (!sc->removal_table)
 2155                 goto free_resources;
 2156 
 2157         sc->enclosure_table = malloc((sizeof(struct enc_mapping_table) *
 2158             sc->max_enclosures), M_MPR, M_ZERO|M_NOWAIT);
 2159         if (!sc->enclosure_table)
 2160                 goto free_resources;
 2161 
 2162         sc->dpm_entry_used = malloc((sizeof(u8) * sc->max_dpm_entries),
 2163             M_MPR, M_ZERO|M_NOWAIT);
 2164         if (!sc->dpm_entry_used)
 2165                 goto free_resources;
 2166 
 2167         sc->dpm_flush_entry = malloc((sizeof(u8) * sc->max_dpm_entries),
 2168             M_MPR, M_ZERO|M_NOWAIT);
 2169         if (!sc->dpm_flush_entry)
 2170                 goto free_resources;
 2171 
 2172         dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
 2173             (sc->max_dpm_entries * sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
 2174 
 2175         sc->dpm_pg0 = malloc(dpm_pg0_sz, M_MPR, M_ZERO|M_NOWAIT);
 2176         if (!sc->dpm_pg0) {
 2177                 printf("%s: memory alloc failed for dpm page; disabling dpm\n",
 2178                     __func__);
 2179                 sc->is_dpm_enable = 0;
 2180         }
 2181 
 2182         return 0;
 2183 
 2184 free_resources:
 2185         free(sc->mapping_table, M_MPR);
 2186         free(sc->removal_table, M_MPR);
 2187         free(sc->enclosure_table, M_MPR);
 2188         free(sc->dpm_entry_used, M_MPR);
 2189         free(sc->dpm_flush_entry, M_MPR);
 2190         free(sc->dpm_pg0, M_MPR);
 2191         printf("%s: device initialization failed due to failure in mapping "
 2192             "table memory allocation\n", __func__);
 2193         return -1;
 2194 }
 2195 
 2196 /**
 2197  * mpr_mapping_free_memory- frees the memory allocated for mapping tables
 2198  * @sc: per adapter object
 2199  *
 2200  * Returns nothing.
 2201  */
 2202 void
 2203 mpr_mapping_free_memory(struct mpr_softc *sc)
 2204 {
 2205         free(sc->mapping_table, M_MPR);
 2206         free(sc->removal_table, M_MPR);
 2207         free(sc->enclosure_table, M_MPR);
 2208         free(sc->dpm_entry_used, M_MPR);
 2209         free(sc->dpm_flush_entry, M_MPR);
 2210         free(sc->dpm_pg0, M_MPR);
 2211 }
 2212 
 2213 static bool
 2214 _mapping_process_dpm_pg0(struct mpr_softc *sc)
 2215 {
 2216         u8 missing_cnt, enc_idx;
 2217         u16 slot_id, entry_num, num_slots;
 2218         u32 map_idx, dev_idx, start_idx, end_idx;
 2219         struct dev_mapping_table *mt_entry;
 2220         Mpi2DriverMap0Entry_t *dpm_entry;
 2221         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 2222         u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
 2223         struct enc_mapping_table *et_entry;
 2224         u64 physical_id;
 2225         u32 phy_bits = 0;
 2226 
 2227         /*
 2228          * start_idx and end_idx are only used for IR.
 2229          */
 2230         if (sc->ir_firmware)
 2231                 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
 2232 
 2233         /*
 2234          * Look through all of the DPM entries that were read from the
 2235          * controller and copy them over to the driver's internal table if they
 2236          * have a non-zero ID. At this point, any ID with a value of 0 would be
 2237          * invalid, so don't copy it.
 2238          */
 2239         mpr_dprint(sc, MPR_MAPPING, "%s: Start copy of %d DPM entries into the "
 2240             "mapping table.\n", __func__, sc->max_dpm_entries);
 2241         dpm_entry = (Mpi2DriverMap0Entry_t *) ((uint8_t *) sc->dpm_pg0 +
 2242             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
 2243         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++, 
 2244             dpm_entry++) {
 2245                 physical_id = dpm_entry->PhysicalIdentifier.High;
 2246                 physical_id = (physical_id << 32) | 
 2247                     dpm_entry->PhysicalIdentifier.Low;
 2248                 if (!physical_id) {
 2249                         sc->dpm_entry_used[entry_num] = 0;
 2250                         continue;
 2251                 }
 2252                 sc->dpm_entry_used[entry_num] = 1;
 2253                 dpm_entry->MappingInformation = le16toh(dpm_entry->
 2254                     MappingInformation);
 2255                 missing_cnt = dpm_entry->MappingInformation &
 2256                     MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
 2257                 dev_idx = le16toh(dpm_entry->DeviceIndex);
 2258                 phy_bits = le32toh(dpm_entry->PhysicalBitsMapping);
 2259 
 2260                 /*
 2261                  * Volumes are at special locations in the mapping table so
 2262                  * account for that. Volume mapping table entries do not depend
 2263                  * on the type of mapping, so continue the loop after adding
 2264                  * volumes to the mapping table.
 2265                  */
 2266                 if (sc->ir_firmware && (dev_idx >= start_idx) &&
 2267                     (dev_idx <= end_idx)) {
 2268                         mt_entry = &sc->mapping_table[dev_idx];
 2269                         mt_entry->physical_id =
 2270                             dpm_entry->PhysicalIdentifier.High;
 2271                         mt_entry->physical_id = (mt_entry->physical_id << 32) |
 2272                             dpm_entry->PhysicalIdentifier.Low;
 2273                         mt_entry->id = dev_idx;
 2274                         mt_entry->missing_count = missing_cnt;
 2275                         mt_entry->dpm_entry_num = entry_num;
 2276                         mt_entry->device_info = MPR_DEV_RESERVED;
 2277                         continue;
 2278                 }
 2279                 if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 2280                     MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 2281 
 2282                         /*
 2283                          * The dev_idx for an enclosure is the start index. If
 2284                          * the start index is within the controller's default
 2285                          * enclosure area, set the number of slots for this
 2286                          * enclosure to the max allowed. Otherwise, it should be
 2287                          * a normal enclosure and the number of slots is in the
 2288                          * DPM entry's Mapping Information.
 2289                          */
 2290                         if (dev_idx < (sc->num_rsvd_entries +
 2291                             max_num_phy_ids)) {
 2292                                 slot_id = 0;
 2293                                 if (ioc_pg8_flags &
 2294                                     MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1)
 2295                                         slot_id = 1;
 2296                                 num_slots = max_num_phy_ids;
 2297                         } else {
 2298                                 slot_id = 0;
 2299                                 num_slots = dpm_entry->MappingInformation &
 2300                                     MPI2_DRVMAP0_MAPINFO_SLOT_MASK;
 2301                                 num_slots >>= MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
 2302                         }
 2303                         enc_idx = sc->num_enc_table_entries;
 2304                         if (enc_idx >= sc->max_enclosures) {
 2305                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 2306                                     "Number of enclosure entries in DPM exceed "
 2307                                     "the max allowed of %d.\n", __func__,
 2308                                     sc->max_enclosures);
 2309                                 break;
 2310                         }
 2311                         sc->num_enc_table_entries++;
 2312                         et_entry = &sc->enclosure_table[enc_idx];
 2313                         physical_id = dpm_entry->PhysicalIdentifier.High;
 2314                         et_entry->enclosure_id = (physical_id << 32) |
 2315                             dpm_entry->PhysicalIdentifier.Low;
 2316                         et_entry->start_index = dev_idx;
 2317                         et_entry->dpm_entry_num = entry_num;
 2318                         et_entry->num_slots = num_slots;
 2319                         et_entry->start_slot = slot_id;
 2320                         et_entry->missing_count = missing_cnt;
 2321                         et_entry->phy_bits = phy_bits;
 2322 
 2323                         /*
 2324                          * Initialize all entries for this enclosure in the
 2325                          * mapping table and mark them as reserved. The actual
 2326                          * devices have not been processed yet but when they are
 2327                          * they will use these entries. If an entry is found
 2328                          * that already has a valid DPM index, the mapping table
 2329                          * is corrupt. This can happen if the mapping type is
 2330                          * changed without clearing all of the DPM entries in
 2331                          * the controller.
 2332                          */
 2333                         mt_entry = &sc->mapping_table[dev_idx];
 2334                         for (map_idx = dev_idx; map_idx < (dev_idx + num_slots);
 2335                             map_idx++, mt_entry++) {
 2336                                 if (mt_entry->dpm_entry_num !=
 2337                                     MPR_DPM_BAD_IDX) {
 2338                                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
 2339                                             "%s: Conflict in mapping table for "
 2340                                             " enclosure %d\n", __func__,
 2341                                             enc_idx);
 2342                                         goto fail;
 2343                                 }
 2344                                 physical_id =
 2345                                     dpm_entry->PhysicalIdentifier.High;
 2346                                 mt_entry->physical_id = (physical_id << 32) |
 2347                                     dpm_entry->PhysicalIdentifier.Low;
 2348                                 mt_entry->phy_bits = phy_bits;
 2349                                 mt_entry->id = dev_idx;
 2350                                 mt_entry->dpm_entry_num = entry_num;
 2351                                 mt_entry->missing_count = missing_cnt;
 2352                                 mt_entry->device_info = MPR_DEV_RESERVED;
 2353                         }
 2354                 } else if ((ioc_pg8_flags &
 2355                     MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 2356                     MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
 2357 
 2358                         /*
 2359                          * Device mapping, so simply copy the DPM entries to the
 2360                          * mapping table, but check for a corrupt mapping table
 2361                          * (as described above in Enc/Slot mapping).
 2362                          */
 2363                         map_idx = dev_idx;
 2364                         mt_entry = &sc->mapping_table[map_idx];
 2365                         if (mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
 2366                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 2367                                     "Conflict in mapping table for device %d\n",
 2368                                     __func__, map_idx);
 2369                                 goto fail;
 2370                         }
 2371                         physical_id = dpm_entry->PhysicalIdentifier.High;
 2372                         mt_entry->physical_id = (physical_id << 32) |
 2373                             dpm_entry->PhysicalIdentifier.Low;
 2374                         mt_entry->phy_bits = phy_bits;
 2375                         mt_entry->id = dev_idx;
 2376                         mt_entry->missing_count = missing_cnt;
 2377                         mt_entry->dpm_entry_num = entry_num;
 2378                         mt_entry->device_info = MPR_DEV_RESERVED;
 2379                 }
 2380         } /*close the loop for DPM table */
 2381         return (true);
 2382 
 2383 fail:
 2384         for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) {
 2385                 sc->dpm_entry_used[entry_num] = 0;
 2386                 /*
 2387                  * for IR firmware, it may be necessary to wipe out
 2388                  * sc->mapping_table volumes tooi
 2389                  */
 2390         }
 2391         for (enc_idx = 0; enc_idx < sc->num_enc_table_entries; enc_idx++)
 2392                 _mapping_clear_enc_entry(sc->enclosure_table + enc_idx);
 2393         sc->num_enc_table_entries = 0;
 2394         return (false);
 2395 }
 2396 
 2397 /*
 2398  * mpr_mapping_check_devices - start of the day check for device availabilty
 2399  * @sc: per adapter object
 2400  *
 2401  * Returns nothing.
 2402  */
 2403 void
 2404 mpr_mapping_check_devices(void *data)
 2405 {
 2406         u32 i;
 2407         struct dev_mapping_table *mt_entry;
 2408         struct mpr_softc *sc = (struct mpr_softc *)data;
 2409         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 2410         struct enc_mapping_table *et_entry;
 2411         u32 start_idx = 0, end_idx = 0;
 2412         u8 stop_device_checks = 0;
 2413 
 2414         MPR_FUNCTRACE(sc);
 2415 
 2416         /*
 2417          * Clear this flag so that this function is never called again except
 2418          * within this function if the check needs to be done again. The
 2419          * purpose is to check for missing devices that are currently in the
 2420          * mapping table so do this only at driver init after discovery.
 2421          */
 2422         sc->track_mapping_events = 0;
 2423 
 2424         /*
 2425          * callout synchronization
 2426          * This is used to prevent race conditions for the callout. 
 2427          */
 2428         mpr_dprint(sc, MPR_MAPPING, "%s: Start check for missing devices.\n",
 2429             __func__);
 2430         mtx_assert(&sc->mpr_mtx, MA_OWNED);
 2431         if ((callout_pending(&sc->device_check_callout)) ||
 2432             (!callout_active(&sc->device_check_callout))) {
 2433                 mpr_dprint(sc, MPR_MAPPING, "%s: Device Check Callout is "
 2434                     "already pending or not active.\n", __func__);
 2435                 return;
 2436         }
 2437         callout_deactivate(&sc->device_check_callout);
 2438 
 2439         /*
 2440          * Use callout to check if any devices in the mapping table have been
 2441          * processed yet. If ALL devices are marked as not init_complete, no
 2442          * devices have been processed and mapped. Until devices are mapped
 2443          * there's no reason to mark them as missing. Continue resetting this
 2444          * callout until devices have been mapped.
 2445          */
 2446         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 2447             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 2448                 et_entry = sc->enclosure_table;
 2449                 for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
 2450                         if (et_entry->init_complete) {
 2451                                 stop_device_checks = 1;
 2452                                 break;
 2453                         }
 2454                 }
 2455         } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 2456             MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
 2457                 mt_entry = sc->mapping_table;
 2458                 for (i = 0; i < sc->max_devices; i++, mt_entry++) {
 2459                         if (mt_entry->init_complete) {
 2460                                 stop_device_checks = 1;
 2461                                 break;
 2462                         }
 2463                 }
 2464         }
 2465 
 2466         /*
 2467          * Setup another callout check after a delay. Keep doing this until
 2468          * devices are mapped.
 2469          */
 2470         if (!stop_device_checks) {
 2471                 mpr_dprint(sc, MPR_MAPPING, "%s: No devices have been mapped. "
 2472                     "Reset callout to check again after a %d second delay.\n",
 2473                     __func__, MPR_MISSING_CHECK_DELAY);
 2474                 callout_reset(&sc->device_check_callout,
 2475                     MPR_MISSING_CHECK_DELAY * hz, mpr_mapping_check_devices,
 2476                     sc);
 2477                 return;
 2478         }
 2479         mpr_dprint(sc, MPR_MAPPING, "%s: Device check complete.\n", __func__);
 2480 
 2481         /*
 2482          * Depending on the mapping type, check if devices have been processed
 2483          * and update their missing counts if not processed.
 2484          */
 2485         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 2486             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
 2487                 et_entry = sc->enclosure_table;
 2488                 for (i = 0; i < sc->num_enc_table_entries; i++, et_entry++) {
 2489                         if (!et_entry->init_complete) {
 2490                                 if (et_entry->missing_count <
 2491                                     MPR_MAX_MISSING_COUNT) {
 2492                                         mpr_dprint(sc, MPR_MAPPING, "%s: "
 2493                                             "Enclosure %d is missing from the "
 2494                                             "topology. Update its missing "
 2495                                             "count.\n", __func__, i);
 2496                                         et_entry->missing_count++;
 2497                                         if (et_entry->dpm_entry_num !=
 2498                                             MPR_DPM_BAD_IDX) {
 2499                                                 _mapping_commit_enc_entry(sc,
 2500                                                     et_entry);
 2501                                         }
 2502                                 }
 2503                                 et_entry->init_complete = 1;
 2504                         }
 2505                 }
 2506                 if (!sc->ir_firmware)
 2507                         return;
 2508                 _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
 2509                 mt_entry = &sc->mapping_table[start_idx];
 2510         } else if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
 2511             MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
 2512                 start_idx = 0;
 2513                 end_idx = sc->max_devices - 1;
 2514                 mt_entry = sc->mapping_table;
 2515         }
 2516 
 2517         /*
 2518          * The start and end indices have been set above according to the
 2519          * mapping type. Go through these mappings and update any entries that
 2520          * do not have the init_complete flag set, which means they are missing.
 2521          */
 2522         if (end_idx == 0)
 2523                 return;
 2524         for (i = start_idx; i < (end_idx + 1); i++, mt_entry++) {
 2525                 if (mt_entry->device_info & MPR_DEV_RESERVED
 2526                     && !mt_entry->physical_id)
 2527                         mt_entry->init_complete = 1;
 2528                 else if (mt_entry->device_info & MPR_DEV_RESERVED) {
 2529                         if (!mt_entry->init_complete) {
 2530                                 mpr_dprint(sc, MPR_MAPPING, "%s: Device in "
 2531                                     "mapping table at index %d is missing from "
 2532                                     "topology. Update its missing count.\n",
 2533                                     __func__, i);
 2534                                 if (mt_entry->missing_count <
 2535                                     MPR_MAX_MISSING_COUNT) {
 2536                                         mt_entry->missing_count++;
 2537                                         if (mt_entry->dpm_entry_num !=
 2538                                             MPR_DPM_BAD_IDX) {
 2539                                                 _mapping_commit_map_entry(sc,
 2540                                                     mt_entry);
 2541                                         }
 2542                                 }
 2543                                 mt_entry->init_complete = 1;
 2544                         }
 2545                 }
 2546         }
 2547 }
 2548 
 2549 /**
 2550  * mpr_mapping_initialize - initialize mapping tables
 2551  * @sc: per adapter object
 2552  *
 2553  * Read controller persitant mapping tables into internal data area.
 2554  *
 2555  * Return 0 for success or non-zero for failure.
 2556  */
 2557 int
 2558 mpr_mapping_initialize(struct mpr_softc *sc)
 2559 {
 2560         uint16_t volume_mapping_flags, dpm_pg0_sz;
 2561         uint32_t i;
 2562         Mpi2ConfigReply_t mpi_reply;
 2563         int error;
 2564         uint8_t retry_count;
 2565         uint16_t ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 2566 
 2567         /* The additional 1 accounts for the virtual enclosure
 2568          * created for the controller
 2569          */
 2570         sc->max_enclosures = sc->facts->MaxEnclosures + 1;
 2571         sc->max_expanders = sc->facts->MaxSasExpanders;
 2572         sc->max_volumes = sc->facts->MaxVolumes;
 2573         sc->max_devices = sc->facts->MaxTargets + sc->max_volumes;
 2574         sc->pending_map_events = 0;
 2575         sc->num_enc_table_entries = 0;
 2576         sc->num_rsvd_entries = 0;
 2577         sc->max_dpm_entries = sc->ioc_pg8.MaxPersistentEntries;
 2578         sc->is_dpm_enable = (sc->max_dpm_entries) ? 1 : 0;
 2579         sc->track_mapping_events = 0;
 2580 
 2581         mpr_dprint(sc, MPR_MAPPING, "%s: Mapping table has a max of %d entries "
 2582             "and DPM has a max of %d entries.\n", __func__, sc->max_devices,
 2583             sc->max_dpm_entries);
 2584         
 2585         if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING)
 2586                 sc->is_dpm_enable = 0;
 2587 
 2588         if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
 2589                 sc->num_rsvd_entries = 1;
 2590 
 2591         volume_mapping_flags = sc->ioc_pg8.IRVolumeMappingFlags &
 2592             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
 2593         if (sc->ir_firmware && (volume_mapping_flags ==
 2594             MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING))
 2595                 sc->num_rsvd_entries += sc->max_volumes;
 2596 
 2597         error = mpr_mapping_allocate_memory(sc);
 2598         if (error)
 2599                 return (error);
 2600 
 2601         for (i = 0; i < sc->max_devices; i++)
 2602                 _mapping_clear_map_entry(sc->mapping_table + i);
 2603 
 2604         for (i = 0; i < sc->max_enclosures; i++)
 2605                 _mapping_clear_enc_entry(sc->enclosure_table + i);
 2606 
 2607         for (i = 0; i < sc->max_devices; i++) {
 2608                 sc->removal_table[i].dev_handle = 0;
 2609                 sc->removal_table[i].dpm_entry_num = MPR_DPM_BAD_IDX;
 2610         }
 2611 
 2612         memset(sc->dpm_entry_used, 0, sc->max_dpm_entries);
 2613         memset(sc->dpm_flush_entry, 0, sc->max_dpm_entries);
 2614 
 2615         if (sc->is_dpm_enable) {
 2616                 dpm_pg0_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER) +
 2617                     (sc->max_dpm_entries *
 2618                      sizeof(MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY));
 2619                 retry_count = 0;
 2620 
 2621 retry_read_dpm:
 2622                 if (mpr_config_get_dpm_pg0(sc, &mpi_reply, sc->dpm_pg0,
 2623                     dpm_pg0_sz)) {
 2624                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: DPM page "
 2625                             "read failed.\n", __func__);
 2626                         if (retry_count < 3) {
 2627                                 retry_count++;
 2628                                 goto retry_read_dpm;
 2629                         }
 2630                         sc->is_dpm_enable = 0;
 2631                 }
 2632         }
 2633 
 2634         if (sc->is_dpm_enable) {
 2635                 if (!_mapping_process_dpm_pg0(sc))
 2636                         sc->is_dpm_enable = 0;
 2637         }
 2638         if (! sc->is_dpm_enable) {
 2639                 mpr_dprint(sc, MPR_MAPPING, "%s: DPM processing is disabled. "
 2640                     "Device mappings will not persist across reboots or "
 2641                     "resets.\n", __func__);
 2642         }
 2643 
 2644         sc->track_mapping_events = 1;
 2645         return 0;
 2646 }
 2647 
 2648 /**
 2649  * mpr_mapping_exit - clear mapping table and associated memory
 2650  * @sc: per adapter object
 2651  *
 2652  * Returns nothing.
 2653  */
 2654 void
 2655 mpr_mapping_exit(struct mpr_softc *sc)
 2656 {
 2657         _mapping_flush_dpm_pages(sc);
 2658         mpr_mapping_free_memory(sc);
 2659 }
 2660 
 2661 /**
 2662  * mpr_mapping_get_tid - return the target id for sas device and handle
 2663  * @sc: per adapter object
 2664  * @sas_address: sas address of the device
 2665  * @handle: device handle
 2666  *
 2667  * Returns valid target ID on success or BAD_ID.
 2668  */
 2669 unsigned int
 2670 mpr_mapping_get_tid(struct mpr_softc *sc, uint64_t sas_address, u16 handle)
 2671 {
 2672         u32 map_idx;
 2673         struct dev_mapping_table *mt_entry;
 2674 
 2675         for (map_idx = 0; map_idx < sc->max_devices; map_idx++) {
 2676                 mt_entry = &sc->mapping_table[map_idx];
 2677                 if (mt_entry->dev_handle == handle && mt_entry->physical_id ==
 2678                     sas_address)
 2679                         return mt_entry->id;
 2680         }
 2681 
 2682         return MPR_MAP_BAD_ID;
 2683 }
 2684 
 2685 /**
 2686  * mpr_mapping_get_tid_from_handle - find a target id in mapping table using
 2687  * only the dev handle.  This is just a wrapper function for the local function
 2688  * _mapping_get_mt_idx_from_handle.
 2689  * @sc: per adapter object
 2690  * @handle: device handle
 2691  *
 2692  * Returns valid target ID on success or BAD_ID.
 2693  */
 2694 unsigned int
 2695 mpr_mapping_get_tid_from_handle(struct mpr_softc *sc, u16 handle)
 2696 {
 2697         return (_mapping_get_mt_idx_from_handle(sc, handle));
 2698 }
 2699 
 2700 /**
 2701  * mpr_mapping_get_raid_tid - return the target id for raid device
 2702  * @sc: per adapter object
 2703  * @wwid: world wide identifier for raid volume
 2704  * @volHandle: volume device handle
 2705  *
 2706  * Returns valid target ID on success or BAD_ID.
 2707  */
 2708 unsigned int
 2709 mpr_mapping_get_raid_tid(struct mpr_softc *sc, u64 wwid, u16 volHandle)
 2710 {
 2711         u32 start_idx, end_idx, map_idx;
 2712         struct dev_mapping_table *mt_entry;
 2713 
 2714         _mapping_get_ir_maprange(sc, &start_idx, &end_idx);
 2715         mt_entry = &sc->mapping_table[start_idx];
 2716         for (map_idx  = start_idx; map_idx <= end_idx; map_idx++, mt_entry++) {
 2717                 if (mt_entry->dev_handle == volHandle &&
 2718                     mt_entry->physical_id == wwid)
 2719                         return mt_entry->id;
 2720         }
 2721 
 2722         return MPR_MAP_BAD_ID;
 2723 }
 2724 
 2725 /**
 2726  * mpr_mapping_get_raid_tid_from_handle - find raid device in mapping table
 2727  * using only the volume dev handle.  This is just a wrapper function for the
 2728  * local function _mapping_get_ir_mt_idx_from_handle.
 2729  * @sc: per adapter object
 2730  * @volHandle: volume device handle
 2731  *
 2732  * Returns valid target ID on success or BAD_ID.
 2733  */
 2734 unsigned int
 2735 mpr_mapping_get_raid_tid_from_handle(struct mpr_softc *sc, u16 volHandle)
 2736 {
 2737         return (_mapping_get_ir_mt_idx_from_handle(sc, volHandle));
 2738 }
 2739 
 2740 /**
 2741  * mpr_mapping_enclosure_dev_status_change_event - handle enclosure events
 2742  * @sc: per adapter object
 2743  * @event_data: event data payload
 2744  *
 2745  * Return nothing.
 2746  */
 2747 void
 2748 mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *sc,
 2749     Mpi2EventDataSasEnclDevStatusChange_t *event_data)
 2750 {
 2751         u8 enc_idx, missing_count;
 2752         struct enc_mapping_table *et_entry;
 2753         Mpi2DriverMap0Entry_t *dpm_entry;
 2754         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 2755         u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
 2756         u8 update_phy_bits = 0;
 2757         u32 saved_phy_bits;
 2758         uint64_t temp64_var;
 2759 
 2760         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) !=
 2761             MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING)
 2762                 goto out;
 2763 
 2764         dpm_entry = (Mpi2DriverMap0Entry_t *)((u8 *)sc->dpm_pg0 +
 2765             sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
 2766 
 2767         if (event_data->ReasonCode == MPI2_EVENT_SAS_ENCL_RC_ADDED) {
 2768                 if (!event_data->NumSlots) {
 2769                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Enclosure "
 2770                             "with handle = 0x%x reported 0 slots.\n", __func__,
 2771                             le16toh(event_data->EnclosureHandle));
 2772                         goto out;
 2773                 }
 2774                 temp64_var = event_data->EnclosureLogicalID.High;
 2775                 temp64_var = (temp64_var << 32) |
 2776                     event_data->EnclosureLogicalID.Low;
 2777                 enc_idx = _mapping_get_enc_idx_from_id(sc, temp64_var,
 2778                     event_data->PhyBits);
 2779 
 2780                 /*
 2781                  * If the Added enclosure is already in the Enclosure Table,
 2782                  * make sure that all the the enclosure info is up to date. If
 2783                  * the enclosure was missing and has just been added back, or if
 2784                  * the enclosure's Phy Bits have changed, clear the missing
 2785                  * count and update the Phy Bits in the mapping table and in the
 2786                  * DPM, if it's being used.
 2787                  */
 2788                 if (enc_idx != MPR_ENCTABLE_BAD_IDX) {
 2789                         et_entry = &sc->enclosure_table[enc_idx];
 2790                         if (et_entry->init_complete &&
 2791                             !et_entry->missing_count) {
 2792                                 mpr_dprint(sc, MPR_MAPPING, "%s: Enclosure %d "
 2793                                     "is already present with handle = 0x%x\n",
 2794                                     __func__, enc_idx, et_entry->enc_handle);
 2795                                 goto out;
 2796                         }
 2797                         et_entry->enc_handle = le16toh(event_data->
 2798                             EnclosureHandle);
 2799                         et_entry->start_slot = le16toh(event_data->StartSlot);
 2800                         saved_phy_bits = et_entry->phy_bits;
 2801                         et_entry->phy_bits |= le32toh(event_data->PhyBits);
 2802                         if (saved_phy_bits != et_entry->phy_bits)
 2803                                 update_phy_bits = 1;
 2804                         if (et_entry->missing_count || update_phy_bits) {
 2805                                 et_entry->missing_count = 0;
 2806                                 if (sc->is_dpm_enable &&
 2807                                     et_entry->dpm_entry_num !=
 2808                                     MPR_DPM_BAD_IDX) {
 2809                                         dpm_entry += et_entry->dpm_entry_num;
 2810                                         missing_count =
 2811                                             (u8)(dpm_entry->MappingInformation &
 2812                                             MPI2_DRVMAP0_MAPINFO_MISSING_MASK);
 2813                                         if (missing_count || update_phy_bits) {
 2814                                                 dpm_entry->MappingInformation
 2815                                                     = et_entry->num_slots;
 2816                                                 dpm_entry->MappingInformation
 2817                                                     <<= map_shift;
 2818                                                 dpm_entry->PhysicalBitsMapping
 2819                                                     = et_entry->phy_bits;
 2820                                                 sc->dpm_flush_entry[et_entry->
 2821                                                     dpm_entry_num] = 1;
 2822                                         }
 2823                                 }
 2824                         }
 2825                 } else {
 2826                         /*
 2827                          * This is a new enclosure that is being added.
 2828                          * Initialize the Enclosure Table entry. It will be
 2829                          * finalized when a device is added for the enclosure
 2830                          * and the enclosure has enough space in the Mapping
 2831                          * Table to map its devices.
 2832                          */
 2833                         enc_idx = sc->num_enc_table_entries;
 2834                         if (enc_idx >= sc->max_enclosures) {
 2835                                 mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: "
 2836                                     "Enclosure cannot be added to mapping "
 2837                                     "table because it's full.\n", __func__);
 2838                                 goto out;
 2839                         }
 2840                         sc->num_enc_table_entries++;
 2841                         et_entry = &sc->enclosure_table[enc_idx];
 2842                         et_entry->enc_handle = le16toh(event_data->
 2843                             EnclosureHandle);
 2844                         et_entry->enclosure_id = le64toh(event_data->
 2845                             EnclosureLogicalID.High);
 2846                         et_entry->enclosure_id =
 2847                             ((et_entry->enclosure_id << 32) |
 2848                             le64toh(event_data->EnclosureLogicalID.Low));
 2849                         et_entry->start_index = MPR_MAPTABLE_BAD_IDX;
 2850                         et_entry->dpm_entry_num = MPR_DPM_BAD_IDX;
 2851                         et_entry->num_slots = le16toh(event_data->NumSlots);
 2852                         et_entry->start_slot = le16toh(event_data->StartSlot);
 2853                         et_entry->phy_bits = le32toh(event_data->PhyBits);
 2854                 }
 2855                 et_entry->init_complete = 1;
 2856         } else if (event_data->ReasonCode ==
 2857             MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING) {
 2858                 /*
 2859                  * An enclosure was removed. Update its missing count and then
 2860                  * update the DPM entry with the new missing count for the
 2861                  * enclosure.
 2862                  */
 2863                 enc_idx = _mapping_get_enc_idx_from_handle(sc,
 2864                     le16toh(event_data->EnclosureHandle));
 2865                 if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
 2866                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Cannot "
 2867                             "unmap enclosure %d because it has already been "
 2868                             "deleted.\n", __func__, enc_idx);
 2869                         goto out;
 2870                 }
 2871                 et_entry = &sc->enclosure_table[enc_idx];
 2872                 if (et_entry->missing_count < MPR_MAX_MISSING_COUNT)
 2873                         et_entry->missing_count++;
 2874                 if (sc->is_dpm_enable &&
 2875                     et_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
 2876                         dpm_entry += et_entry->dpm_entry_num;
 2877                         dpm_entry->MappingInformation = et_entry->num_slots;
 2878                         dpm_entry->MappingInformation <<= map_shift;
 2879                         dpm_entry->MappingInformation |=
 2880                             et_entry->missing_count;
 2881                         sc->dpm_flush_entry[et_entry->dpm_entry_num] = 1;
 2882                 }
 2883                 et_entry->init_complete = 1;
 2884         }
 2885 
 2886 out:
 2887         _mapping_flush_dpm_pages(sc);
 2888         if (sc->pending_map_events)
 2889                 sc->pending_map_events--;
 2890 }
 2891 
 2892 /**
 2893  * mpr_mapping_topology_change_event - handle topology change events
 2894  * @sc: per adapter object
 2895  * @event_data: event data payload
 2896  *
 2897  * Returns nothing.
 2898  */
 2899 void
 2900 mpr_mapping_topology_change_event(struct mpr_softc *sc,
 2901     Mpi2EventDataSasTopologyChangeList_t *event_data)
 2902 {
 2903         struct _map_topology_change topo_change;
 2904         struct _map_phy_change *phy_change;
 2905         Mpi2EventSasTopoPhyEntry_t *event_phy_change;
 2906         u8 i, num_entries;
 2907 
 2908         topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
 2909         topo_change.exp_handle = le16toh(event_data->ExpanderDevHandle);
 2910         num_entries = event_data->NumEntries;
 2911         topo_change.num_entries = num_entries;
 2912         topo_change.start_phy_num = event_data->StartPhyNum;
 2913         topo_change.num_phys = event_data->NumPhys;
 2914         topo_change.exp_status = event_data->ExpStatus;
 2915         event_phy_change = event_data->PHY;
 2916         topo_change.phy_details = NULL;
 2917 
 2918         if (!num_entries)
 2919                 goto out;
 2920         phy_change = malloc(sizeof(struct _map_phy_change) * num_entries,
 2921             M_MPR, M_NOWAIT|M_ZERO);
 2922         topo_change.phy_details = phy_change;
 2923         if (!phy_change)
 2924                 goto out;
 2925         for (i = 0; i < num_entries; i++, event_phy_change++, phy_change++) {
 2926                 phy_change->dev_handle = le16toh(event_phy_change->
 2927                     AttachedDevHandle);
 2928                 phy_change->reason = event_phy_change->PhyStatus &
 2929                     MPI2_EVENT_SAS_TOPO_RC_MASK;
 2930         }
 2931         _mapping_update_missing_count(sc, &topo_change);
 2932         _mapping_get_dev_info(sc, &topo_change);
 2933         _mapping_clear_removed_entries(sc);
 2934         _mapping_add_new_device(sc, &topo_change);
 2935 
 2936 out:
 2937         free(topo_change.phy_details, M_MPR);
 2938         _mapping_flush_dpm_pages(sc);
 2939         if (sc->pending_map_events)
 2940                 sc->pending_map_events--;
 2941 }
 2942 
 2943 /**
 2944  * mpr_mapping_pcie_topology_change_event - handle PCIe topology change events
 2945  * @sc: per adapter object
 2946  * @event_data: event data payload
 2947  *
 2948  * Returns nothing.
 2949  */
 2950 void
 2951 mpr_mapping_pcie_topology_change_event(struct mpr_softc *sc,
 2952     Mpi26EventDataPCIeTopologyChangeList_t *event_data)
 2953 {
 2954         struct _map_pcie_topology_change topo_change;
 2955         struct _map_port_change *port_change;
 2956         Mpi26EventPCIeTopoPortEntry_t *event_port_change;
 2957         u8 i, num_entries;
 2958 
 2959         topo_change.switch_dev_handle = le16toh(event_data->SwitchDevHandle);
 2960         topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
 2961         num_entries = event_data->NumEntries;
 2962         topo_change.num_entries = num_entries;
 2963         topo_change.start_port_num = event_data->StartPortNum;
 2964         topo_change.num_ports = event_data->NumPorts;
 2965         topo_change.switch_status = event_data->SwitchStatus;
 2966         event_port_change = event_data->PortEntry;
 2967         topo_change.port_details = NULL;
 2968 
 2969         if (!num_entries)
 2970                 goto out;
 2971         port_change = malloc(sizeof(struct _map_port_change) * num_entries,
 2972             M_MPR, M_NOWAIT|M_ZERO);
 2973         topo_change.port_details = port_change;
 2974         if (!port_change)
 2975                 goto out;
 2976         for (i = 0; i < num_entries; i++, event_port_change++, port_change++) {
 2977                 port_change->dev_handle = le16toh(event_port_change->
 2978                     AttachedDevHandle);
 2979                 port_change->reason = event_port_change->PortStatus;
 2980         }
 2981         _mapping_update_pcie_missing_count(sc, &topo_change);
 2982         _mapping_get_pcie_dev_info(sc, &topo_change);
 2983         _mapping_clear_removed_entries(sc);
 2984         _mapping_add_new_pcie_device(sc, &topo_change);
 2985 
 2986 out:
 2987         free(topo_change.port_details, M_MPR);
 2988         _mapping_flush_dpm_pages(sc);
 2989         if (sc->pending_map_events)
 2990                 sc->pending_map_events--;
 2991 }
 2992 
 2993 /**
 2994  * mpr_mapping_ir_config_change_event - handle IR config change list events
 2995  * @sc: per adapter object
 2996  * @event_data: event data payload
 2997  *
 2998  * Returns nothing.
 2999  */
 3000 void
 3001 mpr_mapping_ir_config_change_event(struct mpr_softc *sc,
 3002     Mpi2EventDataIrConfigChangeList_t *event_data)
 3003 {
 3004         Mpi2EventIrConfigElement_t *element;
 3005         int i;
 3006         u64 *wwid_table;
 3007         u32 map_idx, flags;
 3008         struct dev_mapping_table *mt_entry;
 3009         u16 element_flags;
 3010 
 3011         wwid_table = malloc(sizeof(u64) * event_data->NumElements, M_MPR,
 3012             M_NOWAIT | M_ZERO);
 3013         if (!wwid_table)
 3014                 goto out;
 3015         element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
 3016         flags = le32toh(event_data->Flags);
 3017 
 3018         /*
 3019          * For volume changes, get the WWID for the volume and put it in a
 3020          * table to be used in the processing of the IR change event.
 3021          */
 3022         for (i = 0; i < event_data->NumElements; i++, element++) {
 3023                 element_flags = le16toh(element->ElementFlags);
 3024                 if ((element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_ADDED) &&
 3025                     (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_REMOVED) &&
 3026                     (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE)
 3027                     && (element->ReasonCode !=
 3028                         MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED))
 3029                         continue;
 3030                 if ((element_flags &
 3031                     MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK) ==
 3032                     MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT) {
 3033                         mpr_config_get_volume_wwid(sc,
 3034                             le16toh(element->VolDevHandle), &wwid_table[i]);
 3035                 }
 3036         }
 3037 
 3038         /*
 3039          * Check the ReasonCode for each element in the IR event and Add/Remove
 3040          * Volumes or Physical Disks of Volumes to/from the mapping table. Use
 3041          * the WWIDs gotten above in wwid_table.
 3042          */
 3043         if (flags == MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
 3044                 goto out;
 3045         else {
 3046                 element = (Mpi2EventIrConfigElement_t *)&event_data->
 3047                     ConfigElement[0];
 3048                 for (i = 0; i < event_data->NumElements; i++, element++) {
 3049                         if (element->ReasonCode ==
 3050                             MPI2_EVENT_IR_CHANGE_RC_ADDED ||
 3051                             element->ReasonCode ==
 3052                             MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED) {
 3053                                 map_idx = _mapping_get_ir_mt_idx_from_wwid
 3054                                     (sc, wwid_table[i]);
 3055                                 if (map_idx != MPR_MAPTABLE_BAD_IDX) {
 3056                                         /*
 3057                                          * The volume is already in the mapping
 3058                                          * table. Just update it's info.
 3059                                          */
 3060                                         mt_entry = &sc->mapping_table[map_idx];
 3061                                         mt_entry->id = map_idx;
 3062                                         mt_entry->dev_handle = le16toh
 3063                                             (element->VolDevHandle);
 3064                                         mt_entry->device_info =
 3065                                             MPR_DEV_RESERVED | MPR_MAP_IN_USE;
 3066                                         _mapping_update_ir_missing_cnt(sc,
 3067                                             map_idx, element, wwid_table[i]);
 3068                                         continue;
 3069                                 }
 3070 
 3071                                 /*
 3072                                  * Volume is not in mapping table yet. Find a
 3073                                  * free entry in the mapping table at the
 3074                                  * volume mapping locations. If no entries are
 3075                                  * available, this is an error because it means
 3076                                  * there are more volumes than can be mapped
 3077                                  * and that should never happen for volumes.
 3078                                  */
 3079                                 map_idx = _mapping_get_free_ir_mt_idx(sc);
 3080                                 if (map_idx == MPR_MAPTABLE_BAD_IDX)
 3081                                 {
 3082                                         mpr_dprint(sc, MPR_ERROR | MPR_MAPPING,
 3083                                             "%s: failed to add the volume with "
 3084                                             "handle 0x%04x because there is no "
 3085                                             "free space available in the "
 3086                                             "mapping table\n", __func__,
 3087                                             le16toh(element->VolDevHandle));
 3088                                         continue;
 3089                                 }
 3090                                 mt_entry = &sc->mapping_table[map_idx];
 3091                                 mt_entry->physical_id = wwid_table[i];
 3092                                 mt_entry->id = map_idx;
 3093                                 mt_entry->dev_handle = le16toh(element->
 3094                                     VolDevHandle);
 3095                                 mt_entry->device_info = MPR_DEV_RESERVED |
 3096                                     MPR_MAP_IN_USE;
 3097                                 _mapping_update_ir_missing_cnt(sc, map_idx,
 3098                                     element, wwid_table[i]);
 3099                         } else if (element->ReasonCode ==
 3100                             MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
 3101                                 map_idx = _mapping_get_ir_mt_idx_from_wwid(sc,
 3102                                     wwid_table[i]);
 3103                                 if (map_idx == MPR_MAPTABLE_BAD_IDX) {
 3104                                         mpr_dprint(sc, MPR_MAPPING,"%s: Failed "
 3105                                             "to remove a volume because it has "
 3106                                             "already been removed.\n",
 3107                                             __func__);
 3108                                         continue;
 3109                                 }
 3110                                 _mapping_update_ir_missing_cnt(sc, map_idx,
 3111                                     element, wwid_table[i]);
 3112                         } else if (element->ReasonCode ==
 3113                             MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED) {
 3114                                 map_idx = _mapping_get_mt_idx_from_handle(sc,
 3115                                     le16toh(element->VolDevHandle));
 3116                                 if (map_idx == MPR_MAPTABLE_BAD_IDX) {
 3117                                         mpr_dprint(sc, MPR_MAPPING,"%s: Failed "
 3118                                             "to remove volume with handle "
 3119                                             "0x%04x because it has already "
 3120                                             "been removed.\n", __func__,
 3121                                             le16toh(element->VolDevHandle));
 3122                                         continue;
 3123                                 }
 3124                                 mt_entry = &sc->mapping_table[map_idx];
 3125                                 _mapping_update_ir_missing_cnt(sc, map_idx,
 3126                                     element, mt_entry->physical_id);
 3127                         }
 3128                 }
 3129         }
 3130 
 3131 out:
 3132         _mapping_flush_dpm_pages(sc);
 3133         free(wwid_table, M_MPR);
 3134         if (sc->pending_map_events)
 3135                 sc->pending_map_events--;
 3136 }

Cache object: f21544a4dcabdae07615b579eaeb5f46


[ 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.