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