6879350 RFE: Add ability to enable/disable SRPT on specific HCAs
authorSue Gleeson <Susan.Gleeson@Sun.COM>
Mon, 05 Apr 2010 15:20:40 -0400
changeset 12075 b143b9fb49fc
parent 12074 fb7af6adefb4
child 12076 f531e5ff251f
6879350 RFE: Add ability to enable/disable SRPT on specific HCAs
usr/src/Makefile.lint
usr/src/cmd/Makefile
usr/src/cmd/srptadm/Makefile
usr/src/cmd/srptadm/srptadm.c
usr/src/lib/Makefile
usr/src/lib/libsrpt/Makefile
usr/src/lib/libsrpt/Makefile.com
usr/src/lib/libsrpt/amd64/Makefile
usr/src/lib/libsrpt/common/libsrpt.c
usr/src/lib/libsrpt/common/libsrpt.h
usr/src/lib/libsrpt/common/llib-lsrpt
usr/src/lib/libsrpt/common/mapfile-vers
usr/src/lib/libsrpt/i386/Makefile
usr/src/lib/libsrpt/sparc/Makefile
usr/src/lib/libsrpt/sparcv9/Makefile
usr/src/pkg/manifests/driver-network-srpt.mf
usr/src/uts/common/io/comstar/port/srpt/srpt_common.h
usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h
usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c
usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h
usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c
usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c
usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h
--- a/usr/src/Makefile.lint	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/Makefile.lint	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
 #
 
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 # include global definitions
@@ -274,6 +273,8 @@
 	cmd/smserverd \
 	cmd/sort \
 	cmd/split \
+	cmd/srptadm \
+	cmd/srptsvc \
 	cmd/ssh \
 	cmd/stat \
 	cmd/stmfadm \
@@ -423,6 +424,7 @@
 	lib/libsmbfs \
 	lib/libsmbios \
 	lib/libsmedia \
+	lib/libsrpt \
 	lib/libstmf \
 	lib/libsun_ima \
 	lib/libthread \
--- a/usr/src/cmd/Makefile	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/cmd/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -19,8 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 include ../Makefile.master
@@ -372,6 +371,7 @@
 	split		\
 	sqlite		\
 	srchtxt		\
+	srptadm		\
 	srptsvc		\
 	ssh		\
 	stat		\
@@ -689,6 +689,7 @@
 	smbsrv		\
 	sort		\
 	split		\
+	srptadm		\
 	ssh		\
 	stat		\
 	stmfadm		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/srptadm/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,42 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+PROG=		srptadm
+
+include ../Makefile.cmd
+
+LDLIBS += -lsecdb -lscf -lstmf -lsrpt
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTUSRSBINPROG)
+
+clean:
+
+lint:	lint_PROG
+
+include ../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/srptadm/srptadm.c	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,582 @@
+/*
+ * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libnvpair.h>
+#include <libintl.h>
+#include <libgen.h>
+#include <pwd.h>
+#include <auth_attr.h>
+#include <secdb.h>
+#include <libscf.h>
+#include <limits.h>
+#include <locale.h>
+#include <dirent.h>
+
+#include <libstmf.h>
+#include <libsrpt.h>
+
+/* SMF service info */
+#define	STMF_SVC	"svc:/system/stmf:default"
+
+#define	STMF_STALE(ret) {\
+	if (ret == STMF_ERROR_PROV_DATA_STALE) {\
+		(void) fprintf(stderr, "%s\n",\
+		    gettext("Configuration changed during processing.  "\
+		    "Check the configuration, then retry this command "\
+		    "if appropriate."));\
+	}\
+}
+
+#define	SRPTADM_CHKAUTH(sec) {\
+	if (!chkauthattr(sec, srptadm_uname)) {\
+		(void) fprintf(stderr,\
+		    gettext("Error, operation requires authorization %s"),\
+		    sec);\
+		(void) fprintf(stderr, "\n");\
+		return (1);\
+	}\
+}
+
+#define	PROPS_FORMAT	"    %-20s: "
+
+static struct option srptadm_long[] = {
+	{"enable",		no_argument,		NULL, 'e'},
+	{"disable",		no_argument,		NULL, 'd'},
+	{"reset",		no_argument,		NULL, 'r'},
+	{"help",		no_argument,		NULL, '?'},
+	{"help",		no_argument,		NULL, 'h'},
+	{NULL, 0, NULL, 0}
+};
+
+static char m_def[] = "srptadm modify-defaults [-e] [-d]";
+static char l_def[] = "srptadm list-defaults";
+static char s_tgt[] = "srptadm modify-target [-e] [-d] [-r] <hca>";
+static char l_tgt[] = "srptadm list-target [<hca>]";
+
+/* keep the order of this enum in the same order as the 'subcmds' struct */
+typedef enum {
+	MODIFY_DEFAULT,
+	LIST_DEFAULT,
+	MODIFY_TARGET,
+	LIST_TARGET,
+	NULL_SUBCMD	/* must always be last! */
+} srptadm_sub_t;
+
+typedef struct {
+	char		*name;
+	char		*shortopts;
+	char		*usemsg;
+} srptadm_subcmds_t;
+
+static srptadm_subcmds_t	subcmds[] = {
+	{"modify-defaults", "edh?", m_def},
+	{"list-defaults", "h?", l_def},
+	{"modify-target", "edrh?", s_tgt},
+	{"list-target", "h?", l_tgt},
+	{NULL, ":h?", NULL},
+};
+
+/* used for checking if user is authorized */
+static char *srptadm_uname = NULL;
+
+/* prototypes */
+static int get_local_hcas(char **hcaArray, int count);
+static int print_target_props(char *hca);
+static int list_target(char *hca);
+static int disable_target(char *hca);
+static int reset_target(char *hca);
+static int list_defaults(void);
+static int enable_target(char *hca);
+static int set_default_state(boolean_t enabled);
+
+int
+main(int argc, char *argv[])
+{
+	int		ret = 0;
+	int		idx = NULL_SUBCMD;
+	char		c;
+	int		newargc = argc;
+	char		**newargv = NULL;
+	char		*objp;
+	int		srptind = 0;
+	struct passwd	*pwd = NULL;
+	char		*smfstate = NULL;
+	boolean_t	reset = B_FALSE;
+	int		dflag = 0;
+	int		eflag = 0;
+
+	(void) setlocale(LC_ALL, "");
+	(void) textdomain(TEXT_DOMAIN);
+
+	if (argc < 2) {
+		ret = 1;
+		goto usage_error;
+	}
+
+	for (idx = 0; subcmds[idx].name != NULL; idx++) {
+		if (strcmp(argv[1], subcmds[idx].name) == 0) {
+			break;
+		}
+	}
+
+	/* get the caller's user name for subsequent chkauthattr() calls */
+	pwd = getpwuid(getuid());
+	if (pwd == NULL) {
+		(void) fprintf(stderr, "%s\n",
+		    gettext("Could not determine callers user name."));
+		return (1);
+	}
+
+	srptadm_uname = strdup(pwd->pw_name);
+
+	/* increment past command & subcommand */
+	newargc--;
+	newargv = &(argv[1]);
+
+	while ((ret == 0) && (newargv)) {
+		c = getopt_long(newargc, newargv, subcmds[idx].shortopts,
+		    srptadm_long, &srptind);
+		if (c == -1) {
+			break;
+		}
+
+		switch (c) {
+			case 0:
+				/* flag set by getopt */
+				break;
+			case 'd':
+				dflag++;
+				break;
+			case 'e':
+				eflag++;
+				break;
+			case 'r':
+				reset = B_TRUE;
+				break;
+			case '?':
+				/*
+				 * '?' is returned for both unrecognized
+				 * options and if explicitly provided on
+				 * the command line.  The latter should
+				 * be handled the same as -h.
+				 */
+				if (strcmp(newargv[optind-1], "-?") != 0) {
+					(void) fprintf(stderr,
+					    gettext("Unrecognized option %s"),
+					    newargv[optind-1]);
+					(void) fprintf(stderr, "\n");
+					ret = 1;
+				}
+				goto usage_error;
+			case 'h':
+				goto usage_error;
+			case ':':
+				(void) fprintf(stderr,
+				    gettext("Option %s requires an operand."),
+				    newargv[optind-1]);
+				(void) fprintf(stderr, "\n");
+
+				/* fall through to default */
+			default:
+				ret = 1;
+				break;
+		}
+	}
+
+	if (ret != 0) {
+		goto usage_error;
+	}
+
+	/* after getopt() to allow handling of -h option */
+	if ((srptadm_sub_t)idx == NULL_SUBCMD) {
+		(void) fprintf(stderr, "%s\n",
+		    gettext("Error, no subcommand specified"));
+		ret = 1;
+		goto usage_error;
+	}
+
+	newargc -= optind;
+	if (newargc == 0) {
+		newargv = NULL;
+		objp = NULL;
+	} else {
+		newargv = &(newargv[optind]);
+		objp = newargv[0];
+	}
+
+	if (objp == NULL) {
+		switch ((srptadm_sub_t)idx) {
+		case MODIFY_TARGET:
+			/* These subcommands need operands */
+			ret = 1;
+			goto usage_error;
+		default:
+			break;
+		}
+	}
+
+	if (newargc > 1) {
+		switch ((srptadm_sub_t)idx) {
+		case MODIFY_TARGET:
+		case LIST_TARGET:
+			/* These subcommands should have at most one operand */
+			ret = 1;
+			goto usage_error;
+
+		default:
+			break;
+		}
+	}
+
+
+	/*
+	 * Make sure STMF service is enabled before proceeding.
+	 */
+	smfstate = smf_get_state(STMF_SVC);
+	if (!smfstate ||
+	    (strcmp(smfstate, SCF_STATE_STRING_ONLINE) != 0)) {
+		(void) fprintf(stderr, "%s\n",
+		    gettext("The STMF service must be online "
+		    "before running this command."));
+		(void) fprintf(stderr,
+		    gettext("Use 'svcadm enable -r %s'"), STMF_SVC);
+		(void) fprintf(stderr, "\n");
+		(void) fprintf(stderr, "%s\n",
+		    gettext("to enable the service and its prerequisite "
+		    "services and/or"));
+		(void) fprintf(stderr,
+		    gettext("'svcs -x %s' to determine why it is not online."),
+		    STMF_SVC);
+		(void) fprintf(stderr, "\n");
+
+		return (1);
+	}
+
+	switch ((srptadm_sub_t)idx) {
+		case MODIFY_DEFAULT:
+			if (eflag) {
+				ret = set_default_state(B_TRUE);
+			} else if (dflag) {
+				ret = set_default_state(B_FALSE);
+			} else {
+				ret = 1;
+				goto usage_error;
+			}
+			break;
+		case LIST_DEFAULT:
+			ret = list_defaults();
+			break;
+		case MODIFY_TARGET:
+			if (reset) {
+				ret = reset_target(objp);
+			} else if (eflag) {
+				ret = enable_target(objp);
+			} else if (dflag) {
+				ret = disable_target(objp);
+			} else {
+				ret = 1;
+				goto usage_error;
+			}
+			break;
+		case LIST_TARGET:
+			ret = list_target(objp);
+			break;
+		default:
+			ret = 1;
+			goto usage_error;
+	}
+
+	if (ret != 0) {
+		(void) fprintf(stderr,
+		    gettext("srptadm %s failed with error %d"),
+		    subcmds[idx].name, ret);
+		(void) fprintf(stderr, "\n");
+	}
+	return (ret);
+
+usage_error:
+	if (subcmds[idx].name) {
+		(void) printf("%s\n", gettext(subcmds[idx].usemsg));
+	} else {
+		/* overall usage */
+		(void) printf("%s\n\n", gettext("srptadm usage:"));
+		for (idx = 0; subcmds[idx].name != NULL; idx++) {
+			if (!subcmds[idx].usemsg) {
+				continue;
+			}
+			(void) printf("\t%s\n", gettext(subcmds[idx].usemsg));
+		}
+	}
+
+	return (ret);
+}
+
+static int
+set_default_state(boolean_t enabled)
+{
+	int		ret;
+	char		*sec = "solaris.smf.modify.stmf";
+
+	SRPTADM_CHKAUTH(sec);
+
+	ret = srpt_SetDefaultState(enabled);
+
+	return (ret);
+}
+
+static int
+enable_target(char *hca)
+{
+	int		ret;
+	char		*sec = "solaris.smf.modify.stmf";
+
+	SRPTADM_CHKAUTH(sec);
+
+	ret = srpt_SetTargetState(hca, B_TRUE);
+
+	return (ret);
+}
+
+static int
+disable_target(char *hca)
+{
+	int		ret;
+	char		*sec = "solaris.smf.modify.stmf";
+
+	SRPTADM_CHKAUTH(sec);
+
+	ret = srpt_SetTargetState(hca, B_FALSE);
+
+	return (ret);
+}
+
+static int
+reset_target(char *hca)
+{
+	int		ret;
+	char		*sec = "solaris.smf.modify.stmf";
+
+	SRPTADM_CHKAUTH(sec);
+
+	ret = srpt_ResetTarget(hca);
+
+	return (ret);
+}
+
+static int
+list_defaults(void)
+{
+	int		ret;
+	char		*sec = "solaris.smf.read.stmf";
+	boolean_t	enabled;
+
+	SRPTADM_CHKAUTH(sec);
+
+	/* only state set as default for now */
+	ret = srpt_GetDefaultState(&enabled);
+
+	if (ret == 0) {
+		(void) printf("%s:\n\n",
+		    gettext("SRP Target Service Default Properties"));
+
+		(void) printf("    %s:\t",
+		    gettext("Target creation enabled by default"));
+
+		if (enabled) {
+			(void) printf("%s\n", gettext("true"));
+		} else {
+			(void) printf("%s\n", gettext("false"));
+		}
+	}
+
+	return (ret);
+}
+
+static int
+list_target(char *hca)
+{
+	int		ret;
+	char		*sec = "solaris.smf.read.stmf";
+	char		*hcaArr[1024];	/* way bigger than we'll ever see */
+	int		i;
+
+	SRPTADM_CHKAUTH(sec);
+
+	if (hca != NULL) {
+		ret = print_target_props(hca);
+		return (ret);
+	}
+
+	/* get list of HCAs configured on this system, from /dev/cfg */
+	(void) memset(&hcaArr, 0, 1024 * sizeof (char *));
+
+	ret = get_local_hcas(hcaArr, sizeof (hcaArr));
+	if (ret == ETOOMANYREFS) {
+		(void) fprintf(stderr, "Internal error:  too many HCAs\n");
+		goto done;
+	} else if (ret != 0) {
+		(void) fprintf(stderr, "Error getting list of HCAs: %d\n", ret);
+		goto done;
+	}
+
+	for (i = 0; i < 1024; i++) {
+		if (hcaArr[i] == NULL) {
+			break;
+		}
+		ret = print_target_props(hcaArr[i]);
+	}
+
+done:
+	for (i = 0; i < 1024; i++) {
+		if (hcaArr[i] == NULL) {
+			break;
+		}
+		free(hcaArr[i]);
+	}
+
+	return (ret);
+}
+
+static int
+print_target_props(char *hca)
+{
+	int		ret;
+	boolean_t	enabled;
+	char		buf[32];
+	char		euibuf[64];
+	uint64_t	hcaguid;
+	stmfDevid	devid;
+	stmfTargetProperties	props;
+	char		*state;
+
+	ret = srpt_NormalizeGuid(hca, buf, sizeof (buf), &hcaguid);
+	if (ret != 0) {
+		(void) fprintf(stderr, "Invalid target HCA: %s\n",
+		    hca);
+		return (ret);
+	}
+
+	/* only property set is enabled */
+	ret = srpt_GetTargetState(buf, &enabled);
+	if (ret != 0) {
+		(void) fprintf(stderr,
+		    "Could not get enabled state for %s: %d\n",
+		    buf, ret);
+		return (ret);
+	}
+
+	(void) printf("Target HCA %s:\n", buf);
+
+	(void) printf(PROPS_FORMAT, gettext("Enabled"));
+
+	if (enabled) {
+		(void) printf("%s\n", gettext("true"));
+	} else {
+		(void) printf("%s\n", gettext("false"));
+	}
+
+	state = "-";
+
+	(void) snprintf(euibuf, sizeof (euibuf), "eui.%016llX", hcaguid);
+
+	ret = stmfDevidFromIscsiName(euibuf, &devid);
+	if (ret == STMF_STATUS_SUCCESS) {
+		ret = stmfGetTargetProperties(&devid, &props);
+		if (ret == STMF_STATUS_SUCCESS) {
+			if (props.status == STMF_TARGET_PORT_ONLINE) {
+				state = "online";
+			} else {
+				state = "offline";
+			}
+		}
+	}
+
+	(void) printf(PROPS_FORMAT, gettext("SRP Target Name"));
+	(void) printf("%s\n", euibuf);
+	(void) printf(PROPS_FORMAT, gettext("Operational Status"));
+	(void) printf("%s\n", state);
+
+	(void) printf("\n");
+
+	return (0);
+}
+
+
+static int
+get_local_hcas(char **hcaArray, int count)
+{
+	int		ret = 0;
+	char		*cfgdir = "/dev/cfg";
+	DIR		*dirp = NULL;
+	struct dirent	*entry;
+	int		idx = 0;
+	char		*bufp;
+
+	if ((hcaArray == NULL) || (count == 0)) {
+		return (EINVAL);
+	}
+
+	dirp = opendir(cfgdir);
+
+	if (dirp == NULL) {
+		ret = errno;
+		(void) fprintf(stderr, "Could not open %s: errno %d\n",
+		    cfgdir, ret);
+		return (ret);
+	}
+
+	while ((entry = readdir(dirp)) != NULL) {
+		bufp = &entry->d_name[0];
+
+		if (strncmp(bufp, "hca:", 4) != 0) {
+			continue;
+		}
+
+		bufp += 4;
+
+		hcaArray[idx] = strdup(bufp);
+		if (hcaArray[idx] == NULL) {
+			ret = ENOMEM;
+			break;
+		}
+		idx++;
+
+		if (idx >= count) {
+			ret = ETOOMANYREFS;
+			break;
+		}
+	}
+
+	return (ret);
+}
--- a/usr/src/lib/Makefile	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/lib/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -19,8 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 include ../Makefile.master
@@ -154,6 +153,7 @@
 	krb5	.WAIT	\
 	libsmbfs	\
 	libfcoe		\
+	libsrpt		\
 	libstmf		\
 	libstmfproxy	\
 	libnsctl	\
@@ -460,6 +460,7 @@
 	libsocket	\
 	libsqlite	\
 	libfcoe		\
+	libsrpt		\
 	libstmf		\
 	libstmfproxy	\
 	libsum		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,53 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS =		libsrpt.h
+HDRDIR =	common
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all :=		TARGET= all
+clean :=	TARGET= clean
+clobber :=	TARGET= clobber
+install :=	TARGET= install
+install_h :=	TARGET= install_h
+lint :=		TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+	@cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/Makefile.com	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,51 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+LIBRARY =	libsrpt.a
+VERS =		.1
+OBJECTS =	libsrpt.o
+
+include ../../Makefile.lib
+
+LIBS =		$(DYNLIB) $(LINTLIB)
+
+SRCDIR =	../common
+$(LINTLIB):=	SRCS = $(SRCDIR)/$(LINTSRC)
+
+SRPTMODDIR =	../../../uts/common/io/comstar/port/srpt
+
+INCS +=		-I$(SRCDIR) -I$(SRPTMODDIR)
+
+C99MODE =	-xc99=%all
+C99LMODE =	-Xc99=%all
+LDLIBS +=	-lc -lnvpair -lstmf
+CPPFLAGS +=	$(INCS) -D_REENTRANT
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/amd64/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,29 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/common/libsrpt.c	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,493 @@
+/*
+ * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <strings.h>
+#include <libintl.h>
+#include <libscf.h>
+#include <libnvpair.h>
+
+#include <libstmf.h>
+#include <libsrpt.h>
+
+#include "srpt_common.h"
+
+#define	SRPT_PROV_NAME	"srpt"
+
+/*
+ * Function:  srpt_GetConfig()
+ *
+ * Parameters:
+ *    cfg	Current SRPT configuration in nvlist form
+ *    token	Configuration generation number.  Use this token
+ *		if updating the configuration with srpt_SetConfig.
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_GetConfig(nvlist_t **cfg, uint64_t *token)
+{
+	int		ret = 0;
+	nvlist_t	*cfg_nv = NULL;
+	uint64_t	stmf_token = 0;
+	nvlist_t	*hcanv = NULL;
+
+	if (!cfg) {
+		return (EINVAL);
+	}
+
+	*cfg = NULL;
+
+	ret = stmfGetProviderDataProt(SRPT_PROV_NAME, &cfg_nv,
+	    STMF_PORT_PROVIDER_TYPE, &stmf_token);
+
+	if (ret == STMF_STATUS_SUCCESS) {
+		ret = 0;
+	} else if (ret == STMF_ERROR_NOT_FOUND) {
+		/* Not initialized yet */
+		ret = nvlist_alloc(&cfg_nv, NV_UNIQUE_NAME, 0);
+		if (ret != 0) {
+			return (ret);
+		}
+		/* create the HCA list */
+		ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0);
+		if (ret == 0) {
+			ret = nvlist_add_nvlist(cfg_nv, SRPT_PROP_HCALIST,
+			    hcanv);
+			if (ret != 0) {
+				nvlist_free(hcanv);
+			}
+		}
+		if (ret != 0) {
+			nvlist_free(cfg_nv);
+			cfg_nv = NULL;
+		}
+	} else if (ret == STMF_ERROR_NOMEM) {
+		ret = ENOMEM;
+	} else {
+		ret = EINVAL;
+	}
+
+	*cfg = cfg_nv;
+	*token = stmf_token;
+
+	return (ret);
+}
+
+/*
+ * Function:  srpt_SetConfig()
+ *
+ * Parameters:
+ *    cfg	SRPT configuration in nvlist form
+ *    token	Configuration generation number from srpt_GetConfig.
+ *		Use this token to ensure the configuration hasn't been
+ *		updated by another user since the time it was fetched.
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ *    ECANCELED Configuration updated by another user
+ */
+int
+srpt_SetConfig(nvlist_t *cfg, uint64_t token)
+{
+	int		ret = 0;
+
+	ret = stmfSetProviderDataProt(SRPT_PROV_NAME, cfg,
+	    STMF_PORT_PROVIDER_TYPE, &token);
+
+	if (ret == STMF_STATUS_SUCCESS) {
+		ret = 0;
+	} else if (ret == STMF_ERROR_NOMEM) {
+		ret = ENOMEM;
+	} else if (ret == STMF_ERROR_PROV_DATA_STALE) {
+		ret = ECANCELED;  /* could be a better errno */
+	} else {
+		ret = EINVAL;
+	}
+
+	return (ret);
+}
+
+/*
+ * Function:  srpt_GetDefaultState()
+ *
+ * Parameters:
+ *    enabled	If B_TRUE, indicates that targets will be created for all
+ *		discovered HCAs that have not been specifically disabled.
+ *		If B_FALSE, targets will not be created unless the HCA has
+ *		been specifically enabled.  See also srpt_SetDefaultState().
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_GetDefaultState(boolean_t *enabled)
+{
+	int		ret;
+	nvlist_t	*cfgnv;
+	uint64_t	token;
+	boolean_t	val = B_TRUE;
+
+	if (enabled == NULL) {
+		return (EINVAL);
+	}
+
+	ret = srpt_GetConfig(&cfgnv, &token);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	if (cfgnv != NULL) {
+		ret = nvlist_lookup_boolean_value(cfgnv,
+		    SRPT_PROP_DEFAULT_ENABLED, &val);
+
+		if (ret == ENOENT) {
+			ret = 0;
+		}
+	}
+
+	*enabled = val;
+	return (ret);
+}
+
+/*
+ * Function:  srpt_SetDefaultState()
+ *
+ * Parameters:
+ *    enabled	If B_TRUE, indicates that targets will be created for all
+ *		discovered HCAs that have not been specifically disabled.
+ *		If B_FALSE, targets will not be created unless the HCA has
+ *		been specifically enabled.  See also srpt_SetDefaultState().
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_SetDefaultState(boolean_t enabled)
+{
+	int		ret;
+	nvlist_t	*cfgnv;
+	uint64_t	token;
+
+	ret = srpt_GetConfig(&cfgnv, &token);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	if (cfgnv == NULL) {
+		ret = nvlist_alloc(&cfgnv, NV_UNIQUE_NAME, 0);
+		if (ret != 0) {
+			return (ret);
+		}
+	}
+
+	ret = nvlist_add_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED,
+	    enabled);
+
+	if (ret == 0) {
+		ret = srpt_SetConfig(cfgnv, token);
+	}
+
+	nvlist_free(cfgnv);
+
+	return (ret);
+}
+
+/*
+ * Function:  srpt_SetTargetState()
+ *
+ * Parameters:
+ *    hca_guid	HCA GUID.  See description of srpt_NormalizeGuid
+ *    enabled	If B_TRUE, indicates that a target will be created for
+ *		this HCA when the SRPT SMF service is enabled.  If B_FALSE,
+ *		a target will not be created
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_SetTargetState(char *hca_guid, boolean_t enabled)
+{
+	int		ret;
+	nvlist_t	*cfgnv;
+	uint64_t	token;
+	nvlist_t	*hcalist;
+	nvlist_t	*hcanv;
+	char		guid[32];
+	uint64_t	hcaguid;
+
+	if (hca_guid == NULL) {
+		return (EINVAL);
+	}
+
+	ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), &hcaguid);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	ret = srpt_GetConfig(&cfgnv, &token);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	/* get the list of HCAs */
+	ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
+	if (ret != 0) {
+		nvlist_free(cfgnv);
+		return (ret);
+	}
+
+	ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv);
+	if (ret == ENOENT) {
+		/* no entry yet */
+		ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0);
+		if (ret == 0) {
+			ret = nvlist_add_uint64(hcanv, SRPT_PROP_GUID, hcaguid);
+		}
+	}
+
+	if (ret == 0) {
+		ret = nvlist_add_boolean_value(hcanv, SRPT_PROP_ENABLED,
+		    enabled);
+	}
+
+	if (ret == 0) {
+		ret = nvlist_add_nvlist(hcalist, guid, hcanv);
+	}
+
+	if (ret == 0) {
+		ret = srpt_SetConfig(cfgnv, token);
+	}
+
+	nvlist_free(cfgnv);
+
+	return (ret);
+}
+
+/*
+ * Function:  srpt_GetTargetState()
+ *
+ * Parameters:
+ *    hca_guid	HCA GUID.  See description of srpt_NormalizeGuid
+ *    enabled	If B_TRUE, indicates that a target will be created for
+ *		this HCA when the SRPT SMF service is enabled.  If B_FALSE,
+ *		a target will not be created
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_GetTargetState(char *hca_guid, boolean_t *enabled)
+{
+	int		ret;
+	nvlist_t	*cfgnv;
+	uint64_t	token;
+	nvlist_t	*hcalist;
+	nvlist_t	*hcanv;
+	boolean_t	defaultState = B_TRUE;
+	char		guid[32];
+
+	if (hca_guid == NULL) {
+		return (EINVAL);
+	}
+
+	ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	ret = srpt_GetConfig(&cfgnv, &token);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	/* get the list of HCAs */
+	ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
+	if (ret != 0) {
+		nvlist_free(cfgnv);
+		return (ret);
+	}
+
+	/*
+	 * Find the default, for the likely case that this HCA isn't
+	 * explicitly set.
+	 */
+	(void) nvlist_lookup_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED,
+	    &defaultState);
+
+	ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv);
+	if (ret == 0) {
+		ret = nvlist_lookup_boolean_value(hcanv, SRPT_PROP_ENABLED,
+		    enabled);
+	}
+
+	if (ret == ENOENT) {
+		/* not explicitly set, use the default */
+		*enabled = defaultState;
+		ret = 0;
+	}
+
+	nvlist_free(cfgnv);
+
+	return (ret);
+
+}
+
+/*
+ * Function:  srpt_ResetTarget()
+ *
+ * Clears the HCA-specific configuration.  Target creation will revert to
+ * the default.
+ *
+ * Parameters:
+ *    hca_guid	HCA GUID.  See description of srpt_NormalizeGuid
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_ResetTarget(char *hca_guid)
+{
+	int		ret;
+	nvlist_t	*cfgnv;
+	nvlist_t	*hcalist;
+	uint64_t	token;
+	char		guid[32];
+
+	if (hca_guid == NULL) {
+		return (EINVAL);
+	}
+
+	ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	ret = srpt_GetConfig(&cfgnv, &token);
+	if (ret != 0) {
+		return (ret);
+	}
+
+	/* get the list of HCAs */
+	ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
+	if (ret != 0) {
+		nvlist_free(cfgnv);
+		return (ret);
+	}
+
+	/* don't set config if we don't actually change anything */
+	if (nvlist_exists(hcalist, guid)) {
+		(void) nvlist_remove_all(hcalist, guid);
+
+		if (ret == 0) {
+			ret = srpt_SetConfig(cfgnv, token);
+		}
+	}
+
+	nvlist_free(cfgnv);
+
+	return (ret);
+}
+
+/*
+ * srpt_NormalizeGuid()
+ *
+ * Parameters:
+ *    in	HCA GUID.  Must be in one of the following forms:
+ *		    3BA000100CD18	- base hex form
+ *		    0003BA000100CD18	- base hex form with leading zeroes
+ *		    hca:3BA000100CD18	- form from cfgadm and/or /dev/cfg
+ *		    eui.0003BA000100CD18 - EUI form
+ *
+ *    buf	Buffer to hold normalized guid string.  Must be at least
+ *		17 chars long.
+ *    buflen	Length of provided buffer
+ *    int_guid	Optional.  If not NULL, the integer form of the GUID will also
+ *		be returned.
+ * Return Values:
+ *    0		Success
+ *    EINVAL	Invalid HCA GUID or invalid parameter.
+ */
+int
+srpt_NormalizeGuid(char *in, char *buf, size_t buflen, uint64_t *int_guid)
+{
+	uint64_t	guid;
+	char		*bufp = in;
+	char		*end = NULL;
+
+	if ((in == NULL) || (buf == NULL)) {
+		return (EINVAL);
+	}
+
+	if (strncasecmp(bufp, "eui.", 4) == 0) {
+		/* EUI form */
+		bufp += 4;
+	} else if (strncasecmp(bufp, "hca:", 4) == 0) {
+		/* cfgadm and /dev/hca form */
+		bufp += 4;
+	}
+
+	/*
+	 * strtoull() does not return EINVAL as documented.  Lucky
+	 * for us, neither 0 nor ULLONG_MAX will be valid.  Trap on
+	 * those and fail.
+	 */
+	guid = strtoull(bufp, &end, 16);
+	if ((guid == 0) || (guid == ULLONG_MAX) ||
+	    ((end != NULL) && (strlen(end) > 0))) {
+		return (EINVAL);
+	}
+
+#if 0
+	(void) snprintf(buf, buflen, "%llX", guid);
+#endif
+	SRPT_FORMAT_HCAKEY(buf, buflen, guid);
+
+	if (int_guid) {
+		*int_guid = guid;
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/common/libsrpt.h	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,180 @@
+/*
+ * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef	_LIBSRPT_H
+#define	_LIBSRPT_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <libnvpair.h>
+
+/*
+ * Function:  srpt_GetConfig()
+ *
+ * Parameters:
+ *    cfg	Current SRPT configuration in nvlist form
+ *    token	Configuration generation number.  Use this token
+ *		if updating the configuration with srpt_SetConfig.
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_GetConfig(nvlist_t **cfg, uint64_t *token);
+
+/*
+ * Function:  srpt_SetConfig()
+ *
+ * Parameters:
+ *    cfg	SRPT configuration in nvlist form
+ *    token	Configuration generation number from srpt_GetConfig.
+ *		Use this token to ensure the configuration hasn't been
+ *		updated by another user since the time it was fetched.
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ *    ECANCELED Configuration updated by another user
+ */
+int
+srpt_SetConfig(nvlist_t *cfg, uint64_t token);
+
+/*
+ * Function:  srpt_GetDefaultState()
+ *
+ * Parameters:
+ *    enabled	If B_TRUE, indicates that targets will be created for all
+ *		discovered HCAs that have not been specifically disabled.
+ *		If B_FALSE, targets will not be created unless the HCA has
+ *		been specifically enabled.  See also srpt_SetDefaultState().
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_GetDefaultState(boolean_t *enabled);
+
+/*
+ * Function:  srpt_SetDefaultState()
+ *
+ * Parameters:
+ *    enabled	If B_TRUE, indicates that targets will be created for all
+ *		discovered HCAs that have not been specifically disabled.
+ *		If B_FALSE, targets will not be created unless the HCA has
+ *		been specifically enabled.  See also srpt_SetDefaultState().
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_SetDefaultState(boolean_t enabled);
+
+/*
+ * Function:  srpt_SetTargetState()
+ *
+ * Parameters:
+ *    hca_guid	HCA GUID.  See description of srpt_NormalizeGuid
+ *    enabled	If B_TRUE, indicates that a target will be created for
+ *		this HCA when the SRPT SMF service is enabled.  If B_FALSE,
+ *		a target will not be created
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_SetTargetState(char *hca_guid, boolean_t enabled);
+
+/*
+ * Function:  srpt_GetTargetState()
+ *
+ * Parameters:
+ *    hca_guid	HCA GUID.  See description of srpt_NormalizeGuid
+ *    enabled	If B_TRUE, indicates that a target will be created for
+ *		this HCA when the SRPT SMF service is enabled.  If B_FALSE,
+ *		a target will not be created
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_GetTargetState(char *hca_guid, boolean_t *enabled);
+
+/*
+ * Function:  srpt_ResetTarget()
+ *
+ * Clears the HCA-specific configuration.  Target creation will revert to
+ * the default.
+ *
+ * Parameters:
+ *    hca_guid	HCA GUID.  See description of srpt_NormalizeGuid
+ *
+ * Return Values:
+ *    0		Success
+ *    ENOMEM	Could not allocate resources
+ *    EINVAL	Invalid parameter
+ */
+int
+srpt_ResetTarget(char *hca_guid);
+
+/*
+ * srpt_NormalizeGuid()
+ *
+ * Parameters:
+ *    in	HCA GUID.  Must be in one of the following forms:
+ *		    3BA000100CD18	- base hex form
+ *		    0003BA000100CD18	- base hex form with leading zeroes
+ *		    hca:3BA000100CD18	- form from cfgadm and/or /dev/cfg
+ *		    eui.0003BA000100CD18 - EUI form
+ *
+ *    buf	Buffer to hold normalized guid string.  Must be at least
+ *		17 chars long.
+ *    buflen	Length of provided buffer
+ *    int_guid	Optional.  If not NULL, the integer form of the GUID will also
+ *		be returned.
+ * Return Values:
+ *    0		Success
+ *    EINVAL	Invalid HCA GUID or invalid parameter.
+ */
+int
+srpt_NormalizeGuid(char *in, char *buf, size_t buflen, uint64_t *int_guid);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LIBSRPT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/common/llib-lsrpt	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,28 @@
+/*
+ * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <libsrpt.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/common/mapfile-vers	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,56 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+#	usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+SUNW_1.1 {
+	global:
+		srpt_GetConfig;
+		srpt_SetConfig;
+		srpt_GetDefaultState;
+		srpt_SetDefaultState;
+		srpt_SetTargetState;
+		srpt_GetTargetState;
+		srpt_ResetTarget;
+		srpt_NormalizeGuid;
+	local:
+		*;
+};
+
+SUNWprivate {
+	global:
+	local:
+	    *;
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/i386/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,26 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/sparc/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,27 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+include ../Makefile.com
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsrpt/sparcv9/Makefile	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,32 @@
+#
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- a/usr/src/pkg/manifests/driver-network-srpt.mf	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/pkg/manifests/driver-network-srpt.mf	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
 #
 
 #
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/driver/network/srpt@$(PKGVERS)
@@ -44,10 +43,13 @@
 dir path=lib/svc opensolaris.zone=global variant.opensolaris.zone=global
 dir path=lib/svc/method opensolaris.zone=global variant.opensolaris.zone=global
 dir path=usr group=sys
+dir path=usr/include
 dir path=usr/lib
+dir path=usr/lib/$(ARCH64)
 dir path=usr/lib/mdb group=sys
 dir path=usr/lib/mdb/kvm group=sys
 dir path=usr/lib/mdb/kvm/$(ARCH64) group=sys
+dir path=usr/sbin
 dir path=lib/svc/manifest group=sys opensolaris.zone=global \
     variant.opensolaris.zone=global
 dir path=lib/svc/manifest/system group=sys opensolaris.zone=global \
@@ -67,10 +69,19 @@
     opensolaris.zone=global reboot-needed=true variant.opensolaris.zone=global
 file path=lib/svc/method/svc-srpt mode=0555 opensolaris.zone=global \
     variant.opensolaris.zone=global
+file path=usr/include/libsrpt.h
+file path=usr/lib/$(ARCH64)/libsrpt.so.1
+file path=usr/lib/$(ARCH64)/llib-lsrpt.ln
+file path=usr/lib/libsrpt.so.1
+file path=usr/lib/llib-lsrpt
+file path=usr/lib/llib-lsrpt.ln
 file path=usr/lib/mdb/kvm/$(ARCH64)/srpt.so group=sys mode=0555
 $(i386_ONLY)file path=usr/lib/mdb/kvm/srpt.so group=sys mode=0555
+file path=usr/sbin/srptadm mode=0555
 file path=lib/svc/manifest/system/ibsrp/target.xml group=sys mode=0444 \
     opensolaris.zone=global variant.opensolaris.zone=global
+link path=usr/lib/libsrpt.so target=libsrpt.so.1
+link path=usr/lib/$(ARCH64)/libsrpt.so target=libsrpt.so.1
 legacy pkg=SUNWsrptr arch=$(ARCH) category=system \
     desc="Sun SRP COMSTAR Port Provider (Root)" \
     hotline="Please contact your local service provider" \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h	Mon Apr 05 15:20:40 2010 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _SRPT_COMMON_H_
+#define	_SRPT_COMMON_H_
+
+/*
+ * Definitions common to both the SRP Target kernel module and the
+ * user-space library and administrative command.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Configuration nvlist keys */
+
+#define	SRPT_PROP_HCALIST		"HCAs"
+#define	SRPT_PROP_DEFAULT_ENABLED	"default_enabled"
+#define	SRPT_PROP_GUID			"guid"
+#define	SRPT_PROP_ENABLED		"enabled"
+
+/* Format the HCA key */
+#define	SRPT_FORMAT_HCAKEY(b, l, g) \
+	((void) snprintf(b, l, "%llX", g))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SRPT_COMMON_H_ */
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _SRPT_IMPL_H_
@@ -446,6 +445,12 @@
 
 	/* IBDMA entry points */
 	srpt_ibdma_ops_t		sc_ibdma_ops;
+
+	/*
+	 *  List of explicitly configured HCAs and their configurable
+	 *  attributes.
+	 */
+	nvlist_t			*sc_cfg_hca_nv;
 } srpt_ctxt_t;
 
 typedef struct srpt_iu_data_s {
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -43,15 +42,17 @@
 #include "srpt_ioc.h"
 #include "srpt_stp.h"
 #include "srpt_ch.h"
+#include "srpt_common.h"
 
 /*
  * srpt_ioc_srq_size - Tunable parameter that specifies the number
  * of receive WQ entries that can be posted to the IOC shared
  * receive queue.
  */
-uint32_t	srpt_ioc_srq_size = SRPT_DEFAULT_IOC_SRQ_SIZE;
-extern uint16_t srpt_send_msg_depth;
-extern uint32_t	srpt_iu_size;
+uint32_t		srpt_ioc_srq_size = SRPT_DEFAULT_IOC_SRQ_SIZE;
+extern uint16_t		srpt_send_msg_depth;
+extern uint32_t		srpt_iu_size;
+extern boolean_t	srpt_enable_by_default;
 
 /* IOC profile capabilities mask must be big-endian */
 typedef struct srpt_ioc_opcap_bits_s {
@@ -115,6 +116,7 @@
 
 static srpt_ioc_t *srpt_ioc_init(ib_guid_t guid);
 static void srpt_ioc_fini(srpt_ioc_t *ioc);
+static boolean_t srpt_check_hca_cfg_enabled(ib_guid_t hca_guid);
 
 static srpt_vmem_pool_t *srpt_vmem_create(const char *name, srpt_ioc_t *ioc,
     ib_memlen_t chunksize, uint64_t maxsize, ibt_mr_flags_t flags);
@@ -144,7 +146,6 @@
 	int		hca_cnt;
 	int		hca_ndx;
 	ib_guid_t	*guid;
-	srpt_ioc_t	*ioc;
 
 	ASSERT(srpt_ctxt != NULL);
 
@@ -171,19 +172,9 @@
 	}
 
 	for (hca_ndx = 0; hca_ndx < hca_cnt; hca_ndx++) {
-		SRPT_DPRINTF_L2("ioc_attach, adding I/O"
-		    " Controller (%016llx)", (u_longlong_t)guid[hca_ndx]);
-
-		ioc = srpt_ioc_init(guid[hca_ndx]);
-		if (ioc == NULL) {
-			SRPT_DPRINTF_L1("ioc_attach, ioc_init GUID(%016llx)"
-			    " failed", (u_longlong_t)guid[hca_ndx]);
-			continue;
-		}
-		list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc);
-		SRPT_DPRINTF_L2("ioc_attach, I/O Controller ibt HCA hdl (%p)",
-		    (void *)ioc->ioc_ibt_hdl);
-		srpt_ctxt->sc_num_iocs++;
+		SRPT_DPRINTF_L2("ioc_attach, attaching HCA %016llx",
+		    (u_longlong_t)guid[hca_ndx]);
+		srpt_ioc_attach_hca(guid[hca_ndx], B_FALSE);
 	}
 
 	ibt_free_hca_list(guid, hca_cnt);
@@ -193,6 +184,156 @@
 }
 
 /*
+ * Initialize I/O Controllers.  sprt_ctxt->sc_rwlock must be locked by the
+ * caller.
+ *
+ * 'checked' indicates no need to lookup the hca in the HCA configuration
+ * list.
+ */
+void
+srpt_ioc_attach_hca(ib_guid_t hca_guid, boolean_t checked)
+{
+	boolean_t	enable_hca = B_TRUE;
+	srpt_ioc_t	*ioc;
+
+	if (!checked) {
+		enable_hca = srpt_check_hca_cfg_enabled(hca_guid);
+
+		if (!enable_hca) {
+			/* nothing to do */
+			SRPT_DPRINTF_L2(
+			    "ioc_attach_hca, HCA %016llx disabled "
+			    "by srpt config",
+			    (u_longlong_t)hca_guid);
+			return;
+		}
+	}
+
+	SRPT_DPRINTF_L2("ioc_attach_hca, adding I/O"
+	    " Controller (%016llx)", (u_longlong_t)hca_guid);
+
+	ioc = srpt_ioc_init(hca_guid);
+	if (ioc == NULL) {
+		/*
+		 * IOC already exists or an error occurred.  Already
+		 * logged by srpt_ioc_init()
+		 */
+		return;
+	}
+
+	/*
+	 * Create the COMSTAR SRP Target for this IOC.  If this fails,
+	 * remove the IOC.
+	 */
+	rw_enter(&ioc->ioc_rwlock, RW_WRITER);
+	ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid);
+	if (ioc->ioc_tgt_port == NULL) {
+		SRPT_DPRINTF_L1("ioc_attach_hca: alloc SCSI"
+		    " Target Port error on GUID(%016llx)",
+		    (u_longlong_t)ioc->ioc_guid);
+		rw_exit(&ioc->ioc_rwlock);
+		srpt_ioc_fini(ioc);
+		return;
+	}
+	rw_exit(&ioc->ioc_rwlock);
+
+	/*
+	 * New HCA added with default SCSI Target Port, SRP service
+	 * will be started when SCSI Target Port is brought
+	 * on-line by STMF.
+	 */
+	list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc);
+	SRPT_DPRINTF_L2("ioc_attach_hca, I/O Controller ibt HCA hdl (%p)",
+	    (void *)ioc->ioc_ibt_hdl);
+
+	srpt_ctxt->sc_num_iocs++;
+}
+
+/*
+ * srpt_check_hca_cfg_enabled()
+ *
+ * Function to check the configuration for the enabled status of a given
+ * HCA.  Returns B_TRUE if SRPT services should be activated for this HCA,
+ * B_FALSE if it should be disabled.
+ */
+static boolean_t
+srpt_check_hca_cfg_enabled(ib_guid_t hca_guid)
+{
+	int		status;
+	char		buf[32];
+	nvlist_t	*hcanv;
+	boolean_t	enable_hca;
+
+	enable_hca = srpt_enable_by_default;
+
+	SRPT_FORMAT_HCAKEY(buf, sizeof (buf), (u_longlong_t)hca_guid);
+
+	if (srpt_ctxt->sc_cfg_hca_nv != NULL) {
+		status = nvlist_lookup_nvlist(srpt_ctxt->sc_cfg_hca_nv,
+		    buf, &hcanv);
+		if (status == 0) {
+			SRPT_DPRINTF_L3("check_hca_cfg, found guid %s",  buf);
+			(void) nvlist_lookup_boolean_value(hcanv,
+			    SRPT_PROP_ENABLED, &enable_hca);
+		} else {
+			SRPT_DPRINTF_L3("check_hca_cfg, did not find guid %s",
+			    buf);
+		}
+	}
+
+	return (enable_hca);
+}
+
+/*
+ * srpt_ioc_update()
+ *
+ * Using the configuration nvlist, enables or disables SRP services
+ * the provided HCAs.  srpt_ctxt->sc_rwlock should be held outside of this call.
+ */
+void
+srpt_ioc_update(void)
+{
+	boolean_t	enabled;
+	nvpair_t	*nvp = NULL;
+	uint64_t	hca_guid;
+	nvlist_t	*nvl;
+	nvlist_t	*cfg = srpt_ctxt->sc_cfg_hca_nv;
+
+	if (cfg == NULL) {
+		SRPT_DPRINTF_L2("ioc_update, no configuration data");
+		return;
+	}
+
+	while ((nvp = nvlist_next_nvpair(cfg, nvp)) != NULL) {
+		enabled = srpt_enable_by_default;
+
+		if ((nvpair_value_nvlist(nvp, &nvl)) != 0) {
+			SRPT_DPRINTF_L2("ioc_update, did not find an nvlist");
+			continue;
+		}
+
+		if ((nvlist_lookup_uint64(nvl, SRPT_PROP_GUID, &hca_guid))
+		    != 0) {
+			SRPT_DPRINTF_L2("ioc_update, did not find a guid");
+			continue;
+		}
+
+		(void) nvlist_lookup_boolean_value(nvl, SRPT_PROP_ENABLED,
+		    &enabled);
+
+		if (enabled) {
+			SRPT_DPRINTF_L2("ioc_update, enabling guid %016llx",
+			    (u_longlong_t)hca_guid);
+			srpt_ioc_attach_hca(hca_guid, B_TRUE);
+		} else {
+			SRPT_DPRINTF_L2("ioc_update, disabling guid %016llx",
+			    (u_longlong_t)hca_guid);
+			srpt_ioc_detach_hca(hca_guid);
+		}
+	}
+}
+
+/*
  * srpt_ioc_detach() - I/O Controller detach
  *
  * srpt_ctxt->sc_rwlock should be held outside of this call.
@@ -202,23 +343,79 @@
 {
 	srpt_ioc_t	*ioc;
 
-	ASSERT(srpt_ctxt != NULL);
-
+	/*
+	 * All SRP targets must be destroyed before calling this
+	 * function.
+	 */
 	while ((ioc = list_head(&srpt_ctxt->sc_ioc_list)) != NULL) {
-		list_remove(&srpt_ctxt->sc_ioc_list, ioc);
 		SRPT_DPRINTF_L2("ioc_detach, removing I/O Controller(%p)"
 		    " (%016llx), ibt_hdl(%p)",
 		    (void *)ioc,
 		    ioc ? (u_longlong_t)ioc->ioc_guid : 0x0ll,
 		    (void *)ioc->ioc_ibt_hdl);
+
+		list_remove(&srpt_ctxt->sc_ioc_list, ioc);
+		ASSERT(ioc->ioc_tgt_port != NULL);
 		srpt_ioc_fini(ioc);
+		srpt_ctxt->sc_num_iocs--;
 	}
 
-	(void) ibt_detach(srpt_ctxt->sc_ibt_hdl);
 	srpt_ctxt->sc_ibt_hdl = NULL;
 }
 
 /*
+ * srpt_ioc_detach_hca()
+ *
+ * Stop SRP Target services on this HCA
+ *
+ * Note that this is not entirely synchronous with srpt_ioc_attach_hca()
+ * in that we don't need to check the configuration to know whether to
+ * disable an HCA.  We get here either because the IB framework has told
+ * us the HCA has been detached, or because the administrator has explicitly
+ * disabled this HCA.
+ *
+ * Must be called with srpt_ctxt->sc_rwlock locked as RW_WRITER.
+ */
+void
+srpt_ioc_detach_hca(ib_guid_t hca_guid)
+{
+	srpt_ioc_t		*ioc;
+	srpt_target_port_t	*tgt;
+	stmf_status_t		stmf_status = STMF_SUCCESS;
+
+	ioc = srpt_ioc_get_locked(hca_guid);
+	if (ioc == NULL) {
+		/* doesn't exist, nothing to do */
+		return;
+	}
+
+	rw_enter(&ioc->ioc_rwlock, RW_WRITER);
+	tgt = ioc->ioc_tgt_port;
+
+	if (tgt != NULL) {
+		stmf_status = srpt_stp_destroy_port(tgt);
+		if (stmf_status == STMF_SUCCESS) {
+			ioc->ioc_tgt_port = NULL;
+			(void) srpt_stp_free_port(tgt);
+		}
+	}
+
+	rw_exit(&ioc->ioc_rwlock);
+
+	if (stmf_status != STMF_SUCCESS) {
+		/* should never happen */
+		return;
+	}
+
+	list_remove(&srpt_ctxt->sc_ioc_list, ioc);
+	srpt_ctxt->sc_num_iocs--;
+
+	srpt_ioc_fini(ioc);
+	SRPT_DPRINTF_L2("ioc_detach_hca, HCA %016llx detached",
+	    (u_longlong_t)hca_guid);
+}
+
+/*
  * srpt_ioc_init() - I/O Controller initialization
  *
  * Requires srpt_ctxt->rw_lock be held outside of call.
@@ -248,7 +445,7 @@
 
 	ioc = srpt_ioc_get_locked(guid);
 	if (ioc != NULL) {
-		SRPT_DPRINTF_L1("ioc_init, HCA already exists");
+		SRPT_DPRINTF_L2("ioc_init, HCA already exists");
 		return (NULL);
 	}
 
@@ -701,7 +898,6 @@
 srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl,
 	ibt_async_code_t code, ibt_async_event_t *event)
 {
-	srpt_ioc_t		*ioc;
 	srpt_channel_t		*ch;
 
 	switch (code) {
@@ -714,47 +910,26 @@
 		break;
 
 	case IBT_HCA_ATTACH_EVENT:
-		rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
-		ioc = srpt_ioc_init(event->ev_hca_guid);
-
-		if (ioc == NULL) {
-			rw_exit(&srpt_ctxt->sc_rwlock);
-			SRPT_DPRINTF_L1("ib_async_hdlr, HCA_ATTACH"
-			    " event failed to initialize HCA (0x%016llx)",
-			    (u_longlong_t)event->ev_hca_guid);
-			return;
-		}
-		SRPT_DPRINTF_L2("HCA_ATTACH_EVENT: I/O Controller"
-		    " ibt hdl (%p)",
-		    (void *)ioc->ioc_ibt_hdl);
+		SRPT_DPRINTF_L2(
+		    "ib_async_hdlr, received attach event for HCA 0x%016llx",
+		    (u_longlong_t)event->ev_hca_guid);
 
-		rw_enter(&ioc->ioc_rwlock, RW_WRITER);
-		ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid);
-		if (ioc->ioc_tgt_port == NULL) {
-			SRPT_DPRINTF_L1("ioc_ib_async_hdlr, alloc SCSI "
-			    "target port error for HCA (0x%016llx)",
-			    (u_longlong_t)event->ev_hca_guid);
-			rw_exit(&ioc->ioc_rwlock);
-			srpt_ioc_fini(ioc);
-			rw_exit(&srpt_ctxt->sc_rwlock);
-			return;
-		}
+		rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
+		srpt_ioc_attach_hca(event->ev_hca_guid, B_FALSE);
+		rw_exit(&srpt_ctxt->sc_rwlock);
 
-		/*
-		 * New HCA added with default SCSI Target Port, SRP service
-		 * will be started when SCSI Target Port is brought
-		 * on-line by STMF.
-		 */
-		srpt_ctxt->sc_num_iocs++;
-		list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc);
-
-		rw_exit(&ioc->ioc_rwlock);
-		rw_exit(&srpt_ctxt->sc_rwlock);
 		break;
 
 	case IBT_HCA_DETACH_EVENT:
 		SRPT_DPRINTF_L1(
-		    "ioc_iob_async_hdlr, HCA_DETACH_EVENT received.");
+		    "ioc_iob_async_hdlr, received HCA_DETACH_EVENT for "
+		    "HCA 0x%016llx",
+		    (u_longlong_t)event->ev_hca_guid);
+
+		rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
+		srpt_ioc_detach_hca(event->ev_hca_guid);
+		rw_exit(&srpt_ctxt->sc_rwlock);
+
 		break;
 
 	case IBT_EVENT_EMPTY_CHAN:
@@ -1445,7 +1620,7 @@
 
 	status = ibt_deregister_mr(ioc->ioc_ibt_hdl, mr->mr_hdl);
 	if (status != IBT_SUCCESS) {
-		SRPT_DPRINTF_L1("ioc_fini, error deregistering MR (%d)",
+		SRPT_DPRINTF_L1("srpt_dereg_mem, error deregistering MR (%d)",
 		    status);
 	}
 	kmem_free(mr, sizeof (srpt_mr_t));
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _SRPT_IOC_H
@@ -38,7 +37,10 @@
 #include "srpt_impl.h"
 
 int srpt_ioc_attach();
+void srpt_ioc_attach_hca(ib_guid_t hca_guid, boolean_t checked);
 void srpt_ioc_detach();
+void srpt_ioc_detach_hca(ib_guid_t hca_guid);
+void srpt_ioc_update(void);
 void srpt_ioc_init_profile(srpt_ioc_t *ioc);
 ibt_status_t srpt_ioc_svc_bind(srpt_target_port_t *tgt, uint_t portnum);
 void srpt_ioc_svc_unbind(srpt_target_port_t *tgt, uint_t portnum);
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -51,10 +50,21 @@
 #include "srpt_stp.h"
 #include "srpt_cm.h"
 #include "srpt_ioctl.h"
+#include "srpt_common.h"
 
 #define	SRPT_NAME_VERSION	"COMSTAR SRP Target"
 
 /*
+ * srpt_enable_by_default - configurable parameter that
+ * determines whether targets are created automatically for
+ * all HCAs when the service is enabled.
+ *
+ * B_TRUE is the legacy default as srpt originally shipped
+ * this way.  Changing it to false is highly desirable.
+ */
+boolean_t	srpt_enable_by_default = B_TRUE;
+
+/*
  * srpt_send_msg_depth - Tunable parameter that specifies the
  * maximum messages that could be in flight for a channel.
  */
@@ -166,6 +176,8 @@
 
 	/* Start-up state is DISABLED.  SMF will tell us if we should enable. */
 	srpt_ctxt->sc_svc_state = SRPT_SVC_DISABLED;
+	list_create(&srpt_ctxt->sc_ioc_list, sizeof (srpt_ioc_t),
+	    offsetof(srpt_ioc_t, ioc_node));
 
 	list_create(&srpt_ctxt->sc_ioc_list, sizeof (srpt_ioc_t),
 	    offsetof(srpt_ioc_t, ioc_node));
@@ -294,7 +306,6 @@
 srpt_enable_srp_services(void)
 {
 	int		status;
-	srpt_ioc_t	*ioc;
 
 	ASSERT((rw_read_locked(&srpt_ctxt->sc_rwlock)) == 0);
 
@@ -314,7 +325,9 @@
 	}
 
 	/*
-	 * Initialize IB resources, creating a list of SRP I/O Controllers.
+	 * Initialize IB resources, creating a list of SRP I/O Controllers
+	 * and for each controller, register the SCSI Target Port with STMF
+	 * and prepare profile and services.
 	 */
 	status = srpt_ioc_attach();
 	if (status != DDI_SUCCESS) {
@@ -323,32 +336,17 @@
 		goto err_exit_2;
 	}
 
-	/* Not an error if no iocs yet; we will listen for ATTACH events */
+	/*
+	 * No configured controllers is not a fatal error.  This can happen
+	 * if all HCAs are currently disabled for use by SRP.  The service
+	 * should remain running in case the user changes their mind and
+	 * enables an HCA for SRP services.
+	 */
 	if (srpt_ctxt->sc_num_iocs == 0) {
 		SRPT_DPRINTF_L2("enable_srp: no IB I/O Controllers found");
 		return (DDI_SUCCESS);
 	}
 
-	/*
-	 * For each I/O Controller register the default SCSI Target Port
-	 * with STMF, and prepare profile and services.  SRP will not
-	 * start until the associated LPORT is brought on-line.
-	 */
-	ioc = list_head(&srpt_ctxt->sc_ioc_list);
-
-	while (ioc != NULL) {
-		rw_enter(&ioc->ioc_rwlock, RW_WRITER);
-		ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid);
-		if (ioc->ioc_tgt_port == NULL) {
-			SRPT_DPRINTF_L1("enable_srp: alloc SCSI"
-			    " Target Port error on GUID(%016llx)",
-			    (u_longlong_t)ioc->ioc_guid);
-		}
-
-		rw_exit(&ioc->ioc_rwlock);
-		ioc = list_next(&srpt_ctxt->sc_ioc_list, ioc);
-	}
-
 	return (DDI_SUCCESS);
 
 err_exit_2:
@@ -383,6 +381,11 @@
 		ddi_remove_minor_node(dip, NULL);
 		srpt_ctxt->sc_dip = NULL;
 
+		if (srpt_ctxt->sc_cfg_hca_nv != NULL) {
+			nvlist_free(srpt_ctxt->sc_cfg_hca_nv);
+			srpt_ctxt->sc_cfg_hca_nv = NULL;
+		}
+
 		rw_exit(&srpt_ctxt->sc_rwlock);
 
 		break;
@@ -407,7 +410,6 @@
 srpt_disable_srp_services(void)
 {
 	stmf_status_t			stmf_status;
-	stmf_change_status_t		cstatus;
 	srpt_ioc_t			*ioc;
 	srpt_target_port_t		*tgt;
 	int				ret_status = 0;
@@ -421,57 +423,17 @@
 	ioc = list_head(&srpt_ctxt->sc_ioc_list);
 
 	while (ioc != NULL) {
-		/*
-		 * Notify STMF to take the I/O Controller SCSI Target Port(s)
-		 * off-line after we mark them as disabled so that they will
-		 * stay off-line.
-		 */
 		rw_enter(&ioc->ioc_rwlock, RW_WRITER);
 
 		tgt = ioc->ioc_tgt_port;
 		if (tgt != NULL) {
-			mutex_enter(&tgt->tp_lock);
-			tgt->tp_drv_disabled = 1;
-			mutex_exit(&tgt->tp_lock);
-
-			SRPT_DPRINTF_L2("disable_srp: unbind and de-register"
-			    " services for GUID(%016llx)",
-			    (u_longlong_t)ioc->ioc_guid);
-
-			cstatus.st_completion_status = STMF_SUCCESS;
-			cstatus.st_additional_info = NULL;
-
-			stmf_status = stmf_ctl(STMF_CMD_LPORT_OFFLINE,
-			    tgt->tp_lport, &cstatus);
-
-			/*
-			 * Wait for asynchronous target off-line operation
-			 * to complete and then deregister the target
-			 * port.
-			 */
-			mutex_enter(&tgt->tp_lock);
-			while (tgt->tp_state != SRPT_TGT_STATE_OFFLINE) {
-				cv_wait(&tgt->tp_offline_complete,
-				    &tgt->tp_lock);
-			}
-			mutex_exit(&tgt->tp_lock);
-			ioc->ioc_tgt_port = NULL;
-
-			SRPT_DPRINTF_L3("disable_srp: IOC (0x%016llx) Target"
-			    " SRP off-line complete",
-			    (u_longlong_t)ioc->ioc_guid);
-
-			stmf_status = srpt_stp_deregister_port(tgt);
-			if (stmf_status != STMF_SUCCESS) {
-				/* Fails if I/O is pending */
-				if (ret_status == 0) {
-					ret_status = EBUSY;
-				}
-				SRPT_DPRINTF_L1("disable_srp: could not"
-				    " de-register LPORT, err(0x%llx)",
-				    (u_longlong_t)stmf_status);
+			stmf_status = srpt_stp_destroy_port(tgt);
+			if (stmf_status == STMF_SUCCESS) {
+				ioc->ioc_tgt_port = NULL;
+				(void) srpt_stp_free_port(tgt);
 			} else {
-				(void) srpt_stp_free_port(tgt);
+				ret_status = DDI_FAILURE;
+				break;
 			}
 		}
 
@@ -586,11 +548,90 @@
 static void
 srpt_pp_cb(stmf_port_provider_t *pp, int cmd, void *arg, uint32_t flags)
 {
-	SRPT_DPRINTF_L3("srpt_pp_cb, invoked (%d)", cmd);
+	int		ret;
+	nvlist_t	*in_nvl = (nvlist_t *)arg;
+	nvlist_t	*nvl = NULL;
+	nvlist_t	*hcalist;
+	nvlist_t	*ctxt_nvl;
+	boolean_t	defaultEnabled = B_TRUE;
+	boolean_t	called_by_reg = B_TRUE;
+
+	SRPT_DPRINTF_L2("srpt_pp_cb, invoked (%d)", cmd);
+
+	if (cmd != STMF_PROVIDER_DATA_UPDATED) {
+		return;
+	}
+
 	/*
-	 * We don't currently utilize the port provider call-back, in the
-	 * future we might use it to synchronize provider data via STMF.
+	 * If STMF_PCB_PREG_COMPLETE is set in the flags, we're being
+	 * called back during provider registration with STMF.
+	 * (while we're calling stmf_register_port_provider()).
+	 * srpt_enable_service() already holds the sc_wrlock, and will
+	 * make sure the configuration is activated, so we just need to
+	 * set the config and get out.  If this function is called at any
+	 * time other than SRPT service start, need to grab the sc_wrlock
+	 * as WRITER.
 	 */
+	if (!(flags & STMF_PCB_PREG_COMPLETE)) {
+		SRPT_DPRINTF_L2(
+		    "srpt_pp_cb:  called after registration");
+		called_by_reg = B_FALSE;
+		rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
+	} else {
+		called_by_reg = B_TRUE;
+		SRPT_DPRINTF_L2(
+		    "srpt_pp_cb:  called as part of registration");
+	}
+
+	if (in_nvl != NULL) {
+		/* copy nvlist */
+		ret = nvlist_lookup_nvlist(in_nvl, SRPT_PROP_HCALIST, &hcalist);
+		if (ret != 0) {
+			SRPT_DPRINTF_L1(
+			    "srpt_pp_cb: Could not read hca config, err=%d",
+			    ret);
+			return;
+		}
+
+		ret = nvlist_dup(hcalist, &nvl, 0);
+		if (ret != 0) {
+			SRPT_DPRINTF_L1(
+			    "srpt_pp_cb: Could not copy hca config, err=%d",
+			    ret);
+			return;
+		}
+		if (nvlist_lookup_boolean_value(in_nvl,
+		    SRPT_PROP_DEFAULT_ENABLED, &defaultEnabled) == 0) {
+			/* set whether targets are created by default */
+			SRPT_DPRINTF_L2(
+			    "srpt_pp_cb:  setting default enabled = %d\n",
+			    (int)defaultEnabled);
+			srpt_enable_by_default = defaultEnabled;
+		}
+	} else {
+		SRPT_DPRINTF_L2(
+		    "srpt_pp_cb:  null config received");
+	}
+
+	/* put list in ctxt and set default state */
+	ctxt_nvl = srpt_ctxt->sc_cfg_hca_nv;
+
+	/* set new config, NULL is valid */
+	srpt_ctxt->sc_cfg_hca_nv = nvl;
+
+	/* free the old nvlist */
+	if (ctxt_nvl != NULL) {
+		nvlist_free(ctxt_nvl);
+	}
+
+	if (called_by_reg) {
+		return;
+	}
+
+	/* Update the HCA based on the new config */
+	srpt_ioc_update();
+
+	rw_exit(&srpt_ctxt->sc_rwlock);
 }
 
 static int
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -445,39 +444,75 @@
 }
 
 /*
- * srpt_stp_deregister_port()
+ * srpt_stp_destroy_port()
  */
 stmf_status_t
-srpt_stp_deregister_port(srpt_target_port_t *tgt)
+srpt_stp_destroy_port(srpt_target_port_t *tgt)
 {
 	stmf_status_t		status;
+	stmf_change_status_t	cstatus;
+	uint64_t		guid;
 
 	ASSERT(tgt != NULL);
 	ASSERT(tgt->tp_lport != NULL);
 
-	SRPT_DPRINTF_L3("stp_deregister_port, de-register STMF LPORT");
+	SRPT_DPRINTF_L3("stp_destroy_port, de-register STMF LPORT");
 
-retry_deregistration:
-	status = stmf_deregister_local_port(tgt->tp_lport);
-	if (status == STMF_SUCCESS) {
-		SRPT_DPRINTF_L3("stp_deregister_port, LPORT de-register"
-		    " complete");
-		return (status);
-	}
-	/*
-	 * This is only done on an administrative thread of
-	 * execution so it is ok to take a while.
-	 */
-	if (status == STMF_BUSY) {
-		delay(drv_usectohz(1000000));
-		goto retry_deregistration;
+	mutex_enter(&tgt->tp_lock);
+	if (tgt->tp_drv_disabled != 0) {
+		/* already being destroyed, get out now - should not happen */
+		mutex_exit(&tgt->tp_lock);
+		return (STMF_ALREADY);
 	}
 
+	tgt->tp_drv_disabled = 1;
+	guid = tgt->tp_ioc->ioc_guid;
+	mutex_exit(&tgt->tp_lock);
+
+	SRPT_DPRINTF_L2("stp_destroy_port: unbind and de-register"
+	    " services for GUID(%016llx)", (u_longlong_t)guid);
+
+	cstatus.st_completion_status = STMF_SUCCESS;
+	cstatus.st_additional_info = NULL;
+
+	status = stmf_ctl(STMF_CMD_LPORT_OFFLINE, tgt->tp_lport, &cstatus);
+
 	/*
-	 * Something other than a BUSY error, this should not happen.
+	 * Wait for asynchronous target off-line operation
+	 * to complete and then deregister the target
+	 * port.
 	 */
-	SRPT_DPRINTF_L1("stp_deregister_port, de-register STMF error(0x%llx)",
-	    (u_longlong_t)status);
+	mutex_enter(&tgt->tp_lock);
+	while (tgt->tp_state != SRPT_TGT_STATE_OFFLINE) {
+		cv_wait(&tgt->tp_offline_complete, &tgt->tp_lock);
+	}
+	mutex_exit(&tgt->tp_lock);
+
+	SRPT_DPRINTF_L3("stp_destroy_port: IOC (0x%016llx) Target"
+	    " SRP off-line complete", (u_longlong_t)guid);
+
+	/* loop waiting for all I/O to drain */
+	for (;;) {
+		status = stmf_deregister_local_port(tgt->tp_lport);
+		if (status == STMF_BUSY) {
+			delay(drv_usectohz(1000000));
+		} else {
+			break;
+		}
+	}
+
+	if (status == STMF_SUCCESS) {
+		SRPT_DPRINTF_L3("stp_destroy_port, LPORT de-register"
+		    " complete");
+	} else {
+		/*
+		 * Something other than a BUSY error, this should not happen.
+		 */
+		SRPT_DPRINTF_L1(
+		    "stp_destroy_port, de-register STMF error(0x%llx)",
+		    (u_longlong_t)status);
+	}
+
 	return (status);
 }
 
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h	Mon Apr 05 11:24:18 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h	Mon Apr 05 15:20:40 2010 -0400
@@ -20,8 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _SRPT_STP_H
@@ -43,7 +42,7 @@
 void srpt_stp_stop_srp(srpt_target_port_t *tgt);
 srpt_target_port_t *srpt_stp_alloc_port(srpt_ioc_t *ioc, ib_guid_t guid);
 stmf_status_t srpt_stp_free_port(srpt_target_port_t *tgt);
-stmf_status_t srpt_stp_deregister_port(srpt_target_port_t *tgt);
+stmf_status_t srpt_stp_destroy_port(srpt_target_port_t *tgt);
 
 srpt_session_t *srpt_stp_alloc_session(srpt_target_port_t *tgt,
 	uint8_t *i_id, uint8_t *t_id, uint8_t port,