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