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 callout_func_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 if (mpt->raid_wakeup == 0) { 679 mpt_sleep(mpt, &mpt->raid_volumes, PUSER, "idle", 0); 680 continue; 681 } 682 683 mpt->raid_wakeup = 0; 684 685 if (mpt_refresh_raid_data(mpt)) { 686 mpt_schedule_raid_refresh(mpt); /* XX NOT QUITE RIGHT */ 687 continue; 688 } 689 690 /* 691 * Now that we have our first snapshot of RAID data, 692 * allow CAM to access our physical disk bus. 693 */ 694 if (firstrun) { 695 firstrun = 0; 696 xpt_release_simq(mpt->phydisk_sim, TRUE); 697 } 698 699 if (mpt->raid_rescan != 0) { 700 union ccb *ccb; 701 int error; 702 703 mpt->raid_rescan = 0; 704 MPT_UNLOCK(mpt); 705 706 ccb = xpt_alloc_ccb(); 707 708 MPT_LOCK(mpt); 709 error = xpt_create_path(&ccb->ccb_h.path, NULL, 710 cam_sim_path(mpt->phydisk_sim), 711 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 712 if (error != CAM_REQ_CMP) { 713 xpt_free_ccb(ccb); 714 mpt_prt(mpt, "Unable to rescan RAID Bus!\n"); 715 } else { 716 xpt_rescan(ccb); 717 } 718 } 719 } 720 mpt->raid_thread = NULL; 721 wakeup(&mpt->raid_thread); 722 MPT_UNLOCK(mpt); 723 kproc_exit(0); 724 } 725 726 #if 0 727 static void 728 mpt_raid_quiesce_timeout(void *arg) 729 { 730 731 /* Complete the CCB with error */ 732 /* COWWWW */ 733 } 734 735 static timeout_t mpt_raid_quiesce_timeout; 736 cam_status 737 mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk, 738 request_t *req) 739 { 740 union ccb *ccb; 741 742 ccb = req->ccb; 743 if ((mpt_disk->flags & MPT_RDF_QUIESCED) != 0) 744 return (CAM_REQ_CMP); 745 746 if ((mpt_disk->flags & MPT_RDF_QUIESCING) == 0) { 747 int rv; 748 749 mpt_disk->flags |= MPT_RDF_QUIESCING; 750 xpt_freeze_devq(ccb->ccb_h.path, 1); 751 752 rv = mpt_issue_raid_req(mpt, mpt_disk->volume, mpt_disk, req, 753 MPI_RAID_ACTION_QUIESCE_PHYS_IO, 754 /*ActionData*/0, /*addr*/0, 755 /*len*/0, /*write*/FALSE, 756 /*wait*/FALSE); 757 if (rv != 0) 758 return (CAM_REQ_CMP_ERR); 759 760 mpt_req_timeout(req, mpt_raid_quiesce_timeout, ccb, 5 * hz); 761 #if 0 762 if (rv == ETIMEDOUT) { 763 mpt_disk_prt(mpt, mpt_disk, "mpt_raid_quiesce_disk: " 764 "Quiece Timed-out\n"); 765 xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0); 766 return (CAM_REQ_CMP_ERR); 767 } 768 769 ar = REQ_TO_RAID_ACTION_RESULT(req); 770 if (rv != 0 771 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 772 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 773 mpt_disk_prt(mpt, mpt_disk, "Quiece Failed" 774 "%d:%x:%x\n", rv, req->IOCStatus, 775 ar->action_status); 776 xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0); 777 return (CAM_REQ_CMP_ERR); 778 } 779 #endif 780 return (CAM_REQ_INPROG); 781 } 782 return (CAM_REQUEUE_REQ); 783 } 784 #endif 785 786 /* XXX Ignores that there may be multiple buses/IOCs involved. */ 787 cam_status 788 mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, target_id_t *tgt) 789 { 790 struct mpt_raid_disk *mpt_disk; 791 792 mpt_disk = mpt->raid_disks + ccb->ccb_h.target_id; 793 if (ccb->ccb_h.target_id < mpt->raid_max_disks 794 && (mpt_disk->flags & MPT_RDF_ACTIVE) != 0) { 795 *tgt = mpt_disk->config_page.PhysDiskID; 796 return (0); 797 } 798 mpt_lprt(mpt, MPT_PRT_DEBUG1, "mpt_map_physdisk(%d) - Not Active\n", 799 ccb->ccb_h.target_id); 800 return (-1); 801 } 802 803 /* XXX Ignores that there may be multiple buses/IOCs involved. */ 804 int 805 mpt_is_raid_member(struct mpt_softc *mpt, target_id_t tgt) 806 { 807 struct mpt_raid_disk *mpt_disk; 808 int i; 809 810 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) 811 return (0); 812 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 813 mpt_disk = &mpt->raid_disks[i]; 814 if ((mpt_disk->flags & MPT_RDF_ACTIVE) != 0 && 815 mpt_disk->config_page.PhysDiskID == tgt) 816 return (1); 817 } 818 return (0); 819 820 } 821 822 /* XXX Ignores that there may be multiple buses/IOCs involved. */ 823 int 824 mpt_is_raid_volume(struct mpt_softc *mpt, target_id_t tgt) 825 { 826 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol; 827 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol; 828 829 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) { 830 return (0); 831 } 832 ioc_vol = mpt->ioc_page2->RaidVolume; 833 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes; 834 for (;ioc_vol != ioc_last_vol; ioc_vol++) { 835 if (ioc_vol->VolumeID == tgt) { 836 return (1); 837 } 838 } 839 return (0); 840 } 841 842 #if 0 843 static void 844 mpt_enable_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 845 int enable) 846 { 847 request_t *req; 848 struct mpt_raid_action_result *ar; 849 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 850 int enabled; 851 int rv; 852 853 vol_pg = mpt_vol->config_page; 854 enabled = vol_pg->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED; 855 856 /* 857 * If the setting matches the configuration, 858 * there is nothing to do. 859 */ 860 if ((enabled && enable) 861 || (!enabled && !enable)) 862 return; 863 864 req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 865 if (req == NULL) { 866 mpt_vol_prt(mpt, mpt_vol, 867 "mpt_enable_vol: Get request failed!\n"); 868 return; 869 } 870 871 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 872 enable ? MPI_RAID_ACTION_ENABLE_VOLUME 873 : MPI_RAID_ACTION_DISABLE_VOLUME, 874 /*data*/0, /*addr*/0, /*len*/0, 875 /*write*/FALSE, /*wait*/TRUE); 876 if (rv == ETIMEDOUT) { 877 mpt_vol_prt(mpt, mpt_vol, "mpt_enable_vol: " 878 "%s Volume Timed-out\n", 879 enable ? "Enable" : "Disable"); 880 return; 881 } 882 ar = REQ_TO_RAID_ACTION_RESULT(req); 883 if (rv != 0 884 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 885 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 886 mpt_vol_prt(mpt, mpt_vol, "%s Volume Failed: %d:%x:%x\n", 887 enable ? "Enable" : "Disable", 888 rv, req->IOCStatus, ar->action_status); 889 } 890 891 mpt_free_request(mpt, req); 892 } 893 #endif 894 895 static void 896 mpt_verify_mwce(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol) 897 { 898 request_t *req; 899 struct mpt_raid_action_result *ar; 900 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 901 uint32_t data; 902 int rv; 903 int resyncing; 904 int mwce; 905 906 vol_pg = mpt_vol->config_page; 907 resyncing = vol_pg->VolumeStatus.Flags 908 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 909 mwce = vol_pg->VolumeSettings.Settings 910 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 911 912 /* 913 * If the setting matches the configuration, 914 * there is nothing to do. 915 */ 916 switch (mpt->raid_mwce_setting) { 917 case MPT_RAID_MWCE_REBUILD_ONLY: 918 if ((resyncing && mwce) || (!resyncing && !mwce)) { 919 return; 920 } 921 mpt_vol->flags ^= MPT_RVF_WCE_CHANGED; 922 if ((mpt_vol->flags & MPT_RVF_WCE_CHANGED) == 0) { 923 /* 924 * Wait one more status update to see if 925 * resyncing gets enabled. It gets disabled 926 * temporarilly when WCE is changed. 927 */ 928 return; 929 } 930 break; 931 case MPT_RAID_MWCE_ON: 932 if (mwce) 933 return; 934 break; 935 case MPT_RAID_MWCE_OFF: 936 if (!mwce) 937 return; 938 break; 939 case MPT_RAID_MWCE_NC: 940 return; 941 } 942 943 req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 944 if (req == NULL) { 945 mpt_vol_prt(mpt, mpt_vol, 946 "mpt_verify_mwce: Get request failed!\n"); 947 return; 948 } 949 950 vol_pg->VolumeSettings.Settings ^= 951 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 952 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data)); 953 vol_pg->VolumeSettings.Settings ^= 954 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 955 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 956 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 957 data, /*addr*/0, /*len*/0, 958 /*write*/FALSE, /*wait*/TRUE); 959 if (rv == ETIMEDOUT) { 960 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_mwce: " 961 "Write Cache Enable Timed-out\n"); 962 return; 963 } 964 ar = REQ_TO_RAID_ACTION_RESULT(req); 965 if (rv != 0 966 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 967 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 968 mpt_vol_prt(mpt, mpt_vol, "Write Cache Enable Failed: " 969 "%d:%x:%x\n", rv, req->IOCStatus, 970 ar->action_status); 971 } else { 972 vol_pg->VolumeSettings.Settings ^= 973 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 974 } 975 mpt_free_request(mpt, req); 976 } 977 978 static void 979 mpt_verify_resync_rate(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol) 980 { 981 request_t *req; 982 struct mpt_raid_action_result *ar; 983 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 984 u_int prio; 985 int rv; 986 987 vol_pg = mpt_vol->config_page; 988 989 if (mpt->raid_resync_rate == MPT_RAID_RESYNC_RATE_NC) 990 return; 991 992 /* 993 * If the current RAID resync rate does not 994 * match our configured rate, update it. 995 */ 996 prio = vol_pg->VolumeSettings.Settings 997 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 998 if (vol_pg->ResyncRate != 0 999 && vol_pg->ResyncRate != mpt->raid_resync_rate) { 1000 req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 1001 if (req == NULL) { 1002 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: " 1003 "Get request failed!\n"); 1004 return; 1005 } 1006 1007 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 1008 MPI_RAID_ACTION_SET_RESYNC_RATE, 1009 mpt->raid_resync_rate, /*addr*/0, 1010 /*len*/0, /*write*/FALSE, /*wait*/TRUE); 1011 if (rv == ETIMEDOUT) { 1012 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: " 1013 "Resync Rate Setting Timed-out\n"); 1014 return; 1015 } 1016 1017 ar = REQ_TO_RAID_ACTION_RESULT(req); 1018 if (rv != 0 1019 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 1020 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 1021 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: " 1022 "%d:%x:%x\n", rv, req->IOCStatus, 1023 ar->action_status); 1024 } else 1025 vol_pg->ResyncRate = mpt->raid_resync_rate; 1026 mpt_free_request(mpt, req); 1027 } else if ((prio && mpt->raid_resync_rate < 128) 1028 || (!prio && mpt->raid_resync_rate >= 128)) { 1029 uint32_t data; 1030 1031 req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 1032 if (req == NULL) { 1033 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: " 1034 "Get request failed!\n"); 1035 return; 1036 } 1037 1038 vol_pg->VolumeSettings.Settings ^= 1039 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1040 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data)); 1041 vol_pg->VolumeSettings.Settings ^= 1042 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1043 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 1044 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 1045 data, /*addr*/0, /*len*/0, 1046 /*write*/FALSE, /*wait*/TRUE); 1047 if (rv == ETIMEDOUT) { 1048 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: " 1049 "Resync Rate Setting Timed-out\n"); 1050 return; 1051 } 1052 ar = REQ_TO_RAID_ACTION_RESULT(req); 1053 if (rv != 0 1054 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 1055 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 1056 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: " 1057 "%d:%x:%x\n", rv, req->IOCStatus, 1058 ar->action_status); 1059 } else { 1060 vol_pg->VolumeSettings.Settings ^= 1061 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1062 } 1063 1064 mpt_free_request(mpt, req); 1065 } 1066 } 1067 1068 static void 1069 mpt_adjust_queue_depth(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 1070 struct cam_path *path) 1071 { 1072 struct ccb_relsim crs; 1073 1074 xpt_setup_ccb(&crs.ccb_h, path, /*priority*/5); 1075 crs.ccb_h.func_code = XPT_REL_SIMQ; 1076 crs.ccb_h.flags = CAM_DEV_QFREEZE; 1077 crs.release_flags = RELSIM_ADJUST_OPENINGS; 1078 crs.openings = mpt->raid_queue_depth; 1079 xpt_action((union ccb *)&crs); 1080 if (crs.ccb_h.status != CAM_REQ_CMP) 1081 mpt_vol_prt(mpt, mpt_vol, "mpt_adjust_queue_depth failed " 1082 "with CAM status %#x\n", crs.ccb_h.status); 1083 } 1084 1085 static void 1086 mpt_announce_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol) 1087 { 1088 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1089 u_int i; 1090 1091 vol_pg = mpt_vol->config_page; 1092 mpt_vol_prt(mpt, mpt_vol, "Settings ("); 1093 for (i = 1; i <= 0x8000; i <<= 1) { 1094 switch (vol_pg->VolumeSettings.Settings & i) { 1095 case MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE: 1096 mpt_prtc(mpt, " Member-WCE"); 1097 break; 1098 case MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART: 1099 mpt_prtc(mpt, " Offline-On-SMART-Err"); 1100 break; 1101 case MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE: 1102 mpt_prtc(mpt, " Hot-Plug-Spares"); 1103 break; 1104 case MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC: 1105 mpt_prtc(mpt, " High-Priority-ReSync"); 1106 break; 1107 default: 1108 break; 1109 } 1110 } 1111 mpt_prtc(mpt, " )\n"); 1112 if (vol_pg->VolumeSettings.HotSparePool != 0) { 1113 mpt_vol_prt(mpt, mpt_vol, "Using Spare Pool%s", 1114 powerof2(vol_pg->VolumeSettings.HotSparePool) 1115 ? ":" : "s:"); 1116 for (i = 0; i < 8; i++) { 1117 u_int mask; 1118 1119 mask = 0x1 << i; 1120 if ((vol_pg->VolumeSettings.HotSparePool & mask) == 0) 1121 continue; 1122 mpt_prtc(mpt, " %d", i); 1123 } 1124 mpt_prtc(mpt, "\n"); 1125 } 1126 mpt_vol_prt(mpt, mpt_vol, "%d Members:\n", vol_pg->NumPhysDisks); 1127 for (i = 0; i < vol_pg->NumPhysDisks; i++){ 1128 struct mpt_raid_disk *mpt_disk; 1129 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1130 int pt_bus = cam_sim_bus(mpt->phydisk_sim); 1131 U8 f, s; 1132 1133 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum; 1134 disk_pg = &mpt_disk->config_page; 1135 mpt_prtc(mpt, " "); 1136 mpt_prtc(mpt, "(%s:%d:%d:0): ", device_get_nameunit(mpt->dev), 1137 pt_bus, disk_pg->PhysDiskID); 1138 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) { 1139 mpt_prtc(mpt, "%s", mpt_disk->member_number == 0? 1140 "Primary" : "Secondary"); 1141 } else { 1142 mpt_prtc(mpt, "Stripe Position %d", 1143 mpt_disk->member_number); 1144 } 1145 f = disk_pg->PhysDiskStatus.Flags; 1146 s = disk_pg->PhysDiskStatus.State; 1147 if (f & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC) { 1148 mpt_prtc(mpt, " Out of Sync"); 1149 } 1150 if (f & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED) { 1151 mpt_prtc(mpt, " Quiesced"); 1152 } 1153 if (f & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) { 1154 mpt_prtc(mpt, " Inactive"); 1155 } 1156 if (f & MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS) { 1157 mpt_prtc(mpt, " Was Optimal"); 1158 } 1159 if (f & MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS) { 1160 mpt_prtc(mpt, " Was Non-Optimal"); 1161 } 1162 switch (s) { 1163 case MPI_PHYSDISK0_STATUS_ONLINE: 1164 mpt_prtc(mpt, " Online"); 1165 break; 1166 case MPI_PHYSDISK0_STATUS_MISSING: 1167 mpt_prtc(mpt, " Missing"); 1168 break; 1169 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE: 1170 mpt_prtc(mpt, " Incompatible"); 1171 break; 1172 case MPI_PHYSDISK0_STATUS_FAILED: 1173 mpt_prtc(mpt, " Failed"); 1174 break; 1175 case MPI_PHYSDISK0_STATUS_INITIALIZING: 1176 mpt_prtc(mpt, " Initializing"); 1177 break; 1178 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED: 1179 mpt_prtc(mpt, " Requested Offline"); 1180 break; 1181 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED: 1182 mpt_prtc(mpt, " Requested Failed"); 1183 break; 1184 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE: 1185 default: 1186 mpt_prtc(mpt, " Offline Other (%x)", s); 1187 break; 1188 } 1189 mpt_prtc(mpt, "\n"); 1190 } 1191 } 1192 1193 static void 1194 mpt_announce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk) 1195 { 1196 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1197 int rd_bus = cam_sim_bus(mpt->sim); 1198 int pt_bus = cam_sim_bus(mpt->phydisk_sim); 1199 u_int i; 1200 1201 disk_pg = &mpt_disk->config_page; 1202 mpt_disk_prt(mpt, mpt_disk, 1203 "Physical (%s:%d:%d:0), Pass-thru (%s:%d:%d:0)\n", 1204 device_get_nameunit(mpt->dev), rd_bus, 1205 disk_pg->PhysDiskID, device_get_nameunit(mpt->dev), 1206 pt_bus, mpt_disk - mpt->raid_disks); 1207 if (disk_pg->PhysDiskSettings.HotSparePool == 0) 1208 return; 1209 mpt_disk_prt(mpt, mpt_disk, "Member of Hot Spare Pool%s", 1210 powerof2(disk_pg->PhysDiskSettings.HotSparePool) 1211 ? ":" : "s:"); 1212 for (i = 0; i < 8; i++) { 1213 u_int mask; 1214 1215 mask = 0x1 << i; 1216 if ((disk_pg->PhysDiskSettings.HotSparePool & mask) == 0) 1217 continue; 1218 mpt_prtc(mpt, " %d", i); 1219 } 1220 mpt_prtc(mpt, "\n"); 1221 } 1222 1223 static void 1224 mpt_refresh_raid_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk, 1225 IOC_3_PHYS_DISK *ioc_disk) 1226 { 1227 int rv; 1228 1229 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 1230 /*PageNumber*/0, ioc_disk->PhysDiskNum, 1231 &mpt_disk->config_page.Header, 1232 /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1233 if (rv != 0) { 1234 mpt_prt(mpt, "mpt_refresh_raid_disk: " 1235 "Failed to read RAID Disk Hdr(%d)\n", 1236 ioc_disk->PhysDiskNum); 1237 return; 1238 } 1239 rv = mpt_read_cur_cfg_page(mpt, ioc_disk->PhysDiskNum, 1240 &mpt_disk->config_page.Header, 1241 sizeof(mpt_disk->config_page), 1242 /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1243 if (rv != 0) 1244 mpt_prt(mpt, "mpt_refresh_raid_disk: " 1245 "Failed to read RAID Disk Page(%d)\n", 1246 ioc_disk->PhysDiskNum); 1247 mpt2host_config_page_raid_phys_disk_0(&mpt_disk->config_page); 1248 } 1249 1250 static void 1251 mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 1252 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol) 1253 { 1254 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1255 struct mpt_raid_action_result *ar; 1256 request_t *req; 1257 int rv; 1258 int i; 1259 1260 vol_pg = mpt_vol->config_page; 1261 mpt_vol->flags &= ~MPT_RVF_UP2DATE; 1262 1263 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, 1264 ioc_vol->VolumePageNumber, &vol_pg->Header, TRUE, 5000); 1265 if (rv != 0) { 1266 mpt_vol_prt(mpt, mpt_vol, 1267 "mpt_refresh_raid_vol: Failed to read RAID Vol Hdr(%d)\n", 1268 ioc_vol->VolumePageNumber); 1269 return; 1270 } 1271 1272 rv = mpt_read_cur_cfg_page(mpt, ioc_vol->VolumePageNumber, 1273 &vol_pg->Header, mpt->raid_page0_len, TRUE, 5000); 1274 if (rv != 0) { 1275 mpt_vol_prt(mpt, mpt_vol, 1276 "mpt_refresh_raid_vol: Failed to read RAID Vol Page(%d)\n", 1277 ioc_vol->VolumePageNumber); 1278 return; 1279 } 1280 mpt2host_config_page_raid_vol_0(vol_pg); 1281 1282 mpt_vol->flags |= MPT_RVF_ACTIVE; 1283 1284 /* Update disk entry array data. */ 1285 for (i = 0; i < vol_pg->NumPhysDisks; i++) { 1286 struct mpt_raid_disk *mpt_disk; 1287 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum; 1288 mpt_disk->volume = mpt_vol; 1289 mpt_disk->member_number = vol_pg->PhysDisk[i].PhysDiskMap; 1290 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) { 1291 mpt_disk->member_number--; 1292 } 1293 } 1294 1295 if ((vol_pg->VolumeStatus.Flags 1296 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0) 1297 return; 1298 1299 req = mpt_get_request(mpt, TRUE); 1300 if (req == NULL) { 1301 mpt_vol_prt(mpt, mpt_vol, 1302 "mpt_refresh_raid_vol: Get request failed!\n"); 1303 return; 1304 } 1305 rv = mpt_issue_raid_req(mpt, mpt_vol, NULL, req, 1306 MPI_RAID_ACTION_INDICATOR_STRUCT, 0, 0, 0, FALSE, TRUE); 1307 if (rv == ETIMEDOUT) { 1308 mpt_vol_prt(mpt, mpt_vol, 1309 "mpt_refresh_raid_vol: Progress Indicator fetch timeout\n"); 1310 mpt_free_request(mpt, req); 1311 return; 1312 } 1313 1314 ar = REQ_TO_RAID_ACTION_RESULT(req); 1315 if (rv == 0 1316 && ar->action_status == MPI_RAID_ACTION_ASTATUS_SUCCESS 1317 && REQ_IOCSTATUS(req) == MPI_IOCSTATUS_SUCCESS) { 1318 memcpy(&mpt_vol->sync_progress, 1319 &ar->action_data.indicator_struct, 1320 sizeof(mpt_vol->sync_progress)); 1321 mpt2host_mpi_raid_vol_indicator(&mpt_vol->sync_progress); 1322 } else { 1323 mpt_vol_prt(mpt, mpt_vol, 1324 "mpt_refresh_raid_vol: Progress indicator fetch failed!\n"); 1325 } 1326 mpt_free_request(mpt, req); 1327 } 1328 1329 /* 1330 * Update in-core information about RAID support. We update any entries 1331 * that didn't previously exists or have been marked as needing to 1332 * be updated by our event handler. Interesting changes are displayed 1333 * to the console. 1334 */ 1335 static int 1336 mpt_refresh_raid_data(struct mpt_softc *mpt) 1337 { 1338 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol; 1339 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol; 1340 IOC_3_PHYS_DISK *ioc_disk; 1341 IOC_3_PHYS_DISK *ioc_last_disk; 1342 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1343 size_t len; 1344 int rv; 1345 int i; 1346 u_int nonopt_volumes; 1347 1348 if (mpt->ioc_page2 == NULL || mpt->ioc_page3 == NULL) { 1349 return (0); 1350 } 1351 1352 /* 1353 * Mark all items as unreferenced by the configuration. 1354 * This allows us to find, report, and discard stale 1355 * entries. 1356 */ 1357 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 1358 mpt->raid_disks[i].flags &= ~MPT_RDF_REFERENCED; 1359 } 1360 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 1361 mpt->raid_volumes[i].flags &= ~MPT_RVF_REFERENCED; 1362 } 1363 1364 /* 1365 * Get Physical Disk information. 1366 */ 1367 len = mpt->ioc_page3->Header.PageLength * sizeof(uint32_t); 1368 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1369 &mpt->ioc_page3->Header, len, 1370 /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1371 if (rv) { 1372 mpt_prt(mpt, 1373 "mpt_refresh_raid_data: Failed to read IOC Page 3\n"); 1374 return (-1); 1375 } 1376 mpt2host_config_page_ioc3(mpt->ioc_page3); 1377 1378 ioc_disk = mpt->ioc_page3->PhysDisk; 1379 ioc_last_disk = ioc_disk + mpt->ioc_page3->NumPhysDisks; 1380 for (; ioc_disk != ioc_last_disk; ioc_disk++) { 1381 struct mpt_raid_disk *mpt_disk; 1382 1383 mpt_disk = mpt->raid_disks + ioc_disk->PhysDiskNum; 1384 mpt_disk->flags |= MPT_RDF_REFERENCED; 1385 if ((mpt_disk->flags & (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) 1386 != (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) { 1387 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 GIANT_REQUIRED; 1748 1749 mpt = (struct mpt_softc *)arg1; 1750 str = mpt_vol_mwce_strs[mpt->raid_mwce_setting]; 1751 error = SYSCTL_OUT(req, str, strlen(str) + 1); 1752 if (error || !req->newptr) { 1753 return (error); 1754 } 1755 1756 size = req->newlen - req->newidx; 1757 if (size >= sizeof(inbuf)) { 1758 return (EINVAL); 1759 } 1760 1761 error = SYSCTL_IN(req, inbuf, size); 1762 if (error) { 1763 return (error); 1764 } 1765 inbuf[size] = '\0'; 1766 for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) { 1767 if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) { 1768 return (mpt_raid_set_vol_mwce(mpt, i)); 1769 } 1770 } 1771 return (EINVAL); 1772 } 1773 1774 static int 1775 mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS) 1776 { 1777 struct mpt_softc *mpt; 1778 u_int raid_resync_rate; 1779 int error; 1780 1781 GIANT_REQUIRED; 1782 1783 mpt = (struct mpt_softc *)arg1; 1784 raid_resync_rate = mpt->raid_resync_rate; 1785 1786 error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req); 1787 if (error || !req->newptr) { 1788 return error; 1789 } 1790 1791 return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate)); 1792 } 1793 1794 static int 1795 mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS) 1796 { 1797 struct mpt_softc *mpt; 1798 u_int raid_queue_depth; 1799 int error; 1800 1801 GIANT_REQUIRED; 1802 1803 mpt = (struct mpt_softc *)arg1; 1804 raid_queue_depth = mpt->raid_queue_depth; 1805 1806 error = sysctl_handle_int(oidp, &raid_queue_depth, 0, req); 1807 if (error || !req->newptr) { 1808 return error; 1809 } 1810 1811 return (mpt_raid_set_vol_queue_depth(mpt, raid_queue_depth)); 1812 } 1813 1814 static void 1815 mpt_raid_sysctl_attach(struct mpt_softc *mpt) 1816 { 1817 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev); 1818 struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev); 1819 1820 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1821 "vol_member_wce", CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 1822 mpt, 0, mpt_raid_sysctl_vol_member_wce, "A", 1823 "volume member WCE(On,Off,On-During-Rebuild,NC)"); 1824 1825 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1826 "vol_queue_depth", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 1827 mpt, 0, mpt_raid_sysctl_vol_queue_depth, "I", 1828 "default volume queue depth"); 1829 1830 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1831 "vol_resync_rate", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 1832 mpt, 0, mpt_raid_sysctl_vol_resync_rate, "I", 1833 "volume resync priority (0 == NC, 1 - 255)"); 1834 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1835 "nonoptimal_volumes", CTLFLAG_RD, 1836 &mpt->raid_nonopt_volumes, 0, 1837 "number of nonoptimal volumes"); 1838 } 1839