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

Cache object: bbbc5a0ac15ac70f8ba17982de5ec43e


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