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