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