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