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