Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 May 2011 23:58:03 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r222237 - in projects/largeSMP: contrib/top sbin/hastctl sbin/hastd share/man/man4 share/mk sys/conf sys/dev/acpica sys/dev/msk sys/fs/nfsclient sys/geom/gate sys/kern sys/netinet sys/n...
Message-ID:  <201105232358.p4NNw3fw043315@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: attilio
Date: Mon May 23 23:58:02 2011
New Revision: 222237
URL: http://svn.freebsd.org/changeset/base/222237

Log:
  MFC

Modified:
  projects/largeSMP/sbin/hastctl/hastctl.c
  projects/largeSMP/sbin/hastd/control.c
  projects/largeSMP/sbin/hastd/hast.h
  projects/largeSMP/sbin/hastd/primary.c
  projects/largeSMP/sbin/hastd/secondary.c
  projects/largeSMP/sbin/hastd/subr.c
  projects/largeSMP/share/man/man4/msk.4
  projects/largeSMP/sys/conf/kern.post.mk
  projects/largeSMP/sys/conf/kmod.mk
  projects/largeSMP/sys/conf/newvers.sh
  projects/largeSMP/sys/dev/acpica/acpi_hpet.c
  projects/largeSMP/sys/dev/acpica/acpi_timer.c
  projects/largeSMP/sys/dev/msk/if_msk.c
  projects/largeSMP/sys/dev/msk/if_mskreg.h
  projects/largeSMP/sys/fs/nfsclient/nfs_clvfsops.c
  projects/largeSMP/sys/geom/gate/g_gate.c
  projects/largeSMP/sys/kern/kern_environment.c
  projects/largeSMP/sys/kern/vfs_bio.c
  projects/largeSMP/sys/netinet/in_pcb.c
  projects/largeSMP/sys/netinet/in_pcb.h
  projects/largeSMP/sys/netinet6/in6_pcb.c
  projects/largeSMP/sys/netinet6/in6_src.c
  projects/largeSMP/usr.bin/gzip/Makefile
  projects/largeSMP/usr.bin/gzip/gzip.1
  projects/largeSMP/usr.bin/gzip/gzip.c
  projects/largeSMP/usr.bin/gzip/zdiff
  projects/largeSMP/usr.bin/gzip/zdiff.1
  projects/largeSMP/usr.bin/gzip/zuncompress.c
Directory Properties:
  projects/largeSMP/   (props changed)
  projects/largeSMP/cddl/contrib/opensolaris/   (props changed)
  projects/largeSMP/contrib/bind9/   (props changed)
  projects/largeSMP/contrib/binutils/   (props changed)
  projects/largeSMP/contrib/bzip2/   (props changed)
  projects/largeSMP/contrib/dialog/   (props changed)
  projects/largeSMP/contrib/ee/   (props changed)
  projects/largeSMP/contrib/expat/   (props changed)
  projects/largeSMP/contrib/file/   (props changed)
  projects/largeSMP/contrib/gcc/   (props changed)
  projects/largeSMP/contrib/gdb/   (props changed)
  projects/largeSMP/contrib/gdtoa/   (props changed)
  projects/largeSMP/contrib/gnu-sort/   (props changed)
  projects/largeSMP/contrib/groff/   (props changed)
  projects/largeSMP/contrib/less/   (props changed)
  projects/largeSMP/contrib/libpcap/   (props changed)
  projects/largeSMP/contrib/libstdc++/   (props changed)
  projects/largeSMP/contrib/llvm/   (props changed)
  projects/largeSMP/contrib/llvm/tools/clang/   (props changed)
  projects/largeSMP/contrib/ncurses/   (props changed)
  projects/largeSMP/contrib/netcat/   (props changed)
  projects/largeSMP/contrib/ntp/   (props changed)
  projects/largeSMP/contrib/one-true-awk/   (props changed)
  projects/largeSMP/contrib/openbsm/   (props changed)
  projects/largeSMP/contrib/openpam/   (props changed)
  projects/largeSMP/contrib/pf/   (props changed)
  projects/largeSMP/contrib/sendmail/   (props changed)
  projects/largeSMP/contrib/tcpdump/   (props changed)
  projects/largeSMP/contrib/tcsh/   (props changed)
  projects/largeSMP/contrib/top/   (props changed)
  projects/largeSMP/contrib/top/install-sh   (props changed)
  projects/largeSMP/contrib/tzcode/stdtime/   (props changed)
  projects/largeSMP/contrib/tzcode/zic/   (props changed)
  projects/largeSMP/contrib/tzdata/   (props changed)
  projects/largeSMP/contrib/wpa/   (props changed)
  projects/largeSMP/contrib/xz/   (props changed)
  projects/largeSMP/crypto/openssh/   (props changed)
  projects/largeSMP/crypto/openssl/   (props changed)
  projects/largeSMP/gnu/lib/   (props changed)
  projects/largeSMP/gnu/usr.bin/binutils/   (props changed)
  projects/largeSMP/gnu/usr.bin/cc/cc_tools/   (props changed)
  projects/largeSMP/gnu/usr.bin/gdb/   (props changed)
  projects/largeSMP/lib/libc/   (props changed)
  projects/largeSMP/lib/libc/stdtime/   (props changed)
  projects/largeSMP/lib/libutil/   (props changed)
  projects/largeSMP/lib/libz/   (props changed)
  projects/largeSMP/sbin/   (props changed)
  projects/largeSMP/sbin/ipfw/   (props changed)
  projects/largeSMP/share/mk/bsd.arch.inc.mk   (props changed)
  projects/largeSMP/share/zoneinfo/   (props changed)
  projects/largeSMP/sys/   (props changed)
  projects/largeSMP/sys/amd64/include/xen/   (props changed)
  projects/largeSMP/sys/boot/   (props changed)
  projects/largeSMP/sys/boot/i386/efi/   (props changed)
  projects/largeSMP/sys/boot/ia64/efi/   (props changed)
  projects/largeSMP/sys/boot/ia64/ski/   (props changed)
  projects/largeSMP/sys/boot/powerpc/boot1.chrp/   (props changed)
  projects/largeSMP/sys/boot/powerpc/ofw/   (props changed)
  projects/largeSMP/sys/cddl/contrib/opensolaris/   (props changed)
  projects/largeSMP/sys/conf/   (props changed)
  projects/largeSMP/sys/contrib/dev/acpica/   (props changed)
  projects/largeSMP/sys/contrib/octeon-sdk/   (props changed)
  projects/largeSMP/sys/contrib/pf/   (props changed)
  projects/largeSMP/sys/contrib/x86emu/   (props changed)
  projects/largeSMP/usr.bin/calendar/   (props changed)
  projects/largeSMP/usr.bin/csup/   (props changed)
  projects/largeSMP/usr.bin/procstat/   (props changed)
  projects/largeSMP/usr.sbin/ndiscvt/   (props changed)
  projects/largeSMP/usr.sbin/zic/   (props changed)

Modified: projects/largeSMP/sbin/hastctl/hastctl.c
==============================================================================
--- projects/largeSMP/sbin/hastctl/hastctl.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sbin/hastctl/hastctl.c	Mon May 23 23:58:02 2011	(r222237)
@@ -341,6 +341,17 @@ control_status(struct nv *nv)
 		printf("  dirty: %ju (%NB)\n",
 		    (uintmax_t)nv_get_uint64(nv, "dirty%u", ii),
 		    (intmax_t)nv_get_uint64(nv, "dirty%u", ii));
+		printf("  statistics:\n");
+		printf("    reads: %ju\n",
+		    (uint64_t)nv_get_uint64(nv, "stat_read%u", ii));
+		printf("    writes: %ju\n",
+		    (uint64_t)nv_get_uint64(nv, "stat_write%u", ii));
+		printf("    deletes: %ju\n",
+		    (uint64_t)nv_get_uint64(nv, "stat_delete%u", ii));
+		printf("    flushes: %ju\n",
+		    (uint64_t)nv_get_uint64(nv, "stat_flush%u", ii));
+		printf("    activemap updates: %ju\n",
+		    (uint64_t)nv_get_uint64(nv, "stat_activemap_update%u", ii));
 	}
 	return (ret);
 }

Modified: projects/largeSMP/sbin/hastd/control.c
==============================================================================
--- projects/largeSMP/sbin/hastd/control.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sbin/hastd/control.c	Mon May 23 23:58:02 2011	(r222237)
@@ -199,6 +199,16 @@ control_status_worker(struct hast_resour
 	    "extentsize%u", no);
 	nv_add_uint32(nvout, nv_get_uint32(cnvin, "keepdirty"),
 	    "keepdirty%u", no);
+	nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_read"),
+	    "stat_read%u", no);
+	nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_write"),
+	    "stat_write%u", no);
+	nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_delete"),
+	    "stat_delete%u", no);
+	nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_flush"),
+	    "stat_flush%u", no);
+	nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_activemap_update"),
+	    "stat_activemap_update%u", no);
 end:
 	if (cnvin != NULL)
 		nv_free(cnvin);
@@ -446,6 +456,13 @@ ctrl_thread(void *arg)
 				nv_add_uint32(nvout, (uint32_t)0, "keepdirty");
 				nv_add_uint64(nvout, (uint64_t)0, "dirty");
 			}
+			nv_add_uint64(nvout, res->hr_stat_read, "stat_read");
+			nv_add_uint64(nvout, res->hr_stat_write, "stat_write");
+			nv_add_uint64(nvout, res->hr_stat_delete,
+			    "stat_delete");
+			nv_add_uint64(nvout, res->hr_stat_flush, "stat_flush");
+			nv_add_uint64(nvout, res->hr_stat_activemap_update,
+			    "stat_activemap_update");
 			nv_add_int16(nvout, 0, "error");
 			break;
 		case CONTROL_RELOAD:

Modified: projects/largeSMP/sbin/hastd/hast.h
==============================================================================
--- projects/largeSMP/sbin/hastd/hast.h	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sbin/hastd/hast.h	Mon May 23 23:58:02 2011	(r222237)
@@ -218,6 +218,17 @@ struct hast_resource {
 	/* Locked used to synchronize access to hr_amp. */
 	pthread_mutex_t hr_amp_lock;
 
+	/* Number of BIO_READ requests. */
+	uint64_t	hr_stat_read;
+	/* Number of BIO_WRITE requests. */
+	uint64_t	hr_stat_write;
+	/* Number of BIO_DELETE requests. */
+	uint64_t	hr_stat_delete;
+	/* Number of BIO_FLUSH requests. */
+	uint64_t	hr_stat_flush;
+	/* Number of activemap updates. */
+	uint64_t	hr_stat_activemap_update;
+
 	/* Next resource. */
 	TAILQ_ENTRY(hast_resource) hr_next;
 };

Modified: projects/largeSMP/sbin/hastd/primary.c
==============================================================================
--- projects/largeSMP/sbin/hastd/primary.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sbin/hastd/primary.c	Mon May 23 23:58:02 2011	(r222237)
@@ -1117,6 +1117,7 @@ ggate_recv_thread(void *arg)
 		 */
 		switch (ggio->gctl_cmd) {
 		case BIO_READ:
+			res->hr_stat_read++;
 			pjdlog_debug(2,
 			    "ggate_recv: (%p) Moving request to the send queue.",
 			    hio);
@@ -1145,6 +1146,7 @@ ggate_recv_thread(void *arg)
 			QUEUE_INSERT1(hio, send, ncomp);
 			break;
 		case BIO_WRITE:
+			res->hr_stat_write++;
 			if (res->hr_resuid == 0) {
 				/*
 				 * This is first write, initialize localcnt and
@@ -1183,12 +1185,21 @@ ggate_recv_thread(void *arg)
 			mtx_lock(&res->hr_amp_lock);
 			if (activemap_write_start(res->hr_amp,
 			    ggio->gctl_offset, ggio->gctl_length)) {
+				res->hr_stat_activemap_update++;
 				(void)hast_activemap_flush(res);
 			}
 			mtx_unlock(&res->hr_amp_lock);
 			/* FALLTHROUGH */
 		case BIO_DELETE:
 		case BIO_FLUSH:
+			switch (ggio->gctl_cmd) {
+			case BIO_DELETE:
+				res->hr_stat_delete++;
+				break;
+			case BIO_FLUSH:
+				res->hr_stat_flush++;
+				break;
+			}
 			pjdlog_debug(2,
 			    "ggate_recv: (%p) Moving request to the send queues.",
 			    hio);

Modified: projects/largeSMP/sbin/hastd/secondary.c
==============================================================================
--- projects/largeSMP/sbin/hastd/secondary.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sbin/hastd/secondary.c	Mon May 23 23:58:02 2011	(r222237)
@@ -612,6 +612,20 @@ recv_thread(void *arg)
 			QUEUE_INSERT(send, hio);
 			continue;
 		}
+		switch (hio->hio_cmd) {
+		case HIO_READ:
+			res->hr_stat_read++;
+			break;
+		case HIO_WRITE:
+			res->hr_stat_write++;
+			break;
+		case HIO_DELETE:
+			res->hr_stat_delete++;
+			break;
+		case HIO_FLUSH:
+			res->hr_stat_flush++;
+			break;
+		}
 		reqlog(LOG_DEBUG, 2, -1, hio,
 		    "recv: (%p) Got request header: ", hio);
 		if (hio->hio_cmd == HIO_KEEPALIVE) {

Modified: projects/largeSMP/sbin/hastd/subr.c
==============================================================================
--- projects/largeSMP/sbin/hastd/subr.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sbin/hastd/subr.c	Mon May 23 23:58:02 2011	(r222237)
@@ -224,7 +224,13 @@ drop_privs(struct hast_resource *res)
 		return (-1);
 	}
 
-	if (res == NULL || res->hr_role != HAST_ROLE_PRIMARY)
+	/*
+	 * Until capsicum doesn't allow ioctl(2) we cannot use it to sandbox
+	 * primary and secondary worker processes, as primary uses GGATE
+	 * ioctls and secondary uses ioctls to handle BIO_DELETE and BIO_FLUSH.
+	 * For now capsicum is only used to sandbox hastctl.
+	 */
+	if (res == NULL)
 		capsicum = (cap_enter() == 0);
 	else
 		capsicum = false;

Modified: projects/largeSMP/share/man/man4/msk.4
==============================================================================
--- projects/largeSMP/share/man/man4/msk.4	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/share/man/man4/msk.4	Mon May 23 23:58:02 2011	(r222237)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 23, 2010
+.Dd May 23, 2011
 .Dt MSK 4
 .Os
 .Sh NAME
@@ -195,6 +195,8 @@ Marvell Yukon 88E8071 Gigabit Ethernet
 .It
 Marvell Yukon 88E8072 Gigabit Ethernet
 .It
+Marvell Yukon 88E8075 Gigabit Ethernet
+.It
 SysKonnect SK-9Sxx Gigabit Ethernet
 .It
 SysKonnect SK-9Exx Gigabit Ethernet

Modified: projects/largeSMP/sys/conf/kern.post.mk
==============================================================================
--- projects/largeSMP/sys/conf/kern.post.mk	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/conf/kern.post.mk	Mon May 23 23:58:02 2011	(r222237)
@@ -228,7 +228,7 @@ kernel-install:
 	mkdir -p ${DESTDIR}${KODIR}
 	${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO} ${DESTDIR}${KODIR}
 .if defined(DEBUG) && !defined(INSTALL_NODEBUG) && \
-    (defined(MK_KERNEL_SYMBOLS) && ${MK_KERNEL_SYMBOLS} == "yes")
+    (defined(MK_KERNEL_SYMBOLS) && ${MK_KERNEL_SYMBOLS} != "no")
 	${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO}.symbols ${DESTDIR}${KODIR}
 .endif
 .if defined(KERNEL_EXTRA_INSTALL)
@@ -241,7 +241,7 @@ kernel-reinstall:
 	@-chflags -R noschg ${DESTDIR}${KODIR}
 	${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO} ${DESTDIR}${KODIR}
 .if defined(DEBUG) && !defined(INSTALL_NODEBUG) && \
-    (defined(MK_KERNEL_SYMBOLS) && ${MK_KERNEL_SYMBOLS} == "yes")
+    (defined(MK_KERNEL_SYMBOLS) && ${MK_KERNEL_SYMBOLS} != "no")
 	${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO}.symbols ${DESTDIR}${KODIR}
 .endif
 

Modified: projects/largeSMP/sys/conf/kmod.mk
==============================================================================
--- projects/largeSMP/sys/conf/kmod.mk	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/conf/kmod.mk	Mon May 23 23:58:02 2011	(r222237)
@@ -286,8 +286,8 @@ realinstall: _kmodinstall
 _kmodinstall:
 	${INSTALL} -o ${KMODOWN} -g ${KMODGRP} -m ${KMODMODE} \
 	    ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${KMODDIR}
-.if defined(DEBUG) && !defined(INSTALL_NODEBUG) && \
-    (defined(MK_KERNEL_SYMBOLS) && ${MK_KERNEL_SYMBOLS} == "yes")
+.if defined(DEBUG_FLAGS) && !defined(INSTALL_NODEBUG) && \
+    (defined(MK_KERNEL_SYMBOLS) && ${MK_KERNEL_SYMBOLS} != "no")
 	${INSTALL} -o ${KMODOWN} -g ${KMODGRP} -m ${KMODMODE} \
 	    ${_INSTALLFLAGS} ${PROG}.symbols ${DESTDIR}${KMODDIR}
 .endif

Modified: projects/largeSMP/sys/conf/newvers.sh
==============================================================================
--- projects/largeSMP/sys/conf/newvers.sh	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/conf/newvers.sh	Mon May 23 23:58:02 2011	(r222237)
@@ -139,4 +139,4 @@ int osreldate = ${RELDATE};
 char kern_ident[] = "${i}";
 EOF
 
-echo `expr ${v} + 1` > version
+echo $((v + 1)) > version

Modified: projects/largeSMP/sys/dev/acpica/acpi_hpet.c
==============================================================================
--- projects/largeSMP/sys/dev/acpica/acpi_hpet.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/dev/acpica/acpi_hpet.c	Mon May 23 23:58:02 2011	(r222237)
@@ -476,7 +476,7 @@ hpet_attach(device_t dev)
 		sc->tc.tc_get_timecount = hpet_get_timecount,
 		sc->tc.tc_counter_mask = ~0u,
 		sc->tc.tc_name = "HPET",
-		sc->tc.tc_quality = 900,
+		sc->tc.tc_quality = 950,
 		sc->tc.tc_frequency = sc->freq;
 		sc->tc.tc_priv = sc;
 		tc_init(&sc->tc);

Modified: projects/largeSMP/sys/dev/acpica/acpi_timer.c
==============================================================================
--- projects/largeSMP/sys/dev/acpica/acpi_timer.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/dev/acpica/acpi_timer.c	Mon May 23 23:58:02 2011	(r222237)
@@ -203,7 +203,7 @@ acpi_timer_probe(device_t dev)
     if (j == 10) {
 	acpi_timer_timecounter.tc_name = "ACPI-fast";
 	acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount;
-	acpi_timer_timecounter.tc_quality = 1000;
+	acpi_timer_timecounter.tc_quality = 900;
     } else {
 	acpi_timer_timecounter.tc_name = "ACPI-safe";
 	acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount_safe;

Modified: projects/largeSMP/sys/dev/msk/if_msk.c
==============================================================================
--- projects/largeSMP/sys/dev/msk/if_msk.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/dev/msk/if_msk.c	Mon May 23 23:58:02 2011	(r222237)
@@ -221,6 +221,10 @@ static struct msk_product {
 	    "Marvell Yukon 88E8071 Gigabit Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_436C,
 	    "Marvell Yukon 88E8072 Gigabit Ethernet" },
+	{ VENDORID_MARVELL, DEVICEID_MRVL_436D,
+	    "Marvell Yukon 88E8055 Gigabit Ethernet" },
+	{ VENDORID_MARVELL, DEVICEID_MRVL_4370,
+	    "Marvell Yukon 88E8075 Gigabit Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_4380,
 	    "Marvell Yukon 88E8057 Gigabit Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_4381,
@@ -1030,7 +1034,10 @@ msk_ioctl(struct ifnet *ifp, u_long comm
 				}
 			}
 			ifp->if_mtu = ifr->ifr_mtu;
-			msk_init_locked(sc_if);
+			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+				msk_init_locked(sc_if);
+			}
 		}
 		MSK_IF_UNLOCK(sc_if);
 		break;
@@ -1212,37 +1219,30 @@ msk_phy_power(struct msk_softc *sc, int 
 		 */
 		CSR_WRITE_1(sc, B2_Y2_CLK_GATE, val);
 
-		val = CSR_PCI_READ_4(sc, PCI_OUR_REG_1);
-		val &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+		our = CSR_PCI_READ_4(sc, PCI_OUR_REG_1);
+		our &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
 		if (sc->msk_hw_id == CHIP_ID_YUKON_XL) {
 			if (sc->msk_hw_rev > CHIP_REV_YU_XL_A1) {
 				/* Deassert Low Power for 1st PHY. */
-				val |= PCI_Y2_PHY1_COMA;
+				our |= PCI_Y2_PHY1_COMA;
 				if (sc->msk_num_port > 1)
-					val |= PCI_Y2_PHY2_COMA;
+					our |= PCI_Y2_PHY2_COMA;
 			}
 		}
-		/* Release PHY from PowerDown/COMA mode. */
-		CSR_PCI_WRITE_4(sc, PCI_OUR_REG_1, val);
-		switch (sc->msk_hw_id) {
-		case CHIP_ID_YUKON_EC_U:
-		case CHIP_ID_YUKON_EX:
-		case CHIP_ID_YUKON_FE_P:
-		case CHIP_ID_YUKON_UL_2:
-		case CHIP_ID_YUKON_OPT:
-			CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_OFF);
-
-			/* Enable all clocks. */
-			CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, 0);
-			our = CSR_PCI_READ_4(sc, PCI_OUR_REG_4);
-			our &= (PCI_FORCE_ASPM_REQUEST|PCI_ASPM_GPHY_LINK_DOWN|
-			    PCI_ASPM_INT_FIFO_EMPTY|PCI_ASPM_CLKRUN_REQUEST);
+		if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U ||
+		    sc->msk_hw_id == CHIP_ID_YUKON_EX ||
+		    sc->msk_hw_id >= CHIP_ID_YUKON_FE_P) {
+			val = CSR_PCI_READ_4(sc, PCI_OUR_REG_4);
+			val &= (PCI_FORCE_ASPM_REQUEST |
+			    PCI_ASPM_GPHY_LINK_DOWN | PCI_ASPM_INT_FIFO_EMPTY |
+			    PCI_ASPM_CLKRUN_REQUEST);
 			/* Set all bits to 0 except bits 15..12. */
-			CSR_PCI_WRITE_4(sc, PCI_OUR_REG_4, our);
-			our = CSR_PCI_READ_4(sc, PCI_OUR_REG_5);
-			our &= PCI_CTL_TIM_VMAIN_AV_MSK;
-			CSR_PCI_WRITE_4(sc, PCI_OUR_REG_5, our);
+			CSR_PCI_WRITE_4(sc, PCI_OUR_REG_4, val);
+			val = CSR_PCI_READ_4(sc, PCI_OUR_REG_5);
+			val &= PCI_CTL_TIM_VMAIN_AV_MSK;
+			CSR_PCI_WRITE_4(sc, PCI_OUR_REG_5, val);
 			CSR_PCI_WRITE_4(sc, PCI_CFG_REG_1, 0);
+			CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_ON);
 			/*
 			 * Disable status race, workaround for
 			 * Yukon EC Ultra & Yukon EX.
@@ -1251,10 +1251,10 @@ msk_phy_power(struct msk_softc *sc, int 
 			val |= GLB_GPIO_STAT_RACE_DIS;
 			CSR_WRITE_4(sc, B2_GP_IO, val);
 			CSR_READ_4(sc, B2_GP_IO);
-			break;
-		default:
-			break;
 		}
+		/* Release PHY from PowerDown/COMA mode. */
+		CSR_PCI_WRITE_4(sc, PCI_OUR_REG_1, our);
+
 		for (i = 0; i < sc->msk_num_port; i++) {
 			CSR_WRITE_2(sc, MR_ADDR(i, GMAC_LINK_CTRL),
 			    GMLC_RST_SET);
@@ -1300,28 +1300,33 @@ mskc_reset(struct msk_softc *sc)
 	bus_addr_t addr;
 	uint16_t status;
 	uint32_t val;
-	int i;
-
-	CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
+	int i, initram;
 
 	/* Disable ASF. */
-	if (sc->msk_hw_id == CHIP_ID_YUKON_EX) {
-		status = CSR_READ_2(sc, B28_Y2_ASF_HCU_CCSR);
-		/* Clear AHB bridge & microcontroller reset. */
-		status &= ~(Y2_ASF_HCU_CCSR_AHB_RST |
-		    Y2_ASF_HCU_CCSR_CPU_RST_MODE);
-		/* Clear ASF microcontroller state. */
-		status &= ~ Y2_ASF_HCU_CCSR_UC_STATE_MSK;
-		CSR_WRITE_2(sc, B28_Y2_ASF_HCU_CCSR, status);
-	} else
-		CSR_WRITE_1(sc, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
-	CSR_WRITE_2(sc, B0_CTST, Y2_ASF_DISABLE);
-
-	/*
-	 * Since we disabled ASF, S/W reset is required for Power Management.
-	 */
-	CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
-	CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
+	if (sc->msk_hw_id >= CHIP_ID_YUKON_XL &&
+	    sc->msk_hw_id <= CHIP_ID_YUKON_SUPR) {
+		if (sc->msk_hw_id == CHIP_ID_YUKON_EX ||
+		    sc->msk_hw_id == CHIP_ID_YUKON_SUPR) {
+			CSR_WRITE_4(sc, B28_Y2_CPU_WDOG, 0);
+			status = CSR_READ_2(sc, B28_Y2_ASF_HCU_CCSR);
+			/* Clear AHB bridge & microcontroller reset. */
+			status &= ~(Y2_ASF_HCU_CCSR_AHB_RST |
+			    Y2_ASF_HCU_CCSR_CPU_RST_MODE);
+			/* Clear ASF microcontroller state. */
+			status &= ~Y2_ASF_HCU_CCSR_UC_STATE_MSK;
+			status &= ~Y2_ASF_HCU_CCSR_CPU_CLK_DIVIDE_MSK;
+			CSR_WRITE_2(sc, B28_Y2_ASF_HCU_CCSR, status);
+			CSR_WRITE_4(sc, B28_Y2_CPU_WDOG, 0);
+		} else
+			CSR_WRITE_1(sc, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
+		CSR_WRITE_2(sc, B0_CTST, Y2_ASF_DISABLE);
+		/*
+		 * Since we disabled ASF, S/W reset is required for
+		 * Power Management.
+		 */
+		CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
+		CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
+	}
 
 	/* Clear all error bits in the PCI status register. */
 	status = pci_read_config(sc->msk_dev, PCIR_STATUS, 2);
@@ -1362,17 +1367,22 @@ mskc_reset(struct msk_softc *sc)
 	/* Reset GPHY/GMAC Control */
 	for (i = 0; i < sc->msk_num_port; i++) {
 		/* GPHY Control reset. */
-		CSR_WRITE_4(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_SET);
-		CSR_WRITE_4(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_CLR);
+		CSR_WRITE_1(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_SET);
+		CSR_WRITE_1(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_CLR);
 		/* GMAC Control reset. */
 		CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_SET);
 		CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_CLR);
 		CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_F_LOOPB_OFF);
-		if (sc->msk_hw_id == CHIP_ID_YUKON_EX)
+		if (sc->msk_hw_id == CHIP_ID_YUKON_EX ||
+		    sc->msk_hw_id == CHIP_ID_YUKON_SUPR)
 			CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL),
 			    GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON |
 			    GMC_BYP_RETR_ON);
 	}
+
+	if (sc->msk_hw_id == CHIP_ID_YUKON_SUPR &&
+	    sc->msk_hw_rev > CHIP_REV_YU_SU_B0)
+		CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, PCI_CLK_MACSEC_DIS);
 	if (sc->msk_hw_id == CHIP_ID_YUKON_OPT && sc->msk_hw_rev == 0) {
 		/* Disable PCIe PHY powerdown(reg 0x80, bit7). */
 		CSR_WRITE_4(sc, Y2_PEX_PHY_DATA, (0x0080 << 16) | 0x0080);
@@ -1396,8 +1406,14 @@ mskc_reset(struct msk_softc *sc)
 	CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_STOP);
 	CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
 
+	initram = 0;
+	if (sc->msk_hw_id == CHIP_ID_YUKON_XL ||
+	    sc->msk_hw_id == CHIP_ID_YUKON_EC ||
+	    sc->msk_hw_id == CHIP_ID_YUKON_FE)
+		initram++;
+
 	/* Configure timeout values. */
-	for (i = 0; i < sc->msk_num_port; i++) {
+	for (i = 0; initram > 0 && i < sc->msk_num_port; i++) {
 		CSR_WRITE_2(sc, SELECT_RAM_BUFFER(i, B3_RI_CTRL), RI_RST_SET);
 		CSR_WRITE_2(sc, SELECT_RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR);
 		CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_R1),
@@ -1706,13 +1722,15 @@ mskc_attach(device_t dev)
 		}
 	}
 
+	/* Enable all clocks before accessing any registers. */
+	CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, 0);
+
 	CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
 	sc->msk_hw_id = CSR_READ_1(sc, B2_CHIP_ID);
 	sc->msk_hw_rev = (CSR_READ_1(sc, B2_MAC_CFG) >> 4) & 0x0f;
 	/* Bail out if chip is not recognized. */
 	if (sc->msk_hw_id < CHIP_ID_YUKON_XL ||
 	    sc->msk_hw_id > CHIP_ID_YUKON_OPT ||
-	    sc->msk_hw_id == CHIP_ID_YUKON_SUPR ||
 	    sc->msk_hw_id == CHIP_ID_YUKON_UNKNOWN) {
 		device_printf(dev, "unknown device: id=0x%02x, rev=0x%02x\n",
 		    sc->msk_hw_id, sc->msk_hw_rev);
@@ -1746,9 +1764,6 @@ mskc_attach(device_t dev)
 	resource_int_value(device_get_name(dev), device_get_unit(dev),
 	    "int_holdoff", &sc->msk_int_holdoff);
 
-	/* Soft reset. */
-	CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
-	CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
 	sc->msk_pmd = CSR_READ_1(sc, B2_PMD_TYP);
 	/* Check number of MACs. */
 	sc->msk_num_port = 1;
@@ -1822,6 +1837,11 @@ mskc_attach(device_t dev)
 		sc->msk_clock = 156;	/* 156 MHz */
 		sc->msk_pflags |= MSK_FLAG_JUMBO;
 		break;
+	case CHIP_ID_YUKON_SUPR:
+		sc->msk_clock = 125;	/* 125 MHz */
+		sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_DESCV2 |
+		    MSK_FLAG_AUTOTX_CSUM;
+		break;
 	case CHIP_ID_YUKON_UL_2:
 		sc->msk_clock = 125;	/* 125 MHz */
 		sc->msk_pflags |= MSK_FLAG_JUMBO;
@@ -2963,6 +2983,7 @@ mskc_resume(device_t dev)
 
 	MSK_LOCK(sc);
 
+	CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, 0);
 	mskc_reset(sc);
 	for (i = 0; i < sc->msk_num_port; i++) {
 		if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL &&
@@ -3654,37 +3675,24 @@ msk_set_tx_stfwd(struct msk_if_softc *sc
 
 	ifp = sc_if->msk_ifp;
 	sc = sc_if->msk_softc;
-	switch (sc->msk_hw_id) {
-	case CHIP_ID_YUKON_EX:
-		if (sc->msk_hw_rev == CHIP_REV_YU_EX_A0)
-			goto yukon_ex_workaround;
-		if (ifp->if_mtu > ETHERMTU)
-			CSR_WRITE_4(sc,
-			    MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
-			    TX_JUMBO_ENA | TX_STFW_ENA);
-		else
-			CSR_WRITE_4(sc,
-			    MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
-			    TX_JUMBO_DIS | TX_STFW_ENA);
-		break;
-	default:
-yukon_ex_workaround:
+	if ((sc->msk_hw_id == CHIP_ID_YUKON_EX &&
+	    sc->msk_hw_rev != CHIP_REV_YU_EX_A0) ||
+	    sc->msk_hw_id >= CHIP_ID_YUKON_SUPR) {
+		CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
+		    TX_STFW_ENA);
+	} else {
 		if (ifp->if_mtu > ETHERMTU) {
 			/* Set Tx GMAC FIFO Almost Empty Threshold. */
 			CSR_WRITE_4(sc,
 			    MR_ADDR(sc_if->msk_port, TX_GMF_AE_THR),
 			    MSK_ECU_JUMBO_WM << 16 | MSK_ECU_AE_THR);
 			/* Disable Store & Forward mode for Tx. */
-			CSR_WRITE_4(sc,
-			    MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
-			    TX_JUMBO_ENA | TX_STFW_DIS);
+			CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
+			    TX_STFW_DIS);
 		} else {
-			/* Enable Store & Forward mode for Tx. */
-			CSR_WRITE_4(sc,
-			    MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
-			    TX_JUMBO_DIS | TX_STFW_ENA);
+			CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
+			    TX_STFW_ENA);
 		}
-		break;
 	}
 }
 
@@ -3737,7 +3745,8 @@ msk_init_locked(struct msk_if_softc *sc_
  	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_SET);
  	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_CLR);
  	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_F_LOOPB_OFF);
-	if (sc->msk_hw_id == CHIP_ID_YUKON_EX)
+	if (sc->msk_hw_id == CHIP_ID_YUKON_EX ||
+	    sc->msk_hw_id == CHIP_ID_YUKON_SUPR)
 		CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL),
 		    GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON |
 		    GMC_BYP_RETR_ON);
@@ -3932,7 +3941,8 @@ msk_init_locked(struct msk_if_softc *sc_
 		msk_stop(sc_if);
 		return;
 	}
-	if (sc->msk_hw_id == CHIP_ID_YUKON_EX) {
+	if (sc->msk_hw_id == CHIP_ID_YUKON_EX ||
+	    sc->msk_hw_id == CHIP_ID_YUKON_SUPR) {
 		/* Disable flushing of non-ASF packets. */
 		CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T),
 		    GMF_RX_MACSEC_FLUSH_OFF);

Modified: projects/largeSMP/sys/dev/msk/if_mskreg.h
==============================================================================
--- projects/largeSMP/sys/dev/msk/if_mskreg.h	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/dev/msk/if_mskreg.h	Mon May 23 23:58:02 2011	(r222237)
@@ -144,6 +144,8 @@
 #define DEVICEID_MRVL_436A	0x436A
 #define DEVICEID_MRVL_436B	0x436B
 #define DEVICEID_MRVL_436C	0x436C
+#define DEVICEID_MRVL_436D	0x436D
+#define DEVICEID_MRVL_4370	0x4370
 #define DEVICEID_MRVL_4380	0x4380
 #define DEVICEID_MRVL_4381	0x4381
 
@@ -321,6 +323,9 @@
 #define PCI_OS_SPD_X100		2	/* PCI-X 100MHz Bus */
 #define PCI_OS_SPD_X133		3	/* PCI-X 133MHz Bus */
 
+/* PCI_OUR_REG_3	32 bit	Our Register 3 (Yukon-ECU only) */
+#define	PCI_CLK_MACSEC_DIS	BIT_17	/* Disable Clock MACSec. */
+
 /* PCI_OUR_REG_4	32 bit	Our Register 4 (Yukon-ECU only) */
 #define	PCI_TIMER_VALUE_MSK	(0xff<<16)	/* Bit 23..16:	Timer Value Mask */
 #define	PCI_FORCE_ASPM_REQUEST	BIT_15	/* Force ASPM Request (A1 only) */
@@ -677,6 +682,7 @@
 /* ASF Subsystem Registers (Yukon-2 only) */
 #define B28_Y2_SMB_CONFIG	0x0e40	/* 32 bit ASF SMBus Config Register */
 #define B28_Y2_SMB_CSD_REG	0x0e44	/* 32 bit ASF SMB Control/Status/Data */
+#define B28_Y2_CPU_WDOG		0x0e48	/* 32 bit Watchdog Register */
 #define B28_Y2_ASF_IRQ_V_BASE	0x0e60	/* 32 bit ASF IRQ Vector Base */
 #define B28_Y2_ASF_STAT_CMD	0x0e68	/* 32 bit ASF Status and Command Reg */
 #define B28_Y2_ASF_HCU_CCSR	0x0e68	/* 32 bit ASF HCU CCSR (Yukon EX) */
@@ -918,6 +924,10 @@
 #define	CHIP_REV_YU_EX_A0	1 /* Chip Rev. for Yukon-2 EX A0 */
 #define	CHIP_REV_YU_EX_B0	2 /* Chip Rev. for Yukon-2 EX B0 */
 
+#define	CHIP_REV_YU_SU_A0	0 /* Chip Rev. for Yukon-2 SUPR A0 */
+#define	CHIP_REV_YU_SU_B0	1 /* Chip Rev. for Yukon-2 SUPR B0 */
+#define	CHIP_REV_YU_SU_B1	3 /* Chip Rev. for Yukon-2 SUPR B1 */
+
 /*	B2_Y2_CLK_GATE	 8 bit	Clock Gating (Yukon-2 only) */
 #define Y2_STATUS_LNK2_INAC	BIT_7	/* Status Link 2 inactiv (0 = activ) */
 #define Y2_CLK_GAT_LNK2_DIS	BIT_6	/* Disable clock gating Link 2 */

Modified: projects/largeSMP/sys/fs/nfsclient/nfs_clvfsops.c
==============================================================================
--- projects/largeSMP/sys/fs/nfsclient/nfs_clvfsops.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/fs/nfsclient/nfs_clvfsops.c	Mon May 23 23:58:02 2011	(r222237)
@@ -79,6 +79,7 @@ FEATURE(nfscl, "NFSv4 client");
 extern int nfscl_ticks;
 extern struct timeval nfsboottime;
 extern struct nfsstats	newnfsstats;
+extern int nfsrv_useacl;
 
 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
@@ -1331,6 +1332,15 @@ mountnfs(struct nfs_args *argp, struct m
 		if (argp->flags & NFSMNT_NFSV3)
 			ncl_fsinfo(nmp, *vpp, cred, td);
 	
+		/* Mark if the mount point supports NFSv4 ACLs. */
+		if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
+		    ret == 0 &&
+		    NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
+			MNT_ILOCK(mp);
+			mp->mnt_flag |= MNT_NFS4ACLS;
+			MNT_IUNLOCK(mp);
+		}
+	
 		/*
 		 * Lose the lock but keep the ref.
 		 */

Modified: projects/largeSMP/sys/geom/gate/g_gate.c
==============================================================================
--- projects/largeSMP/sys/geom/gate/g_gate.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/geom/gate/g_gate.c	Mon May 23 23:58:02 2011	(r222237)
@@ -180,6 +180,7 @@ g_gate_start(struct bio *bp)
 		break;
 	case BIO_DELETE:
 	case BIO_WRITE:
+	case BIO_FLUSH:
 		/* XXX: Hack to allow read-only mounts. */
 		if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0) {
 			g_io_deliver(bp, EPERM);
@@ -580,6 +581,7 @@ g_gate_ioctl(struct cdev *dev, u_long cm
 		switch (bp->bio_cmd) {
 		case BIO_READ:
 		case BIO_DELETE:
+		case BIO_FLUSH:
 			break;
 		case BIO_WRITE:
 			error = copyout(bp->bio_data, ggio->gctl_data,
@@ -643,6 +645,7 @@ start_end:
 					break;
 				case BIO_DELETE:
 				case BIO_WRITE:
+				case BIO_FLUSH:
 					break;
 				}
 			}

Modified: projects/largeSMP/sys/kern/kern_environment.c
==============================================================================
--- projects/largeSMP/sys/kern/kern_environment.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/kern/kern_environment.c	Mon May 23 23:58:02 2011	(r222237)
@@ -225,13 +225,19 @@ static void
 init_dynamic_kenv(void *data __unused)
 {
 	char *cp;
-	int len, i;
+	size_t len;
+	int i;
 
 	kenvp = malloc((KENV_SIZE + 1) * sizeof(char *), M_KENV,
 		M_WAITOK | M_ZERO);
 	i = 0;
 	for (cp = kern_envp; cp != NULL; cp = kernenv_next(cp)) {
 		len = strlen(cp) + 1;
+		if (len > KENV_MNAMELEN + 1 + KENV_MVALLEN + 1) {
+			printf("WARNING: too long kenv string, ignoring %s\n",
+			    cp);
+			continue;
+		}
 		if (i < KENV_SIZE) {
 			kenvp[i] = malloc(len, M_KENV, M_WAITOK);
 			strcpy(kenvp[i++], cp);

Modified: projects/largeSMP/sys/kern/vfs_bio.c
==============================================================================
--- projects/largeSMP/sys/kern/vfs_bio.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/kern/vfs_bio.c	Mon May 23 23:58:02 2011	(r222237)
@@ -654,7 +654,7 @@ bufinit(void)
  * To support extreme low-memory systems, make sure hidirtybuffers cannot
  * eat up all available buffer space.  This occurs when our minimum cannot
  * be met.  We try to size hidirtybuffers to 3/4 our buffer space assuming
- * BKVASIZE'd (8K) buffers.
+ * BKVASIZE'd buffers.
  */
 	while ((long)hidirtybuffers * BKVASIZE > 3 * hibufspace / 4) {
 		hidirtybuffers >>= 1;

Modified: projects/largeSMP/sys/netinet/in_pcb.c
==============================================================================
--- projects/largeSMP/sys/netinet/in_pcb.c	Mon May 23 23:51:01 2011	(r222236)
+++ projects/largeSMP/sys/netinet/in_pcb.c	Mon May 23 23:58:02 2011	(r222237)
@@ -2,8 +2,12 @@
  * Copyright (c) 1982, 1986, 1991, 1993, 1995
  *	The Regents of the University of California.
  * Copyright (c) 2007-2009 Robert N. M. Watson
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
  * All rights reserved.
  *
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -50,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/socketvar.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
+#include <sys/refcount.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
@@ -287,7 +292,7 @@ in_pcballoc(struct socket *so, struct in
 #endif
 	INP_WLOCK(inp);
 	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
-	inp->inp_refcount = 1;	/* Reference from the inpcbinfo */
+	refcount_init(&inp->inp_refcount, 1);	/* Reference from inpcbinfo */
 #if defined(IPSEC) || defined(MAC)
 out:
 	if (error != 0) {
@@ -329,7 +334,7 @@ in_pcbbind(struct inpcb *inp, struct soc
 #if defined(INET) || defined(INET6)
 int
 in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
-    struct ucred *cred, int wild)
+    struct ucred *cred, int lookupflags)
 {
 	struct inpcbinfo *pcbinfo;
 	struct inpcb *tmpinp;
@@ -424,14 +429,14 @@ in_pcb_lport(struct inpcb *inp, struct i
 #ifdef INET6
 		if ((inp->inp_vflag & INP_IPV6) != 0)
 			tmpinp = in6_pcblookup_local(pcbinfo,
-			    &inp->in6p_laddr, lport, wild, cred);
+			    &inp->in6p_laddr, lport, lookupflags, cred);
 #endif
 #if defined(INET) && defined(INET6)
 		else
 #endif
 #ifdef INET
 			tmpinp = in_pcblookup_local(pcbinfo, laddr,
-			    lport, wild, cred);
+			    lport, lookupflags, cred);
 #endif
 	} while (tmpinp != NULL);
 
@@ -464,7 +469,7 @@ in_pcbbind_setup(struct inpcb *inp, stru
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct in_addr laddr;
 	u_short lport = 0;
-	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
+	int lookupflags = 0, reuseport = (so->so_options & SO_REUSEPORT);
 	int error;
 
 	/*
@@ -480,7 +485,7 @@ in_pcbbind_setup(struct inpcb *inp, stru
 	if (nam != NULL && laddr.s_addr != INADDR_ANY)
 		return (EINVAL);
 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
-		wild = INPLOOKUP_WILDCARD;
+		lookupflags = INPLOOKUP_WILDCARD;
 	if (nam == NULL) {
 		if ((error = prison_local_ip4(cred, &laddr)) != 0)
 			return (error);
@@ -561,7 +566,7 @@ in_pcbbind_setup(struct inpcb *inp, stru
 					return (EADDRINUSE);
 			}
 			t = in_pcblookup_local(pcbinfo, sin->sin_addr,
-			    lport, wild, cred);
+			    lport, lookupflags, cred);
 			if (t && (t->inp_flags & INP_TIMEWAIT)) {
 				/*
 				 * XXXRW: If an incpb has had its timewait
@@ -590,7 +595,7 @@ in_pcbbind_setup(struct inpcb *inp, stru
 	if (*lportp != 0)
 		lport = *lportp;
 	if (lport == 0) {
-		error = in_pcb_lport(inp, &laddr, &lport, cred, wild);
+		error = in_pcb_lport(inp, &laddr, &lport, cred, lookupflags);
 		if (error != 0)
 			return (error);
 
@@ -1028,56 +1033,18 @@ in_pcbdetach(struct inpcb *inp)
 }
 
 /*
- * in_pcbfree_internal() frees an inpcb that has been detached from its
- * socket, and whose reference count has reached 0.  It will also remove the
- * inpcb from any global lists it might remain on.
- */
-static void
-in_pcbfree_internal(struct inpcb *inp)
-{
-	struct inpcbinfo *ipi = inp->inp_pcbinfo;
-
-	KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
-	KASSERT(inp->inp_refcount == 0, ("%s: refcount !0", __func__));
-
-	INP_INFO_WLOCK_ASSERT(ipi);
-	INP_WLOCK_ASSERT(inp);
-
-#ifdef IPSEC
-	if (inp->inp_sp != NULL)
-		ipsec_delete_pcbpolicy(inp);
-#endif /* IPSEC */
-	inp->inp_gencnt = ++ipi->ipi_gencnt;
-	in_pcbremlists(inp);
-#ifdef INET6
-	if (inp->inp_vflag & INP_IPV6PROTO) {
-		ip6_freepcbopts(inp->in6p_outputopts);
-		if (inp->in6p_moptions != NULL)
-			ip6_freemoptions(inp->in6p_moptions);
-	}
-#endif
-	if (inp->inp_options)
-		(void)m_free(inp->inp_options);
-#ifdef INET
-	if (inp->inp_moptions != NULL)
-		inp_freemoptions(inp->inp_moptions);
-#endif
-	inp->inp_vflag = 0;
-	crfree(inp->inp_cred);
-
-#ifdef MAC
-	mac_inpcb_destroy(inp);
-#endif
-	INP_WUNLOCK(inp);
-	uma_zfree(ipi->ipi_zone, inp);
-}
-
-/*
  * in_pcbref() bumps the reference count on an inpcb in order to maintain
  * stability of an inpcb pointer despite the inpcb lock being released.  This
  * is used in TCP when the inpcbinfo lock needs to be acquired or upgraded,
  * but where the inpcb lock is already held.
  *
+ * in_pcbref() should be used only to provide brief memory stability, and
+ * must always be followed by a call to INP_WLOCK() and in_pcbrele() to
+ * garbage collect the inpcb if it has been in_pcbfree()'d from another
+ * context.  Until in_pcbrele() has returned that the inpcb is still valid,
+ * lock and rele are the *only* safe operations that may be performed on the
+ * inpcb.
+ *
  * While the inpcb will not be freed, releasing the inpcb lock means that the
  * connection's state may change, so the caller should be careful to
  * revalidate any cached state on reacquiring the lock.  Drop the reference
@@ -1091,7 +1058,7 @@ in_pcbref(struct inpcb *inp)
 
 	KASSERT(inp->inp_refcount > 0, ("%s: refcount 0", __func__));
 
-	inp->inp_refcount++;
+	refcount_acquire(&inp->inp_refcount);
 }
 
 /*
@@ -1099,47 +1066,108 @@ in_pcbref(struct inpcb *inp)
  * in_pcbfree() may have been made between in_pcbref() and in_pcbrele(), we
  * return a flag indicating whether or not the inpcb remains valid.  If it is
  * valid, we return with the inpcb lock held.
+ *
+ * Notice that, unlike in_pcbref(), the inpcb lock must be held to drop a
+ * reference on an inpcb.  Historically more work was done here (actually, in
+ * in_pcbfree_internal()) but has been moved to in_pcbfree() to avoid the
+ * need for the pcbinfo lock in in_pcbrele().  Deferring the free is entirely
+ * about memory stability (and continued use of the write lock).
  */
 int
-in_pcbrele(struct inpcb *inp)
+in_pcbrele_rlocked(struct inpcb *inp)
 {
-#ifdef INVARIANTS
-	struct inpcbinfo *ipi = inp->inp_pcbinfo;
-#endif
+	struct inpcbinfo *pcbinfo;
+
+	KASSERT(inp->inp_refcount > 0, ("%s: refcount 0", __func__));
+
+	INP_RLOCK_ASSERT(inp);
+
+	if (refcount_release(&inp->inp_refcount) == 0)
+		return (0);
+
+	KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
+
+	INP_RUNLOCK(inp);
+	pcbinfo = inp->inp_pcbinfo;
+	uma_zfree(pcbinfo->ipi_zone, inp);
+	return (1);
+}
+
+int
+in_pcbrele_wlocked(struct inpcb *inp)
+{
+	struct inpcbinfo *pcbinfo;
 
 	KASSERT(inp->inp_refcount > 0, ("%s: refcount 0", __func__));
 
-	INP_INFO_WLOCK_ASSERT(ipi);
 	INP_WLOCK_ASSERT(inp);
 
-	inp->inp_refcount--;
-	if (inp->inp_refcount > 0)
+	if (refcount_release(&inp->inp_refcount) == 0)
 		return (0);
-	in_pcbfree_internal(inp);
+
+	KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
+
+	INP_WUNLOCK(inp);
+	pcbinfo = inp->inp_pcbinfo;
+	uma_zfree(pcbinfo->ipi_zone, inp);
 	return (1);
 }
 
 /*
+ * Temporary wrapper.
+ */
+int
+in_pcbrele(struct inpcb *inp)
+{
+
+	return (in_pcbrele_wlocked(inp));
+}
+
+/*
  * Unconditionally schedule an inpcb to be freed by decrementing its
  * reference count, which should occur only after the inpcb has been detached
  * from its socket.  If another thread holds a temporary reference (acquired
  * using in_pcbref()) then the free is deferred until that reference is
- * released using in_pcbrele(), but the inpcb is still unlocked.
+ * released using in_pcbrele(), but the inpcb is still unlocked.  Almost all
+ * work, including removal from global lists, is done in this context, where
+ * the pcbinfo lock is held.
  */
 void
 in_pcbfree(struct inpcb *inp)
 {
-#ifdef INVARIANTS
-	struct inpcbinfo *ipi = inp->inp_pcbinfo;
-#endif
+	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
-	KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL",
-	    __func__));
+	KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
 
-	INP_INFO_WLOCK_ASSERT(ipi);
+	INP_INFO_WLOCK_ASSERT(pcbinfo);
 	INP_WLOCK_ASSERT(inp);
 
-	if (!in_pcbrele(inp))
+	/* XXXRW: Do as much as possible here. */
+#ifdef IPSEC
+	if (inp->inp_sp != NULL)
+		ipsec_delete_pcbpolicy(inp);
+#endif /* IPSEC */
+	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
+	in_pcbremlists(inp);
+#ifdef INET6
+	if (inp->inp_vflag & INP_IPV6PROTO) {
+		ip6_freepcbopts(inp->in6p_outputopts);
+		if (inp->in6p_moptions != NULL)
+			ip6_freemoptions(inp->in6p_moptions);
+	}
+#endif
+	if (inp->inp_options)
+		(void)m_free(inp->inp_options);
+#ifdef INET
+	if (inp->inp_moptions != NULL)
+		inp_freemoptions(inp->inp_moptions);
+#endif
+	inp->inp_vflag = 0;
+	crfree(inp->inp_cred);
+#ifdef MAC
+	mac_inpcb_destroy(inp);
+#endif
+	if (!in_pcbrele_wlocked(inp))
 		INP_WUNLOCK(inp);
 }
 
@@ -1307,7 +1335,7 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo
 #define INP_LOOKUP_MAPPED_PCB_COST	3
 struct inpcb *
 in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
-    u_short lport, int wild_okay, struct ucred *cred)
+    u_short lport, int lookupflags, struct ucred *cred)
 {
 	struct inpcb *inp;
 #ifdef INET6
@@ -1317,9 +1345,12 @@ in_pcblookup_local(struct inpcbinfo *pcb
 #endif
 	int wildcard;
 
+	KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
+	    ("%s: invalid lookup flags %d", __func__, lookupflags));
+
 	INP_INFO_LOCK_ASSERT(pcbinfo);
 
-	if (!wild_okay) {
+	if ((lookupflags & INPLOOKUP_WILDCARD) == 0) {
 		struct inpcbhead *head;
 		/*
 		 * Look for an unconnected (wildcard foreign addr) PCB that
@@ -1425,13 +1456,16 @@ in_pcblookup_local(struct inpcbinfo *pcb
  */
 struct inpcb *
 in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
-    u_int fport_arg, struct in_addr laddr, u_int lport_arg, int wildcard,
+    u_int fport_arg, struct in_addr laddr, u_int lport_arg, int lookupflags,
     struct ifnet *ifp)
 {
 	struct inpcbhead *head;
 	struct inpcb *inp, *tmpinp;
 	u_short fport = fport_arg, lport = lport_arg;
 
+	KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
+	    ("%s: invalid lookup flags %d", __func__, lookupflags));
+
 	INP_INFO_LOCK_ASSERT(pcbinfo);
 
 	/*
@@ -1467,7 +1501,7 @@ in_pcblookup_hash(struct inpcbinfo *pcbi

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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