1 /*- 2 * Routines for handling the integrated RAID features LSI MPT Fusion adapters. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 2005, WHEEL Sp. z o.o. 7 * Copyright (c) 2005 Justin T. Gibbs. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are 12 * met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16 * substantially similar to the "NO WARRANTY" disclaimer below 17 * ("Disclaimer") and any redistribution must be conditioned upon including 18 * a substantially similar Disclaimer requirement for further binary 19 * redistribution. 20 * 3. Neither the names of the above listed copyright holders nor the names 21 * of any contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 34 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 /*- 37 * Some Breakage and Bug Fixing added later. 38 * Copyright (c) 2006, by Matthew Jacob 39 * All Rights Reserved 40 * 41 * Support from LSI-Logic has also gone a great deal toward making this a 42 * workable subsystem and is gratefully acknowledged. 43 */ 44 45 #include <sys/cdefs.h> 46 #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/stdarg.h> 61 #include <sys/sysctl.h> 62 63 struct mpt_raid_action_result 64 { 65 union { 66 MPI_RAID_VOL_INDICATOR indicator_struct; 67 uint32_t new_settings; 68 uint8_t phys_disk_num; 69 } action_data; 70 uint16_t action_status; 71 }; 72 73 #define REQ_TO_RAID_ACTION_RESULT(req) ((struct mpt_raid_action_result *) \ 74 (((MSG_RAID_ACTION_REQUEST *)(req->req_vbuf)) + 1)) 75 76 #define REQ_IOCSTATUS(req) ((req)->IOCStatus & MPI_IOCSTATUS_MASK) 77 78 static mpt_probe_handler_t mpt_raid_probe; 79 static mpt_attach_handler_t mpt_raid_attach; 80 static mpt_enable_handler_t mpt_raid_enable; 81 static mpt_event_handler_t mpt_raid_event; 82 static mpt_shutdown_handler_t mpt_raid_shutdown; 83 static mpt_reset_handler_t mpt_raid_ioc_reset; 84 static mpt_detach_handler_t mpt_raid_detach; 85 86 static struct mpt_personality mpt_raid_personality = 87 { 88 .name = "mpt_raid", 89 .probe = mpt_raid_probe, 90 .attach = mpt_raid_attach, 91 .enable = mpt_raid_enable, 92 .event = mpt_raid_event, 93 .reset = mpt_raid_ioc_reset, 94 .shutdown = mpt_raid_shutdown, 95 .detach = mpt_raid_detach, 96 }; 97 98 DECLARE_MPT_PERSONALITY(mpt_raid, SI_ORDER_THIRD); 99 MPT_PERSONALITY_DEPEND(mpt_raid, mpt_cam, 1, 1, 1); 100 101 static mpt_reply_handler_t mpt_raid_reply_handler; 102 static int mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req, 103 MSG_DEFAULT_REPLY *reply_frame); 104 static int mpt_spawn_raid_thread(struct mpt_softc *mpt); 105 static void mpt_terminate_raid_thread(struct mpt_softc *mpt); 106 static void mpt_raid_thread(void *arg); 107 static callout_func_t mpt_raid_timer; 108 #if 0 109 static void mpt_enable_vol(struct mpt_softc *mpt, 110 struct mpt_raid_volume *mpt_vol, int enable); 111 #endif 112 static void mpt_verify_mwce(struct mpt_softc *, struct mpt_raid_volume *); 113 static void mpt_adjust_queue_depth(struct mpt_softc *, struct mpt_raid_volume *, 114 struct cam_path *); 115 static void mpt_raid_sysctl_attach(struct mpt_softc *); 116 117 static const char *mpt_vol_type(struct mpt_raid_volume *vol); 118 static const char *mpt_vol_state(struct mpt_raid_volume *vol); 119 static const char *mpt_disk_state(struct mpt_raid_disk *disk); 120 static void mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol, 121 const char *fmt, ...); 122 static void mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk, 123 const char *fmt, ...); 124 125 static int mpt_issue_raid_req(struct mpt_softc *mpt, 126 struct mpt_raid_volume *vol, struct mpt_raid_disk *disk, request_t *req, 127 u_int Action, uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len, 128 int write, int wait); 129 130 static int mpt_refresh_raid_data(struct mpt_softc *mpt); 131 static void mpt_schedule_raid_refresh(struct mpt_softc *mpt); 132 133 static uint32_t raid_handler_id = MPT_HANDLER_ID_NONE; 134 135 static const char * 136 mpt_vol_type(struct mpt_raid_volume *vol) 137 { 138 switch (vol->config_page->VolumeType) { 139 case MPI_RAID_VOL_TYPE_IS: 140 return ("RAID-0"); 141 case MPI_RAID_VOL_TYPE_IME: 142 return ("RAID-1E"); 143 case MPI_RAID_VOL_TYPE_IM: 144 return ("RAID-1"); 145 default: 146 return ("Unknown"); 147 } 148 } 149 150 static const char * 151 mpt_vol_state(struct mpt_raid_volume *vol) 152 { 153 switch (vol->config_page->VolumeStatus.State) { 154 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: 155 return ("Optimal"); 156 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: 157 return ("Degraded"); 158 case MPI_RAIDVOL0_STATUS_STATE_FAILED: 159 return ("Failed"); 160 default: 161 return ("Unknown"); 162 } 163 } 164 165 static const char * 166 mpt_disk_state(struct mpt_raid_disk *disk) 167 { 168 switch (disk->config_page.PhysDiskStatus.State) { 169 case MPI_PHYSDISK0_STATUS_ONLINE: 170 return ("Online"); 171 case MPI_PHYSDISK0_STATUS_MISSING: 172 return ("Missing"); 173 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE: 174 return ("Incompatible"); 175 case MPI_PHYSDISK0_STATUS_FAILED: 176 return ("Failed"); 177 case MPI_PHYSDISK0_STATUS_INITIALIZING: 178 return ("Initializing"); 179 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED: 180 return ("Offline Requested"); 181 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED: 182 return ("Failed per Host Request"); 183 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE: 184 return ("Offline"); 185 default: 186 return ("Unknown"); 187 } 188 } 189 190 static void 191 mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol, 192 const char *fmt, ...) 193 { 194 va_list ap; 195 196 printf("%s:vol%d(%s:%d:%d): ", device_get_nameunit(mpt->dev), 197 (u_int)(vol - mpt->raid_volumes), device_get_nameunit(mpt->dev), 198 vol->config_page->VolumeBus, vol->config_page->VolumeID); 199 va_start(ap, fmt); 200 vprintf(fmt, ap); 201 va_end(ap); 202 } 203 204 static void 205 mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk, 206 const char *fmt, ...) 207 { 208 va_list ap; 209 210 if (disk->volume != NULL) { 211 printf("(%s:vol%d:%d): ", 212 device_get_nameunit(mpt->dev), 213 disk->volume->config_page->VolumeID, 214 disk->member_number); 215 } else { 216 printf("(%s:%d:%d): ", device_get_nameunit(mpt->dev), 217 disk->config_page.PhysDiskBus, 218 disk->config_page.PhysDiskID); 219 } 220 va_start(ap, fmt); 221 vprintf(fmt, ap); 222 va_end(ap); 223 } 224 225 static void 226 mpt_raid_async(void *callback_arg, u_int32_t code, 227 struct cam_path *path, void *arg) 228 { 229 struct mpt_softc *mpt; 230 231 mpt = (struct mpt_softc*)callback_arg; 232 switch (code) { 233 case AC_FOUND_DEVICE: 234 { 235 struct ccb_getdev *cgd; 236 struct mpt_raid_volume *mpt_vol; 237 238 cgd = (struct ccb_getdev *)arg; 239 if (cgd == NULL) { 240 break; 241 } 242 243 mpt_lprt(mpt, MPT_PRT_DEBUG, "Callback for %d\n", 244 cgd->ccb_h.target_id); 245 246 RAID_VOL_FOREACH(mpt, mpt_vol) { 247 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 248 continue; 249 250 if (mpt_vol->config_page->VolumeID 251 == cgd->ccb_h.target_id) { 252 mpt_adjust_queue_depth(mpt, mpt_vol, path); 253 break; 254 } 255 } 256 } 257 default: 258 break; 259 } 260 } 261 262 static int 263 mpt_raid_probe(struct mpt_softc *mpt) 264 { 265 266 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) { 267 return (ENODEV); 268 } 269 return (0); 270 } 271 272 static int 273 mpt_raid_attach(struct mpt_softc *mpt) 274 { 275 struct ccb_setasync csa; 276 mpt_handler_t handler; 277 int error; 278 279 mpt_callout_init(mpt, &mpt->raid_timer); 280 281 error = mpt_spawn_raid_thread(mpt); 282 if (error != 0) { 283 mpt_prt(mpt, "Unable to spawn RAID thread!\n"); 284 goto cleanup; 285 } 286 287 MPT_LOCK(mpt); 288 handler.reply_handler = mpt_raid_reply_handler; 289 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 290 &raid_handler_id); 291 if (error != 0) { 292 mpt_prt(mpt, "Unable to register RAID haandler!\n"); 293 goto cleanup; 294 } 295 296 memset(&csa, 0, sizeof(csa)); 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 memset(&csa, 0, sizeof(csa)); 338 xpt_setup_ccb(&csa.ccb_h, mpt->path, /*priority*/5); 339 csa.ccb_h.func_code = XPT_SASYNC_CB; 340 csa.event_enable = 0; 341 csa.callback = mpt_raid_async; 342 csa.callback_arg = mpt; 343 xpt_action((union ccb *)&csa); 344 MPT_UNLOCK(mpt); 345 } 346 347 static void 348 mpt_raid_ioc_reset(struct mpt_softc *mpt, int type) 349 { 350 351 /* Nothing to do yet. */ 352 } 353 354 static const char *raid_event_txt[] = 355 { 356 "Volume Created", 357 "Volume Deleted", 358 "Volume Settings Changed", 359 "Volume Status Changed", 360 "Volume Physical Disk Membership Changed", 361 "Physical Disk Created", 362 "Physical Disk Deleted", 363 "Physical Disk Settings Changed", 364 "Physical Disk Status Changed", 365 "Domain Validation Required", 366 "SMART Data Received", 367 "Replace Action Started", 368 }; 369 370 static int 371 mpt_raid_event(struct mpt_softc *mpt, request_t *req, 372 MSG_EVENT_NOTIFY_REPLY *msg) 373 { 374 EVENT_DATA_RAID *raid_event; 375 struct mpt_raid_volume *mpt_vol; 376 struct mpt_raid_disk *mpt_disk; 377 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 378 int i; 379 int print_event; 380 381 if (msg->Event != MPI_EVENT_INTEGRATED_RAID) { 382 return (0); 383 } 384 385 raid_event = (EVENT_DATA_RAID *)&msg->Data; 386 387 mpt_vol = NULL; 388 vol_pg = NULL; 389 if (mpt->raid_volumes != NULL && mpt->ioc_page2 != NULL) { 390 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 391 mpt_vol = &mpt->raid_volumes[i]; 392 vol_pg = mpt_vol->config_page; 393 394 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 395 continue; 396 397 if (vol_pg->VolumeID == raid_event->VolumeID 398 && vol_pg->VolumeBus == raid_event->VolumeBus) 399 break; 400 } 401 if (i >= mpt->ioc_page2->MaxVolumes) { 402 mpt_vol = NULL; 403 vol_pg = NULL; 404 } 405 } 406 407 mpt_disk = NULL; 408 if (raid_event->PhysDiskNum != 0xFF && mpt->raid_disks != NULL) { 409 mpt_disk = mpt->raid_disks + raid_event->PhysDiskNum; 410 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) { 411 mpt_disk = NULL; 412 } 413 } 414 415 print_event = 1; 416 switch(raid_event->ReasonCode) { 417 case MPI_EVENT_RAID_RC_VOLUME_CREATED: 418 case MPI_EVENT_RAID_RC_VOLUME_DELETED: 419 break; 420 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: 421 if (mpt_vol != NULL) { 422 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) { 423 mpt_vol->flags &= ~MPT_RVF_UP2DATE; 424 } else { 425 /* 426 * Coalesce status messages into one 427 * per background run of our RAID thread. 428 * This removes "spurious" status messages 429 * from our output. 430 */ 431 print_event = 0; 432 } 433 } 434 break; 435 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED: 436 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED: 437 mpt->raid_rescan++; 438 if (mpt_vol != NULL) { 439 mpt_vol->flags &= ~(MPT_RVF_UP2DATE|MPT_RVF_ANNOUNCED); 440 } 441 break; 442 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: 443 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: 444 mpt->raid_rescan++; 445 break; 446 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED: 447 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: 448 mpt->raid_rescan++; 449 if (mpt_disk != NULL) { 450 mpt_disk->flags &= ~MPT_RDF_UP2DATE; 451 } 452 break; 453 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED: 454 mpt->raid_rescan++; 455 break; 456 case MPI_EVENT_RAID_RC_SMART_DATA: 457 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED: 458 break; 459 } 460 461 if (print_event) { 462 if (mpt_disk != NULL) { 463 mpt_disk_prt(mpt, mpt_disk, ""); 464 } else if (mpt_vol != NULL) { 465 mpt_vol_prt(mpt, mpt_vol, ""); 466 } else { 467 mpt_prt(mpt, "Volume(%d:%d", raid_event->VolumeBus, 468 raid_event->VolumeID); 469 470 if (raid_event->PhysDiskNum != 0xFF) 471 mpt_prtc(mpt, ":%d): ", 472 raid_event->PhysDiskNum); 473 else 474 mpt_prtc(mpt, "): "); 475 } 476 477 if (raid_event->ReasonCode >= NUM_ELEMENTS(raid_event_txt)) 478 mpt_prtc(mpt, "Unhandled RaidEvent %#x\n", 479 raid_event->ReasonCode); 480 else 481 mpt_prtc(mpt, "%s\n", 482 raid_event_txt[raid_event->ReasonCode]); 483 } 484 485 if (raid_event->ReasonCode == MPI_EVENT_RAID_RC_SMART_DATA) { 486 /* XXX Use CAM's print sense for this... */ 487 if (mpt_disk != NULL) 488 mpt_disk_prt(mpt, mpt_disk, ""); 489 else 490 mpt_prt(mpt, "Volume(%d:%d:%d: ", 491 raid_event->VolumeBus, raid_event->VolumeID, 492 raid_event->PhysDiskNum); 493 mpt_prtc(mpt, "ASC 0x%x, ASCQ 0x%x)\n", 494 raid_event->ASC, raid_event->ASCQ); 495 } 496 497 mpt_raid_wakeup(mpt); 498 return (1); 499 } 500 501 static void 502 mpt_raid_shutdown(struct mpt_softc *mpt) 503 { 504 struct mpt_raid_volume *mpt_vol; 505 506 if (mpt->raid_mwce_setting != MPT_RAID_MWCE_REBUILD_ONLY) { 507 return; 508 } 509 510 mpt->raid_mwce_setting = MPT_RAID_MWCE_OFF; 511 RAID_VOL_FOREACH(mpt, mpt_vol) { 512 mpt_verify_mwce(mpt, mpt_vol); 513 } 514 } 515 516 static int 517 mpt_raid_reply_handler(struct mpt_softc *mpt, request_t *req, 518 uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) 519 { 520 int free_req; 521 522 if (req == NULL) 523 return (TRUE); 524 525 free_req = TRUE; 526 if (reply_frame != NULL) 527 free_req = mpt_raid_reply_frame_handler(mpt, req, reply_frame); 528 #ifdef NOTYET 529 else if (req->ccb != NULL) { 530 /* Complete Quiesce CCB with error... */ 531 } 532 #endif 533 534 req->state &= ~REQ_STATE_QUEUED; 535 req->state |= REQ_STATE_DONE; 536 TAILQ_REMOVE(&mpt->request_pending_list, req, links); 537 538 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { 539 wakeup(req); 540 } else if (free_req) { 541 mpt_free_request(mpt, req); 542 } 543 544 return (TRUE); 545 } 546 547 /* 548 * Parse additional completion information in the reply 549 * frame for RAID I/O requests. 550 */ 551 static int 552 mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req, 553 MSG_DEFAULT_REPLY *reply_frame) 554 { 555 MSG_RAID_ACTION_REPLY *reply; 556 struct mpt_raid_action_result *action_result; 557 MSG_RAID_ACTION_REQUEST *rap; 558 559 reply = (MSG_RAID_ACTION_REPLY *)reply_frame; 560 req->IOCStatus = le16toh(reply->IOCStatus); 561 rap = (MSG_RAID_ACTION_REQUEST *)req->req_vbuf; 562 563 switch (rap->Action) { 564 case MPI_RAID_ACTION_QUIESCE_PHYS_IO: 565 mpt_prt(mpt, "QUIESCE PHYSIO DONE\n"); 566 break; 567 case MPI_RAID_ACTION_ENABLE_PHYS_IO: 568 mpt_prt(mpt, "ENABLY PHYSIO DONE\n"); 569 break; 570 default: 571 break; 572 } 573 action_result = REQ_TO_RAID_ACTION_RESULT(req); 574 memcpy(&action_result->action_data, &reply->ActionData, 575 sizeof(action_result->action_data)); 576 action_result->action_status = le16toh(reply->ActionStatus); 577 return (TRUE); 578 } 579 580 /* 581 * Utiltity routine to perform a RAID action command; 582 */ 583 static int 584 mpt_issue_raid_req(struct mpt_softc *mpt, struct mpt_raid_volume *vol, 585 struct mpt_raid_disk *disk, request_t *req, u_int Action, 586 uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len, 587 int write, int wait) 588 { 589 MSG_RAID_ACTION_REQUEST *rap; 590 SGE_SIMPLE32 *se; 591 592 rap = req->req_vbuf; 593 memset(rap, 0, sizeof *rap); 594 rap->Action = Action; 595 rap->ActionDataWord = htole32(ActionDataWord); 596 rap->Function = MPI_FUNCTION_RAID_ACTION; 597 rap->VolumeID = vol->config_page->VolumeID; 598 rap->VolumeBus = vol->config_page->VolumeBus; 599 if (disk != NULL) 600 rap->PhysDiskNum = disk->config_page.PhysDiskNum; 601 else 602 rap->PhysDiskNum = 0xFF; 603 se = (SGE_SIMPLE32 *)&rap->ActionDataSGE; 604 se->Address = htole32(addr); 605 MPI_pSGE_SET_LENGTH(se, len); 606 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 607 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 608 MPI_SGE_FLAGS_END_OF_LIST | 609 (write ? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST))); 610 se->FlagsLength = htole32(se->FlagsLength); 611 rap->MsgContext = htole32(req->index | raid_handler_id); 612 613 mpt_check_doorbell(mpt); 614 mpt_send_cmd(mpt, req); 615 616 if (wait) { 617 return (mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, 618 /*sleep_ok*/FALSE, /*time_ms*/2000)); 619 } else { 620 return (0); 621 } 622 } 623 624 /*************************** RAID Status Monitoring ***************************/ 625 static int 626 mpt_spawn_raid_thread(struct mpt_softc *mpt) 627 { 628 int error; 629 630 /* 631 * Freeze out any CAM transactions until our thread 632 * is able to run at least once. We need to update 633 * our RAID pages before acception I/O or we may 634 * reject I/O to an ID we later determine is for a 635 * hidden physdisk. 636 */ 637 MPT_LOCK(mpt); 638 xpt_freeze_simq(mpt->phydisk_sim, 1); 639 MPT_UNLOCK(mpt); 640 error = kproc_create(mpt_raid_thread, mpt, 641 &mpt->raid_thread, /*flags*/0, /*altstack*/0, 642 "mpt_raid%d", mpt->unit); 643 if (error != 0) { 644 MPT_LOCK(mpt); 645 xpt_release_simq(mpt->phydisk_sim, /*run_queue*/FALSE); 646 MPT_UNLOCK(mpt); 647 } 648 return (error); 649 } 650 651 static void 652 mpt_terminate_raid_thread(struct mpt_softc *mpt) 653 { 654 655 if (mpt->raid_thread == NULL) { 656 return; 657 } 658 mpt->shutdwn_raid = 1; 659 wakeup(&mpt->raid_volumes); 660 /* 661 * Sleep on a slightly different location 662 * for this interlock just for added safety. 663 */ 664 mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0); 665 } 666 667 static void 668 mpt_raid_thread(void *arg) 669 { 670 struct mpt_softc *mpt; 671 int firstrun; 672 673 mpt = (struct mpt_softc *)arg; 674 firstrun = 1; 675 MPT_LOCK(mpt); 676 while (mpt->shutdwn_raid == 0) { 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 req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 1000 if (req == NULL) { 1001 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: " 1002 "Get request failed!\n"); 1003 return; 1004 } 1005 1006 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 1007 MPI_RAID_ACTION_SET_RESYNC_RATE, 1008 mpt->raid_resync_rate, /*addr*/0, 1009 /*len*/0, /*write*/FALSE, /*wait*/TRUE); 1010 if (rv == ETIMEDOUT) { 1011 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: " 1012 "Resync Rate Setting Timed-out\n"); 1013 return; 1014 } 1015 1016 ar = REQ_TO_RAID_ACTION_RESULT(req); 1017 if (rv != 0 1018 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 1019 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 1020 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: " 1021 "%d:%x:%x\n", rv, req->IOCStatus, 1022 ar->action_status); 1023 } else 1024 vol_pg->ResyncRate = mpt->raid_resync_rate; 1025 mpt_free_request(mpt, req); 1026 } else if ((prio && mpt->raid_resync_rate < 128) 1027 || (!prio && mpt->raid_resync_rate >= 128)) { 1028 uint32_t data; 1029 1030 req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 1031 if (req == NULL) { 1032 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: " 1033 "Get request failed!\n"); 1034 return; 1035 } 1036 1037 vol_pg->VolumeSettings.Settings ^= 1038 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1039 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data)); 1040 vol_pg->VolumeSettings.Settings ^= 1041 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1042 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 1043 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 1044 data, /*addr*/0, /*len*/0, 1045 /*write*/FALSE, /*wait*/TRUE); 1046 if (rv == ETIMEDOUT) { 1047 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: " 1048 "Resync Rate Setting Timed-out\n"); 1049 return; 1050 } 1051 ar = REQ_TO_RAID_ACTION_RESULT(req); 1052 if (rv != 0 1053 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 1054 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 1055 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: " 1056 "%d:%x:%x\n", rv, req->IOCStatus, 1057 ar->action_status); 1058 } else { 1059 vol_pg->VolumeSettings.Settings ^= 1060 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1061 } 1062 1063 mpt_free_request(mpt, req); 1064 } 1065 } 1066 1067 static void 1068 mpt_adjust_queue_depth(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 1069 struct cam_path *path) 1070 { 1071 struct ccb_relsim crs; 1072 1073 memset(&crs, 0, sizeof(crs)); 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 mpt_refresh_raid_disk(mpt, mpt_disk, ioc_disk); 1388 } 1389 mpt_disk->flags |= MPT_RDF_ACTIVE; 1390 mpt->raid_rescan++; 1391 } 1392 1393 /* 1394 * Refresh volume data. 1395 */ 1396 len = mpt->ioc_page2->Header.PageLength * sizeof(uint32_t); 1397 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1398 &mpt->ioc_page2->Header, len, 1399 /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1400 if (rv) { 1401 mpt_prt(mpt, "mpt_refresh_raid_data: " 1402 "Failed to read IOC Page 2\n"); 1403 return (-1); 1404 } 1405 mpt2host_config_page_ioc2(mpt->ioc_page2); 1406 1407 ioc_vol = mpt->ioc_page2->RaidVolume; 1408 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes; 1409 for (;ioc_vol != ioc_last_vol; ioc_vol++) { 1410 struct mpt_raid_volume *mpt_vol; 1411 1412 mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber; 1413 mpt_vol->flags |= MPT_RVF_REFERENCED; 1414 vol_pg = mpt_vol->config_page; 1415 if (vol_pg == NULL) 1416 continue; 1417 if (((mpt_vol->flags & (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE)) 1418 != (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE)) 1419 || (vol_pg->VolumeStatus.Flags 1420 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) != 0) { 1421 mpt_refresh_raid_vol(mpt, mpt_vol, ioc_vol); 1422 } 1423 mpt_vol->flags |= MPT_RVF_ACTIVE; 1424 } 1425 1426 nonopt_volumes = 0; 1427 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 1428 struct mpt_raid_volume *mpt_vol; 1429 uint64_t total; 1430 uint64_t left; 1431 int m; 1432 u_int prio; 1433 1434 mpt_vol = &mpt->raid_volumes[i]; 1435 1436 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) { 1437 continue; 1438 } 1439 1440 vol_pg = mpt_vol->config_page; 1441 if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED)) 1442 == MPT_RVF_ANNOUNCED) { 1443 mpt_vol_prt(mpt, mpt_vol, "No longer configured\n"); 1444 mpt_vol->flags = 0; 1445 continue; 1446 } 1447 1448 if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) { 1449 mpt_announce_vol(mpt, mpt_vol); 1450 mpt_vol->flags |= MPT_RVF_ANNOUNCED; 1451 } 1452 1453 if (vol_pg->VolumeStatus.State != 1454 MPI_RAIDVOL0_STATUS_STATE_OPTIMAL) 1455 nonopt_volumes++; 1456 1457 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) 1458 continue; 1459 1460 mpt_vol->flags |= MPT_RVF_UP2DATE; 1461 mpt_vol_prt(mpt, mpt_vol, "%s - %s\n", 1462 mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol)); 1463 mpt_verify_mwce(mpt, mpt_vol); 1464 1465 if (vol_pg->VolumeStatus.Flags == 0) { 1466 continue; 1467 } 1468 1469 mpt_vol_prt(mpt, mpt_vol, "Status ("); 1470 for (m = 1; m <= 0x80; m <<= 1) { 1471 switch (vol_pg->VolumeStatus.Flags & m) { 1472 case MPI_RAIDVOL0_STATUS_FLAG_ENABLED: 1473 mpt_prtc(mpt, " Enabled"); 1474 break; 1475 case MPI_RAIDVOL0_STATUS_FLAG_QUIESCED: 1476 mpt_prtc(mpt, " Quiesced"); 1477 break; 1478 case MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS: 1479 mpt_prtc(mpt, " Re-Syncing"); 1480 break; 1481 case MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE: 1482 mpt_prtc(mpt, " Inactive"); 1483 break; 1484 default: 1485 break; 1486 } 1487 } 1488 mpt_prtc(mpt, " )\n"); 1489 1490 if ((vol_pg->VolumeStatus.Flags 1491 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0) 1492 continue; 1493 1494 mpt_verify_resync_rate(mpt, mpt_vol); 1495 1496 left = MPT_U64_2_SCALAR(mpt_vol->sync_progress.BlocksRemaining); 1497 total = MPT_U64_2_SCALAR(mpt_vol->sync_progress.TotalBlocks); 1498 if (vol_pg->ResyncRate != 0) { 1499 prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF; 1500 mpt_vol_prt(mpt, mpt_vol, "Rate %d.%d%%\n", 1501 prio / 1000, prio % 1000); 1502 } else { 1503 prio = vol_pg->VolumeSettings.Settings 1504 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1505 mpt_vol_prt(mpt, mpt_vol, "%s Priority Re-Sync\n", 1506 prio ? "High" : "Low"); 1507 } 1508 mpt_vol_prt(mpt, mpt_vol, "%ju of %ju " 1509 "blocks remaining\n", (uintmax_t)left, 1510 (uintmax_t)total); 1511 1512 /* Periodically report on sync progress. */ 1513 mpt_schedule_raid_refresh(mpt); 1514 } 1515 1516 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 1517 struct mpt_raid_disk *mpt_disk; 1518 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1519 int m; 1520 1521 mpt_disk = &mpt->raid_disks[i]; 1522 disk_pg = &mpt_disk->config_page; 1523 1524 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) 1525 continue; 1526 1527 if ((mpt_disk->flags & (MPT_RDF_REFERENCED|MPT_RDF_ANNOUNCED)) 1528 == MPT_RDF_ANNOUNCED) { 1529 mpt_disk_prt(mpt, mpt_disk, "No longer configured\n"); 1530 mpt_disk->flags = 0; 1531 mpt->raid_rescan++; 1532 continue; 1533 } 1534 1535 if ((mpt_disk->flags & MPT_RDF_ANNOUNCED) == 0) { 1536 mpt_announce_disk(mpt, mpt_disk); 1537 mpt_disk->flags |= MPT_RVF_ANNOUNCED; 1538 } 1539 1540 if ((mpt_disk->flags & MPT_RDF_UP2DATE) != 0) 1541 continue; 1542 1543 mpt_disk->flags |= MPT_RDF_UP2DATE; 1544 mpt_disk_prt(mpt, mpt_disk, "%s\n", mpt_disk_state(mpt_disk)); 1545 if (disk_pg->PhysDiskStatus.Flags == 0) 1546 continue; 1547 1548 mpt_disk_prt(mpt, mpt_disk, "Status ("); 1549 for (m = 1; m <= 0x80; m <<= 1) { 1550 switch (disk_pg->PhysDiskStatus.Flags & m) { 1551 case MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC: 1552 mpt_prtc(mpt, " Out-Of-Sync"); 1553 break; 1554 case MPI_PHYSDISK0_STATUS_FLAG_QUIESCED: 1555 mpt_prtc(mpt, " Quiesced"); 1556 break; 1557 default: 1558 break; 1559 } 1560 } 1561 mpt_prtc(mpt, " )\n"); 1562 } 1563 1564 mpt->raid_nonopt_volumes = nonopt_volumes; 1565 return (0); 1566 } 1567 1568 static void 1569 mpt_raid_timer(void *arg) 1570 { 1571 struct mpt_softc *mpt; 1572 1573 mpt = (struct mpt_softc *)arg; 1574 MPT_LOCK_ASSERT(mpt); 1575 mpt_raid_wakeup(mpt); 1576 } 1577 1578 static void 1579 mpt_schedule_raid_refresh(struct mpt_softc *mpt) 1580 { 1581 1582 callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL, 1583 mpt_raid_timer, mpt); 1584 } 1585 1586 void 1587 mpt_raid_free_mem(struct mpt_softc *mpt) 1588 { 1589 1590 if (mpt->raid_volumes) { 1591 struct mpt_raid_volume *mpt_raid; 1592 int i; 1593 for (i = 0; i < mpt->raid_max_volumes; i++) { 1594 mpt_raid = &mpt->raid_volumes[i]; 1595 if (mpt_raid->config_page) { 1596 free(mpt_raid->config_page, M_DEVBUF); 1597 mpt_raid->config_page = NULL; 1598 } 1599 } 1600 free(mpt->raid_volumes, M_DEVBUF); 1601 mpt->raid_volumes = NULL; 1602 } 1603 if (mpt->raid_disks) { 1604 free(mpt->raid_disks, M_DEVBUF); 1605 mpt->raid_disks = NULL; 1606 } 1607 if (mpt->ioc_page2) { 1608 free(mpt->ioc_page2, M_DEVBUF); 1609 mpt->ioc_page2 = NULL; 1610 } 1611 if (mpt->ioc_page3) { 1612 free(mpt->ioc_page3, M_DEVBUF); 1613 mpt->ioc_page3 = NULL; 1614 } 1615 mpt->raid_max_volumes = 0; 1616 mpt->raid_max_disks = 0; 1617 } 1618 1619 static int 1620 mpt_raid_set_vol_resync_rate(struct mpt_softc *mpt, u_int rate) 1621 { 1622 struct mpt_raid_volume *mpt_vol; 1623 1624 if ((rate > MPT_RAID_RESYNC_RATE_MAX 1625 || rate < MPT_RAID_RESYNC_RATE_MIN) 1626 && rate != MPT_RAID_RESYNC_RATE_NC) 1627 return (EINVAL); 1628 1629 MPT_LOCK(mpt); 1630 mpt->raid_resync_rate = rate; 1631 RAID_VOL_FOREACH(mpt, mpt_vol) { 1632 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) { 1633 continue; 1634 } 1635 mpt_verify_resync_rate(mpt, mpt_vol); 1636 } 1637 MPT_UNLOCK(mpt); 1638 return (0); 1639 } 1640 1641 static int 1642 mpt_raid_set_vol_queue_depth(struct mpt_softc *mpt, u_int vol_queue_depth) 1643 { 1644 struct mpt_raid_volume *mpt_vol; 1645 1646 if (vol_queue_depth > 255 || vol_queue_depth < 1) 1647 return (EINVAL); 1648 1649 MPT_LOCK(mpt); 1650 mpt->raid_queue_depth = vol_queue_depth; 1651 RAID_VOL_FOREACH(mpt, mpt_vol) { 1652 struct cam_path *path; 1653 int error; 1654 1655 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1656 continue; 1657 1658 mpt->raid_rescan = 0; 1659 1660 error = xpt_create_path(&path, NULL, 1661 cam_sim_path(mpt->sim), 1662 mpt_vol->config_page->VolumeID, 1663 /*lun*/0); 1664 if (error != CAM_REQ_CMP) { 1665 mpt_vol_prt(mpt, mpt_vol, "Unable to allocate path!\n"); 1666 continue; 1667 } 1668 mpt_adjust_queue_depth(mpt, mpt_vol, path); 1669 xpt_free_path(path); 1670 } 1671 MPT_UNLOCK(mpt); 1672 return (0); 1673 } 1674 1675 static int 1676 mpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce) 1677 { 1678 struct mpt_raid_volume *mpt_vol; 1679 int force_full_resync; 1680 1681 MPT_LOCK(mpt); 1682 if (mwce == mpt->raid_mwce_setting) { 1683 MPT_UNLOCK(mpt); 1684 return (0); 1685 } 1686 1687 /* 1688 * Catch MWCE being left on due to a failed shutdown. Since 1689 * sysctls cannot be set by the loader, we treat the first 1690 * setting of this varible specially and force a full volume 1691 * resync if MWCE is enabled and a resync is in progress. 1692 */ 1693 force_full_resync = 0; 1694 if (mpt->raid_mwce_set == 0 1695 && mpt->raid_mwce_setting == MPT_RAID_MWCE_NC 1696 && mwce == MPT_RAID_MWCE_REBUILD_ONLY) 1697 force_full_resync = 1; 1698 1699 mpt->raid_mwce_setting = mwce; 1700 RAID_VOL_FOREACH(mpt, mpt_vol) { 1701 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1702 int resyncing; 1703 int mwce; 1704 1705 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1706 continue; 1707 1708 vol_pg = mpt_vol->config_page; 1709 resyncing = vol_pg->VolumeStatus.Flags 1710 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 1711 mwce = vol_pg->VolumeSettings.Settings 1712 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 1713 if (force_full_resync && resyncing && mwce) { 1714 /* 1715 * XXX disable/enable volume should force a resync, 1716 * but we'll need to queice, drain, and restart 1717 * I/O to do that. 1718 */ 1719 mpt_vol_prt(mpt, mpt_vol, "WARNING - Unsafe shutdown " 1720 "detected. Suggest full resync.\n"); 1721 } 1722 mpt_verify_mwce(mpt, mpt_vol); 1723 } 1724 mpt->raid_mwce_set = 1; 1725 MPT_UNLOCK(mpt); 1726 return (0); 1727 } 1728 1729 static const char *mpt_vol_mwce_strs[] = 1730 { 1731 "On", 1732 "Off", 1733 "On-During-Rebuild", 1734 "NC" 1735 }; 1736 1737 static int 1738 mpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS) 1739 { 1740 char inbuf[20]; 1741 struct mpt_softc *mpt; 1742 const char *str; 1743 int error; 1744 u_int size; 1745 u_int i; 1746 1747 mpt = (struct mpt_softc *)arg1; 1748 str = mpt_vol_mwce_strs[mpt->raid_mwce_setting]; 1749 error = SYSCTL_OUT(req, str, strlen(str) + 1); 1750 if (error || !req->newptr) { 1751 return (error); 1752 } 1753 1754 size = req->newlen - req->newidx; 1755 if (size >= sizeof(inbuf)) { 1756 return (EINVAL); 1757 } 1758 1759 error = SYSCTL_IN(req, inbuf, size); 1760 if (error) { 1761 return (error); 1762 } 1763 inbuf[size] = '\0'; 1764 for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) { 1765 if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) { 1766 return (mpt_raid_set_vol_mwce(mpt, i)); 1767 } 1768 } 1769 return (EINVAL); 1770 } 1771 1772 static int 1773 mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS) 1774 { 1775 struct mpt_softc *mpt; 1776 u_int raid_resync_rate; 1777 int error; 1778 1779 mpt = (struct mpt_softc *)arg1; 1780 raid_resync_rate = mpt->raid_resync_rate; 1781 1782 error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req); 1783 if (error || !req->newptr) { 1784 return error; 1785 } 1786 1787 return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate)); 1788 } 1789 1790 static int 1791 mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS) 1792 { 1793 struct mpt_softc *mpt; 1794 u_int raid_queue_depth; 1795 int error; 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 | CTLFLAG_MPSAFE, 1816 mpt, 0, 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 | CTLFLAG_MPSAFE, 1821 mpt, 0, 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 | CTLFLAG_MPSAFE, 1826 mpt, 0, mpt_raid_sysctl_vol_resync_rate, "I", 1827 "volume resync priority (0 == NC, 1 - 255)"); 1828 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1829 "nonoptimal_volumes", CTLFLAG_RD, 1830 &mpt->raid_nonopt_volumes, 0, 1831 "number of nonoptimal volumes"); 1832 } 1833