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 UNUSED 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 #if 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 UNUSED 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 1230 if (mpt->ioc_page2 == NULL || mpt->ioc_page3 == NULL) 1231 return; 1232 1233 /* 1234 * Mark all items as unreferrened by the configuration. 1235 * This allows us to find, report, and discard stale 1236 * entries. 1237 */ 1238 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) 1239 mpt->raid_disks[i].flags &= ~MPT_RDF_REFERENCED; 1240 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) 1241 mpt->raid_volumes[i].flags &= ~MPT_RVF_REFERENCED; 1242 1243 /* 1244 * Get Physical Disk information. 1245 */ 1246 len = mpt->ioc_page3->Header.PageLength * sizeof(uint32_t); 1247 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1248 &mpt->ioc_page3->Header, len, 1249 /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1250 if (rv) { 1251 mpt_prt(mpt, "mpt_refresh_raid_data: " 1252 "Failed to read IOC Page 3\n"); 1253 return; 1254 } 1255 1256 ioc_disk = mpt->ioc_page3->PhysDisk; 1257 ioc_last_disk = ioc_disk + mpt->ioc_page3->NumPhysDisks; 1258 for (; ioc_disk != ioc_last_disk; ioc_disk++) { 1259 struct mpt_raid_disk *mpt_disk; 1260 1261 mpt_disk = mpt->raid_disks + ioc_disk->PhysDiskNum; 1262 mpt_disk->flags |= MPT_RDF_REFERENCED; 1263 if ((mpt_disk->flags & (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) 1264 != (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) { 1265 1266 mpt_refresh_raid_disk(mpt, mpt_disk, ioc_disk); 1267 1268 } 1269 mpt_disk->flags |= MPT_RDF_ACTIVE; 1270 mpt->raid_rescan++; 1271 } 1272 1273 /* 1274 * Refresh volume data. 1275 */ 1276 len = mpt->ioc_page2->Header.PageLength * sizeof(uint32_t); 1277 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1278 &mpt->ioc_page2->Header, len, 1279 /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1280 if (rv) { 1281 mpt_prt(mpt, "mpt_refresh_raid_data: " 1282 "Failed to read IOC Page 2\n"); 1283 return; 1284 } 1285 1286 ioc_vol = mpt->ioc_page2->RaidVolume; 1287 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes; 1288 for (;ioc_vol != ioc_last_vol; ioc_vol++) { 1289 struct mpt_raid_volume *mpt_vol; 1290 1291 mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber; 1292 mpt_vol->flags |= MPT_RVF_REFERENCED; 1293 vol_pg = mpt_vol->config_page; 1294 if (vol_pg == NULL) 1295 continue; 1296 if (((mpt_vol->flags & (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE)) 1297 != (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE)) 1298 || (vol_pg->VolumeStatus.Flags 1299 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) != 0) { 1300 1301 mpt_refresh_raid_vol(mpt, mpt_vol, ioc_vol); 1302 } 1303 mpt_vol->flags |= MPT_RVF_ACTIVE; 1304 } 1305 1306 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 1307 struct mpt_raid_volume *mpt_vol; 1308 uint64_t total; 1309 uint64_t left; 1310 int m; 1311 u_int prio; 1312 1313 mpt_vol = &mpt->raid_volumes[i]; 1314 1315 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1316 continue; 1317 1318 vol_pg = mpt_vol->config_page; 1319 if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED)) 1320 == MPT_RVF_ANNOUNCED) { 1321 mpt_vol_prt(mpt, mpt_vol, "No longer configured\n"); 1322 mpt_vol->flags = 0; 1323 continue; 1324 } 1325 1326 if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) { 1327 1328 mpt_announce_vol(mpt, mpt_vol); 1329 mpt_vol->flags |= MPT_RVF_ANNOUNCED; 1330 } 1331 1332 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) 1333 continue; 1334 1335 mpt_vol->flags |= MPT_RVF_UP2DATE; 1336 mpt_vol_prt(mpt, mpt_vol, "%s - %s\n", 1337 mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol)); 1338 mpt_verify_mwce(mpt, mpt_vol); 1339 1340 if (vol_pg->VolumeStatus.Flags == 0) 1341 continue; 1342 1343 mpt_vol_prt(mpt, mpt_vol, "Status ("); 1344 for (m = 1; m <= 0x80; m <<= 1) { 1345 switch (vol_pg->VolumeStatus.Flags & m) { 1346 case MPI_RAIDVOL0_STATUS_FLAG_ENABLED: 1347 mpt_prtc(mpt, " Enabled"); 1348 break; 1349 case MPI_RAIDVOL0_STATUS_FLAG_QUIESCED: 1350 mpt_prtc(mpt, " Quiesced"); 1351 break; 1352 case MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS: 1353 mpt_prtc(mpt, " Re-Syncing"); 1354 break; 1355 case MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE: 1356 mpt_prtc(mpt, " Inactive"); 1357 break; 1358 default: 1359 break; 1360 } 1361 } 1362 mpt_prtc(mpt, " )\n"); 1363 1364 if ((vol_pg->VolumeStatus.Flags 1365 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0) 1366 continue; 1367 1368 mpt_verify_resync_rate(mpt, mpt_vol); 1369 1370 left = u64toh(mpt_vol->sync_progress.BlocksRemaining); 1371 total = u64toh(mpt_vol->sync_progress.TotalBlocks); 1372 if (vol_pg->ResyncRate != 0) { 1373 1374 prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF; 1375 mpt_vol_prt(mpt, mpt_vol, "Rate %d.%d%%\n", 1376 prio / 1000, prio % 1000); 1377 } else { 1378 prio = vol_pg->VolumeSettings.Settings 1379 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1380 mpt_vol_prt(mpt, mpt_vol, "%s Priority Re-Sync\n", 1381 prio ? "High" : "Low"); 1382 } 1383 mpt_vol_prt(mpt, mpt_vol, "%ju of %ju " 1384 "blocks remaining\n", (uintmax_t)left, 1385 (uintmax_t)total); 1386 1387 /* Periodically report on sync progress. */ 1388 mpt_schedule_raid_refresh(mpt); 1389 } 1390 1391 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 1392 struct mpt_raid_disk *mpt_disk; 1393 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1394 int m; 1395 1396 mpt_disk = &mpt->raid_disks[i]; 1397 disk_pg = &mpt_disk->config_page; 1398 1399 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) 1400 continue; 1401 1402 if ((mpt_disk->flags & (MPT_RDF_REFERENCED|MPT_RDF_ANNOUNCED)) 1403 == MPT_RDF_ANNOUNCED) { 1404 mpt_disk_prt(mpt, mpt_disk, "No longer configured\n"); 1405 mpt_disk->flags = 0; 1406 mpt->raid_rescan++; 1407 continue; 1408 } 1409 1410 if ((mpt_disk->flags & MPT_RDF_ANNOUNCED) == 0) { 1411 1412 mpt_announce_disk(mpt, mpt_disk); 1413 mpt_disk->flags |= MPT_RVF_ANNOUNCED; 1414 } 1415 1416 if ((mpt_disk->flags & MPT_RDF_UP2DATE) != 0) 1417 continue; 1418 1419 mpt_disk->flags |= MPT_RDF_UP2DATE; 1420 mpt_disk_prt(mpt, mpt_disk, "%s\n", mpt_disk_state(mpt_disk)); 1421 if (disk_pg->PhysDiskStatus.Flags == 0) 1422 continue; 1423 1424 mpt_disk_prt(mpt, mpt_disk, "Status ("); 1425 for (m = 1; m <= 0x80; m <<= 1) { 1426 switch (disk_pg->PhysDiskStatus.Flags & m) { 1427 case MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC: 1428 mpt_prtc(mpt, " Out-Of-Sync"); 1429 break; 1430 case MPI_PHYSDISK0_STATUS_FLAG_QUIESCED: 1431 mpt_prtc(mpt, " Quiesced"); 1432 break; 1433 default: 1434 break; 1435 } 1436 } 1437 mpt_prtc(mpt, " )\n"); 1438 } 1439 } 1440 1441 static void 1442 mpt_raid_timer(void *arg) 1443 { 1444 struct mpt_softc *mpt; 1445 1446 mpt = (struct mpt_softc *)arg; 1447 MPT_LOCK(mpt); 1448 mpt_raid_wakeup(mpt); 1449 MPT_UNLOCK(mpt); 1450 } 1451 1452 static void 1453 mpt_raid_quiesce_timeout(void *arg) 1454 { 1455 /* Complete the CCB with error */ 1456 /* COWWWW */ 1457 } 1458 1459 void 1460 mpt_schedule_raid_refresh(struct mpt_softc *mpt) 1461 { 1462 callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL, 1463 mpt_raid_timer, mpt); 1464 } 1465 1466 static int 1467 mpt_raid_set_vol_resync_rate(struct mpt_softc *mpt, u_int rate) 1468 { 1469 struct mpt_raid_volume *mpt_vol; 1470 1471 if ((rate > MPT_RAID_RESYNC_RATE_MAX 1472 || rate < MPT_RAID_RESYNC_RATE_MIN) 1473 && rate != MPT_RAID_RESYNC_RATE_NC) 1474 return (EINVAL); 1475 1476 MPT_LOCK(mpt); 1477 mpt->raid_resync_rate = rate; 1478 RAID_VOL_FOREACH(mpt, mpt_vol) { 1479 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1480 continue; 1481 mpt_verify_resync_rate(mpt, mpt_vol); 1482 } 1483 MPT_UNLOCK(mpt); 1484 return (0); 1485 } 1486 1487 static int 1488 mpt_raid_set_vol_queue_depth(struct mpt_softc *mpt, u_int vol_queue_depth) 1489 { 1490 struct mpt_raid_volume *mpt_vol; 1491 1492 if (vol_queue_depth > 255 1493 || vol_queue_depth < 1) 1494 return (EINVAL); 1495 1496 MPT_LOCK(mpt); 1497 mpt->raid_queue_depth = vol_queue_depth; 1498 RAID_VOL_FOREACH(mpt, mpt_vol) { 1499 struct cam_path *path; 1500 int error; 1501 1502 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1503 continue; 1504 1505 mpt->raid_rescan = 0; 1506 1507 error = xpt_create_path(&path, xpt_periph, 1508 cam_sim_path(mpt->sim), 1509 mpt_vol->config_page->VolumeID, 1510 /*lun*/0); 1511 if (error != CAM_REQ_CMP) { 1512 mpt_vol_prt(mpt, mpt_vol, "Unable to allocate path!\n"); 1513 continue; 1514 } 1515 mpt_adjust_queue_depth(mpt, mpt_vol, path); 1516 xpt_free_path(path); 1517 } 1518 MPT_UNLOCK(mpt); 1519 return (0); 1520 } 1521 1522 static int 1523 mpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce) 1524 { 1525 struct mpt_raid_volume *mpt_vol; 1526 int force_full_resync; 1527 1528 MPT_LOCK(mpt); 1529 if (mwce == mpt->raid_mwce_setting) { 1530 MPT_UNLOCK(mpt); 1531 return (0); 1532 } 1533 1534 /* 1535 * Catch MWCE being left on due to a failed shutdown. Since 1536 * sysctls cannot be set by the loader, we treat the first 1537 * setting of this varible specially and force a full volume 1538 * resync if MWCE is enabled and a resync is in progress. 1539 */ 1540 force_full_resync = 0; 1541 if (mpt->raid_mwce_set == 0 1542 && mpt->raid_mwce_setting == MPT_RAID_MWCE_NC 1543 && mwce == MPT_RAID_MWCE_REBUILD_ONLY) 1544 force_full_resync = 1; 1545 1546 mpt->raid_mwce_setting = mwce; 1547 RAID_VOL_FOREACH(mpt, mpt_vol) { 1548 CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1549 int resyncing; 1550 int mwce; 1551 1552 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1553 continue; 1554 1555 vol_pg = mpt_vol->config_page; 1556 resyncing = vol_pg->VolumeStatus.Flags 1557 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 1558 mwce = vol_pg->VolumeSettings.Settings 1559 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 1560 if (force_full_resync && resyncing && mwce) { 1561 1562 /* 1563 * XXX disable/enable volume should force a resync, 1564 * but we'll need to queice, drain, and restart 1565 * I/O to do that. 1566 */ 1567 mpt_vol_prt(mpt, mpt_vol, "WARNING - Unsafe shutdown " 1568 "detected. Suggest full resync.\n"); 1569 } 1570 mpt_verify_mwce(mpt, mpt_vol); 1571 } 1572 mpt->raid_mwce_set = 1; 1573 MPT_UNLOCK(mpt); 1574 return (0); 1575 } 1576 1577 const char *mpt_vol_mwce_strs[] = 1578 { 1579 "On", 1580 "Off", 1581 "On-During-Rebuild", 1582 "NC" 1583 }; 1584 1585 static int 1586 mpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS) 1587 { 1588 char inbuf[20]; 1589 struct mpt_softc *mpt; 1590 const char *str; 1591 int error; 1592 u_int size; 1593 u_int i; 1594 1595 GIANT_REQUIRED; 1596 mpt = (struct mpt_softc *)arg1; 1597 str = mpt_vol_mwce_strs[mpt->raid_mwce_setting]; 1598 error = SYSCTL_OUT(req, str, strlen(str) + 1); 1599 if (error || !req->newptr) 1600 return (error); 1601 1602 size = req->newlen - req->newidx; 1603 if (size >= sizeof(inbuf)) 1604 return (EINVAL); 1605 1606 error = SYSCTL_IN(req, inbuf, size); 1607 if (error) 1608 return (error); 1609 inbuf[size] = '\0'; 1610 for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) { 1611 1612 if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) 1613 return (mpt_raid_set_vol_mwce(mpt, i)); 1614 } 1615 return (EINVAL); 1616 } 1617 1618 static int 1619 mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS) 1620 { 1621 struct mpt_softc *mpt; 1622 u_int raid_resync_rate; 1623 int error; 1624 1625 GIANT_REQUIRED; 1626 mpt = (struct mpt_softc *)arg1; 1627 raid_resync_rate = mpt->raid_resync_rate; 1628 1629 error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req); 1630 if (error || !req->newptr) 1631 return error; 1632 1633 return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate)); 1634 } 1635 1636 static int 1637 mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS) 1638 { 1639 struct mpt_softc *mpt; 1640 u_int raid_queue_depth; 1641 int error; 1642 1643 GIANT_REQUIRED; 1644 mpt = (struct mpt_softc *)arg1; 1645 raid_queue_depth = mpt->raid_queue_depth; 1646 1647 error = sysctl_handle_int(oidp, &raid_queue_depth, 0, req); 1648 if (error || !req->newptr) 1649 return error; 1650 1651 return (mpt_raid_set_vol_queue_depth(mpt, raid_queue_depth)); 1652 } 1653 1654 static void 1655 mpt_raid_sysctl_attach(struct mpt_softc *mpt) 1656 { 1657 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev); 1658 struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev); 1659 1660 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1661 "vol_member_wce", CTLTYPE_STRING | CTLFLAG_RW, mpt, 0, 1662 mpt_raid_sysctl_vol_member_wce, "A", 1663 "volume member WCE(On,Off,On-During-Rebuild,NC)"); 1664 1665 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1666 "vol_queue_depth", CTLTYPE_INT | CTLFLAG_RW, mpt, 0, 1667 mpt_raid_sysctl_vol_queue_depth, "I", 1668 "default volume queue depth"); 1669 1670 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1671 "vol_resync_rate", CTLTYPE_INT | CTLFLAG_RW, mpt, 0, 1672 mpt_raid_sysctl_vol_resync_rate, "I", 1673 "volume resync priority (0 == NC, 1 - 255)"); 1674 } 1675