1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2000 to 2010, LSI Corporation. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms of all code within 32 * this file that is exclusively owned by LSI, with or without 33 * modification, is permitted provided that, in addition to the CDDL 1.0 34 * License requirements, the following conditions are met: 35 * 36 * Neither the name of the author nor the names of its contributors may be 37 * used to endorse or promote products derived from this software without 38 * specific prior written permission. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 43 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 44 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 46 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 47 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 48 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 49 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 50 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 51 * DAMAGE. 52 */ 53 54 /* 55 * mptsas_raid - This file contains all the RAID related functions for the 56 * MPT interface. 57 */ 58 59 #if defined(lint) || defined(DEBUG) 60 #define MPTSAS_DEBUG 61 #endif 62 63 #define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX 2 64 65 /* 66 * standard header files 67 */ 68 #include <sys/note.h> 69 #include <sys/scsi/scsi.h> 70 #include <sys/byteorder.h> 71 #include <sys/raidioctl.h> 72 73 #pragma pack(1) 74 75 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> 76 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> 77 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h> 78 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> 79 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h> 80 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h> 81 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h> 82 83 #pragma pack() 84 85 /* 86 * private header files. 87 */ 88 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h> 89 90 static int mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol); 91 92 extern int mptsas_check_dma_handle(ddi_dma_handle_t handle); 93 extern int mptsas_check_acc_handle(ddi_acc_handle_t handle); 94 extern mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, 95 uint64_t, uint32_t, mptsas_phymask_t, uint8_t); 96 97 static int 98 mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp, 99 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 100 va_list ap) 101 { 102 #ifndef __lock_lint 103 _NOTE(ARGUNUSED(ap)) 104 #endif 105 pMpi2RaidConfigurationPage0_t raidconfig_page0; 106 pMpi2RaidConfig0ConfigElement_t element; 107 uint32_t *confignum; 108 int rval = DDI_SUCCESS, i; 109 uint8_t numelements, vol, disk; 110 uint16_t elementtype, voldevhandle; 111 uint16_t etype_vol, etype_pd, etype_hs; 112 uint16_t etype_oce; 113 m_raidconfig_t *raidconfig; 114 uint64_t raidwwn; 115 uint32_t native; 116 mptsas_target_t *ptgt; 117 uint32_t configindex; 118 119 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 120 return (DDI_FAILURE); 121 } 122 123 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 124 mptsas_log(mpt, CE_WARN, "mptsas_get_raid_conf_page0 " 125 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 126 iocstatus, iocloginfo); 127 rval = DDI_FAILURE; 128 return (rval); 129 } 130 confignum = va_arg(ap, uint32_t *); 131 configindex = va_arg(ap, uint32_t); 132 raidconfig_page0 = (pMpi2RaidConfigurationPage0_t)page_memp; 133 /* 134 * Get all RAID configurations. 135 */ 136 etype_vol = MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT; 137 etype_pd = MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT; 138 etype_hs = MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT; 139 etype_oce = MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT; 140 /* 141 * Set up page address for next time through. 142 */ 143 *confignum = ddi_get8(accessp, 144 &raidconfig_page0->ConfigNum); 145 146 /* 147 * Point to the right config in the structure. 148 * Increment the number of valid RAID configs. 149 */ 150 raidconfig = &mpt->m_raidconfig[configindex]; 151 mpt->m_num_raid_configs++; 152 153 /* 154 * Set the native flag if this is not a foreign 155 * configuration. 156 */ 157 native = ddi_get32(accessp, &raidconfig_page0->Flags); 158 if (native & MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG) { 159 native = FALSE; 160 } else { 161 native = TRUE; 162 } 163 raidconfig->m_native = (uint8_t)native; 164 165 /* 166 * Get volume information for the volumes in the 167 * config. 168 */ 169 numelements = ddi_get8(accessp, &raidconfig_page0->NumElements); 170 vol = 0; 171 disk = 0; 172 element = (pMpi2RaidConfig0ConfigElement_t) 173 &raidconfig_page0->ConfigElement; 174 175 for (i = 0; ((i < numelements) && native); i++, element++) { 176 /* 177 * Get the element type. Could be Volume, 178 * PhysDisk, Hot Spare, or Online Capacity 179 * Expansion PhysDisk. 180 */ 181 elementtype = ddi_get16(accessp, &element->ElementFlags); 182 elementtype &= MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; 183 184 /* 185 * For volumes, get the RAID settings and the 186 * WWID. 187 */ 188 if (elementtype == etype_vol) { 189 voldevhandle = ddi_get16(accessp, 190 &element->VolDevHandle); 191 raidconfig->m_raidvol[vol].m_israid = 1; 192 raidconfig->m_raidvol[vol]. 193 m_raidhandle = voldevhandle; 194 /* 195 * Get the settings for the raid 196 * volume. This includes the 197 * DevHandles for the disks making up 198 * the raid volume. 199 */ 200 if (mptsas_get_raid_settings(mpt, 201 &raidconfig->m_raidvol[vol])) 202 continue; 203 204 /* 205 * Get the WWID of the RAID volume for 206 * SAS HBA 207 */ 208 if (mptsas_get_raid_wwid(mpt, 209 &raidconfig->m_raidvol[vol])) 210 continue; 211 212 raidwwn = raidconfig->m_raidvol[vol]. 213 m_raidwwid; 214 215 /* 216 * RAID uses phymask of 0. 217 */ 218 ptgt = mptsas_tgt_alloc(mpt, 219 voldevhandle, raidwwn, 0, 0, 0); 220 221 raidconfig->m_raidvol[vol].m_raidtgt = 222 ptgt; 223 224 /* 225 * Increment volume index within this 226 * raid config. 227 */ 228 vol++; 229 } else if ((elementtype == etype_pd) || 230 (elementtype == etype_hs) || 231 (elementtype == etype_oce)) { 232 /* 233 * For all other element types, put 234 * their DevHandles in the phys disk 235 * list of the config. These are all 236 * some variation of a Phys Disk and 237 * this list is used to keep these 238 * disks from going online. 239 */ 240 raidconfig->m_physdisk_devhdl[disk] = ddi_get16(accessp, 241 &element->PhysDiskDevHandle); 242 243 /* 244 * Increment disk index within this 245 * raid config. 246 */ 247 disk++; 248 } 249 } 250 251 return (rval); 252 } 253 254 int 255 mptsas_get_raid_info(mptsas_t *mpt) 256 { 257 int rval = DDI_SUCCESS; 258 uint32_t confignum, pageaddress; 259 uint8_t configindex; 260 261 ASSERT(mutex_owned(&mpt->m_mutex)); 262 263 /* 264 * Clear all RAID info before starting. 265 */ 266 bzero(mpt->m_raidconfig, sizeof (mpt->m_raidconfig)); 267 mpt->m_num_raid_configs = 0; 268 269 configindex = 0; 270 confignum = 0xff; 271 pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM | confignum; 272 while (rval == DDI_SUCCESS) { 273 /* 274 * Get the header and config page. reply contains the reply 275 * frame, which holds status info for the request. 276 */ 277 rval = mptsas_access_config_page(mpt, 278 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 279 MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, pageaddress, 280 mptsas_raidconf_page_0_cb, &confignum, configindex); 281 configindex++; 282 pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM | 283 confignum; 284 } 285 286 return (rval); 287 } 288 289 static int 290 mptsas_raidvol_page_0_cb(mptsas_t *mpt, caddr_t page_memp, 291 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 292 va_list ap) 293 { 294 #ifndef __lock_lint 295 _NOTE(ARGUNUSED(ap)) 296 #endif 297 pMpi2RaidVolPage0_t raidpage; 298 int rval = DDI_SUCCESS, i; 299 mptsas_raidvol_t *raidvol; 300 uint8_t numdisks, volstate, voltype, physdisknum; 301 uint32_t volsetting; 302 uint32_t statusflags, resync_flag; 303 304 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) 305 return (DDI_FAILURE); 306 307 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 308 mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page0_cb " 309 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 310 iocstatus, iocloginfo); 311 rval = DDI_FAILURE; 312 return (rval); 313 } 314 315 raidvol = va_arg(ap, mptsas_raidvol_t *); 316 317 raidpage = (pMpi2RaidVolPage0_t)page_memp; 318 volstate = ddi_get8(accessp, &raidpage->VolumeState); 319 volsetting = ddi_get32(accessp, 320 (uint32_t *)(void *)&raidpage->VolumeSettings); 321 statusflags = ddi_get32(accessp, &raidpage->VolumeStatusFlags); 322 voltype = ddi_get8(accessp, &raidpage->VolumeType); 323 324 raidvol->m_state = volstate; 325 raidvol->m_statusflags = statusflags; 326 /* 327 * Volume size is not used right now. Set to 0. 328 */ 329 raidvol->m_raidsize = 0; 330 raidvol->m_settings = volsetting; 331 raidvol->m_raidlevel = voltype; 332 333 if (statusflags & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED) { 334 mptsas_log(mpt, CE_NOTE, "?Volume %d is quiesced\n", 335 raidvol->m_raidhandle); 336 } 337 338 if (statusflags & 339 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { 340 mptsas_log(mpt, CE_NOTE, "?Volume %d is resyncing\n", 341 raidvol->m_raidhandle); 342 } 343 344 resync_flag = MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 345 switch (volstate) { 346 case MPI2_RAID_VOL_STATE_OPTIMAL: 347 mptsas_log(mpt, CE_NOTE, "?Volume %d is " 348 "optimal\n", raidvol->m_raidhandle); 349 break; 350 case MPI2_RAID_VOL_STATE_DEGRADED: 351 if ((statusflags & resync_flag) == 0) { 352 mptsas_log(mpt, CE_WARN, "Volume %d " 353 "is degraded\n", 354 raidvol->m_raidhandle); 355 } 356 break; 357 case MPI2_RAID_VOL_STATE_FAILED: 358 mptsas_log(mpt, CE_WARN, "Volume %d is " 359 "failed\n", raidvol->m_raidhandle); 360 break; 361 case MPI2_RAID_VOL_STATE_MISSING: 362 mptsas_log(mpt, CE_WARN, "Volume %d is " 363 "missing\n", raidvol->m_raidhandle); 364 break; 365 default: 366 break; 367 } 368 numdisks = raidpage->NumPhysDisks; 369 raidvol->m_ndisks = numdisks; 370 for (i = 0; i < numdisks; i++) { 371 physdisknum = raidpage->PhysDisk[i].PhysDiskNum; 372 raidvol->m_disknum[i] = physdisknum; 373 if (mptsas_get_physdisk_settings(mpt, raidvol, 374 physdisknum)) 375 break; 376 } 377 return (rval); 378 } 379 380 int 381 mptsas_get_raid_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol) 382 { 383 int rval = DDI_SUCCESS; 384 uint32_t page_address; 385 386 ASSERT(mutex_owned(&mpt->m_mutex)); 387 388 /* 389 * Get the header and config page. reply contains the reply frame, 390 * which holds status info for the request. 391 */ 392 page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK & 393 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle; 394 rval = mptsas_access_config_page(mpt, 395 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 396 MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, page_address, 397 mptsas_raidvol_page_0_cb, raidvol); 398 399 return (rval); 400 } 401 402 static int 403 mptsas_raidvol_page_1_cb(mptsas_t *mpt, caddr_t page_memp, 404 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 405 va_list ap) 406 { 407 #ifndef __lock_lint 408 _NOTE(ARGUNUSED(ap)) 409 #endif 410 pMpi2RaidVolPage1_t raidpage; 411 int rval = DDI_SUCCESS, i; 412 uint8_t *sas_addr = NULL; 413 uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE]; 414 uint64_t *sas_wwn; 415 416 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 417 mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page_1_cb " 418 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 419 iocstatus, iocloginfo); 420 rval = DDI_FAILURE; 421 return (rval); 422 } 423 sas_wwn = va_arg(ap, uint64_t *); 424 425 raidpage = (pMpi2RaidVolPage1_t)page_memp; 426 sas_addr = (uint8_t *)(&raidpage->WWID); 427 for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) { 428 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i); 429 } 430 bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE); 431 *sas_wwn = LE_64(*sas_wwn); 432 return (rval); 433 } 434 435 static int 436 mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol) 437 { 438 int rval = DDI_SUCCESS; 439 uint32_t page_address; 440 uint64_t sas_wwn; 441 442 ASSERT(mutex_owned(&mpt->m_mutex)); 443 444 /* 445 * Get the header and config page. reply contains the reply frame, 446 * which holds status info for the request. 447 */ 448 page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK & 449 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle; 450 rval = mptsas_access_config_page(mpt, 451 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 452 MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, page_address, 453 mptsas_raidvol_page_1_cb, &sas_wwn); 454 455 /* 456 * Get the required information from the page. 457 */ 458 if (rval == DDI_SUCCESS) { 459 460 /* 461 * replace top nibble of WWID of RAID to '3' for OBP 462 */ 463 sas_wwn = MPTSAS_RAID_WWID(sas_wwn); 464 raidvol->m_raidwwid = sas_wwn; 465 } 466 467 return (rval); 468 } 469 470 static int 471 mptsas_raidphydsk_page_0_cb(mptsas_t *mpt, caddr_t page_memp, 472 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 473 va_list ap) 474 { 475 #ifndef __lock_lint 476 _NOTE(ARGUNUSED(ap)) 477 #endif 478 pMpi2RaidPhysDiskPage0_t diskpage; 479 int rval = DDI_SUCCESS; 480 uint16_t *devhdl; 481 uint8_t *state; 482 483 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) 484 return (DDI_FAILURE); 485 486 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 487 mptsas_log(mpt, CE_WARN, "mptsas_raidphydsk_page0_cb " 488 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 489 iocstatus, iocloginfo); 490 rval = DDI_FAILURE; 491 return (rval); 492 } 493 devhdl = va_arg(ap, uint16_t *); 494 state = va_arg(ap, uint8_t *); 495 diskpage = (pMpi2RaidPhysDiskPage0_t)page_memp; 496 *devhdl = ddi_get16(accessp, &diskpage->DevHandle); 497 *state = ddi_get8(accessp, &diskpage->PhysDiskState); 498 return (rval); 499 } 500 501 int 502 mptsas_get_physdisk_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol, 503 uint8_t physdisknum) 504 { 505 int rval = DDI_SUCCESS, i; 506 uint8_t state; 507 uint16_t devhdl; 508 uint32_t page_address; 509 510 ASSERT(mutex_owned(&mpt->m_mutex)); 511 512 /* 513 * Get the header and config page. reply contains the reply frame, 514 * which holds status info for the request. 515 */ 516 page_address = (MPI2_PHYSDISK_PGAD_FORM_MASK & 517 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM) | physdisknum; 518 rval = mptsas_access_config_page(mpt, 519 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 520 MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, page_address, 521 mptsas_raidphydsk_page_0_cb, &devhdl, &state); 522 523 /* 524 * Get the required information from the page. 525 */ 526 if (rval == DDI_SUCCESS) { 527 for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) { 528 /* find the correct position in the arrays */ 529 if (raidvol->m_disknum[i] == physdisknum) 530 break; 531 } 532 raidvol->m_devhdl[i] = devhdl; 533 534 switch (state) { 535 case MPI2_RAID_PD_STATE_OFFLINE: 536 raidvol->m_diskstatus[i] = 537 RAID_DISKSTATUS_FAILED; 538 break; 539 540 case MPI2_RAID_PD_STATE_HOT_SPARE: 541 case MPI2_RAID_PD_STATE_NOT_CONFIGURED: 542 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: 543 break; 544 545 case MPI2_RAID_PD_STATE_DEGRADED: 546 case MPI2_RAID_PD_STATE_OPTIMAL: 547 case MPI2_RAID_PD_STATE_REBUILDING: 548 case MPI2_RAID_PD_STATE_ONLINE: 549 default: 550 raidvol->m_diskstatus[i] = 551 RAID_DISKSTATUS_GOOD; 552 break; 553 } 554 } 555 556 return (rval); 557 } 558 559 /* 560 * RAID Action for System Shutdown. This request uses the dedicated TM slot to 561 * avoid a call to mptsas_save_cmd. Since Solaris requires that the mutex is 562 * not held during the mptsas_quiesce function, this RAID action must not use 563 * the normal code path of requests and replies. 564 */ 565 void 566 mptsas_raid_action_system_shutdown(mptsas_t *mpt) 567 { 568 pMpi2RaidActionRequest_t action; 569 uint8_t ir_active = FALSE, reply_type; 570 uint8_t function, found_reply = FALSE; 571 uint16_t SMID, action_type; 572 mptsas_slots_t *slots = mpt->m_active; 573 int config, vol; 574 mptsas_cmd_t *cmd; 575 uint32_t request_desc_low, reply_addr; 576 int cnt; 577 pMpi2ReplyDescriptorsUnion_t reply_desc_union; 578 pMPI2DefaultReply_t reply; 579 pMpi2AddressReplyDescriptor_t address_reply; 580 581 /* 582 * Before doing the system shutdown RAID Action, make sure that the IOC 583 * supports IR and make sure there is a valid volume for the request. 584 */ 585 if (mpt->m_ir_capable) { 586 for (config = 0; (config < mpt->m_num_raid_configs) && 587 (!ir_active); config++) { 588 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) { 589 if (mpt->m_raidconfig[config].m_raidvol[vol]. 590 m_israid) { 591 ir_active = TRUE; 592 break; 593 } 594 } 595 } 596 } 597 if (!ir_active) { 598 return; 599 } 600 601 /* 602 * If TM slot is already being used (highly unlikely), show message and 603 * don't issue the RAID action. 604 */ 605 if (slots->m_slot[MPTSAS_TM_SLOT(mpt)] != NULL) { 606 mptsas_log(mpt, CE_WARN, "RAID Action slot in use. Cancelling" 607 " System Shutdown RAID Action.\n"); 608 return; 609 } 610 611 /* 612 * Create the cmd and put it in the dedicated TM slot. 613 */ 614 cmd = &(mpt->m_event_task_mgmt.m_event_cmd); 615 bzero((caddr_t)cmd, sizeof (*cmd)); 616 cmd->cmd_pkt = NULL; 617 cmd->cmd_slot = MPTSAS_TM_SLOT(mpt); 618 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = cmd; 619 620 /* 621 * Form message for raid action. 622 */ 623 action = (pMpi2RaidActionRequest_t)(mpt->m_req_frame + 624 (mpt->m_req_frame_size * cmd->cmd_slot)); 625 bzero(action, mpt->m_req_frame_size); 626 action->Function = MPI2_FUNCTION_RAID_ACTION; 627 action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; 628 629 /* 630 * Send RAID Action. 631 */ 632 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0, 633 DDI_DMA_SYNC_FORDEV); 634 request_desc_low = (cmd->cmd_slot << 16) + 635 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 636 MPTSAS_START_CMD(mpt, request_desc_low, 0); 637 638 /* 639 * Even though reply does not matter because the system is shutting 640 * down, wait no more than 5 seconds here to get the reply just because 641 * we don't want to leave it hanging if it's coming. Poll because 642 * interrupts are disabled when this function is called. 643 */ 644 for (cnt = 0; cnt < 5000; cnt++) { 645 /* 646 * Check for a reply. 647 */ 648 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0, 649 DDI_DMA_SYNC_FORCPU); 650 651 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t) 652 MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index); 653 654 if (ddi_get32(mpt->m_acc_post_queue_hdl, 655 &reply_desc_union->Words.Low) == 0xFFFFFFFF || 656 ddi_get32(mpt->m_acc_post_queue_hdl, 657 &reply_desc_union->Words.High) == 0xFFFFFFFF) { 658 drv_usecwait(1000); 659 continue; 660 } 661 662 /* 663 * There is a reply. If it's not an address reply, ignore it. 664 */ 665 reply_type = ddi_get8(mpt->m_acc_post_queue_hdl, 666 &reply_desc_union->Default.ReplyFlags); 667 reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; 668 if (reply_type != MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { 669 goto clear_and_continue; 670 } 671 672 /* 673 * SMID must be the TM slot since that's what we're using for 674 * this RAID action. If not, ignore this reply. 675 */ 676 address_reply = 677 (pMpi2AddressReplyDescriptor_t)reply_desc_union; 678 SMID = ddi_get16(mpt->m_acc_post_queue_hdl, 679 &address_reply->SMID); 680 if (SMID != MPTSAS_TM_SLOT(mpt)) { 681 goto clear_and_continue; 682 } 683 684 /* 685 * If reply frame is not in the proper range ignore it. 686 */ 687 reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl, 688 &address_reply->ReplyFrameAddress); 689 if ((reply_addr < mpt->m_reply_frame_dma_addr) || 690 (reply_addr >= (mpt->m_reply_frame_dma_addr + 691 (mpt->m_reply_frame_size * mpt->m_free_queue_depth))) || 692 ((reply_addr - mpt->m_reply_frame_dma_addr) % 693 mpt->m_reply_frame_size != 0)) { 694 goto clear_and_continue; 695 } 696 697 /* 698 * If not a RAID action reply ignore it. 699 */ 700 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0, 701 DDI_DMA_SYNC_FORCPU); 702 reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + 703 (reply_addr - mpt->m_reply_frame_dma_addr)); 704 function = ddi_get8(mpt->m_acc_reply_frame_hdl, 705 &reply->Function); 706 if (function != MPI2_FUNCTION_RAID_ACTION) { 707 goto clear_and_continue; 708 } 709 710 /* 711 * Finally, make sure this is the System Shutdown RAID action. 712 * If not, ignore reply. 713 */ 714 action_type = ddi_get16(mpt->m_acc_reply_frame_hdl, 715 &reply->FunctionDependent1); 716 if (action_type != 717 MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED) { 718 goto clear_and_continue; 719 } 720 found_reply = TRUE; 721 722 clear_and_continue: 723 /* 724 * Clear the reply descriptor for re-use and increment index. 725 */ 726 ddi_put64(mpt->m_acc_post_queue_hdl, 727 &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index], 728 0xFFFFFFFFFFFFFFFF); 729 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0, 730 DDI_DMA_SYNC_FORDEV); 731 732 /* 733 * Update the global reply index and keep looking for the 734 * reply if not found yet. 735 */ 736 if (++mpt->m_post_index == mpt->m_post_queue_depth) { 737 mpt->m_post_index = 0; 738 } 739 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyPostHostIndex, 740 mpt->m_post_index); 741 if (!found_reply) { 742 continue; 743 } 744 745 break; 746 } 747 748 /* 749 * clear the used slot as the last step. 750 */ 751 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL; 752 } 753 754 int 755 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid) 756 { 757 int config, i = 0, vol = (-1); 758 759 for (config = 0; (config < mpt->m_num_raid_configs) && (vol != i); 760 config++) { 761 for (i = 0; i < MPTSAS_MAX_RAIDVOLS; i++) { 762 if (mpt->m_raidconfig[config].m_raidvol[i]. 763 m_raidhandle == volid) { 764 vol = i; 765 break; 766 } 767 } 768 } 769 770 if (vol < 0) { 771 mptsas_log(mpt, CE_WARN, "raid doesn't exist at specified " 772 "target."); 773 return (-1); 774 } 775 776 mpt->m_raidconfig[config].m_raidvol[vol].m_israid = 0; 777 mpt->m_raidconfig[config].m_raidvol[vol].m_ndisks = 0; 778 for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) { 779 mpt->m_raidconfig[config].m_raidvol[vol].m_disknum[i] = 0; 780 mpt->m_raidconfig[config].m_raidvol[vol].m_devhdl[i] = 0; 781 } 782 783 return (0); 784 } 785