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