Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Dec 2016 01:04:59 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r309458 - in stable: 10/sys/dev/cxgbe 10/sys/dev/cxgbe/common 10/sys/dev/cxgbe/firmware 11/sys/dev/cxgbe 11/sys/dev/cxgbe/common 11/sys/dev/cxgbe/firmware
Message-ID:  <201612030104.uB314x9I018767@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Sat Dec  3 01:04:59 2016
New Revision: 309458
URL: https://svnweb.freebsd.org/changeset/base/309458

Log:
  MFC 302440,304873,305704,305985,306787,307531: Fixes for sysctls.
  
  302440:
  cxgbe(4): Add sysctl to display the RSS indirection table size for an
  interface.
  
  dev.cxl.<n>.rss_size
  dev.vcxl.<n>.rss_size
  
  304873:
  cxgbe(4): Provide more details about the card in the sysctl MIB.
  
  dev.t5nex.0.%desc: Chelsio T580-CR
  dev.t5nex.0.hw_revision: 1
  dev.t5nex.0.sn: PT13140042
  dev.t5nex.0.pn: 110117150A0
  dev.t5nex.0.ec: 0000000000000000
  dev.t5nex.0.na: 0007432AF490
  dev.t5nex.0.vpd_version: 3
  dev.t5nex.0.scfg_version: 53255
  dev.t5nex.0.bs_version: 1.1.0.0
  dev.t5nex.0.er_version: 1.0.0.68
  dev.t5nex.0.tp_version: 0.1.4.9
  dev.t5nex.0.firmware_version: 1.16.2.0
  
  305704:
  cxgbe(4): Rename the debug_flags driver tunable/sysctl to dflags.
  Tunables that end with _flags are special.
  
  305985:
  cxgbe(4): Fixes to wrq stats.
  
  - Increment tx_wrs_copied in the correct place.
  - Add tx_wrs_sspace to the sysctl MIB.
  
  306787:
  cxgbe(4): Fix whitespace in the pm_stats display.
  
  307531:
  cxgbe(4): Adjust whitespace to line up the column titles in cim_qcfg
  with the values displayed.
  
  Sponsored by:	Chelsio Communications

Modified:
  stable/10/sys/dev/cxgbe/adapter.h
  stable/10/sys/dev/cxgbe/common/common.h
  stable/10/sys/dev/cxgbe/common/t4_hw.c
  stable/10/sys/dev/cxgbe/firmware/t4fw_interface.h
  stable/10/sys/dev/cxgbe/t4_main.c
  stable/10/sys/dev/cxgbe/t4_sge.c
Directory Properties:
  stable/10/   (props changed)

Changes in other areas also in this revision:
Modified:
  stable/11/sys/dev/cxgbe/adapter.h
  stable/11/sys/dev/cxgbe/common/common.h
  stable/11/sys/dev/cxgbe/common/t4_hw.c
  stable/11/sys/dev/cxgbe/firmware/t4fw_interface.h
  stable/11/sys/dev/cxgbe/t4_main.c
  stable/11/sys/dev/cxgbe/t4_sge.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/10/sys/dev/cxgbe/adapter.h
==============================================================================
--- stable/10/sys/dev/cxgbe/adapter.h	Sat Dec  3 00:46:18 2016	(r309457)
+++ stable/10/sys/dev/cxgbe/adapter.h	Sat Dec  3 01:04:59 2016	(r309458)
@@ -814,7 +814,8 @@ struct adapter {
 
 	char fw_version[16];
 	char tp_version[16];
-	char exprom_version[16];
+	char er_version[16];
+	char bs_version[16];
 	char cfg_file[32];
 	u_int cfcsum;
 	struct adapter_params params;

Modified: stable/10/sys/dev/cxgbe/common/common.h
==============================================================================
--- stable/10/sys/dev/cxgbe/common/common.h	Sat Dec  3 00:46:18 2016	(r309457)
+++ stable/10/sys/dev/cxgbe/common/common.h	Sat Dec  3 01:04:59 2016	(r309458)
@@ -330,9 +330,12 @@ struct adapter_params {
 	unsigned int sf_size;             /* serial flash size in bytes */
 	unsigned int sf_nsec;             /* # of flash sectors */
 
-	unsigned int fw_vers;
-	unsigned int tp_vers;
-	unsigned int exprom_vers;
+	unsigned int fw_vers;		/* firmware version */
+	unsigned int bs_vers;		/* bootstrap version */
+	unsigned int tp_vers;		/* TP microcode version */
+	unsigned int er_vers;		/* expansion ROM version */
+	unsigned int scfg_vers;		/* Serial Configuration version */
+	unsigned int vpd_vers;		/* VPD version */
 
 	unsigned short mtus[NMTUS];
 	unsigned short a_wnd[NCCTRL_WIN];
@@ -548,8 +551,12 @@ int t4_flash_erase_sectors(struct adapte
 int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
 int t4_get_fw_version(struct adapter *adapter, u32 *vers);
+int t4_get_bs_version(struct adapter *adapter, u32 *vers);
 int t4_get_tp_version(struct adapter *adapter, u32 *vers);
 int t4_get_exprom_version(struct adapter *adapter, u32 *vers);
+int t4_get_scfg_version(struct adapter *adapter, u32 *vers);
+int t4_get_vpd_version(struct adapter *adapter, u32 *vers);
+int t4_get_version_info(struct adapter *adapter);
 int t4_init_hw(struct adapter *adapter, u32 fw_params);
 const struct chip_params *t4_get_chip_params(int chipid);
 int t4_prep_adapter(struct adapter *adapter, u8 *buf);

Modified: stable/10/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- stable/10/sys/dev/cxgbe/common/t4_hw.c	Sat Dec  3 00:46:18 2016	(r309457)
+++ stable/10/sys/dev/cxgbe/common/t4_hw.c	Sat Dec  3 01:04:59 2016	(r309458)
@@ -3231,6 +3231,20 @@ int t4_get_fw_version(struct adapter *ad
 }
 
 /**
+ *	t4_get_bs_version - read the firmware bootstrap version
+ *	@adapter: the adapter
+ *	@vers: where to place the version
+ *
+ *	Reads the FW Bootstrap version from flash.
+ */
+int t4_get_bs_version(struct adapter *adapter, u32 *vers)
+{
+	return t4_read_flash(adapter, FLASH_FWBOOTSTRAP_START +
+			     offsetof(struct fw_hdr, fw_ver), 1,
+			     vers, 0);
+}
+
+/**
  *	t4_get_tp_version - read the TP microcode version
  *	@adapter: the adapter
  *	@vers: where to place the version
@@ -3282,6 +3296,110 @@ int t4_get_exprom_version(struct adapter
 }
 
 /**
+ *	t4_get_scfg_version - return the Serial Configuration version
+ *	@adapter: the adapter
+ *	@vers: where to place the version
+ *
+ *	Reads the Serial Configuration Version via the Firmware interface
+ *	(thus this can only be called once we're ready to issue Firmware
+ *	commands).  The format of the Serial Configuration version is
+ *	adapter specific.  Returns 0 on success, an error on failure.
+ *
+ *	Note that early versions of the Firmware didn't include the ability
+ *	to retrieve the Serial Configuration version, so we zero-out the
+ *	return-value parameter in that case to avoid leaving it with
+ *	garbage in it.
+ *
+ *	Also note that the Firmware will return its cached copy of the Serial
+ *	Initialization Revision ID, not the actual Revision ID as written in
+ *	the Serial EEPROM.  This is only an issue if a new VPD has been written
+ *	and the Firmware/Chip haven't yet gone through a RESET sequence.  So
+ *	it's best to defer calling this routine till after a FW_RESET_CMD has
+ *	been issued if the Host Driver will be performing a full adapter
+ *	initialization.
+ */
+int t4_get_scfg_version(struct adapter *adapter, u32 *vers)
+{
+	u32 scfgrev_param;
+	int ret;
+
+	scfgrev_param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+			 V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_SCFGREV));
+	ret = t4_query_params(adapter, adapter->mbox, adapter->pf, 0,
+			      1, &scfgrev_param, vers);
+	if (ret)
+		*vers = 0;
+	return ret;
+}
+
+/**
+ *	t4_get_vpd_version - return the VPD version
+ *	@adapter: the adapter
+ *	@vers: where to place the version
+ *
+ *	Reads the VPD via the Firmware interface (thus this can only be called
+ *	once we're ready to issue Firmware commands).  The format of the
+ *	VPD version is adapter specific.  Returns 0 on success, an error on
+ *	failure.
+ *
+ *	Note that early versions of the Firmware didn't include the ability
+ *	to retrieve the VPD version, so we zero-out the return-value parameter
+ *	in that case to avoid leaving it with garbage in it.
+ *
+ *	Also note that the Firmware will return its cached copy of the VPD
+ *	Revision ID, not the actual Revision ID as written in the Serial
+ *	EEPROM.  This is only an issue if a new VPD has been written and the
+ *	Firmware/Chip haven't yet gone through a RESET sequence.  So it's best
+ *	to defer calling this routine till after a FW_RESET_CMD has been issued
+ *	if the Host Driver will be performing a full adapter initialization.
+ */
+int t4_get_vpd_version(struct adapter *adapter, u32 *vers)
+{
+	u32 vpdrev_param;
+	int ret;
+
+	vpdrev_param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+			V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_VPDREV));
+	ret = t4_query_params(adapter, adapter->mbox, adapter->pf, 0,
+			      1, &vpdrev_param, vers);
+	if (ret)
+		*vers = 0;
+	return ret;
+}
+
+/**
+ *	t4_get_version_info - extract various chip/firmware version information
+ *	@adapter: the adapter
+ *
+ *	Reads various chip/firmware version numbers and stores them into the
+ *	adapter Adapter Parameters structure.  If any of the efforts fails
+ *	the first failure will be returned, but all of the version numbers
+ *	will be read.
+ */
+int t4_get_version_info(struct adapter *adapter)
+{
+	int ret = 0;
+
+	#define FIRST_RET(__getvinfo) \
+	do { \
+		int __ret = __getvinfo; \
+		if (__ret && !ret) \
+			ret = __ret; \
+	} while (0)
+
+	FIRST_RET(t4_get_fw_version(adapter, &adapter->params.fw_vers));
+	FIRST_RET(t4_get_bs_version(adapter, &adapter->params.bs_vers));
+	FIRST_RET(t4_get_tp_version(adapter, &adapter->params.tp_vers));
+	FIRST_RET(t4_get_exprom_version(adapter, &adapter->params.er_vers));
+	FIRST_RET(t4_get_scfg_version(adapter, &adapter->params.scfg_vers));
+	FIRST_RET(t4_get_vpd_version(adapter, &adapter->params.vpd_vers));
+
+	#undef FIRST_RET
+
+	return ret;
+}
+
+/**
  *	t4_flash_erase_sectors - erase a range of flash sectors
  *	@adapter: the adapter
  *	@start: the first sector to erase

Modified: stable/10/sys/dev/cxgbe/firmware/t4fw_interface.h
==============================================================================
--- stable/10/sys/dev/cxgbe/firmware/t4fw_interface.h	Sat Dec  3 00:46:18 2016	(r309457)
+++ stable/10/sys/dev/cxgbe/firmware/t4fw_interface.h	Sat Dec  3 01:04:59 2016	(r309458)
@@ -4206,6 +4206,8 @@ enum fw_params_param_dev {
 	FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
 	FW_PARAMS_PARAM_DEV_FWCACHE	= 0x18,
 	FW_PARAMS_PARAM_DEV_RSSINFO	= 0x19,
+	FW_PARAMS_PARAM_DEV_SCFGREV	= 0x1A,
+	FW_PARAMS_PARAM_DEV_VPDREV	= 0x1B,
 };
 
 /*

Modified: stable/10/sys/dev/cxgbe/t4_main.c
==============================================================================
--- stable/10/sys/dev/cxgbe/t4_main.c	Sat Dec  3 00:46:18 2016	(r309457)
+++ stable/10/sys/dev/cxgbe/t4_main.c	Sat Dec  3 01:04:59 2016	(r309458)
@@ -666,7 +666,7 @@ t4_attach(device_t dev)
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
-	TUNABLE_INT_FETCH("hw.cxgbe.debug_flags", &sc->debug_flags);
+	TUNABLE_INT_FETCH("hw.cxgbe.dflags", &sc->debug_flags);
 
 	if ((pci_get_device(dev) & 0xff00) == 0x5400)
 		t5_attribute_workaround(dev);
@@ -2711,32 +2711,6 @@ prep_firmware(struct adapter *sc)
 		goto done;
 	}
 
-	/* We're using whatever's on the card and it's known to be good. */
-	sc->params.fw_vers = ntohl(card_fw->fw_ver);
-	snprintf(sc->fw_version, sizeof(sc->fw_version), "%u.%u.%u.%u",
-	    G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers),
-	    G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers),
-	    G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers),
-	    G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers));
-
-	t4_get_tp_version(sc, &sc->params.tp_vers);
-	snprintf(sc->tp_version, sizeof(sc->tp_version), "%u.%u.%u.%u",
-	    G_FW_HDR_FW_VER_MAJOR(sc->params.tp_vers),
-	    G_FW_HDR_FW_VER_MINOR(sc->params.tp_vers),
-	    G_FW_HDR_FW_VER_MICRO(sc->params.tp_vers),
-	    G_FW_HDR_FW_VER_BUILD(sc->params.tp_vers));
-
-	if (t4_get_exprom_version(sc, &sc->params.exprom_vers) != 0)
-		sc->params.exprom_vers = 0;
-	else {
-		snprintf(sc->exprom_version, sizeof(sc->exprom_version),
-		    "%u.%u.%u.%u",
-		    G_FW_HDR_FW_VER_MAJOR(sc->params.exprom_vers),
-		    G_FW_HDR_FW_VER_MINOR(sc->params.exprom_vers),
-		    G_FW_HDR_FW_VER_MICRO(sc->params.exprom_vers),
-		    G_FW_HDR_FW_VER_BUILD(sc->params.exprom_vers));
-	}
-
 	/* Reset device */
 	if (need_fw_reset &&
 	    (rc = -t4_fw_reset(sc, sc->mbox, F_PIORSTMODE | F_PIORST)) != 0) {
@@ -2981,6 +2955,32 @@ get_params__pre_init(struct adapter *sc)
 	int rc;
 	uint32_t param[2], val[2];
 
+	t4_get_version_info(sc);
+
+	snprintf(sc->fw_version, sizeof(sc->fw_version), "%u.%u.%u.%u",
+	    G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers),
+	    G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers),
+	    G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers),
+	    G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers));
+
+	snprintf(sc->bs_version, sizeof(sc->bs_version), "%u.%u.%u.%u",
+	    G_FW_HDR_FW_VER_MAJOR(sc->params.bs_vers),
+	    G_FW_HDR_FW_VER_MINOR(sc->params.bs_vers),
+	    G_FW_HDR_FW_VER_MICRO(sc->params.bs_vers),
+	    G_FW_HDR_FW_VER_BUILD(sc->params.bs_vers));
+
+	snprintf(sc->tp_version, sizeof(sc->tp_version), "%u.%u.%u.%u",
+	    G_FW_HDR_FW_VER_MAJOR(sc->params.tp_vers),
+	    G_FW_HDR_FW_VER_MINOR(sc->params.tp_vers),
+	    G_FW_HDR_FW_VER_MICRO(sc->params.tp_vers),
+	    G_FW_HDR_FW_VER_BUILD(sc->params.tp_vers));
+
+	snprintf(sc->er_version, sizeof(sc->er_version), "%u.%u.%u.%u",
+	    G_FW_HDR_FW_VER_MAJOR(sc->params.er_vers),
+	    G_FW_HDR_FW_VER_MINOR(sc->params.er_vers),
+	    G_FW_HDR_FW_VER_MICRO(sc->params.er_vers),
+	    G_FW_HDR_FW_VER_BUILD(sc->params.er_vers));
+
 	param[0] = FW_PARAM_DEV(PORTVEC);
 	param[1] = FW_PARAM_DEV(CCLK);
 	rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 2, param, val);
@@ -3194,9 +3194,7 @@ t4_set_desc(struct adapter *sc)
 	char buf[128];
 	struct adapter_params *p = &sc->params;
 
-	snprintf(buf, sizeof(buf), "Chelsio %s %sNIC (rev %d), S/N:%s, "
-	    "P/N:%s, E/C:%s", p->vpd.id, is_offload(sc) ? "R" : "",
-	    chip_rev(sc), p->vpd.sn, p->vpd.pn, p->vpd.ec);
+	snprintf(buf, sizeof(buf), "Chelsio %s", p->vpd.id);
 
 	device_set_desc_copy(sc->dev, buf);
 }
@@ -4496,7 +4494,7 @@ t4_sysctls(struct adapter *sc)
 	SYSCTL_ADD_INT(ctx, children, OID_AUTO, "lro_timeout", CTLFLAG_RW,
 	    &sc->lro_timeout, 0, "lro inactive-flush timeout (in us)");
 
-	SYSCTL_ADD_INT(ctx, children, OID_AUTO, "debug_flags", CTLFLAG_RW,
+	SYSCTL_ADD_INT(ctx, children, OID_AUTO, "dflags", CTLFLAG_RW,
 	    &sc->debug_flags, 0, "flags to enable runtime debugging");
 
 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "tp_version",
@@ -4511,10 +4509,29 @@ t4_sysctls(struct adapter *sc)
 	SYSCTL_ADD_INT(ctx, children, OID_AUTO, "hw_revision", CTLFLAG_RD,
 	    NULL, chip_rev(sc), "chip hardware revision");
 
-	if (sc->params.exprom_vers != 0) {
-		SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "exprom_version",
-		    CTLFLAG_RD, sc->exprom_version, 0, "expansion ROM version");
-	}
+	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "sn",
+	    CTLFLAG_RD, sc->params.vpd.sn, 0, "serial number");
+
+	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "pn",
+	    CTLFLAG_RD, sc->params.vpd.pn, 0, "part number");
+
+	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "ec",
+	    CTLFLAG_RD, sc->params.vpd.ec, 0, "engineering change");
+
+	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "na",
+	    CTLFLAG_RD, sc->params.vpd.na, 0, "network address");
+
+	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "er_version", CTLFLAG_RD,
+	    sc->er_version, 0, "expansion ROM version");
+
+	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "bs_version", CTLFLAG_RD,
+	    sc->bs_version, 0, "bootstrap firmware version");
+
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "scfg_version", CTLFLAG_RD,
+	    NULL, sc->params.scfg_vers, "serial config version");
+
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "vpd_version", CTLFLAG_RD,
+	    NULL, sc->params.vpd_vers, "VPD version");
 
 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "cf",
 	    CTLFLAG_RD, sc->cfg_file, 0, "configuration file");
@@ -4525,7 +4542,7 @@ t4_sysctls(struct adapter *sc)
 #define SYSCTL_CAP(name, n, text) \
 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, #name, \
 	    CTLTYPE_STRING | CTLFLAG_RD, caps_decoder[n], sc->name, \
-	    sysctl_bitfield, "A", "available " text "capabilities")
+	    sysctl_bitfield, "A", "available " text " capabilities")
 
 	SYSCTL_CAP(nbmcaps, 0, "NBM");
 	SYSCTL_CAP(linkcaps, 1, "link");
@@ -4827,6 +4844,8 @@ vi_sysctls(struct vi_info *vi)
 	    &vi->first_rxq, 0, "index of first rx queue");
 	SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_txq", CTLFLAG_RD,
 	    &vi->first_txq, 0, "index of first tx queue");
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "rss_size", CTLFLAG_RD, NULL,
+	    vi->rss_size, "size of RSS indirection table");
 
 	if (IS_MAIN_VI(vi)) {
 		SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rsrv_noflowq",
@@ -5772,7 +5791,8 @@ sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS)
 	if (sb == NULL)
 		return (ENOMEM);
 
-	sbuf_printf(sb, "Queue  Base  Size Thres RdPtr WrPtr  SOP  EOP Avail");
+	sbuf_printf(sb,
+	    "  Queue  Base  Size Thres  RdPtr WrPtr  SOP  EOP Avail");
 
 	for (i = 0; i < CIM_NUM_IBQ; i++, p += 4)
 		sbuf_printf(sb, "\n%7s %5x %5u %5u %6x  %4x %4u %4u %5u",
@@ -6716,7 +6736,7 @@ sysctl_pm_stats(SYSCTL_HANDLER_ARGS)
 	};
 	static const char *rx_stats[MAX_PM_NSTATS] = {
 		"Read:", "Write bypass:", "Write mem:", "Flush:",
-		" Rx FIFO wait", NULL, "Rx latency"
+		"Rx FIFO wait", NULL, "Rx latency"
 	};
 
 	rc = sysctl_wire_old_buffer(req, 0);

Modified: stable/10/sys/dev/cxgbe/t4_sge.c
==============================================================================
--- stable/10/sys/dev/cxgbe/t4_sge.c	Sat Dec  3 00:46:18 2016	(r309457)
+++ stable/10/sys/dev/cxgbe/t4_sge.c	Sat Dec  3 01:04:59 2016	(r309458)
@@ -1890,6 +1890,7 @@ drain_wrq_wr_list(struct adapter *sc, st
 			}
 			eq->pidx = n - (eq->sidx - eq->pidx);
 		}
+		wrq->tx_wrs_copied++;
 
 		if (available < eq->sidx / 4 &&
 		    atomic_cmpset_int(&eq->equiq, 0, 1)) {
@@ -3545,6 +3546,8 @@ alloc_wrq(struct adapter *sc, struct vi_
 	    &wrq->tx_wrs_direct, "# of work requests (direct)");
 	SYSCTL_ADD_UQUAD(ctx, children, OID_AUTO, "tx_wrs_copied", CTLFLAG_RD,
 	    &wrq->tx_wrs_copied, "# of work requests (copied)");
+	SYSCTL_ADD_UQUAD(ctx, children, OID_AUTO, "tx_wrs_sspace", CTLFLAG_RD,
+	    &wrq->tx_wrs_ss, "# of work requests (copied from scratch space)");
 
 	return (rc);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612030104.uB314x9I018767>