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