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