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