summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSue Gleeson <Susan.Gleeson@Sun.COM>2010-04-05 15:20:40 -0400
committerSue Gleeson <Susan.Gleeson@Sun.COM>2010-04-05 15:20:40 -0400
commitc3a558e7c77127215b010652905be7916ec5a080 (patch)
tree4f5c95cd7be43ee57cfe8981c5e9052edea7a5bb
parent9adc5a4e4d9ae99cc46988904fa0509938a2133d (diff)
downloadillumos-joyent-c3a558e7c77127215b010652905be7916ec5a080.tar.gz
6879350 RFE: Add ability to enable/disable SRPT on specific HCAs
-rw-r--r--usr/src/Makefile.lint6
-rw-r--r--usr/src/cmd/Makefile5
-rw-r--r--usr/src/cmd/srptadm/Makefile42
-rw-r--r--usr/src/cmd/srptadm/srptadm.c582
-rw-r--r--usr/src/lib/Makefile5
-rw-r--r--usr/src/lib/libsrpt/Makefile53
-rw-r--r--usr/src/lib/libsrpt/Makefile.com51
-rw-r--r--usr/src/lib/libsrpt/amd64/Makefile29
-rw-r--r--usr/src/lib/libsrpt/common/libsrpt.c493
-rw-r--r--usr/src/lib/libsrpt/common/libsrpt.h180
-rw-r--r--usr/src/lib/libsrpt/common/llib-lsrpt28
-rw-r--r--usr/src/lib/libsrpt/common/mapfile-vers56
-rw-r--r--usr/src/lib/libsrpt/i386/Makefile26
-rw-r--r--usr/src/lib/libsrpt/sparc/Makefile27
-rw-r--r--usr/src/lib/libsrpt/sparcv9/Makefile32
-rw-r--r--usr/src/pkg/manifests/driver-network-srpt.mf15
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_common.h54
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h9
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c297
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h6
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c191
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c77
-rw-r--r--usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h5
23 files changed, 2097 insertions, 172 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index baaf43922c..6eb4120f27 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -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 @@ COMMON_SUBDIRS = \
cmd/smserverd \
cmd/sort \
cmd/split \
+ cmd/srptadm \
+ cmd/srptsvc \
cmd/ssh \
cmd/stat \
cmd/stmfadm \
@@ -423,6 +424,7 @@ COMMON_SUBDIRS = \
lib/libsmbfs \
lib/libsmbios \
lib/libsmedia \
+ lib/libsrpt \
lib/libstmf \
lib/libsun_ima \
lib/libthread \
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index b493fa6ef1..a17a96695e 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -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 @@ COMMON_SUBDIRS= \
split \
sqlite \
srchtxt \
+ srptadm \
srptsvc \
ssh \
stat \
@@ -689,6 +689,7 @@ MSGSUBDIRS= \
smbsrv \
sort \
split \
+ srptadm \
ssh \
stat \
stmfadm \
diff --git a/usr/src/cmd/srptadm/Makefile b/usr/src/cmd/srptadm/Makefile
new file mode 100644
index 0000000000..b35c3a90e4
--- /dev/null
+++ b/usr/src/cmd/srptadm/Makefile
@@ -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
diff --git a/usr/src/cmd/srptadm/srptadm.c b/usr/src/cmd/srptadm/srptadm.c
new file mode 100644
index 0000000000..90b248a12d
--- /dev/null
+++ b/usr/src/cmd/srptadm/srptadm.c
@@ -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);
+}
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 2ed5c76543..a458acba3a 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -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 @@ SUBDIRS += \
krb5 .WAIT \
libsmbfs \
libfcoe \
+ libsrpt \
libstmf \
libstmfproxy \
libnsctl \
@@ -460,6 +460,7 @@ HDRSUBDIRS= \
libsocket \
libsqlite \
libfcoe \
+ libsrpt \
libstmf \
libstmfproxy \
libsum \
diff --git a/usr/src/lib/libsrpt/Makefile b/usr/src/lib/libsrpt/Makefile
new file mode 100644
index 0000000000..4e049e0fe5
--- /dev/null
+++ b/usr/src/lib/libsrpt/Makefile
@@ -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
diff --git a/usr/src/lib/libsrpt/Makefile.com b/usr/src/lib/libsrpt/Makefile.com
new file mode 100644
index 0000000000..4cc7d1d599
--- /dev/null
+++ b/usr/src/lib/libsrpt/Makefile.com
@@ -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
diff --git a/usr/src/lib/libsrpt/amd64/Makefile b/usr/src/lib/libsrpt/amd64/Makefile
new file mode 100644
index 0000000000..644e6b23da
--- /dev/null
+++ b/usr/src/lib/libsrpt/amd64/Makefile
@@ -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)
diff --git a/usr/src/lib/libsrpt/common/libsrpt.c b/usr/src/lib/libsrpt/common/libsrpt.c
new file mode 100644
index 0000000000..5a89f88568
--- /dev/null
+++ b/usr/src/lib/libsrpt/common/libsrpt.c
@@ -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);
+}
diff --git a/usr/src/lib/libsrpt/common/libsrpt.h b/usr/src/lib/libsrpt/common/libsrpt.h
new file mode 100644
index 0000000000..8b5d1fe26e
--- /dev/null
+++ b/usr/src/lib/libsrpt/common/libsrpt.h
@@ -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 */
diff --git a/usr/src/lib/libsrpt/common/llib-lsrpt b/usr/src/lib/libsrpt/common/llib-lsrpt
new file mode 100644
index 0000000000..c807a7d9f5
--- /dev/null
+++ b/usr/src/lib/libsrpt/common/llib-lsrpt
@@ -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>
diff --git a/usr/src/lib/libsrpt/common/mapfile-vers b/usr/src/lib/libsrpt/common/mapfile-vers
new file mode 100644
index 0000000000..8be8e62a75
--- /dev/null
+++ b/usr/src/lib/libsrpt/common/mapfile-vers
@@ -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:
+ *;
+};
+
diff --git a/usr/src/lib/libsrpt/i386/Makefile b/usr/src/lib/libsrpt/i386/Makefile
new file mode 100644
index 0000000000..f9373d2096
--- /dev/null
+++ b/usr/src/lib/libsrpt/i386/Makefile
@@ -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)
diff --git a/usr/src/lib/libsrpt/sparc/Makefile b/usr/src/lib/libsrpt/sparc/Makefile
new file mode 100644
index 0000000000..3f74bc6793
--- /dev/null
+++ b/usr/src/lib/libsrpt/sparc/Makefile
@@ -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)
diff --git a/usr/src/lib/libsrpt/sparcv9/Makefile b/usr/src/lib/libsrpt/sparcv9/Makefile
new file mode 100644
index 0000000000..8f83585151
--- /dev/null
+++ b/usr/src/lib/libsrpt/sparcv9/Makefile
@@ -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)
diff --git a/usr/src/pkg/manifests/driver-network-srpt.mf b/usr/src/pkg/manifests/driver-network-srpt.mf
index b1d28be2be..31dd8c8edf 100644
--- a/usr/src/pkg/manifests/driver-network-srpt.mf
+++ b/usr/src/pkg/manifests/driver-network-srpt.mf
@@ -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 opensolaris.zone=global variant.opensolaris.zone=global
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 @@ $(i386_ONLY)file path=kernel/kmdb/srpt group=sys mode=0555 \
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" \
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h
new file mode 100644
index 0000000000..fa8a688a3a
--- /dev/null
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h
@@ -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_ */
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h
index 864513595a..ebb7d7a8eb 100644
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h
@@ -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 @@ typedef struct srpt_ctxt_s {
/* 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 {
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c
index 3b5f48c388..edd06e7ddd 100644
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c
@@ -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 struct ibt_clnt_modinfo_s srpt_ibt_modinfo = {
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 @@ srpt_ioc_attach()
int hca_cnt;
int hca_ndx;
ib_guid_t *guid;
- srpt_ioc_t *ioc;
ASSERT(srpt_ctxt != NULL);
@@ -171,19 +172,9 @@ srpt_ioc_attach()
}
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 @@ srpt_ioc_attach()
}
/*
+ * 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_detach()
{
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 @@ srpt_ioc_init(ib_guid_t guid)
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 @@ void
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 @@ srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl,
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);
-
- 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;
- }
-
- /*
- * 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);
+ SRPT_DPRINTF_L2(
+ "ib_async_hdlr, received attach event for HCA 0x%016llx",
+ (u_longlong_t)event->ev_hca_guid);
- rw_exit(&ioc->ioc_rwlock);
+ rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER);
+ srpt_ioc_attach_hca(event->ev_hca_guid, B_FALSE);
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 @@ srpt_dereg_mem(srpt_ioc_t *ioc, srpt_mr_t *mr)
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));
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h
index f9c6fab614..20f9392366 100644
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h
@@ -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 @@ extern "C" {
#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);
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c b/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c
index 12d5d0f79e..829d67eca8 100644
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c
@@ -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 @@ _init(void)
/* 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 @@ static int
srpt_enable_srp_services(void)
{
int status;
- srpt_ioc_t *ioc;
ASSERT((rw_read_locked(&srpt_ctxt->sc_rwlock)) == 0);
@@ -314,7 +325,9 @@ srpt_enable_srp_services(void)
}
/*
- * 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 @@ srpt_enable_srp_services(void)
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 @@ srpt_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
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 @@ static int
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 @@ srpt_disable_srp_services(void)
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);
- } else {
+ stmf_status = srpt_stp_destroy_port(tgt);
+ if (stmf_status == STMF_SUCCESS) {
+ ioc->ioc_tgt_port = NULL;
(void) srpt_stp_free_port(tgt);
+ } else {
+ ret_status = DDI_FAILURE;
+ break;
}
}
@@ -586,11 +548,90 @@ srpt_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred,
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
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c
index 62fc86c4a6..d7da726086 100644
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c
@@ -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_free_port(srpt_target_port_t *tgt)
}
/*
- * 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);
+ 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);
+
/*
- * This is only done on an administrative thread of
- * execution so it is ok to take a while.
+ * Wait for asynchronous target off-line operation
+ * to complete and then deregister the target
+ * port.
*/
- if (status == STMF_BUSY) {
- delay(drv_usectohz(1000000));
- goto retry_deregistration;
+ 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);
}
- /*
- * Something other than a BUSY error, this should not happen.
- */
- SRPT_DPRINTF_L1("stp_deregister_port, de-register STMF error(0x%llx)",
- (u_longlong_t)status);
return (status);
}
diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h
index e1bd099b05..f22a44a600 100644
--- a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h
+++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h
@@ -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 @@ int srpt_stp_start_srp(srpt_target_port_t *tgt);
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,