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/mpt/mpt_raid.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  * Routines for handling the integrated RAID features LSI MPT Fusion adapters.
    3  *
    4  * SPDX-License-Identifier: BSD-3-Clause
    5  *
    6  * Copyright (c) 2005, WHEEL Sp. z o.o.
    7  * Copyright (c) 2005 Justin T. Gibbs.
    8  * All rights reserved.
    9  * 
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions are
   12  * met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   16  *    substantially similar to the "NO WARRANTY" disclaimer below
   17  *    ("Disclaimer") and any redistribution must be conditioned upon including
   18  *    a substantially similar Disclaimer requirement for further binary
   19  *    redistribution.
   20  * 3. Neither the names of the above listed copyright holders nor the names
   21  *    of any contributors may be used to endorse or promote products derived
   22  *    from this software without specific prior written permission.
   23  * 
   24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   34  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 /*-
   37  * Some Breakage and Bug Fixing added later.
   38  * Copyright (c) 2006, by Matthew Jacob
   39  * All Rights Reserved
   40  *
   41  * Support from LSI-Logic has also gone a great deal toward making this a
   42  * workable subsystem and is gratefully acknowledged.
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __FBSDID("$FreeBSD$");
   47 
   48 #include <dev/mpt/mpt.h>
   49 #include <dev/mpt/mpt_raid.h>
   50 
   51 #include "dev/mpt/mpilib/mpi_ioc.h" /* XXX Fix Event Handling!!! */
   52 #include "dev/mpt/mpilib/mpi_raid.h"
   53 
   54 #include <cam/cam.h>
   55 #include <cam/cam_ccb.h>
   56 #include <cam/cam_periph.h>
   57 #include <cam/cam_sim.h>
   58 #include <cam/cam_xpt_sim.h>
   59 
   60 #include <sys/callout.h>
   61 #include <sys/kthread.h>
   62 #include <sys/sysctl.h>
   63 
   64 #include <machine/stdarg.h>
   65 
   66 struct mpt_raid_action_result
   67 {
   68         union {
   69                 MPI_RAID_VOL_INDICATOR  indicator_struct;
   70                 uint32_t                new_settings;
   71                 uint8_t                 phys_disk_num;
   72         } action_data;
   73         uint16_t                        action_status;
   74 };
   75 
   76 #define REQ_TO_RAID_ACTION_RESULT(req) ((struct mpt_raid_action_result *) \
   77         (((MSG_RAID_ACTION_REQUEST *)(req->req_vbuf)) + 1))
   78 
   79 #define REQ_IOCSTATUS(req) ((req)->IOCStatus & MPI_IOCSTATUS_MASK)
   80 
   81 static mpt_probe_handler_t      mpt_raid_probe;
   82 static mpt_attach_handler_t     mpt_raid_attach;
   83 static mpt_enable_handler_t     mpt_raid_enable;
   84 static mpt_event_handler_t      mpt_raid_event;
   85 static mpt_shutdown_handler_t   mpt_raid_shutdown;
   86 static mpt_reset_handler_t      mpt_raid_ioc_reset;
   87 static mpt_detach_handler_t     mpt_raid_detach;
   88 
   89 static struct mpt_personality mpt_raid_personality =
   90 {
   91         .name           = "mpt_raid",
   92         .probe          = mpt_raid_probe,
   93         .attach         = mpt_raid_attach,
   94         .enable         = mpt_raid_enable,
   95         .event          = mpt_raid_event,
   96         .reset          = mpt_raid_ioc_reset,
   97         .shutdown       = mpt_raid_shutdown,
   98         .detach         = mpt_raid_detach,
   99 };
  100 
  101 DECLARE_MPT_PERSONALITY(mpt_raid, SI_ORDER_THIRD);
  102 MPT_PERSONALITY_DEPEND(mpt_raid, mpt_cam, 1, 1, 1);
  103 
  104 static mpt_reply_handler_t mpt_raid_reply_handler;
  105 static int mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
  106                                         MSG_DEFAULT_REPLY *reply_frame);
  107 static int mpt_spawn_raid_thread(struct mpt_softc *mpt);
  108 static void mpt_terminate_raid_thread(struct mpt_softc *mpt);
  109 static void mpt_raid_thread(void *arg);
  110 static callout_func_t mpt_raid_timer;
  111 #if 0
  112 static void mpt_enable_vol(struct mpt_softc *mpt,
  113                            struct mpt_raid_volume *mpt_vol, int enable);
  114 #endif
  115 static void mpt_verify_mwce(struct mpt_softc *, struct mpt_raid_volume *);
  116 static void mpt_adjust_queue_depth(struct mpt_softc *, struct mpt_raid_volume *,
  117     struct cam_path *);
  118 static void mpt_raid_sysctl_attach(struct mpt_softc *);
  119 
  120 static const char *mpt_vol_type(struct mpt_raid_volume *vol);
  121 static const char *mpt_vol_state(struct mpt_raid_volume *vol);
  122 static const char *mpt_disk_state(struct mpt_raid_disk *disk);
  123 static void mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
  124     const char *fmt, ...);
  125 static void mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
  126     const char *fmt, ...);
  127 
  128 static int mpt_issue_raid_req(struct mpt_softc *mpt,
  129     struct mpt_raid_volume *vol, struct mpt_raid_disk *disk, request_t *req,
  130     u_int Action, uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
  131     int write, int wait);
  132 
  133 static int mpt_refresh_raid_data(struct mpt_softc *mpt);
  134 static void mpt_schedule_raid_refresh(struct mpt_softc *mpt);
  135 
  136 static uint32_t raid_handler_id = MPT_HANDLER_ID_NONE;
  137 
  138 static const char *
  139 mpt_vol_type(struct mpt_raid_volume *vol)
  140 {
  141         switch (vol->config_page->VolumeType) {
  142         case MPI_RAID_VOL_TYPE_IS:
  143                 return ("RAID-0");
  144         case MPI_RAID_VOL_TYPE_IME:
  145                 return ("RAID-1E");
  146         case MPI_RAID_VOL_TYPE_IM:
  147                 return ("RAID-1");
  148         default:
  149                 return ("Unknown");
  150         }
  151 }
  152 
  153 static const char *
  154 mpt_vol_state(struct mpt_raid_volume *vol)
  155 {
  156         switch (vol->config_page->VolumeStatus.State) {
  157         case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
  158                 return ("Optimal");
  159         case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
  160                 return ("Degraded");
  161         case MPI_RAIDVOL0_STATUS_STATE_FAILED:
  162                 return ("Failed");
  163         default:
  164                 return ("Unknown");
  165         }
  166 }
  167 
  168 static const char *
  169 mpt_disk_state(struct mpt_raid_disk *disk)
  170 {
  171         switch (disk->config_page.PhysDiskStatus.State) {
  172         case MPI_PHYSDISK0_STATUS_ONLINE:
  173                 return ("Online");
  174         case MPI_PHYSDISK0_STATUS_MISSING:
  175                 return ("Missing");
  176         case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
  177                 return ("Incompatible");
  178         case MPI_PHYSDISK0_STATUS_FAILED:
  179                 return ("Failed");
  180         case MPI_PHYSDISK0_STATUS_INITIALIZING:
  181                 return ("Initializing");
  182         case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
  183                 return ("Offline Requested");
  184         case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
  185                 return ("Failed per Host Request");
  186         case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
  187                 return ("Offline");
  188         default:
  189                 return ("Unknown");
  190         }
  191 }
  192 
  193 static void
  194 mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
  195             const char *fmt, ...)
  196 {
  197         va_list ap;
  198 
  199         printf("%s:vol%d(%s:%d:%d): ", device_get_nameunit(mpt->dev),
  200                (u_int)(vol - mpt->raid_volumes), device_get_nameunit(mpt->dev),
  201                vol->config_page->VolumeBus, vol->config_page->VolumeID);
  202         va_start(ap, fmt);
  203         vprintf(fmt, ap);
  204         va_end(ap);
  205 }
  206 
  207 static void
  208 mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
  209              const char *fmt, ...)
  210 {
  211         va_list ap;
  212 
  213         if (disk->volume != NULL) {
  214                 printf("(%s:vol%d:%d): ",
  215                        device_get_nameunit(mpt->dev),
  216                        disk->volume->config_page->VolumeID,
  217                        disk->member_number);
  218         } else {
  219                 printf("(%s:%d:%d): ", device_get_nameunit(mpt->dev),
  220                        disk->config_page.PhysDiskBus,
  221                        disk->config_page.PhysDiskID);
  222         }
  223         va_start(ap, fmt);
  224         vprintf(fmt, ap);
  225         va_end(ap);
  226 }
  227 
  228 static void
  229 mpt_raid_async(void *callback_arg, u_int32_t code,
  230                struct cam_path *path, void *arg)
  231 {
  232         struct mpt_softc *mpt;
  233 
  234         mpt = (struct mpt_softc*)callback_arg;
  235         switch (code) {
  236         case AC_FOUND_DEVICE:
  237         {
  238                 struct ccb_getdev *cgd;
  239                 struct mpt_raid_volume *mpt_vol;
  240 
  241                 cgd = (struct ccb_getdev *)arg;
  242                 if (cgd == NULL) {
  243                         break;
  244                 }
  245 
  246                 mpt_lprt(mpt, MPT_PRT_DEBUG, "Callback for %d\n",
  247                          cgd->ccb_h.target_id);
  248                 
  249                 RAID_VOL_FOREACH(mpt, mpt_vol) {
  250                         if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
  251                                 continue;
  252 
  253                         if (mpt_vol->config_page->VolumeID 
  254                          == cgd->ccb_h.target_id) {
  255                                 mpt_adjust_queue_depth(mpt, mpt_vol, path);
  256                                 break;
  257                         }
  258                 }
  259         }
  260         default:
  261                 break;
  262         }
  263 }
  264 
  265 static int
  266 mpt_raid_probe(struct mpt_softc *mpt)
  267 {
  268 
  269         if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
  270                 return (ENODEV);
  271         }
  272         return (0);
  273 }
  274 
  275 static int
  276 mpt_raid_attach(struct mpt_softc *mpt)
  277 {
  278         struct ccb_setasync csa;
  279         mpt_handler_t    handler;
  280         int              error;
  281 
  282         mpt_callout_init(mpt, &mpt->raid_timer);
  283 
  284         error = mpt_spawn_raid_thread(mpt);
  285         if (error != 0) {
  286                 mpt_prt(mpt, "Unable to spawn RAID thread!\n");
  287                 goto cleanup;
  288         }
  289 
  290         MPT_LOCK(mpt);
  291         handler.reply_handler = mpt_raid_reply_handler;
  292         error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
  293                                      &raid_handler_id);
  294         if (error != 0) {
  295                 mpt_prt(mpt, "Unable to register RAID haandler!\n");
  296                 goto cleanup;
  297         }
  298 
  299         memset(&csa, 0, sizeof(csa));
  300         xpt_setup_ccb(&csa.ccb_h, mpt->path, 5);
  301         csa.ccb_h.func_code = XPT_SASYNC_CB;
  302         csa.event_enable = AC_FOUND_DEVICE;
  303         csa.callback = mpt_raid_async;
  304         csa.callback_arg = mpt;
  305         xpt_action((union ccb *)&csa);
  306         if (csa.ccb_h.status != CAM_REQ_CMP) {
  307                 mpt_prt(mpt, "mpt_raid_attach: Unable to register "
  308                         "CAM async handler.\n");
  309         }
  310         MPT_UNLOCK(mpt);
  311 
  312         mpt_raid_sysctl_attach(mpt);
  313         return (0);
  314 cleanup:
  315         MPT_UNLOCK(mpt);
  316         mpt_raid_detach(mpt);
  317         return (error);
  318 }
  319 
  320 static int
  321 mpt_raid_enable(struct mpt_softc *mpt)
  322 {
  323 
  324         return (0);
  325 }
  326 
  327 static void
  328 mpt_raid_detach(struct mpt_softc *mpt)
  329 {
  330         struct ccb_setasync csa;
  331         mpt_handler_t handler;
  332 
  333         mpt_callout_drain(mpt, &mpt->raid_timer);
  334 
  335         MPT_LOCK(mpt);
  336         mpt_terminate_raid_thread(mpt); 
  337         handler.reply_handler = mpt_raid_reply_handler;
  338         mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
  339                                raid_handler_id);
  340         memset(&csa, 0, sizeof(csa));
  341         xpt_setup_ccb(&csa.ccb_h, mpt->path, /*priority*/5);
  342         csa.ccb_h.func_code = XPT_SASYNC_CB;
  343         csa.event_enable = 0;
  344         csa.callback = mpt_raid_async;
  345         csa.callback_arg = mpt;
  346         xpt_action((union ccb *)&csa);
  347         MPT_UNLOCK(mpt);
  348 }
  349 
  350 static void
  351 mpt_raid_ioc_reset(struct mpt_softc *mpt, int type)
  352 {
  353 
  354         /* Nothing to do yet. */
  355 }
  356 
  357 static const char *raid_event_txt[] =
  358 {
  359         "Volume Created",
  360         "Volume Deleted",
  361         "Volume Settings Changed",
  362         "Volume Status Changed",
  363         "Volume Physical Disk Membership Changed",
  364         "Physical Disk Created",
  365         "Physical Disk Deleted",
  366         "Physical Disk Settings Changed",
  367         "Physical Disk Status Changed",
  368         "Domain Validation Required",
  369         "SMART Data Received",
  370         "Replace Action Started",
  371 };
  372 
  373 static int
  374 mpt_raid_event(struct mpt_softc *mpt, request_t *req,
  375                MSG_EVENT_NOTIFY_REPLY *msg)
  376 {
  377         EVENT_DATA_RAID *raid_event;
  378         struct mpt_raid_volume *mpt_vol;
  379         struct mpt_raid_disk *mpt_disk;
  380         CONFIG_PAGE_RAID_VOL_0 *vol_pg;
  381         int i;
  382         int print_event;
  383 
  384         if (msg->Event != MPI_EVENT_INTEGRATED_RAID) {
  385                 return (0);
  386         }
  387 
  388         raid_event = (EVENT_DATA_RAID *)&msg->Data;
  389 
  390         mpt_vol = NULL;
  391         vol_pg = NULL;
  392         if (mpt->raid_volumes != NULL && mpt->ioc_page2 != NULL) {
  393                 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
  394                         mpt_vol = &mpt->raid_volumes[i];
  395                         vol_pg = mpt_vol->config_page;
  396 
  397                         if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
  398                                 continue;
  399 
  400                         if (vol_pg->VolumeID == raid_event->VolumeID
  401                          && vol_pg->VolumeBus == raid_event->VolumeBus)
  402                                 break;
  403                 }
  404                 if (i >= mpt->ioc_page2->MaxVolumes) {
  405                         mpt_vol = NULL;
  406                         vol_pg = NULL;
  407                 }
  408         }
  409 
  410         mpt_disk = NULL;
  411         if (raid_event->PhysDiskNum != 0xFF && mpt->raid_disks != NULL) {
  412                 mpt_disk = mpt->raid_disks + raid_event->PhysDiskNum;
  413                 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) {
  414                         mpt_disk = NULL;
  415                 }
  416         }
  417 
  418         print_event = 1;
  419         switch(raid_event->ReasonCode) {
  420         case MPI_EVENT_RAID_RC_VOLUME_CREATED:
  421         case MPI_EVENT_RAID_RC_VOLUME_DELETED:
  422                 break;
  423         case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
  424                 if (mpt_vol != NULL) {
  425                         if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) {
  426                                 mpt_vol->flags &= ~MPT_RVF_UP2DATE;
  427                         } else {
  428                                 /*
  429                                  * Coalesce status messages into one
  430                                  * per background run of our RAID thread.
  431                                  * This removes "spurious" status messages
  432                                  * from our output.
  433                                  */
  434                                 print_event = 0;
  435                         }
  436                 }
  437                 break;
  438         case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
  439         case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
  440                 mpt->raid_rescan++;
  441                 if (mpt_vol != NULL) {
  442                         mpt_vol->flags &= ~(MPT_RVF_UP2DATE|MPT_RVF_ANNOUNCED);
  443                 }
  444                 break;
  445         case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
  446         case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
  447                 mpt->raid_rescan++;
  448                 break;
  449         case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
  450         case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
  451                 mpt->raid_rescan++;
  452                 if (mpt_disk != NULL) {
  453                         mpt_disk->flags &= ~MPT_RDF_UP2DATE;
  454                 }
  455                 break;
  456         case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
  457                 mpt->raid_rescan++;
  458                 break;
  459         case MPI_EVENT_RAID_RC_SMART_DATA:
  460         case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
  461                 break;
  462         }
  463 
  464         if (print_event) {
  465                 if (mpt_disk != NULL) {
  466                         mpt_disk_prt(mpt, mpt_disk, "");
  467                 } else if (mpt_vol != NULL) {
  468                         mpt_vol_prt(mpt, mpt_vol, "");
  469                 } else {
  470                         mpt_prt(mpt, "Volume(%d:%d", raid_event->VolumeBus,
  471                                 raid_event->VolumeID);
  472 
  473                         if (raid_event->PhysDiskNum != 0xFF)
  474                                 mpt_prtc(mpt, ":%d): ",
  475                                          raid_event->PhysDiskNum);
  476                         else
  477                                 mpt_prtc(mpt, "): ");
  478                 }
  479 
  480                 if (raid_event->ReasonCode >= NUM_ELEMENTS(raid_event_txt))
  481                         mpt_prtc(mpt, "Unhandled RaidEvent %#x\n",
  482                                  raid_event->ReasonCode);
  483                 else
  484                         mpt_prtc(mpt, "%s\n",
  485                                  raid_event_txt[raid_event->ReasonCode]);
  486         }
  487 
  488         if (raid_event->ReasonCode == MPI_EVENT_RAID_RC_SMART_DATA) {
  489                 /* XXX Use CAM's print sense for this... */
  490                 if (mpt_disk != NULL)
  491                         mpt_disk_prt(mpt, mpt_disk, "");
  492                 else
  493                         mpt_prt(mpt, "Volume(%d:%d:%d: ",
  494                             raid_event->VolumeBus, raid_event->VolumeID,
  495                             raid_event->PhysDiskNum);
  496                 mpt_prtc(mpt, "ASC 0x%x, ASCQ 0x%x)\n",
  497                          raid_event->ASC, raid_event->ASCQ);
  498         }
  499 
  500         mpt_raid_wakeup(mpt);
  501         return (1);
  502 }
  503 
  504 static void
  505 mpt_raid_shutdown(struct mpt_softc *mpt)
  506 {
  507         struct mpt_raid_volume *mpt_vol;
  508 
  509         if (mpt->raid_mwce_setting != MPT_RAID_MWCE_REBUILD_ONLY) {
  510                 return;
  511         }
  512 
  513         mpt->raid_mwce_setting = MPT_RAID_MWCE_OFF;
  514         RAID_VOL_FOREACH(mpt, mpt_vol) {
  515                 mpt_verify_mwce(mpt, mpt_vol);
  516         }
  517 }
  518 
  519 static int
  520 mpt_raid_reply_handler(struct mpt_softc *mpt, request_t *req,
  521     uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
  522 {
  523         int free_req;
  524 
  525         if (req == NULL)
  526                 return (TRUE);
  527 
  528         free_req = TRUE;
  529         if (reply_frame != NULL)
  530                 free_req = mpt_raid_reply_frame_handler(mpt, req, reply_frame);
  531 #ifdef NOTYET
  532         else if (req->ccb != NULL) {
  533                 /* Complete Quiesce CCB with error... */
  534         }
  535 #endif
  536 
  537         req->state &= ~REQ_STATE_QUEUED;
  538         req->state |= REQ_STATE_DONE;
  539         TAILQ_REMOVE(&mpt->request_pending_list, req, links);
  540 
  541         if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
  542                 wakeup(req);
  543         } else if (free_req) {
  544                 mpt_free_request(mpt, req);
  545         }
  546 
  547         return (TRUE);
  548 }
  549 
  550 /*
  551  * Parse additional completion information in the reply
  552  * frame for RAID I/O requests.
  553  */
  554 static int
  555 mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
  556     MSG_DEFAULT_REPLY *reply_frame)
  557 {
  558         MSG_RAID_ACTION_REPLY *reply;
  559         struct mpt_raid_action_result *action_result;
  560         MSG_RAID_ACTION_REQUEST *rap;
  561 
  562         reply = (MSG_RAID_ACTION_REPLY *)reply_frame;
  563         req->IOCStatus = le16toh(reply->IOCStatus);
  564         rap = (MSG_RAID_ACTION_REQUEST *)req->req_vbuf;
  565 
  566         switch (rap->Action) {
  567         case MPI_RAID_ACTION_QUIESCE_PHYS_IO:
  568                 mpt_prt(mpt, "QUIESCE PHYSIO DONE\n");
  569                 break;
  570         case MPI_RAID_ACTION_ENABLE_PHYS_IO:
  571                 mpt_prt(mpt, "ENABLY PHYSIO DONE\n");
  572                 break;
  573         default:
  574                 break;
  575         }
  576         action_result = REQ_TO_RAID_ACTION_RESULT(req);
  577         memcpy(&action_result->action_data, &reply->ActionData,
  578             sizeof(action_result->action_data));
  579         action_result->action_status = le16toh(reply->ActionStatus);
  580         return (TRUE);
  581 }
  582 
  583 /*
  584  * Utiltity routine to perform a RAID action command;
  585  */
  586 static int
  587 mpt_issue_raid_req(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
  588                    struct mpt_raid_disk *disk, request_t *req, u_int Action,
  589                    uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
  590                    int write, int wait)
  591 {
  592         MSG_RAID_ACTION_REQUEST *rap;
  593         SGE_SIMPLE32 *se;
  594 
  595         rap = req->req_vbuf;
  596         memset(rap, 0, sizeof *rap);
  597         rap->Action = Action;
  598         rap->ActionDataWord = htole32(ActionDataWord);
  599         rap->Function = MPI_FUNCTION_RAID_ACTION;
  600         rap->VolumeID = vol->config_page->VolumeID;
  601         rap->VolumeBus = vol->config_page->VolumeBus;
  602         if (disk != NULL)
  603                 rap->PhysDiskNum = disk->config_page.PhysDiskNum;
  604         else
  605                 rap->PhysDiskNum = 0xFF;
  606         se = (SGE_SIMPLE32 *)&rap->ActionDataSGE;
  607         se->Address = htole32(addr);
  608         MPI_pSGE_SET_LENGTH(se, len);
  609         MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
  610             MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
  611             MPI_SGE_FLAGS_END_OF_LIST |
  612             (write ? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST)));
  613         se->FlagsLength = htole32(se->FlagsLength);
  614         rap->MsgContext = htole32(req->index | raid_handler_id);
  615 
  616         mpt_check_doorbell(mpt);
  617         mpt_send_cmd(mpt, req);
  618 
  619         if (wait) {
  620                 return (mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE,
  621                                      /*sleep_ok*/FALSE, /*time_ms*/2000));
  622         } else {
  623                 return (0);
  624         }
  625 }
  626 
  627 /*************************** RAID Status Monitoring ***************************/
  628 static int
  629 mpt_spawn_raid_thread(struct mpt_softc *mpt)
  630 {
  631         int error;
  632 
  633         /*
  634          * Freeze out any CAM transactions until our thread
  635          * is able to run at least once.  We need to update
  636          * our RAID pages before acception I/O or we may
  637          * reject I/O to an ID we later determine is for a
  638          * hidden physdisk.
  639          */
  640         MPT_LOCK(mpt);
  641         xpt_freeze_simq(mpt->phydisk_sim, 1);
  642         MPT_UNLOCK(mpt);
  643         error = kproc_create(mpt_raid_thread, mpt,
  644             &mpt->raid_thread, /*flags*/0, /*altstack*/0,
  645             "mpt_raid%d", mpt->unit);
  646         if (error != 0) {
  647                 MPT_LOCK(mpt);
  648                 xpt_release_simq(mpt->phydisk_sim, /*run_queue*/FALSE);
  649                 MPT_UNLOCK(mpt);
  650         }
  651         return (error);
  652 }
  653 
  654 static void
  655 mpt_terminate_raid_thread(struct mpt_softc *mpt)
  656 {
  657 
  658         if (mpt->raid_thread == NULL) {
  659                 return;
  660         }
  661         mpt->shutdwn_raid = 1;
  662         wakeup(&mpt->raid_volumes);
  663         /*
  664          * Sleep on a slightly different location
  665          * for this interlock just for added safety.
  666          */
  667         mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0);
  668 }
  669 
  670 static void
  671 mpt_raid_thread(void *arg)
  672 {
  673         struct mpt_softc *mpt;
  674         int firstrun;
  675 
  676         mpt = (struct mpt_softc *)arg;
  677         firstrun = 1;
  678         MPT_LOCK(mpt);
  679         while (mpt->shutdwn_raid == 0) {
  680                 if (mpt->raid_wakeup == 0) {
  681                         mpt_sleep(mpt, &mpt->raid_volumes, PUSER, "idle", 0);
  682                         continue;
  683                 }
  684 
  685                 mpt->raid_wakeup = 0;
  686 
  687                 if (mpt_refresh_raid_data(mpt)) {
  688                         mpt_schedule_raid_refresh(mpt); /* XX NOT QUITE RIGHT */
  689                         continue;
  690                 }
  691 
  692                 /*
  693                  * Now that we have our first snapshot of RAID data,
  694                  * allow CAM to access our physical disk bus.
  695                  */
  696                 if (firstrun) {
  697                         firstrun = 0;
  698                         xpt_release_simq(mpt->phydisk_sim, TRUE);
  699                 }
  700 
  701                 if (mpt->raid_rescan != 0) {
  702                         union ccb *ccb;
  703                         int error;
  704 
  705                         mpt->raid_rescan = 0;
  706                         MPT_UNLOCK(mpt);
  707 
  708                         ccb = xpt_alloc_ccb();
  709 
  710                         MPT_LOCK(mpt);
  711                         error = xpt_create_path(&ccb->ccb_h.path, NULL,
  712                             cam_sim_path(mpt->phydisk_sim),
  713                             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
  714                         if (error != CAM_REQ_CMP) {
  715                                 xpt_free_ccb(ccb);
  716                                 mpt_prt(mpt, "Unable to rescan RAID Bus!\n");
  717                         } else {
  718                                 xpt_rescan(ccb);
  719                         }
  720                 }
  721         }
  722         mpt->raid_thread = NULL;
  723         wakeup(&mpt->raid_thread);
  724         MPT_UNLOCK(mpt);
  725         kproc_exit(0);
  726 }
  727 
  728 #if 0
  729 static void
  730 mpt_raid_quiesce_timeout(void *arg)
  731 {
  732 
  733         /* Complete the CCB with error */
  734         /* COWWWW */
  735 }
  736 
  737 static timeout_t mpt_raid_quiesce_timeout;
  738 cam_status
  739 mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
  740                       request_t *req)
  741 {
  742         union ccb *ccb;
  743 
  744         ccb = req->ccb;
  745         if ((mpt_disk->flags & MPT_RDF_QUIESCED) != 0)
  746                 return (CAM_REQ_CMP);
  747 
  748         if ((mpt_disk->flags & MPT_RDF_QUIESCING) == 0) {
  749                 int rv;
  750 
  751                 mpt_disk->flags |= MPT_RDF_QUIESCING;
  752                 xpt_freeze_devq(ccb->ccb_h.path, 1);
  753                 
  754                 rv = mpt_issue_raid_req(mpt, mpt_disk->volume, mpt_disk, req,
  755                                         MPI_RAID_ACTION_QUIESCE_PHYS_IO,
  756                                         /*ActionData*/0, /*addr*/0,
  757                                         /*len*/0, /*write*/FALSE,
  758                                         /*wait*/FALSE);
  759                 if (rv != 0)
  760                         return (CAM_REQ_CMP_ERR);
  761 
  762                 mpt_req_timeout(req, mpt_raid_quiesce_timeout, ccb, 5 * hz);
  763 #if 0
  764                 if (rv == ETIMEDOUT) {
  765                         mpt_disk_prt(mpt, mpt_disk, "mpt_raid_quiesce_disk: "
  766                                      "Quiece Timed-out\n");
  767                         xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0);
  768                         return (CAM_REQ_CMP_ERR);
  769                 }
  770 
  771                 ar = REQ_TO_RAID_ACTION_RESULT(req);
  772                 if (rv != 0
  773                  || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
  774                  || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
  775                         mpt_disk_prt(mpt, mpt_disk, "Quiece Failed"
  776                                     "%d:%x:%x\n", rv, req->IOCStatus,
  777                                     ar->action_status);
  778                         xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0);
  779                         return (CAM_REQ_CMP_ERR);
  780                 }
  781 #endif
  782                 return (CAM_REQ_INPROG);
  783         }
  784         return (CAM_REQUEUE_REQ);
  785 }
  786 #endif
  787 
  788 /* XXX Ignores that there may be multiple buses/IOCs involved. */
  789 cam_status
  790 mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, target_id_t *tgt)
  791 {
  792         struct mpt_raid_disk *mpt_disk;
  793 
  794         mpt_disk = mpt->raid_disks + ccb->ccb_h.target_id;
  795         if (ccb->ccb_h.target_id < mpt->raid_max_disks
  796          && (mpt_disk->flags & MPT_RDF_ACTIVE) != 0) {
  797                 *tgt = mpt_disk->config_page.PhysDiskID;
  798                 return (0);
  799         }
  800         mpt_lprt(mpt, MPT_PRT_DEBUG1, "mpt_map_physdisk(%d) - Not Active\n",
  801                  ccb->ccb_h.target_id);
  802         return (-1);
  803 }
  804 
  805 /* XXX Ignores that there may be multiple buses/IOCs involved. */
  806 int
  807 mpt_is_raid_member(struct mpt_softc *mpt, target_id_t tgt)
  808 {
  809         struct mpt_raid_disk *mpt_disk;
  810         int i;
  811 
  812         if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0)
  813                 return (0);
  814         for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
  815                 mpt_disk = &mpt->raid_disks[i];
  816                 if ((mpt_disk->flags & MPT_RDF_ACTIVE) != 0 &&
  817                     mpt_disk->config_page.PhysDiskID == tgt)
  818                         return (1);
  819         }
  820         return (0);
  821 
  822 }
  823 
  824 /* XXX Ignores that there may be multiple buses/IOCs involved. */
  825 int
  826 mpt_is_raid_volume(struct mpt_softc *mpt, target_id_t tgt)
  827 {
  828         CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
  829         CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
  830 
  831         if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
  832                 return (0);
  833         }
  834         ioc_vol = mpt->ioc_page2->RaidVolume;
  835         ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
  836         for (;ioc_vol != ioc_last_vol; ioc_vol++) {
  837                 if (ioc_vol->VolumeID == tgt) {
  838                         return (1);
  839                 }
  840         }
  841         return (0);
  842 }
  843 
  844 #if 0
  845 static void
  846 mpt_enable_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
  847                int enable)
  848 {
  849         request_t *req;
  850         struct mpt_raid_action_result *ar;
  851         CONFIG_PAGE_RAID_VOL_0 *vol_pg;
  852         int enabled;
  853         int rv;
  854 
  855         vol_pg = mpt_vol->config_page;
  856         enabled = vol_pg->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED;
  857 
  858         /*
  859          * If the setting matches the configuration,
  860          * there is nothing to do.
  861          */
  862         if ((enabled && enable)
  863          || (!enabled && !enable))
  864                 return;
  865 
  866         req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
  867         if (req == NULL) {
  868                 mpt_vol_prt(mpt, mpt_vol,
  869                             "mpt_enable_vol: Get request failed!\n");
  870                 return;
  871         }
  872 
  873         rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
  874                                 enable ? MPI_RAID_ACTION_ENABLE_VOLUME
  875                                        : MPI_RAID_ACTION_DISABLE_VOLUME,
  876                                 /*data*/0, /*addr*/0, /*len*/0,
  877                                 /*write*/FALSE, /*wait*/TRUE);
  878         if (rv == ETIMEDOUT) {
  879                 mpt_vol_prt(mpt, mpt_vol, "mpt_enable_vol: "
  880                             "%s Volume Timed-out\n",
  881                             enable ? "Enable" : "Disable");
  882                 return;
  883         }
  884         ar = REQ_TO_RAID_ACTION_RESULT(req);
  885         if (rv != 0
  886          || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
  887          || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
  888                 mpt_vol_prt(mpt, mpt_vol, "%s Volume Failed: %d:%x:%x\n",
  889                             enable ? "Enable" : "Disable",
  890                             rv, req->IOCStatus, ar->action_status);
  891         }
  892 
  893         mpt_free_request(mpt, req);
  894 }
  895 #endif
  896 
  897 static void
  898 mpt_verify_mwce(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
  899 {
  900         request_t *req;
  901         struct mpt_raid_action_result *ar;
  902         CONFIG_PAGE_RAID_VOL_0 *vol_pg;
  903         uint32_t data;
  904         int rv;
  905         int resyncing;
  906         int mwce;
  907 
  908         vol_pg = mpt_vol->config_page;
  909         resyncing = vol_pg->VolumeStatus.Flags
  910                   & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
  911         mwce = vol_pg->VolumeSettings.Settings
  912              & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
  913 
  914         /*
  915          * If the setting matches the configuration,
  916          * there is nothing to do.
  917          */
  918         switch (mpt->raid_mwce_setting) {
  919         case MPT_RAID_MWCE_REBUILD_ONLY:
  920                 if ((resyncing && mwce) || (!resyncing && !mwce)) {
  921                         return;
  922                 }
  923                 mpt_vol->flags ^= MPT_RVF_WCE_CHANGED;
  924                 if ((mpt_vol->flags & MPT_RVF_WCE_CHANGED) == 0) {
  925                         /*
  926                          * Wait one more status update to see if
  927                          * resyncing gets enabled.  It gets disabled
  928                          * temporarilly when WCE is changed.
  929                          */
  930                         return;
  931                 }
  932                 break;
  933         case MPT_RAID_MWCE_ON:
  934                 if (mwce)
  935                         return;
  936                 break;
  937         case MPT_RAID_MWCE_OFF:
  938                 if (!mwce)
  939                         return;
  940                 break;
  941         case MPT_RAID_MWCE_NC:
  942                 return;
  943         }
  944 
  945         req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
  946         if (req == NULL) {
  947                 mpt_vol_prt(mpt, mpt_vol,
  948                             "mpt_verify_mwce: Get request failed!\n");
  949                 return;
  950         }
  951 
  952         vol_pg->VolumeSettings.Settings ^=
  953             MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
  954         memcpy(&data, &vol_pg->VolumeSettings, sizeof(data));
  955         vol_pg->VolumeSettings.Settings ^=
  956             MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
  957         rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
  958                                 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
  959                                 data, /*addr*/0, /*len*/0,
  960                                 /*write*/FALSE, /*wait*/TRUE);
  961         if (rv == ETIMEDOUT) {
  962                 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_mwce: "
  963                             "Write Cache Enable Timed-out\n");
  964                 return;
  965         }
  966         ar = REQ_TO_RAID_ACTION_RESULT(req);
  967         if (rv != 0
  968          || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
  969          || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
  970                 mpt_vol_prt(mpt, mpt_vol, "Write Cache Enable Failed: "
  971                             "%d:%x:%x\n", rv, req->IOCStatus,
  972                             ar->action_status);
  973         } else {
  974                 vol_pg->VolumeSettings.Settings ^=
  975                     MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
  976         }
  977         mpt_free_request(mpt, req);
  978 }
  979 
  980 static void
  981 mpt_verify_resync_rate(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
  982 {
  983         request_t *req;
  984         struct mpt_raid_action_result *ar;
  985         CONFIG_PAGE_RAID_VOL_0  *vol_pg;
  986         u_int prio;
  987         int rv;
  988 
  989         vol_pg = mpt_vol->config_page;
  990 
  991         if (mpt->raid_resync_rate == MPT_RAID_RESYNC_RATE_NC)
  992                 return;
  993 
  994         /*
  995          * If the current RAID resync rate does not
  996          * match our configured rate, update it.
  997          */
  998         prio = vol_pg->VolumeSettings.Settings
  999              & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
 1000         if (vol_pg->ResyncRate != 0
 1001          && vol_pg->ResyncRate != mpt->raid_resync_rate) {
 1002                 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
 1003                 if (req == NULL) {
 1004                         mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: "
 1005                                     "Get request failed!\n");
 1006                         return;
 1007                 }
 1008 
 1009                 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
 1010                                         MPI_RAID_ACTION_SET_RESYNC_RATE,
 1011                                         mpt->raid_resync_rate, /*addr*/0,
 1012                                         /*len*/0, /*write*/FALSE, /*wait*/TRUE);
 1013                 if (rv == ETIMEDOUT) {
 1014                         mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: "
 1015                                     "Resync Rate Setting Timed-out\n");
 1016                         return;
 1017                 }
 1018 
 1019                 ar = REQ_TO_RAID_ACTION_RESULT(req);
 1020                 if (rv != 0
 1021                  || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
 1022                  || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
 1023                         mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: "
 1024                                     "%d:%x:%x\n", rv, req->IOCStatus,
 1025                                     ar->action_status);
 1026                 } else 
 1027                         vol_pg->ResyncRate = mpt->raid_resync_rate;
 1028                 mpt_free_request(mpt, req);
 1029         } else if ((prio && mpt->raid_resync_rate < 128)
 1030                 || (!prio && mpt->raid_resync_rate >= 128)) {
 1031                 uint32_t data;
 1032 
 1033                 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
 1034                 if (req == NULL) {
 1035                         mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: "
 1036                                     "Get request failed!\n");
 1037                         return;
 1038                 }
 1039 
 1040                 vol_pg->VolumeSettings.Settings ^=
 1041                     MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
 1042                 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data));
 1043                 vol_pg->VolumeSettings.Settings ^=
 1044                     MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
 1045                 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
 1046                                         MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
 1047                                         data, /*addr*/0, /*len*/0,
 1048                                         /*write*/FALSE, /*wait*/TRUE);
 1049                 if (rv == ETIMEDOUT) {
 1050                         mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: "
 1051                                     "Resync Rate Setting Timed-out\n");
 1052                         return;
 1053                 }
 1054                 ar = REQ_TO_RAID_ACTION_RESULT(req);
 1055                 if (rv != 0
 1056                  || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
 1057                  || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
 1058                         mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: "
 1059                                     "%d:%x:%x\n", rv, req->IOCStatus,
 1060                                     ar->action_status);
 1061                 } else {
 1062                         vol_pg->VolumeSettings.Settings ^=
 1063                             MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
 1064                 }
 1065 
 1066                 mpt_free_request(mpt, req);
 1067         }
 1068 }
 1069 
 1070 static void
 1071 mpt_adjust_queue_depth(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
 1072                        struct cam_path *path)
 1073 {
 1074         struct ccb_relsim crs;
 1075 
 1076         memset(&crs, 0, sizeof(crs));
 1077         xpt_setup_ccb(&crs.ccb_h, path, /*priority*/5);
 1078         crs.ccb_h.func_code = XPT_REL_SIMQ;
 1079         crs.ccb_h.flags = CAM_DEV_QFREEZE;
 1080         crs.release_flags = RELSIM_ADJUST_OPENINGS;
 1081         crs.openings = mpt->raid_queue_depth;
 1082         xpt_action((union ccb *)&crs);
 1083         if (crs.ccb_h.status != CAM_REQ_CMP)
 1084                 mpt_vol_prt(mpt, mpt_vol, "mpt_adjust_queue_depth failed "
 1085                             "with CAM status %#x\n", crs.ccb_h.status);
 1086 }
 1087 
 1088 static void
 1089 mpt_announce_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
 1090 {
 1091         CONFIG_PAGE_RAID_VOL_0 *vol_pg;
 1092         u_int i;
 1093 
 1094         vol_pg = mpt_vol->config_page;
 1095         mpt_vol_prt(mpt, mpt_vol, "Settings (");
 1096         for (i = 1; i <= 0x8000; i <<= 1) {
 1097                 switch (vol_pg->VolumeSettings.Settings & i) {
 1098                 case MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE:
 1099                         mpt_prtc(mpt, " Member-WCE");
 1100                         break;
 1101                 case MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART:
 1102                         mpt_prtc(mpt, " Offline-On-SMART-Err");
 1103                         break;
 1104                 case MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE:
 1105                         mpt_prtc(mpt, " Hot-Plug-Spares");
 1106                         break;
 1107                 case MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC:
 1108                         mpt_prtc(mpt, " High-Priority-ReSync");
 1109                         break;
 1110                 default:
 1111                         break;
 1112                 }
 1113         }
 1114         mpt_prtc(mpt, " )\n");
 1115         if (vol_pg->VolumeSettings.HotSparePool != 0) {
 1116                 mpt_vol_prt(mpt, mpt_vol, "Using Spare Pool%s",
 1117                             powerof2(vol_pg->VolumeSettings.HotSparePool)
 1118                           ? ":" : "s:");
 1119                 for (i = 0; i < 8; i++) {
 1120                         u_int mask;
 1121 
 1122                         mask = 0x1 << i;
 1123                         if ((vol_pg->VolumeSettings.HotSparePool & mask) == 0)
 1124                                 continue;
 1125                         mpt_prtc(mpt, " %d", i);
 1126                 }
 1127                 mpt_prtc(mpt, "\n");
 1128         }
 1129         mpt_vol_prt(mpt, mpt_vol, "%d Members:\n", vol_pg->NumPhysDisks);
 1130         for (i = 0; i < vol_pg->NumPhysDisks; i++){
 1131                 struct mpt_raid_disk *mpt_disk;
 1132                 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
 1133                 int pt_bus = cam_sim_bus(mpt->phydisk_sim);
 1134                 U8 f, s;
 1135 
 1136                 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
 1137                 disk_pg = &mpt_disk->config_page;
 1138                 mpt_prtc(mpt, "      ");
 1139                 mpt_prtc(mpt, "(%s:%d:%d:0): ", device_get_nameunit(mpt->dev),
 1140                          pt_bus, disk_pg->PhysDiskID);
 1141                 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) {
 1142                         mpt_prtc(mpt, "%s", mpt_disk->member_number == 0?
 1143                             "Primary" : "Secondary");
 1144                 } else {
 1145                         mpt_prtc(mpt, "Stripe Position %d",
 1146                                  mpt_disk->member_number);
 1147                 }
 1148                 f = disk_pg->PhysDiskStatus.Flags;
 1149                 s = disk_pg->PhysDiskStatus.State;
 1150                 if (f & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC) {
 1151                         mpt_prtc(mpt, " Out of Sync");
 1152                 }
 1153                 if (f & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED) {
 1154                         mpt_prtc(mpt, " Quiesced");
 1155                 }
 1156                 if (f & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) {
 1157                         mpt_prtc(mpt, " Inactive");
 1158                 }
 1159                 if (f & MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS) {
 1160                         mpt_prtc(mpt, " Was Optimal");
 1161                 }
 1162                 if (f & MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS) {
 1163                         mpt_prtc(mpt, " Was Non-Optimal");
 1164                 }
 1165                 switch (s) {
 1166                 case MPI_PHYSDISK0_STATUS_ONLINE:
 1167                         mpt_prtc(mpt, " Online");
 1168                         break;
 1169                 case MPI_PHYSDISK0_STATUS_MISSING:
 1170                         mpt_prtc(mpt, " Missing");
 1171                         break;
 1172                 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
 1173                         mpt_prtc(mpt, " Incompatible");
 1174                         break;
 1175                 case MPI_PHYSDISK0_STATUS_FAILED:
 1176                         mpt_prtc(mpt, " Failed");
 1177                         break;
 1178                 case MPI_PHYSDISK0_STATUS_INITIALIZING:
 1179                         mpt_prtc(mpt, " Initializing");
 1180                         break;
 1181                 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
 1182                         mpt_prtc(mpt, " Requested Offline");
 1183                         break;
 1184                 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
 1185                         mpt_prtc(mpt, " Requested Failed");
 1186                         break;
 1187                 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
 1188                 default:
 1189                         mpt_prtc(mpt, " Offline Other (%x)", s);
 1190                         break;
 1191                 }
 1192                 mpt_prtc(mpt, "\n");
 1193         }
 1194 }
 1195 
 1196 static void
 1197 mpt_announce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk)
 1198 {
 1199         CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
 1200         int rd_bus = cam_sim_bus(mpt->sim);
 1201         int pt_bus = cam_sim_bus(mpt->phydisk_sim);
 1202         u_int i;
 1203 
 1204         disk_pg = &mpt_disk->config_page;
 1205         mpt_disk_prt(mpt, mpt_disk,
 1206                      "Physical (%s:%d:%d:0), Pass-thru (%s:%d:%d:0)\n",
 1207                      device_get_nameunit(mpt->dev), rd_bus,
 1208                      disk_pg->PhysDiskID, device_get_nameunit(mpt->dev),
 1209                      pt_bus, mpt_disk - mpt->raid_disks);
 1210         if (disk_pg->PhysDiskSettings.HotSparePool == 0)
 1211                 return;
 1212         mpt_disk_prt(mpt, mpt_disk, "Member of Hot Spare Pool%s",
 1213                      powerof2(disk_pg->PhysDiskSettings.HotSparePool)
 1214                    ? ":" : "s:");
 1215         for (i = 0; i < 8; i++) {
 1216                 u_int mask;
 1217 
 1218                 mask = 0x1 << i;
 1219                 if ((disk_pg->PhysDiskSettings.HotSparePool & mask) == 0)
 1220                         continue;
 1221                 mpt_prtc(mpt, " %d", i);
 1222         }
 1223         mpt_prtc(mpt, "\n");
 1224 }
 1225 
 1226 static void
 1227 mpt_refresh_raid_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
 1228                       IOC_3_PHYS_DISK *ioc_disk)
 1229 {
 1230         int rv;
 1231 
 1232         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK,
 1233                                  /*PageNumber*/0, ioc_disk->PhysDiskNum,
 1234                                  &mpt_disk->config_page.Header,
 1235                                  /*sleep_ok*/TRUE, /*timeout_ms*/5000);
 1236         if (rv != 0) {
 1237                 mpt_prt(mpt, "mpt_refresh_raid_disk: "
 1238                         "Failed to read RAID Disk Hdr(%d)\n",
 1239                         ioc_disk->PhysDiskNum);
 1240                 return;
 1241         }
 1242         rv = mpt_read_cur_cfg_page(mpt, ioc_disk->PhysDiskNum,
 1243                                    &mpt_disk->config_page.Header,
 1244                                    sizeof(mpt_disk->config_page),
 1245                                    /*sleep_ok*/TRUE, /*timeout_ms*/5000);
 1246         if (rv != 0)
 1247                 mpt_prt(mpt, "mpt_refresh_raid_disk: "
 1248                         "Failed to read RAID Disk Page(%d)\n",
 1249                         ioc_disk->PhysDiskNum);
 1250         mpt2host_config_page_raid_phys_disk_0(&mpt_disk->config_page);
 1251 }
 1252 
 1253 static void
 1254 mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
 1255     CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol)
 1256 {
 1257         CONFIG_PAGE_RAID_VOL_0 *vol_pg;
 1258         struct mpt_raid_action_result *ar;
 1259         request_t *req;
 1260         int rv;
 1261         int i;
 1262 
 1263         vol_pg = mpt_vol->config_page;
 1264         mpt_vol->flags &= ~MPT_RVF_UP2DATE;
 1265 
 1266         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0,
 1267             ioc_vol->VolumePageNumber, &vol_pg->Header, TRUE, 5000);
 1268         if (rv != 0) {
 1269                 mpt_vol_prt(mpt, mpt_vol,
 1270                     "mpt_refresh_raid_vol: Failed to read RAID Vol Hdr(%d)\n",
 1271                     ioc_vol->VolumePageNumber);
 1272                 return;
 1273         }
 1274 
 1275         rv = mpt_read_cur_cfg_page(mpt, ioc_vol->VolumePageNumber,
 1276             &vol_pg->Header, mpt->raid_page0_len, TRUE, 5000);
 1277         if (rv != 0) {
 1278                 mpt_vol_prt(mpt, mpt_vol,
 1279                     "mpt_refresh_raid_vol: Failed to read RAID Vol Page(%d)\n",
 1280                     ioc_vol->VolumePageNumber);
 1281                 return;
 1282         }
 1283         mpt2host_config_page_raid_vol_0(vol_pg);
 1284 
 1285         mpt_vol->flags |= MPT_RVF_ACTIVE;
 1286 
 1287         /* Update disk entry array data. */
 1288         for (i = 0; i < vol_pg->NumPhysDisks; i++) {
 1289                 struct mpt_raid_disk *mpt_disk;
 1290                 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
 1291                 mpt_disk->volume = mpt_vol;
 1292                 mpt_disk->member_number = vol_pg->PhysDisk[i].PhysDiskMap;
 1293                 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) {
 1294                         mpt_disk->member_number--;
 1295                 }
 1296         }
 1297 
 1298         if ((vol_pg->VolumeStatus.Flags
 1299            & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
 1300                 return;
 1301 
 1302         req = mpt_get_request(mpt, TRUE);
 1303         if (req == NULL) {
 1304                 mpt_vol_prt(mpt, mpt_vol,
 1305                     "mpt_refresh_raid_vol: Get request failed!\n");
 1306                 return;
 1307         }
 1308         rv = mpt_issue_raid_req(mpt, mpt_vol, NULL, req,
 1309             MPI_RAID_ACTION_INDICATOR_STRUCT, 0, 0, 0, FALSE, TRUE);
 1310         if (rv == ETIMEDOUT) {
 1311                 mpt_vol_prt(mpt, mpt_vol,
 1312                     "mpt_refresh_raid_vol: Progress Indicator fetch timeout\n");
 1313                 mpt_free_request(mpt, req);
 1314                 return;
 1315         }
 1316 
 1317         ar = REQ_TO_RAID_ACTION_RESULT(req);
 1318         if (rv == 0
 1319          && ar->action_status == MPI_RAID_ACTION_ASTATUS_SUCCESS
 1320          && REQ_IOCSTATUS(req) == MPI_IOCSTATUS_SUCCESS) {
 1321                 memcpy(&mpt_vol->sync_progress,
 1322                        &ar->action_data.indicator_struct,
 1323                        sizeof(mpt_vol->sync_progress));
 1324                 mpt2host_mpi_raid_vol_indicator(&mpt_vol->sync_progress);
 1325         } else {
 1326                 mpt_vol_prt(mpt, mpt_vol,
 1327                     "mpt_refresh_raid_vol: Progress indicator fetch failed!\n");
 1328         }
 1329         mpt_free_request(mpt, req);
 1330 }
 1331 
 1332 /*
 1333  * Update in-core information about RAID support.  We update any entries
 1334  * that didn't previously exists or have been marked as needing to
 1335  * be updated by our event handler.  Interesting changes are displayed
 1336  * to the console.
 1337  */
 1338 static int
 1339 mpt_refresh_raid_data(struct mpt_softc *mpt)
 1340 {
 1341         CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
 1342         CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
 1343         IOC_3_PHYS_DISK *ioc_disk;
 1344         IOC_3_PHYS_DISK *ioc_last_disk;
 1345         CONFIG_PAGE_RAID_VOL_0  *vol_pg;
 1346         size_t len;
 1347         int rv;
 1348         int i;
 1349         u_int nonopt_volumes;
 1350 
 1351         if (mpt->ioc_page2 == NULL || mpt->ioc_page3 == NULL) {
 1352                 return (0);
 1353         }
 1354 
 1355         /*
 1356          * Mark all items as unreferenced by the configuration.
 1357          * This allows us to find, report, and discard stale
 1358          * entries.
 1359          */
 1360         for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
 1361                 mpt->raid_disks[i].flags &= ~MPT_RDF_REFERENCED;
 1362         }
 1363         for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
 1364                 mpt->raid_volumes[i].flags &= ~MPT_RVF_REFERENCED;
 1365         }
 1366 
 1367         /*
 1368          * Get Physical Disk information.
 1369          */
 1370         len = mpt->ioc_page3->Header.PageLength * sizeof(uint32_t);
 1371         rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0,
 1372                                    &mpt->ioc_page3->Header, len,
 1373                                    /*sleep_ok*/TRUE, /*timeout_ms*/5000);
 1374         if (rv) {
 1375                 mpt_prt(mpt,
 1376                     "mpt_refresh_raid_data: Failed to read IOC Page 3\n");
 1377                 return (-1);
 1378         }
 1379         mpt2host_config_page_ioc3(mpt->ioc_page3);
 1380 
 1381         ioc_disk = mpt->ioc_page3->PhysDisk;
 1382         ioc_last_disk = ioc_disk + mpt->ioc_page3->NumPhysDisks;
 1383         for (; ioc_disk != ioc_last_disk; ioc_disk++) {
 1384                 struct mpt_raid_disk *mpt_disk;
 1385 
 1386                 mpt_disk = mpt->raid_disks + ioc_disk->PhysDiskNum;
 1387                 mpt_disk->flags |= MPT_RDF_REFERENCED;
 1388                 if ((mpt_disk->flags & (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE))
 1389                  != (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) {
 1390                         mpt_refresh_raid_disk(mpt, mpt_disk, ioc_disk);
 1391                 }
 1392                 mpt_disk->flags |= MPT_RDF_ACTIVE;
 1393                 mpt->raid_rescan++;
 1394         }
 1395 
 1396         /*
 1397          * Refresh volume data.
 1398          */
 1399         len = mpt->ioc_page2->Header.PageLength * sizeof(uint32_t);
 1400         rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0,
 1401                                    &mpt->ioc_page2->Header, len,
 1402                                    /*sleep_ok*/TRUE, /*timeout_ms*/5000);
 1403         if (rv) {
 1404                 mpt_prt(mpt, "mpt_refresh_raid_data: "
 1405                         "Failed to read IOC Page 2\n");
 1406                 return (-1);
 1407         }
 1408         mpt2host_config_page_ioc2(mpt->ioc_page2);
 1409 
 1410         ioc_vol = mpt->ioc_page2->RaidVolume;
 1411         ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
 1412         for (;ioc_vol != ioc_last_vol; ioc_vol++) {
 1413                 struct mpt_raid_volume *mpt_vol;
 1414 
 1415                 mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber;
 1416                 mpt_vol->flags |= MPT_RVF_REFERENCED;
 1417                 vol_pg = mpt_vol->config_page;
 1418                 if (vol_pg == NULL)
 1419                         continue;
 1420                 if (((mpt_vol->flags & (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE))
 1421                   != (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE))
 1422                  || (vol_pg->VolumeStatus.Flags
 1423                    & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) != 0) {
 1424                         mpt_refresh_raid_vol(mpt, mpt_vol, ioc_vol);
 1425                 }
 1426                 mpt_vol->flags |= MPT_RVF_ACTIVE;
 1427         }
 1428 
 1429         nonopt_volumes = 0;
 1430         for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
 1431                 struct mpt_raid_volume *mpt_vol;
 1432                 uint64_t total;
 1433                 uint64_t left;
 1434                 int m;
 1435                 u_int prio;
 1436 
 1437                 mpt_vol = &mpt->raid_volumes[i];
 1438 
 1439                 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
 1440                         continue;
 1441                 }
 1442 
 1443                 vol_pg = mpt_vol->config_page;
 1444                 if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED))
 1445                  == MPT_RVF_ANNOUNCED) {
 1446                         mpt_vol_prt(mpt, mpt_vol, "No longer configured\n");
 1447                         mpt_vol->flags = 0;
 1448                         continue;
 1449                 }
 1450 
 1451                 if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) {
 1452                         mpt_announce_vol(mpt, mpt_vol);
 1453                         mpt_vol->flags |= MPT_RVF_ANNOUNCED;
 1454                 }
 1455 
 1456                 if (vol_pg->VolumeStatus.State !=
 1457                     MPI_RAIDVOL0_STATUS_STATE_OPTIMAL)
 1458                         nonopt_volumes++;
 1459 
 1460                 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0)
 1461                         continue;
 1462 
 1463                 mpt_vol->flags |= MPT_RVF_UP2DATE;
 1464                 mpt_vol_prt(mpt, mpt_vol, "%s - %s\n",
 1465                     mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol));
 1466                 mpt_verify_mwce(mpt, mpt_vol);
 1467 
 1468                 if (vol_pg->VolumeStatus.Flags == 0) {
 1469                         continue;
 1470                 }
 1471 
 1472                 mpt_vol_prt(mpt, mpt_vol, "Status (");
 1473                 for (m = 1; m <= 0x80; m <<= 1) {
 1474                         switch (vol_pg->VolumeStatus.Flags & m) {
 1475                         case MPI_RAIDVOL0_STATUS_FLAG_ENABLED:
 1476                                 mpt_prtc(mpt, " Enabled");
 1477                                 break;
 1478                         case MPI_RAIDVOL0_STATUS_FLAG_QUIESCED:
 1479                                 mpt_prtc(mpt, " Quiesced");
 1480                                 break;
 1481                         case MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS:
 1482                                 mpt_prtc(mpt, " Re-Syncing");
 1483                                 break;
 1484                         case MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE:
 1485                                 mpt_prtc(mpt, " Inactive");
 1486                                 break;
 1487                         default:
 1488                                 break;
 1489                         }
 1490                 }
 1491                 mpt_prtc(mpt, " )\n");
 1492 
 1493                 if ((vol_pg->VolumeStatus.Flags
 1494                    & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
 1495                         continue;
 1496 
 1497                 mpt_verify_resync_rate(mpt, mpt_vol);
 1498 
 1499                 left = MPT_U64_2_SCALAR(mpt_vol->sync_progress.BlocksRemaining);
 1500                 total = MPT_U64_2_SCALAR(mpt_vol->sync_progress.TotalBlocks);
 1501                 if (vol_pg->ResyncRate != 0) {
 1502                         prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF;
 1503                         mpt_vol_prt(mpt, mpt_vol, "Rate %d.%d%%\n",
 1504                             prio / 1000, prio % 1000);
 1505                 } else {
 1506                         prio = vol_pg->VolumeSettings.Settings
 1507                              & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
 1508                         mpt_vol_prt(mpt, mpt_vol, "%s Priority Re-Sync\n",
 1509                             prio ? "High" : "Low");
 1510                 }
 1511                 mpt_vol_prt(mpt, mpt_vol, "%ju of %ju "
 1512                             "blocks remaining\n", (uintmax_t)left,
 1513                             (uintmax_t)total);
 1514 
 1515                 /* Periodically report on sync progress. */
 1516                 mpt_schedule_raid_refresh(mpt);
 1517         }
 1518 
 1519         for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
 1520                 struct mpt_raid_disk *mpt_disk;
 1521                 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
 1522                 int m;
 1523 
 1524                 mpt_disk = &mpt->raid_disks[i];
 1525                 disk_pg = &mpt_disk->config_page;
 1526 
 1527                 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0)
 1528                         continue;
 1529 
 1530                 if ((mpt_disk->flags & (MPT_RDF_REFERENCED|MPT_RDF_ANNOUNCED))
 1531                  == MPT_RDF_ANNOUNCED) {
 1532                         mpt_disk_prt(mpt, mpt_disk, "No longer configured\n");
 1533                         mpt_disk->flags = 0;
 1534                         mpt->raid_rescan++;
 1535                         continue;
 1536                 }
 1537 
 1538                 if ((mpt_disk->flags & MPT_RDF_ANNOUNCED) == 0) {
 1539                         mpt_announce_disk(mpt, mpt_disk);
 1540                         mpt_disk->flags |= MPT_RVF_ANNOUNCED;
 1541                 }
 1542 
 1543                 if ((mpt_disk->flags & MPT_RDF_UP2DATE) != 0)
 1544                         continue;
 1545 
 1546                 mpt_disk->flags |= MPT_RDF_UP2DATE;
 1547                 mpt_disk_prt(mpt, mpt_disk, "%s\n", mpt_disk_state(mpt_disk));
 1548                 if (disk_pg->PhysDiskStatus.Flags == 0)
 1549                         continue;
 1550 
 1551                 mpt_disk_prt(mpt, mpt_disk, "Status (");
 1552                 for (m = 1; m <= 0x80; m <<= 1) {
 1553                         switch (disk_pg->PhysDiskStatus.Flags & m) {
 1554                         case MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC:
 1555                                 mpt_prtc(mpt, " Out-Of-Sync");
 1556                                 break;
 1557                         case MPI_PHYSDISK0_STATUS_FLAG_QUIESCED:
 1558                                 mpt_prtc(mpt, " Quiesced");
 1559                                 break;
 1560                         default:
 1561                                 break;
 1562                         }
 1563                 }
 1564                 mpt_prtc(mpt, " )\n");
 1565         }
 1566 
 1567         mpt->raid_nonopt_volumes = nonopt_volumes;
 1568         return (0);
 1569 }
 1570 
 1571 static void
 1572 mpt_raid_timer(void *arg)
 1573 {
 1574         struct mpt_softc *mpt;
 1575 
 1576         mpt = (struct mpt_softc *)arg;
 1577         MPT_LOCK_ASSERT(mpt);
 1578         mpt_raid_wakeup(mpt);
 1579 }
 1580 
 1581 static void
 1582 mpt_schedule_raid_refresh(struct mpt_softc *mpt)
 1583 {
 1584 
 1585         callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL,
 1586                       mpt_raid_timer, mpt);
 1587 }
 1588 
 1589 void
 1590 mpt_raid_free_mem(struct mpt_softc *mpt)
 1591 {
 1592 
 1593         if (mpt->raid_volumes) {
 1594                 struct mpt_raid_volume *mpt_raid;
 1595                 int i;
 1596                 for (i = 0; i < mpt->raid_max_volumes; i++) {
 1597                         mpt_raid = &mpt->raid_volumes[i];
 1598                         if (mpt_raid->config_page) {
 1599                                 free(mpt_raid->config_page, M_DEVBUF);
 1600                                 mpt_raid->config_page = NULL;
 1601                         }
 1602                 }
 1603                 free(mpt->raid_volumes, M_DEVBUF);
 1604                 mpt->raid_volumes = NULL;
 1605         }
 1606         if (mpt->raid_disks) {
 1607                 free(mpt->raid_disks, M_DEVBUF);
 1608                 mpt->raid_disks = NULL;
 1609         }
 1610         if (mpt->ioc_page2) {
 1611                 free(mpt->ioc_page2, M_DEVBUF);
 1612                 mpt->ioc_page2 = NULL;
 1613         }
 1614         if (mpt->ioc_page3) {
 1615                 free(mpt->ioc_page3, M_DEVBUF);
 1616                 mpt->ioc_page3 = NULL;
 1617         }
 1618         mpt->raid_max_volumes =  0;
 1619         mpt->raid_max_disks =  0;
 1620 }
 1621 
 1622 static int
 1623 mpt_raid_set_vol_resync_rate(struct mpt_softc *mpt, u_int rate)
 1624 {
 1625         struct mpt_raid_volume *mpt_vol;
 1626 
 1627         if ((rate > MPT_RAID_RESYNC_RATE_MAX
 1628           || rate < MPT_RAID_RESYNC_RATE_MIN)
 1629          && rate != MPT_RAID_RESYNC_RATE_NC)
 1630                 return (EINVAL);
 1631 
 1632         MPT_LOCK(mpt);
 1633         mpt->raid_resync_rate = rate;
 1634         RAID_VOL_FOREACH(mpt, mpt_vol) {
 1635                 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
 1636                         continue;
 1637                 }
 1638                 mpt_verify_resync_rate(mpt, mpt_vol);
 1639         }
 1640         MPT_UNLOCK(mpt);
 1641         return (0);
 1642 }
 1643 
 1644 static int
 1645 mpt_raid_set_vol_queue_depth(struct mpt_softc *mpt, u_int vol_queue_depth)
 1646 {
 1647         struct mpt_raid_volume *mpt_vol;
 1648 
 1649         if (vol_queue_depth > 255 || vol_queue_depth < 1)
 1650                 return (EINVAL);
 1651 
 1652         MPT_LOCK(mpt);
 1653         mpt->raid_queue_depth = vol_queue_depth;
 1654         RAID_VOL_FOREACH(mpt, mpt_vol) {
 1655                 struct cam_path *path;
 1656                 int error;
 1657 
 1658                 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
 1659                         continue;
 1660 
 1661                 mpt->raid_rescan = 0;
 1662 
 1663                 error = xpt_create_path(&path, NULL,
 1664                                         cam_sim_path(mpt->sim),
 1665                                         mpt_vol->config_page->VolumeID,
 1666                                         /*lun*/0);
 1667                 if (error != CAM_REQ_CMP) {
 1668                         mpt_vol_prt(mpt, mpt_vol, "Unable to allocate path!\n");
 1669                         continue;
 1670                 }
 1671                 mpt_adjust_queue_depth(mpt, mpt_vol, path);
 1672                 xpt_free_path(path);
 1673         }
 1674         MPT_UNLOCK(mpt);
 1675         return (0);
 1676 }
 1677 
 1678 static int
 1679 mpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce)
 1680 {
 1681         struct mpt_raid_volume *mpt_vol;
 1682         int force_full_resync;
 1683 
 1684         MPT_LOCK(mpt);
 1685         if (mwce == mpt->raid_mwce_setting) {
 1686                 MPT_UNLOCK(mpt);
 1687                 return (0);
 1688         }
 1689 
 1690         /*
 1691          * Catch MWCE being left on due to a failed shutdown.  Since
 1692          * sysctls cannot be set by the loader, we treat the first
 1693          * setting of this varible specially and force a full volume
 1694          * resync if MWCE is enabled and a resync is in progress.
 1695          */
 1696         force_full_resync = 0;
 1697         if (mpt->raid_mwce_set == 0
 1698          && mpt->raid_mwce_setting == MPT_RAID_MWCE_NC
 1699          && mwce == MPT_RAID_MWCE_REBUILD_ONLY)
 1700                 force_full_resync = 1;
 1701 
 1702         mpt->raid_mwce_setting = mwce;
 1703         RAID_VOL_FOREACH(mpt, mpt_vol) {
 1704                 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
 1705                 int resyncing;
 1706                 int mwce;
 1707 
 1708                 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
 1709                         continue;
 1710 
 1711                 vol_pg = mpt_vol->config_page;
 1712                 resyncing = vol_pg->VolumeStatus.Flags
 1713                           & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
 1714                 mwce = vol_pg->VolumeSettings.Settings
 1715                      & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
 1716                 if (force_full_resync && resyncing && mwce) {
 1717                         /*
 1718                          * XXX disable/enable volume should force a resync,
 1719                          *     but we'll need to queice, drain, and restart
 1720                          *     I/O to do that.
 1721                          */
 1722                         mpt_vol_prt(mpt, mpt_vol, "WARNING - Unsafe shutdown "
 1723                                     "detected.  Suggest full resync.\n");
 1724                 }
 1725                 mpt_verify_mwce(mpt, mpt_vol);
 1726         }
 1727         mpt->raid_mwce_set = 1;
 1728         MPT_UNLOCK(mpt);
 1729         return (0);
 1730 }
 1731 
 1732 static const char *mpt_vol_mwce_strs[] =
 1733 {
 1734         "On",
 1735         "Off",
 1736         "On-During-Rebuild",
 1737         "NC"
 1738 };
 1739 
 1740 static int
 1741 mpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS)
 1742 {
 1743         char inbuf[20];
 1744         struct mpt_softc *mpt;
 1745         const char *str;
 1746         int error;
 1747         u_int size;
 1748         u_int i;
 1749 
 1750         mpt = (struct mpt_softc *)arg1;
 1751         str = mpt_vol_mwce_strs[mpt->raid_mwce_setting];
 1752         error = SYSCTL_OUT(req, str, strlen(str) + 1);
 1753         if (error || !req->newptr) {
 1754                 return (error);
 1755         }
 1756 
 1757         size = req->newlen - req->newidx;
 1758         if (size >= sizeof(inbuf)) {
 1759                 return (EINVAL);
 1760         }
 1761 
 1762         error = SYSCTL_IN(req, inbuf, size);
 1763         if (error) {
 1764                 return (error);
 1765         }
 1766         inbuf[size] = '\0'; 
 1767         for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) {
 1768                 if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) {
 1769                         return (mpt_raid_set_vol_mwce(mpt, i));
 1770                 }
 1771         }
 1772         return (EINVAL);
 1773 }
 1774 
 1775 static int
 1776 mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS)
 1777 {
 1778         struct mpt_softc *mpt;
 1779         u_int raid_resync_rate;
 1780         int error;
 1781 
 1782         mpt = (struct mpt_softc *)arg1;
 1783         raid_resync_rate = mpt->raid_resync_rate;
 1784 
 1785         error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req);
 1786         if (error || !req->newptr) {
 1787                 return error;
 1788         }
 1789 
 1790         return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate));
 1791 }
 1792 
 1793 static int
 1794 mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS)
 1795 {
 1796         struct mpt_softc *mpt;
 1797         u_int raid_queue_depth;
 1798         int error;
 1799 
 1800         mpt = (struct mpt_softc *)arg1;
 1801         raid_queue_depth = mpt->raid_queue_depth;
 1802 
 1803         error = sysctl_handle_int(oidp, &raid_queue_depth, 0, req);
 1804         if (error || !req->newptr) {
 1805                 return error;
 1806         }
 1807 
 1808         return (mpt_raid_set_vol_queue_depth(mpt, raid_queue_depth));
 1809 }
 1810 
 1811 static void
 1812 mpt_raid_sysctl_attach(struct mpt_softc *mpt)
 1813 {
 1814         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev);
 1815         struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev);
 1816 
 1817         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1818             "vol_member_wce", CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
 1819             mpt, 0, mpt_raid_sysctl_vol_member_wce, "A",
 1820             "volume member WCE(On,Off,On-During-Rebuild,NC)");
 1821 
 1822         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1823             "vol_queue_depth", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
 1824             mpt, 0, mpt_raid_sysctl_vol_queue_depth, "I",
 1825             "default volume queue depth");
 1826 
 1827         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1828             "vol_resync_rate", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
 1829             mpt, 0, mpt_raid_sysctl_vol_resync_rate, "I",
 1830             "volume resync priority (0 == NC, 1 - 255)");
 1831         SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1832                         "nonoptimal_volumes", CTLFLAG_RD,
 1833                         &mpt->raid_nonopt_volumes, 0,
 1834                         "number of nonoptimal volumes");
 1835 }

Cache object: 4faea395d2327085169068c3dd24dc95


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