2 * Routines for handling the integrated RAID features LSI MPT Fusion adapters.
4 * Copyright (c) 2005, WHEEL Sp. z o.o.
5 * Copyright (c) 2005 Justin T. Gibbs.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
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 at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon including
16 * a substantially similar Disclaimer requirement for further binary
18 * 3. Neither the names of the above listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
32 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * Some Breakage and Bug Fixing added later.
36 * Copyright (c) 2006, by Matthew Jacob
39 * Support from LSI-Logic has also gone a great deal toward making this a
40 * workable subsystem and is gratefully acknowledged.
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
46 #include <dev/mpt/mpt.h>
47 #include <dev/mpt/mpt_raid.h>
49 #include "dev/mpt/mpilib/mpi_ioc.h" /* XXX Fix Event Handling!!! */
50 #include "dev/mpt/mpilib/mpi_raid.h"
53 #include <cam/cam_ccb.h>
54 #include <cam/cam_sim.h>
55 #include <cam/cam_xpt_sim.h>
57 #if __FreeBSD_version < 500000
58 #include <sys/devicestat.h>
59 #define GIANT_REQUIRED
61 #include <cam/cam_periph.h>
63 #include <sys/callout.h>
64 #include <sys/kthread.h>
65 #include <sys/sysctl.h>
67 #include <machine/stdarg.h>
69 struct mpt_raid_action_result
72 MPI_RAID_VOL_INDICATOR indicator_struct;
73 uint32_t new_settings;
74 uint8_t phys_disk_num;
76 uint16_t action_status;
79 #define REQ_TO_RAID_ACTION_RESULT(req) ((struct mpt_raid_action_result *) \
80 (((MSG_RAID_ACTION_REQUEST *)(req->req_vbuf)) + 1))
82 #define REQ_IOCSTATUS(req) ((req)->IOCStatus & MPI_IOCSTATUS_MASK)
85 static mpt_probe_handler_t mpt_raid_probe;
86 static mpt_attach_handler_t mpt_raid_attach;
87 static mpt_enable_handler_t mpt_raid_enable;
88 static mpt_event_handler_t mpt_raid_event;
89 static mpt_shutdown_handler_t mpt_raid_shutdown;
90 static mpt_reset_handler_t mpt_raid_ioc_reset;
91 static mpt_detach_handler_t mpt_raid_detach;
93 static struct mpt_personality mpt_raid_personality =
96 .probe = mpt_raid_probe,
97 .attach = mpt_raid_attach,
98 .enable = mpt_raid_enable,
99 .event = mpt_raid_event,
100 .reset = mpt_raid_ioc_reset,
101 .shutdown = mpt_raid_shutdown,
102 .detach = mpt_raid_detach,
105 DECLARE_MPT_PERSONALITY(mpt_raid, SI_ORDER_THIRD);
106 MPT_PERSONALITY_DEPEND(mpt_raid, mpt_cam, 1, 1, 1);
108 static mpt_reply_handler_t mpt_raid_reply_handler;
109 static int mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
110 MSG_DEFAULT_REPLY *reply_frame);
111 static int mpt_spawn_raid_thread(struct mpt_softc *mpt);
112 static void mpt_terminate_raid_thread(struct mpt_softc *mpt);
113 static void mpt_raid_thread(void *arg);
114 static timeout_t mpt_raid_timer;
116 static void mpt_enable_vol(struct mpt_softc *mpt,
117 struct mpt_raid_volume *mpt_vol, int enable);
119 static void mpt_verify_mwce(struct mpt_softc *, struct mpt_raid_volume *);
120 static void mpt_adjust_queue_depth(struct mpt_softc *, struct mpt_raid_volume *,
122 #if __FreeBSD_version < 500000
123 #define mpt_raid_sysctl_attach(x) do { } while (0)
125 static void mpt_raid_sysctl_attach(struct mpt_softc *);
128 static uint32_t raid_handler_id = MPT_HANDLER_ID_NONE;
131 mpt_vol_type(struct mpt_raid_volume *vol)
133 switch (vol->config_page->VolumeType) {
134 case MPI_RAID_VOL_TYPE_IS:
136 case MPI_RAID_VOL_TYPE_IME:
138 case MPI_RAID_VOL_TYPE_IM:
146 mpt_vol_state(struct mpt_raid_volume *vol)
148 switch (vol->config_page->VolumeStatus.State) {
149 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
151 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
153 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
161 mpt_disk_state(struct mpt_raid_disk *disk)
163 switch (disk->config_page.PhysDiskStatus.State) {
164 case MPI_PHYSDISK0_STATUS_ONLINE:
166 case MPI_PHYSDISK0_STATUS_MISSING:
168 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
169 return ("Incompatible");
170 case MPI_PHYSDISK0_STATUS_FAILED:
172 case MPI_PHYSDISK0_STATUS_INITIALIZING:
173 return ("Initializing");
174 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
175 return ("Offline Requested");
176 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
177 return ("Failed per Host Request");
178 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
186 mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
187 const char *fmt, ...)
191 printf("%s:vol%d(%s:%d:%d): ", device_get_nameunit(mpt->dev),
192 (u_int)(vol - mpt->raid_volumes), device_get_nameunit(mpt->dev),
193 vol->config_page->VolumeBus, vol->config_page->VolumeID);
200 mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
201 const char *fmt, ...)
205 if (disk->volume != NULL) {
206 printf("(%s:vol%d:%d): ",
207 device_get_nameunit(mpt->dev),
208 disk->volume->config_page->VolumeID,
209 disk->member_number);
211 printf("(%s:%d:%d): ", device_get_nameunit(mpt->dev),
212 disk->config_page.PhysDiskBus,
213 disk->config_page.PhysDiskID);
221 mpt_raid_async(void *callback_arg, u_int32_t code,
222 struct cam_path *path, void *arg)
224 struct mpt_softc *mpt;
226 mpt = (struct mpt_softc*)callback_arg;
228 case AC_FOUND_DEVICE:
230 struct ccb_getdev *cgd;
231 struct mpt_raid_volume *mpt_vol;
233 cgd = (struct ccb_getdev *)arg;
238 mpt_lprt(mpt, MPT_PRT_DEBUG, "Callback for %d\n",
239 cgd->ccb_h.target_id);
241 RAID_VOL_FOREACH(mpt, mpt_vol) {
242 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
245 if (mpt_vol->config_page->VolumeID
246 == cgd->ccb_h.target_id) {
247 mpt_adjust_queue_depth(mpt, mpt_vol, path);
258 mpt_raid_probe(struct mpt_softc *mpt)
260 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
267 mpt_raid_attach(struct mpt_softc *mpt)
269 struct ccb_setasync csa;
270 mpt_handler_t handler;
273 mpt_callout_init(mpt, &mpt->raid_timer);
275 error = mpt_spawn_raid_thread(mpt);
277 mpt_prt(mpt, "Unable to spawn RAID thread!\n");
282 handler.reply_handler = mpt_raid_reply_handler;
283 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
286 mpt_prt(mpt, "Unable to register RAID haandler!\n");
290 xpt_setup_ccb(&csa.ccb_h, mpt->path, 5);
291 csa.ccb_h.func_code = XPT_SASYNC_CB;
292 csa.event_enable = AC_FOUND_DEVICE;
293 csa.callback = mpt_raid_async;
294 csa.callback_arg = mpt;
295 xpt_action((union ccb *)&csa);
296 if (csa.ccb_h.status != CAM_REQ_CMP) {
297 mpt_prt(mpt, "mpt_raid_attach: Unable to register "
298 "CAM async handler.\n");
302 mpt_raid_sysctl_attach(mpt);
306 mpt_raid_detach(mpt);
311 mpt_raid_enable(struct mpt_softc *mpt)
317 mpt_raid_detach(struct mpt_softc *mpt)
319 struct ccb_setasync csa;
320 mpt_handler_t handler;
322 mpt_callout_drain(mpt, &mpt->raid_timer);
325 mpt_terminate_raid_thread(mpt);
326 handler.reply_handler = mpt_raid_reply_handler;
327 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
329 xpt_setup_ccb(&csa.ccb_h, mpt->path, /*priority*/5);
330 csa.ccb_h.func_code = XPT_SASYNC_CB;
331 csa.event_enable = 0;
332 csa.callback = mpt_raid_async;
333 csa.callback_arg = mpt;
334 xpt_action((union ccb *)&csa);
339 mpt_raid_ioc_reset(struct mpt_softc *mpt, int type)
341 /* Nothing to do yet. */
344 static const char *raid_event_txt[] =
348 "Volume Settings Changed",
349 "Volume Status Changed",
350 "Volume Physical Disk Membership Changed",
351 "Physical Disk Created",
352 "Physical Disk Deleted",
353 "Physical Disk Settings Changed",
354 "Physical Disk Status Changed",
355 "Domain Validation Required",
356 "SMART Data Received",
357 "Replace Action Started",
361 mpt_raid_event(struct mpt_softc *mpt, request_t *req,
362 MSG_EVENT_NOTIFY_REPLY *msg)
364 EVENT_DATA_RAID *raid_event;
365 struct mpt_raid_volume *mpt_vol;
366 struct mpt_raid_disk *mpt_disk;
367 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
371 if (msg->Event != MPI_EVENT_INTEGRATED_RAID) {
375 raid_event = (EVENT_DATA_RAID *)&msg->Data;
379 if (mpt->raid_volumes != NULL && mpt->ioc_page2 != NULL) {
380 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
381 mpt_vol = &mpt->raid_volumes[i];
382 vol_pg = mpt_vol->config_page;
384 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
387 if (vol_pg->VolumeID == raid_event->VolumeID
388 && vol_pg->VolumeBus == raid_event->VolumeBus)
391 if (i >= mpt->ioc_page2->MaxVolumes) {
398 if (raid_event->PhysDiskNum != 0xFF && mpt->raid_disks != NULL) {
399 mpt_disk = mpt->raid_disks + raid_event->PhysDiskNum;
400 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) {
406 switch(raid_event->ReasonCode) {
407 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
408 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
410 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
411 if (mpt_vol != NULL) {
412 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) {
413 mpt_vol->flags &= ~MPT_RVF_UP2DATE;
416 * Coalesce status messages into one
417 * per background run of our RAID thread.
418 * This removes "spurious" status messages
425 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
426 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
428 if (mpt_vol != NULL) {
429 mpt_vol->flags &= ~(MPT_RVF_UP2DATE|MPT_RVF_ANNOUNCED);
432 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
433 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
436 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
437 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
439 if (mpt_disk != NULL) {
440 mpt_disk->flags &= ~MPT_RDF_UP2DATE;
443 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
446 case MPI_EVENT_RAID_RC_SMART_DATA:
447 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
452 if (mpt_disk != NULL) {
453 mpt_disk_prt(mpt, mpt_disk, "");
454 } else if (mpt_vol != NULL) {
455 mpt_vol_prt(mpt, mpt_vol, "");
457 mpt_prt(mpt, "Volume(%d:%d", raid_event->VolumeBus,
458 raid_event->VolumeID);
460 if (raid_event->PhysDiskNum != 0xFF)
461 mpt_prtc(mpt, ":%d): ",
462 raid_event->PhysDiskNum);
464 mpt_prtc(mpt, "): ");
467 if (raid_event->ReasonCode >= NUM_ELEMENTS(raid_event_txt))
468 mpt_prtc(mpt, "Unhandled RaidEvent %#x\n",
469 raid_event->ReasonCode);
471 mpt_prtc(mpt, "%s\n",
472 raid_event_txt[raid_event->ReasonCode]);
475 if (raid_event->ReasonCode == MPI_EVENT_RAID_RC_SMART_DATA) {
476 /* XXX Use CAM's print sense for this... */
477 if (mpt_disk != NULL)
478 mpt_disk_prt(mpt, mpt_disk, "");
480 mpt_prt(mpt, "Volume(%d:%d:%d: ",
481 raid_event->VolumeBus, raid_event->VolumeID,
482 raid_event->PhysDiskNum);
483 mpt_prtc(mpt, "ASC 0x%x, ASCQ 0x%x)\n",
484 raid_event->ASC, raid_event->ASCQ);
487 mpt_raid_wakeup(mpt);
492 mpt_raid_shutdown(struct mpt_softc *mpt)
494 struct mpt_raid_volume *mpt_vol;
496 if (mpt->raid_mwce_setting != MPT_RAID_MWCE_REBUILD_ONLY) {
500 mpt->raid_mwce_setting = MPT_RAID_MWCE_OFF;
501 RAID_VOL_FOREACH(mpt, mpt_vol) {
502 mpt_verify_mwce(mpt, mpt_vol);
507 mpt_raid_reply_handler(struct mpt_softc *mpt, request_t *req,
508 uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
516 if (reply_frame != NULL)
517 free_req = mpt_raid_reply_frame_handler(mpt, req, reply_frame);
519 else if (req->ccb != NULL) {
520 /* Complete Quiesce CCB with error... */
524 req->state &= ~REQ_STATE_QUEUED;
525 req->state |= REQ_STATE_DONE;
526 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
528 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
530 } else if (free_req) {
531 mpt_free_request(mpt, req);
538 * Parse additional completion information in the reply
539 * frame for RAID I/O requests.
542 mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
543 MSG_DEFAULT_REPLY *reply_frame)
545 MSG_RAID_ACTION_REPLY *reply;
546 struct mpt_raid_action_result *action_result;
547 MSG_RAID_ACTION_REQUEST *rap;
549 reply = (MSG_RAID_ACTION_REPLY *)reply_frame;
550 req->IOCStatus = le16toh(reply->IOCStatus);
551 rap = (MSG_RAID_ACTION_REQUEST *)req->req_vbuf;
553 switch (rap->Action) {
554 case MPI_RAID_ACTION_QUIESCE_PHYS_IO:
555 mpt_prt(mpt, "QUIESCE PHYSIO DONE\n");
557 case MPI_RAID_ACTION_ENABLE_PHYS_IO:
558 mpt_prt(mpt, "ENABLY PHYSIO DONE\n");
563 action_result = REQ_TO_RAID_ACTION_RESULT(req);
564 memcpy(&action_result->action_data, &reply->ActionData,
565 sizeof(action_result->action_data));
566 action_result->action_status = le16toh(reply->ActionStatus);
571 * Utiltity routine to perform a RAID action command;
574 mpt_issue_raid_req(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
575 struct mpt_raid_disk *disk, request_t *req, u_int Action,
576 uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
579 MSG_RAID_ACTION_REQUEST *rap;
583 memset(rap, 0, sizeof *rap);
584 rap->Action = Action;
585 rap->ActionDataWord = htole32(ActionDataWord);
586 rap->Function = MPI_FUNCTION_RAID_ACTION;
587 rap->VolumeID = vol->config_page->VolumeID;
588 rap->VolumeBus = vol->config_page->VolumeBus;
590 rap->PhysDiskNum = disk->config_page.PhysDiskNum;
592 rap->PhysDiskNum = 0xFF;
593 se = (SGE_SIMPLE32 *)&rap->ActionDataSGE;
594 se->Address = htole32(addr);
595 MPI_pSGE_SET_LENGTH(se, len);
596 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
597 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
598 MPI_SGE_FLAGS_END_OF_LIST |
599 write ? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST));
600 se->FlagsLength = htole32(se->FlagsLength);
601 rap->MsgContext = htole32(req->index | raid_handler_id);
603 mpt_check_doorbell(mpt);
604 mpt_send_cmd(mpt, req);
607 return (mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE,
608 /*sleep_ok*/FALSE, /*time_ms*/2000));
614 /*************************** RAID Status Monitoring ***************************/
616 mpt_spawn_raid_thread(struct mpt_softc *mpt)
621 * Freeze out any CAM transactions until our thread
622 * is able to run at least once. We need to update
623 * our RAID pages before acception I/O or we may
624 * reject I/O to an ID we later determine is for a
628 xpt_freeze_simq(mpt->phydisk_sim, 1);
630 error = mpt_kthread_create(mpt_raid_thread, mpt,
631 &mpt->raid_thread, /*flags*/0, /*altstack*/0,
632 "mpt_raid%d", mpt->unit);
635 xpt_release_simq(mpt->phydisk_sim, /*run_queue*/FALSE);
642 mpt_terminate_raid_thread(struct mpt_softc *mpt)
645 if (mpt->raid_thread == NULL) {
648 mpt->shutdwn_raid = 1;
649 wakeup(&mpt->raid_volumes);
651 * Sleep on a slightly different location
652 * for this interlock just for added safety.
654 mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0);
658 mpt_raid_thread(void *arg)
660 struct mpt_softc *mpt;
663 mpt = (struct mpt_softc *)arg;
666 while (mpt->shutdwn_raid == 0) {
668 if (mpt->raid_wakeup == 0) {
669 mpt_sleep(mpt, &mpt->raid_volumes, PUSER, "idle", 0);
673 mpt->raid_wakeup = 0;
675 if (mpt_refresh_raid_data(mpt)) {
676 mpt_schedule_raid_refresh(mpt); /* XX NOT QUITE RIGHT */
681 * Now that we have our first snapshot of RAID data,
682 * allow CAM to access our physical disk bus.
686 MPTLOCK_2_CAMLOCK(mpt);
687 xpt_release_simq(mpt->phydisk_sim, TRUE);
688 CAMLOCK_2_MPTLOCK(mpt);
691 if (mpt->raid_rescan != 0) {
695 mpt->raid_rescan = 0;
698 ccb = xpt_alloc_ccb();
701 error = xpt_create_path(&ccb->ccb_h.path, xpt_periph,
702 cam_sim_path(mpt->phydisk_sim),
703 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
704 if (error != CAM_REQ_CMP) {
706 mpt_prt(mpt, "Unable to rescan RAID Bus!\n");
712 mpt->raid_thread = NULL;
713 wakeup(&mpt->raid_thread);
720 mpt_raid_quiesce_timeout(void *arg)
722 /* Complete the CCB with error */
726 static timeout_t mpt_raid_quiesce_timeout;
728 mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
734 if ((mpt_disk->flags & MPT_RDF_QUIESCED) != 0)
735 return (CAM_REQ_CMP);
737 if ((mpt_disk->flags & MPT_RDF_QUIESCING) == 0) {
740 mpt_disk->flags |= MPT_RDF_QUIESCING;
741 xpt_freeze_devq(ccb->ccb_h.path, 1);
743 rv = mpt_issue_raid_req(mpt, mpt_disk->volume, mpt_disk, req,
744 MPI_RAID_ACTION_QUIESCE_PHYS_IO,
745 /*ActionData*/0, /*addr*/0,
746 /*len*/0, /*write*/FALSE,
749 return (CAM_REQ_CMP_ERR);
751 mpt_req_timeout(req, mpt_raid_quiesce_timeout, ccb, 5 * hz);
753 if (rv == ETIMEDOUT) {
754 mpt_disk_prt(mpt, mpt_disk, "mpt_raid_quiesce_disk: "
755 "Quiece Timed-out\n");
756 xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0);
757 return (CAM_REQ_CMP_ERR);
760 ar = REQ_TO_RAID_ACTION_RESULT(req);
762 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
763 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
764 mpt_disk_prt(mpt, mpt_disk, "Quiece Failed"
765 "%d:%x:%x\n", rv, req->IOCStatus,
767 xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0);
768 return (CAM_REQ_CMP_ERR);
771 return (CAM_REQ_INPROG);
773 return (CAM_REQUEUE_REQ);
777 /* XXX Ignores that there may be multiple busses/IOCs involved. */
779 mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, u_int *tgt)
781 struct mpt_raid_disk *mpt_disk;
783 mpt_disk = mpt->raid_disks + ccb->ccb_h.target_id;
784 if (ccb->ccb_h.target_id < mpt->raid_max_disks
785 && (mpt_disk->flags & MPT_RDF_ACTIVE) != 0) {
786 *tgt = mpt_disk->config_page.PhysDiskID;
789 mpt_lprt(mpt, MPT_PRT_DEBUG1, "mpt_map_physdisk(%d) - Not Active\n",
790 ccb->ccb_h.target_id);
794 /* XXX Ignores that there may be multiple busses/IOCs involved. */
796 mpt_is_raid_volume(struct mpt_softc *mpt, int tgt)
798 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
799 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
801 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
804 ioc_vol = mpt->ioc_page2->RaidVolume;
805 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
806 for (;ioc_vol != ioc_last_vol; ioc_vol++) {
807 if (ioc_vol->VolumeID == tgt) {
816 mpt_enable_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
820 struct mpt_raid_action_result *ar;
821 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
825 vol_pg = mpt_vol->config_page;
826 enabled = vol_pg->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED;
829 * If the setting matches the configuration,
830 * there is nothing to do.
832 if ((enabled && enable)
833 || (!enabled && !enable))
836 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
838 mpt_vol_prt(mpt, mpt_vol,
839 "mpt_enable_vol: Get request failed!\n");
843 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
844 enable ? MPI_RAID_ACTION_ENABLE_VOLUME
845 : MPI_RAID_ACTION_DISABLE_VOLUME,
846 /*data*/0, /*addr*/0, /*len*/0,
847 /*write*/FALSE, /*wait*/TRUE);
848 if (rv == ETIMEDOUT) {
849 mpt_vol_prt(mpt, mpt_vol, "mpt_enable_vol: "
850 "%s Volume Timed-out\n",
851 enable ? "Enable" : "Disable");
854 ar = REQ_TO_RAID_ACTION_RESULT(req);
856 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
857 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
858 mpt_vol_prt(mpt, mpt_vol, "%s Volume Failed: %d:%x:%x\n",
859 enable ? "Enable" : "Disable",
860 rv, req->IOCStatus, ar->action_status);
863 mpt_free_request(mpt, req);
868 mpt_verify_mwce(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
871 struct mpt_raid_action_result *ar;
872 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
878 vol_pg = mpt_vol->config_page;
879 resyncing = vol_pg->VolumeStatus.Flags
880 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
881 mwce = vol_pg->VolumeSettings.Settings
882 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
885 * If the setting matches the configuration,
886 * there is nothing to do.
888 switch (mpt->raid_mwce_setting) {
889 case MPT_RAID_MWCE_REBUILD_ONLY:
890 if ((resyncing && mwce) || (!resyncing && !mwce)) {
893 mpt_vol->flags ^= MPT_RVF_WCE_CHANGED;
894 if ((mpt_vol->flags & MPT_RVF_WCE_CHANGED) == 0) {
896 * Wait one more status update to see if
897 * resyncing gets enabled. It gets disabled
898 * temporarilly when WCE is changed.
903 case MPT_RAID_MWCE_ON:
907 case MPT_RAID_MWCE_OFF:
911 case MPT_RAID_MWCE_NC:
915 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
917 mpt_vol_prt(mpt, mpt_vol,
918 "mpt_verify_mwce: Get request failed!\n");
922 vol_pg->VolumeSettings.Settings ^=
923 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
924 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data));
925 vol_pg->VolumeSettings.Settings ^=
926 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
927 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
928 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
929 data, /*addr*/0, /*len*/0,
930 /*write*/FALSE, /*wait*/TRUE);
931 if (rv == ETIMEDOUT) {
932 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_mwce: "
933 "Write Cache Enable Timed-out\n");
936 ar = REQ_TO_RAID_ACTION_RESULT(req);
938 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
939 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
940 mpt_vol_prt(mpt, mpt_vol, "Write Cache Enable Failed: "
941 "%d:%x:%x\n", rv, req->IOCStatus,
944 vol_pg->VolumeSettings.Settings ^=
945 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
947 mpt_free_request(mpt, req);
951 mpt_verify_resync_rate(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
954 struct mpt_raid_action_result *ar;
955 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
959 vol_pg = mpt_vol->config_page;
961 if (mpt->raid_resync_rate == MPT_RAID_RESYNC_RATE_NC)
965 * If the current RAID resync rate does not
966 * match our configured rate, update it.
968 prio = vol_pg->VolumeSettings.Settings
969 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
970 if (vol_pg->ResyncRate != 0
971 && vol_pg->ResyncRate != mpt->raid_resync_rate) {
973 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
975 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: "
976 "Get request failed!\n");
980 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
981 MPI_RAID_ACTION_SET_RESYNC_RATE,
982 mpt->raid_resync_rate, /*addr*/0,
983 /*len*/0, /*write*/FALSE, /*wait*/TRUE);
984 if (rv == ETIMEDOUT) {
985 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: "
986 "Resync Rate Setting Timed-out\n");
990 ar = REQ_TO_RAID_ACTION_RESULT(req);
992 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
993 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
994 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: "
995 "%d:%x:%x\n", rv, req->IOCStatus,
998 vol_pg->ResyncRate = mpt->raid_resync_rate;
999 mpt_free_request(mpt, req);
1000 } else if ((prio && mpt->raid_resync_rate < 128)
1001 || (!prio && mpt->raid_resync_rate >= 128)) {
1004 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
1006 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: "
1007 "Get request failed!\n");
1011 vol_pg->VolumeSettings.Settings ^=
1012 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1013 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data));
1014 vol_pg->VolumeSettings.Settings ^=
1015 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1016 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
1017 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
1018 data, /*addr*/0, /*len*/0,
1019 /*write*/FALSE, /*wait*/TRUE);
1020 if (rv == ETIMEDOUT) {
1021 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: "
1022 "Resync Rate Setting Timed-out\n");
1025 ar = REQ_TO_RAID_ACTION_RESULT(req);
1027 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
1028 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
1029 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: "
1030 "%d:%x:%x\n", rv, req->IOCStatus,
1033 vol_pg->VolumeSettings.Settings ^=
1034 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1037 mpt_free_request(mpt, req);
1042 mpt_adjust_queue_depth(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
1043 struct cam_path *path)
1045 struct ccb_relsim crs;
1047 xpt_setup_ccb(&crs.ccb_h, path, /*priority*/5);
1048 crs.ccb_h.func_code = XPT_REL_SIMQ;
1049 crs.ccb_h.flags = CAM_DEV_QFREEZE;
1050 crs.release_flags = RELSIM_ADJUST_OPENINGS;
1051 crs.openings = mpt->raid_queue_depth;
1052 xpt_action((union ccb *)&crs);
1053 if (crs.ccb_h.status != CAM_REQ_CMP)
1054 mpt_vol_prt(mpt, mpt_vol, "mpt_adjust_queue_depth failed "
1055 "with CAM status %#x\n", crs.ccb_h.status);
1059 mpt_announce_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
1061 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1064 vol_pg = mpt_vol->config_page;
1065 mpt_vol_prt(mpt, mpt_vol, "Settings (");
1066 for (i = 1; i <= 0x8000; i <<= 1) {
1067 switch (vol_pg->VolumeSettings.Settings & i) {
1068 case MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE:
1069 mpt_prtc(mpt, " Member-WCE");
1071 case MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART:
1072 mpt_prtc(mpt, " Offline-On-SMART-Err");
1074 case MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE:
1075 mpt_prtc(mpt, " Hot-Plug-Spares");
1077 case MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC:
1078 mpt_prtc(mpt, " High-Priority-ReSync");
1084 mpt_prtc(mpt, " )\n");
1085 if (vol_pg->VolumeSettings.HotSparePool != 0) {
1086 mpt_vol_prt(mpt, mpt_vol, "Using Spare Pool%s",
1087 powerof2(vol_pg->VolumeSettings.HotSparePool)
1089 for (i = 0; i < 8; i++) {
1093 if ((vol_pg->VolumeSettings.HotSparePool & mask) == 0)
1095 mpt_prtc(mpt, " %d", i);
1097 mpt_prtc(mpt, "\n");
1099 mpt_vol_prt(mpt, mpt_vol, "%d Members:\n", vol_pg->NumPhysDisks);
1100 for (i = 0; i < vol_pg->NumPhysDisks; i++){
1101 struct mpt_raid_disk *mpt_disk;
1102 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
1103 int pt_bus = cam_sim_bus(mpt->phydisk_sim);
1106 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
1107 disk_pg = &mpt_disk->config_page;
1109 mpt_prtc(mpt, "(%s:%d:%d:0): ", device_get_nameunit(mpt->dev),
1110 pt_bus, disk_pg->PhysDiskID);
1111 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) {
1112 mpt_prtc(mpt, "%s", mpt_disk->member_number == 0?
1113 "Primary" : "Secondary");
1115 mpt_prtc(mpt, "Stripe Position %d",
1116 mpt_disk->member_number);
1118 f = disk_pg->PhysDiskStatus.Flags;
1119 s = disk_pg->PhysDiskStatus.State;
1120 if (f & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC) {
1121 mpt_prtc(mpt, " Out of Sync");
1123 if (f & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED) {
1124 mpt_prtc(mpt, " Quiesced");
1126 if (f & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) {
1127 mpt_prtc(mpt, " Inactive");
1129 if (f & MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS) {
1130 mpt_prtc(mpt, " Was Optimal");
1132 if (f & MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS) {
1133 mpt_prtc(mpt, " Was Non-Optimal");
1136 case MPI_PHYSDISK0_STATUS_ONLINE:
1137 mpt_prtc(mpt, " Online");
1139 case MPI_PHYSDISK0_STATUS_MISSING:
1140 mpt_prtc(mpt, " Missing");
1142 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
1143 mpt_prtc(mpt, " Incompatible");
1145 case MPI_PHYSDISK0_STATUS_FAILED:
1146 mpt_prtc(mpt, " Failed");
1148 case MPI_PHYSDISK0_STATUS_INITIALIZING:
1149 mpt_prtc(mpt, " Initializing");
1151 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
1152 mpt_prtc(mpt, " Requested Offline");
1154 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
1155 mpt_prtc(mpt, " Requested Failed");
1157 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
1159 mpt_prtc(mpt, " Offline Other (%x)", s);
1162 mpt_prtc(mpt, "\n");
1167 mpt_announce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk)
1169 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
1170 int rd_bus = cam_sim_bus(mpt->sim);
1171 int pt_bus = cam_sim_bus(mpt->phydisk_sim);
1174 disk_pg = &mpt_disk->config_page;
1175 mpt_disk_prt(mpt, mpt_disk,
1176 "Physical (%s:%d:%d:0), Pass-thru (%s:%d:%d:0)\n",
1177 device_get_nameunit(mpt->dev), rd_bus,
1178 disk_pg->PhysDiskID, device_get_nameunit(mpt->dev),
1179 pt_bus, mpt_disk - mpt->raid_disks);
1180 if (disk_pg->PhysDiskSettings.HotSparePool == 0)
1182 mpt_disk_prt(mpt, mpt_disk, "Member of Hot Spare Pool%s",
1183 powerof2(disk_pg->PhysDiskSettings.HotSparePool)
1185 for (i = 0; i < 8; i++) {
1189 if ((disk_pg->PhysDiskSettings.HotSparePool & mask) == 0)
1191 mpt_prtc(mpt, " %d", i);
1193 mpt_prtc(mpt, "\n");
1197 mpt_refresh_raid_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
1198 IOC_3_PHYS_DISK *ioc_disk)
1202 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK,
1203 /*PageNumber*/0, ioc_disk->PhysDiskNum,
1204 &mpt_disk->config_page.Header,
1205 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1207 mpt_prt(mpt, "mpt_refresh_raid_disk: "
1208 "Failed to read RAID Disk Hdr(%d)\n",
1209 ioc_disk->PhysDiskNum);
1212 rv = mpt_read_cur_cfg_page(mpt, ioc_disk->PhysDiskNum,
1213 &mpt_disk->config_page.Header,
1214 sizeof(mpt_disk->config_page),
1215 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1217 mpt_prt(mpt, "mpt_refresh_raid_disk: "
1218 "Failed to read RAID Disk Page(%d)\n",
1219 ioc_disk->PhysDiskNum);
1220 mpt2host_config_page_raid_phys_disk_0(&mpt_disk->config_page);
1224 mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
1225 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol)
1227 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1228 struct mpt_raid_action_result *ar;
1233 vol_pg = mpt_vol->config_page;
1234 mpt_vol->flags &= ~MPT_RVF_UP2DATE;
1236 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0,
1237 ioc_vol->VolumePageNumber, &vol_pg->Header, TRUE, 5000);
1239 mpt_vol_prt(mpt, mpt_vol,
1240 "mpt_refresh_raid_vol: Failed to read RAID Vol Hdr(%d)\n",
1241 ioc_vol->VolumePageNumber);
1245 rv = mpt_read_cur_cfg_page(mpt, ioc_vol->VolumePageNumber,
1246 &vol_pg->Header, mpt->raid_page0_len, TRUE, 5000);
1248 mpt_vol_prt(mpt, mpt_vol,
1249 "mpt_refresh_raid_vol: Failed to read RAID Vol Page(%d)\n",
1250 ioc_vol->VolumePageNumber);
1253 mpt2host_config_page_raid_vol_0(vol_pg);
1255 mpt_vol->flags |= MPT_RVF_ACTIVE;
1257 /* Update disk entry array data. */
1258 for (i = 0; i < vol_pg->NumPhysDisks; i++) {
1259 struct mpt_raid_disk *mpt_disk;
1260 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
1261 mpt_disk->volume = mpt_vol;
1262 mpt_disk->member_number = vol_pg->PhysDisk[i].PhysDiskMap;
1263 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) {
1264 mpt_disk->member_number--;
1268 if ((vol_pg->VolumeStatus.Flags
1269 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
1272 req = mpt_get_request(mpt, TRUE);
1274 mpt_vol_prt(mpt, mpt_vol,
1275 "mpt_refresh_raid_vol: Get request failed!\n");
1278 rv = mpt_issue_raid_req(mpt, mpt_vol, NULL, req,
1279 MPI_RAID_ACTION_INDICATOR_STRUCT, 0, 0, 0, FALSE, TRUE);
1280 if (rv == ETIMEDOUT) {
1281 mpt_vol_prt(mpt, mpt_vol,
1282 "mpt_refresh_raid_vol: Progress Indicator fetch timeout\n");
1283 mpt_free_request(mpt, req);
1287 ar = REQ_TO_RAID_ACTION_RESULT(req);
1289 && ar->action_status == MPI_RAID_ACTION_ASTATUS_SUCCESS
1290 && REQ_IOCSTATUS(req) == MPI_IOCSTATUS_SUCCESS) {
1291 memcpy(&mpt_vol->sync_progress,
1292 &ar->action_data.indicator_struct,
1293 sizeof(mpt_vol->sync_progress));
1294 mpt2host_mpi_raid_vol_indicator(&mpt_vol->sync_progress);
1296 mpt_vol_prt(mpt, mpt_vol,
1297 "mpt_refresh_raid_vol: Progress indicator fetch failed!\n");
1299 mpt_free_request(mpt, req);
1303 * Update in-core information about RAID support. We update any entries
1304 * that didn't previously exists or have been marked as needing to
1305 * be updated by our event handler. Interesting changes are displayed
1309 mpt_refresh_raid_data(struct mpt_softc *mpt)
1311 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
1312 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
1313 IOC_3_PHYS_DISK *ioc_disk;
1314 IOC_3_PHYS_DISK *ioc_last_disk;
1315 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1319 u_int nonopt_volumes;
1321 if (mpt->ioc_page2 == NULL || mpt->ioc_page3 == NULL) {
1326 * Mark all items as unreferenced by the configuration.
1327 * This allows us to find, report, and discard stale
1330 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
1331 mpt->raid_disks[i].flags &= ~MPT_RDF_REFERENCED;
1333 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
1334 mpt->raid_volumes[i].flags &= ~MPT_RVF_REFERENCED;
1338 * Get Physical Disk information.
1340 len = mpt->ioc_page3->Header.PageLength * sizeof(uint32_t);
1341 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0,
1342 &mpt->ioc_page3->Header, len,
1343 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1346 "mpt_refresh_raid_data: Failed to read IOC Page 3\n");
1349 mpt2host_config_page_ioc3(mpt->ioc_page3);
1351 ioc_disk = mpt->ioc_page3->PhysDisk;
1352 ioc_last_disk = ioc_disk + mpt->ioc_page3->NumPhysDisks;
1353 for (; ioc_disk != ioc_last_disk; ioc_disk++) {
1354 struct mpt_raid_disk *mpt_disk;
1356 mpt_disk = mpt->raid_disks + ioc_disk->PhysDiskNum;
1357 mpt_disk->flags |= MPT_RDF_REFERENCED;
1358 if ((mpt_disk->flags & (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE))
1359 != (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) {
1361 mpt_refresh_raid_disk(mpt, mpt_disk, ioc_disk);
1364 mpt_disk->flags |= MPT_RDF_ACTIVE;
1369 * Refresh volume data.
1371 len = mpt->ioc_page2->Header.PageLength * sizeof(uint32_t);
1372 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0,
1373 &mpt->ioc_page2->Header, len,
1374 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1376 mpt_prt(mpt, "mpt_refresh_raid_data: "
1377 "Failed to read IOC Page 2\n");
1380 mpt2host_config_page_ioc2(mpt->ioc_page2);
1382 ioc_vol = mpt->ioc_page2->RaidVolume;
1383 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
1384 for (;ioc_vol != ioc_last_vol; ioc_vol++) {
1385 struct mpt_raid_volume *mpt_vol;
1387 mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber;
1388 mpt_vol->flags |= MPT_RVF_REFERENCED;
1389 vol_pg = mpt_vol->config_page;
1392 if (((mpt_vol->flags & (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE))
1393 != (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE))
1394 || (vol_pg->VolumeStatus.Flags
1395 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) != 0) {
1397 mpt_refresh_raid_vol(mpt, mpt_vol, ioc_vol);
1399 mpt_vol->flags |= MPT_RVF_ACTIVE;
1403 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
1404 struct mpt_raid_volume *mpt_vol;
1410 mpt_vol = &mpt->raid_volumes[i];
1412 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
1416 vol_pg = mpt_vol->config_page;
1417 if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED))
1418 == MPT_RVF_ANNOUNCED) {
1419 mpt_vol_prt(mpt, mpt_vol, "No longer configured\n");
1424 if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) {
1425 mpt_announce_vol(mpt, mpt_vol);
1426 mpt_vol->flags |= MPT_RVF_ANNOUNCED;
1429 if (vol_pg->VolumeStatus.State !=
1430 MPI_RAIDVOL0_STATUS_STATE_OPTIMAL)
1433 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0)
1436 mpt_vol->flags |= MPT_RVF_UP2DATE;
1437 mpt_vol_prt(mpt, mpt_vol, "%s - %s\n",
1438 mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol));
1439 mpt_verify_mwce(mpt, mpt_vol);
1441 if (vol_pg->VolumeStatus.Flags == 0) {
1445 mpt_vol_prt(mpt, mpt_vol, "Status (");
1446 for (m = 1; m <= 0x80; m <<= 1) {
1447 switch (vol_pg->VolumeStatus.Flags & m) {
1448 case MPI_RAIDVOL0_STATUS_FLAG_ENABLED:
1449 mpt_prtc(mpt, " Enabled");
1451 case MPI_RAIDVOL0_STATUS_FLAG_QUIESCED:
1452 mpt_prtc(mpt, " Quiesced");
1454 case MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS:
1455 mpt_prtc(mpt, " Re-Syncing");
1457 case MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE:
1458 mpt_prtc(mpt, " Inactive");
1464 mpt_prtc(mpt, " )\n");
1466 if ((vol_pg->VolumeStatus.Flags
1467 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
1470 mpt_verify_resync_rate(mpt, mpt_vol);
1472 left = MPT_U64_2_SCALAR(mpt_vol->sync_progress.BlocksRemaining);
1473 total = MPT_U64_2_SCALAR(mpt_vol->sync_progress.TotalBlocks);
1474 if (vol_pg->ResyncRate != 0) {
1476 prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF;
1477 mpt_vol_prt(mpt, mpt_vol, "Rate %d.%d%%\n",
1478 prio / 1000, prio % 1000);
1480 prio = vol_pg->VolumeSettings.Settings
1481 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1482 mpt_vol_prt(mpt, mpt_vol, "%s Priority Re-Sync\n",
1483 prio ? "High" : "Low");
1485 #if __FreeBSD_version >= 500000
1486 mpt_vol_prt(mpt, mpt_vol, "%ju of %ju "
1487 "blocks remaining\n", (uintmax_t)left,
1490 mpt_vol_prt(mpt, mpt_vol, "%llu of %llu "
1491 "blocks remaining\n", (uint64_t)left,
1495 /* Periodically report on sync progress. */
1496 mpt_schedule_raid_refresh(mpt);
1499 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
1500 struct mpt_raid_disk *mpt_disk;
1501 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
1504 mpt_disk = &mpt->raid_disks[i];
1505 disk_pg = &mpt_disk->config_page;
1507 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0)
1510 if ((mpt_disk->flags & (MPT_RDF_REFERENCED|MPT_RDF_ANNOUNCED))
1511 == MPT_RDF_ANNOUNCED) {
1512 mpt_disk_prt(mpt, mpt_disk, "No longer configured\n");
1513 mpt_disk->flags = 0;
1518 if ((mpt_disk->flags & MPT_RDF_ANNOUNCED) == 0) {
1520 mpt_announce_disk(mpt, mpt_disk);
1521 mpt_disk->flags |= MPT_RVF_ANNOUNCED;
1524 if ((mpt_disk->flags & MPT_RDF_UP2DATE) != 0)
1527 mpt_disk->flags |= MPT_RDF_UP2DATE;
1528 mpt_disk_prt(mpt, mpt_disk, "%s\n", mpt_disk_state(mpt_disk));
1529 if (disk_pg->PhysDiskStatus.Flags == 0)
1532 mpt_disk_prt(mpt, mpt_disk, "Status (");
1533 for (m = 1; m <= 0x80; m <<= 1) {
1534 switch (disk_pg->PhysDiskStatus.Flags & m) {
1535 case MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC:
1536 mpt_prtc(mpt, " Out-Of-Sync");
1538 case MPI_PHYSDISK0_STATUS_FLAG_QUIESCED:
1539 mpt_prtc(mpt, " Quiesced");
1545 mpt_prtc(mpt, " )\n");
1548 mpt->raid_nonopt_volumes = nonopt_volumes;
1553 mpt_raid_timer(void *arg)
1555 struct mpt_softc *mpt;
1557 mpt = (struct mpt_softc *)arg;
1558 #if __FreeBSD_version < 500000
1561 MPT_LOCK_ASSERT(mpt);
1562 mpt_raid_wakeup(mpt);
1563 #if __FreeBSD_version < 500000
1569 mpt_schedule_raid_refresh(struct mpt_softc *mpt)
1571 callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL,
1572 mpt_raid_timer, mpt);
1576 mpt_raid_free_mem(struct mpt_softc *mpt)
1579 if (mpt->raid_volumes) {
1580 struct mpt_raid_volume *mpt_raid;
1582 for (i = 0; i < mpt->raid_max_volumes; i++) {
1583 mpt_raid = &mpt->raid_volumes[i];
1584 if (mpt_raid->config_page) {
1585 free(mpt_raid->config_page, M_DEVBUF);
1586 mpt_raid->config_page = NULL;
1589 free(mpt->raid_volumes, M_DEVBUF);
1590 mpt->raid_volumes = NULL;
1592 if (mpt->raid_disks) {
1593 free(mpt->raid_disks, M_DEVBUF);
1594 mpt->raid_disks = NULL;
1596 if (mpt->ioc_page2) {
1597 free(mpt->ioc_page2, M_DEVBUF);
1598 mpt->ioc_page2 = NULL;
1600 if (mpt->ioc_page3) {
1601 free(mpt->ioc_page3, M_DEVBUF);
1602 mpt->ioc_page3 = NULL;
1604 mpt->raid_max_volumes = 0;
1605 mpt->raid_max_disks = 0;
1608 #if __FreeBSD_version >= 500000
1610 mpt_raid_set_vol_resync_rate(struct mpt_softc *mpt, u_int rate)
1612 struct mpt_raid_volume *mpt_vol;
1614 if ((rate > MPT_RAID_RESYNC_RATE_MAX
1615 || rate < MPT_RAID_RESYNC_RATE_MIN)
1616 && rate != MPT_RAID_RESYNC_RATE_NC)
1620 mpt->raid_resync_rate = rate;
1621 RAID_VOL_FOREACH(mpt, mpt_vol) {
1622 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
1625 mpt_verify_resync_rate(mpt, mpt_vol);
1632 mpt_raid_set_vol_queue_depth(struct mpt_softc *mpt, u_int vol_queue_depth)
1634 struct mpt_raid_volume *mpt_vol;
1636 if (vol_queue_depth > 255 || vol_queue_depth < 1)
1640 mpt->raid_queue_depth = vol_queue_depth;
1641 RAID_VOL_FOREACH(mpt, mpt_vol) {
1642 struct cam_path *path;
1645 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
1648 mpt->raid_rescan = 0;
1650 MPTLOCK_2_CAMLOCK(mpt);
1651 error = xpt_create_path(&path, xpt_periph,
1652 cam_sim_path(mpt->sim),
1653 mpt_vol->config_page->VolumeID,
1655 if (error != CAM_REQ_CMP) {
1656 CAMLOCK_2_MPTLOCK(mpt);
1657 mpt_vol_prt(mpt, mpt_vol, "Unable to allocate path!\n");
1660 mpt_adjust_queue_depth(mpt, mpt_vol, path);
1661 xpt_free_path(path);
1662 CAMLOCK_2_MPTLOCK(mpt);
1669 mpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce)
1671 struct mpt_raid_volume *mpt_vol;
1672 int force_full_resync;
1675 if (mwce == mpt->raid_mwce_setting) {
1681 * Catch MWCE being left on due to a failed shutdown. Since
1682 * sysctls cannot be set by the loader, we treat the first
1683 * setting of this varible specially and force a full volume
1684 * resync if MWCE is enabled and a resync is in progress.
1686 force_full_resync = 0;
1687 if (mpt->raid_mwce_set == 0
1688 && mpt->raid_mwce_setting == MPT_RAID_MWCE_NC
1689 && mwce == MPT_RAID_MWCE_REBUILD_ONLY)
1690 force_full_resync = 1;
1692 mpt->raid_mwce_setting = mwce;
1693 RAID_VOL_FOREACH(mpt, mpt_vol) {
1694 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1698 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
1701 vol_pg = mpt_vol->config_page;
1702 resyncing = vol_pg->VolumeStatus.Flags
1703 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
1704 mwce = vol_pg->VolumeSettings.Settings
1705 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
1706 if (force_full_resync && resyncing && mwce) {
1709 * XXX disable/enable volume should force a resync,
1710 * but we'll need to queice, drain, and restart
1713 mpt_vol_prt(mpt, mpt_vol, "WARNING - Unsafe shutdown "
1714 "detected. Suggest full resync.\n");
1716 mpt_verify_mwce(mpt, mpt_vol);
1718 mpt->raid_mwce_set = 1;
1722 const char *mpt_vol_mwce_strs[] =
1726 "On-During-Rebuild",
1731 mpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS)
1734 struct mpt_softc *mpt;
1742 mpt = (struct mpt_softc *)arg1;
1743 str = mpt_vol_mwce_strs[mpt->raid_mwce_setting];
1744 error = SYSCTL_OUT(req, str, strlen(str) + 1);
1745 if (error || !req->newptr) {
1749 size = req->newlen - req->newidx;
1750 if (size >= sizeof(inbuf)) {
1754 error = SYSCTL_IN(req, inbuf, size);
1759 for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) {
1760 if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) {
1761 return (mpt_raid_set_vol_mwce(mpt, i));
1768 mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS)
1770 struct mpt_softc *mpt;
1771 u_int raid_resync_rate;
1776 mpt = (struct mpt_softc *)arg1;
1777 raid_resync_rate = mpt->raid_resync_rate;
1779 error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req);
1780 if (error || !req->newptr) {
1784 return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate));
1788 mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS)
1790 struct mpt_softc *mpt;
1791 u_int raid_queue_depth;
1796 mpt = (struct mpt_softc *)arg1;
1797 raid_queue_depth = mpt->raid_queue_depth;
1799 error = sysctl_handle_int(oidp, &raid_queue_depth, 0, req);
1800 if (error || !req->newptr) {
1804 return (mpt_raid_set_vol_queue_depth(mpt, raid_queue_depth));
1808 mpt_raid_sysctl_attach(struct mpt_softc *mpt)
1810 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev);
1811 struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev);
1813 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1814 "vol_member_wce", CTLTYPE_STRING | CTLFLAG_RW, mpt, 0,
1815 mpt_raid_sysctl_vol_member_wce, "A",
1816 "volume member WCE(On,Off,On-During-Rebuild,NC)");
1818 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1819 "vol_queue_depth", CTLTYPE_INT | CTLFLAG_RW, mpt, 0,
1820 mpt_raid_sysctl_vol_queue_depth, "I",
1821 "default volume queue depth");
1823 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1824 "vol_resync_rate", CTLTYPE_INT | CTLFLAG_RW, mpt, 0,
1825 mpt_raid_sysctl_vol_resync_rate, "I",
1826 "volume resync priority (0 == NC, 1 - 255)");
1827 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1828 "nonoptimal_volumes", CTLFLAG_RD,
1829 &mpt->raid_nonopt_volumes, 0,
1830 "number of nonoptimal volumes");