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

Cache object: b88d06b4929491e58248ed8c0194174c


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