/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Copyright (c) 2000 to 2010, LSI Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms of all code within
* this file that is exclusively owned by LSI, with or without
* modification, is permitted provided that, in addition to the CDDL 1.0
* License requirements, the following conditions are met:
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/*
* mptsas_raid - This file contains all the RAID related functions for the
* MPT interface.
*/
#define MPTSAS_DEBUG
#endif
/*
* standard header files
*/
#include <sys/byteorder.h>
#include <sys/raidioctl.h>
#pragma pack(1)
#pragma pack()
/*
* private header files.
*/
static int
{
#ifndef __lock_lint
#endif
if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
return (DDI_FAILURE);
}
if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
"config: IOCStatus=0x%x, IOCLogInfo=0x%x",
rval = DDI_FAILURE;
return (rval);
}
/*
* Get all RAID configurations.
*/
/*
* Set up page address for next time through.
*/
/*
* Point to the right config in the structure.
* Increment the number of valid RAID configs.
*/
/*
* Set the native flag if this is not a foreign
* configuration.
*/
} else {
}
/*
* Get volume information for the volumes in the
* config.
*/
vol = 0;
disk = 0;
/*
* Get the element type. Could be Volume,
* PhysDisk, Hot Spare, or Online Capacity
* Expansion PhysDisk.
*/
/*
* For volumes, get the RAID settings and the
* WWID.
*/
if (elementtype == etype_vol) {
&element->VolDevHandle);
/*
* Get the settings for the raid
* volume. This includes the
* DevHandles for the disks making up
* the raid volume.
*/
continue;
/*
* Get the WWID of the RAID volume for
* SAS HBA
*/
if (mptsas_get_raid_wwid(mpt,
continue;
/*
* RAID uses phymask of 0.
*/
voldevhandle, raidwwn, 0, 0, 0);
ptgt;
/*
* Increment volume index within this
* raid config.
*/
vol++;
} else if ((elementtype == etype_pd) ||
(elementtype == etype_hs) ||
(elementtype == etype_oce)) {
/*
* For all other element types, put
* their DevHandles in the phys disk
* list of the config. These are all
* some variation of a Phys Disk and
* this list is used to keep these
* disks from going online.
*/
/*
* Increment disk index within this
* raid config.
*/
disk++;
}
}
return (rval);
}
int
{
/*
* Clear all RAID info before starting.
*/
mpt->m_num_raid_configs = 0;
configindex = 0;
confignum = 0xff;
while (rval == DDI_SUCCESS) {
/*
* Get the header and config page. reply contains the reply
* frame, which holds status info for the request.
*/
configindex++;
}
return (rval);
}
static int
{
#ifndef __lock_lint
#endif
int rval = DDI_SUCCESS, i;
return (DDI_FAILURE);
if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
"config: IOCStatus=0x%x, IOCLogInfo=0x%x",
rval = DDI_FAILURE;
return (rval);
}
/*
* Volume size is not used right now. Set to 0.
*/
raidvol->m_raidsize = 0;
}
if (statusflags &
}
switch (volstate) {
break;
if ((statusflags & resync_flag) == 0) {
"is degraded\n",
}
break;
break;
break;
default:
break;
}
for (i = 0; i < numdisks; i++) {
break;
}
return (rval);
}
int
{
/*
* Get the header and config page. reply contains the reply frame,
* which holds status info for the request.
*/
return (rval);
}
static int
{
#ifndef __lock_lint
#endif
int rval = DDI_SUCCESS, i;
if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
"config: IOCStatus=0x%x, IOCLogInfo=0x%x",
rval = DDI_FAILURE;
return (rval);
}
for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
}
return (rval);
}
static int
{
/*
* Get the header and config page. reply contains the reply frame,
* which holds status info for the request.
*/
/*
* Get the required information from the page.
*/
if (rval == DDI_SUCCESS) {
/*
* replace top nibble of WWID of RAID to '3' for OBP
*/
}
return (rval);
}
static int
{
#ifndef __lock_lint
#endif
int rval = DDI_SUCCESS;
return (DDI_FAILURE);
if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
"config: IOCStatus=0x%x, IOCLogInfo=0x%x",
rval = DDI_FAILURE;
return (rval);
}
return (rval);
}
int
{
/*
* Get the header and config page. reply contains the reply frame,
* which holds status info for the request.
*/
/*
* Get the required information from the page.
*/
if (rval == DDI_SUCCESS) {
for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
/* find the correct position in the arrays */
break;
}
switch (state) {
raidvol->m_diskstatus[i] =
break;
break;
default:
raidvol->m_diskstatus[i] =
break;
}
}
return (rval);
}
/*
* RAID Action for System Shutdown. This request uses the dedicated TM slot to
* avoid a call to mptsas_save_cmd. Since Solaris requires that the mutex is
* not held during the mptsas_quiesce function, this RAID action must not use
* the normal code path of requests and replies.
*/
void
{
int cnt;
/*
* Before doing the system shutdown RAID Action, make sure that the IOC
* supports IR and make sure there is a valid volume for the request.
*/
if (mpt->m_ir_capable) {
m_israid) {
break;
}
}
}
}
if (!ir_active) {
return;
}
/*
* If TM slot is already being used (highly unlikely), show message and
* don't issue the RAID action.
*/
" System Shutdown RAID Action.\n");
return;
}
/*
* Create the cmd and put it in the dedicated TM slot.
*/
/*
* Form message for raid action.
*/
/*
* Send RAID Action.
*/
/*
* Even though reply does not matter because the system is shutting
* down, wait no more than 5 seconds here to get the reply just because
* we don't want to leave it hanging if it's coming. Poll because
* interrupts are disabled when this function is called.
*/
/*
* Check for a reply.
*/
drv_usecwait(1000);
continue;
}
/*
* There is a reply. If it's not an address reply, ignore it.
*/
goto clear_and_continue;
}
/*
* SMID must be the TM slot since that's what we're using for
* this RAID action. If not, ignore this reply.
*/
&address_reply->SMID);
goto clear_and_continue;
}
/*
* If reply frame is not in the proper range ignore it.
*/
mpt->m_reply_frame_size != 0)) {
goto clear_and_continue;
}
/*
* If not a RAID action reply ignore it.
*/
if (function != MPI2_FUNCTION_RAID_ACTION) {
goto clear_and_continue;
}
/*
* Finally, make sure this is the System Shutdown RAID action.
* If not, ignore reply.
*/
if (action_type !=
goto clear_and_continue;
}
found_reply = TRUE;
/*
* Clear the reply descriptor for re-use and increment index.
*/
0xFFFFFFFFFFFFFFFF);
/*
* Update the global reply index and keep looking for the
* reply if not found yet.
*/
mpt->m_post_index = 0;
}
mpt->m_post_index);
if (!found_reply) {
continue;
}
break;
}
/*
* clear the used slot as the last step.
*/
}
int
{
config++) {
for (i = 0; i < MPTSAS_MAX_RAIDVOLS; i++) {
m_raidhandle == volid) {
vol = i;
break;
}
}
}
if (vol < 0) {
"target.");
return (-1);
}
for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
}
return (0);
}