1147883Sscottl/*- 2147883Sscottl * Routines for handling the integrated RAID features LSI MPT Fusion adapters. 3147883Sscottl * 4147883Sscottl * Copyright (c) 2005, WHEEL Sp. z o.o. 5147883Sscottl * Copyright (c) 2005 Justin T. Gibbs. 6147883Sscottl * All rights reserved. 7147883Sscottl * 8147883Sscottl * Redistribution and use in source and binary forms, with or without 9147883Sscottl * modification, are permitted provided that the following conditions are 10147883Sscottl * met: 11147883Sscottl * 1. Redistributions of source code must retain the above copyright 12147883Sscottl * notice, this list of conditions and the following disclaimer. 13147883Sscottl * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14147883Sscottl * substantially similar to the "NO WARRANTY" disclaimer below 15147883Sscottl * ("Disclaimer") and any redistribution must be conditioned upon including 16147883Sscottl * a substantially similar Disclaimer requirement for further binary 17147883Sscottl * redistribution. 18148679Sgibbs * 3. Neither the names of the above listed copyright holders nor the names 19148679Sgibbs * of any contributors may be used to endorse or promote products derived 20148679Sgibbs * from this software without specific prior written permission. 21147883Sscottl * 22147883Sscottl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23147883Sscottl * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24147883Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25147883Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26147883Sscottl * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27147883Sscottl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28147883Sscottl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29147883Sscottl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30147883Sscottl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31147883Sscottl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 32147883Sscottl * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33147883Sscottl */ 34159052Smjacob/*- 35159052Smjacob * Some Breakage and Bug Fixing added later. 36159052Smjacob * Copyright (c) 2006, by Matthew Jacob 37159052Smjacob * All Rights Reserved 38159052Smjacob * 39159052Smjacob * Support from LSI-Logic has also gone a great deal toward making this a 40159052Smjacob * workable subsystem and is gratefully acknowledged. 41159052Smjacob */ 42147883Sscottl 43147883Sscottl#include <sys/cdefs.h> 44147883Sscottl__FBSDID("$FreeBSD$"); 45147883Sscottl 46147883Sscottl#include <dev/mpt/mpt.h> 47147883Sscottl#include <dev/mpt/mpt_raid.h> 48147883Sscottl 49147883Sscottl#include "dev/mpt/mpilib/mpi_ioc.h" /* XXX Fix Event Handling!!! */ 50147883Sscottl#include "dev/mpt/mpilib/mpi_raid.h" 51147883Sscottl 52147883Sscottl#include <cam/cam.h> 53147883Sscottl#include <cam/cam_ccb.h> 54241874Smarius#include <cam/cam_periph.h> 55147883Sscottl#include <cam/cam_sim.h> 56147883Sscottl#include <cam/cam_xpt_sim.h> 57147883Sscottl 58147883Sscottl#include <sys/callout.h> 59147883Sscottl#include <sys/kthread.h> 60147883Sscottl#include <sys/sysctl.h> 61147883Sscottl 62147883Sscottl#include <machine/stdarg.h> 63147883Sscottl 64147883Sscottlstruct mpt_raid_action_result 65147883Sscottl{ 66147883Sscottl union { 67147883Sscottl MPI_RAID_VOL_INDICATOR indicator_struct; 68147883Sscottl uint32_t new_settings; 69147883Sscottl uint8_t phys_disk_num; 70147883Sscottl } action_data; 71147883Sscottl uint16_t action_status; 72147883Sscottl}; 73147883Sscottl 74147883Sscottl#define REQ_TO_RAID_ACTION_RESULT(req) ((struct mpt_raid_action_result *) \ 75147883Sscottl (((MSG_RAID_ACTION_REQUEST *)(req->req_vbuf)) + 1)) 76147883Sscottl 77147883Sscottl#define REQ_IOCSTATUS(req) ((req)->IOCStatus & MPI_IOCSTATUS_MASK) 78147883Sscottl 79147883Sscottlstatic mpt_probe_handler_t mpt_raid_probe; 80147883Sscottlstatic mpt_attach_handler_t mpt_raid_attach; 81158935Smjacobstatic mpt_enable_handler_t mpt_raid_enable; 82147883Sscottlstatic mpt_event_handler_t mpt_raid_event; 83147883Sscottlstatic mpt_shutdown_handler_t mpt_raid_shutdown; 84147883Sscottlstatic mpt_reset_handler_t mpt_raid_ioc_reset; 85147883Sscottlstatic mpt_detach_handler_t mpt_raid_detach; 86147883Sscottl 87147883Sscottlstatic struct mpt_personality mpt_raid_personality = 88147883Sscottl{ 89147883Sscottl .name = "mpt_raid", 90147883Sscottl .probe = mpt_raid_probe, 91147883Sscottl .attach = mpt_raid_attach, 92158935Smjacob .enable = mpt_raid_enable, 93147883Sscottl .event = mpt_raid_event, 94147883Sscottl .reset = mpt_raid_ioc_reset, 95147883Sscottl .shutdown = mpt_raid_shutdown, 96147883Sscottl .detach = mpt_raid_detach, 97147883Sscottl}; 98147883Sscottl 99147883SscottlDECLARE_MPT_PERSONALITY(mpt_raid, SI_ORDER_THIRD); 100147883SscottlMPT_PERSONALITY_DEPEND(mpt_raid, mpt_cam, 1, 1, 1); 101147883Sscottl 102147883Sscottlstatic mpt_reply_handler_t mpt_raid_reply_handler; 103147883Sscottlstatic int mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req, 104147883Sscottl MSG_DEFAULT_REPLY *reply_frame); 105147883Sscottlstatic int mpt_spawn_raid_thread(struct mpt_softc *mpt); 106147883Sscottlstatic void mpt_terminate_raid_thread(struct mpt_softc *mpt); 107147883Sscottlstatic void mpt_raid_thread(void *arg); 108147883Sscottlstatic timeout_t mpt_raid_timer; 109153072Sru#if 0 110147883Sscottlstatic void mpt_enable_vol(struct mpt_softc *mpt, 111147883Sscottl struct mpt_raid_volume *mpt_vol, int enable); 112147883Sscottl#endif 113169293Smjacobstatic void mpt_verify_mwce(struct mpt_softc *, struct mpt_raid_volume *); 114169293Smjacobstatic void mpt_adjust_queue_depth(struct mpt_softc *, struct mpt_raid_volume *, 115169293Smjacob struct cam_path *); 116169293Smjacobstatic void mpt_raid_sysctl_attach(struct mpt_softc *); 117147883Sscottl 118224493Smariusstatic const char *mpt_vol_type(struct mpt_raid_volume *vol); 119224493Smariusstatic const char *mpt_vol_state(struct mpt_raid_volume *vol); 120224493Smariusstatic const char *mpt_disk_state(struct mpt_raid_disk *disk); 121224493Smariusstatic void mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol, 122224493Smarius const char *fmt, ...); 123224493Smariusstatic void mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk, 124224493Smarius const char *fmt, ...); 125224493Smarius 126224493Smariusstatic int mpt_issue_raid_req(struct mpt_softc *mpt, 127224493Smarius struct mpt_raid_volume *vol, struct mpt_raid_disk *disk, request_t *req, 128224493Smarius u_int Action, uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len, 129224493Smarius int write, int wait); 130224493Smarius 131224493Smariusstatic int mpt_refresh_raid_data(struct mpt_softc *mpt); 132224493Smariusstatic void mpt_schedule_raid_refresh(struct mpt_softc *mpt); 133224493Smarius 134147883Sscottlstatic uint32_t raid_handler_id = MPT_HANDLER_ID_NONE; 135147883Sscottl 136224493Smariusstatic const char * 137147883Sscottlmpt_vol_type(struct mpt_raid_volume *vol) 138147883Sscottl{ 139147883Sscottl switch (vol->config_page->VolumeType) { 140147883Sscottl case MPI_RAID_VOL_TYPE_IS: 141147883Sscottl return ("RAID-0"); 142147883Sscottl case MPI_RAID_VOL_TYPE_IME: 143147883Sscottl return ("RAID-1E"); 144147883Sscottl case MPI_RAID_VOL_TYPE_IM: 145147883Sscottl return ("RAID-1"); 146147883Sscottl default: 147147883Sscottl return ("Unknown"); 148147883Sscottl } 149147883Sscottl} 150147883Sscottl 151224493Smariusstatic const char * 152147883Sscottlmpt_vol_state(struct mpt_raid_volume *vol) 153147883Sscottl{ 154147883Sscottl switch (vol->config_page->VolumeStatus.State) { 155147883Sscottl case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: 156147883Sscottl return ("Optimal"); 157147883Sscottl case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: 158147883Sscottl return ("Degraded"); 159147883Sscottl case MPI_RAIDVOL0_STATUS_STATE_FAILED: 160147883Sscottl return ("Failed"); 161147883Sscottl default: 162147883Sscottl return ("Unknown"); 163147883Sscottl } 164147883Sscottl} 165147883Sscottl 166224493Smariusstatic const char * 167147883Sscottlmpt_disk_state(struct mpt_raid_disk *disk) 168147883Sscottl{ 169147883Sscottl switch (disk->config_page.PhysDiskStatus.State) { 170147883Sscottl case MPI_PHYSDISK0_STATUS_ONLINE: 171147883Sscottl return ("Online"); 172147883Sscottl case MPI_PHYSDISK0_STATUS_MISSING: 173147883Sscottl return ("Missing"); 174147883Sscottl case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE: 175147883Sscottl return ("Incompatible"); 176147883Sscottl case MPI_PHYSDISK0_STATUS_FAILED: 177147883Sscottl return ("Failed"); 178147883Sscottl case MPI_PHYSDISK0_STATUS_INITIALIZING: 179147883Sscottl return ("Initializing"); 180147883Sscottl case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED: 181147883Sscottl return ("Offline Requested"); 182147883Sscottl case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED: 183147883Sscottl return ("Failed per Host Request"); 184147883Sscottl case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE: 185147883Sscottl return ("Offline"); 186147883Sscottl default: 187147883Sscottl return ("Unknown"); 188147883Sscottl } 189147883Sscottl} 190147883Sscottl 191224493Smariusstatic void 192147883Sscottlmpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol, 193147883Sscottl const char *fmt, ...) 194147883Sscottl{ 195147883Sscottl va_list ap; 196147883Sscottl 197147883Sscottl printf("%s:vol%d(%s:%d:%d): ", device_get_nameunit(mpt->dev), 198147883Sscottl (u_int)(vol - mpt->raid_volumes), device_get_nameunit(mpt->dev), 199147883Sscottl vol->config_page->VolumeBus, vol->config_page->VolumeID); 200147883Sscottl va_start(ap, fmt); 201147883Sscottl vprintf(fmt, ap); 202147883Sscottl va_end(ap); 203147883Sscottl} 204147883Sscottl 205224493Smariusstatic void 206147883Sscottlmpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk, 207147883Sscottl const char *fmt, ...) 208147883Sscottl{ 209147883Sscottl va_list ap; 210147883Sscottl 211147883Sscottl if (disk->volume != NULL) { 212147883Sscottl printf("(%s:vol%d:%d): ", 213147883Sscottl device_get_nameunit(mpt->dev), 214147883Sscottl disk->volume->config_page->VolumeID, 215147883Sscottl disk->member_number); 216147883Sscottl } else { 217147883Sscottl printf("(%s:%d:%d): ", device_get_nameunit(mpt->dev), 218147883Sscottl disk->config_page.PhysDiskBus, 219147883Sscottl disk->config_page.PhysDiskID); 220147883Sscottl } 221147883Sscottl va_start(ap, fmt); 222147883Sscottl vprintf(fmt, ap); 223147883Sscottl va_end(ap); 224147883Sscottl} 225147883Sscottl 226147883Sscottlstatic void 227147883Sscottlmpt_raid_async(void *callback_arg, u_int32_t code, 228147883Sscottl struct cam_path *path, void *arg) 229147883Sscottl{ 230147883Sscottl struct mpt_softc *mpt; 231147883Sscottl 232147883Sscottl mpt = (struct mpt_softc*)callback_arg; 233147883Sscottl switch (code) { 234147883Sscottl case AC_FOUND_DEVICE: 235147883Sscottl { 236147883Sscottl struct ccb_getdev *cgd; 237147883Sscottl struct mpt_raid_volume *mpt_vol; 238147883Sscottl 239147883Sscottl cgd = (struct ccb_getdev *)arg; 240158935Smjacob if (cgd == NULL) { 241147883Sscottl break; 242158935Smjacob } 243147883Sscottl 244159050Smjacob mpt_lprt(mpt, MPT_PRT_DEBUG, "Callback for %d\n", 245147883Sscottl cgd->ccb_h.target_id); 246147883Sscottl 247147883Sscottl RAID_VOL_FOREACH(mpt, mpt_vol) { 248147883Sscottl if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 249147883Sscottl continue; 250147883Sscottl 251147883Sscottl if (mpt_vol->config_page->VolumeID 252147883Sscottl == cgd->ccb_h.target_id) { 253147883Sscottl mpt_adjust_queue_depth(mpt, mpt_vol, path); 254147883Sscottl break; 255147883Sscottl } 256147883Sscottl } 257147883Sscottl } 258147883Sscottl default: 259147883Sscottl break; 260147883Sscottl } 261147883Sscottl} 262147883Sscottl 263224493Smariusstatic int 264147883Sscottlmpt_raid_probe(struct mpt_softc *mpt) 265147883Sscottl{ 266224493Smarius 267157117Smjacob if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) { 268147883Sscottl return (ENODEV); 269157117Smjacob } 270147883Sscottl return (0); 271147883Sscottl} 272147883Sscottl 273224493Smariusstatic int 274147883Sscottlmpt_raid_attach(struct mpt_softc *mpt) 275147883Sscottl{ 276147883Sscottl struct ccb_setasync csa; 277147883Sscottl mpt_handler_t handler; 278147883Sscottl int error; 279147883Sscottl 280198262Skan mpt_callout_init(mpt, &mpt->raid_timer); 281147883Sscottl 282169293Smjacob error = mpt_spawn_raid_thread(mpt); 283169293Smjacob if (error != 0) { 284169293Smjacob mpt_prt(mpt, "Unable to spawn RAID thread!\n"); 285169293Smjacob goto cleanup; 286169293Smjacob } 287169293Smjacob 288169293Smjacob MPT_LOCK(mpt); 289147883Sscottl handler.reply_handler = mpt_raid_reply_handler; 290147883Sscottl error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 291147883Sscottl &raid_handler_id); 292158935Smjacob if (error != 0) { 293158935Smjacob mpt_prt(mpt, "Unable to register RAID haandler!\n"); 294147883Sscottl goto cleanup; 295158935Smjacob } 296147883Sscottl 297158935Smjacob xpt_setup_ccb(&csa.ccb_h, mpt->path, 5); 298147883Sscottl csa.ccb_h.func_code = XPT_SASYNC_CB; 299147883Sscottl csa.event_enable = AC_FOUND_DEVICE; 300147883Sscottl csa.callback = mpt_raid_async; 301147883Sscottl csa.callback_arg = mpt; 302147883Sscottl xpt_action((union ccb *)&csa); 303147883Sscottl if (csa.ccb_h.status != CAM_REQ_CMP) { 304147883Sscottl mpt_prt(mpt, "mpt_raid_attach: Unable to register " 305147883Sscottl "CAM async handler.\n"); 306147883Sscottl } 307169293Smjacob MPT_UNLOCK(mpt); 308147883Sscottl 309147883Sscottl mpt_raid_sysctl_attach(mpt); 310147883Sscottl return (0); 311147883Sscottlcleanup: 312169293Smjacob MPT_UNLOCK(mpt); 313147883Sscottl mpt_raid_detach(mpt); 314147883Sscottl return (error); 315147883Sscottl} 316147883Sscottl 317224493Smariusstatic int 318158935Smjacobmpt_raid_enable(struct mpt_softc *mpt) 319158935Smjacob{ 320224493Smarius 321158935Smjacob return (0); 322158935Smjacob} 323158935Smjacob 324224493Smariusstatic void 325147883Sscottlmpt_raid_detach(struct mpt_softc *mpt) 326147883Sscottl{ 327147883Sscottl struct ccb_setasync csa; 328147883Sscottl mpt_handler_t handler; 329147883Sscottl 330198262Skan mpt_callout_drain(mpt, &mpt->raid_timer); 331198262Skan 332169293Smjacob MPT_LOCK(mpt); 333147883Sscottl mpt_terminate_raid_thread(mpt); 334147883Sscottl handler.reply_handler = mpt_raid_reply_handler; 335147883Sscottl mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 336147883Sscottl raid_handler_id); 337147883Sscottl xpt_setup_ccb(&csa.ccb_h, mpt->path, /*priority*/5); 338147883Sscottl csa.ccb_h.func_code = XPT_SASYNC_CB; 339147883Sscottl csa.event_enable = 0; 340147883Sscottl csa.callback = mpt_raid_async; 341147883Sscottl csa.callback_arg = mpt; 342147883Sscottl xpt_action((union ccb *)&csa); 343169293Smjacob MPT_UNLOCK(mpt); 344147883Sscottl} 345147883Sscottl 346147883Sscottlstatic void 347147883Sscottlmpt_raid_ioc_reset(struct mpt_softc *mpt, int type) 348147883Sscottl{ 349224493Smarius 350147883Sscottl /* Nothing to do yet. */ 351147883Sscottl} 352147883Sscottl 353147883Sscottlstatic const char *raid_event_txt[] = 354147883Sscottl{ 355147883Sscottl "Volume Created", 356147883Sscottl "Volume Deleted", 357147883Sscottl "Volume Settings Changed", 358147883Sscottl "Volume Status Changed", 359147883Sscottl "Volume Physical Disk Membership Changed", 360147883Sscottl "Physical Disk Created", 361147883Sscottl "Physical Disk Deleted", 362147883Sscottl "Physical Disk Settings Changed", 363147883Sscottl "Physical Disk Status Changed", 364147883Sscottl "Domain Validation Required", 365147883Sscottl "SMART Data Received", 366147883Sscottl "Replace Action Started", 367147883Sscottl}; 368147883Sscottl 369147883Sscottlstatic int 370147883Sscottlmpt_raid_event(struct mpt_softc *mpt, request_t *req, 371147883Sscottl MSG_EVENT_NOTIFY_REPLY *msg) 372147883Sscottl{ 373147883Sscottl EVENT_DATA_RAID *raid_event; 374147883Sscottl struct mpt_raid_volume *mpt_vol; 375147883Sscottl struct mpt_raid_disk *mpt_disk; 376147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 377147883Sscottl int i; 378147883Sscottl int print_event; 379147883Sscottl 380158935Smjacob if (msg->Event != MPI_EVENT_INTEGRATED_RAID) { 381158935Smjacob return (0); 382158935Smjacob } 383147883Sscottl 384147883Sscottl raid_event = (EVENT_DATA_RAID *)&msg->Data; 385158935Smjacob 386147883Sscottl mpt_vol = NULL; 387147883Sscottl vol_pg = NULL; 388147883Sscottl if (mpt->raid_volumes != NULL && mpt->ioc_page2 != NULL) { 389147883Sscottl for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 390147883Sscottl mpt_vol = &mpt->raid_volumes[i]; 391147883Sscottl vol_pg = mpt_vol->config_page; 392147883Sscottl 393147883Sscottl if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 394147883Sscottl continue; 395147883Sscottl 396147883Sscottl if (vol_pg->VolumeID == raid_event->VolumeID 397147883Sscottl && vol_pg->VolumeBus == raid_event->VolumeBus) 398147883Sscottl break; 399147883Sscottl } 400147883Sscottl if (i >= mpt->ioc_page2->MaxVolumes) { 401147883Sscottl mpt_vol = NULL; 402147883Sscottl vol_pg = NULL; 403147883Sscottl } 404147883Sscottl } 405147883Sscottl 406147883Sscottl mpt_disk = NULL; 407158935Smjacob if (raid_event->PhysDiskNum != 0xFF && mpt->raid_disks != NULL) { 408158935Smjacob mpt_disk = mpt->raid_disks + raid_event->PhysDiskNum; 409158935Smjacob if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) { 410147883Sscottl mpt_disk = NULL; 411158935Smjacob } 412147883Sscottl } 413147883Sscottl 414147883Sscottl print_event = 1; 415147883Sscottl switch(raid_event->ReasonCode) { 416147883Sscottl case MPI_EVENT_RAID_RC_VOLUME_CREATED: 417147883Sscottl case MPI_EVENT_RAID_RC_VOLUME_DELETED: 418147883Sscottl break; 419147883Sscottl case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: 420147883Sscottl if (mpt_vol != NULL) { 421147883Sscottl if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) { 422147883Sscottl mpt_vol->flags &= ~MPT_RVF_UP2DATE; 423147883Sscottl } else { 424147883Sscottl /* 425147883Sscottl * Coalesce status messages into one 426147883Sscottl * per background run of our RAID thread. 427147883Sscottl * This removes "spurious" status messages 428147883Sscottl * from our output. 429147883Sscottl */ 430147883Sscottl print_event = 0; 431147883Sscottl } 432147883Sscottl } 433147883Sscottl break; 434147883Sscottl case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED: 435147883Sscottl case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED: 436147883Sscottl mpt->raid_rescan++; 437158935Smjacob if (mpt_vol != NULL) { 438147883Sscottl mpt_vol->flags &= ~(MPT_RVF_UP2DATE|MPT_RVF_ANNOUNCED); 439158935Smjacob } 440147883Sscottl break; 441147883Sscottl case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: 442147883Sscottl case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: 443147883Sscottl mpt->raid_rescan++; 444147883Sscottl break; 445147883Sscottl case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED: 446147883Sscottl case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: 447147883Sscottl mpt->raid_rescan++; 448158935Smjacob if (mpt_disk != NULL) { 449147883Sscottl mpt_disk->flags &= ~MPT_RDF_UP2DATE; 450158935Smjacob } 451147883Sscottl break; 452147883Sscottl case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED: 453147883Sscottl mpt->raid_rescan++; 454147883Sscottl break; 455147883Sscottl case MPI_EVENT_RAID_RC_SMART_DATA: 456147883Sscottl case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED: 457147883Sscottl break; 458147883Sscottl } 459147883Sscottl 460147883Sscottl if (print_event) { 461147883Sscottl if (mpt_disk != NULL) { 462147883Sscottl mpt_disk_prt(mpt, mpt_disk, ""); 463147883Sscottl } else if (mpt_vol != NULL) { 464147883Sscottl mpt_vol_prt(mpt, mpt_vol, ""); 465147883Sscottl } else { 466147883Sscottl mpt_prt(mpt, "Volume(%d:%d", raid_event->VolumeBus, 467147883Sscottl raid_event->VolumeID); 468147883Sscottl 469147883Sscottl if (raid_event->PhysDiskNum != 0xFF) 470147883Sscottl mpt_prtc(mpt, ":%d): ", 471147883Sscottl raid_event->PhysDiskNum); 472147883Sscottl else 473147883Sscottl mpt_prtc(mpt, "): "); 474147883Sscottl } 475147883Sscottl 476147883Sscottl if (raid_event->ReasonCode >= NUM_ELEMENTS(raid_event_txt)) 477147883Sscottl mpt_prtc(mpt, "Unhandled RaidEvent %#x\n", 478147883Sscottl raid_event->ReasonCode); 479147883Sscottl else 480147883Sscottl mpt_prtc(mpt, "%s\n", 481147883Sscottl raid_event_txt[raid_event->ReasonCode]); 482147883Sscottl } 483147883Sscottl 484147883Sscottl if (raid_event->ReasonCode == MPI_EVENT_RAID_RC_SMART_DATA) { 485147883Sscottl /* XXX Use CAM's print sense for this... */ 486147883Sscottl if (mpt_disk != NULL) 487147883Sscottl mpt_disk_prt(mpt, mpt_disk, ""); 488147883Sscottl else 489157117Smjacob mpt_prt(mpt, "Volume(%d:%d:%d: ", 490157117Smjacob raid_event->VolumeBus, raid_event->VolumeID, 491157117Smjacob raid_event->PhysDiskNum); 492157117Smjacob mpt_prtc(mpt, "ASC 0x%x, ASCQ 0x%x)\n", 493147883Sscottl raid_event->ASC, raid_event->ASCQ); 494147883Sscottl } 495147883Sscottl 496147883Sscottl mpt_raid_wakeup(mpt); 497158935Smjacob return (1); 498147883Sscottl} 499147883Sscottl 500147883Sscottlstatic void 501147883Sscottlmpt_raid_shutdown(struct mpt_softc *mpt) 502147883Sscottl{ 503147883Sscottl struct mpt_raid_volume *mpt_vol; 504147883Sscottl 505157117Smjacob if (mpt->raid_mwce_setting != MPT_RAID_MWCE_REBUILD_ONLY) { 506147883Sscottl return; 507157117Smjacob } 508147883Sscottl 509147883Sscottl mpt->raid_mwce_setting = MPT_RAID_MWCE_OFF; 510147883Sscottl RAID_VOL_FOREACH(mpt, mpt_vol) { 511147883Sscottl mpt_verify_mwce(mpt, mpt_vol); 512147883Sscottl } 513147883Sscottl} 514147883Sscottl 515147883Sscottlstatic int 516147883Sscottlmpt_raid_reply_handler(struct mpt_softc *mpt, request_t *req, 517157117Smjacob uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) 518147883Sscottl{ 519147883Sscottl int free_req; 520147883Sscottl 521147883Sscottl if (req == NULL) 522158935Smjacob return (TRUE); 523147883Sscottl 524147883Sscottl free_req = TRUE; 525147883Sscottl if (reply_frame != NULL) 526147883Sscottl free_req = mpt_raid_reply_frame_handler(mpt, req, reply_frame); 527153072Sru#ifdef NOTYET 528147883Sscottl else if (req->ccb != NULL) { 529147883Sscottl /* Complete Quiesce CCB with error... */ 530147883Sscottl } 531147883Sscottl#endif 532147883Sscottl 533147883Sscottl req->state &= ~REQ_STATE_QUEUED; 534147883Sscottl req->state |= REQ_STATE_DONE; 535147883Sscottl TAILQ_REMOVE(&mpt->request_pending_list, req, links); 536147883Sscottl 537147883Sscottl if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { 538147883Sscottl wakeup(req); 539147883Sscottl } else if (free_req) { 540147883Sscottl mpt_free_request(mpt, req); 541147883Sscottl } 542147883Sscottl 543158935Smjacob return (TRUE); 544147883Sscottl} 545147883Sscottl 546147883Sscottl/* 547147883Sscottl * Parse additional completion information in the reply 548147883Sscottl * frame for RAID I/O requests. 549147883Sscottl */ 550147883Sscottlstatic int 551147883Sscottlmpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req, 552158935Smjacob MSG_DEFAULT_REPLY *reply_frame) 553147883Sscottl{ 554147883Sscottl MSG_RAID_ACTION_REPLY *reply; 555147883Sscottl struct mpt_raid_action_result *action_result; 556147883Sscottl MSG_RAID_ACTION_REQUEST *rap; 557147883Sscottl 558147883Sscottl reply = (MSG_RAID_ACTION_REPLY *)reply_frame; 559147883Sscottl req->IOCStatus = le16toh(reply->IOCStatus); 560147883Sscottl rap = (MSG_RAID_ACTION_REQUEST *)req->req_vbuf; 561147883Sscottl 562147883Sscottl switch (rap->Action) { 563147883Sscottl case MPI_RAID_ACTION_QUIESCE_PHYS_IO: 564158935Smjacob mpt_prt(mpt, "QUIESCE PHYSIO DONE\n"); 565147883Sscottl break; 566147883Sscottl case MPI_RAID_ACTION_ENABLE_PHYS_IO: 567158935Smjacob mpt_prt(mpt, "ENABLY PHYSIO DONE\n"); 568147883Sscottl break; 569147883Sscottl default: 570147883Sscottl break; 571147883Sscottl } 572158935Smjacob action_result = REQ_TO_RAID_ACTION_RESULT(req); 573158935Smjacob memcpy(&action_result->action_data, &reply->ActionData, 574158935Smjacob sizeof(action_result->action_data)); 575186878Smarius action_result->action_status = le16toh(reply->ActionStatus); 576158935Smjacob return (TRUE); 577147883Sscottl} 578147883Sscottl 579147883Sscottl/* 580147883Sscottl * Utiltity routine to perform a RAID action command; 581147883Sscottl */ 582224493Smariusstatic int 583147883Sscottlmpt_issue_raid_req(struct mpt_softc *mpt, struct mpt_raid_volume *vol, 584147883Sscottl struct mpt_raid_disk *disk, request_t *req, u_int Action, 585147883Sscottl uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len, 586147883Sscottl int write, int wait) 587147883Sscottl{ 588147883Sscottl MSG_RAID_ACTION_REQUEST *rap; 589147883Sscottl SGE_SIMPLE32 *se; 590147883Sscottl 591147883Sscottl rap = req->req_vbuf; 592147883Sscottl memset(rap, 0, sizeof *rap); 593147883Sscottl rap->Action = Action; 594186878Smarius rap->ActionDataWord = htole32(ActionDataWord); 595147883Sscottl rap->Function = MPI_FUNCTION_RAID_ACTION; 596147883Sscottl rap->VolumeID = vol->config_page->VolumeID; 597147883Sscottl rap->VolumeBus = vol->config_page->VolumeBus; 598147883Sscottl if (disk != 0) 599147883Sscottl rap->PhysDiskNum = disk->config_page.PhysDiskNum; 600147883Sscottl else 601147883Sscottl rap->PhysDiskNum = 0xFF; 602147883Sscottl se = (SGE_SIMPLE32 *)&rap->ActionDataSGE; 603186878Smarius se->Address = htole32(addr); 604147883Sscottl MPI_pSGE_SET_LENGTH(se, len); 605147883Sscottl MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 606147883Sscottl MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 607147883Sscottl MPI_SGE_FLAGS_END_OF_LIST | 608251187Sdelphij (write ? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST))); 609186878Smarius se->FlagsLength = htole32(se->FlagsLength); 610147883Sscottl rap->MsgContext = htole32(req->index | raid_handler_id); 611147883Sscottl 612147883Sscottl mpt_check_doorbell(mpt); 613147883Sscottl mpt_send_cmd(mpt, req); 614147883Sscottl 615147883Sscottl if (wait) { 616147883Sscottl return (mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, 617147883Sscottl /*sleep_ok*/FALSE, /*time_ms*/2000)); 618147883Sscottl } else { 619147883Sscottl return (0); 620147883Sscottl } 621147883Sscottl} 622147883Sscottl 623147883Sscottl/*************************** RAID Status Monitoring ***************************/ 624147883Sscottlstatic int 625147883Sscottlmpt_spawn_raid_thread(struct mpt_softc *mpt) 626147883Sscottl{ 627147883Sscottl int error; 628147883Sscottl 629147883Sscottl /* 630147883Sscottl * Freeze out any CAM transactions until our thread 631147883Sscottl * is able to run at least once. We need to update 632147883Sscottl * our RAID pages before acception I/O or we may 633147883Sscottl * reject I/O to an ID we later determine is for a 634147883Sscottl * hidden physdisk. 635147883Sscottl */ 636169293Smjacob MPT_LOCK(mpt); 637147883Sscottl xpt_freeze_simq(mpt->phydisk_sim, 1); 638169293Smjacob MPT_UNLOCK(mpt); 639147883Sscottl error = mpt_kthread_create(mpt_raid_thread, mpt, 640147883Sscottl &mpt->raid_thread, /*flags*/0, /*altstack*/0, 641147883Sscottl "mpt_raid%d", mpt->unit); 642169293Smjacob if (error != 0) { 643169293Smjacob MPT_LOCK(mpt); 644147883Sscottl xpt_release_simq(mpt->phydisk_sim, /*run_queue*/FALSE); 645169293Smjacob MPT_UNLOCK(mpt); 646169293Smjacob } 647147883Sscottl return (error); 648147883Sscottl} 649147883Sscottl 650147883Sscottlstatic void 651147883Sscottlmpt_terminate_raid_thread(struct mpt_softc *mpt) 652147883Sscottl{ 653147883Sscottl 654147883Sscottl if (mpt->raid_thread == NULL) { 655147883Sscottl return; 656147883Sscottl } 657147883Sscottl mpt->shutdwn_raid = 1; 658209599Sken wakeup(&mpt->raid_volumes); 659147883Sscottl /* 660147883Sscottl * Sleep on a slightly different location 661147883Sscottl * for this interlock just for added safety. 662147883Sscottl */ 663147883Sscottl mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0); 664147883Sscottl} 665147883Sscottl 666147883Sscottlstatic void 667147883Sscottlmpt_raid_thread(void *arg) 668147883Sscottl{ 669147883Sscottl struct mpt_softc *mpt; 670147883Sscottl int firstrun; 671147883Sscottl 672147883Sscottl mpt = (struct mpt_softc *)arg; 673147883Sscottl firstrun = 1; 674147883Sscottl MPT_LOCK(mpt); 675147883Sscottl while (mpt->shutdwn_raid == 0) { 676147883Sscottl 677147883Sscottl if (mpt->raid_wakeup == 0) { 678147883Sscottl mpt_sleep(mpt, &mpt->raid_volumes, PUSER, "idle", 0); 679147883Sscottl continue; 680147883Sscottl } 681147883Sscottl 682147883Sscottl mpt->raid_wakeup = 0; 683147883Sscottl 684158935Smjacob if (mpt_refresh_raid_data(mpt)) { 685158935Smjacob mpt_schedule_raid_refresh(mpt); /* XX NOT QUITE RIGHT */ 686158935Smjacob continue; 687158935Smjacob } 688147883Sscottl 689147883Sscottl /* 690147883Sscottl * Now that we have our first snapshot of RAID data, 691147883Sscottl * allow CAM to access our physical disk bus. 692147883Sscottl */ 693147883Sscottl if (firstrun) { 694147883Sscottl firstrun = 0; 695158935Smjacob xpt_release_simq(mpt->phydisk_sim, TRUE); 696147883Sscottl } 697147883Sscottl 698147883Sscottl if (mpt->raid_rescan != 0) { 699192534Sjhb union ccb *ccb; 700147883Sscottl int error; 701147883Sscottl 702147883Sscottl mpt->raid_rescan = 0; 703192534Sjhb MPT_UNLOCK(mpt); 704147883Sscottl 705192534Sjhb ccb = xpt_alloc_ccb(); 706192534Sjhb 707192534Sjhb MPT_LOCK(mpt); 708249468Smav error = xpt_create_path(&ccb->ccb_h.path, NULL, 709158935Smjacob cam_sim_path(mpt->phydisk_sim), 710158935Smjacob CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 711147883Sscottl if (error != CAM_REQ_CMP) { 712192534Sjhb xpt_free_ccb(ccb); 713147883Sscottl mpt_prt(mpt, "Unable to rescan RAID Bus!\n"); 714147883Sscottl } else { 715203108Smav xpt_rescan(ccb); 716147883Sscottl } 717147883Sscottl } 718147883Sscottl } 719147883Sscottl mpt->raid_thread = NULL; 720147883Sscottl wakeup(&mpt->raid_thread); 721147883Sscottl MPT_UNLOCK(mpt); 722178725Sjkim mpt_kthread_exit(0); 723147883Sscottl} 724147883Sscottl 725160395Smjacob#if 0 726160395Smjacobstatic void 727160395Smjacobmpt_raid_quiesce_timeout(void *arg) 728160395Smjacob{ 729224493Smarius 730160395Smjacob /* Complete the CCB with error */ 731160395Smjacob /* COWWWW */ 732160395Smjacob} 733160395Smjacob 734160395Smjacobstatic timeout_t mpt_raid_quiesce_timeout; 735147883Sscottlcam_status 736147883Sscottlmpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk, 737147883Sscottl request_t *req) 738147883Sscottl{ 739147883Sscottl union ccb *ccb; 740147883Sscottl 741147883Sscottl ccb = req->ccb; 742147883Sscottl if ((mpt_disk->flags & MPT_RDF_QUIESCED) != 0) 743147883Sscottl return (CAM_REQ_CMP); 744147883Sscottl 745147883Sscottl if ((mpt_disk->flags & MPT_RDF_QUIESCING) == 0) { 746147883Sscottl int rv; 747147883Sscottl 748147883Sscottl mpt_disk->flags |= MPT_RDF_QUIESCING; 749147883Sscottl xpt_freeze_devq(ccb->ccb_h.path, 1); 750147883Sscottl 751147883Sscottl rv = mpt_issue_raid_req(mpt, mpt_disk->volume, mpt_disk, req, 752147883Sscottl MPI_RAID_ACTION_QUIESCE_PHYS_IO, 753147883Sscottl /*ActionData*/0, /*addr*/0, 754147883Sscottl /*len*/0, /*write*/FALSE, 755147883Sscottl /*wait*/FALSE); 756147883Sscottl if (rv != 0) 757147883Sscottl return (CAM_REQ_CMP_ERR); 758147883Sscottl 759169293Smjacob mpt_req_timeout(req, mpt_raid_quiesce_timeout, ccb, 5 * hz); 760147883Sscottl#if 0 761147883Sscottl if (rv == ETIMEDOUT) { 762147883Sscottl mpt_disk_prt(mpt, mpt_disk, "mpt_raid_quiesce_disk: " 763147883Sscottl "Quiece Timed-out\n"); 764147883Sscottl xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0); 765147883Sscottl return (CAM_REQ_CMP_ERR); 766147883Sscottl } 767147883Sscottl 768147883Sscottl ar = REQ_TO_RAID_ACTION_RESULT(req); 769147883Sscottl if (rv != 0 770147883Sscottl || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 771147883Sscottl || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 772147883Sscottl mpt_disk_prt(mpt, mpt_disk, "Quiece Failed" 773147883Sscottl "%d:%x:%x\n", rv, req->IOCStatus, 774147883Sscottl ar->action_status); 775147883Sscottl xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0); 776147883Sscottl return (CAM_REQ_CMP_ERR); 777147883Sscottl } 778147883Sscottl#endif 779147883Sscottl return (CAM_REQ_INPROG); 780147883Sscottl } 781147883Sscottl return (CAM_REQUEUE_REQ); 782147883Sscottl} 783160395Smjacob#endif 784147883Sscottl 785147883Sscottl/* XXX Ignores that there may be multiple busses/IOCs involved. */ 786147883Sscottlcam_status 787224493Smariusmpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, target_id_t *tgt) 788147883Sscottl{ 789147883Sscottl struct mpt_raid_disk *mpt_disk; 790147883Sscottl 791147883Sscottl mpt_disk = mpt->raid_disks + ccb->ccb_h.target_id; 792147883Sscottl if (ccb->ccb_h.target_id < mpt->raid_max_disks 793147883Sscottl && (mpt_disk->flags & MPT_RDF_ACTIVE) != 0) { 794147883Sscottl *tgt = mpt_disk->config_page.PhysDiskID; 795147883Sscottl return (0); 796147883Sscottl } 797159050Smjacob mpt_lprt(mpt, MPT_PRT_DEBUG1, "mpt_map_physdisk(%d) - Not Active\n", 798147883Sscottl ccb->ccb_h.target_id); 799147883Sscottl return (-1); 800147883Sscottl} 801147883Sscottl 802159050Smjacob/* XXX Ignores that there may be multiple busses/IOCs involved. */ 803159050Smjacobint 804224494Smariusmpt_is_raid_member(struct mpt_softc *mpt, target_id_t tgt) 805224494Smarius{ 806224494Smarius struct mpt_raid_disk *mpt_disk; 807224494Smarius int i; 808224494Smarius 809224494Smarius if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) 810224494Smarius return (0); 811224494Smarius for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 812224494Smarius mpt_disk = &mpt->raid_disks[i]; 813224494Smarius if ((mpt_disk->flags & MPT_RDF_ACTIVE) != 0 && 814224494Smarius mpt_disk->config_page.PhysDiskID == tgt) 815224494Smarius return (1); 816224494Smarius } 817224494Smarius return (0); 818224494Smarius 819224494Smarius} 820224494Smarius 821224494Smarius/* XXX Ignores that there may be multiple busses/IOCs involved. */ 822224494Smariusint 823224493Smariusmpt_is_raid_volume(struct mpt_softc *mpt, target_id_t tgt) 824159050Smjacob{ 825159050Smjacob CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol; 826159050Smjacob CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol; 827159050Smjacob 828164837Smjacob if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) { 829164837Smjacob return (0); 830164837Smjacob } 831159050Smjacob ioc_vol = mpt->ioc_page2->RaidVolume; 832159050Smjacob ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes; 833159050Smjacob for (;ioc_vol != ioc_last_vol; ioc_vol++) { 834159050Smjacob if (ioc_vol->VolumeID == tgt) { 835159050Smjacob return (1); 836159050Smjacob } 837159050Smjacob } 838159050Smjacob return (0); 839159050Smjacob} 840159050Smjacob 841153072Sru#if 0 842147883Sscottlstatic void 843147883Sscottlmpt_enable_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 844147883Sscottl int enable) 845147883Sscottl{ 846147883Sscottl request_t *req; 847147883Sscottl struct mpt_raid_action_result *ar; 848147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 849147883Sscottl int enabled; 850147883Sscottl int rv; 851147883Sscottl 852147883Sscottl vol_pg = mpt_vol->config_page; 853147883Sscottl enabled = vol_pg->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED; 854147883Sscottl 855147883Sscottl /* 856147883Sscottl * If the setting matches the configuration, 857147883Sscottl * there is nothing to do. 858147883Sscottl */ 859147883Sscottl if ((enabled && enable) 860147883Sscottl || (!enabled && !enable)) 861147883Sscottl return; 862147883Sscottl 863147883Sscottl req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 864147883Sscottl if (req == NULL) { 865147883Sscottl mpt_vol_prt(mpt, mpt_vol, 866147883Sscottl "mpt_enable_vol: Get request failed!\n"); 867147883Sscottl return; 868147883Sscottl } 869147883Sscottl 870147883Sscottl rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 871147883Sscottl enable ? MPI_RAID_ACTION_ENABLE_VOLUME 872147883Sscottl : MPI_RAID_ACTION_DISABLE_VOLUME, 873147883Sscottl /*data*/0, /*addr*/0, /*len*/0, 874147883Sscottl /*write*/FALSE, /*wait*/TRUE); 875147883Sscottl if (rv == ETIMEDOUT) { 876147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_enable_vol: " 877147883Sscottl "%s Volume Timed-out\n", 878147883Sscottl enable ? "Enable" : "Disable"); 879147883Sscottl return; 880147883Sscottl } 881147883Sscottl ar = REQ_TO_RAID_ACTION_RESULT(req); 882147883Sscottl if (rv != 0 883147883Sscottl || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 884147883Sscottl || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 885147883Sscottl mpt_vol_prt(mpt, mpt_vol, "%s Volume Failed: %d:%x:%x\n", 886147883Sscottl enable ? "Enable" : "Disable", 887147883Sscottl rv, req->IOCStatus, ar->action_status); 888147883Sscottl } 889147883Sscottl 890147883Sscottl mpt_free_request(mpt, req); 891147883Sscottl} 892147883Sscottl#endif 893147883Sscottl 894147883Sscottlstatic void 895147883Sscottlmpt_verify_mwce(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol) 896147883Sscottl{ 897147883Sscottl request_t *req; 898147883Sscottl struct mpt_raid_action_result *ar; 899147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 900147883Sscottl uint32_t data; 901147883Sscottl int rv; 902147883Sscottl int resyncing; 903147883Sscottl int mwce; 904147883Sscottl 905147883Sscottl vol_pg = mpt_vol->config_page; 906147883Sscottl resyncing = vol_pg->VolumeStatus.Flags 907147883Sscottl & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 908147883Sscottl mwce = vol_pg->VolumeSettings.Settings 909147883Sscottl & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 910147883Sscottl 911147883Sscottl /* 912147883Sscottl * If the setting matches the configuration, 913147883Sscottl * there is nothing to do. 914147883Sscottl */ 915147883Sscottl switch (mpt->raid_mwce_setting) { 916147883Sscottl case MPT_RAID_MWCE_REBUILD_ONLY: 917157117Smjacob if ((resyncing && mwce) || (!resyncing && !mwce)) { 918147883Sscottl return; 919157117Smjacob } 920147883Sscottl mpt_vol->flags ^= MPT_RVF_WCE_CHANGED; 921147883Sscottl if ((mpt_vol->flags & MPT_RVF_WCE_CHANGED) == 0) { 922147883Sscottl /* 923147883Sscottl * Wait one more status update to see if 924147883Sscottl * resyncing gets enabled. It gets disabled 925147883Sscottl * temporarilly when WCE is changed. 926147883Sscottl */ 927147883Sscottl return; 928147883Sscottl } 929147883Sscottl break; 930147883Sscottl case MPT_RAID_MWCE_ON: 931147883Sscottl if (mwce) 932147883Sscottl return; 933147883Sscottl break; 934147883Sscottl case MPT_RAID_MWCE_OFF: 935147883Sscottl if (!mwce) 936147883Sscottl return; 937147883Sscottl break; 938147883Sscottl case MPT_RAID_MWCE_NC: 939147883Sscottl return; 940147883Sscottl } 941147883Sscottl 942147883Sscottl req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 943147883Sscottl if (req == NULL) { 944147883Sscottl mpt_vol_prt(mpt, mpt_vol, 945147883Sscottl "mpt_verify_mwce: Get request failed!\n"); 946147883Sscottl return; 947147883Sscottl } 948147883Sscottl 949147883Sscottl vol_pg->VolumeSettings.Settings ^= 950147883Sscottl MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 951147883Sscottl memcpy(&data, &vol_pg->VolumeSettings, sizeof(data)); 952147883Sscottl vol_pg->VolumeSettings.Settings ^= 953147883Sscottl MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 954147883Sscottl rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 955147883Sscottl MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 956147883Sscottl data, /*addr*/0, /*len*/0, 957147883Sscottl /*write*/FALSE, /*wait*/TRUE); 958147883Sscottl if (rv == ETIMEDOUT) { 959147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_verify_mwce: " 960147883Sscottl "Write Cache Enable Timed-out\n"); 961147883Sscottl return; 962147883Sscottl } 963147883Sscottl ar = REQ_TO_RAID_ACTION_RESULT(req); 964147883Sscottl if (rv != 0 965147883Sscottl || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 966147883Sscottl || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 967147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Write Cache Enable Failed: " 968147883Sscottl "%d:%x:%x\n", rv, req->IOCStatus, 969147883Sscottl ar->action_status); 970147883Sscottl } else { 971147883Sscottl vol_pg->VolumeSettings.Settings ^= 972147883Sscottl MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 973147883Sscottl } 974147883Sscottl mpt_free_request(mpt, req); 975147883Sscottl} 976147883Sscottl 977147883Sscottlstatic void 978147883Sscottlmpt_verify_resync_rate(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol) 979147883Sscottl{ 980147883Sscottl request_t *req; 981147883Sscottl struct mpt_raid_action_result *ar; 982147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 983147883Sscottl u_int prio; 984147883Sscottl int rv; 985147883Sscottl 986147883Sscottl vol_pg = mpt_vol->config_page; 987147883Sscottl 988147883Sscottl if (mpt->raid_resync_rate == MPT_RAID_RESYNC_RATE_NC) 989147883Sscottl return; 990147883Sscottl 991147883Sscottl /* 992147883Sscottl * If the current RAID resync rate does not 993147883Sscottl * match our configured rate, update it. 994147883Sscottl */ 995147883Sscottl prio = vol_pg->VolumeSettings.Settings 996147883Sscottl & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 997147883Sscottl if (vol_pg->ResyncRate != 0 998147883Sscottl && vol_pg->ResyncRate != mpt->raid_resync_rate) { 999147883Sscottl 1000147883Sscottl req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 1001147883Sscottl if (req == NULL) { 1002147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: " 1003147883Sscottl "Get request failed!\n"); 1004147883Sscottl return; 1005147883Sscottl } 1006147883Sscottl 1007147883Sscottl rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 1008147883Sscottl MPI_RAID_ACTION_SET_RESYNC_RATE, 1009147883Sscottl mpt->raid_resync_rate, /*addr*/0, 1010147883Sscottl /*len*/0, /*write*/FALSE, /*wait*/TRUE); 1011147883Sscottl if (rv == ETIMEDOUT) { 1012147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: " 1013147883Sscottl "Resync Rate Setting Timed-out\n"); 1014147883Sscottl return; 1015147883Sscottl } 1016147883Sscottl 1017147883Sscottl ar = REQ_TO_RAID_ACTION_RESULT(req); 1018147883Sscottl if (rv != 0 1019147883Sscottl || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 1020147883Sscottl || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 1021147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: " 1022147883Sscottl "%d:%x:%x\n", rv, req->IOCStatus, 1023147883Sscottl ar->action_status); 1024147883Sscottl } else 1025147883Sscottl vol_pg->ResyncRate = mpt->raid_resync_rate; 1026147883Sscottl mpt_free_request(mpt, req); 1027147883Sscottl } else if ((prio && mpt->raid_resync_rate < 128) 1028147883Sscottl || (!prio && mpt->raid_resync_rate >= 128)) { 1029147883Sscottl uint32_t data; 1030147883Sscottl 1031147883Sscottl req = mpt_get_request(mpt, /*sleep_ok*/TRUE); 1032147883Sscottl if (req == NULL) { 1033147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: " 1034147883Sscottl "Get request failed!\n"); 1035147883Sscottl return; 1036147883Sscottl } 1037147883Sscottl 1038147883Sscottl vol_pg->VolumeSettings.Settings ^= 1039147883Sscottl MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1040147883Sscottl memcpy(&data, &vol_pg->VolumeSettings, sizeof(data)); 1041147883Sscottl vol_pg->VolumeSettings.Settings ^= 1042147883Sscottl MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1043147883Sscottl rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req, 1044147883Sscottl MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 1045147883Sscottl data, /*addr*/0, /*len*/0, 1046147883Sscottl /*write*/FALSE, /*wait*/TRUE); 1047147883Sscottl if (rv == ETIMEDOUT) { 1048147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: " 1049147883Sscottl "Resync Rate Setting Timed-out\n"); 1050147883Sscottl return; 1051147883Sscottl } 1052147883Sscottl ar = REQ_TO_RAID_ACTION_RESULT(req); 1053147883Sscottl if (rv != 0 1054147883Sscottl || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS 1055147883Sscottl || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) { 1056147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: " 1057147883Sscottl "%d:%x:%x\n", rv, req->IOCStatus, 1058147883Sscottl ar->action_status); 1059147883Sscottl } else { 1060147883Sscottl vol_pg->VolumeSettings.Settings ^= 1061147883Sscottl MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1062147883Sscottl } 1063147883Sscottl 1064147883Sscottl mpt_free_request(mpt, req); 1065147883Sscottl } 1066147883Sscottl} 1067147883Sscottl 1068147883Sscottlstatic void 1069147883Sscottlmpt_adjust_queue_depth(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 1070147883Sscottl struct cam_path *path) 1071147883Sscottl{ 1072147883Sscottl struct ccb_relsim crs; 1073147883Sscottl 1074147883Sscottl xpt_setup_ccb(&crs.ccb_h, path, /*priority*/5); 1075147883Sscottl crs.ccb_h.func_code = XPT_REL_SIMQ; 1076203484Smav crs.ccb_h.flags = CAM_DEV_QFREEZE; 1077147883Sscottl crs.release_flags = RELSIM_ADJUST_OPENINGS; 1078147883Sscottl crs.openings = mpt->raid_queue_depth; 1079147883Sscottl xpt_action((union ccb *)&crs); 1080147883Sscottl if (crs.ccb_h.status != CAM_REQ_CMP) 1081147883Sscottl mpt_vol_prt(mpt, mpt_vol, "mpt_adjust_queue_depth failed " 1082147883Sscottl "with CAM status %#x\n", crs.ccb_h.status); 1083147883Sscottl} 1084147883Sscottl 1085147883Sscottlstatic void 1086147883Sscottlmpt_announce_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol) 1087147883Sscottl{ 1088147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1089147883Sscottl u_int i; 1090147883Sscottl 1091147883Sscottl vol_pg = mpt_vol->config_page; 1092147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Settings ("); 1093147883Sscottl for (i = 1; i <= 0x8000; i <<= 1) { 1094147883Sscottl switch (vol_pg->VolumeSettings.Settings & i) { 1095147883Sscottl case MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE: 1096147883Sscottl mpt_prtc(mpt, " Member-WCE"); 1097147883Sscottl break; 1098147883Sscottl case MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART: 1099147883Sscottl mpt_prtc(mpt, " Offline-On-SMART-Err"); 1100147883Sscottl break; 1101147883Sscottl case MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE: 1102147883Sscottl mpt_prtc(mpt, " Hot-Plug-Spares"); 1103147883Sscottl break; 1104147883Sscottl case MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC: 1105147883Sscottl mpt_prtc(mpt, " High-Priority-ReSync"); 1106147883Sscottl break; 1107147883Sscottl default: 1108147883Sscottl break; 1109147883Sscottl } 1110147883Sscottl } 1111147883Sscottl mpt_prtc(mpt, " )\n"); 1112147883Sscottl if (vol_pg->VolumeSettings.HotSparePool != 0) { 1113147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Using Spare Pool%s", 1114147883Sscottl powerof2(vol_pg->VolumeSettings.HotSparePool) 1115147883Sscottl ? ":" : "s:"); 1116147883Sscottl for (i = 0; i < 8; i++) { 1117147883Sscottl u_int mask; 1118147883Sscottl 1119147883Sscottl mask = 0x1 << i; 1120147883Sscottl if ((vol_pg->VolumeSettings.HotSparePool & mask) == 0) 1121147883Sscottl continue; 1122147883Sscottl mpt_prtc(mpt, " %d", i); 1123147883Sscottl } 1124147883Sscottl mpt_prtc(mpt, "\n"); 1125147883Sscottl } 1126147883Sscottl mpt_vol_prt(mpt, mpt_vol, "%d Members:\n", vol_pg->NumPhysDisks); 1127147883Sscottl for (i = 0; i < vol_pg->NumPhysDisks; i++){ 1128147883Sscottl struct mpt_raid_disk *mpt_disk; 1129147883Sscottl CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1130164837Smjacob int pt_bus = cam_sim_bus(mpt->phydisk_sim); 1131164837Smjacob U8 f, s; 1132147883Sscottl 1133164837Smjacob mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum; 1134147883Sscottl disk_pg = &mpt_disk->config_page; 1135147883Sscottl mpt_prtc(mpt, " "); 1136164837Smjacob mpt_prtc(mpt, "(%s:%d:%d:0): ", device_get_nameunit(mpt->dev), 1137164837Smjacob pt_bus, disk_pg->PhysDiskID); 1138164837Smjacob if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) { 1139164837Smjacob mpt_prtc(mpt, "%s", mpt_disk->member_number == 0? 1140164837Smjacob "Primary" : "Secondary"); 1141164837Smjacob } else { 1142164837Smjacob mpt_prtc(mpt, "Stripe Position %d", 1143147883Sscottl mpt_disk->member_number); 1144164837Smjacob } 1145164837Smjacob f = disk_pg->PhysDiskStatus.Flags; 1146164837Smjacob s = disk_pg->PhysDiskStatus.State; 1147164837Smjacob if (f & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC) { 1148164837Smjacob mpt_prtc(mpt, " Out of Sync"); 1149164837Smjacob } 1150164837Smjacob if (f & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED) { 1151164837Smjacob mpt_prtc(mpt, " Quiesced"); 1152164837Smjacob } 1153164837Smjacob if (f & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) { 1154164837Smjacob mpt_prtc(mpt, " Inactive"); 1155164837Smjacob } 1156164837Smjacob if (f & MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS) { 1157164837Smjacob mpt_prtc(mpt, " Was Optimal"); 1158164837Smjacob } 1159164837Smjacob if (f & MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS) { 1160164837Smjacob mpt_prtc(mpt, " Was Non-Optimal"); 1161164837Smjacob } 1162164837Smjacob switch (s) { 1163164837Smjacob case MPI_PHYSDISK0_STATUS_ONLINE: 1164164837Smjacob mpt_prtc(mpt, " Online"); 1165164837Smjacob break; 1166164837Smjacob case MPI_PHYSDISK0_STATUS_MISSING: 1167164837Smjacob mpt_prtc(mpt, " Missing"); 1168164837Smjacob break; 1169164837Smjacob case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE: 1170164837Smjacob mpt_prtc(mpt, " Incompatible"); 1171164837Smjacob break; 1172164837Smjacob case MPI_PHYSDISK0_STATUS_FAILED: 1173164837Smjacob mpt_prtc(mpt, " Failed"); 1174164837Smjacob break; 1175164837Smjacob case MPI_PHYSDISK0_STATUS_INITIALIZING: 1176164837Smjacob mpt_prtc(mpt, " Initializing"); 1177164837Smjacob break; 1178164837Smjacob case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED: 1179164837Smjacob mpt_prtc(mpt, " Requested Offline"); 1180164837Smjacob break; 1181164837Smjacob case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED: 1182164837Smjacob mpt_prtc(mpt, " Requested Failed"); 1183164837Smjacob break; 1184164837Smjacob case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE: 1185164837Smjacob default: 1186164837Smjacob mpt_prtc(mpt, " Offline Other (%x)", s); 1187164837Smjacob break; 1188164837Smjacob } 1189164837Smjacob mpt_prtc(mpt, "\n"); 1190147883Sscottl } 1191147883Sscottl} 1192147883Sscottl 1193147883Sscottlstatic void 1194147883Sscottlmpt_announce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk) 1195147883Sscottl{ 1196147883Sscottl CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1197164837Smjacob int rd_bus = cam_sim_bus(mpt->sim); 1198164837Smjacob int pt_bus = cam_sim_bus(mpt->phydisk_sim); 1199147883Sscottl u_int i; 1200147883Sscottl 1201147883Sscottl disk_pg = &mpt_disk->config_page; 1202147883Sscottl mpt_disk_prt(mpt, mpt_disk, 1203164837Smjacob "Physical (%s:%d:%d:0), Pass-thru (%s:%d:%d:0)\n", 1204164837Smjacob device_get_nameunit(mpt->dev), rd_bus, 1205147883Sscottl disk_pg->PhysDiskID, device_get_nameunit(mpt->dev), 1206164837Smjacob pt_bus, mpt_disk - mpt->raid_disks); 1207147883Sscottl if (disk_pg->PhysDiskSettings.HotSparePool == 0) 1208147883Sscottl return; 1209147883Sscottl mpt_disk_prt(mpt, mpt_disk, "Member of Hot Spare Pool%s", 1210147883Sscottl powerof2(disk_pg->PhysDiskSettings.HotSparePool) 1211147883Sscottl ? ":" : "s:"); 1212147883Sscottl for (i = 0; i < 8; i++) { 1213147883Sscottl u_int mask; 1214147883Sscottl 1215147883Sscottl mask = 0x1 << i; 1216147883Sscottl if ((disk_pg->PhysDiskSettings.HotSparePool & mask) == 0) 1217147883Sscottl continue; 1218147883Sscottl mpt_prtc(mpt, " %d", i); 1219147883Sscottl } 1220147883Sscottl mpt_prtc(mpt, "\n"); 1221147883Sscottl} 1222147883Sscottl 1223147883Sscottlstatic void 1224147883Sscottlmpt_refresh_raid_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk, 1225147883Sscottl IOC_3_PHYS_DISK *ioc_disk) 1226147883Sscottl{ 1227147883Sscottl int rv; 1228147883Sscottl 1229147883Sscottl rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 1230147883Sscottl /*PageNumber*/0, ioc_disk->PhysDiskNum, 1231147883Sscottl &mpt_disk->config_page.Header, 1232147883Sscottl /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1233147883Sscottl if (rv != 0) { 1234147883Sscottl mpt_prt(mpt, "mpt_refresh_raid_disk: " 1235147883Sscottl "Failed to read RAID Disk Hdr(%d)\n", 1236147883Sscottl ioc_disk->PhysDiskNum); 1237147883Sscottl return; 1238147883Sscottl } 1239147883Sscottl rv = mpt_read_cur_cfg_page(mpt, ioc_disk->PhysDiskNum, 1240147883Sscottl &mpt_disk->config_page.Header, 1241147883Sscottl sizeof(mpt_disk->config_page), 1242147883Sscottl /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1243147883Sscottl if (rv != 0) 1244147883Sscottl mpt_prt(mpt, "mpt_refresh_raid_disk: " 1245147883Sscottl "Failed to read RAID Disk Page(%d)\n", 1246147883Sscottl ioc_disk->PhysDiskNum); 1247186878Smarius mpt2host_config_page_raid_phys_disk_0(&mpt_disk->config_page); 1248147883Sscottl} 1249147883Sscottl 1250147883Sscottlstatic void 1251147883Sscottlmpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, 1252164990Smjacob CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol) 1253147883Sscottl{ 1254147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1255147883Sscottl struct mpt_raid_action_result *ar; 1256147883Sscottl request_t *req; 1257147883Sscottl int rv; 1258147883Sscottl int i; 1259147883Sscottl 1260147883Sscottl vol_pg = mpt_vol->config_page; 1261147883Sscottl mpt_vol->flags &= ~MPT_RVF_UP2DATE; 1262164990Smjacob 1263164990Smjacob rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, 1264164990Smjacob ioc_vol->VolumePageNumber, &vol_pg->Header, TRUE, 5000); 1265147883Sscottl if (rv != 0) { 1266164990Smjacob mpt_vol_prt(mpt, mpt_vol, 1267164990Smjacob "mpt_refresh_raid_vol: Failed to read RAID Vol Hdr(%d)\n", 1268164990Smjacob ioc_vol->VolumePageNumber); 1269147883Sscottl return; 1270147883Sscottl } 1271164990Smjacob 1272147883Sscottl rv = mpt_read_cur_cfg_page(mpt, ioc_vol->VolumePageNumber, 1273164990Smjacob &vol_pg->Header, mpt->raid_page0_len, TRUE, 5000); 1274147883Sscottl if (rv != 0) { 1275164990Smjacob mpt_vol_prt(mpt, mpt_vol, 1276164990Smjacob "mpt_refresh_raid_vol: Failed to read RAID Vol Page(%d)\n", 1277164990Smjacob ioc_vol->VolumePageNumber); 1278147883Sscottl return; 1279147883Sscottl } 1280164990Smjacob mpt2host_config_page_raid_vol_0(vol_pg); 1281164990Smjacob 1282147883Sscottl mpt_vol->flags |= MPT_RVF_ACTIVE; 1283147883Sscottl 1284147883Sscottl /* Update disk entry array data. */ 1285147883Sscottl for (i = 0; i < vol_pg->NumPhysDisks; i++) { 1286147883Sscottl struct mpt_raid_disk *mpt_disk; 1287147883Sscottl mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum; 1288147883Sscottl mpt_disk->volume = mpt_vol; 1289147883Sscottl mpt_disk->member_number = vol_pg->PhysDisk[i].PhysDiskMap; 1290164837Smjacob if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) { 1291147883Sscottl mpt_disk->member_number--; 1292164837Smjacob } 1293147883Sscottl } 1294147883Sscottl 1295147883Sscottl if ((vol_pg->VolumeStatus.Flags 1296147883Sscottl & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0) 1297147883Sscottl return; 1298147883Sscottl 1299164990Smjacob req = mpt_get_request(mpt, TRUE); 1300147883Sscottl if (req == NULL) { 1301147883Sscottl mpt_vol_prt(mpt, mpt_vol, 1302164990Smjacob "mpt_refresh_raid_vol: Get request failed!\n"); 1303147883Sscottl return; 1304147883Sscottl } 1305164990Smjacob rv = mpt_issue_raid_req(mpt, mpt_vol, NULL, req, 1306164990Smjacob MPI_RAID_ACTION_INDICATOR_STRUCT, 0, 0, 0, FALSE, TRUE); 1307147883Sscottl if (rv == ETIMEDOUT) { 1308164990Smjacob mpt_vol_prt(mpt, mpt_vol, 1309164990Smjacob "mpt_refresh_raid_vol: Progress Indicator fetch timeout\n"); 1310164990Smjacob mpt_free_request(mpt, req); 1311147883Sscottl return; 1312147883Sscottl } 1313147883Sscottl 1314147883Sscottl ar = REQ_TO_RAID_ACTION_RESULT(req); 1315147883Sscottl if (rv == 0 1316147883Sscottl && ar->action_status == MPI_RAID_ACTION_ASTATUS_SUCCESS 1317147883Sscottl && REQ_IOCSTATUS(req) == MPI_IOCSTATUS_SUCCESS) { 1318147883Sscottl memcpy(&mpt_vol->sync_progress, 1319147883Sscottl &ar->action_data.indicator_struct, 1320147883Sscottl sizeof(mpt_vol->sync_progress)); 1321164990Smjacob mpt2host_mpi_raid_vol_indicator(&mpt_vol->sync_progress); 1322147883Sscottl } else { 1323164990Smjacob mpt_vol_prt(mpt, mpt_vol, 1324164990Smjacob "mpt_refresh_raid_vol: Progress indicator fetch failed!\n"); 1325147883Sscottl } 1326147883Sscottl mpt_free_request(mpt, req); 1327147883Sscottl} 1328147883Sscottl 1329147883Sscottl/* 1330147883Sscottl * Update in-core information about RAID support. We update any entries 1331147883Sscottl * that didn't previously exists or have been marked as needing to 1332147883Sscottl * be updated by our event handler. Interesting changes are displayed 1333147883Sscottl * to the console. 1334147883Sscottl */ 1335224493Smariusstatic int 1336147883Sscottlmpt_refresh_raid_data(struct mpt_softc *mpt) 1337147883Sscottl{ 1338147883Sscottl CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol; 1339147883Sscottl CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol; 1340147883Sscottl IOC_3_PHYS_DISK *ioc_disk; 1341147883Sscottl IOC_3_PHYS_DISK *ioc_last_disk; 1342147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1343147883Sscottl size_t len; 1344147883Sscottl int rv; 1345147883Sscottl int i; 1346152444Skan u_int nonopt_volumes; 1347147883Sscottl 1348157117Smjacob if (mpt->ioc_page2 == NULL || mpt->ioc_page3 == NULL) { 1349158935Smjacob return (0); 1350157117Smjacob } 1351147883Sscottl 1352147883Sscottl /* 1353157117Smjacob * Mark all items as unreferenced by the configuration. 1354147883Sscottl * This allows us to find, report, and discard stale 1355147883Sscottl * entries. 1356147883Sscottl */ 1357157117Smjacob for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 1358147883Sscottl mpt->raid_disks[i].flags &= ~MPT_RDF_REFERENCED; 1359157117Smjacob } 1360157117Smjacob for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 1361147883Sscottl mpt->raid_volumes[i].flags &= ~MPT_RVF_REFERENCED; 1362157117Smjacob } 1363147883Sscottl 1364147883Sscottl /* 1365147883Sscottl * Get Physical Disk information. 1366147883Sscottl */ 1367147883Sscottl len = mpt->ioc_page3->Header.PageLength * sizeof(uint32_t); 1368147883Sscottl rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1369147883Sscottl &mpt->ioc_page3->Header, len, 1370147883Sscottl /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1371147883Sscottl if (rv) { 1372158935Smjacob mpt_prt(mpt, 1373158935Smjacob "mpt_refresh_raid_data: Failed to read IOC Page 3\n"); 1374158935Smjacob return (-1); 1375147883Sscottl } 1376186878Smarius mpt2host_config_page_ioc3(mpt->ioc_page3); 1377147883Sscottl 1378147883Sscottl ioc_disk = mpt->ioc_page3->PhysDisk; 1379147883Sscottl ioc_last_disk = ioc_disk + mpt->ioc_page3->NumPhysDisks; 1380147883Sscottl for (; ioc_disk != ioc_last_disk; ioc_disk++) { 1381147883Sscottl struct mpt_raid_disk *mpt_disk; 1382147883Sscottl 1383147883Sscottl mpt_disk = mpt->raid_disks + ioc_disk->PhysDiskNum; 1384147883Sscottl mpt_disk->flags |= MPT_RDF_REFERENCED; 1385147883Sscottl if ((mpt_disk->flags & (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) 1386147883Sscottl != (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) { 1387147883Sscottl 1388147883Sscottl mpt_refresh_raid_disk(mpt, mpt_disk, ioc_disk); 1389147883Sscottl 1390147883Sscottl } 1391147883Sscottl mpt_disk->flags |= MPT_RDF_ACTIVE; 1392147883Sscottl mpt->raid_rescan++; 1393147883Sscottl } 1394147883Sscottl 1395147883Sscottl /* 1396147883Sscottl * Refresh volume data. 1397147883Sscottl */ 1398147883Sscottl len = mpt->ioc_page2->Header.PageLength * sizeof(uint32_t); 1399147883Sscottl rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1400147883Sscottl &mpt->ioc_page2->Header, len, 1401147883Sscottl /*sleep_ok*/TRUE, /*timeout_ms*/5000); 1402147883Sscottl if (rv) { 1403147883Sscottl mpt_prt(mpt, "mpt_refresh_raid_data: " 1404147883Sscottl "Failed to read IOC Page 2\n"); 1405158935Smjacob return (-1); 1406147883Sscottl } 1407186878Smarius mpt2host_config_page_ioc2(mpt->ioc_page2); 1408147883Sscottl 1409147883Sscottl ioc_vol = mpt->ioc_page2->RaidVolume; 1410147883Sscottl ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes; 1411147883Sscottl for (;ioc_vol != ioc_last_vol; ioc_vol++) { 1412147883Sscottl struct mpt_raid_volume *mpt_vol; 1413147883Sscottl 1414147883Sscottl mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber; 1415147883Sscottl mpt_vol->flags |= MPT_RVF_REFERENCED; 1416147883Sscottl vol_pg = mpt_vol->config_page; 1417147883Sscottl if (vol_pg == NULL) 1418147883Sscottl continue; 1419147883Sscottl if (((mpt_vol->flags & (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE)) 1420147883Sscottl != (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE)) 1421147883Sscottl || (vol_pg->VolumeStatus.Flags 1422147883Sscottl & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) != 0) { 1423147883Sscottl 1424147883Sscottl mpt_refresh_raid_vol(mpt, mpt_vol, ioc_vol); 1425147883Sscottl } 1426147883Sscottl mpt_vol->flags |= MPT_RVF_ACTIVE; 1427147883Sscottl } 1428147883Sscottl 1429152444Skan nonopt_volumes = 0; 1430147883Sscottl for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 1431147883Sscottl struct mpt_raid_volume *mpt_vol; 1432147883Sscottl uint64_t total; 1433147883Sscottl uint64_t left; 1434147883Sscottl int m; 1435147883Sscottl u_int prio; 1436147883Sscottl 1437147883Sscottl mpt_vol = &mpt->raid_volumes[i]; 1438147883Sscottl 1439164990Smjacob if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) { 1440147883Sscottl continue; 1441164990Smjacob } 1442147883Sscottl 1443147883Sscottl vol_pg = mpt_vol->config_page; 1444147883Sscottl if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED)) 1445147883Sscottl == MPT_RVF_ANNOUNCED) { 1446147883Sscottl mpt_vol_prt(mpt, mpt_vol, "No longer configured\n"); 1447147883Sscottl mpt_vol->flags = 0; 1448147883Sscottl continue; 1449147883Sscottl } 1450147883Sscottl 1451147883Sscottl if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) { 1452147883Sscottl mpt_announce_vol(mpt, mpt_vol); 1453147883Sscottl mpt_vol->flags |= MPT_RVF_ANNOUNCED; 1454147883Sscottl } 1455147883Sscottl 1456152444Skan if (vol_pg->VolumeStatus.State != 1457152444Skan MPI_RAIDVOL0_STATUS_STATE_OPTIMAL) 1458152444Skan nonopt_volumes++; 1459152444Skan 1460147883Sscottl if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) 1461147883Sscottl continue; 1462147883Sscottl 1463147883Sscottl mpt_vol->flags |= MPT_RVF_UP2DATE; 1464147883Sscottl mpt_vol_prt(mpt, mpt_vol, "%s - %s\n", 1465164990Smjacob mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol)); 1466147883Sscottl mpt_verify_mwce(mpt, mpt_vol); 1467147883Sscottl 1468164990Smjacob if (vol_pg->VolumeStatus.Flags == 0) { 1469147883Sscottl continue; 1470164990Smjacob } 1471147883Sscottl 1472147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Status ("); 1473147883Sscottl for (m = 1; m <= 0x80; m <<= 1) { 1474147883Sscottl switch (vol_pg->VolumeStatus.Flags & m) { 1475147883Sscottl case MPI_RAIDVOL0_STATUS_FLAG_ENABLED: 1476147883Sscottl mpt_prtc(mpt, " Enabled"); 1477147883Sscottl break; 1478147883Sscottl case MPI_RAIDVOL0_STATUS_FLAG_QUIESCED: 1479147883Sscottl mpt_prtc(mpt, " Quiesced"); 1480147883Sscottl break; 1481147883Sscottl case MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS: 1482147883Sscottl mpt_prtc(mpt, " Re-Syncing"); 1483147883Sscottl break; 1484147883Sscottl case MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE: 1485147883Sscottl mpt_prtc(mpt, " Inactive"); 1486147883Sscottl break; 1487147883Sscottl default: 1488147883Sscottl break; 1489147883Sscottl } 1490147883Sscottl } 1491147883Sscottl mpt_prtc(mpt, " )\n"); 1492147883Sscottl 1493147883Sscottl if ((vol_pg->VolumeStatus.Flags 1494147883Sscottl & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0) 1495147883Sscottl continue; 1496147883Sscottl 1497147883Sscottl mpt_verify_resync_rate(mpt, mpt_vol); 1498147883Sscottl 1499164990Smjacob left = MPT_U64_2_SCALAR(mpt_vol->sync_progress.BlocksRemaining); 1500164990Smjacob total = MPT_U64_2_SCALAR(mpt_vol->sync_progress.TotalBlocks); 1501147883Sscottl if (vol_pg->ResyncRate != 0) { 1502147883Sscottl 1503147883Sscottl prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF; 1504147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Rate %d.%d%%\n", 1505147883Sscottl prio / 1000, prio % 1000); 1506147883Sscottl } else { 1507147883Sscottl prio = vol_pg->VolumeSettings.Settings 1508147883Sscottl & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC; 1509147883Sscottl mpt_vol_prt(mpt, mpt_vol, "%s Priority Re-Sync\n", 1510147883Sscottl prio ? "High" : "Low"); 1511147883Sscottl } 1512147883Sscottl mpt_vol_prt(mpt, mpt_vol, "%ju of %ju " 1513147883Sscottl "blocks remaining\n", (uintmax_t)left, 1514147883Sscottl (uintmax_t)total); 1515147883Sscottl 1516147883Sscottl /* Periodically report on sync progress. */ 1517147883Sscottl mpt_schedule_raid_refresh(mpt); 1518147883Sscottl } 1519147883Sscottl 1520147883Sscottl for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) { 1521147883Sscottl struct mpt_raid_disk *mpt_disk; 1522147883Sscottl CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg; 1523147883Sscottl int m; 1524147883Sscottl 1525147883Sscottl mpt_disk = &mpt->raid_disks[i]; 1526147883Sscottl disk_pg = &mpt_disk->config_page; 1527147883Sscottl 1528147883Sscottl if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) 1529147883Sscottl continue; 1530147883Sscottl 1531147883Sscottl if ((mpt_disk->flags & (MPT_RDF_REFERENCED|MPT_RDF_ANNOUNCED)) 1532147883Sscottl == MPT_RDF_ANNOUNCED) { 1533147883Sscottl mpt_disk_prt(mpt, mpt_disk, "No longer configured\n"); 1534147883Sscottl mpt_disk->flags = 0; 1535147883Sscottl mpt->raid_rescan++; 1536147883Sscottl continue; 1537147883Sscottl } 1538147883Sscottl 1539147883Sscottl if ((mpt_disk->flags & MPT_RDF_ANNOUNCED) == 0) { 1540147883Sscottl 1541147883Sscottl mpt_announce_disk(mpt, mpt_disk); 1542147883Sscottl mpt_disk->flags |= MPT_RVF_ANNOUNCED; 1543147883Sscottl } 1544147883Sscottl 1545147883Sscottl if ((mpt_disk->flags & MPT_RDF_UP2DATE) != 0) 1546147883Sscottl continue; 1547147883Sscottl 1548147883Sscottl mpt_disk->flags |= MPT_RDF_UP2DATE; 1549147883Sscottl mpt_disk_prt(mpt, mpt_disk, "%s\n", mpt_disk_state(mpt_disk)); 1550147883Sscottl if (disk_pg->PhysDiskStatus.Flags == 0) 1551147883Sscottl continue; 1552147883Sscottl 1553147883Sscottl mpt_disk_prt(mpt, mpt_disk, "Status ("); 1554147883Sscottl for (m = 1; m <= 0x80; m <<= 1) { 1555147883Sscottl switch (disk_pg->PhysDiskStatus.Flags & m) { 1556147883Sscottl case MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC: 1557147883Sscottl mpt_prtc(mpt, " Out-Of-Sync"); 1558147883Sscottl break; 1559147883Sscottl case MPI_PHYSDISK0_STATUS_FLAG_QUIESCED: 1560147883Sscottl mpt_prtc(mpt, " Quiesced"); 1561147883Sscottl break; 1562147883Sscottl default: 1563147883Sscottl break; 1564147883Sscottl } 1565147883Sscottl } 1566147883Sscottl mpt_prtc(mpt, " )\n"); 1567147883Sscottl } 1568152444Skan 1569152444Skan mpt->raid_nonopt_volumes = nonopt_volumes; 1570158935Smjacob return (0); 1571147883Sscottl} 1572147883Sscottl 1573147883Sscottlstatic void 1574147883Sscottlmpt_raid_timer(void *arg) 1575147883Sscottl{ 1576147883Sscottl struct mpt_softc *mpt; 1577147883Sscottl 1578147883Sscottl mpt = (struct mpt_softc *)arg; 1579198262Skan MPT_LOCK_ASSERT(mpt); 1580147883Sscottl mpt_raid_wakeup(mpt); 1581147883Sscottl} 1582147883Sscottl 1583224493Smariusstatic void 1584147883Sscottlmpt_schedule_raid_refresh(struct mpt_softc *mpt) 1585147883Sscottl{ 1586224493Smarius 1587147883Sscottl callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL, 1588147883Sscottl mpt_raid_timer, mpt); 1589147883Sscottl} 1590147883Sscottl 1591158982Smjacobvoid 1592158982Smjacobmpt_raid_free_mem(struct mpt_softc *mpt) 1593158982Smjacob{ 1594158982Smjacob 1595158982Smjacob if (mpt->raid_volumes) { 1596158982Smjacob struct mpt_raid_volume *mpt_raid; 1597158982Smjacob int i; 1598158982Smjacob for (i = 0; i < mpt->raid_max_volumes; i++) { 1599158982Smjacob mpt_raid = &mpt->raid_volumes[i]; 1600158982Smjacob if (mpt_raid->config_page) { 1601158982Smjacob free(mpt_raid->config_page, M_DEVBUF); 1602158982Smjacob mpt_raid->config_page = NULL; 1603158982Smjacob } 1604158982Smjacob } 1605158982Smjacob free(mpt->raid_volumes, M_DEVBUF); 1606158982Smjacob mpt->raid_volumes = NULL; 1607158982Smjacob } 1608158982Smjacob if (mpt->raid_disks) { 1609158982Smjacob free(mpt->raid_disks, M_DEVBUF); 1610158982Smjacob mpt->raid_disks = NULL; 1611158982Smjacob } 1612158982Smjacob if (mpt->ioc_page2) { 1613158982Smjacob free(mpt->ioc_page2, M_DEVBUF); 1614158982Smjacob mpt->ioc_page2 = NULL; 1615158982Smjacob } 1616158982Smjacob if (mpt->ioc_page3) { 1617158982Smjacob free(mpt->ioc_page3, M_DEVBUF); 1618158982Smjacob mpt->ioc_page3 = NULL; 1619158982Smjacob } 1620158982Smjacob mpt->raid_max_volumes = 0; 1621158982Smjacob mpt->raid_max_disks = 0; 1622158982Smjacob} 1623158982Smjacob 1624147883Sscottlstatic int 1625147883Sscottlmpt_raid_set_vol_resync_rate(struct mpt_softc *mpt, u_int rate) 1626147883Sscottl{ 1627147883Sscottl struct mpt_raid_volume *mpt_vol; 1628147883Sscottl 1629147883Sscottl if ((rate > MPT_RAID_RESYNC_RATE_MAX 1630147883Sscottl || rate < MPT_RAID_RESYNC_RATE_MIN) 1631147883Sscottl && rate != MPT_RAID_RESYNC_RATE_NC) 1632147883Sscottl return (EINVAL); 1633147883Sscottl 1634147883Sscottl MPT_LOCK(mpt); 1635147883Sscottl mpt->raid_resync_rate = rate; 1636147883Sscottl RAID_VOL_FOREACH(mpt, mpt_vol) { 1637157117Smjacob if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) { 1638147883Sscottl continue; 1639157117Smjacob } 1640147883Sscottl mpt_verify_resync_rate(mpt, mpt_vol); 1641147883Sscottl } 1642147883Sscottl MPT_UNLOCK(mpt); 1643147883Sscottl return (0); 1644147883Sscottl} 1645147883Sscottl 1646147883Sscottlstatic int 1647147883Sscottlmpt_raid_set_vol_queue_depth(struct mpt_softc *mpt, u_int vol_queue_depth) 1648147883Sscottl{ 1649147883Sscottl struct mpt_raid_volume *mpt_vol; 1650147883Sscottl 1651157117Smjacob if (vol_queue_depth > 255 || vol_queue_depth < 1) 1652147883Sscottl return (EINVAL); 1653147883Sscottl 1654147883Sscottl MPT_LOCK(mpt); 1655147883Sscottl mpt->raid_queue_depth = vol_queue_depth; 1656147883Sscottl RAID_VOL_FOREACH(mpt, mpt_vol) { 1657147883Sscottl struct cam_path *path; 1658147883Sscottl int error; 1659147883Sscottl 1660147883Sscottl if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1661147883Sscottl continue; 1662147883Sscottl 1663147883Sscottl mpt->raid_rescan = 0; 1664147883Sscottl 1665249468Smav error = xpt_create_path(&path, NULL, 1666147883Sscottl cam_sim_path(mpt->sim), 1667147883Sscottl mpt_vol->config_page->VolumeID, 1668147883Sscottl /*lun*/0); 1669147883Sscottl if (error != CAM_REQ_CMP) { 1670147883Sscottl mpt_vol_prt(mpt, mpt_vol, "Unable to allocate path!\n"); 1671147883Sscottl continue; 1672147883Sscottl } 1673147883Sscottl mpt_adjust_queue_depth(mpt, mpt_vol, path); 1674147883Sscottl xpt_free_path(path); 1675147883Sscottl } 1676147883Sscottl MPT_UNLOCK(mpt); 1677147883Sscottl return (0); 1678147883Sscottl} 1679147883Sscottl 1680147883Sscottlstatic int 1681147883Sscottlmpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce) 1682147883Sscottl{ 1683147883Sscottl struct mpt_raid_volume *mpt_vol; 1684147883Sscottl int force_full_resync; 1685147883Sscottl 1686147883Sscottl MPT_LOCK(mpt); 1687147883Sscottl if (mwce == mpt->raid_mwce_setting) { 1688147883Sscottl MPT_UNLOCK(mpt); 1689147883Sscottl return (0); 1690147883Sscottl } 1691147883Sscottl 1692147883Sscottl /* 1693147883Sscottl * Catch MWCE being left on due to a failed shutdown. Since 1694147883Sscottl * sysctls cannot be set by the loader, we treat the first 1695147883Sscottl * setting of this varible specially and force a full volume 1696147883Sscottl * resync if MWCE is enabled and a resync is in progress. 1697147883Sscottl */ 1698147883Sscottl force_full_resync = 0; 1699147883Sscottl if (mpt->raid_mwce_set == 0 1700147883Sscottl && mpt->raid_mwce_setting == MPT_RAID_MWCE_NC 1701147883Sscottl && mwce == MPT_RAID_MWCE_REBUILD_ONLY) 1702147883Sscottl force_full_resync = 1; 1703147883Sscottl 1704147883Sscottl mpt->raid_mwce_setting = mwce; 1705147883Sscottl RAID_VOL_FOREACH(mpt, mpt_vol) { 1706147883Sscottl CONFIG_PAGE_RAID_VOL_0 *vol_pg; 1707147883Sscottl int resyncing; 1708147883Sscottl int mwce; 1709147883Sscottl 1710147883Sscottl if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) 1711147883Sscottl continue; 1712147883Sscottl 1713147883Sscottl vol_pg = mpt_vol->config_page; 1714147883Sscottl resyncing = vol_pg->VolumeStatus.Flags 1715147883Sscottl & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 1716147883Sscottl mwce = vol_pg->VolumeSettings.Settings 1717147883Sscottl & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE; 1718147883Sscottl if (force_full_resync && resyncing && mwce) { 1719147883Sscottl 1720147883Sscottl /* 1721147883Sscottl * XXX disable/enable volume should force a resync, 1722147883Sscottl * but we'll need to queice, drain, and restart 1723147883Sscottl * I/O to do that. 1724147883Sscottl */ 1725147883Sscottl mpt_vol_prt(mpt, mpt_vol, "WARNING - Unsafe shutdown " 1726147883Sscottl "detected. Suggest full resync.\n"); 1727147883Sscottl } 1728147883Sscottl mpt_verify_mwce(mpt, mpt_vol); 1729147883Sscottl } 1730147883Sscottl mpt->raid_mwce_set = 1; 1731147883Sscottl MPT_UNLOCK(mpt); 1732147883Sscottl return (0); 1733147883Sscottl} 1734224493Smarius 1735224493Smariusstatic const char *mpt_vol_mwce_strs[] = 1736147883Sscottl{ 1737147883Sscottl "On", 1738147883Sscottl "Off", 1739147883Sscottl "On-During-Rebuild", 1740147883Sscottl "NC" 1741147883Sscottl}; 1742147883Sscottl 1743147883Sscottlstatic int 1744147883Sscottlmpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS) 1745147883Sscottl{ 1746147883Sscottl char inbuf[20]; 1747147883Sscottl struct mpt_softc *mpt; 1748147883Sscottl const char *str; 1749147883Sscottl int error; 1750147883Sscottl u_int size; 1751147883Sscottl u_int i; 1752147883Sscottl 1753147883Sscottl GIANT_REQUIRED; 1754158935Smjacob 1755147883Sscottl mpt = (struct mpt_softc *)arg1; 1756147883Sscottl str = mpt_vol_mwce_strs[mpt->raid_mwce_setting]; 1757147883Sscottl error = SYSCTL_OUT(req, str, strlen(str) + 1); 1758158935Smjacob if (error || !req->newptr) { 1759147883Sscottl return (error); 1760158935Smjacob } 1761147883Sscottl 1762147883Sscottl size = req->newlen - req->newidx; 1763158935Smjacob if (size >= sizeof(inbuf)) { 1764147883Sscottl return (EINVAL); 1765158935Smjacob } 1766147883Sscottl 1767147883Sscottl error = SYSCTL_IN(req, inbuf, size); 1768158935Smjacob if (error) { 1769147883Sscottl return (error); 1770158935Smjacob } 1771147883Sscottl inbuf[size] = '\0'; 1772147883Sscottl for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) { 1773158935Smjacob if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) { 1774147883Sscottl return (mpt_raid_set_vol_mwce(mpt, i)); 1775158935Smjacob } 1776147883Sscottl } 1777147883Sscottl return (EINVAL); 1778147883Sscottl} 1779147883Sscottl 1780147883Sscottlstatic int 1781147883Sscottlmpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS) 1782147883Sscottl{ 1783147883Sscottl struct mpt_softc *mpt; 1784147883Sscottl u_int raid_resync_rate; 1785147883Sscottl int error; 1786147883Sscottl 1787147883Sscottl GIANT_REQUIRED; 1788158935Smjacob 1789147883Sscottl mpt = (struct mpt_softc *)arg1; 1790147883Sscottl raid_resync_rate = mpt->raid_resync_rate; 1791147883Sscottl 1792147883Sscottl error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req); 1793158935Smjacob if (error || !req->newptr) { 1794147883Sscottl return error; 1795158935Smjacob } 1796147883Sscottl 1797147883Sscottl return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate)); 1798147883Sscottl} 1799147883Sscottl 1800147883Sscottlstatic int 1801147883Sscottlmpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS) 1802147883Sscottl{ 1803147883Sscottl struct mpt_softc *mpt; 1804147883Sscottl u_int raid_queue_depth; 1805147883Sscottl int error; 1806147883Sscottl 1807147883Sscottl GIANT_REQUIRED; 1808158935Smjacob 1809147883Sscottl mpt = (struct mpt_softc *)arg1; 1810147883Sscottl raid_queue_depth = mpt->raid_queue_depth; 1811147883Sscottl 1812147883Sscottl error = sysctl_handle_int(oidp, &raid_queue_depth, 0, req); 1813158935Smjacob if (error || !req->newptr) { 1814147883Sscottl return error; 1815158935Smjacob } 1816147883Sscottl 1817147883Sscottl return (mpt_raid_set_vol_queue_depth(mpt, raid_queue_depth)); 1818147883Sscottl} 1819147883Sscottl 1820147883Sscottlstatic void 1821147883Sscottlmpt_raid_sysctl_attach(struct mpt_softc *mpt) 1822147883Sscottl{ 1823147883Sscottl struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev); 1824147883Sscottl struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev); 1825147883Sscottl 1826147883Sscottl SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1827147883Sscottl "vol_member_wce", CTLTYPE_STRING | CTLFLAG_RW, mpt, 0, 1828147883Sscottl mpt_raid_sysctl_vol_member_wce, "A", 1829147883Sscottl "volume member WCE(On,Off,On-During-Rebuild,NC)"); 1830147883Sscottl 1831147883Sscottl SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1832147883Sscottl "vol_queue_depth", CTLTYPE_INT | CTLFLAG_RW, mpt, 0, 1833147883Sscottl mpt_raid_sysctl_vol_queue_depth, "I", 1834147883Sscottl "default volume queue depth"); 1835147883Sscottl 1836147883Sscottl SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1837147883Sscottl "vol_resync_rate", CTLTYPE_INT | CTLFLAG_RW, mpt, 0, 1838147883Sscottl mpt_raid_sysctl_vol_resync_rate, "I", 1839147883Sscottl "volume resync priority (0 == NC, 1 - 255)"); 1840217323Smdf SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1841152444Skan "nonoptimal_volumes", CTLFLAG_RD, 1842152444Skan &mpt->raid_nonopt_volumes, 0, 1843152444Skan "number of nonoptimal volumes"); 1844169293Smjacob} 1845