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