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