/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*LINTLIBRARY*/
/*
* This module is part of fibre channel interface library.
*/
/*
* I18N message number ranges
* This file: 11000 - 11499
* Shared common messages: 1 - 1999
*/
/* #define _POSIX_SOURCE 1 */
/* Includes */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <nl_types.h>
#include <l_common.h>
#include <stgcom.h>
#include <l_error.h>
#include <g_state.h>
/* Forward declarations */
static int issue_lip(char *, int);
/* Global variables */
extern uchar_t g_switch_to_alpa[];
extern uchar_t g_sf_alpa_to_switch[];
/*
* starts a device.
*
* RETURNS:
* 0 if O.K.
* non-zero otherwise
*/
int
{
int status;
return (status);
}
}
return (L_INVALID_PATH);
}
/*
* stops a device. If the device was
* reserved by a host, it gets multiple
* paths to the device and try to stop the
* device using a different path.
*
* Returns:
* 0 if OK
* -1 otherwise
*/
int
int verbose)
{
char *phys_path;
/* stop the device */
/* Make the stop NOT immediate, so we wait. */
return (L_INVALID_PATH);
}
/*
* In case of reservation conflict,
* get the multiple paths and try to
* stop the device through the path
* which held the reservations.
*/
== NULL) {
return (L_INVALID_PATH);
}
return (err);
}
(void) g_free_multipath(ml);
goto done;
}
}
(void) g_free_multipath(ml);
}
return (status);
}
done:
return (0);
}
/*
* This function is for Leadville devices only
* It takes as input the actual path on which to issue the LIP and issues it
*
* INPUT :
* Path to the FCA devctl node.
*
* For example,
*
* No SCSI_VHCI paths will work. No checks are done and we'll let the ioctl
* handle any failures if it is passed in.
*
* RETURNS:
* 0 on Success
* non-zero otherwise
*/
static int
{
int fp_fd;
/*
* open fp path with exclusive path, otherwise,
* FCIO_RESET_LINK ioctl will fail with permission
* denied error.
*/
return (L_OPEN_PATH_FAIL);
}
if (verbose) {
" Reinitializing the loop at: %s\n"), fp_path);
}
/*
* Reset the local loop here (fcio_ibuf = 0).
* Reset a remote loop on the Fabric by
* passing its node wwn (fcio_len = sizeof(nwwn)
* and fcio_ibuf = (caddr_t)&nwwn) to the port driver.
*/
I_DPRINTF(" issue_lip: FCIO_RESET_LINK"
" ioctl failed: %s\n", fp_path);
return (L_FCIO_RESET_LINK_FAIL);
}
return (0);
}
/*
* Issues the LIP (Loop Intialization Protocol)
* on a nexus path (in case of socal) or on an
* fp path (in case of fabric).
*
* RETURNS:
* 0 O.K.
* non-zero otherwise
*/
int
{
/* return invalid path if path_phys NULL */
return (L_INVALID_PATH);
}
/* Make a copy of the arg passed in ... we'll need it down */
/*
* Its an MPXIO device path
*
* First, Get a list of all the pHCI for the given vHCI
* Then issue a LIP on all the pHCI FCAs that are in the
* MDI_PATHINFO_STATE_ONLINE or MDI_PATHINFO_STATE_STANDBY
* states.
*/
return (L_INVALID_PATH);
}
for (i = 0; i < pathlist.path_count; i++) {
if ((pinfop->path_state ==
(pinfop->path_state ==
pathcnt++;
err++;
}
}
}
if (err == 0)
return (0);
return (L_FCIO_FORCE_LIP_FAIL);
return (L_FCIO_FORCE_LIP_PARTIAL_FAIL);
}
/* Non-MPXIO case */
return (L_INVALID_PATH);
}
if (dev_type & FC_FCA_MASK) {
return (L_INVALID_PATH);
}
*charPtr = '\0';
/* append devctl to the path */
} else {
/* should have fp transport node to continue. */
if (!(dev_type & FC_XPORT_MASK)) {
return (L_INVALID_PATH_TYPE);
}
return (L_LSTAT_ERROR);
}
/* append devctl to the path */
}
}
} else { /* for fc4 devices */
&nexus_path_ptr)) != 0)
return (err);
(void) g_destroy_data(nexus_path_ptr);
P_DPRINTF(" g_force_lip: Force lip on:"
" Path %s\n", nexus_path);
/* open driver */
return (L_OPEN_PATH_FAIL);
if (verbose) {
MSGSTR(11000,
" Forcing lip (Loop Initialization "
"Protocol)"
"\n on loop at: %s\n"), nexus_path);
}
I_DPRINTF(" FCIO_FORCE_LIP ioctl failed.\n");
return (L_FCIO_FORCE_LIP_FAIL);
}
}
return (0);
}
/*
* Takes one or more drives offline.
* If the force flag is supplied then: (1) don't pass the exclusive flag
* to the acquire routine and (2) allow the offline to fail
* If any acquire fails, print an error message and continue.
*
* RETURNS:
* 0 iff each offline succeeds
* non-zero otherwise
*/
int
{
/* for each drive attempt to take it offline */
/* attempt to acquire the device */
P_DPRINTF("%s: Could not acquire"
" the device: %s\n\n",
continue;
}
}
/* attempt to offline the drive */
(void) devctl_release(devhdl);
return (L_DEV_BUSY);
}
/* offline succeeded -- release handle acquired above */
(void) devctl_release(devhdl);
}
return (0);
}
/*
* Brings one or more drives online.
* If the force flag is supplied then: (1) don't pass the exclusive
* flag to the acquire routine and (2) allow the offline to fail
* If any acquire fails, continue with the next device.
*
* RETURNS:
* None.
*/
void
{
(void) devctl_device_online(devhdl);
(void) devctl_release(devhdl);
}
}
}
void
{
uchar_t c;
for (j = 0, k = 0; j < 8; j++) {
c = wwn_ll[j];
snib = (c & 0x0f);
}
wwn_str[k] = '\0';
}
/*
* Creates a list of nexus paths for each
* hotpluggable device and sends the list to g_force_lip(),
* which forces the LIP on each nexus path in the list.
*
* RETURNS:
* None.
*/
int
{
char *p;
while (disk_list) {
} else {
}
/* non-MPXIO device path */
} else {
if (p == NULL) {
}
}
if (p == NULL) {
" g_forcelip_all: Not able to do"
" LIP on this path because path "
continue;
}
} else {
/* MPXIO path */
}
/*
* Avoid issuing forcelip
* on the same HA more than once
*/
if (llist_head != NULL) {
break;
}
}
continue;
}
}
return (L_MALLOC_FAILED);
ndevs++;
if (llist_head == NULL) {
} else {
}
}
}
while (llist_head) {
(void) g_destroy_data(llist);
(void) g_destroy_data(llist_head);
return (err);
}
llist = llist_head;
(void) g_destroy_data((char *)llist);
}
return (0);
}