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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2000 to 2009, 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_hash_table_t *, uint16_t, 95 uint64_t, uint32_t, uint8_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 mptsas_slots_t *slots = mpt->m_active; 114 m_raidconfig_t *raidconfig; 115 uint64_t raidwwn; 116 uint32_t native; 117 mptsas_target_t *ptgt; 118 uint32_t configindex; 119 120 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 121 return (DDI_FAILURE); 122 } 123 124 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 125 mptsas_log(mpt, CE_WARN, "mptsas_get_raid_conf_page0 " 126 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 127 iocstatus, iocloginfo); 128 rval = DDI_FAILURE; 129 return (rval); 130 } 131 confignum = va_arg(ap, uint32_t *); 132 configindex = va_arg(ap, uint32_t); 133 raidconfig_page0 = (pMpi2RaidConfigurationPage0_t)page_memp; 134 /* 135 * Get all RAID configurations. 136 */ 137 etype_vol = MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT; 138 etype_pd = MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT; 139 etype_hs = MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT; 140 etype_oce = MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT; 141 /* 142 * Set up page address for next time through. 143 */ 144 *confignum = ddi_get8(accessp, 145 &raidconfig_page0->ConfigNum); 146 147 /* 148 * Point to the right config in the structure. 149 * Increment the number of valid RAID configs. 150 */ 151 raidconfig = &slots->m_raidconfig[configindex]; 152 slots->m_num_raid_configs++; 153 154 /* 155 * Set the native flag if this is not a foreign 156 * configuration. 157 */ 158 native = ddi_get32(accessp, &raidconfig_page0->Flags); 159 if (native & MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG) { 160 native = FALSE; 161 } else { 162 native = TRUE; 163 } 164 raidconfig->m_native = (uint8_t)native; 165 166 /* 167 * Get volume information for the volumes in the 168 * config. 169 */ 170 numelements = ddi_get8(accessp, &raidconfig_page0->NumElements); 171 vol = 0; 172 disk = 0; 173 element = (pMpi2RaidConfig0ConfigElement_t) 174 &raidconfig_page0->ConfigElement; 175 176 for (i = 0; i < numelements; i++, element++) { 177 /* 178 * Get the element type. Could be Volume, 179 * PhysDisk, Hot Spare, or Online Capacity 180 * Expansion PhysDisk. 181 */ 182 elementtype = ddi_get16(accessp, &element->ElementFlags); 183 elementtype &= MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; 184 185 /* 186 * For volumes, get the RAID settings and the 187 * WWID. 188 */ 189 if (elementtype == etype_vol) { 190 voldevhandle = ddi_get16(accessp, 191 &element->VolDevHandle); 192 raidconfig->m_raidvol[vol].m_israid = 1; 193 raidconfig->m_raidvol[vol]. 194 m_raidhandle = voldevhandle; 195 /* 196 * Get the settings for the raid 197 * volume. This includes the 198 * DevHandles for the disks making up 199 * the raid volume. 200 */ 201 if (mptsas_get_raid_settings(mpt, 202 &raidconfig->m_raidvol[vol])) 203 continue; 204 205 /* 206 * Get the WWID of the RAID volume for 207 * SAS HBA 208 */ 209 if (mptsas_get_raid_wwid(mpt, 210 &raidconfig->m_raidvol[vol])) 211 continue; 212 213 raidwwn = raidconfig->m_raidvol[vol]. 214 m_raidwwid; 215 216 /* 217 * RAID uses phymask of 0. 218 */ 219 ptgt = mptsas_tgt_alloc(&slots->m_tgttbl, 220 voldevhandle, raidwwn, 0, 0, 0); 221 222 raidconfig->m_raidvol[vol].m_raidtgt = 223 ptgt; 224 225 /* 226 * Increment volume index within this 227 * raid config. 228 */ 229 vol++; 230 } else if ((elementtype == etype_pd) || 231 (elementtype == etype_hs) || 232 (elementtype == etype_oce)) { 233 /* 234 * For all other element types, put 235 * their DevHandles in the phys disk 236 * list of the config. These are all 237 * some variation of a Phys Disk and 238 * this list is used to keep these 239 * disks from going online. 240 */ 241 raidconfig->m_physdisk_devhdl[disk] = ddi_get16(accessp, 242 &element->PhysDiskDevHandle); 243 244 /* 245 * Increment disk index within this 246 * raid config. 247 */ 248 disk++; 249 } 250 } 251 252 return (rval); 253 } 254 255 int 256 mptsas_get_raid_info(mptsas_t *mpt) 257 { 258 int rval = DDI_SUCCESS; 259 uint32_t confignum, pageaddress; 260 uint8_t configindex; 261 mptsas_slots_t *slots = mpt->m_active; 262 263 ASSERT(mutex_owned(&mpt->m_mutex)); 264 265 /* 266 * Clear all RAID info before starting. 267 */ 268 bzero(slots->m_raidconfig, sizeof (slots->m_raidconfig)); 269 slots->m_num_raid_configs = 0; 270 271 configindex = 0; 272 confignum = 0xff; 273 pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM | confignum; 274 while (rval == DDI_SUCCESS) { 275 /* 276 * Get the header and config page. reply contains the reply 277 * frame, which holds status info for the request. 278 */ 279 rval = mptsas_access_config_page(mpt, 280 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 281 MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, pageaddress, 282 mptsas_raidconf_page_0_cb, &confignum, configindex); 283 configindex++; 284 pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM | 285 confignum; 286 } 287 288 return (rval); 289 } 290 291 static int 292 mptsas_raidvol_page_0_cb(mptsas_t *mpt, caddr_t page_memp, 293 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 294 va_list ap) 295 { 296 #ifndef __lock_lint 297 _NOTE(ARGUNUSED(ap)) 298 #endif 299 pMpi2RaidVolPage0_t raidpage; 300 int rval = DDI_SUCCESS, i; 301 mptsas_raidvol_t *raidvol; 302 uint8_t numdisks, volstate, voltype, physdisknum; 303 uint32_t volsetting; 304 uint32_t statusflags, resync_flag; 305 306 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) 307 return (DDI_FAILURE); 308 309 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 310 mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page0_cb " 311 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 312 iocstatus, iocloginfo); 313 rval = DDI_FAILURE; 314 return (rval); 315 } 316 317 raidvol = va_arg(ap, mptsas_raidvol_t *); 318 319 raidpage = (pMpi2RaidVolPage0_t)page_memp; 320 volstate = ddi_get8(accessp, &raidpage->VolumeState); 321 volsetting = ddi_get32(accessp, 322 (uint32_t *)(void *)&raidpage->VolumeSettings); 323 statusflags = ddi_get32(accessp, &raidpage->VolumeStatusFlags); 324 voltype = ddi_get8(accessp, &raidpage->VolumeType); 325 326 raidvol->m_state = volstate; 327 raidvol->m_statusflags = statusflags; 328 /* 329 * Volume size is not used right now. Set to 0. 330 */ 331 raidvol->m_raidsize = 0; 332 raidvol->m_settings = volsetting; 333 raidvol->m_raidlevel = voltype; 334 335 if (statusflags & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED) { 336 mptsas_log(mpt, CE_NOTE, "?Volume %d is quiesced\n", 337 raidvol->m_raidhandle); 338 } 339 340 if (statusflags & 341 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { 342 mptsas_log(mpt, CE_NOTE, "?Volume %d is resyncing\n", 343 raidvol->m_raidhandle); 344 } 345 346 resync_flag = MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS; 347 switch (volstate) { 348 case MPI2_RAID_VOL_STATE_OPTIMAL: 349 mptsas_log(mpt, CE_NOTE, "?Volume %d is " 350 "optimal\n", raidvol->m_raidhandle); 351 break; 352 case MPI2_RAID_VOL_STATE_DEGRADED: 353 if ((statusflags & resync_flag) == 0) { 354 mptsas_log(mpt, CE_WARN, "Volume %d " 355 "is degraded\n", 356 raidvol->m_raidhandle); 357 } 358 break; 359 case MPI2_RAID_VOL_STATE_FAILED: 360 mptsas_log(mpt, CE_WARN, "Volume %d is " 361 "failed\n", raidvol->m_raidhandle); 362 break; 363 case MPI2_RAID_VOL_STATE_MISSING: 364 mptsas_log(mpt, CE_WARN, "Volume %d is " 365 "missing\n", raidvol->m_raidhandle); 366 break; 367 default: 368 break; 369 } 370 numdisks = raidpage->NumPhysDisks; 371 raidvol->m_ndisks = numdisks; 372 for (i = 0; i < numdisks; i++) { 373 physdisknum = raidpage->PhysDisk[i].PhysDiskNum; 374 raidvol->m_disknum[i] = physdisknum; 375 if (mptsas_get_physdisk_settings(mpt, raidvol, 376 physdisknum)) 377 break; 378 } 379 return (rval); 380 } 381 382 int 383 mptsas_get_raid_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol) 384 { 385 int rval = DDI_SUCCESS; 386 uint32_t page_address; 387 388 ASSERT(mutex_owned(&mpt->m_mutex)); 389 390 /* 391 * Get the header and config page. reply contains the reply frame, 392 * which holds status info for the request. 393 */ 394 page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK & 395 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle; 396 rval = mptsas_access_config_page(mpt, 397 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 398 MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, page_address, 399 mptsas_raidvol_page_0_cb, raidvol); 400 401 return (rval); 402 } 403 404 static int 405 mptsas_raidvol_page_1_cb(mptsas_t *mpt, caddr_t page_memp, 406 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 407 va_list ap) 408 { 409 #ifndef __lock_lint 410 _NOTE(ARGUNUSED(ap)) 411 #endif 412 pMpi2RaidVolPage1_t raidpage; 413 int rval = DDI_SUCCESS, i; 414 uint8_t *sas_addr = NULL; 415 uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE]; 416 uint64_t *sas_wwn; 417 418 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 419 mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page_1_cb " 420 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 421 iocstatus, iocloginfo); 422 rval = DDI_FAILURE; 423 return (rval); 424 } 425 sas_wwn = va_arg(ap, uint64_t *); 426 427 raidpage = (pMpi2RaidVolPage1_t)page_memp; 428 sas_addr = (uint8_t *)(&raidpage->WWID); 429 for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) { 430 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i); 431 } 432 bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE); 433 *sas_wwn = LE_64(*sas_wwn); 434 return (rval); 435 } 436 437 static int 438 mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol) 439 { 440 int rval = DDI_SUCCESS; 441 uint32_t page_address; 442 uint64_t sas_wwn; 443 444 ASSERT(mutex_owned(&mpt->m_mutex)); 445 446 /* 447 * Get the header and config page. reply contains the reply frame, 448 * which holds status info for the request. 449 */ 450 page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK & 451 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle; 452 rval = mptsas_access_config_page(mpt, 453 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 454 MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, page_address, 455 mptsas_raidvol_page_1_cb, &sas_wwn); 456 457 /* 458 * Get the required information from the page. 459 */ 460 if (rval == DDI_SUCCESS) { 461 462 /* 463 * replace top nibble of WWID of RAID to '3' for OBP 464 */ 465 sas_wwn = MPTSAS_RAID_WWID(sas_wwn); 466 raidvol->m_raidwwid = sas_wwn; 467 } 468 469 done: 470 return (rval); 471 } 472 473 static int 474 mptsas_raidphydsk_page_0_cb(mptsas_t *mpt, caddr_t page_memp, 475 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, 476 va_list ap) 477 { 478 #ifndef __lock_lint 479 _NOTE(ARGUNUSED(ap)) 480 #endif 481 pMpi2RaidPhysDiskPage0_t diskpage; 482 int rval = DDI_SUCCESS; 483 uint16_t *devhdl; 484 uint8_t *state; 485 486 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) 487 return (DDI_FAILURE); 488 489 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { 490 mptsas_log(mpt, CE_WARN, "mptsas_raidphydsk_page0_cb " 491 "config: IOCStatus=0x%x, IOCLogInfo=0x%x", 492 iocstatus, iocloginfo); 493 rval = DDI_FAILURE; 494 return (rval); 495 } 496 devhdl = va_arg(ap, uint16_t *); 497 state = va_arg(ap, uint8_t *); 498 diskpage = (pMpi2RaidPhysDiskPage0_t)page_memp; 499 *devhdl = ddi_get16(accessp, &diskpage->DevHandle); 500 *state = ddi_get8(accessp, &diskpage->PhysDiskState); 501 return (rval); 502 } 503 504 int 505 mptsas_get_physdisk_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol, 506 uint8_t physdisknum) 507 { 508 int rval = DDI_SUCCESS, i; 509 uint8_t state; 510 uint16_t devhdl; 511 uint32_t page_address; 512 513 ASSERT(mutex_owned(&mpt->m_mutex)); 514 515 /* 516 * Get the header and config page. reply contains the reply frame, 517 * which holds status info for the request. 518 */ 519 page_address = (MPI2_PHYSDISK_PGAD_FORM_MASK & 520 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM) | physdisknum; 521 rval = mptsas_access_config_page(mpt, 522 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT, 523 MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, page_address, 524 mptsas_raidphydsk_page_0_cb, &devhdl, &state); 525 526 /* 527 * Get the required information from the page. 528 */ 529 if (rval == DDI_SUCCESS) { 530 for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) { 531 /* find the correct position in the arrays */ 532 if (raidvol->m_disknum[i] == physdisknum) 533 break; 534 } 535 raidvol->m_devhdl[i] = devhdl; 536 537 switch (state) { 538 case MPI2_RAID_PD_STATE_OFFLINE: 539 raidvol->m_diskstatus[i] = 540 RAID_DISKSTATUS_FAILED; 541 break; 542 543 case MPI2_RAID_PD_STATE_HOT_SPARE: 544 case MPI2_RAID_PD_STATE_NOT_CONFIGURED: 545 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: 546 break; 547 548 case MPI2_RAID_PD_STATE_DEGRADED: 549 case MPI2_RAID_PD_STATE_OPTIMAL: 550 case MPI2_RAID_PD_STATE_REBUILDING: 551 case MPI2_RAID_PD_STATE_ONLINE: 552 default: 553 raidvol->m_diskstatus[i] = 554 RAID_DISKSTATUS_GOOD; 555 break; 556 } 557 } 558 559 return (rval); 560 } 561 562 /* 563 * The only RAID Action needed throughout the driver is for System Shutdown. 564 * Since this is the only RAID Action and because this Action does not require 565 * waiting for a reply, make this a non-generic function. If it turns out that 566 * other RAID Actions are required later, a generic function should be used. 567 */ 568 void 569 mptsas_raid_action_system_shutdown(mptsas_t *mpt) 570 { 571 pMpi2RaidActionRequest_t action; 572 uint8_t ir_active = FALSE; 573 mptsas_slots_t *slots = mpt->m_active; 574 int config, vol, action_flags = 0; 575 mptsas_cmd_t *cmd; 576 struct scsi_pkt *pkt; 577 uint32_t request_desc_low; 578 579 ASSERT(mutex_owned(&mpt->m_mutex)); 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 < slots->m_num_raid_configs; 587 config++) { 588 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) { 589 if (slots->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 * Get a command from the pool. 603 */ 604 if (mptsas_request_from_pool(mpt, &cmd, &pkt) == -1) { 605 mptsas_log(mpt, CE_NOTE, "command pool is full for RAID " 606 "action request"); 607 return; 608 } 609 action_flags |= MPTSAS_REQUEST_POOL_CMD; 610 611 bzero((caddr_t)cmd, sizeof (*cmd)); 612 bzero((caddr_t)pkt, scsi_pkt_size()); 613 614 pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb[0]; 615 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb; 616 pkt->pkt_ha_private = (opaque_t)cmd; 617 pkt->pkt_flags = (FLAG_NOINTR | FLAG_HEAD); 618 pkt->pkt_time = 5; 619 cmd->cmd_pkt = pkt; 620 cmd->cmd_flags = CFLAG_CMDIOC; 621 622 /* 623 * Send RAID Action. We don't care what the reply is so just exit 624 * after sending the request. This is just sent to the controller to 625 * keep the volume from having to resync the next time it starts. If 626 * the request doesn't work for whatever reason, we're not going to 627 * bother wondering why. 628 */ 629 if (mptsas_save_cmd(mpt, cmd) == TRUE) { 630 cmd->cmd_flags |= CFLAG_PREPARED; 631 /* 632 * Form message for raid action 633 */ 634 action = (pMpi2RaidActionRequest_t)(mpt->m_req_frame + 635 (mpt->m_req_frame_size * cmd->cmd_slot)); 636 bzero(action, mpt->m_req_frame_size); 637 action->Function = MPI2_FUNCTION_RAID_ACTION; 638 action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; 639 640 /* 641 * Send request 642 */ 643 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0, 644 DDI_DMA_SYNC_FORDEV); 645 request_desc_low = (cmd->cmd_slot << 16) + 646 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 647 MPTSAS_START_CMD(mpt, request_desc_low, 0); 648 649 /* 650 * Even though reply does not matter, wait no more than 5 651 * seconds here to get the reply just because we don't want to 652 * leave it hanging if it's coming. Use the FW diag cv. 653 */ 654 (void) cv_reltimedwait(&mpt->m_fw_diag_cv, &mpt->m_mutex, 655 drv_usectohz(5 * MICROSEC), TR_CLOCK_TICK); 656 } 657 658 /* 659 * Be sure to deallocate cmd before leaving. 660 */ 661 if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) { 662 mptsas_remove_cmd(mpt, cmd); 663 action_flags &= (~MPTSAS_REQUEST_POOL_CMD); 664 } 665 if (action_flags & MPTSAS_REQUEST_POOL_CMD) 666 mptsas_return_to_pool(mpt, cmd); 667 668 } 669 670 int 671 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid) 672 { 673 int config, i, vol = (-1); 674 mptsas_slots_t *slots = mpt->m_active; 675 676 for (config = 0; config < slots->m_num_raid_configs; config++) { 677 for (i = 0; i < MPTSAS_MAX_RAIDVOLS; i++) { 678 if (slots->m_raidconfig[config].m_raidvol[i]. 679 m_raidhandle == volid) { 680 vol = i; 681 break; 682 } 683 } 684 } 685 686 if (vol < 0) { 687 mptsas_log(mpt, CE_WARN, "raid doesn't exist at specified " 688 "target."); 689 return (-1); 690 } 691 692 slots->m_raidconfig[config].m_raidvol[vol].m_israid = 0; 693 slots->m_raidconfig[config].m_raidvol[vol].m_ndisks = 0; 694 for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) { 695 slots->m_raidconfig[config].m_raidvol[vol].m_disknum[i] = 0; 696 slots->m_raidconfig[config].m_raidvol[vol].m_devhdl[i] = 0; 697 } 698 699 return (0); 700 } 701