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