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


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

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

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

    1 /*-
    2  * Copyright (c) 2011-2015 LSI Corp.
    3  * Copyright (c) 2013-2016 Avago Technologies
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 /* Communications core for Avago Technologies (LSI) MPT3 */
   34 
   35 /* TODO Move headers to mprvar */
   36 #include <sys/types.h>
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/selinfo.h>
   41 #include <sys/module.h>
   42 #include <sys/bus.h>
   43 #include <sys/conf.h>
   44 #include <sys/bio.h>
   45 #include <sys/malloc.h>
   46 #include <sys/uio.h>
   47 #include <sys/sysctl.h>
   48 #include <sys/endian.h>
   49 #include <sys/queue.h>
   50 #include <sys/kthread.h>
   51 #include <sys/taskqueue.h>
   52 #include <sys/sbuf.h>
   53 
   54 #include <machine/bus.h>
   55 #include <machine/resource.h>
   56 #include <sys/rman.h>
   57 
   58 #include <machine/stdarg.h>
   59 
   60 #include <cam/cam.h>
   61 #include <cam/cam_ccb.h>
   62 #include <cam/cam_debug.h>
   63 #include <cam/cam_sim.h>
   64 #include <cam/cam_xpt_sim.h>
   65 #include <cam/cam_xpt_periph.h>
   66 #include <cam/cam_periph.h>
   67 #include <cam/scsi/scsi_all.h>
   68 #include <cam/scsi/scsi_message.h>
   69 
   70 #include <dev/mpr/mpi/mpi2_type.h>
   71 #include <dev/mpr/mpi/mpi2.h>
   72 #include <dev/mpr/mpi/mpi2_ioc.h>
   73 #include <dev/mpr/mpi/mpi2_sas.h>
   74 #include <dev/mpr/mpi/mpi2_pci.h>
   75 #include <dev/mpr/mpi/mpi2_cnfg.h>
   76 #include <dev/mpr/mpi/mpi2_init.h>
   77 #include <dev/mpr/mpi/mpi2_raid.h>
   78 #include <dev/mpr/mpi/mpi2_tool.h>
   79 #include <dev/mpr/mpr_ioctl.h>
   80 #include <dev/mpr/mprvar.h>
   81 #include <dev/mpr/mpr_table.h>
   82 #include <dev/mpr/mpr_sas.h>
   83 
   84 /* For Hashed SAS Address creation for SATA Drives */
   85 #define MPT2SAS_SN_LEN 20
   86 #define MPT2SAS_MN_LEN 40
   87 
   88 struct mpr_fw_event_work {
   89         u16                     event;
   90         void                    *event_data;
   91         TAILQ_ENTRY(mpr_fw_event_work)  ev_link;
   92 };
   93 
   94 union _sata_sas_address {
   95         u8 wwid[8];
   96         struct {
   97                 u32 high;
   98                 u32 low;
   99         } word;
  100 };
  101 
  102 /*
  103  * define the IDENTIFY DEVICE structure
  104  */
  105 struct _ata_identify_device_data {
  106         u16 reserved1[10];      /* 0-9 */
  107         u16 serial_number[10];  /* 10-19 */
  108         u16 reserved2[7];       /* 20-26 */
  109         u16 model_number[20];   /* 27-46*/
  110         u16 reserved3[170];     /* 47-216 */
  111         u16 rotational_speed;   /* 217 */
  112         u16 reserved4[38];      /* 218-255 */
  113 };
  114 static u32 event_count;
  115 static void mprsas_fw_work(struct mpr_softc *sc,
  116     struct mpr_fw_event_work *fw_event);
  117 static void mprsas_fw_event_free(struct mpr_softc *,
  118     struct mpr_fw_event_work *);
  119 static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate);
  120 static int mprsas_add_pcie_device(struct mpr_softc *sc, u16 handle,
  121     u8 linkrate);
  122 static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
  123     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
  124     u32 devinfo);
  125 static void mprsas_ata_id_timeout(void *data);
  126 int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
  127     u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
  128 static int mprsas_volume_add(struct mpr_softc *sc,
  129     u16 handle);
  130 static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc);
  131 static void mprsas_stop_unit_done(struct cam_periph *periph,
  132     union ccb *done_ccb);
  133 
  134 void
  135 mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data,
  136     MPI2_EVENT_NOTIFICATION_REPLY *event)
  137 {
  138         struct mpr_fw_event_work *fw_event;
  139         u16 sz;
  140 
  141         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  142         MPR_DPRINT_EVENT(sc, sas, event);
  143         mprsas_record_event(sc, event);
  144 
  145         fw_event = malloc(sizeof(struct mpr_fw_event_work), M_MPR,
  146              M_ZERO|M_NOWAIT);
  147         if (!fw_event) {
  148                 printf("%s: allocate failed for fw_event\n", __func__);
  149                 return;
  150         }
  151         sz = le16toh(event->EventDataLength) * 4;
  152         fw_event->event_data = malloc(sz, M_MPR, M_ZERO|M_NOWAIT);
  153         if (!fw_event->event_data) {
  154                 printf("%s: allocate failed for event_data\n", __func__);
  155                 free(fw_event, M_MPR);
  156                 return;
  157         }
  158 
  159         bcopy(event->EventData, fw_event->event_data, sz);
  160         fw_event->event = event->Event;
  161         if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
  162             event->Event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ||
  163             event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||
  164             event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
  165             sc->track_mapping_events)
  166                 sc->pending_map_events++;
  167 
  168         /*
  169          * When wait_for_port_enable flag is set, make sure that all the events
  170          * are processed. Increment the startup_refcount and decrement it after
  171          * events are processed.
  172          */
  173         if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
  174             event->Event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ||
  175             event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
  176             sc->wait_for_port_enable)
  177                 mprsas_startup_increment(sc->sassc);
  178 
  179         TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
  180         taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
  181 }
  182 
  183 static void
  184 mprsas_fw_event_free(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
  185 {
  186 
  187         free(fw_event->event_data, M_MPR);
  188         free(fw_event, M_MPR);
  189 }
  190 
  191 /**
  192  * _mpr_fw_work - delayed task for processing firmware events
  193  * @sc: per adapter object
  194  * @fw_event: The fw_event_work object
  195  * Context: user.
  196  *
  197  * Return nothing.
  198  */
  199 static void
  200 mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
  201 {
  202         struct mprsas_softc *sassc;
  203         sassc = sc->sassc;
  204 
  205         mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Working on  Event: [%x]\n",
  206             event_count++, __func__, fw_event->event);
  207         switch (fw_event->event) {
  208         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 
  209         {
  210                 MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
  211                 MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
  212                 uint8_t i;
  213 
  214                 data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
  215                     fw_event->event_data;
  216 
  217                 mpr_mapping_topology_change_event(sc, fw_event->event_data);
  218 
  219                 for (i = 0; i < data->NumEntries; i++) {
  220                         phy = &data->PHY[i];
  221                         switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
  222                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
  223                                 if (mprsas_add_device(sc,
  224                                     le16toh(phy->AttachedDevHandle),
  225                                     phy->LinkRate)) {
  226                                         mpr_dprint(sc, MPR_ERROR, "%s: "
  227                                             "failed to add device with handle "
  228                                             "0x%x\n", __func__,
  229                                             le16toh(phy->AttachedDevHandle));
  230                                         mprsas_prepare_remove(sassc, le16toh(
  231                                             phy->AttachedDevHandle));
  232                                 }
  233                                 break;
  234                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
  235                                 mprsas_prepare_remove(sassc, le16toh(
  236                                     phy->AttachedDevHandle));
  237                                 break;
  238                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
  239                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
  240                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
  241                         default:
  242                                 break;
  243                         }
  244                 }
  245                 /*
  246                  * refcount was incremented for this event in
  247                  * mprsas_evt_handler.  Decrement it here because the event has
  248                  * been processed.
  249                  */
  250                 mprsas_startup_decrement(sassc);
  251                 break;
  252         }
  253         case MPI2_EVENT_SAS_DISCOVERY:
  254         {
  255                 MPI2_EVENT_DATA_SAS_DISCOVERY *data;
  256 
  257                 data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data;
  258 
  259                 if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED)
  260                         mpr_dprint(sc, MPR_TRACE,"SAS discovery start event\n");
  261                 if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) {
  262                         mpr_dprint(sc, MPR_TRACE,"SAS discovery stop event\n");
  263                         sassc->flags &= ~MPRSAS_IN_DISCOVERY;
  264                         mprsas_discovery_end(sassc);
  265                 }
  266                 break;
  267         }
  268         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
  269         {
  270                 Mpi2EventDataSasEnclDevStatusChange_t *data;
  271                 data = (Mpi2EventDataSasEnclDevStatusChange_t *)
  272                     fw_event->event_data;
  273                 mpr_mapping_enclosure_dev_status_change_event(sc,
  274                     fw_event->event_data);
  275                 break;
  276         }
  277         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
  278         {
  279                 Mpi2EventIrConfigElement_t *element;
  280                 int i;
  281                 u8 foreign_config, reason;
  282                 u16 elementType;
  283                 Mpi2EventDataIrConfigChangeList_t *event_data;
  284                 struct mprsas_target *targ;
  285                 unsigned int id;
  286 
  287                 event_data = fw_event->event_data;
  288                 foreign_config = (le32toh(event_data->Flags) &
  289                     MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
  290 
  291                 element =
  292                     (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
  293                 id = mpr_mapping_get_raid_tid_from_handle(sc,
  294                     element->VolDevHandle);
  295 
  296                 mpr_mapping_ir_config_change_event(sc, event_data);
  297                 for (i = 0; i < event_data->NumElements; i++, element++) {
  298                         reason = element->ReasonCode;
  299                         elementType = le16toh(element->ElementFlags) &
  300                             MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
  301                         /*
  302                          * check for element type of Phys Disk or Hot Spare
  303                          */
  304                         if ((elementType != 
  305                             MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT)
  306                             && (elementType !=
  307                             MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT))
  308                                 // do next element
  309                                 goto skip_fp_send;
  310 
  311                         /*
  312                          * check for reason of Hide, Unhide, PD Created, or PD
  313                          * Deleted
  314                          */
  315                         if ((reason != MPI2_EVENT_IR_CHANGE_RC_HIDE) &&
  316                             (reason != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) &&
  317                             (reason != MPI2_EVENT_IR_CHANGE_RC_PD_CREATED) &&
  318                             (reason != MPI2_EVENT_IR_CHANGE_RC_PD_DELETED))
  319                                 goto skip_fp_send;
  320 
  321                         // check for a reason of Hide or PD Created
  322                         if ((reason == MPI2_EVENT_IR_CHANGE_RC_HIDE) ||
  323                             (reason == MPI2_EVENT_IR_CHANGE_RC_PD_CREATED))
  324                         {
  325                                 // build RAID Action message
  326                                 Mpi2RaidActionRequest_t *action;
  327                                 Mpi2RaidActionReply_t *reply = NULL;
  328                                 struct mpr_command *cm;
  329                                 int error = 0;
  330                                 if ((cm = mpr_alloc_command(sc)) == NULL) {
  331                                         printf("%s: command alloc failed\n",
  332                                             __func__);
  333                                         return;
  334                                 }
  335 
  336                                 mpr_dprint(sc, MPR_EVENT, "Sending FP action "
  337                                     "from "
  338                                     "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST "
  339                                     ":\n");
  340                                 action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
  341                                 action->Function = MPI2_FUNCTION_RAID_ACTION;
  342                                 action->Action =
  343                                     MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
  344                                 action->PhysDiskNum = element->PhysDiskNum;
  345                                 cm->cm_desc.Default.RequestFlags =
  346                                     MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  347                                 error = mpr_request_polled(sc, &cm);
  348                                 if (cm != NULL)
  349                                         reply = (Mpi2RaidActionReply_t *)
  350                                             cm->cm_reply;
  351                                 if (error || (reply == NULL)) {
  352                                         /* FIXME */
  353                                         /*
  354                                          * If the poll returns error then we
  355                                          * need to do diag reset
  356                                          */
  357                                         printf("%s: poll for page completed "
  358                                             "with error %d", __func__, error);
  359                                 }
  360                                 if (reply && (le16toh(reply->IOCStatus) &
  361                                     MPI2_IOCSTATUS_MASK) !=
  362                                     MPI2_IOCSTATUS_SUCCESS) {
  363                                         mpr_dprint(sc, MPR_ERROR, "%s: error "
  364                                             "sending RaidActionPage; "
  365                                             "iocstatus = 0x%x\n", __func__,
  366                                             le16toh(reply->IOCStatus));
  367                                 }
  368 
  369                                 if (cm)
  370                                         mpr_free_command(sc, cm);
  371                         }
  372 skip_fp_send:
  373                         mpr_dprint(sc, MPR_EVENT, "Received "
  374                             "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason "
  375                             "code %x:\n", element->ReasonCode);
  376                         switch (element->ReasonCode) {
  377                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
  378                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
  379                                 if (!foreign_config) {
  380                                         if (mprsas_volume_add(sc,
  381                                             le16toh(element->VolDevHandle))) {
  382                                                 printf("%s: failed to add RAID "
  383                                                     "volume with handle 0x%x\n",
  384                                                     __func__, le16toh(element->
  385                                                     VolDevHandle));
  386                                         }
  387                                 }
  388                                 break;
  389                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
  390                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
  391                                 /*
  392                                  * Rescan after volume is deleted or removed.
  393                                  */
  394                                 if (!foreign_config) {
  395                                         if (id == MPR_MAP_BAD_ID) {
  396                                                 printf("%s: could not get ID "
  397                                                     "for volume with handle "
  398                                                     "0x%04x\n", __func__,
  399                                                     le16toh(element->
  400                                                     VolDevHandle));
  401                                                 break;
  402                                         }
  403                                         
  404                                         targ = &sassc->targets[id];
  405                                         targ->handle = 0x0;
  406                                         targ->encl_slot = 0x0;
  407                                         targ->encl_handle = 0x0;
  408                                         targ->encl_level_valid = 0x0;
  409                                         targ->encl_level = 0x0;
  410                                         targ->connector_name[0] = ' ';
  411                                         targ->connector_name[1] = ' ';
  412                                         targ->connector_name[2] = ' ';
  413                                         targ->connector_name[3] = ' ';
  414                                         targ->exp_dev_handle = 0x0;
  415                                         targ->phy_num = 0x0;
  416                                         targ->linkrate = 0x0;
  417                                         mprsas_rescan_target(sc, targ);
  418                                         printf("RAID target id 0x%x removed\n",
  419                                             targ->tid);
  420                                 }
  421                                 break;
  422                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
  423                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
  424                                 /*
  425                                  * Phys Disk of a volume has been created.  Hide
  426                                  * it from the OS.
  427                                  */
  428                                 targ = mprsas_find_target_by_handle(sassc, 0,
  429                                     element->PhysDiskDevHandle);
  430                                 if (targ == NULL) 
  431                                         break;
  432                                 targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT;
  433                                 mprsas_rescan_target(sc, targ);
  434                                 break;
  435                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
  436                                 /*
  437                                  * Phys Disk of a volume has been deleted.
  438                                  * Expose it to the OS.
  439                                  */
  440                                 if (mprsas_add_device(sc,
  441                                     le16toh(element->PhysDiskDevHandle), 0)) {
  442                                         printf("%s: failed to add device with "
  443                                             "handle 0x%x\n", __func__,
  444                                             le16toh(element->
  445                                             PhysDiskDevHandle));
  446                                         mprsas_prepare_remove(sassc,
  447                                             le16toh(element->
  448                                             PhysDiskDevHandle));
  449                                 }
  450                                 break;
  451                         }
  452                 }
  453                 /*
  454                  * refcount was incremented for this event in
  455                  * mprsas_evt_handler.  Decrement it here because the event has
  456                  * been processed.
  457                  */
  458                 mprsas_startup_decrement(sassc);
  459                 break;
  460         }
  461         case MPI2_EVENT_IR_VOLUME:
  462         {
  463                 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
  464 
  465                 /*
  466                  * Informational only.
  467                  */
  468                 mpr_dprint(sc, MPR_EVENT, "Received IR Volume event:\n");
  469                 switch (event_data->ReasonCode) {
  470                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
  471                         mpr_dprint(sc, MPR_EVENT, "   Volume Settings "
  472                             "changed from 0x%x to 0x%x for Volome with "
  473                             "handle 0x%x", le32toh(event_data->PreviousValue),
  474                             le32toh(event_data->NewValue),
  475                             le16toh(event_data->VolDevHandle));
  476                         break;
  477                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
  478                         mpr_dprint(sc, MPR_EVENT, "   Volume Status "
  479                             "changed from 0x%x to 0x%x for Volome with "
  480                             "handle 0x%x", le32toh(event_data->PreviousValue),
  481                             le32toh(event_data->NewValue),
  482                             le16toh(event_data->VolDevHandle));
  483                         break;
  484                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
  485                         mpr_dprint(sc, MPR_EVENT, "   Volume State "
  486                             "changed from 0x%x to 0x%x for Volome with "
  487                             "handle 0x%x", le32toh(event_data->PreviousValue),
  488                             le32toh(event_data->NewValue),
  489                             le16toh(event_data->VolDevHandle));
  490                                 u32 state;
  491                                 struct mprsas_target *targ;
  492                                 state = le32toh(event_data->NewValue);
  493                                 switch (state) {
  494                                 case MPI2_RAID_VOL_STATE_MISSING:
  495                                 case MPI2_RAID_VOL_STATE_FAILED:
  496                                         mprsas_prepare_volume_remove(sassc,
  497                                             event_data->VolDevHandle);
  498                                         break;
  499                  
  500                                 case MPI2_RAID_VOL_STATE_ONLINE:
  501                                 case MPI2_RAID_VOL_STATE_DEGRADED:
  502                                 case MPI2_RAID_VOL_STATE_OPTIMAL:
  503                                         targ =
  504                                             mprsas_find_target_by_handle(sassc,
  505                                             0, event_data->VolDevHandle);
  506                                         if (targ) {
  507                                                 printf("%s %d: Volume handle "
  508                                                     "0x%x is already added \n",
  509                                                     __func__, __LINE__,
  510                                                     event_data->VolDevHandle);
  511                                                 break;
  512                                         }
  513                                         if (mprsas_volume_add(sc,
  514                                             le16toh(event_data->
  515                                             VolDevHandle))) {
  516                                                 printf("%s: failed to add RAID "
  517                                                     "volume with handle 0x%x\n",
  518                                                     __func__, le16toh(
  519                                                     event_data->VolDevHandle));
  520                                         }
  521                                         break;
  522                                 default:
  523                                         break;
  524                                 }
  525                         break;
  526                 default:
  527                         break;
  528                 }
  529                 break;
  530         }
  531         case MPI2_EVENT_IR_PHYSICAL_DISK:
  532         {
  533                 Mpi2EventDataIrPhysicalDisk_t *event_data =
  534                     fw_event->event_data;
  535                 struct mprsas_target *targ;
  536 
  537                 /*
  538                  * Informational only.
  539                  */
  540                 mpr_dprint(sc, MPR_EVENT, "Received IR Phys Disk event:\n");
  541                 switch (event_data->ReasonCode) {
  542                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
  543                         mpr_dprint(sc, MPR_EVENT, "   Phys Disk Settings "
  544                             "changed from 0x%x to 0x%x for Phys Disk Number "
  545                             "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
  546                             "%d", le32toh(event_data->PreviousValue),
  547                             le32toh(event_data->NewValue),
  548                             event_data->PhysDiskNum,
  549                             le16toh(event_data->PhysDiskDevHandle),
  550                             le16toh(event_data->EnclosureHandle),
  551                             le16toh(event_data->Slot));
  552                         break;
  553                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
  554                         mpr_dprint(sc, MPR_EVENT, "   Phys Disk Status changed "
  555                             "from 0x%x to 0x%x for Phys Disk Number %d and "
  556                             "handle 0x%x at Enclosure handle 0x%x, Slot %d",
  557                             le32toh(event_data->PreviousValue),
  558                             le32toh(event_data->NewValue),
  559                             event_data->PhysDiskNum,
  560                             le16toh(event_data->PhysDiskDevHandle),
  561                             le16toh(event_data->EnclosureHandle),
  562                             le16toh(event_data->Slot));
  563                         break;
  564                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
  565                         mpr_dprint(sc, MPR_EVENT, "   Phys Disk State changed "
  566                             "from 0x%x to 0x%x for Phys Disk Number %d and "
  567                             "handle 0x%x at Enclosure handle 0x%x, Slot %d",
  568                             le32toh(event_data->PreviousValue),
  569                             le32toh(event_data->NewValue),
  570                             event_data->PhysDiskNum,
  571                             le16toh(event_data->PhysDiskDevHandle),
  572                             le16toh(event_data->EnclosureHandle),
  573                             le16toh(event_data->Slot));
  574                         switch (event_data->NewValue) {
  575                                 case MPI2_RAID_PD_STATE_ONLINE:
  576                                 case MPI2_RAID_PD_STATE_DEGRADED:
  577                                 case MPI2_RAID_PD_STATE_REBUILDING:
  578                                 case MPI2_RAID_PD_STATE_OPTIMAL:
  579                                 case MPI2_RAID_PD_STATE_HOT_SPARE:
  580                                         targ = mprsas_find_target_by_handle(
  581                                             sassc, 0,
  582                                             event_data->PhysDiskDevHandle);
  583                                         if (targ) {
  584                                                 targ->flags |=
  585                                                     MPR_TARGET_FLAGS_RAID_COMPONENT;
  586                                                 printf("%s %d: Found Target "
  587                                                     "for handle 0x%x.\n", 
  588                                                     __func__, __LINE__ ,
  589                                                     event_data->
  590                                                     PhysDiskDevHandle);
  591                                         }
  592                                 break;
  593                                 case MPI2_RAID_PD_STATE_OFFLINE:
  594                                 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
  595                                 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
  596                                 default:
  597                                         targ = mprsas_find_target_by_handle(
  598                                             sassc, 0,
  599                                             event_data->PhysDiskDevHandle);
  600                                         if (targ) {
  601                                                 targ->flags |=
  602                                             ~MPR_TARGET_FLAGS_RAID_COMPONENT;
  603                                                 printf("%s %d: Found Target "
  604                                                     "for handle 0x%x.  \n",
  605                                                     __func__, __LINE__ ,
  606                                                     event_data->
  607                                                     PhysDiskDevHandle);
  608                                         }
  609                                 break;
  610                         }
  611                 default:
  612                         break;
  613                 }
  614                 break;
  615         }
  616         case MPI2_EVENT_IR_OPERATION_STATUS:
  617         {
  618                 Mpi2EventDataIrOperationStatus_t *event_data =
  619                     fw_event->event_data;
  620 
  621                 /*
  622                  * Informational only.
  623                  */
  624                 mpr_dprint(sc, MPR_EVENT, "Received IR Op Status event:\n");
  625                 mpr_dprint(sc, MPR_EVENT, "   RAID Operation of %d is %d "
  626                     "percent complete for Volume with handle 0x%x",
  627                     event_data->RAIDOperation, event_data->PercentComplete,
  628                     le16toh(event_data->VolDevHandle));
  629                 break;
  630         }
  631         case MPI2_EVENT_TEMP_THRESHOLD:
  632         {
  633                 pMpi2EventDataTemperature_t     temp_event;
  634 
  635                 temp_event = (pMpi2EventDataTemperature_t)fw_event->event_data;
  636 
  637                 /*
  638                  * The Temp Sensor Count must be greater than the event's Sensor
  639                  * Num to be valid.  If valid, print the temp thresholds that
  640                  * have been exceeded.
  641                  */
  642                 if (sc->iounit_pg8.NumSensors > temp_event->SensorNum) {
  643                         mpr_dprint(sc, MPR_FAULT, "Temperature Threshold flags "
  644                             "%s %s %s %s exceeded for Sensor: %d !!!\n",
  645                             ((temp_event->Status & 0x01) == 1) ? "0 " : " ",
  646                             ((temp_event->Status & 0x02) == 2) ? "1 " : " ",
  647                             ((temp_event->Status & 0x04) == 4) ? "2 " : " ",
  648                             ((temp_event->Status & 0x08) == 8) ? "3 " : " ",
  649                             temp_event->SensorNum);
  650                         mpr_dprint(sc, MPR_FAULT, "Current Temp in Celsius: "
  651                             "%d\n", temp_event->CurrentTemperature);
  652                 }
  653                 break;
  654         }
  655         case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
  656         {
  657                 pMpi26EventDataActiveCableExcept_t      ace_event_data;
  658                 ace_event_data =
  659                     (pMpi26EventDataActiveCableExcept_t)fw_event->event_data;
  660 
  661                 switch(ace_event_data->ReasonCode) {
  662                 case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER:
  663                 {
  664                         mpr_printf(sc, "Currently a cable with "
  665                             "ReceptacleID %d cannot be powered and device "
  666                             "connected to this active cable will not be seen. "
  667                             "This active cable requires %d mW of power.\n",
  668                             ace_event_data->ReceptacleID,
  669                             ace_event_data->ActiveCablePowerRequirement);
  670                         break;
  671                 }
  672                 case MPI26_EVENT_ACTIVE_CABLE_DEGRADED:
  673                 {
  674                         mpr_printf(sc, "Currently a cable with "
  675                             "ReceptacleID %d is not running at optimal speed "
  676                             "(12 Gb/s rate)\n", ace_event_data->ReceptacleID);
  677                         break;
  678                 }
  679                 default:
  680                         break;
  681                 }
  682                 break;
  683         }
  684         case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
  685         {
  686                 pMpi25EventDataSasDeviceDiscoveryError_t discovery_error_data;
  687                 uint64_t sas_address;
  688 
  689                 discovery_error_data =
  690                     (pMpi25EventDataSasDeviceDiscoveryError_t)
  691                     fw_event->event_data;
  692                 
  693                 sas_address = discovery_error_data->SASAddress.High;
  694                 sas_address = (sas_address << 32) |
  695                     discovery_error_data->SASAddress.Low;
  696 
  697                 switch(discovery_error_data->ReasonCode) {
  698                 case MPI25_EVENT_SAS_DISC_ERR_SMP_FAILED:
  699                 {
  700                         mpr_printf(sc, "SMP command failed during discovery "
  701                             "for expander with SAS Address %jx and "
  702                             "handle 0x%x.\n", sas_address,
  703                             discovery_error_data->DevHandle);
  704                         break;
  705                 }
  706                 case MPI25_EVENT_SAS_DISC_ERR_SMP_TIMEOUT:
  707                 {
  708                         mpr_printf(sc, "SMP command timed out during "
  709                             "discovery for expander with SAS Address %jx and "
  710                             "handle 0x%x.\n", sas_address,
  711                             discovery_error_data->DevHandle);
  712                         break;
  713                 }
  714                 default:
  715                         break;
  716                 }
  717                 break;
  718         }
  719         case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 
  720         {
  721                 MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST *data;
  722                 MPI26_EVENT_PCIE_TOPO_PORT_ENTRY *port_entry;
  723                 uint8_t i, link_rate;
  724                 uint16_t handle;
  725 
  726                 data = (MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST *)
  727                     fw_event->event_data;
  728 
  729                 mpr_mapping_pcie_topology_change_event(sc,
  730                     fw_event->event_data);
  731 
  732                 for (i = 0; i < data->NumEntries; i++) {
  733                         port_entry = &data->PortEntry[i];
  734                         handle = le16toh(port_entry->AttachedDevHandle);
  735                         link_rate = port_entry->CurrentPortInfo &
  736                             MPI26_EVENT_PCIE_TOPO_PI_RATE_MASK;
  737                         switch (port_entry->PortStatus) {
  738                         case MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED:
  739                                 if (link_rate <
  740                                     MPI26_EVENT_PCIE_TOPO_PI_RATE_2_5) {
  741                                         mpr_dprint(sc, MPR_ERROR, "%s: Cannot "
  742                                             "add PCIe device with handle 0x%x "
  743                                             "with unknown link rate.\n",
  744                                             __func__, handle);
  745                                         break;
  746                                 }
  747                                 if (mprsas_add_pcie_device(sc, handle,
  748                                     link_rate)) {
  749                                         mpr_dprint(sc, MPR_ERROR, "%s: failed "
  750                                             "to add PCIe device with handle "
  751                                             "0x%x\n", __func__, handle);
  752                                         mprsas_prepare_remove(sassc, handle);
  753                                 }
  754                                 break;
  755                         case MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING:
  756                                 mprsas_prepare_remove(sassc, handle);
  757                                 break;
  758                         case MPI26_EVENT_PCIE_TOPO_PS_PORT_CHANGED:
  759                         case MPI26_EVENT_PCIE_TOPO_PS_NO_CHANGE:
  760                         case MPI26_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING:
  761                         default:
  762                                 break;
  763                         }
  764                 }
  765                 /*
  766                  * refcount was incremented for this event in
  767                  * mprsas_evt_handler.  Decrement it here because the event has
  768                  * been processed.
  769                  */
  770                 mprsas_startup_decrement(sassc);
  771                 break;
  772         }
  773         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
  774         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
  775         default:
  776                 mpr_dprint(sc, MPR_TRACE,"Unhandled event 0x%0X\n",
  777                     fw_event->event);
  778                 break;
  779 
  780         }
  781         mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count,
  782             __func__, fw_event->event);
  783         mprsas_fw_event_free(sc, fw_event);
  784 }
  785 
  786 void
  787 mprsas_firmware_event_work(void *arg, int pending)
  788 {
  789         struct mpr_fw_event_work *fw_event;
  790         struct mpr_softc *sc;
  791 
  792         sc = (struct mpr_softc *)arg;
  793         mpr_lock(sc);
  794         while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
  795                 TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
  796                 mprsas_fw_work(sc, fw_event);
  797         }
  798         mpr_unlock(sc);
  799 }
  800 
  801 static int
  802 mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate)
  803 {
  804         char devstring[80];
  805         struct mprsas_softc *sassc;
  806         struct mprsas_target *targ;
  807         Mpi2ConfigReply_t mpi_reply;
  808         Mpi2SasDevicePage0_t config_page;
  809         uint64_t sas_address, parent_sas_address = 0;
  810         u32 device_info, parent_devinfo = 0;
  811         unsigned int id;
  812         int ret = 1, error = 0, i;
  813         struct mprsas_lun *lun;
  814         u8 is_SATA_SSD = 0;
  815         struct mpr_command *cm;
  816 
  817         sassc = sc->sassc;
  818         mprsas_startup_increment(sassc);
  819         if ((mpr_config_get_sas_device_pg0(sc, &mpi_reply, &config_page,
  820              MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
  821                 printf("%s: error reading SAS device page0\n", __func__);
  822                 error = ENXIO;
  823                 goto out;
  824         }
  825 
  826         device_info = le32toh(config_page.DeviceInfo);
  827 
  828         if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
  829             && (le16toh(config_page.ParentDevHandle) != 0)) {
  830                 Mpi2ConfigReply_t tmp_mpi_reply;
  831                 Mpi2SasDevicePage0_t parent_config_page;
  832 
  833                 if ((mpr_config_get_sas_device_pg0(sc, &tmp_mpi_reply,
  834                      &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
  835                      le16toh(config_page.ParentDevHandle)))) {
  836                         printf("%s: error reading SAS device %#x page0\n",
  837                             __func__, le16toh(config_page.ParentDevHandle));
  838                 } else {
  839                         parent_sas_address = parent_config_page.SASAddress.High;
  840                         parent_sas_address = (parent_sas_address << 32) |
  841                             parent_config_page.SASAddress.Low;
  842                         parent_devinfo = le32toh(parent_config_page.DeviceInfo);
  843                 }
  844         }
  845         /* TODO Check proper endianness */
  846         sas_address = config_page.SASAddress.High;
  847         sas_address = (sas_address << 32) | config_page.SASAddress.Low;
  848         mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n",
  849             sas_address);
  850 
  851         /*
  852          * Always get SATA Identify information because this is used to
  853          * determine if Start/Stop Unit should be sent to the drive when the
  854          * system is shutdown.
  855          */
  856         if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
  857                 ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address,
  858                     handle, device_info, &is_SATA_SSD);
  859                 if (ret) {
  860                         mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type "
  861                             "(SSD or HDD) for SATA device with handle 0x%04x\n",
  862                             __func__, handle);
  863                 } else {
  864                         mpr_dprint(sc, MPR_INFO, "SAS Address from SATA "
  865                             "device = %jx\n", sas_address);
  866                 }
  867         }
  868 
  869         /*
  870          * use_phynum:
  871          *  1 - use the PhyNum field as a fallback to the mapping logic
  872          *  0 - never use the PhyNum field
  873          * -1 - only use the PhyNum field
  874          *
  875          * Note that using the Phy number to map a device can cause device adds
  876          * to fail if multiple enclosures/expanders are in the topology. For
  877          * example, if two devices are in the same slot number in two different
  878          * enclosures within the topology, only one of those devices will be
  879          * added. PhyNum mapping should not be used if multiple enclosures are
  880          * in the topology.
  881          */
  882         id = MPR_MAP_BAD_ID;
  883         if (sc->use_phynum != -1) 
  884                 id = mpr_mapping_get_tid(sc, sas_address, handle);
  885         if (id == MPR_MAP_BAD_ID) {
  886                 if ((sc->use_phynum == 0) ||
  887                     ((id = config_page.PhyNum) > sassc->maxtargets)) {
  888                         mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! "
  889                             "Could not get ID for device with handle 0x%04x\n",
  890                             __FILE__, __LINE__, __func__, handle);
  891                         error = ENXIO;
  892                         goto out;
  893                 }
  894         }
  895         mpr_dprint(sc, MPR_MAPPING, "%s: Target ID for added device is %d.\n",
  896             __func__, id);
  897 
  898         /*
  899          * Only do the ID check and reuse check if the target is not from a
  900          * RAID Component. For Physical Disks of a Volume, the ID will be reused
  901          * when a volume is deleted because the mapping entry for the PD will
  902          * still be in the mapping table. The ID check should not be done here
  903          * either since this PD is already being used.
  904          */
  905         targ = &sassc->targets[id];
  906         if (!(targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT)) {
  907                 if (mprsas_check_id(sassc, id) != 0) {
  908                         device_printf(sc->mpr_dev, "Excluding target id %d\n",
  909                             id);
  910                         error = ENXIO;
  911                         goto out;
  912                 }
  913 
  914                 if (targ->handle != 0x0) {
  915                         mpr_dprint(sc, MPR_MAPPING, "Attempting to reuse "
  916                             "target id %d handle 0x%04x\n", id, targ->handle);
  917                         error = ENXIO;
  918                         goto out;
  919                 }
  920         }
  921 
  922         mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n",
  923             sas_address);
  924         targ->devinfo = device_info;
  925         targ->devname = le32toh(config_page.DeviceName.High);
  926         targ->devname = (targ->devname << 32) | 
  927             le32toh(config_page.DeviceName.Low);
  928         targ->encl_handle = le16toh(config_page.EnclosureHandle);
  929         targ->encl_slot = le16toh(config_page.Slot);
  930         targ->encl_level = config_page.EnclosureLevel;
  931         targ->connector_name[0] = config_page.ConnectorName[0];
  932         targ->connector_name[1] = config_page.ConnectorName[1];
  933         targ->connector_name[2] = config_page.ConnectorName[2];
  934         targ->connector_name[3] = config_page.ConnectorName[3];
  935         targ->handle = handle;
  936         targ->parent_handle = le16toh(config_page.ParentDevHandle);
  937         targ->sasaddr = mpr_to_u64(&config_page.SASAddress);
  938         targ->parent_sasaddr = le64toh(parent_sas_address);
  939         targ->parent_devinfo = parent_devinfo;
  940         targ->tid = id;
  941         targ->linkrate = (linkrate>>4);
  942         targ->flags = 0;
  943         if (is_SATA_SSD) {
  944                 targ->flags = MPR_TARGET_IS_SATA_SSD;
  945         }
  946         if ((le16toh(config_page.Flags) &
  947             MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) &&
  948             (le16toh(config_page.Flags) &
  949             MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE)) {
  950                 targ->scsi_req_desc_type =
  951                     MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
  952         }
  953         if (le16toh(config_page.Flags) &
  954             MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
  955                 targ->encl_level_valid = TRUE;
  956         }
  957         TAILQ_INIT(&targ->commands);
  958         TAILQ_INIT(&targ->timedout_commands);
  959         while (!SLIST_EMPTY(&targ->luns)) {
  960                 lun = SLIST_FIRST(&targ->luns);
  961                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
  962                 free(lun, M_MPR);
  963         }
  964         SLIST_INIT(&targ->luns);
  965 
  966         mpr_describe_devinfo(targ->devinfo, devstring, 80);
  967         mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> "
  968             "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring,
  969             mpr_describe_table(mpr_linkrate_names, targ->linkrate),
  970             targ->handle, targ->encl_handle, targ->encl_slot);
  971         if (targ->encl_level_valid) {
  972                 mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d "
  973                     "and connector name (%4s)\n", targ->encl_level,
  974                     targ->connector_name);
  975         }
  976 #if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \
  977     (__FreeBSD_version < 902502)
  978         if ((sassc->flags & MPRSAS_IN_STARTUP) == 0)
  979 #endif
  980                 mprsas_rescan_target(sc, targ);
  981         mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid);
  982 
  983         /*
  984          * Check all commands to see if the SATA_ID_TIMEOUT flag has been set.
  985          * If so, send a Target Reset TM to the target that was just created.
  986          * An Abort Task TM should be used instead of a Target Reset, but that
  987          * would be much more difficult because targets have not been fully
  988          * discovered yet, and LUN's haven't been setup.  So, just reset the
  989          * target instead of the LUN.
  990          */
  991         for (i = 1; i < sc->num_reqs; i++) {
  992                 cm = &sc->commands[i];
  993                 if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
  994                         targ->timeouts++;
  995                         cm->cm_state = MPR_CM_STATE_TIMEDOUT;
  996 
  997                         if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) {
  998                                 mpr_dprint(sc, MPR_INFO, "%s: sending Target "
  999                                     "Reset for stuck SATA identify command "
 1000                                     "(cm = %p)\n", __func__, cm);
 1001                                 targ->tm->cm_targ = targ;
 1002                                 mprsas_send_reset(sc, targ->tm,
 1003                                     MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
 1004                         } else {
 1005                                 mpr_dprint(sc, MPR_ERROR, "Failed to allocate "
 1006                                     "tm for Target Reset after SATA ID command "
 1007                                     "timed out (cm %p)\n", cm);
 1008                         }
 1009                         /*
 1010                          * No need to check for more since the target is
 1011                          * already being reset.
 1012                          */
 1013                         break;
 1014                 }
 1015         }
 1016 out:
 1017         /*
 1018          * Free the commands that may not have been freed from the SATA ID call
 1019          */
 1020         for (i = 1; i < sc->num_reqs; i++) {
 1021                 cm = &sc->commands[i];
 1022                 if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
 1023                         mpr_free_command(sc, cm);
 1024                 }
 1025         }
 1026         mprsas_startup_decrement(sassc);
 1027         return (error);
 1028 }
 1029 
 1030 int
 1031 mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
 1032     u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD)
 1033 {
 1034         Mpi2SataPassthroughReply_t mpi_reply;
 1035         int i, rc, try_count;
 1036         u32 *bufferptr;
 1037         union _sata_sas_address hash_address;
 1038         struct _ata_identify_device_data ata_identify;
 1039         u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN];
 1040         u32 ioc_status;
 1041         u8 sas_status;
 1042 
 1043         memset(&ata_identify, 0, sizeof(ata_identify));
 1044         memset(&mpi_reply, 0, sizeof(mpi_reply));
 1045         try_count = 0;
 1046         do {
 1047                 rc = mprsas_get_sata_identify(sc, handle, &mpi_reply,
 1048                     (char *)&ata_identify, sizeof(ata_identify), device_info);
 1049                 try_count++;
 1050                 ioc_status = le16toh(mpi_reply.IOCStatus)
 1051                     & MPI2_IOCSTATUS_MASK;
 1052                 sas_status = mpi_reply.SASStatus;
 1053                 switch (ioc_status) {
 1054                 case MPI2_IOCSTATUS_SUCCESS:
 1055                         break;
 1056                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
 1057                         /* No sense sleeping.  this error won't get better */
 1058                         break;
 1059                 default:
 1060                         if (sc->spinup_wait_time > 0) {
 1061                                 mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds "
 1062                                     "after SATA ID error to wait for spinup\n",
 1063                                     sc->spinup_wait_time);
 1064                                 msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0,
 1065                                     "mprid", sc->spinup_wait_time * hz);
 1066                         }
 1067                 }
 1068         } while (((rc && (rc != EWOULDBLOCK)) ||
 1069             (ioc_status && (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR))
 1070             || sas_status) && (try_count < 5));
 1071 
 1072         if (rc == 0 && !ioc_status && !sas_status) {
 1073                 mpr_dprint(sc, MPR_MAPPING, "%s: got SATA identify "
 1074                     "successfully for handle = 0x%x with try_count = %d\n",
 1075                     __func__, handle, try_count);
 1076         } else {
 1077                 mpr_dprint(sc, MPR_MAPPING, "%s: handle = 0x%x failed\n",
 1078                     __func__, handle);
 1079                 return -1;
 1080         }
 1081         /* Copy & byteswap the 40 byte model number to a buffer */
 1082         for (i = 0; i < MPT2SAS_MN_LEN; i += 2) {
 1083                 buffer[i] = ((u8 *)ata_identify.model_number)[i + 1];
 1084                 buffer[i + 1] = ((u8 *)ata_identify.model_number)[i];
 1085         }
 1086         /* Copy & byteswap the 20 byte serial number to a buffer */
 1087         for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
 1088                 buffer[MPT2SAS_MN_LEN + i] =
 1089                     ((u8 *)ata_identify.serial_number)[i + 1];
 1090                 buffer[MPT2SAS_MN_LEN + i + 1] =
 1091                     ((u8 *)ata_identify.serial_number)[i];
 1092         }
 1093         bufferptr = (u32 *)buffer;
 1094         /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
 1095          * so loop through the first 56 bytes (7*8),
 1096          * and then add in the last dword.
 1097          */
 1098         hash_address.word.low  = 0;
 1099         hash_address.word.high = 0;
 1100         for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) {
 1101                 hash_address.word.low += *bufferptr;
 1102                 bufferptr++;
 1103                 hash_address.word.high += *bufferptr;
 1104                 bufferptr++;
 1105         }
 1106         /* Add the last dword */
 1107         hash_address.word.low += *bufferptr;
 1108         /* Make sure the hash doesn't start with 5, because it could clash
 1109          * with a SAS address. Change 5 to a D.
 1110          */
 1111         if ((hash_address.word.high & 0x000000F0) == (0x00000050))
 1112                 hash_address.word.high |= 0x00000080;
 1113         *sas_address = (u64)hash_address.wwid[0] << 56 |
 1114             (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 |
 1115             (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
 1116             (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] <<  8 |
 1117             (u64)hash_address.wwid[7];
 1118         if (ata_identify.rotational_speed == 1) {
 1119                 *is_SATA_SSD = 1;
 1120         }
 1121 
 1122         return 0;
 1123 }
 1124 
 1125 static int
 1126 mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
 1127     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
 1128 {
 1129         Mpi2SataPassthroughRequest_t *mpi_request;
 1130         Mpi2SataPassthroughReply_t *reply;
 1131         struct mpr_command *cm;
 1132         char *buffer;
 1133         int error = 0;
 1134 
 1135         buffer = malloc( sz, M_MPR, M_NOWAIT | M_ZERO);
 1136         if (!buffer)
 1137                 return ENOMEM;
 1138 
 1139         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1140                 free(buffer, M_MPR);
 1141                 return (EBUSY);
 1142         }
 1143         mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
 1144         bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
 1145         mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
 1146         mpi_request->VF_ID = 0;
 1147         mpi_request->DevHandle = htole16(handle);
 1148         mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
 1149             MPI2_SATA_PT_REQ_PT_FLAGS_READ);
 1150         mpi_request->DataLength = htole32(sz);
 1151         mpi_request->CommandFIS[0] = 0x27;
 1152         mpi_request->CommandFIS[1] = 0x80;
 1153         mpi_request->CommandFIS[2] =  (devinfo &
 1154             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
 1155         cm->cm_sge = &mpi_request->SGL;
 1156         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1157         cm->cm_flags = MPR_CM_FLAGS_DATAIN;
 1158         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1159         cm->cm_data = buffer;
 1160         cm->cm_length = htole32(sz);
 1161 
 1162         /*
 1163          * Start a timeout counter specifically for the SATA ID command. This
 1164          * is used to fix a problem where the FW does not send a reply sometimes
 1165          * when a bad disk is in the topology. So, this is used to timeout the
 1166          * command so that processing can continue normally.
 1167          */
 1168         mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID "
 1169             "command\n", __func__);
 1170         callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz,
 1171             mprsas_ata_id_timeout, cm);
 1172         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1173         mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID "
 1174             "command\n", __func__);
 1175         /* XXX KDM need to fix the case where this command is destroyed */
 1176         callout_stop(&cm->cm_callout);
 1177 
 1178         if (cm != NULL)
 1179                 reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
 1180         if (error || (reply == NULL)) {
 1181                 /* FIXME */
 1182                 /*
 1183                  * If the request returns an error then we need to do a diag
 1184                  * reset
 1185                  */
 1186                 printf("%s: request for page completed with error %d",
 1187                     __func__, error);
 1188                 error = ENXIO;
 1189                 goto out;
 1190         }
 1191         bcopy(buffer, id_buffer, sz);
 1192         bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
 1193         if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
 1194             MPI2_IOCSTATUS_SUCCESS) {
 1195                 printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
 1196                     __func__, reply->IOCStatus);
 1197                 error = ENXIO;
 1198                 goto out;
 1199         }
 1200 out:
 1201         /*
 1202          * If the SATA_ID_TIMEOUT flag has been set for this command, don't free
 1203          * it.  The command will be freed after sending a target reset TM. If
 1204          * the command did timeout, use EWOULDBLOCK.
 1205          */
 1206         if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
 1207                 mpr_free_command(sc, cm);
 1208         else if (error == 0)
 1209                 error = EWOULDBLOCK;
 1210         cm->cm_data = NULL;
 1211         free(buffer, M_MPR);
 1212         return (error);
 1213 }
 1214 
 1215 static void
 1216 mprsas_ata_id_timeout(void *data)
 1217 {
 1218         struct mpr_softc *sc;
 1219         struct mpr_command *cm;
 1220 
 1221         cm = (struct mpr_command *)data;
 1222         sc = cm->cm_sc;
 1223         mtx_assert(&sc->mpr_mtx, MA_OWNED);
 1224 
 1225         mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n",
 1226             __func__, cm, sc);
 1227         if ((callout_pending(&cm->cm_callout)) ||
 1228             (!callout_active(&cm->cm_callout))) {
 1229                 mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n",
 1230                     __func__);
 1231                 return;
 1232         }
 1233         callout_deactivate(&cm->cm_callout);
 1234 
 1235         /*
 1236          * Run the interrupt handler to make sure it's not pending.  This
 1237          * isn't perfect because the command could have already completed
 1238          * and been re-used, though this is unlikely.
 1239          */
 1240         mpr_intr_locked(sc);
 1241         if (cm->cm_state == MPR_CM_STATE_FREE) {
 1242                 mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n",
 1243                     __func__);
 1244                 return;
 1245         }
 1246 
 1247         mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm);
 1248 
 1249         /*
 1250          * Send wakeup() to the sleeping thread that issued this ATA ID command.
 1251          * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this
 1252          * will keep reinit() from being called. This way, an Abort Task TM can
 1253          * be issued so that the timed out command can be cleared. The Abort
 1254          * Task cannot be sent from here because the driver has not completed
 1255          * setting up targets.  Instead, the command is flagged so that special
 1256          * handling will be used to send the abort.
 1257          */
 1258         cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT;
 1259         wakeup(cm);
 1260 }
 1261 
 1262 static int
 1263 mprsas_add_pcie_device(struct mpr_softc *sc, u16 handle, u8 linkrate)
 1264 {
 1265         char devstring[80];
 1266         struct mprsas_softc *sassc;
 1267         struct mprsas_target *targ;
 1268         Mpi2ConfigReply_t mpi_reply;
 1269         Mpi26PCIeDevicePage0_t config_page;
 1270         Mpi26PCIeDevicePage2_t config_page2;
 1271         uint64_t pcie_wwid, parent_wwid = 0;
 1272         u32 device_info, parent_devinfo = 0;
 1273         unsigned int id;
 1274         int error = 0;
 1275         struct mprsas_lun *lun;
 1276 
 1277         sassc = sc->sassc;
 1278         mprsas_startup_increment(sassc);
 1279         if ((mpr_config_get_pcie_device_pg0(sc, &mpi_reply, &config_page,
 1280              MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) {
 1281                 printf("%s: error reading PCIe device page0\n", __func__);
 1282                 error = ENXIO;
 1283                 goto out;
 1284         }
 1285 
 1286         device_info = le32toh(config_page.DeviceInfo);
 1287 
 1288         if (((device_info & MPI26_PCIE_DEVINFO_PCI_SWITCH) == 0)
 1289             && (le16toh(config_page.ParentDevHandle) != 0)) {
 1290                 Mpi2ConfigReply_t tmp_mpi_reply;
 1291                 Mpi26PCIeDevicePage0_t parent_config_page;
 1292 
 1293                 if ((mpr_config_get_pcie_device_pg0(sc, &tmp_mpi_reply,
 1294                      &parent_config_page, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE,
 1295                      le16toh(config_page.ParentDevHandle)))) {
 1296                         printf("%s: error reading PCIe device %#x page0\n",
 1297                             __func__, le16toh(config_page.ParentDevHandle));
 1298                 } else {
 1299                         parent_wwid = parent_config_page.WWID.High;
 1300                         parent_wwid = (parent_wwid << 32) |
 1301                             parent_config_page.WWID.Low;
 1302                         parent_devinfo = le32toh(parent_config_page.DeviceInfo);
 1303                 }
 1304         }
 1305         /* TODO Check proper endianness */
 1306         pcie_wwid = config_page.WWID.High;
 1307         pcie_wwid = (pcie_wwid << 32) | config_page.WWID.Low;
 1308         mpr_dprint(sc, MPR_INFO, "PCIe WWID from PCIe device page0 = %jx\n",
 1309             pcie_wwid);
 1310 
 1311         if ((mpr_config_get_pcie_device_pg2(sc, &mpi_reply, &config_page2,
 1312              MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) {
 1313                 printf("%s: error reading PCIe device page2\n", __func__);
 1314                 error = ENXIO;
 1315                 goto out;
 1316         }
 1317 
 1318         id = mpr_mapping_get_tid(sc, pcie_wwid, handle);
 1319         if (id == MPR_MAP_BAD_ID) {
 1320                 mpr_dprint(sc, MPR_ERROR | MPR_INFO, "failure at %s:%d/%s()! "
 1321                     "Could not get ID for device with handle 0x%04x\n",
 1322                     __FILE__, __LINE__, __func__, handle);
 1323                 error = ENXIO;
 1324                 goto out;
 1325         }
 1326         mpr_dprint(sc, MPR_MAPPING, "%s: Target ID for added device is %d.\n",
 1327             __func__, id);
 1328 
 1329         if (mprsas_check_id(sassc, id) != 0) {
 1330                 device_printf(sc->mpr_dev, "Excluding target id %d\n", id);
 1331                 error = ENXIO;
 1332                 goto out;
 1333         }
 1334 
 1335         mpr_dprint(sc, MPR_MAPPING, "WWID from PCIe device page0 = %jx\n",
 1336             pcie_wwid);
 1337         targ = &sassc->targets[id];
 1338         targ->devinfo = device_info;
 1339         targ->encl_handle = le16toh(config_page.EnclosureHandle);
 1340         targ->encl_slot = le16toh(config_page.Slot);
 1341         targ->encl_level = config_page.EnclosureLevel;
 1342         targ->connector_name[0] = ((char *)&config_page.ConnectorName)[0];
 1343         targ->connector_name[1] = ((char *)&config_page.ConnectorName)[1];
 1344         targ->connector_name[2] = ((char *)&config_page.ConnectorName)[2];
 1345         targ->connector_name[3] = ((char *)&config_page.ConnectorName)[3];
 1346         targ->is_nvme = device_info & MPI26_PCIE_DEVINFO_NVME;
 1347         targ->MDTS = config_page2.MaximumDataTransferSize;
 1348         /*
 1349          * Assume always TRUE for encl_level_valid because there is no valid
 1350          * flag for PCIe.
 1351          */
 1352         targ->encl_level_valid = TRUE;
 1353         targ->handle = handle;
 1354         targ->parent_handle = le16toh(config_page.ParentDevHandle);
 1355         targ->sasaddr = mpr_to_u64(&config_page.WWID);
 1356         targ->parent_sasaddr = le64toh(parent_wwid);
 1357         targ->parent_devinfo = parent_devinfo;
 1358         targ->tid = id;
 1359         targ->linkrate = linkrate;
 1360         targ->flags = 0;
 1361         if ((le16toh(config_page.Flags) &
 1362             MPI26_PCIEDEV0_FLAGS_ENABLED_FAST_PATH) && 
 1363             (le16toh(config_page.Flags) &
 1364             MPI26_PCIEDEV0_FLAGS_FAST_PATH_CAPABLE)) {
 1365                 targ->scsi_req_desc_type =
 1366                     MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
 1367         }
 1368         TAILQ_INIT(&targ->commands);
 1369         TAILQ_INIT(&targ->timedout_commands);
 1370         while (!SLIST_EMPTY(&targ->luns)) {
 1371                 lun = SLIST_FIRST(&targ->luns);
 1372                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
 1373                 free(lun, M_MPR);
 1374         }
 1375         SLIST_INIT(&targ->luns);
 1376 
 1377         mpr_describe_devinfo(targ->devinfo, devstring, 80);
 1378         mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found PCIe device <%s> <%s> "
 1379             "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring,
 1380             mpr_describe_table(mpr_pcie_linkrate_names, targ->linkrate),
 1381             targ->handle, targ->encl_handle, targ->encl_slot);
 1382         if (targ->encl_level_valid) {
 1383                 mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d "
 1384                     "and connector name (%4s)\n", targ->encl_level,
 1385                     targ->connector_name);
 1386         }
 1387 #if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \
 1388     (__FreeBSD_version < 902502)
 1389         if ((sassc->flags & MPRSAS_IN_STARTUP) == 0)
 1390 #endif
 1391                 mprsas_rescan_target(sc, targ);
 1392         mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid);
 1393 
 1394 out:
 1395         mprsas_startup_decrement(sassc);
 1396         return (error);
 1397 }
 1398 
 1399 static int
 1400 mprsas_volume_add(struct mpr_softc *sc, u16 handle)
 1401 {
 1402         struct mprsas_softc *sassc;
 1403         struct mprsas_target *targ;
 1404         u64 wwid;
 1405         unsigned int id;
 1406         int error = 0;
 1407         struct mprsas_lun *lun;
 1408 
 1409         sassc = sc->sassc;
 1410         mprsas_startup_increment(sassc);
 1411         /* wwid is endian safe */
 1412         mpr_config_get_volume_wwid(sc, handle, &wwid);
 1413         if (!wwid) {
 1414                 printf("%s: invalid WWID; cannot add volume to mapping table\n",
 1415                     __func__);
 1416                 error = ENXIO;
 1417                 goto out;
 1418         }
 1419 
 1420         id = mpr_mapping_get_raid_tid(sc, wwid, handle);
 1421         if (id == MPR_MAP_BAD_ID) {
 1422                 printf("%s: could not get ID for volume with handle 0x%04x and "
 1423                     "WWID 0x%016llx\n", __func__, handle,
 1424                     (unsigned long long)wwid);
 1425                 error = ENXIO;
 1426                 goto out;
 1427         }
 1428 
 1429         targ = &sassc->targets[id];
 1430         targ->tid = id;
 1431         targ->handle = handle;
 1432         targ->devname = wwid;
 1433         TAILQ_INIT(&targ->commands);
 1434         TAILQ_INIT(&targ->timedout_commands);
 1435         while (!SLIST_EMPTY(&targ->luns)) {
 1436                 lun = SLIST_FIRST(&targ->luns);
 1437                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
 1438                 free(lun, M_MPR);
 1439         }
 1440         SLIST_INIT(&targ->luns);
 1441 #if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \
 1442     (__FreeBSD_version < 902502)
 1443         if ((sassc->flags & MPRSAS_IN_STARTUP) == 0)
 1444 #endif
 1445                 mprsas_rescan_target(sc, targ);
 1446         mpr_dprint(sc, MPR_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n",
 1447             targ->tid, wwid);
 1448 out:
 1449         mprsas_startup_decrement(sassc);
 1450         return (error);
 1451 }
 1452 
 1453 /**
 1454  * mprsas_SSU_to_SATA_devices 
 1455  * @sc: per adapter object
 1456  *
 1457  * Looks through the target list and issues a StartStopUnit SCSI command to each
 1458  * SATA direct-access device.  This helps to ensure that data corruption is
 1459  * avoided when the system is being shut down.  This must be called after the IR
 1460  * System Shutdown RAID Action is sent if in IR mode.
 1461  *
 1462  * Return nothing.
 1463  */
 1464 static void
 1465 mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
 1466 {
 1467         struct mprsas_softc *sassc = sc->sassc;
 1468         union ccb *ccb;
 1469         path_id_t pathid = cam_sim_path(sassc->sim);
 1470         target_id_t targetid;
 1471         struct mprsas_target *target;
 1472         char path_str[64];
 1473         struct timeval cur_time, start_time;
 1474 
 1475         mpr_lock(sc);
 1476 
 1477         /*
 1478          * For each target, issue a StartStopUnit command to stop the device.
 1479          */
 1480         sc->SSU_started = TRUE;
 1481         sc->SSU_refcount = 0;
 1482         for (targetid = 0; targetid < sc->max_devices; targetid++) {
 1483                 target = &sassc->targets[targetid];
 1484                 if (target->handle == 0x0) {
 1485                         continue;
 1486                 }
 1487 
 1488                 /*
 1489                  * The stop_at_shutdown flag will be set if this device is
 1490                  * a SATA direct-access end device.
 1491                  */
 1492                 if (target->stop_at_shutdown) {
 1493                         ccb = xpt_alloc_ccb_nowait();
 1494                         if (ccb == NULL) {
 1495                                 mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB "
 1496                                     "to stop unit.\n");
 1497                                 return;
 1498                         }
 1499 
 1500                         if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
 1501                             pathid, targetid, CAM_LUN_WILDCARD) !=
 1502                             CAM_REQ_CMP) {
 1503                                 mpr_dprint(sc, MPR_ERROR, "Unable to create "
 1504                                     "path to stop unit.\n");
 1505                                 xpt_free_ccb(ccb);
 1506                                 return;
 1507                         }
 1508                         xpt_path_string(ccb->ccb_h.path, path_str,
 1509                             sizeof(path_str));
 1510 
 1511                         mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s "
 1512                             "handle %d\n", path_str, target->handle);
 1513 
 1514                         /*
 1515                          * Issue a START STOP UNIT command for the target.
 1516                          * Increment the SSU counter to be used to count the
 1517                          * number of required replies.
 1518                          */
 1519                         mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n");
 1520                         sc->SSU_refcount++;
 1521                         ccb->ccb_h.target_id =
 1522                             xpt_path_target_id(ccb->ccb_h.path);
 1523                         ccb->ccb_h.ppriv_ptr1 = sassc;
 1524                         scsi_start_stop(&ccb->csio,
 1525                             /*retries*/0,
 1526                             mprsas_stop_unit_done,
 1527                             MSG_SIMPLE_Q_TAG,
 1528                             /*start*/FALSE,
 1529                             /*load/eject*/0,
 1530                             /*immediate*/FALSE,
 1531                             MPR_SENSE_LEN,
 1532                             /*timeout*/10000);
 1533                         xpt_action(ccb);
 1534                 }
 1535         }
 1536 
 1537         mpr_unlock(sc);
 1538 
 1539         /*
 1540          * Wait until all of the SSU commands have completed or time has
 1541          * expired (60 seconds).  Pause for 100ms each time through.  If any
 1542          * command times out, the target will be reset in the SCSI command
 1543          * timeout routine.
 1544          */
 1545         getmicrotime(&start_time);
 1546         while (sc->SSU_refcount) {
 1547                 pause("mprwait", hz/10);
 1548                 
 1549                 getmicrotime(&cur_time);
 1550                 if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
 1551                         mpr_dprint(sc, MPR_ERROR, "Time has expired waiting "
 1552                             "for SSU commands to complete.\n");
 1553                         break;
 1554                 }
 1555         }
 1556 }
 1557 
 1558 static void
 1559 mprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
 1560 {
 1561         struct mprsas_softc *sassc;
 1562         char path_str[64];
 1563 
 1564         if (done_ccb == NULL)
 1565                 return;
 1566 
 1567         sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1;
 1568 
 1569         xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
 1570         mpr_dprint(sassc->sc, MPR_INFO, "Completing stop unit for %s\n",
 1571             path_str);
 1572 
 1573         /*
 1574          * Nothing more to do except free the CCB and path.  If the command
 1575          * timed out, an abort reset, then target reset will be issued during
 1576          * the SCSI Command process.
 1577          */
 1578         xpt_free_path(done_ccb->ccb_h.path);
 1579         xpt_free_ccb(done_ccb);
 1580 }
 1581 
 1582 /**
 1583  * mprsas_ir_shutdown - IR shutdown notification
 1584  * @sc: per adapter object
 1585  *
 1586  * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
 1587  * the host system is shutting down.
 1588  *
 1589  * Return nothing.
 1590  */
 1591 void
 1592 mprsas_ir_shutdown(struct mpr_softc *sc)
 1593 {
 1594         u16 volume_mapping_flags;
 1595         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 1596         struct dev_mapping_table *mt_entry;
 1597         u32 start_idx, end_idx;
 1598         unsigned int id, found_volume = 0;
 1599         struct mpr_command *cm;
 1600         Mpi2RaidActionRequest_t *action;
 1601         target_id_t targetid;
 1602         struct mprsas_target *target;
 1603 
 1604         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
 1605 
 1606         /* is IR firmware build loaded? */
 1607         if (!sc->ir_firmware)
 1608                 goto out;
 1609 
 1610         /* are there any volumes?  Look at IR target IDs. */
 1611         // TODO-later, this should be looked up in the RAID config structure
 1612         // when it is implemented.
 1613         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
 1614             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
 1615         if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
 1616                 start_idx = 0;
 1617                 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
 1618                         start_idx = 1;
 1619         } else
 1620                 start_idx = sc->max_devices - sc->max_volumes;
 1621         end_idx = start_idx + sc->max_volumes - 1;
 1622 
 1623         for (id = start_idx; id < end_idx; id++) {
 1624                 mt_entry = &sc->mapping_table[id];
 1625                 if ((mt_entry->physical_id != 0) &&
 1626                     (mt_entry->missing_count == 0)) {
 1627                         found_volume = 1;
 1628                         break;
 1629                 }
 1630         }
 1631 
 1632         if (!found_volume)
 1633                 goto out;
 1634 
 1635         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1636                 printf("%s: command alloc failed\n", __func__);
 1637                 goto out;
 1638         }
 1639 
 1640         action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
 1641         action->Function = MPI2_FUNCTION_RAID_ACTION;
 1642         action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
 1643         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1644         mpr_lock(sc);
 1645         mpr_wait_command(sc, &cm, 5, CAN_SLEEP);
 1646         mpr_unlock(sc);
 1647 
 1648         /*
 1649          * Don't check for reply, just leave.
 1650          */
 1651         if (cm)
 1652                 mpr_free_command(sc, cm);
 1653 
 1654 out:
 1655         /*
 1656          * All of the targets must have the correct value set for
 1657          * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable.
 1658          *
 1659          * The possible values for the 'enable_ssu' variable are:
 1660          * 0: disable to SSD and HDD
 1661          * 1: disable only to HDD (default)
 1662          * 2: disable only to SSD
 1663          * 3: enable to SSD and HDD
 1664          * anything else will default to 1.
 1665          */
 1666         for (targetid = 0; targetid < sc->max_devices; targetid++) {
 1667                 target = &sc->sassc->targets[targetid];
 1668                 if (target->handle == 0x0) {
 1669                         continue;
 1670                 }
 1671 
 1672                 if (target->supports_SSU) {
 1673                         switch (sc->enable_ssu) {
 1674                         case MPR_SSU_DISABLE_SSD_DISABLE_HDD:
 1675                                 target->stop_at_shutdown = FALSE;
 1676                                 break;
 1677                         case MPR_SSU_DISABLE_SSD_ENABLE_HDD:
 1678                                 target->stop_at_shutdown = TRUE;
 1679                                 if (target->flags & MPR_TARGET_IS_SATA_SSD) {
 1680                                         target->stop_at_shutdown = FALSE;
 1681                                 }
 1682                                 break;
 1683                         case MPR_SSU_ENABLE_SSD_ENABLE_HDD:
 1684                                 target->stop_at_shutdown = TRUE;
 1685                                 break;
 1686                         case MPR_SSU_ENABLE_SSD_DISABLE_HDD:
 1687                         default:
 1688                                 target->stop_at_shutdown = TRUE;
 1689                                 if ((target->flags &
 1690                                     MPR_TARGET_IS_SATA_SSD) == 0) {
 1691                                         target->stop_at_shutdown = FALSE;
 1692                                 }
 1693                                 break;
 1694                         }
 1695                 }
 1696         }
 1697         mprsas_SSU_to_SATA_devices(sc);
 1698 }

Cache object: 96edb68185a21549cdad09d2dea20dce


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