changeset 10275:f0b35eb34c31

PSARC/2009/401 Fibre Channel port link reinitialize support 6858288 add subcommand force-lip to fcadm
author Reed <Reed.Liu@Sun.COM>
date Fri, 07 Aug 2009 15:32:17 +0800
parents b6754e1b3938
children f3e12ac807fa
files usr/src/cmd/fcinfo/fcadm-list.c usr/src/cmd/fcinfo/fcinfo.c usr/src/cmd/fcinfo/fcinfo.h usr/src/lib/hbaapi/common/HBAAPILIB-sun.c usr/src/lib/hbaapi/common/hbaapi-sun.h usr/src/lib/hbaapi/common/mapfile-vers usr/src/lib/sun_fc/Makefile.com usr/src/lib/sun_fc/common/FCHBA.cc usr/src/lib/sun_fc/common/FCHBA.h usr/src/lib/sun_fc/common/HBA.h usr/src/lib/sun_fc/common/Handle.cc usr/src/lib/sun_fc/common/Handle.h usr/src/lib/sun_fc/common/Sun_fcDoForceLip.cc usr/src/lib/sun_fc/common/TgtFCHBA.cc usr/src/lib/sun_fc/common/TgtFCHBA.h usr/src/lib/sun_fc/common/mapfile-vers usr/src/uts/common/io/comstar/port/fct/fct.c usr/src/uts/common/io/comstar/port/qlt/qlt.c usr/src/uts/common/sys/fct.h usr/src/uts/common/sys/fctio.h
diffstat 20 files changed, 366 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fcinfo/fcadm-list.c	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/cmd/fcinfo/fcadm-list.c	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -943,3 +943,49 @@
 
 	return (0);
 }
+
+/* ARGSUSED */
+int
+fc_util_force_lip(int objects, char *argv[])
+{
+	uint64_t	hbaWWN;
+	HBA_WWN		myWWN;
+	HBA_HANDLE	handle;
+	HBA_STATUS	status;
+	int		rval = 0;
+
+	if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
+		fprintf(stderr, gettext("Failed to load FC-HBA library\n"));
+		printStatus(status);
+		fprintf(stderr, "\n");
+		return (1);
+	}
+
+	sscanf(argv[0], "%016llx", &hbaWWN);
+	hbaWWN = htonll(hbaWWN);
+	memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN));
+
+	/*
+	 * Try target mode first
+	 */
+	if ((status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN)) !=
+	    HBA_STATUS_OK) {
+		/*
+		 * Continue to try initiator mode
+		 */
+		if ((status = HBA_OpenAdapterByWWN(&handle, myWWN)) !=
+		    HBA_STATUS_OK) {
+			fprintf(stderr, gettext("Error: HBA %s not found\n"),
+			    argv[0]);
+			return (0);
+		}
+	}
+
+	status = Sun_HBA_ForceLip(handle, &rval);
+	if ((status != HBA_STATUS_OK) || (rval != 0)) {
+		fprintf(stderr, gettext("Error: Failed to reinitialize the "
+		    "link of HBA %s\n"), argv[0]);
+	}
+
+	return (0);
+}
--- a/usr/src/cmd/fcinfo/fcinfo.c	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/cmd/fcinfo/fcinfo.c	Fri Aug 07 15:32:17 2009 +0800
@@ -53,6 +53,7 @@
 static int fcoeAdmCreatePortFunc(int, char **, cmdOptions_t *, void *);
 static int fcoeListPortsFunc(int, char **, cmdOptions_t *, void *);
 static int fcoeAdmDeletePortFunc(int, char **, cmdOptions_t *, void *);
+static int fcadmForceLipFunc(int, char **, cmdOptions_t *, void *);
 static char *getExecBasename(char *);
 
 /*
@@ -122,6 +123,9 @@
 	{"list-fcoe-ports",
 	    fcoeListPortsFunc, "it", NULL, NULL,
 		OPERAND_NONE, NULL},
+	{"force-lip",
+	    fcadmForceLipFunc, NULL, NULL, NULL,
+		OPERAND_MANDATORY_SINGLE, "WWN"},
 	{NULL, 0, NULL, NULL, NULL, 0, NULL, NULL}
 };
 
@@ -240,6 +244,17 @@
 }
 
 /*
+ * Pass in options/arguments, rest of arguments
+ */
+/*ARGSUSED*/
+static int
+fcadmForceLipFunc(int objects, char *argv[], cmdOptions_t *options,
+    void *addArgs)
+{
+	return (fc_util_force_lip(objects, argv));
+}
+
+/*
  * input:
  *  execFullName - exec name of program (argv[0])
  *
--- a/usr/src/cmd/fcinfo/fcinfo.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/cmd/fcinfo/fcinfo.h	Fri Aug 07 15:32:17 2009 +0800
@@ -146,6 +146,7 @@
 int fc_util_delete_npivport(int wwnCount, char **argv, cmdOptions_t *options);
 int fc_util_create_npivport(int wwnCount, char **argv, cmdOptions_t *options);
 int fc_util_create_portlist();
+int fc_util_force_lip(int objects, char *argv[]);
 
 int fcoe_adm_create_port(int objects, char *argv[],
     cmdOptions_t *options);
--- a/usr/src/lib/hbaapi/common/HBAAPILIB-sun.c	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/hbaapi/common/HBAAPILIB-sun.c	Fri Aug 07 15:32:17 2009 +0800
@@ -18,7 +18,7 @@
  *************************************************************************
  */
 /*
- * 	Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * 	Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * 	Use is subject to license terms.
  */
 
@@ -102,7 +102,7 @@
 	}\
     }
 #endif /* WIN32*/
- 
+
 #else /* Not both USESYSLOG and USELOGFILE */
 #if defined(USESYSLOG)
 int _hbaapi_sysloginit = 0;
@@ -142,11 +142,11 @@
 #endif /* WIN32 */
 #endif /* USELOGFILE */
 #endif /* Not both USELOGFILE and USESYSLOG */
- 
+
 #ifdef POSIX_THREADS
 #include <pthread.h>
 /*
- * When multiple mutex's are grabed, they must be always be grabbed in 
+ * When multiple mutex's are grabed, they must be always be grabbed in
  * the same order, or deadlock can result.  There are three levels
  * of mutex's involved in this API.  If LL_mutex is grabbed, always grap
  * it first.  If AL_mutex is grabbed, it may not be grabbed before
@@ -167,11 +167,11 @@
 #define RELEASE_MUTEX(M)
 #define RELEASE_MUTEX_RETURN(M,RET)	return(RET)
 #endif
- 
+
 /*
  * HBA_LIBRARY_STATUS and HBA_LIBRARY_INFO are redefined here.
  * Avoid any change in the common code.
- */ 
+ */
 typedef enum {
     HBA_LIBRARY_UNKNOWN,
     HBA_LIBRARY_LOADED,
@@ -232,6 +232,7 @@
 typedef	HBA_STATUS	(* Sun_HBARegisterForAdapterDeviceEventsFunc)
 			    (void (*)(void *, HBA_WWN, HBA_UINT32, HBA_UINT32),
 			    void *, HBA_HANDLE, HBA_WWN, HBA_CALLBACKHANDLE *);
+typedef	HBA_STATUS	(* Sun_HBADoForceLipFunc)(HBA_HANDLE, int *);
 
 /*
  * Individual adapter (hba) information
@@ -324,7 +325,7 @@
             GetTgtAdapterNameFunc = (Sun_HBAGetTgtAdapterNameFunc)
 		dlsym(lib_infop->hLibrary, "Sun_fcGetTgtAdapterName");
 	    if (GetNumberOfTgtAdaptersFunc == NULL ||
-		GetTgtAdapterNameFunc == NULL)	{	    
+		GetTgtAdapterNameFunc == NULL)	{
 		GetNumberOfTgtAdaptersFunc = GetTgtAdapterNameFunc = NULL;
                 continue;
             }
@@ -334,10 +335,10 @@
 
 	num_adapters = ((GetNumberOfTgtAdaptersFunc)());
 #ifndef WIN32
-	DEBUG(1, "HBAAPI: number of target mode adapters for %s = %d\n", 
+	DEBUG(1, "HBAAPI: number of target mode adapters for %s = %d\n",
 	      lib_infop->LibraryName, num_adapters, 0);
 #else
-	DEBUG(1, "HBAAPI: number of target mode_adapters for %s = %d\n", 
+	DEBUG(1, "HBAAPI: number of target mode_adapters for %s = %d\n",
 	      lib_infop->LibraryPath, num_adapters, 0);
 #endif
 
@@ -380,7 +381,7 @@
 		adapt_infop->name = strdup(adaptername);
 	    } else {
 		char dummyname[512];
-		sprintf(dummyname, "NULLADAPTER-%s-%03d", 
+		sprintf(dummyname, "NULLADAPTER-%s-%03d",
 			lib_infop->LibraryPath, _hbaapi_total_tgtadapter_count);
 		dummyname[255] = '\0';
 		adapt_infop->name = strdup(dummyname);
@@ -421,7 +422,7 @@
 	adapt_infop = adapt_infop->next) {
 
 	if(adapt_infop->index == adapterindex) {
-	    if(adapt_infop->name != NULL && 
+	    if(adapt_infop->name != NULL &&
 	       adapt_infop->GNstatus == HBA_STATUS_OK) {
 		strcpy(adaptername, adapt_infop->name);
 	    } else {
@@ -517,13 +518,13 @@
         OpenTgtAdapterByWWNFunc = (Sun_HBAOpenTgtAdapterByWWNFunc)
 		dlsym(lib_infop->hLibrary, "Sun_fcOpenTgtAdapterByWWN");
 	if (GetNumberOfTgtAdaptersFunc == NULL ||
-		OpenTgtAdapterByWWNFunc == NULL) {	    
+		OpenTgtAdapterByWWNFunc == NULL) {
 		GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
                 continue;
         }
 
 	(void) ((GetNumberOfTgtAdaptersFunc)());
- 
+
 	if((status = (OpenTgtAdapterByWWNFunc)(&handle, nodeWWN))
 	    != HBA_STATUS_OK) {
 	    GetNumberOfTgtAdaptersFunc = OpenTgtAdapterByWWNFunc = NULL;
@@ -842,3 +843,25 @@
 
 	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
 }
+
+HBA_STATUS
+Sun_HBA_ForceLip(HBA_HANDLE handle, int *rval)
+{
+	HBA_STATUS		status;
+	HBA_LIBRARY_INFO	*lib_infop;
+	HBA_HANDLE		vendorHandle;
+
+	Sun_HBADoForceLipFunc	DoForceLipFunc;
+
+	DEBUG(2, "Sun_HBA_DoForceLip", 0, 0, 0);
+
+	NPIVCHECKLIBRARY();
+	DoForceLipFunc = (Sun_HBADoForceLipFunc)
+		dlsym(lib_infop->hLibrary, "Sun_fcDoForceLip");
+	if (DoForceLipFunc != NULL) {
+		status = ((DoForceLipFunc)(vendorHandle, rval));
+	} else {
+		status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+	}
+	RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
--- a/usr/src/lib/hbaapi/common/hbaapi-sun.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/hbaapi/common/hbaapi-sun.h	Fri Aug 07 15:32:17 2009 +0800
@@ -20,7 +20,7 @@
  * *******************************************************************************
  */
 /*
- * 	Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * 	Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * 	Use is subject to license terms.
  */
 
@@ -140,6 +140,9 @@
     HBA_CALLBACKHANDLE	*callbackHandle
     );
 
+HBA_API HBA_STATUS Sun_HBA_ForceLip(
+    HBA_HANDLE handle,
+    int *rval);
 
 #endif /* HBA_API_SUN_H */
 
--- a/usr/src/lib/hbaapi/common/mapfile-vers	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/hbaapi/common/mapfile-vers	Fri Aug 07 15:32:17 2009 +0800
@@ -113,6 +113,7 @@
 	Sun_HBA_OpenTgtAdapterByWWN;
 	Sun_HBA_AdapterCreateWWN;
 	Sun_HBA_AdapterReturnWWN;
+	Sun_HBA_ForceLip;
 
     local:
 	*;
--- a/usr/src/lib/sun_fc/Makefile.com	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/Makefile.com	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #
@@ -119,6 +119,7 @@
 		HandleNPIVPort.o \
 		AdapterDeviceEventListener.o \
 		Sun_fcRegisterForAdapterDeviceEvents.o \
+		Sun_fcDoForceLip.o \
 		Sun_fcAdapterCreateWWN.o \
 		Sun_fcAdapterReturnWWN.o
 
--- a/usr/src/lib/sun_fc/common/FCHBA.cc	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/FCHBA.cc	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -204,6 +204,51 @@
     return (attributes);
 }
 
+int FCHBA::doForceLip() {
+    Trace	 log("FCHBA::doForceLip");
+    int		 fd;
+    fcio_t	 fcio;
+    uint64_t	 wwn  = 0;
+    HBAPort	*port = getPortByIndex(0);
+
+    errno = 0;
+    if ((fd = open(port->getPath().c_str(), O_RDONLY | O_EXCL)) == -1) {
+	if (errno == EBUSY) {
+	    throw BusyException();
+	} else if (errno == EAGAIN) {
+	    throw TryAgainException();
+	} else if (errno == ENOTSUP) {
+	    throw NotSupportedException();
+	} else {
+	    throw IOError(port);
+	}
+    }
+
+    memset(&fcio, 0, sizeof (fcio));
+    fcio.fcio_cmd = FCIO_RESET_LINK;
+    fcio.fcio_xfer = FCIO_XFER_WRITE;
+    fcio.fcio_ilen = sizeof (wwn);
+    fcio.fcio_ibuf = (caddr_t)&wwn;
+
+    errno = 0;
+    if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
+	close(fd);
+
+	if (errno == EBUSY) {
+	    throw BusyException();
+	} else if (errno == EAGAIN) {
+	    throw TryAgainException();
+	} else if (errno == ENOTSUP) {
+	    throw NotSupportedException();
+	} else {
+	    throw IOError("Unable to reinitialize the link");
+	}
+    } else {
+        close(fd);
+	return (fcio.fcio_errno);
+    }
+}
+
 HBA_ADAPTERATTRIBUTES FCHBA::npivGetHBAAttributes() {
 	Trace log("FCHBA::npivGetHBAAttributes");
 	int fd;
--- a/usr/src/lib/sun_fc/common/FCHBA.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/FCHBA.h	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,6 +47,7 @@
      */
     virtual std::string		    getName();
     virtual HBA_ADAPTERATTRIBUTES   getHBAAttributes();
+    virtual int 		    doForceLip();
     virtual HBA_ADAPTERATTRIBUTES	npivGetHBAAttributes();
     static void loadAdapters(std::vector<HBA*> &list);
 
--- a/usr/src/lib/sun_fc/common/HBA.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/HBA.h	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -61,6 +61,7 @@
 	bool				containsWWN(uint64_t wwn);
 
 	virtual HBA_ADAPTERATTRIBUTES	getHBAAttributes() = 0;
+	virtual int			doForceLip() = 0;
 	virtual HBA_ADAPTERATTRIBUTES	npivGetHBAAttributes() = 0;
 	void				setRNID(HBA_MGMTINFO info);
 	/*
--- a/usr/src/lib/sun_fc/common/Handle.cc	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/Handle.cc	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -123,7 +123,7 @@
 
 
 	// if initiator mode call constructor for initiator.
-	if (m == INITIATOR) { 
+	if (m == INITIATOR) {
 		Handle(myhba, TARGET);
 	}
 
@@ -377,6 +377,24 @@
 	}
 }
 
+/**
+ * @memo	    Do FORCELIP
+ *
+ * @see		    HBA::doForceLip
+ */
+int Handle::doForceLip() {
+	Trace log("Handle::doForceLip");
+	lock();
+	try {
+	    int rval = hba->doForceLip();
+	    unlock();
+	    return (rval);
+	} catch (...) {
+	    unlock();
+	    throw;
+	}
+}
+
 HBA_ADAPTERATTRIBUTES Handle::npivGetHBAAttributes() {
 	Trace log("Handle::npivGetHBAAttributes");
 	lock();
--- a/usr/src/lib/sun_fc/common/Handle.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/Handle.h	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -69,6 +69,7 @@
     void		    refresh();
 
     HBA_ADAPTERATTRIBUTES	    getHBAAttributes();
+    int				    doForceLip();
     HBA_ADAPTERATTRIBUTES	    npivGetHBAAttributes();
     HBA_PORTATTRIBUTES		    getPortAttributes(uint64_t wwn);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/sun_fc/common/Sun_fcDoForceLip.cc	Fri Aug 07 15:32:17 2009 +0800
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "Handle.h"
+#include "Trace.h"
+#include "Exceptions.h"
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/**
+ * @memo	    Retrieves the attributes for an adapter
+ * @precondition    Library must be loaded
+ * @return	    HBA_STATUS_OK if attributes were filled in
+ * @param	    handle The desired HBA
+ * @param	    rval Return value
+ *
+ */
+HBA_STATUS Sun_fcDoForceLip(HBA_HANDLE handle,
+	    int *rval) {
+	Trace log("Sun_fcDoForceLip");
+
+	try {
+	    Handle *myHandle = Handle::findHandle(handle);
+	    *rval = myHandle->doForceLip();
+	    return (HBA_STATUS_OK);
+	} catch (HBAException &e) {
+	    return (e.getErrorCode());
+	} catch (...) {
+	    log.internalError(
+		"Uncaught exception");
+	    return (HBA_STATUS_ERROR);
+	}
+}
+
+#ifdef	__cplusplus
+}
+#endif
--- a/usr/src/lib/sun_fc/common/TgtFCHBA.cc	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/TgtFCHBA.cc	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -160,6 +160,63 @@
     return (attributes);
 }
 
+int TgtFCHBA::doForceLip()
+{
+    Trace	 log("TgtFCHBA::doForceLip");
+    int		 fd;
+    HBAPort	*port = getPortByIndex(0);
+    fctio_t	 fctio;
+    uint64_t	 portwwn;
+
+    errno = 0;
+    if ((fd = open(FCT_DRIVER_PATH.c_str(), O_NDELAY | O_RDONLY)) == -1) {
+	if (errno == EBUSY) {
+	    throw BusyException();
+	} else if (errno == EAGAIN) {
+	    throw TryAgainException();
+	} else if (errno == ENOTSUP) {
+	    throw NotSupportedException();
+	} else {
+	    throw IOError(port);
+	}
+    }
+
+    try {
+	    std::string path = port->getPath();
+	    string::size_type offset = path.find_last_of(".");
+	    if (offset >= 0) {
+		string portwwnString = path.substr(offset+1);
+		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
+	    }
+    } catch (...) {
+	    throw BadArgumentException();
+    }
+
+    uint64_t en_wwn = htonll(portwwn);
+    memset(&fctio, 0, sizeof (fctio));
+    fctio.fctio_cmd = FCTIO_FORCE_LIP;
+    fctio.fctio_xfer = FCTIO_XFER_READ;
+    fctio.fctio_ilen = 8;
+    fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
+
+    errno = 0;
+    if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
+	close(fd);
+	if (errno == EBUSY) {
+	    throw BusyException();
+	} else if (errno == EAGAIN) {
+	    throw TryAgainException();
+	} else if (errno == ENOTSUP) {
+	    throw NotSupportedException();
+	} else {
+	    throw IOError("Unable to reinitialize the link");
+	}
+    } else {
+	close(fd);
+	return ((int)fctio.fctio_errno);
+    }
+}
+
 void TgtFCHBA::loadAdapters(vector<HBA*> &list)
 {
     Trace log("TgtFCHBA::loadAdapters");
@@ -257,11 +314,11 @@
 	try {
 	    std::string hbapath = FCT_ADAPTER_NAME_PREFIX.c_str();
 	    hbapath += ".";
-	    // move the row with two dimentional uint8 array for WWN 
+	    // move the row with two dimentional uint8 array for WWN
 	    uint64_t tmp = ntohll(*((uint64_t *)&tgthbaList->port_wwn[i][0]));
 	    sprintf(wwnStr, "%llx", tmp);
 	    hbapath += wwnStr;
-	    
+
 	    HBA *hba = new TgtFCHBA(hbapath);
 	    list.insert(list.begin(), hba);
 	} catch (...) {
--- a/usr/src/lib/sun_fc/common/TgtFCHBA.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/TgtFCHBA.h	Fri Aug 07 15:32:17 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,6 +47,7 @@
      */
     virtual std::string		    getName();
     virtual HBA_ADAPTERATTRIBUTES   getHBAAttributes();
+    virtual int 		    doForceLip();
     static void loadAdapters(std::vector<HBA*> &list);
     virtual HBA_ADAPTERATTRIBUTES   npivGetHBAAttributes() {
 					throw NotSupportedException(); }
--- a/usr/src/lib/sun_fc/common/mapfile-vers	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/lib/sun_fc/common/mapfile-vers	Fri Aug 07 15:32:17 2009 +0800
@@ -108,6 +108,7 @@
 	Sun_fcSetBindingSupport;
 	Sun_fcSetPersistentBindingV2;
 	Sun_fcSetRNIDMgmtInfo;
+	Sun_fcDoForceLip;
 
     local:
 	*;
--- a/usr/src/uts/common/io/comstar/port/fct/fct.c	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/uts/common/io/comstar/port/fct/fct.c	Fri Aug 07 15:32:17 2009 +0800
@@ -743,6 +743,30 @@
 }
 
 static int
+fct_forcelip(uint8_t *port_wwn, uint32_t *fctio_errno)
+{
+	fct_status_t		 rval;
+	fct_i_local_port_t	*iport;
+
+	mutex_enter(&fct_global_mutex);
+	iport = fct_get_iport_per_wwn(port_wwn);
+	mutex_exit(&fct_global_mutex);
+	if (iport == NULL) {
+		return (-1);
+	}
+
+	iport->iport_port->port_ctl(iport->iport_port,
+	    FCT_CMD_FORCE_LIP, &rval);
+	if (rval != FCT_SUCCESS) {
+		*fctio_errno = FCTIO_FAILURE;
+	} else {
+		*fctio_errno = 0;
+	}
+
+	return (0);
+}
+
+static int
 fct_fctiocmd(intptr_t data, int mode)
 {
 	int ret	 = 0;
@@ -885,6 +909,10 @@
 		break;
 		}
 
+	case FCTIO_FORCE_LIP:
+		ret = fct_forcelip((uint8_t *)ibuf, &fctio->fctio_errno);
+		break;
+
 	default:
 		break;
 	}
--- a/usr/src/uts/common/io/comstar/port/qlt/qlt.c	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/uts/common/io/comstar/port/qlt/qlt.c	Fri Aug 07 15:32:17 2009 +0800
@@ -1646,18 +1646,38 @@
 	return (ret);
 }
 
+static fct_status_t
+qlt_force_lip(qlt_state_t *qlt)
+{
+	mbox_cmd_t	*mcp;
+	fct_status_t	 rval;
+
+	mcp = qlt_alloc_mailbox_command(qlt, 0);
+	mcp->to_fw[0] = 0x0072;
+	mcp->to_fw[1] = BIT_4;
+	mcp->to_fw[3] = 1;
+	mcp->to_fw_mask |= BIT_1 | BIT_3;
+	rval = qlt_mailbox_command(qlt, mcp);
+	if (rval != FCT_SUCCESS) {
+		QLT_LOG(qlt->qlt_port_alias, "qlt FLIP MB failed: rval=%x");
+	} else {
+		if (mcp->from_fw[0] != 0x4000) {
+			QLT_LOG(qlt->qlt_port_alias, "qlt FLIP: fw[0]=%x",
+			    mcp->from_fw[0]);
+			rval = FCT_FAILURE;
+		}
+	}
+	qlt_free_mailbox_command(qlt, mcp);
+	return (rval);
+}
+
 static void
 qlt_ctl(struct fct_local_port *port, int cmd, void *arg)
 {
-	stmf_change_status_t		st;
+	stmf_change_status_t		 st;
 	stmf_state_change_info_t	*ssci = (stmf_state_change_info_t *)arg;
 	qlt_state_t			*qlt;
 
-	ASSERT((cmd == FCT_CMD_PORT_ONLINE) ||
-	    (cmd == FCT_CMD_PORT_OFFLINE) ||
-	    (cmd == FCT_ACK_PORT_ONLINE_COMPLETE) ||
-	    (cmd == FCT_ACK_PORT_OFFLINE_COMPLETE));
-
 	qlt = (qlt_state_t *)port->port_fca_private;
 	st.st_completion_status = FCT_SUCCESS;
 	st.st_additional_info = NULL;
@@ -1727,6 +1747,15 @@
 			}
 		}
 		break;
+
+	case FCT_CMD_FORCE_LIP:
+		*((fct_status_t *)arg) = qlt_force_lip(qlt);
+		QLT_LOG(qlt->qlt_port_alias, "qlt_ctl: forcelip done");
+		break;
+
+	default:
+		QLT_LOG(qlt->qlt_port_alias, "qlt_ctl: unsupport-0x%02X", cmd);
+		break;
 	}
 }
 
--- a/usr/src/uts/common/sys/fct.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/uts/common/sys/fct.h	Fri Aug 07 15:32:17 2009 +0800
@@ -346,6 +346,7 @@
 #define	FCT_CMD_PORT_OFFLINE_COMPLETE	(STMF_LPORT_CTL_CMDS | 0x04)
 #define	FCT_ACK_PORT_ONLINE_COMPLETE	(STMF_LPORT_CTL_CMDS | 0x05)
 #define	FCT_ACK_PORT_OFFLINE_COMPLETE	(STMF_LPORT_CTL_CMDS | 0x06)
+#define	FCT_CMD_FORCE_LIP		(STMF_LPORT_CTL_CMDS | 0x07)
 
 /*
  * IO flags for cmd flow.
--- a/usr/src/uts/common/sys/fctio.h	Thu Aug 06 23:54:01 2009 -0700
+++ b/usr/src/uts/common/sys/fctio.h	Fri Aug 07 15:32:17 2009 +0800
@@ -39,6 +39,7 @@
 #define	FCTIO_GET_PORT_ATTRIBUTES		(FCTIO_SUB_CMD + 0x05)
 #define	FCTIO_GET_ADAPTER_PORT_STATS		(FCTIO_SUB_CMD + 0x06)
 #define	FCTIO_GET_LINK_STATUS			(FCTIO_SUB_CMD + 0x07)
+#define	FCTIO_FORCE_LIP				(FCTIO_SUB_CMD + 0x08)
 
 /*
  * fcio_xfer definitions