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