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