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