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_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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2011-2015 LSI Corp.
    5  * Copyright (c) 2013-2015 Avago Technologies
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/12.0/sys/dev/mps/mps_sas_lsi.c 337725 2018-08-13 19:59:42Z imp $");
   34 
   35 /* Communications core for Avago Technologies (LSI) MPT2 */
   36 
   37 /* TODO Move headers to mpsvar */
   38 #include <sys/types.h>
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/selinfo.h>
   43 #include <sys/module.h>
   44 #include <sys/bus.h>
   45 #include <sys/conf.h>
   46 #include <sys/bio.h>
   47 #include <sys/malloc.h>
   48 #include <sys/uio.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/endian.h>
   51 #include <sys/proc.h>
   52 #include <sys/queue.h>
   53 #include <sys/kthread.h>
   54 #include <sys/taskqueue.h>
   55 #include <sys/sbuf.h>
   56 #include <sys/reboot.h>
   57 
   58 #include <machine/bus.h>
   59 #include <machine/resource.h>
   60 #include <sys/rman.h>
   61 
   62 #include <machine/stdarg.h>
   63 
   64 #include <cam/cam.h>
   65 #include <cam/cam_ccb.h>
   66 #include <cam/cam_debug.h>
   67 #include <cam/cam_sim.h>
   68 #include <cam/cam_xpt_sim.h>
   69 #include <cam/cam_xpt_periph.h>
   70 #include <cam/cam_periph.h>
   71 #include <cam/scsi/scsi_all.h>
   72 #include <cam/scsi/scsi_message.h>
   73 
   74 #include <dev/mps/mpi/mpi2_type.h>
   75 #include <dev/mps/mpi/mpi2.h>
   76 #include <dev/mps/mpi/mpi2_ioc.h>
   77 #include <dev/mps/mpi/mpi2_sas.h>
   78 #include <dev/mps/mpi/mpi2_cnfg.h>
   79 #include <dev/mps/mpi/mpi2_init.h>
   80 #include <dev/mps/mpi/mpi2_raid.h>
   81 #include <dev/mps/mpi/mpi2_tool.h>
   82 #include <dev/mps/mps_ioctl.h>
   83 #include <dev/mps/mpsvar.h>
   84 #include <dev/mps/mps_table.h>
   85 #include <dev/mps/mps_sas.h>
   86 
   87 /* For Hashed SAS Address creation for SATA Drives */
   88 #define MPT2SAS_SN_LEN 20
   89 #define MPT2SAS_MN_LEN 40
   90 
   91 struct mps_fw_event_work {
   92         u16                     event;
   93         void                    *event_data;
   94         TAILQ_ENTRY(mps_fw_event_work)  ev_link;
   95 };
   96 
   97 union _sata_sas_address {
   98         u8 wwid[8];
   99         struct {
  100                 u32 high;
  101                 u32 low;
  102         } word;
  103 };
  104 
  105 /*
  106  * define the IDENTIFY DEVICE structure
  107  */
  108 struct _ata_identify_device_data {
  109         u16 reserved1[10];      /* 0-9 */
  110         u16 serial_number[10];  /* 10-19 */
  111         u16 reserved2[7];       /* 20-26 */
  112         u16 model_number[20];   /* 27-46*/
  113         u16 reserved3[170];     /* 47-216 */
  114         u16 rotational_speed;   /* 217 */
  115         u16 reserved4[38];      /* 218-255 */
  116 };
  117 static u32 event_count;
  118 static void mpssas_fw_work(struct mps_softc *sc,
  119     struct mps_fw_event_work *fw_event);
  120 static void mpssas_fw_event_free(struct mps_softc *,
  121     struct mps_fw_event_work *);
  122 static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate);
  123 static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
  124     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
  125     u32 devinfo);
  126 static void mpssas_ata_id_timeout(void *data);
  127 int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
  128     u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
  129 static int mpssas_volume_add(struct mps_softc *sc,
  130     u16 handle);
  131 static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc, int howto);
  132 static void mpssas_stop_unit_done(struct cam_periph *periph,
  133     union ccb *done_ccb);
  134 
  135 void
  136 mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
  137     MPI2_EVENT_NOTIFICATION_REPLY *event)
  138 {
  139         struct mps_fw_event_work *fw_event;
  140         u16 sz;
  141 
  142         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  143         MPS_DPRINT_EVENT(sc, sas, event);
  144         mpssas_record_event(sc, event);
  145 
  146         fw_event = malloc(sizeof(struct mps_fw_event_work), M_MPT2,
  147              M_ZERO|M_NOWAIT);
  148         if (!fw_event) {
  149                 printf("%s: allocate failed for fw_event\n", __func__);
  150                 return;
  151         }
  152         sz = le16toh(event->EventDataLength) * 4;
  153         fw_event->event_data = malloc(sz, M_MPT2, M_ZERO|M_NOWAIT);
  154         if (!fw_event->event_data) {
  155                 printf("%s: allocate failed for event_data\n", __func__);
  156                 free(fw_event, M_MPT2);
  157                 return;
  158         }
  159 
  160         bcopy(event->EventData, fw_event->event_data, sz);
  161         fw_event->event = event->Event;
  162         if ((event->Event == MPI2_EVENT_SAS_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_IR_CONFIGURATION_CHANGE_LIST) &&
  175             sc->wait_for_port_enable)
  176                 mpssas_startup_increment(sc->sassc);
  177 
  178         TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
  179         taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
  180 
  181 }
  182 
  183 static void
  184 mpssas_fw_event_free(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
  185 {
  186 
  187         free(fw_event->event_data, M_MPT2);
  188         free(fw_event, M_MPT2);
  189 }
  190 
  191 /**
  192  * _mps_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 mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
  201 {
  202         struct mpssas_softc *sassc;
  203         sassc = sc->sassc;
  204 
  205         mps_dprint(sc, MPS_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                 int i;
  213 
  214                 data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
  215                     fw_event->event_data;
  216 
  217                 mps_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 (mpssas_add_device(sc,
  224                                     le16toh(phy->AttachedDevHandle),
  225                                     phy->LinkRate)){
  226                                         mps_dprint(sc, MPS_ERROR, "%s: "
  227                                             "failed to add device with handle "
  228                                             "0x%x\n", __func__,
  229                                             le16toh(phy->AttachedDevHandle));
  230                                         mpssas_prepare_remove(sassc, le16toh(
  231                                                 phy->AttachedDevHandle));
  232                                 }
  233                                 break;
  234                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
  235                                 mpssas_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                  * mpssas_evt_handler.  Decrement it here because the event has
  248                  * been processed.
  249                  */
  250                 mpssas_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                         mps_dprint(sc, MPS_TRACE,"SAS discovery start event\n");
  261                 if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) {
  262                         mps_dprint(sc, MPS_TRACE,"SAS discovery stop event\n");
  263                         sassc->flags &= ~MPSSAS_IN_DISCOVERY;
  264                         mpssas_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                 mps_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;
  282                 Mpi2EventDataIrConfigChangeList_t *event_data;
  283                 struct mpssas_target *targ;
  284                 unsigned int id;
  285 
  286                 event_data = fw_event->event_data;
  287                 foreign_config = (le32toh(event_data->Flags) &
  288                     MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
  289 
  290                 element =
  291                     (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
  292                 id = mps_mapping_get_raid_tid_from_handle(sc,
  293                     element->VolDevHandle);
  294 
  295                 mps_mapping_ir_config_change_event(sc, event_data);
  296 
  297                 for (i = 0; i < event_data->NumElements; i++, element++) {
  298                         switch (element->ReasonCode) {
  299                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
  300                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
  301                                 if (!foreign_config) {
  302                                         if (mpssas_volume_add(sc,
  303                                             le16toh(element->VolDevHandle))){
  304                                                 printf("%s: failed to add RAID "
  305                                                     "volume with handle 0x%x\n",
  306                                                     __func__, le16toh(element->
  307                                                     VolDevHandle));
  308                                         }
  309                                 }
  310                                 break;
  311                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
  312                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
  313                                 /*
  314                                  * Rescan after volume is deleted or removed.
  315                                  */
  316                                 if (!foreign_config) {
  317                                         if (id == MPS_MAP_BAD_ID) {
  318                                                 printf("%s: could not get ID "
  319                                                     "for volume with handle "
  320                                                     "0x%04x\n", __func__,
  321                                                     le16toh(element->VolDevHandle));
  322                                                 break;
  323                                         }
  324                                         
  325                                         targ = &sassc->targets[id];
  326                                         targ->handle = 0x0;
  327                                         targ->encl_slot = 0x0;
  328                                         targ->encl_handle = 0x0;
  329                                         targ->exp_dev_handle = 0x0;
  330                                         targ->phy_num = 0x0;
  331                                         targ->linkrate = 0x0;
  332                                         mpssas_rescan_target(sc, targ);
  333                                         printf("RAID target id 0x%x removed\n",
  334                                             targ->tid);
  335                                 }
  336                                 break;
  337                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
  338                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
  339                                 /*
  340                                  * Phys Disk of a volume has been created.  Hide
  341                                  * it from the OS.
  342                                  */
  343                                 targ = mpssas_find_target_by_handle(sassc, 0,
  344                                     element->PhysDiskDevHandle);
  345                                 if (targ == NULL) 
  346                                         break;
  347                                 
  348                                 /*
  349                                  * Set raid component flags only if it is not
  350                                  * WD. OR WrapDrive with
  351                                  * WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in
  352                                  * NVRAM
  353                                  */
  354                                 if((!sc->WD_available) ||
  355                                 ((sc->WD_available && 
  356                                 (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
  357                                 (sc->WD_valid_config && (sc->WD_hide_expose ==
  358                                 MPS_WD_HIDE_IF_VOLUME)))) {
  359                                         targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
  360                                 }
  361                                 mpssas_rescan_target(sc, targ);
  362                                 
  363                                 break;
  364                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
  365                                 /*
  366                                  * Phys Disk of a volume has been deleted.
  367                                  * Expose it to the OS.
  368                                  */
  369                                 if (mpssas_add_device(sc,
  370                                     le16toh(element->PhysDiskDevHandle), 0)){
  371                                         printf("%s: failed to add device with "
  372                                             "handle 0x%x\n", __func__,
  373                                             le16toh(element->PhysDiskDevHandle));
  374                                         mpssas_prepare_remove(sassc, le16toh(element->
  375                                             PhysDiskDevHandle));
  376                                 }
  377                                 break;
  378                         }
  379                 }
  380                 /*
  381                  * refcount was incremented for this event in
  382                  * mpssas_evt_handler.  Decrement it here because the event has
  383                  * been processed.
  384                  */
  385                 mpssas_startup_decrement(sassc);
  386                 break;
  387         }
  388         case MPI2_EVENT_IR_VOLUME:
  389         {
  390                 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
  391 
  392                 /*
  393                  * Informational only.
  394                  */
  395                 mps_dprint(sc, MPS_EVENT, "Received IR Volume event:\n");
  396                 switch (event_data->ReasonCode) {
  397                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
  398                         mps_dprint(sc, MPS_EVENT, "   Volume Settings "
  399                             "changed from 0x%x to 0x%x for Volome with "
  400                             "handle 0x%x", le32toh(event_data->PreviousValue),
  401                             le32toh(event_data->NewValue),
  402                             le16toh(event_data->VolDevHandle));
  403                         break;
  404                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
  405                         mps_dprint(sc, MPS_EVENT, "   Volume Status "
  406                             "changed from 0x%x to 0x%x for Volome with "
  407                             "handle 0x%x", le32toh(event_data->PreviousValue),
  408                             le32toh(event_data->NewValue),
  409                             le16toh(event_data->VolDevHandle));
  410                         break;
  411                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
  412                         mps_dprint(sc, MPS_EVENT, "   Volume State "
  413                             "changed from 0x%x to 0x%x for Volome with "
  414                             "handle 0x%x", le32toh(event_data->PreviousValue),
  415                             le32toh(event_data->NewValue),
  416                             le16toh(event_data->VolDevHandle));
  417                                 u32 state;
  418                                 struct mpssas_target *targ;
  419                                 state = le32toh(event_data->NewValue);
  420                                 switch (state) {
  421                                 case MPI2_RAID_VOL_STATE_MISSING:
  422                                 case MPI2_RAID_VOL_STATE_FAILED:
  423                                         mpssas_prepare_volume_remove(sassc, event_data->
  424                                                         VolDevHandle);
  425                                         break;
  426                  
  427                                 case MPI2_RAID_VOL_STATE_ONLINE:
  428                                 case MPI2_RAID_VOL_STATE_DEGRADED:
  429                                 case MPI2_RAID_VOL_STATE_OPTIMAL:
  430                                         targ = mpssas_find_target_by_handle(sassc, 0, event_data->VolDevHandle);
  431                                         if (targ) {
  432                                                 printf("%s %d: Volume handle 0x%x is already added \n",
  433                                                                 __func__, __LINE__ , event_data->VolDevHandle);
  434                                                 break;
  435                                         }
  436                                         if (mpssas_volume_add(sc, le16toh(event_data->VolDevHandle))) {
  437                                                 printf("%s: failed to add RAID "
  438                                                         "volume with handle 0x%x\n",
  439                                                         __func__, le16toh(event_data->
  440                                                         VolDevHandle));
  441                                         }
  442                                         break;
  443                                 default:
  444                                         break;
  445                                 }
  446                         break;
  447                 default:
  448                         break;
  449                 }
  450                 break;
  451         }
  452         case MPI2_EVENT_IR_PHYSICAL_DISK:
  453         {
  454                 Mpi2EventDataIrPhysicalDisk_t *event_data =
  455                     fw_event->event_data;
  456                 struct mpssas_target *targ;
  457 
  458                 /*
  459                  * Informational only.
  460                  */
  461                 mps_dprint(sc, MPS_EVENT, "Received IR Phys Disk event:\n");
  462                 switch (event_data->ReasonCode) {
  463                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
  464                         mps_dprint(sc, MPS_EVENT, "   Phys Disk Settings "
  465                             "changed from 0x%x to 0x%x for Phys Disk Number "
  466                             "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
  467                             "%d", le32toh(event_data->PreviousValue),
  468                             le32toh(event_data->NewValue),
  469                                 event_data->PhysDiskNum,
  470                             le16toh(event_data->PhysDiskDevHandle),
  471                             le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
  472                         break;
  473                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
  474                         mps_dprint(sc, MPS_EVENT, "   Phys Disk Status changed "
  475                             "from 0x%x to 0x%x for Phys Disk Number %d and "
  476                             "handle 0x%x at Enclosure handle 0x%x, Slot %d",
  477                                 le32toh(event_data->PreviousValue),
  478                             le32toh(event_data->NewValue), event_data->PhysDiskNum,
  479                             le16toh(event_data->PhysDiskDevHandle),
  480                             le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
  481                         break;
  482                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
  483                         mps_dprint(sc, MPS_EVENT, "   Phys Disk State changed "
  484                             "from 0x%x to 0x%x for Phys Disk Number %d and "
  485                             "handle 0x%x at Enclosure handle 0x%x, Slot %d",
  486                                 le32toh(event_data->PreviousValue),
  487                             le32toh(event_data->NewValue), event_data->PhysDiskNum,
  488                             le16toh(event_data->PhysDiskDevHandle),
  489                             le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
  490                         switch (event_data->NewValue) {
  491                                 case MPI2_RAID_PD_STATE_ONLINE:
  492                                 case MPI2_RAID_PD_STATE_DEGRADED:
  493                                 case MPI2_RAID_PD_STATE_REBUILDING:
  494                                 case MPI2_RAID_PD_STATE_OPTIMAL:
  495                                 case MPI2_RAID_PD_STATE_HOT_SPARE:
  496                                         targ = mpssas_find_target_by_handle(sassc, 0, 
  497                                                         event_data->PhysDiskDevHandle);
  498                                         if (targ) {
  499                                                 if(!sc->WD_available) {
  500                                                         targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
  501                                                         printf("%s %d: Found Target for handle 0x%x.  \n",
  502                                                         __func__, __LINE__ , event_data->PhysDiskDevHandle);
  503                                                 } else if ((sc->WD_available && 
  504                                                         (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
  505                                                         (sc->WD_valid_config && (sc->WD_hide_expose ==
  506                                                         MPS_WD_HIDE_IF_VOLUME))) {
  507                                                         targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
  508                                                         printf("%s %d: WD: Found Target for handle 0x%x.  \n",
  509                                                         __func__, __LINE__ , event_data->PhysDiskDevHandle);
  510                                                 }
  511                                         }               
  512                                 break;
  513                                 case MPI2_RAID_PD_STATE_OFFLINE:
  514                                 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
  515                                 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
  516                                 default:
  517                                         targ = mpssas_find_target_by_handle(sassc, 0, 
  518                                                         event_data->PhysDiskDevHandle);
  519                                         if (targ) {
  520                                                 targ->flags |= ~MPS_TARGET_FLAGS_RAID_COMPONENT;
  521                                                 printf("%s %d: Found Target for handle 0x%x.  \n",
  522                                                 __func__, __LINE__ , event_data->PhysDiskDevHandle);
  523                                         }
  524                                 break;
  525                         }
  526                 default:
  527                         break;
  528                 }
  529                 break;
  530         }
  531         case MPI2_EVENT_IR_OPERATION_STATUS:
  532         {
  533                 Mpi2EventDataIrOperationStatus_t *event_data =
  534                     fw_event->event_data;
  535 
  536                 /*
  537                  * Informational only.
  538                  */
  539                 mps_dprint(sc, MPS_EVENT, "Received IR Op Status event:\n");
  540                 mps_dprint(sc, MPS_EVENT, "   RAID Operation of %d is %d "
  541                     "percent complete for Volume with handle 0x%x",
  542                     event_data->RAIDOperation, event_data->PercentComplete,
  543                     le16toh(event_data->VolDevHandle));
  544                 break;
  545         }
  546         case MPI2_EVENT_LOG_ENTRY_ADDED:
  547         {
  548                 pMpi2EventDataLogEntryAdded_t   logEntry;
  549                 uint16_t                        logQualifier;
  550                 uint8_t                         logCode;
  551 
  552                 logEntry = (pMpi2EventDataLogEntryAdded_t)fw_event->event_data;
  553                 logQualifier = logEntry->LogEntryQualifier;
  554 
  555                 if (logQualifier == MPI2_WD_LOG_ENTRY) {
  556                         logCode = logEntry->LogData[0];
  557 
  558                         switch (logCode) {
  559                         case MPI2_WD_SSD_THROTTLING:
  560                                 printf("WarpDrive Warning: IO Throttling has "
  561                                     "occurred in the WarpDrive subsystem. "
  562                                     "Check WarpDrive documentation for "
  563                                     "additional details\n");
  564                                 break;
  565                         case MPI2_WD_DRIVE_LIFE_WARN:
  566                                 printf("WarpDrive Warning: Program/Erase "
  567                                     "Cycles for the WarpDrive subsystem in "
  568                                     "degraded range. Check WarpDrive "
  569                                     "documentation for additional details\n");
  570                                 break;
  571                         case MPI2_WD_DRIVE_LIFE_DEAD:
  572                                 printf("WarpDrive Fatal Error: There are no "
  573                                     "Program/Erase Cycles for the WarpDrive "
  574                                     "subsystem. The storage device will be in "
  575                                     "read-only mode. Check WarpDrive "
  576                                     "documentation for additional details\n");
  577                                 break;
  578                         case MPI2_WD_RAIL_MON_FAIL:
  579                                 printf("WarpDrive Fatal Error: The Backup Rail "
  580                                     "Monitor has failed on the WarpDrive "
  581                                     "subsystem. Check WarpDrive documentation "
  582                                     "for additional details\n");
  583                                 break;
  584                         default:
  585                                 break;
  586                         }
  587                 }
  588                 break;
  589         }
  590         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
  591         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
  592         default:
  593                 mps_dprint(sc, MPS_TRACE,"Unhandled event 0x%0X\n",
  594                     fw_event->event);
  595                 break;
  596 
  597         }
  598         mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event);
  599         mpssas_fw_event_free(sc, fw_event);
  600 }
  601 
  602 void
  603 mpssas_firmware_event_work(void *arg, int pending)
  604 {
  605         struct mps_fw_event_work *fw_event;
  606         struct mps_softc *sc;
  607 
  608         sc = (struct mps_softc *)arg;
  609         mps_lock(sc);
  610         while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
  611                 TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
  612                 mpssas_fw_work(sc, fw_event);
  613         }
  614         mps_unlock(sc);
  615 }
  616 
  617 static int
  618 mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
  619         char devstring[80];
  620         struct mpssas_softc *sassc;
  621         struct mpssas_target *targ;
  622         Mpi2ConfigReply_t mpi_reply;
  623         Mpi2SasDevicePage0_t config_page;
  624         uint64_t sas_address;
  625         uint64_t parent_sas_address = 0;
  626         u32 device_info, parent_devinfo = 0;
  627         unsigned int id;
  628         int ret = 1, error = 0, i;
  629         struct mpssas_lun *lun;
  630         u8 is_SATA_SSD = 0;
  631         struct mps_command *cm;
  632 
  633         sassc = sc->sassc;
  634         mpssas_startup_increment(sassc);
  635         if (mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page,
  636             MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle) != 0) {
  637                 mps_dprint(sc, MPS_INFO|MPS_MAPPING|MPS_FAULT,
  638                     "Error reading SAS device %#x page0, iocstatus= 0x%x\n",
  639                     handle, mpi_reply.IOCStatus);
  640                 error = ENXIO;
  641                 goto out;
  642         }
  643 
  644         device_info = le32toh(config_page.DeviceInfo);
  645 
  646         if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
  647          && (le16toh(config_page.ParentDevHandle) != 0)) {
  648                 Mpi2ConfigReply_t tmp_mpi_reply;
  649                 Mpi2SasDevicePage0_t parent_config_page;
  650 
  651                 if (mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply,
  652                     &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
  653                     le16toh(config_page.ParentDevHandle)) != 0) {
  654                         mps_dprint(sc, MPS_MAPPING|MPS_FAULT,
  655                             "Error reading parent SAS device %#x page0, "
  656                             "iocstatus= 0x%x\n",
  657                             le16toh(config_page.ParentDevHandle),
  658                             tmp_mpi_reply.IOCStatus);
  659                 } else {
  660                         parent_sas_address = parent_config_page.SASAddress.High;
  661                         parent_sas_address = (parent_sas_address << 32) |
  662                                 parent_config_page.SASAddress.Low;
  663                         parent_devinfo = le32toh(parent_config_page.DeviceInfo);
  664                 }
  665         }
  666         /* TODO Check proper endianness */
  667         sas_address = config_page.SASAddress.High;
  668         sas_address = (sas_address << 32) | config_page.SASAddress.Low;
  669         mps_dprint(sc, MPS_MAPPING, "Handle 0x%04x SAS Address from SAS device "
  670             "page0 = %jx\n", handle, sas_address);
  671 
  672         /*
  673          * Always get SATA Identify information because this is used to
  674          * determine if Start/Stop Unit should be sent to the drive when the
  675          * system is shutdown.
  676          */
  677         if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
  678                 ret = mpssas_get_sas_address_for_sata_disk(sc, &sas_address,
  679                     handle, device_info, &is_SATA_SSD);
  680                 if (ret) {
  681                         mps_dprint(sc, MPS_MAPPING|MPS_ERROR,
  682                             "%s: failed to get disk type (SSD or HDD) for SATA "
  683                             "device with handle 0x%04x\n",
  684                             __func__, handle);
  685                 } else {
  686                         mps_dprint(sc, MPS_MAPPING, "Handle 0x%04x SAS Address "
  687                             "from SATA device = %jx\n", handle, sas_address);
  688                 }
  689         }
  690 
  691         /*
  692          * use_phynum:
  693          *  1 - use the PhyNum field as a fallback to the mapping logic
  694          *  0 - never use the PhyNum field
  695          * -1 - only use the PhyNum field
  696          *
  697          * Note that using the Phy number to map a device can cause device adds
  698          * to fail if multiple enclosures/expanders are in the topology. For
  699          * example, if two devices are in the same slot number in two different
  700          * enclosures within the topology, only one of those devices will be
  701          * added. PhyNum mapping should not be used if multiple enclosures are
  702          * in the topology.
  703          */
  704         id = MPS_MAP_BAD_ID;
  705         if (sc->use_phynum != -1) 
  706                 id = mps_mapping_get_tid(sc, sas_address, handle);
  707         if (id == MPS_MAP_BAD_ID) {
  708                 if ((sc->use_phynum == 0)
  709                  || ((id = config_page.PhyNum) > sassc->maxtargets)) {
  710                         mps_dprint(sc, MPS_INFO, "failure at %s:%d/%s()! "
  711                             "Could not get ID for device with handle 0x%04x\n",
  712                             __FILE__, __LINE__, __func__, handle);
  713                         error = ENXIO;
  714                         goto out;
  715                 }
  716         }
  717         mps_dprint(sc, MPS_MAPPING, "%s: Target ID for added device is %d.\n",
  718             __func__, id);
  719 
  720         /*
  721          * Only do the ID check and reuse check if the target is not from a
  722          * RAID Component. For Physical Disks of a Volume, the ID will be reused
  723          * when a volume is deleted because the mapping entry for the PD will
  724          * still be in the mapping table. The ID check should not be done here
  725          * either since this PD is already being used.
  726          */
  727         targ = &sassc->targets[id];
  728         if (!(targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT)) {
  729                 if (mpssas_check_id(sassc, id) != 0) {
  730                         mps_dprint(sc, MPS_MAPPING|MPS_INFO,
  731                             "Excluding target id %d\n", id);
  732                         error = ENXIO;
  733                         goto out;
  734                 }
  735 
  736                 if (targ->handle != 0x0) {
  737                         mps_dprint(sc, MPS_MAPPING, "Attempting to reuse "
  738                             "target id %d handle 0x%04x\n", id, targ->handle);
  739                         error = ENXIO;
  740                         goto out;
  741                 }
  742         }
  743 
  744         targ->devinfo = device_info;
  745         targ->devname = le32toh(config_page.DeviceName.High);
  746         targ->devname = (targ->devname << 32) | 
  747             le32toh(config_page.DeviceName.Low);
  748         targ->encl_handle = le16toh(config_page.EnclosureHandle);
  749         targ->encl_slot = le16toh(config_page.Slot);
  750         targ->handle = handle;
  751         targ->parent_handle = le16toh(config_page.ParentDevHandle);
  752         targ->sasaddr = mps_to_u64(&config_page.SASAddress);
  753         targ->parent_sasaddr = le64toh(parent_sas_address);
  754         targ->parent_devinfo = parent_devinfo;
  755         targ->tid = id;
  756         targ->linkrate = (linkrate>>4);
  757         targ->flags = 0;
  758         if (is_SATA_SSD) {
  759                 targ->flags = MPS_TARGET_IS_SATA_SSD;
  760         }
  761         TAILQ_INIT(&targ->commands);
  762         TAILQ_INIT(&targ->timedout_commands);
  763         while(!SLIST_EMPTY(&targ->luns)) {
  764                 lun = SLIST_FIRST(&targ->luns);
  765                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
  766                 free(lun, M_MPT2);
  767         }
  768         SLIST_INIT(&targ->luns);
  769 
  770         mps_describe_devinfo(targ->devinfo, devstring, 80);
  771         mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n",
  772             devstring, mps_describe_table(mps_linkrate_names, targ->linkrate),
  773             targ->handle, targ->encl_handle, targ->encl_slot);
  774 
  775 #if __FreeBSD_version < 1000039
  776         if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
  777 #endif
  778                 mpssas_rescan_target(sc, targ);
  779         mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid);
  780 
  781         /*
  782          * Check all commands to see if the SATA_ID_TIMEOUT flag has been set.
  783          * If so, send a Target Reset TM to the target that was just created.
  784          * An Abort Task TM should be used instead of a Target Reset, but that
  785          * would be much more difficult because targets have not been fully
  786          * discovered yet, and LUN's haven't been setup.  So, just reset the
  787          * target instead of the LUN.
  788          */
  789         for (i = 1; i < sc->num_reqs; i++) {
  790                 cm = &sc->commands[i];
  791                 if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
  792                         targ->timeouts++;
  793                         cm->cm_state = MPS_CM_STATE_TIMEDOUT;
  794 
  795                         if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) {
  796                                 mps_dprint(sc, MPS_INFO, "%s: sending Target "
  797                                     "Reset for stuck SATA identify command "
  798                                     "(cm = %p)\n", __func__, cm);
  799                                 targ->tm->cm_targ = targ;
  800                                 mpssas_send_reset(sc, targ->tm,
  801                                     MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
  802                         } else {
  803                                 mps_dprint(sc, MPS_ERROR, "Failed to allocate "
  804                                     "tm for Target Reset after SATA ID command "
  805                                     "timed out (cm %p)\n", cm);
  806                         }
  807                         /*
  808                          * No need to check for more since the target is
  809                          * already being reset.
  810                          */
  811                         break;
  812                 }
  813         }
  814 out:
  815         /*
  816          * Free the commands that may not have been freed from the SATA ID call
  817          */
  818         for (i = 1; i < sc->num_reqs; i++) {
  819                 cm = &sc->commands[i];
  820                 if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
  821                         mps_free_command(sc, cm);
  822                 }
  823         }
  824         mpssas_startup_decrement(sassc);
  825         return (error);
  826 }
  827         
  828 int
  829 mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
  830     u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD)
  831 {
  832         Mpi2SataPassthroughReply_t mpi_reply;
  833         int i, rc, try_count;
  834         u32 *bufferptr;
  835         union _sata_sas_address hash_address;
  836         struct _ata_identify_device_data ata_identify;
  837         u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN];
  838         u32 ioc_status;
  839         u8 sas_status;
  840 
  841         memset(&ata_identify, 0, sizeof(ata_identify));
  842         try_count = 0;
  843         do {
  844                 rc = mpssas_get_sata_identify(sc, handle, &mpi_reply,
  845                     (char *)&ata_identify, sizeof(ata_identify), device_info);
  846                 try_count++;
  847                 ioc_status = le16toh(mpi_reply.IOCStatus)
  848                     & MPI2_IOCSTATUS_MASK;
  849                 sas_status = mpi_reply.SASStatus;
  850                 switch (ioc_status) {
  851                 case MPI2_IOCSTATUS_SUCCESS:
  852                         break;
  853                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
  854                         /* No sense sleeping.  this error won't get better */
  855                         break;
  856                 default:
  857                         if (sc->spinup_wait_time > 0) {
  858                                 mps_dprint(sc, MPS_INFO, "Sleeping %d seconds "
  859                                     "after SATA ID error to wait for spinup\n",
  860                                     sc->spinup_wait_time);
  861                                 msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
  862                                     "mpsid", sc->spinup_wait_time * hz);
  863                         }
  864                 }
  865         } while (((rc && (rc != EWOULDBLOCK)) ||
  866                  (ioc_status && 
  867                   (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR))
  868                || sas_status) && (try_count < 5));
  869 
  870         if (rc == 0 && !ioc_status && !sas_status) {
  871                 mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify "
  872                     "successfully for handle = 0x%x with try_count = %d\n",
  873                     __func__, handle, try_count);
  874         } else {
  875                 mps_dprint(sc, MPS_MAPPING, "%s: handle = 0x%x failed\n",
  876                     __func__, handle);
  877                 return -1;
  878         }
  879         /* Copy & byteswap the 40 byte model number to a buffer */
  880         for (i = 0; i < MPT2SAS_MN_LEN; i += 2) {
  881                 buffer[i] = ((u8 *)ata_identify.model_number)[i + 1];
  882                 buffer[i + 1] = ((u8 *)ata_identify.model_number)[i];
  883         }
  884         /* Copy & byteswap the 20 byte serial number to a buffer */
  885         for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
  886                 buffer[MPT2SAS_MN_LEN + i] =
  887                     ((u8 *)ata_identify.serial_number)[i + 1];
  888                 buffer[MPT2SAS_MN_LEN + i + 1] =
  889                     ((u8 *)ata_identify.serial_number)[i];
  890         }
  891         bufferptr = (u32 *)buffer;
  892         /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
  893          * so loop through the first 56 bytes (7*8),
  894          * and then add in the last dword.
  895          */
  896         hash_address.word.low  = 0;
  897         hash_address.word.high = 0;
  898         for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) {
  899                 hash_address.word.low += *bufferptr;
  900                 bufferptr++;
  901                 hash_address.word.high += *bufferptr;
  902                 bufferptr++;
  903         }
  904         /* Add the last dword */
  905         hash_address.word.low += *bufferptr;
  906         /* Make sure the hash doesn't start with 5, because it could clash
  907          * with a SAS address. Change 5 to a D.
  908          */
  909         if ((hash_address.word.high & 0x000000F0) == (0x00000050))
  910                 hash_address.word.high |= 0x00000080;
  911         *sas_address = (u64)hash_address.wwid[0] << 56 |
  912             (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 |
  913             (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
  914             (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] <<  8 |
  915             (u64)hash_address.wwid[7];
  916         if (ata_identify.rotational_speed == 1) {
  917                 *is_SATA_SSD = 1;
  918         }
  919 
  920         return 0;
  921 }
  922 
  923 static int
  924 mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
  925     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
  926 {
  927         Mpi2SataPassthroughRequest_t *mpi_request;
  928         Mpi2SataPassthroughReply_t *reply = NULL;
  929         struct mps_command *cm;
  930         char *buffer;
  931         int error = 0;
  932 
  933         buffer = malloc( sz, M_MPT2, M_NOWAIT | M_ZERO);
  934         if (!buffer)
  935                 return ENOMEM;
  936 
  937         if ((cm = mps_alloc_command(sc)) == NULL) {
  938                 free(buffer, M_MPT2);
  939                 return (EBUSY);
  940         }
  941         mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
  942         bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
  943         mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
  944         mpi_request->VF_ID = 0;
  945         mpi_request->DevHandle = htole16(handle);
  946         mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
  947             MPI2_SATA_PT_REQ_PT_FLAGS_READ);
  948         mpi_request->DataLength = htole32(sz);
  949         mpi_request->CommandFIS[0] = 0x27;
  950         mpi_request->CommandFIS[1] = 0x80;
  951         mpi_request->CommandFIS[2] =  (devinfo &
  952             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
  953         cm->cm_sge = &mpi_request->SGL;
  954         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  955         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
  956         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  957         cm->cm_data = buffer;
  958         cm->cm_length = htole32(sz);
  959 
  960         /*
  961          * Start a timeout counter specifically for the SATA ID command. This
  962          * is used to fix a problem where the FW does not send a reply sometimes
  963          * when a bad disk is in the topology. So, this is used to timeout the
  964          * command so that processing can continue normally.
  965          */
  966         mps_dprint(sc, MPS_XINFO, "%s start timeout counter for SATA ID "
  967             "command\n", __func__);
  968         callout_reset(&cm->cm_callout, MPS_ATA_ID_TIMEOUT * hz,
  969             mpssas_ata_id_timeout, cm);
  970         error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
  971         mps_dprint(sc, MPS_XINFO, "%s stop timeout counter for SATA ID "
  972             "command\n", __func__);
  973         /* XXX KDM need to fix the case where this command is destroyed */
  974         callout_stop(&cm->cm_callout);
  975 
  976         if (cm != NULL)
  977                 reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
  978         if (error || (reply == NULL)) {
  979                 /* FIXME */
  980                 /*
  981                  * If the request returns an error then we need to do a diag
  982                  * reset
  983                  */ 
  984                 mps_dprint(sc, MPS_INFO|MPS_FAULT|MPS_MAPPING,
  985                     "Request for SATA PASSTHROUGH page completed with error %d",
  986                     error);
  987                 error = ENXIO;
  988                 goto out;
  989         }
  990         bcopy(buffer, id_buffer, sz);
  991         bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
  992         if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
  993             MPI2_IOCSTATUS_SUCCESS) {
  994                 mps_dprint(sc, MPS_INFO|MPS_MAPPING|MPS_FAULT,
  995                     "Error reading device %#x SATA PASSTHRU; iocstatus= 0x%x\n",
  996                     handle, reply->IOCStatus);
  997                 error = ENXIO;
  998                 goto out;
  999         }
 1000 out:
 1001         /*
 1002          * If the SATA_ID_TIMEOUT flag has been set for this command, don't free
 1003          * it.  The command will be freed after sending a target reset TM. If
 1004          * the command did timeout, use EWOULDBLOCK.
 1005          */
 1006         if ((cm != NULL)
 1007          && (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
 1008                 mps_free_command(sc, cm);
 1009         else if (error == 0)
 1010                 error = EWOULDBLOCK;
 1011         free(buffer, M_MPT2);
 1012         return (error);
 1013 }
 1014 
 1015 static void
 1016 mpssas_ata_id_timeout(void *data)
 1017 {
 1018         struct mps_softc *sc;
 1019         struct mps_command *cm;
 1020 
 1021         cm = (struct mps_command *)data;
 1022         sc = cm->cm_sc;
 1023         mtx_assert(&sc->mps_mtx, MA_OWNED);
 1024 
 1025         mps_dprint(sc, MPS_INFO, "%s checking ATA ID command %p sc %p\n",
 1026             __func__, cm, sc);
 1027         if ((callout_pending(&cm->cm_callout)) ||
 1028             (!callout_active(&cm->cm_callout))) {
 1029                 mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n",
 1030                     __func__);
 1031                 return;
 1032         }
 1033         callout_deactivate(&cm->cm_callout);
 1034 
 1035         /*
 1036          * Run the interrupt handler to make sure it's not pending.  This
 1037          * isn't perfect because the command could have already completed
 1038          * and been re-used, though this is unlikely.
 1039          */
 1040         mps_intr_locked(sc);
 1041         if (cm->cm_state == MPS_CM_STATE_FREE) {
 1042                 mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n",
 1043                     __func__);
 1044                 return;
 1045         }
 1046 
 1047         mps_dprint(sc, MPS_INFO, "ATA ID command timeout cm %p\n", cm);
 1048 
 1049         /*
 1050          * Send wakeup() to the sleeping thread that issued this ATA ID command.
 1051          * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this
 1052          * will keep reinit() from being called. This way, an Abort Task TM can
 1053          * be issued so that the timed out command can be cleared.  The Abort
 1054          * Task cannot be sent from here because the driver has not completed
 1055          * setting up targets.  Instead, the command is flagged so that special
 1056          * handling will be used to send the abort.
 1057          */
 1058         cm->cm_flags |= MPS_CM_FLAGS_SATA_ID_TIMEOUT;
 1059         wakeup(cm);
 1060 }
 1061 
 1062 static int
 1063 mpssas_volume_add(struct mps_softc *sc, u16 handle)
 1064 {
 1065         struct mpssas_softc *sassc;
 1066         struct mpssas_target *targ;
 1067         u64 wwid;
 1068         unsigned int id;
 1069         int error = 0;
 1070         struct mpssas_lun *lun;
 1071 
 1072         sassc = sc->sassc;
 1073         mpssas_startup_increment(sassc);
 1074         /* wwid is endian safe */
 1075         mps_config_get_volume_wwid(sc, handle, &wwid);
 1076         if (!wwid) {
 1077                 printf("%s: invalid WWID; cannot add volume to mapping table\n",
 1078                     __func__);
 1079                 error = ENXIO;
 1080                 goto out;
 1081         }
 1082 
 1083         id = mps_mapping_get_raid_tid(sc, wwid, handle);
 1084         if (id == MPS_MAP_BAD_ID) {
 1085                 printf("%s: could not get ID for volume with handle 0x%04x and "
 1086                     "WWID 0x%016llx\n", __func__, handle,
 1087                     (unsigned long long)wwid);
 1088                 error = ENXIO;
 1089                 goto out;
 1090         }
 1091 
 1092         targ = &sassc->targets[id];
 1093         targ->tid = id;
 1094         targ->handle = handle;
 1095         targ->devname = wwid;
 1096         TAILQ_INIT(&targ->commands);
 1097         TAILQ_INIT(&targ->timedout_commands);
 1098         while(!SLIST_EMPTY(&targ->luns)) {
 1099                 lun = SLIST_FIRST(&targ->luns);
 1100                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
 1101                 free(lun, M_MPT2);
 1102         }
 1103         SLIST_INIT(&targ->luns);
 1104 #if __FreeBSD_version < 1000039
 1105         if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
 1106 #endif
 1107                 mpssas_rescan_target(sc, targ);
 1108         mps_dprint(sc, MPS_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n",
 1109             targ->tid, wwid);
 1110 out:
 1111         mpssas_startup_decrement(sassc);
 1112         return (error);
 1113 }
 1114 
 1115 /**
 1116  * mpssas_SSU_to_SATA_devices 
 1117  * @sc: per adapter object
 1118  * @howto: mast of RB_* bits for how we're rebooting
 1119  *
 1120  * Looks through the target list and issues a StartStopUnit SCSI command to each
 1121  * SATA direct-access device.  This helps to ensure that data corruption is
 1122  * avoided when the system is being shut down.  This must be called after the IR
 1123  * System Shutdown RAID Action is sent if in IR mode.
 1124  *
 1125  * Return nothing.
 1126  */
 1127 static void
 1128 mpssas_SSU_to_SATA_devices(struct mps_softc *sc, int howto)
 1129 {
 1130         struct mpssas_softc *sassc = sc->sassc;
 1131         union ccb *ccb;
 1132         path_id_t pathid = cam_sim_path(sassc->sim);
 1133         target_id_t targetid;
 1134         struct mpssas_target *target;
 1135         char path_str[64];
 1136         int timeout;
 1137 
 1138         /*
 1139          * For each target, issue a StartStopUnit command to stop the device.
 1140          */
 1141         sc->SSU_started = TRUE;
 1142         sc->SSU_refcount = 0;
 1143         for (targetid = 0; targetid < sc->max_devices; targetid++) {
 1144                 target = &sassc->targets[targetid];
 1145                 if (target->handle == 0x0) {
 1146                         continue;
 1147                 }
 1148 
 1149                 ccb = xpt_alloc_ccb_nowait();
 1150                 if (ccb == NULL) {
 1151                         mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB to stop "
 1152                             "unit.\n");
 1153                         return;
 1154                 }
 1155 
 1156                 /*
 1157                  * The stop_at_shutdown flag will be set if this device is
 1158                  * a SATA direct-access end device.
 1159                  */
 1160                 if (target->stop_at_shutdown) {
 1161                         if (xpt_create_path(&ccb->ccb_h.path,
 1162                             xpt_periph, pathid, targetid,
 1163                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
 1164                                 mps_dprint(sc, MPS_FAULT, "Unable to create "
 1165                                     "LUN path to stop unit.\n");
 1166                                 xpt_free_ccb(ccb);
 1167                                 return;
 1168                         }
 1169                         xpt_path_string(ccb->ccb_h.path, path_str,
 1170                             sizeof(path_str));
 1171 
 1172                         mps_dprint(sc, MPS_INFO, "Sending StopUnit: path %s "
 1173                             "handle %d\n", path_str, target->handle);
 1174                         
 1175                         /*
 1176                          * Issue a START STOP UNIT command for the target.
 1177                          * Increment the SSU counter to be used to count the
 1178                          * number of required replies.
 1179                          */
 1180                         mps_dprint(sc, MPS_INFO, "Incrementing SSU count\n");
 1181                         sc->SSU_refcount++;
 1182                         ccb->ccb_h.target_id =
 1183                             xpt_path_target_id(ccb->ccb_h.path);
 1184                         ccb->ccb_h.ppriv_ptr1 = sassc;
 1185                         scsi_start_stop(&ccb->csio,
 1186                             /*retries*/0,
 1187                             mpssas_stop_unit_done,
 1188                             MSG_SIMPLE_Q_TAG,
 1189                             /*start*/FALSE,
 1190                             /*load/eject*/0,
 1191                             /*immediate*/FALSE,
 1192                             MPS_SENSE_LEN,
 1193                             /*timeout*/10000);
 1194                         xpt_action(ccb);
 1195                 }
 1196         }
 1197 
 1198         /*
 1199          * Timeout after 60 seconds by default or 10 seconds if howto has
 1200          * RB_NOSYNC set which indicates we're likely handling a panic.
 1201          */
 1202         timeout = 600;
 1203         if (howto & RB_NOSYNC)
 1204                 timeout = 100;
 1205 
 1206         /*
 1207          * Wait until all of the SSU commands have completed or timeout has
 1208          * expired.  Pause for 100ms each time through.  If any command
 1209          * times out, the target will be reset in the SCSI command timeout
 1210          * routine.
 1211          */
 1212         while (sc->SSU_refcount > 0) {
 1213                 pause("mpswait", hz/10);
 1214                 if (SCHEDULER_STOPPED())
 1215                         xpt_sim_poll(sassc->sim);
 1216 
 1217                 if (--timeout == 0) {
 1218                         mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
 1219                             "for SSU commands to complete.\n");
 1220                         break;
 1221                 }
 1222         }
 1223 }
 1224 
 1225 static void
 1226 mpssas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
 1227 {
 1228         struct mpssas_softc *sassc;
 1229         char path_str[64];
 1230 
 1231         if (done_ccb == NULL)
 1232                 return;
 1233 
 1234         sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
 1235 
 1236         xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
 1237         mps_dprint(sassc->sc, MPS_INFO, "Completing stop unit for %s\n",
 1238             path_str);
 1239 
 1240         /*
 1241          * Nothing more to do except free the CCB and path.  If the command
 1242          * timed out, an abort reset, then target reset will be issued during
 1243          * the SCSI Command process.
 1244          */
 1245         xpt_free_path(done_ccb->ccb_h.path);
 1246         xpt_free_ccb(done_ccb);
 1247 }
 1248 
 1249 /**
 1250  * mpssas_ir_shutdown - IR shutdown notification
 1251  * @sc: per adapter object
 1252  * @howto: mast of RB_* bits for how we're rebooting
 1253  *
 1254  * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
 1255  * the host system is shutting down.
 1256  *
 1257  * Return nothing.
 1258  */
 1259 void
 1260 mpssas_ir_shutdown(struct mps_softc *sc, int howto)
 1261 {
 1262         u16 volume_mapping_flags;
 1263         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
 1264         struct dev_mapping_table *mt_entry;
 1265         u32 start_idx, end_idx;
 1266         unsigned int id, found_volume = 0;
 1267         struct mps_command *cm;
 1268         Mpi2RaidActionRequest_t *action;
 1269         target_id_t targetid;
 1270         struct mpssas_target *target;
 1271 
 1272         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 1273 
 1274         /* is IR firmware build loaded? */
 1275         if (!sc->ir_firmware)
 1276                 goto out;
 1277 
 1278         /* are there any volumes?  Look at IR target IDs. */
 1279         // TODO-later, this should be looked up in the RAID config structure
 1280         // when it is implemented.
 1281         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
 1282             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
 1283         if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
 1284                 start_idx = 0;
 1285                 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
 1286                         start_idx = 1;
 1287         } else
 1288                 start_idx = sc->max_devices - sc->max_volumes;
 1289         end_idx = start_idx + sc->max_volumes - 1;
 1290 
 1291         for (id = start_idx; id < end_idx; id++) {
 1292                 mt_entry = &sc->mapping_table[id];
 1293                 if ((mt_entry->physical_id != 0) &&
 1294                     (mt_entry->missing_count == 0)) {
 1295                         found_volume = 1;
 1296                         break;
 1297                 }
 1298         }
 1299 
 1300         if (!found_volume)
 1301                 goto out;
 1302 
 1303         if ((cm = mps_alloc_command(sc)) == NULL) {
 1304                 printf("%s: command alloc failed\n", __func__);
 1305                 goto out;
 1306         }
 1307 
 1308         action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
 1309         action->Function = MPI2_FUNCTION_RAID_ACTION;
 1310         action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
 1311         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1312         mps_lock(sc);
 1313         mps_wait_command(sc, &cm, 5, CAN_SLEEP);
 1314         mps_unlock(sc);
 1315 
 1316         /*
 1317          * Don't check for reply, just leave.
 1318          */
 1319         if (cm)
 1320                 mps_free_command(sc, cm);
 1321 
 1322 out:
 1323         /*
 1324          * All of the targets must have the correct value set for
 1325          * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable.
 1326          *
 1327          * The possible values for the 'enable_ssu' variable are:
 1328          * 0: disable to SSD and HDD
 1329          * 1: disable only to HDD (default)
 1330          * 2: disable only to SSD
 1331          * 3: enable to SSD and HDD
 1332          * anything else will default to 1.
 1333          */
 1334         for (targetid = 0; targetid < sc->max_devices; targetid++) {
 1335                 target = &sc->sassc->targets[targetid];
 1336                 if (target->handle == 0x0) {
 1337                         continue;
 1338                 }
 1339 
 1340                 if (target->supports_SSU) {
 1341                         switch (sc->enable_ssu) {
 1342                         case MPS_SSU_DISABLE_SSD_DISABLE_HDD:
 1343                                 target->stop_at_shutdown = FALSE;
 1344                                 break;
 1345                         case MPS_SSU_DISABLE_SSD_ENABLE_HDD:
 1346                                 target->stop_at_shutdown = TRUE;
 1347                                 if (target->flags & MPS_TARGET_IS_SATA_SSD) {
 1348                                         target->stop_at_shutdown = FALSE;
 1349                                 }
 1350                                 break;
 1351                         case MPS_SSU_ENABLE_SSD_ENABLE_HDD:
 1352                                 target->stop_at_shutdown = TRUE;
 1353                                 break;
 1354                         case MPS_SSU_ENABLE_SSD_DISABLE_HDD:
 1355                         default:
 1356                                 target->stop_at_shutdown = TRUE;
 1357                                 if ((target->flags &
 1358                                     MPS_TARGET_IS_SATA_SSD) == 0) {
 1359                                         target->stop_at_shutdown = FALSE;
 1360                                 }
 1361                                 break;
 1362                         }
 1363                 }
 1364         }
 1365         mpssas_SSU_to_SATA_devices(sc, howto);
 1366 }

Cache object: 47f0b6e12e42af78d11b0914b8e288dc


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