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