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


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

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

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

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

Cache object: a60123f39846af13dd72a124cf0cdc83


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