From c01a79842c34ad06b62b2f069ed8a9d2e8a901b2 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Wed, 2 Nov 2016 17:32:31 +0000 Subject: [PATCH 001/127] 6051 lzc_receive: allow the caller to read the begin record illumos/illumos-gate@620f322510b2d6433f7f6af60fa52380c07756ad https://github.com/illumos/illumos-gate/commit/620f322510b2d6433f7f6af60fa52380c07756ad https://www.illumos.org/issues/6051 Currently lzc_receive() requires that its snapname argument is a snapshot name (contains ''). @zfs receive allows to specify just a dataset name and would try to deduce the snapshot name from the stream. I propose to allow lzc_receive() to do the same. That seems to be quite easy to implement, it requires only a small amount of logic, it does not require any additional system calls or any additional data from the stream. The benefit is that the new behavior would allow to keep the snapshot names the same between the sender and receiver at zero cost, without a need to pass the names out of band. Reviewed by: Matthew Ahrens Reviewed by: Paul Dagnelie Approved by: Robert Mustacchi Author: Andriy Gapon --- lib/libzfs_core/common/libzfs_core.c | 42 +++++++++++++++++++++++----- lib/libzfs_core/common/libzfs_core.h | 7 ++++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/libzfs_core/common/libzfs_core.c b/lib/libzfs_core/common/libzfs_core.c index c8e5df03600d..cc5e2a781bb2 100644 --- a/lib/libzfs_core/common/libzfs_core.c +++ b/lib/libzfs_core/common/libzfs_core.c @@ -549,8 +549,9 @@ recv_read(int fd, void *buf, int ilen) } static int -lzc_receive_impl(const char *snapname, nvlist_t *props, const char *origin, - boolean_t force, boolean_t resumable, int fd) +recv_impl(const char *snapname, nvlist_t *props, const char *origin, + boolean_t force, boolean_t resumable, int fd, + const dmu_replay_record_t *begin_record) { /* * The receive ioctl is still legacy, so we need to construct our own @@ -595,9 +596,14 @@ lzc_receive_impl(const char *snapname, nvlist_t *props, const char *origin, (void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string)); /* zc_begin_record is non-byteswapped BEGIN record */ - error = recv_read(fd, &zc.zc_begin_record, sizeof (zc.zc_begin_record)); - if (error != 0) - goto out; + if (begin_record == NULL) { + error = recv_read(fd, &zc.zc_begin_record, + sizeof (zc.zc_begin_record)); + if (error != 0) + goto out; + } else { + zc.zc_begin_record = *begin_record; + } /* zc_cookie is fd to read from */ zc.zc_cookie = fd; @@ -638,7 +644,7 @@ int lzc_receive(const char *snapname, nvlist_t *props, const char *origin, boolean_t force, int fd) { - return (lzc_receive_impl(snapname, props, origin, force, B_FALSE, fd)); + return (recv_impl(snapname, props, origin, force, B_FALSE, fd, NULL)); } /* @@ -651,7 +657,29 @@ int lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin, boolean_t force, int fd) { - return (lzc_receive_impl(snapname, props, origin, force, B_TRUE, fd)); + return (recv_impl(snapname, props, origin, force, B_TRUE, fd, NULL)); +} + +/* + * Like lzc_receive, but allows the caller to read the begin record and then to + * pass it in. That could be useful if the caller wants to derive, for example, + * the snapname or the origin parameters based on the information contained in + * the begin record. + * The begin record must be in its original form as read from the stream, + * in other words, it should not be byteswapped. + * + * The 'resumable' parameter allows to obtain the same behavior as with + * lzc_receive_resumable. + */ +int +lzc_receive_with_header(const char *snapname, nvlist_t *props, + const char *origin, boolean_t force, boolean_t resumable, int fd, + const dmu_replay_record_t *begin_record) +{ + if (begin_record == NULL) + return (EINVAL); + return (recv_impl(snapname, props, origin, force, resumable, fd, + begin_record)); } /* diff --git a/lib/libzfs_core/common/libzfs_core.h b/lib/libzfs_core/common/libzfs_core.h index f570c05aa656..6b4575ddebff 100644 --- a/lib/libzfs_core/common/libzfs_core.h +++ b/lib/libzfs_core/common/libzfs_core.h @@ -68,10 +68,15 @@ enum lzc_send_flags { int lzc_send(const char *, const char *, int, enum lzc_send_flags); int lzc_send_resume(const char *, const char *, int, enum lzc_send_flags, uint64_t, uint64_t); +int lzc_send_space(const char *, const char *, uint64_t *); + +struct dmu_replay_record; + int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int); int lzc_receive_resumable(const char *, nvlist_t *, const char *, boolean_t, int); -int lzc_send_space(const char *, const char *, uint64_t *); +int lzc_receive_with_header(const char *, nvlist_t *, const char *, boolean_t, + boolean_t, int, const struct dmu_replay_record *); boolean_t lzc_exists(const char *); From 75409ce1dd73241d28f5f8772ddd6c9f43a3ad9d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 2 Nov 2016 20:57:20 +0000 Subject: [PATCH 002/127] Remove remnants of the recursive sleep support. Instead assert that we never try to sleep while the thread is on a sleepqueue. Reviewed by: jhb Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D8422 --- sys/kern/kern_synch.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index a11743f9e3fc..fc02cb390444 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -170,13 +170,7 @@ _sleep(void *ident, struct lock_object *lock, int priority, catch = priority & PCATCH; pri = priority & PRIMASK; - /* - * If we are already on a sleep queue, then remove us from that - * sleep queue first. We have to do this to handle recursive - * sleeps. - */ - if (TD_ON_SLEEPQ(td)) - sleepq_remove(td, td->td_wchan); + KASSERT(!TD_ON_SLEEPQ(td), ("recursive sleep")); if ((uint8_t *)ident >= &pause_wchan[0] && (uint8_t *)ident <= &pause_wchan[MAXCPU - 1]) From 3c47cee5c871f35e1ae32cd07f7127f248545f73 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Wed, 2 Nov 2016 22:33:37 +0000 Subject: [PATCH 003/127] sh: Add simple test for 'set -C' (noclobber). To ensure fast test runs, race conditions are not tested. --- bin/sh/tests/execution/Makefile | 1 + bin/sh/tests/execution/set-C1.0 | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 bin/sh/tests/execution/set-C1.0 diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile index 92aecc854d15..1f92c1a835f7 100644 --- a/bin/sh/tests/execution/Makefile +++ b/bin/sh/tests/execution/Makefile @@ -37,6 +37,7 @@ ${PACKAGE}FILES+= redir4.0 ${PACKAGE}FILES+= redir5.0 ${PACKAGE}FILES+= redir6.0 ${PACKAGE}FILES+= redir7.0 +${PACKAGE}FILES+= set-C1.0 ${PACKAGE}FILES+= set-n1.0 ${PACKAGE}FILES+= set-n2.0 ${PACKAGE}FILES+= set-n3.0 diff --git a/bin/sh/tests/execution/set-C1.0 b/bin/sh/tests/execution/set-C1.0 new file mode 100644 index 000000000000..7877a33989b7 --- /dev/null +++ b/bin/sh/tests/execution/set-C1.0 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +T=$(mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX") || exit +trap 'rm -rf "$T"' 0 + +set -C +echo . >"$T/a" && +[ -s "$T/a" ] && +{ ! true >"$T/a"; } 2>/dev/null && +[ -s "$T/a" ] && +ln -s /dev/null "$T/b" && +true >"$T/b" From ea9e23edf392405750dd0bf886a038e8a5202e17 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Wed, 2 Nov 2016 23:18:16 +0000 Subject: [PATCH 004/127] ioat(4): Read CHANSTS register for suspended/halted checks The device doesn't accurately update the CHANCMP address with the device state when the device is suspended or halted. So, read the CHANSTS register to check for those states. We still need to read the CHANCMP address for the last completed descriptor. Sponsored by: Dell EMC Isilon --- sys/dev/ioat/ioat.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index 68c207a953f6..a434b4225348 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -747,6 +747,12 @@ ioat_process_events(struct ioat_softc *ioat) wakeup(&ioat->tail); } + /* + * The device doesn't seem to reliably push suspend/halt statuses to + * the channel completion memory address, so poll the device register + * here. + */ + comp_update = ioat_get_chansts(ioat) & IOAT_CHANSTS_STATUS; if (!is_ioat_halted(comp_update) && !is_ioat_suspended(comp_update)) return; From e8f58f1fb8b68f9c610f1c6a895458a11643c734 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Wed, 2 Nov 2016 23:43:18 +0000 Subject: [PATCH 005/127] Fix the build. protctl is only used on powerpc. While here, remove the need to check the SVR SPR, as others may be compatible with the p1022-esdhc type. --- sys/dev/sdhci/fsl_sdhci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/dev/sdhci/fsl_sdhci.c b/sys/dev/sdhci/fsl_sdhci.c index b691756c8b7b..44694255b925 100644 --- a/sys/dev/sdhci/fsl_sdhci.c +++ b/sys/dev/sdhci/fsl_sdhci.c @@ -811,7 +811,9 @@ fsl_sdhci_attach(device_t dev) struct fsl_sdhci_softc *sc = device_get_softc(dev); int rid, err; phandle_t node; +#ifdef __powerpc__ uint32_t protctl; +#endif sc->dev = dev; @@ -869,7 +871,7 @@ fsl_sdhci_attach(device_t dev) */ #ifdef __powerpc__ /* P1022 has the '*_BRST_LEN' fields as reserved, always reading 0x10 */ - if ((SVR_VER(mfspr(SPR_SVR)) & 0xfff6) == SVR_P1022 ) + if (ofw_bus_is_compatible(dev, "fsl,p1022-esdhc")) WR4(sc, SDHC_WTMK_LVL, 0x10801080); else #endif From 47a4ca603bd4292e6583c077c37447ec342fff4d Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Wed, 2 Nov 2016 23:44:30 +0000 Subject: [PATCH 006/127] Since it's no longer accessing a powerpc-specific register, drop the #ifdef. --- sys/dev/sdhci/fsl_sdhci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/dev/sdhci/fsl_sdhci.c b/sys/dev/sdhci/fsl_sdhci.c index 44694255b925..4e667bd04b73 100644 --- a/sys/dev/sdhci/fsl_sdhci.c +++ b/sys/dev/sdhci/fsl_sdhci.c @@ -869,12 +869,10 @@ fsl_sdhci_attach(device_t dev) * * XXX need named constants for this stuff. */ -#ifdef __powerpc__ /* P1022 has the '*_BRST_LEN' fields as reserved, always reading 0x10 */ if (ofw_bus_is_compatible(dev, "fsl,p1022-esdhc")) WR4(sc, SDHC_WTMK_LVL, 0x10801080); else -#endif WR4(sc, SDHC_WTMK_LVL, 0x08800880); /* From 8c07f7653a699230818a1825c978249c9e145fd5 Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Wed, 2 Nov 2016 23:46:23 +0000 Subject: [PATCH 007/127] The DTS may report fewer than 4 parents for a module clock. Avoid setting the module clock parent to an out-of-range index in these cases. --- sys/arm/allwinner/clk/aw_modclk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/arm/allwinner/clk/aw_modclk.c b/sys/arm/allwinner/clk/aw_modclk.c index 8bf5f3a4594b..1ef001264326 100644 --- a/sys/arm/allwinner/clk/aw_modclk.c +++ b/sys/arm/allwinner/clk/aw_modclk.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #define SCLK_GATING (1 << 31) #define CLK_SRC_SEL (0x3 << 24) #define CLK_SRC_SEL_SHIFT 24 -#define CLK_SRC_SEL_MAX 0x3 #define CLK_RATIO_N (0x3 << 16) #define CLK_RATIO_N_SHIFT 16 #define CLK_RATIO_N_MAX 0x3 @@ -69,6 +68,7 @@ static struct ofw_compat_data compat_data[] = { struct aw_modclk_sc { device_t clkdev; bus_addr_t reg; + u_int parent_cnt; }; #define MODCLK_READ(sc, val) CLKDEV_READ_4((sc)->clkdev, (sc)->reg, (val)) @@ -102,7 +102,7 @@ aw_modclk_set_mux(struct clknode *clk, int index) sc = clknode_get_softc(clk); - if (index < 0 || index > CLK_SRC_SEL_MAX) + if (index < 0 || index >= sc->parent_cnt) return (ERANGE); DEVICE_LOCK(sc); @@ -170,7 +170,7 @@ aw_modclk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, best_diff = (int64_t)*fout; best_src = 0; - for (src = 0; src < CLK_SRC_SEL_MAX; src++) { + for (src = 0; src < sc->parent_cnt; src++) { error = clknode_set_parent_by_idx(clk, src); if (error != 0) continue; @@ -299,6 +299,7 @@ aw_modclk_attach(device_t dev) sc = clknode_get_softc(clk); sc->reg = paddr; sc->clkdev = device_get_parent(dev); + sc->parent_cnt = def.parent_cnt; clknode_register(clkdom, clk); From 5f7cfb6035b1baf05e95d0fb6837d3bb3e47ff3c Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Wed, 2 Nov 2016 23:49:57 +0000 Subject: [PATCH 008/127] Add support for H3 PLL2 (PLL_Audio). --- sys/arm/allwinner/clk/aw_pll.c | 96 ++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/sys/arm/allwinner/clk/aw_pll.c b/sys/arm/allwinner/clk/aw_pll.c index 6d159c8eaa0d..ab12dfa94dea 100644 --- a/sys/arm/allwinner/clk/aw_pll.c +++ b/sys/arm/allwinner/clk/aw_pll.c @@ -171,6 +171,15 @@ __FBSDID("$FreeBSD$"); #define A83T_PLLCPUX_POSTDIV_M (0x3 << 0) #define A83T_PLLCPUX_POSTDIV_M_SHIFT 0 +#define H3_PLL2_LOCK (1 << 28) +#define H3_PLL2_SDM_EN (1 << 24) +#define H3_PLL2_POST_DIV (0xf << 16) +#define H3_PLL2_POST_DIV_SHIFT 16 +#define H3_PLL2_FACTOR_N (0x7f << 8) +#define H3_PLL2_FACTOR_N_SHIFT 8 +#define H3_PLL2_PRE_DIV (0x1f << 0) +#define H3_PLL2_PRE_DIV_SHIFT 0 + #define CLKID_A10_PLL3_1X 0 #define CLKID_A10_PLL3_2X 1 @@ -278,6 +287,11 @@ static struct aw_pll_factor aw_a23_pll1_factors[] = { PLLFACTOR(25, 2, 0, 0, 1872000000), }; +static struct aw_pll_factor aw_h3_pll2_factors[] = { + PLLFACTOR(13, 0, 0, 13, 24576000), + PLLFACTOR(6, 0, 0, 7, 22579200), +}; + enum aw_pll_type { AWPLL_A10_PLL1 = 1, AWPLL_A10_PLL2, @@ -292,6 +306,7 @@ enum aw_pll_type { AWPLL_A80_PLL4, AWPLL_A83T_PLLCPUX, AWPLL_H3_PLL1, + AWPLL_H3_PLL2, }; struct aw_pll_sc { @@ -697,6 +712,85 @@ a13_pll2_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout, return (0); } +static int +h3_pll2_recalc(struct aw_pll_sc *sc, uint64_t *freq) +{ + uint32_t val, p, n, m; + + DEVICE_LOCK(sc); + PLL_READ(sc, &val); + DEVICE_UNLOCK(sc); + + p = ((val & H3_PLL2_POST_DIV) >> H3_PLL2_POST_DIV_SHIFT) + 1; + n = ((val & H3_PLL2_FACTOR_N) >> H3_PLL2_FACTOR_N_SHIFT) + 1; + m = ((val & H3_PLL2_PRE_DIV) >> H3_PLL2_PRE_DIV_SHIFT) + 1; + + switch (sc->id) { + case SUN4I_A10_PLL2_1X: + *freq = (*freq * n) / (m * p); + break; + case SUN4I_A10_PLL2_2X: + *freq = (*freq * 2 * n) / m / 4; + break; + case SUN4I_A10_PLL2_4X: + *freq = (*freq * 2 * n) / m / 2; + break; + case SUN4I_A10_PLL2_8X: + *freq = (*freq * 2 * n) / m; + break; + default: + return (EINVAL); + } + + return (0); +} + +static int +h3_pll2_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout, + int flags) +{ + struct aw_pll_factor *f; + uint32_t val; + int n, error, retry; + + if (sc->id != SUN4I_A10_PLL2_1X) + return (ENXIO); + + f = NULL; + for (n = 0; n < nitems(aw_h3_pll2_factors); n++) { + if (aw_h3_pll2_factors[n].freq == *fout) { + f = &aw_h3_pll2_factors[n]; + break; + } + } + if (f == NULL) + return (EINVAL); + + DEVICE_LOCK(sc); + PLL_READ(sc, &val); + val &= ~(H3_PLL2_POST_DIV|H3_PLL2_FACTOR_N|H3_PLL2_PRE_DIV); + val |= (f->p << H3_PLL2_POST_DIV_SHIFT); + val |= (f->n << H3_PLL2_FACTOR_N_SHIFT); + val |= (f->m << H3_PLL2_PRE_DIV_SHIFT); + val |= AW_PLL_ENABLE; + PLL_WRITE(sc, val); + + /* Wait for lock */ + error = 0; + for (retry = 0; retry < 1000; retry++) { + PLL_READ(sc, &val); + if ((val & H3_PLL2_LOCK) != 0) + break; + DELAY(100); + } + if (retry == 0) + error = ETIMEDOUT; + + DEVICE_UNLOCK(sc); + + return (error); +} + static int a23_pll1_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout, int flags) @@ -1006,6 +1100,7 @@ static struct aw_pll_funcs aw_pll_func[] = { PLL(AWPLL_A83T_PLLCPUX, a83t_pllcpux_recalc, a83t_pllcpux_set_freq, NULL), PLL(AWPLL_A64_PLLHSIC, a64_pllhsic_recalc, NULL, a64_pllhsic_init), PLL(AWPLL_H3_PLL1, a23_pll1_recalc, h3_pll1_set_freq, NULL), + PLL(AWPLL_H3_PLL2, h3_pll2_recalc, h3_pll2_set_freq, NULL), }; static struct ofw_compat_data compat_data[] = { @@ -1020,6 +1115,7 @@ static struct ofw_compat_data compat_data[] = { { "allwinner,sun8i-a23-pll1-clk", AWPLL_A23_PLL1 }, { "allwinner,sun8i-a83t-pllcpux-clk", AWPLL_A83T_PLLCPUX }, { "allwinner,sun8i-h3-pll1-clk", AWPLL_H3_PLL1 }, + { "allwinner,sun8i-h3-pll2-clk", AWPLL_H3_PLL2 }, { "allwinner,sun9i-a80-pll4-clk", AWPLL_A80_PLL4 }, { "allwinner,sun50i-a64-pllhsic-clk", AWPLL_A64_PLLHSIC }, { NULL, 0 } From ddfb3d5aa7979fd54dad55b4128b0126787bb5b0 Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Wed, 2 Nov 2016 23:53:47 +0000 Subject: [PATCH 009/127] Register the device's xref handle at attach time. --- sys/arm/allwinner/a10_dmac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/arm/allwinner/a10_dmac.c b/sys/arm/allwinner/a10_dmac.c index cf7d0c33186f..c670badf834b 100644 --- a/sys/arm/allwinner/a10_dmac.c +++ b/sys/arm/allwinner/a10_dmac.c @@ -168,6 +168,7 @@ a10dmac_attach(device_t dev) return (ENXIO); } + OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev); return (0); } From e1ca1a284c6ceca559530c5babec3894a229fa9a Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Wed, 2 Nov 2016 23:58:10 +0000 Subject: [PATCH 010/127] Add support for the integrated DMA controller found in the Allwinner A31, A64, A83T, and H3 SoCs. Relnotes: yes --- sys/arm/allwinner/a31_dmac.c | 557 ++++++++++++++++++++++++++++++ sys/arm/allwinner/files.allwinner | 1 + 2 files changed, 558 insertions(+) create mode 100644 sys/arm/allwinner/a31_dmac.c diff --git a/sys/arm/allwinner/a31_dmac.c b/sys/arm/allwinner/a31_dmac.c new file mode 100644 index 000000000000..d6b3b78bd6de --- /dev/null +++ b/sys/arm/allwinner/a31_dmac.c @@ -0,0 +1,557 @@ +/*- + * Copyright (c) 2016 Jared D. McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Allwinner DMA controller + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include "sunxi_dma_if.h" + +#define DMA_IRQ_EN_REG0 0x00 +#define DMA_IRQ_EN_REG1 0x04 +#define DMA_IRQ_EN_REG(ch) (DMA_IRQ_EN_REG0 + ((ch) / 8) * 4) +#define DMA_PKG_IRQ_EN(ch) (1 << (((ch) % 8) * 4 + 1)) +#define DMA_PKG_IRQ_MASK 0x2222222222222222ULL +#define DMA_IRQ_PEND_REG0 0x10 +#define DMA_IRQ_PEND_REG1 0x14 +#define DMA_IRQ_PEND_REG(ch) (DMA_IRQ_PEND_REG0 + ((ch) / 8) * 4) +#define DMA_STA_REG 0x30 +#define DMA_EN_REG(n) (0x100 + (n) * 0x40 + 0x00) +#define DMA_EN (1 << 0) +#define DMA_PAU_REG(n) (0x100 + (n) * 0x40 + 0x04) +#define DMA_STAR_ADDR_REG(n) (0x100 + (n) * 0x40 + 0x08) +#define DMA_CFG_REG(n) (0x100 + (n) * 0x40 + 0x0c) +#define DMA_DEST_DATA_WIDTH (0x3 << 25) +#define DMA_DEST_DATA_WIDTH_SHIFT 25 +#define DMA_DEST_BST_LEN (0x3 << 22) +#define DMA_DEST_BST_LEN_SHIFT 22 +#define DMA_DEST_ADDR_MODE (0x1 << 21) +#define DMA_DEST_ADDR_MODE_SHIFT 21 +#define DMA_DEST_DRQ_TYPE (0x1f << 16) +#define DMA_DEST_DRQ_TYPE_SHIFT 16 +#define DMA_SRC_DATA_WIDTH (0x3 << 9) +#define DMA_SRC_DATA_WIDTH_SHIFT 9 +#define DMA_SRC_BST_LEN (0x3 << 6) +#define DMA_SRC_BST_LEN_SHIFT 6 +#define DMA_SRC_ADDR_MODE (0x1 << 5) +#define DMA_SRC_ADDR_MODE_SHIFT 5 +#define DMA_SRC_DRQ_TYPE (0x1f << 0) +#define DMA_SRC_DRQ_TYPE_SHIFT 0 +#define DMA_DATA_WIDTH_8BIT 0 +#define DMA_DATA_WIDTH_16BIT 1 +#define DMA_DATA_WIDTH_32BIT 2 +#define DMA_DATA_WIDTH_64BIT 3 +#define DMA_ADDR_MODE_LINEAR 0 +#define DMA_ADDR_MODE_IO 1 +#define DMA_BST_LEN_1 0 +#define DMA_BST_LEN_4 1 +#define DMA_BST_LEN_8 2 +#define DMA_BST_LEN_16 3 +#define DMA_CUR_SRC_REG(n) (0x100 + (n) * 0x40 + 0x10) +#define DMA_CUR_DEST_REG(n) (0x100 + (n) * 0x40 + 0x14) +#define DMA_BCNT_LEFT_REG(n) (0x100 + (n) * 0x40 + 0x18) +#define DMA_PARA_REG(n) (0x100 + (n) * 0x40 + 0x1c) +#define WAIT_CYC (0xff << 0) +#define WAIT_CYC_SHIFT 0 + +struct a31dmac_desc { + uint32_t config; + uint32_t srcaddr; + uint32_t dstaddr; + uint32_t bcnt; + uint32_t para; + uint32_t next; +#define DMA_NULL 0xfffff800 +}; +#define DESC_ALIGN 4 +#define DESC_SIZE sizeof(struct a31dmac_desc) + +struct a31dmac_config { + u_int nchans; +}; + +static const struct a31dmac_config a31_config = { .nchans = 16 }; +static const struct a31dmac_config h3_config = { .nchans = 12 }; +static const struct a31dmac_config a83t_config = { .nchans = 8 }; +static const struct a31dmac_config a64_config = { .nchans = 8 }; + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun6i-a31-dma", (uintptr_t)&a31_config }, + { "allwinner,sun8i-a83t-dma", (uintptr_t)&a83t_config }, + { "allwinner,sun8i-h3-dma", (uintptr_t)&h3_config }, + { "allwinner,sun50i-a64-dma", (uintptr_t)&a64_config }, + { NULL, (uintptr_t)NULL } +}; + +struct a31dmac_softc; + +struct a31dmac_channel { + struct a31dmac_softc * sc; + uint8_t index; + void (*callback)(void *); + void * callbackarg; + + bus_dmamap_t dmamap; + struct a31dmac_desc *desc; + bus_addr_t physaddr; +}; + +struct a31dmac_softc { + struct resource * res[2]; + struct mtx mtx; + void * ih; + + bus_dma_tag_t dmat; + + u_int nchans; + struct a31dmac_channel * chans; +}; + +static struct resource_spec a31dmac_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +#define DMA_READ(sc, reg) bus_read_4((sc)->res[0], (reg)) +#define DMA_WRITE(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val)) + +static void a31dmac_intr(void *); +static void a31dmac_dmamap_cb(void *, bus_dma_segment_t *, int, int); + +static int +a31dmac_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "Allwinner DMA controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +a31dmac_attach(device_t dev) +{ + struct a31dmac_softc *sc; + struct a31dmac_config *conf; + u_int index; + hwreset_t rst; + clk_t clk; + int error; + + sc = device_get_softc(dev); + conf = (void *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; + clk = NULL; + rst = NULL; + + if (bus_alloc_resources(dev, a31dmac_spec, sc->res)) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + mtx_init(&sc->mtx, "a31 dmac", NULL, MTX_SPIN); + + /* Clock and reset setup */ + if (clk_get_by_ofw_index(dev, 0, 0, &clk) != 0) { + device_printf(dev, "cannot get clock\n"); + goto fail; + } + if (clk_enable(clk) != 0) { + device_printf(dev, "cannot enable clock\n"); + goto fail; + } + if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) != 0) { + device_printf(dev, "cannot get hwreset\n"); + goto fail; + } + if (hwreset_deassert(rst) != 0) { + device_printf(dev, "cannot de-assert reset\n"); + goto fail; + } + + /* Descriptor DMA */ + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent tag */ + DESC_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + DESC_SIZE, 1, /* maxsize, nsegs */ + DESC_SIZE, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->dmat); + if (error != 0) { + device_printf(dev, "cannot create dma tag\n"); + goto fail; + } + + /* Disable all interrupts and clear pending status */ + DMA_WRITE(sc, DMA_IRQ_EN_REG0, 0); + DMA_WRITE(sc, DMA_IRQ_EN_REG1, 0); + DMA_WRITE(sc, DMA_IRQ_PEND_REG0, ~0); + DMA_WRITE(sc, DMA_IRQ_PEND_REG1, ~0); + + /* Initialize channels */ + sc->nchans = conf->nchans; + sc->chans = malloc(sizeof(*sc->chans) * sc->nchans, M_DEVBUF, + M_WAITOK | M_ZERO); + + for (index = 0; index < sc->nchans; index++) { + sc->chans[index].sc = sc; + sc->chans[index].index = index; + sc->chans[index].callback = NULL; + sc->chans[index].callbackarg = NULL; + + error = bus_dmamem_alloc(sc->dmat, + (void **)&sc->chans[index].desc, + BUS_DMA_WAITOK | BUS_DMA_COHERENT, + &sc->chans[index].dmamap); + if (error != 0) { + device_printf(dev, "cannot allocate dma mem\n"); + goto fail; + } + error = bus_dmamap_load(sc->dmat, sc->chans[index].dmamap, + sc->chans[index].desc, sizeof(*sc->chans[index].desc), + a31dmac_dmamap_cb, &sc->chans[index], BUS_DMA_WAITOK); + if (error != 0) { + device_printf(dev, "cannot load dma map\n"); + goto fail; + } + + DMA_WRITE(sc, DMA_EN_REG(index), 0); + } + + error = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_MISC, + NULL, a31dmac_intr, sc, &sc->ih); + if (error != 0) { + device_printf(dev, "could not setup interrupt handler\n"); + bus_release_resources(dev, a31dmac_spec, sc->res); + mtx_destroy(&sc->mtx); + return (ENXIO); + } + + OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev); + return (0); + +fail: + for (index = 0; index < sc->nchans; index++) + if (sc->chans[index].desc != NULL) { + bus_dmamap_unload(sc->dmat, sc->chans[index].dmamap); + bus_dmamem_free(sc->dmat, sc->chans[index].desc, + sc->chans[index].dmamap); + } + if (sc->chans != NULL) + free(sc->chans, M_DEVBUF); + if (sc->ih != NULL) + bus_teardown_intr(dev, sc->res[1], sc->ih); + if (rst != NULL) + hwreset_release(rst); + if (clk != NULL) + clk_release(clk); + bus_release_resources(dev, a31dmac_spec, sc->res); + + return (ENXIO); +} + +static void +a31dmac_dmamap_cb(void *priv, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct a31dmac_channel *ch; + + if (error != 0) + return; + + ch = priv; + ch->physaddr = segs[0].ds_addr; +} + +static void +a31dmac_intr(void *priv) +{ + struct a31dmac_softc *sc; + uint32_t pend0, pend1, bit; + uint64_t pend, mask; + u_int index; + + sc = priv; + pend0 = DMA_READ(sc, DMA_IRQ_PEND_REG0); + pend1 = sc->nchans > 8 ? DMA_READ(sc, DMA_IRQ_PEND_REG1) : 0; + if (pend0 == 0 && pend1 == 0) + return; + + if (pend0 != 0) + DMA_WRITE(sc, DMA_IRQ_PEND_REG0, pend0); + if (pend1 != 0) + DMA_WRITE(sc, DMA_IRQ_PEND_REG1, pend1); + + pend = pend0 | ((uint64_t)pend1 << 32); + + while ((bit = ffsll(pend & DMA_PKG_IRQ_MASK)) != 0) { + mask = (1U << (bit - 1)); + pend &= ~mask; + index = (bit - 1) / 4; + + if (index >= sc->nchans) + continue; + if (sc->chans[index].callback == NULL) + continue; + sc->chans[index].callback(sc->chans[index].callbackarg); + } +} + +static int +a31dmac_set_config(device_t dev, void *priv, const struct sunxi_dma_config *cfg) +{ + struct a31dmac_channel *ch; + uint32_t config, para; + unsigned int dst_dw, dst_bl, dst_wc, dst_am; + unsigned int src_dw, src_bl, src_wc, src_am; + + ch = priv; + + switch (cfg->dst_width) { + case 8: + dst_dw = DMA_DATA_WIDTH_8BIT; + break; + case 16: + dst_dw = DMA_DATA_WIDTH_16BIT; + break; + case 32: + dst_dw = DMA_DATA_WIDTH_32BIT; + break; + case 64: + dst_dw = DMA_DATA_WIDTH_64BIT; + break; + default: + return (EINVAL); + } + switch (cfg->dst_burst_len) { + case 1: + dst_bl = DMA_BST_LEN_1; + break; + case 4: + dst_bl = DMA_BST_LEN_4; + break; + case 8: + dst_bl = DMA_BST_LEN_8; + break; + case 16: + dst_bl = DMA_BST_LEN_16; + break; + default: + return (EINVAL); + } + switch (cfg->src_width) { + case 8: + src_dw = DMA_DATA_WIDTH_8BIT; + break; + case 16: + src_dw = DMA_DATA_WIDTH_16BIT; + break; + case 32: + src_dw = DMA_DATA_WIDTH_32BIT; + break; + case 64: + src_dw = DMA_DATA_WIDTH_64BIT; + default: + return (EINVAL); + } + switch (cfg->src_burst_len) { + case 1: + src_bl = DMA_BST_LEN_1; + break; + case 4: + src_bl = DMA_BST_LEN_4; + break; + case 8: + src_bl = DMA_BST_LEN_8; + break; + case 16: + src_bl = DMA_BST_LEN_16; + break; + default: + return (EINVAL); + } + dst_am = cfg->dst_noincr ? DMA_ADDR_MODE_IO : DMA_ADDR_MODE_LINEAR; + src_am = cfg->src_noincr ? DMA_ADDR_MODE_IO : DMA_ADDR_MODE_LINEAR; + dst_wc = cfg->dst_wait_cyc; + src_wc = cfg->src_wait_cyc; + if (dst_wc != src_wc) + return (EINVAL); + + config = (dst_dw << DMA_DEST_DATA_WIDTH_SHIFT) | + (dst_bl << DMA_DEST_BST_LEN_SHIFT) | + (dst_am << DMA_DEST_ADDR_MODE_SHIFT) | + (cfg->dst_drqtype << DMA_DEST_DRQ_TYPE_SHIFT) | + (src_dw << DMA_SRC_DATA_WIDTH_SHIFT) | + (src_bl << DMA_SRC_BST_LEN_SHIFT) | + (src_am << DMA_SRC_ADDR_MODE_SHIFT) | + (cfg->src_drqtype << DMA_SRC_DRQ_TYPE_SHIFT); + para = (dst_wc << WAIT_CYC_SHIFT); + + ch->desc->config = htole32(config); + ch->desc->para = htole32(para); + + return (0); +} + +static void * +a31dmac_alloc(device_t dev, bool dedicated, void (*cb)(void *), void *cbarg) +{ + struct a31dmac_softc *sc; + struct a31dmac_channel *ch; + uint32_t irqen; + u_int index; + + sc = device_get_softc(dev); + ch = NULL; + + mtx_lock_spin(&sc->mtx); + for (index = 0; index < sc->nchans; index++) { + if (sc->chans[index].callback == NULL) { + ch = &sc->chans[index]; + ch->callback = cb; + ch->callbackarg = cbarg; + + irqen = DMA_READ(sc, DMA_IRQ_EN_REG(index)); + irqen |= DMA_PKG_IRQ_EN(index); + DMA_WRITE(sc, DMA_IRQ_EN_REG(index), irqen); + break; + } + } + mtx_unlock_spin(&sc->mtx); + + return (ch); +} + +static void +a31dmac_free(device_t dev, void *priv) +{ + struct a31dmac_channel *ch; + struct a31dmac_softc *sc; + uint32_t irqen; + u_int index; + + ch = priv; + sc = ch->sc; + index = ch->index; + + mtx_lock_spin(&sc->mtx); + + irqen = DMA_READ(sc, DMA_IRQ_EN_REG(index)); + irqen &= ~DMA_PKG_IRQ_EN(index); + DMA_WRITE(sc, DMA_IRQ_EN_REG(index), irqen); + DMA_WRITE(sc, DMA_IRQ_PEND_REG(index), DMA_PKG_IRQ_EN(index)); + + ch->callback = NULL; + ch->callbackarg = NULL; + + mtx_unlock_spin(&sc->mtx); +} + +static int +a31dmac_transfer(device_t dev, void *priv, bus_addr_t src, bus_addr_t dst, + size_t nbytes) +{ + struct a31dmac_channel *ch; + struct a31dmac_softc *sc; + + ch = priv; + sc = ch->sc; + + ch->desc->srcaddr = htole32((uint32_t)src); + ch->desc->dstaddr = htole32((uint32_t)dst); + ch->desc->bcnt = htole32(nbytes); + ch->desc->next = htole32(DMA_NULL); + + DMA_WRITE(sc, DMA_STAR_ADDR_REG(ch->index), (uint32_t)ch->physaddr); + DMA_WRITE(sc, DMA_EN_REG(ch->index), DMA_EN); + + return (0); +} + +static void +a31dmac_halt(device_t dev, void *priv) +{ + struct a31dmac_channel *ch; + struct a31dmac_softc *sc; + + ch = priv; + sc = ch->sc; + + DMA_WRITE(sc, DMA_EN_REG(ch->index), 0); +} + +static device_method_t a31dmac_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, a31dmac_probe), + DEVMETHOD(device_attach, a31dmac_attach), + + /* sunxi DMA interface */ + DEVMETHOD(sunxi_dma_alloc, a31dmac_alloc), + DEVMETHOD(sunxi_dma_free, a31dmac_free), + DEVMETHOD(sunxi_dma_set_config, a31dmac_set_config), + DEVMETHOD(sunxi_dma_transfer, a31dmac_transfer), + DEVMETHOD(sunxi_dma_halt, a31dmac_halt), + + DEVMETHOD_END +}; + +static driver_t a31dmac_driver = { + "a31dmac", + a31dmac_methods, + sizeof(struct a31dmac_softc) +}; + +static devclass_t a31dmac_devclass; + +DRIVER_MODULE(a31dmac, simplebus, a31dmac_driver, a31dmac_devclass, 0, 0); diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner index d4e6a88456c7..9e56e0d4a847 100644 --- a/sys/arm/allwinner/files.allwinner +++ b/sys/arm/allwinner/files.allwinner @@ -5,6 +5,7 @@ arm/allwinner/a10_ahci.c optional ahci arm/allwinner/a10_codec.c optional sound arm/allwinner/a10_common.c standard arm/allwinner/a10_dmac.c standard +arm/allwinner/a31_dmac.c standard arm/allwinner/a10_ehci.c optional ehci arm/allwinner/aw_usbphy.c optional ehci arm/allwinner/a10_gpio.c optional gpio From e40145851b827e7eb57baf216209c6372ac90339 Mon Sep 17 00:00:00 2001 From: Luiz Otavio O Souza Date: Thu, 3 Nov 2016 00:26:58 +0000 Subject: [PATCH 011/127] Remove the mbuf tag after use (for reinjected packets). Fixes the packet processing in dummynet l2 rules. Obtained from: pfSense MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC (Netgate) --- sys/netpfil/ipfw/ip_fw_pfil.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sys/netpfil/ipfw/ip_fw_pfil.c b/sys/netpfil/ipfw/ip_fw_pfil.c index 8d0b69ea6338..4316526df800 100644 --- a/sys/netpfil/ipfw/ip_fw_pfil.c +++ b/sys/netpfil/ipfw/ip_fw_pfil.c @@ -315,20 +315,15 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, struct ip_fw_args args; struct m_tag *mtag; - /* fetch start point from rule, if any */ + /* fetch start point from rule, if any. remove the tag if present. */ mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL); if (mtag == NULL) { args.rule.slot = 0; } else { - /* dummynet packet, already partially processed */ - struct ipfw_rule_ref *r; - - /* XXX can we free it after use ? */ - mtag->m_tag_id = PACKET_TAG_NONE; - r = (struct ipfw_rule_ref *)(mtag + 1); - if (r->info & IPFW_ONEPASS) + args.rule = *((struct ipfw_rule_ref *)(mtag+1)); + m_tag_delete(*m0, mtag); + if (args.rule.info & IPFW_ONEPASS) return (0); - args.rule = *r; } /* I need some amt of data to be contiguous */ From 38ae0c59b9f553459a47352d88895c4c7ed4efcf Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Thu, 3 Nov 2016 00:56:59 +0000 Subject: [PATCH 012/127] [evdev] Add evdev support to atkbd(4) driver To enable event sourcing from atkbd kern.evdev.rcpt_mask value should have bit 3 set. Submitted by: Vladimir Kondratiev MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D8381 --- sys/dev/atkbdc/atkbd.c | 83 +++++++++++++++++++++++++++++++++++ sys/dev/atkbdc/atkbd_atkbdc.c | 4 ++ 2 files changed, 87 insertions(+) diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c index 8fba5788db90..f380367bc308 100644 --- a/sys/dev/atkbdc/atkbd.c +++ b/sys/dev/atkbdc/atkbd.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_kbd.h" #include "opt_atkbd.h" +#include "opt_evdev.h" #include #include @@ -49,6 +50,11 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef EVDEV_SUPPORT +#include +#include +#endif + typedef struct atkbd_state { KBDC kbdc; /* keyboard controller */ int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ @@ -60,6 +66,10 @@ typedef struct atkbd_state { u_int ks_composed_char; /* composed char code (> 0) */ u_char ks_prefix; /* AT scan code prefix */ struct callout ks_timer; +#ifdef EVDEV_SUPPORT + struct evdev_dev *ks_evdev; + int ks_evdev_state; +#endif } atkbd_state_t; static void atkbd_timeout(void *arg); @@ -72,6 +82,11 @@ static int atkbd_reset(KBDC kbdc, int flags, int c); #define DEFAULT_DELAY 0x1 /* 500ms */ #define DEFAULT_RATE 0x10 /* 14Hz */ +#ifdef EVDEV_SUPPORT +#define PS2_KEYBOARD_VENDOR 1 +#define PS2_KEYBOARD_PRODUCT 1 +#endif + int atkbd_probe_unit(device_t dev, int irq, int flags) { @@ -250,6 +265,12 @@ static int typematic(int delay, int rate); static int typematic_delay(int delay); static int typematic_rate(int rate); +#ifdef EVDEV_SUPPORT +static const struct evdev_methods atkbd_evdev_methods = { + .ev_event = evdev_ev_kbd_event, +}; +#endif + /* local variables */ /* the initial key map, accent map and fkey strings */ @@ -352,6 +373,10 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) int delay[2]; int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ int error, needfree; +#ifdef EVDEV_SUPPORT + struct evdev_dev *evdev; + char phys_loc[8]; +#endif /* XXX */ if (unit == ATKBD_DEFAULT) { @@ -436,6 +461,34 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) delay[0] = kbd->kb_delay1; delay[1] = kbd->kb_delay2; atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); + +#ifdef EVDEV_SUPPORT + /* register as evdev provider on first init */ + if (state->ks_evdev == NULL) { + snprintf(phys_loc, sizeof(phys_loc), "atkbd%d", unit); + evdev = evdev_alloc(); + evdev_set_name(evdev, "AT keyboard"); + evdev_set_phys(evdev, phys_loc); + evdev_set_id(evdev, BUS_I8042, PS2_KEYBOARD_VENDOR, + PS2_KEYBOARD_PRODUCT, 0); + evdev_set_methods(evdev, kbd, &atkbd_evdev_methods); + evdev_support_event(evdev, EV_SYN); + evdev_support_event(evdev, EV_KEY); + evdev_support_event(evdev, EV_LED); + evdev_support_event(evdev, EV_REP); + evdev_support_all_known_keys(evdev); + evdev_support_led(evdev, LED_NUML); + evdev_support_led(evdev, LED_CAPSL); + evdev_support_led(evdev, LED_SCROLLL); + + if (evdev_register(evdev)) + evdev_free(evdev); + else + state->ks_evdev = evdev; + state->ks_evdev_state = 0; + } +#endif + KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { @@ -620,6 +673,20 @@ atkbd_read_char(keyboard_t *kbd, int wait) printf("atkbd_read_char(): scancode:0x%x\n", scancode); #endif +#ifdef EVDEV_SUPPORT + /* push evdev event */ + if (evdev_rcpt_mask & EVDEV_RCPT_HW_KBD && state->ks_evdev != NULL) { + keycode = evdev_scancode2key(&state->ks_evdev_state, + scancode); + + if (keycode != KEY_RESERVED) { + evdev_push_event(state->ks_evdev, EV_KEY, + (uint16_t)keycode, scancode & 0x80 ? 0 : 1); + evdev_sync(state->ks_evdev); + } + } +#endif + /* return the byte as is for the K_RAW mode */ if (state->ks_mode == K_RAW) return scancode; @@ -930,6 +997,12 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) return error; } } +#ifdef EVDEV_SUPPORT + /* push LED states to evdev */ + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_HW_KBD) + evdev_push_leds(state->ks_evdev, *(int *)arg); +#endif KBD_LED_VAL(kbd) = *(int *)arg; break; @@ -963,6 +1036,11 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) if (error == 0) { kbd->kb_delay1 = typematic_delay(i); kbd->kb_delay2 = typematic_rate(i); +#ifdef EVDEV_SUPPORT + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_HW_KBD) + evdev_push_repeats(state->ks_evdev, kbd); +#endif } return error; @@ -981,6 +1059,11 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) if (error == 0) { kbd->kb_delay1 = typematic_delay(*(int *)arg); kbd->kb_delay2 = typematic_rate(*(int *)arg); +#ifdef EVDEV_SUPPORT + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_HW_KBD) + evdev_push_repeats(state->ks_evdev, kbd); +#endif } return error; diff --git a/sys/dev/atkbdc/atkbd_atkbdc.c b/sys/dev/atkbdc/atkbd_atkbdc.c index dd0a9d61fc12..22227f364473 100644 --- a/sys/dev/atkbdc/atkbd_atkbdc.c +++ b/sys/dev/atkbdc/atkbd_atkbdc.c @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include "opt_kbd.h" +#include "opt_evdev.h" #include #include @@ -169,3 +170,6 @@ atkbdintr(void *arg) } DRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, 0, 0); +#ifdef EVDEV_SUPPORT +MODULE_DEPEND(atkbd, evdev, 1, 1, 1); +#endif From 19a8946bce1e8cb309aa152462fcb30bf49e457e Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 3 Nov 2016 07:40:52 +0000 Subject: [PATCH 013/127] smbus: remove smbus_trans / SMB_TRANS This change reverts most of r281985. The method did not map to anything defined by SMBus protocol and could not be implemented for SMBus controllers. This change is obviously not backwards compatible, but I have good reasons to believe that there have never been any users of SMB_TRANS. Discussed with: grembo, jhb MFC after: 6 weeks --- share/man/man4/smb.4 | 27 --------------------------- sys/dev/smbus/smb.c | 18 ------------------ sys/dev/smbus/smb.h | 7 ++----- sys/dev/smbus/smbconf.h | 19 ------------------- sys/dev/smbus/smbus_if.m | 17 ----------------- 5 files changed, 2 insertions(+), 86 deletions(-) diff --git a/share/man/man4/smb.4 b/share/man/man4/smb.4 index de053f4f25a8..82202a480512 100644 --- a/share/man/man4/smb.4 +++ b/share/man/man4/smb.4 @@ -162,33 +162,6 @@ to the device, then reads bytes of data that from the device. This data is returned in the buffer pointed to by .Fa rbuf . -.It Dv SMB_TRANS Ta -.Em Trans -sends an SMB roll-up transaction with flags that also allow it to -be used for (mostly) I2C pass-through and with 10-bit addresses. -This function can be utilized to roll up all of the above functions. -It first sends the byte from -.Fa cmd -to the device, followed by -.Fa wcount -bytes of data that are taken from the buffer pointed to by -.Fa wbuf , -then reads -.Fa rcount -bytes of data that from the device. -This data is returned in the buffer pointed to by -.Fa rbuf . -.Pp -The following flags are allowed in -.Fa op : -.Pp -.Bd -literal -compact -SMB_TRANS_NOSTOP Do not send STOP at end -SMB_TRANS_NOCMD Ignore cmd field (do not tx) -SMB_TRANS_NOCNT Do not tx or rx count field -SMB_TRANS_7BIT Change address mode to 7-bit -SMB_TRANS_10BIT Change address mode to 10-bit -.Ed .El .Pp The diff --git a/sys/dev/smbus/smb.c b/sys/dev/smbus/smb.c index e84244118927..21d1e2f7c3d3 100644 --- a/sys/dev/smbus/smb.c +++ b/sys/dev/smbus/smb.c @@ -293,24 +293,6 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t error = copyout(buf, s->rbuf, s->rcount); break; - case SMB_TRANS: - if (s->rcount < 0 || s->wcount < 0) { - error = EINVAL; - break; - } - if (s->rcount > SMB_MAXBLOCKSIZE) - s->rcount = SMB_MAXBLOCKSIZE; - if (s->wcount > SMB_MAXBLOCKSIZE) - s->wcount = SMB_MAXBLOCKSIZE; - if (s->wcount) - error = copyin(s->wbuf, buf, s->wcount); - if (error) - break; - error = smbus_error(smbus_trans(parent, s->slave, s->cmd, - s->op, buf, s->wcount, buf, s->rcount, &s->rcount)); - if (error == 0) - error = copyout(buf, s->rbuf, s->rcount); - break; default: error = ENOTTY; } diff --git a/sys/dev/smbus/smb.h b/sys/dev/smbus/smb.h index 80076530bb52..44b71e8a40ef 100644 --- a/sys/dev/smbus/smb.h +++ b/sys/dev/smbus/smb.h @@ -54,11 +54,8 @@ struct smbcmd { /* * SMBus spec 2.0 says block transfers may be at most 32 bytes. - * We use SMBus for i2c as well, make the size limit something more - * reasonable. Keep in mind that a char buf array is declared on the - * kernel stack. */ -#define SMB_MAXBLOCKSIZE 1024 +#define SMB_MAXBLOCKSIZE 32 #define SMB_QUICK_WRITE _IOW('i', 1, struct smbcmd) #define SMB_QUICK_READ _IOW('i', 2, struct smbcmd) @@ -72,6 +69,6 @@ struct smbcmd { #define SMB_BWRITE _IOW('i', 10, struct smbcmd) #define SMB_OLD_BREAD _IOW('i', 11, struct smbcmd) #define SMB_BREAD _IOWR('i', 11, struct smbcmd) -#define SMB_TRANS _IOWR('i', 12, struct smbcmd) +#define SMB_OLD_TRANS _IOWR('i', 12, struct smbcmd) #endif diff --git a/sys/dev/smbus/smbconf.h b/sys/dev/smbus/smbconf.h index 2c120c1a8a08..ceb80aca267c 100644 --- a/sys/dev/smbus/smbconf.h +++ b/sys/dev/smbus/smbconf.h @@ -71,25 +71,6 @@ #define SMB_QWRITE 0x0 #define SMB_QREAD 0x1 -/* - * smbus transction op with pass-thru capabilities - * - * This smbus function is capable of doing a smbus command transaction - * (read or write), and can be flagged to not issue the 'cmd' and/or - * issue or expect a count field as well as flagged for chaining (no STOP), - * which gives it an i2c pass-through capability. - * - * NOSTOP- Caller chaining transactions, do not issue STOP - * NOCMD- Do not transmit the command field - * NOCNT- Do not transmit (wr) or expect (rd) the count field - */ -#define SMB_TRANS_NOSTOP 0x0001 /* do not send STOP at end */ -#define SMB_TRANS_NOCMD 0x0002 /* ignore cmd field (do not tx) */ -#define SMB_TRANS_NOCNT 0x0004 /* do not tx or rx count field */ -#define SMB_TRANS_7BIT 0x0008 /* change address mode to 7-bit */ -#define SMB_TRANS_10BIT 0x0010 /* change address mode to 10-bit */ -#define SMB_TRANS_NOREPORT 0x0020 /* do not report errors */ - /* * ivars codes */ diff --git a/sys/dev/smbus/smbus_if.m b/sys/dev/smbus/smbus_if.m index 6a5acf5dbcb9..d969e25ed566 100644 --- a/sys/dev/smbus/smbus_if.m +++ b/sys/dev/smbus/smbus_if.m @@ -149,20 +149,3 @@ METHOD int bread { u_char *count; char *buf; }; - -# -# SMB roll-up transaction with flags that also allow it to be -# used for (mostly) i2c pass-through and with 10-bit addresses. -# This function can be used to roll-up all of the above functions. -# -METHOD int trans { - device_t dev; - int slave; - char cmd; - int op; - char *wbuf; - int wcount; - char *rbuf; - int rcount; - int *actualp; -}; From a851d1fbfd3ec5f1a351a4c19a97178264b21194 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Thu, 3 Nov 2016 10:11:59 +0000 Subject: [PATCH 014/127] Check for lengths being <= 0. Note that this interface can only be accessed by root. It uses unsigned ints instead of size_t to preserve the ABI. PR: 207627 Submitted by: ryan@ryanday.net (with slight tweaks) MFC after: 1 month --- sys/cam/ctl/ctl.c | 15 ++++++++++++++- sys/cam/ctl/ctl_ioctl.h | 14 +++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 89c1304c6b44..fad40f3133bc 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -2370,7 +2370,7 @@ ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num, } static void * -ctl_copyin_alloc(void *user_addr, int len, char *error_str, +ctl_copyin_alloc(void *user_addr, unsigned int len, char *error_str, size_t error_str_len) { void *kptr; @@ -2425,6 +2425,12 @@ ctl_copyin_args(int num_args, struct ctl_be_arg *uargs, for (i = 0; i < num_args; i++) { uint8_t *tmpptr; + if (args[i].namelen == 0) { + snprintf(error_str, error_str_len, "Argument %d " + "name length is zero", i); + goto bailout; + } + args[i].kname = ctl_copyin_alloc(args[i].name, args[i].namelen, error_str, error_str_len); if (args[i].kname == NULL) @@ -2437,10 +2443,17 @@ ctl_copyin_args(int num_args, struct ctl_be_arg *uargs, } if (args[i].flags & CTL_BEARG_RD) { + if (args[i].vallen == 0) { + snprintf(error_str, error_str_len, "Argument %d " + "value length is zero", i); + goto bailout; + } + tmpptr = ctl_copyin_alloc(args[i].value, args[i].vallen, error_str, error_str_len); if (tmpptr == NULL) goto bailout; + if ((args[i].flags & CTL_BEARG_ASCII) && (tmpptr[args[i].vallen - 1] != '\0')) { snprintf(error_str, error_str_len, "Argument " diff --git a/sys/cam/ctl/ctl_ioctl.h b/sys/cam/ctl/ctl_ioctl.h index 2872d7727c5b..80a9c2c1f5dd 100644 --- a/sys/cam/ctl/ctl_ioctl.h +++ b/sys/cam/ctl/ctl_ioctl.h @@ -317,20 +317,20 @@ typedef enum { * * flags: Flags for the parameter, see above for values. * - * vallen: Length of the value in bytes. + * vallen: Length of the value in bytes, including the terminating NUL. * - * value: Value to be set/fetched. + * value: Value to be set/fetched. This must be NUL-terminated. * * kname: For kernel use only. * * kvalue: For kernel use only. */ struct ctl_be_arg { - int namelen; - char *name; - int flags; - int vallen; - void *value; + unsigned int namelen; + char *name; + int flags; + unsigned int vallen; + void *value; char *kname; void *kvalue; From 2ad1d09f1698b8de6d78765b783ae005994e8f4e Mon Sep 17 00:00:00 2001 From: Ruslan Bukin Date: Thu, 3 Nov 2016 13:06:17 +0000 Subject: [PATCH 015/127] o Add support for long double. o Add support for latest RISC-V GNU toolchain. Sponsored by: DARPA, AFRL Sponsored by: HEIF5 --- lib/libcompiler_rt/Makefile.inc | 7 +++++-- lib/msun/riscv/Makefile.inc | 5 +---- share/man/man7/arch.7 | 2 +- share/mk/bsd.cpu.mk | 6 +++--- share/mk/bsd.stand.mk | 7 ++++++- sys/modules/dtrace/dtrace/Makefile | 2 +- sys/riscv/include/asm.h | 2 +- sys/riscv/include/float.h | 17 ----------------- 8 files changed, 18 insertions(+), 30 deletions(-) diff --git a/lib/libcompiler_rt/Makefile.inc b/lib/libcompiler_rt/Makefile.inc index cd665edfecbd..27a5879dd24a 100644 --- a/lib/libcompiler_rt/Makefile.inc +++ b/lib/libcompiler_rt/Makefile.inc @@ -123,8 +123,11 @@ SRCF+= udivti3 SRCF+= umoddi3 SRCF+= umodti3 -# 128-bit quad precision long double support, only used on arm64 -.if ${MACHINE_CPUARCH} == "aarch64" +# +# 128-bit quad precision long double support, +# only used on arm64 and riscv. +# +.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv" SRCF+= addtf3 SRCF+= comparetf2 SRCF+= divtf3 diff --git a/lib/msun/riscv/Makefile.inc b/lib/msun/riscv/Makefile.inc index 0ce69db5cdba..97d3302b96da 100644 --- a/lib/msun/riscv/Makefile.inc +++ b/lib/msun/riscv/Makefile.inc @@ -1,6 +1,3 @@ # $FreeBSD$ -# RISCVTODO: should be 113 -# compilation problems: gcc generates bltuz instruction, which is not exists - -LDBL_PREC = 53 +LDBL_PREC = 113 diff --git a/share/man/man7/arch.7 b/share/man/man7/arch.7 index d198c98665bf..6f09463ef49a 100644 --- a/share/man/man7/arch.7 +++ b/share/man/man7/arch.7 @@ -66,7 +66,7 @@ On all supported architectures, .It mips64hf Ta 8 Ta 8 .It powerpc Ta 4 Ta 8 .It powerpc64 Ta 8 Ta 8 -.It riscv Ta 8 Ta +.It riscv Ta 8 Ta 16 .It sparc64 Ta 8 Ta 16 .El .Ss Endianness and Char Signedness diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk index 5ccfe548cbc1..32776d6c75ab 100644 --- a/share/mk/bsd.cpu.mk +++ b/share/mk/bsd.cpu.mk @@ -156,7 +156,7 @@ _CPUCFLAGS = -march=${CPUTYPE} _CPUCFLAGS = -march=${CPUTYPE:S/^mips//} . endif . elif ${MACHINE_CPUARCH} == "riscv" -_CPUCFLAGS = -msoft-float # -march="RV64I" # RISCVTODO +_CPUCFLAGS = -mno-float -march="IMAFD" . elif ${MACHINE_ARCH} == "sparc64" . if ${CPUTYPE} == "v9" _CPUCFLAGS = -mcpu=v9 @@ -337,8 +337,8 @@ CFLAGS += -mcpu=8540 -Wa,-me500 -mspe=yes -mabi=spe -mfloat-gprs=double .endif .if ${MACHINE_CPUARCH} == "riscv" -CFLAGS += -msoft-float -ACFLAGS += -msoft-float +CFLAGS += -mno-float +ACFLAGS += -mno-float .endif # NB: COPTFLAGS is handled in /usr/src/sys/conf/kern.pre.mk diff --git a/share/mk/bsd.stand.mk b/share/mk/bsd.stand.mk index 965171b9ff67..42e01d451319 100644 --- a/share/mk/bsd.stand.mk +++ b/share/mk/bsd.stand.mk @@ -5,7 +5,12 @@ # CFLAGS+= -ffreestanding -Wformat -CFLAGS+= ${CFLAGS_NO_SIMD} -msoft-float -D_STANDALONE +CFLAGS+= ${CFLAGS_NO_SIMD} -D_STANDALONE +.if ${MACHINE_CPUARCH} == "riscv" +CFLAGS+= -mno-float +.else +CFLAGS+= -msoft-float +.endif .if ${MACHINE_CPUARCH} == "i386" CFLAGS.gcc+= -mpreferred-stack-boundary=2 diff --git a/sys/modules/dtrace/dtrace/Makefile b/sys/modules/dtrace/dtrace/Makefile index 3c0812c5ccd7..543be8c20191 100644 --- a/sys/modules/dtrace/dtrace/Makefile +++ b/sys/modules/dtrace/dtrace/Makefile @@ -60,7 +60,7 @@ assym.o: assym.s .if ${MACHINE_CPUARCH} == "riscv" assym.o: assym.s - ${AS} -msoft-float -o assym.o assym.s + ${AS} -mfloat-abi=soft -o assym.o assym.s .endif .include diff --git a/sys/riscv/include/asm.h b/sys/riscv/include/asm.h index adcc23aa9501..5b517322732c 100644 --- a/sys/riscv/include/asm.h +++ b/sys/riscv/include/asm.h @@ -47,7 +47,7 @@ #define _C_LABEL(x) x #define ENTRY(sym) \ - .text; .globl sym; .type sym,@function; .align 2; sym: + .text; .globl sym; .type sym,@function; .align 4; sym: #define END(sym) .size sym, . - sym #define EENTRY(sym) \ diff --git a/sys/riscv/include/float.h b/sys/riscv/include/float.h index 0d6abe1281ac..0829f6f52aa9 100644 --- a/sys/riscv/include/float.h +++ b/sys/riscv/include/float.h @@ -76,22 +76,6 @@ __END_DECLS #define DBL_HAS_SUBNORM 1 #endif /* __ISO_C_VISIBLE >= 2011 */ -#define LDBL_MANT_DIG DBL_MANT_DIG -#define LDBL_EPSILON ((long double)DBL_EPSILON) -#define LDBL_DIG DBL_DIG -#define LDBL_MIN_EXP DBL_MIN_EXP -#define LDBL_MIN ((long double)DBL_MIN) -#define LDBL_MIN_10_EXP DBL_MIN_10_EXP -#define LDBL_MAX_EXP DBL_MAX_EXP -#define LDBL_MAX ((long double)DBL_MAX) -#define LDBL_MAX_10_EXP DBL_MAX_10_EXP -#if __ISO_C_VISIBLE >= 2011 -#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN) -#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG -#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM -#endif /* __ISO_C_VISIBLE >= 2011 */ - -#if 0 /* RISCVTODO */ #define LDBL_MANT_DIG 113 #define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L #define LDBL_DIG 33 @@ -106,6 +90,5 @@ __END_DECLS #define LDBL_DECIMAL_DIG 36 #define LDBL_HAS_SUBNORM 1 #endif /* __ISO_C_VISIBLE >= 2011 */ -#endif #endif /* _MACHINE_FLOAT_H_ */ From 857025056f1176818f6275788ca7cf6819dc6a37 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 3 Nov 2016 16:44:55 +0000 Subject: [PATCH 016/127] In vm_fault()'s loop over the shadow chain, move a comment describing our invariants to a better place. Also, add two comments concerning the relationship between the map and vnode locks. Reviewed by: kib MFC after: 3 days --- sys/vm/vm_fault.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 47a1bd57ef24..11993054d0c0 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -563,6 +563,14 @@ RetryFault:; } readrest: + /* + * At this point, we have either allocated a new page or found + * an existing page that is only partially valid. + * + * We hold a reference on the current object and the page is + * exclusive busied. + */ + /* * If the pager for the current object might have the page, * then determine the number of additional pages to read and @@ -632,18 +640,23 @@ RetryFault:; */ if (fs.object->type != OBJT_DEFAULT) { /* - * We have either allocated a new page or found an - * existing page that is only partially valid. We - * hold a reference on fs.object and the page is - * exclusive busied. + * Release the map lock before locking the vnode or + * sleeping in the pager. (If the current object has + * a shadow, then an earlier iteration of this loop + * may have already unlocked the map.) */ unlock_map(&fs); if (fs.object->type == OBJT_VNODE && (vp = fs.object->handle) != fs.vp) { + /* + * Perform an unlock in case the desired vnode + * changed while the map was unlocked during a + * retry. + */ unlock_vp(&fs); - locked = VOP_ISLOCKED(vp); + locked = VOP_ISLOCKED(vp); if (locked != LK_EXCLUSIVE) locked = LK_SHARED; From 1bec4c5b3d970c741ffcb08a40080924e6ce97af Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Thu, 3 Nov 2016 19:39:32 +0000 Subject: [PATCH 017/127] Use proper MACHINE_ARCH. This fixes ports on mips after r308130. --- share/mk/bsd.cpu.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk index 32776d6c75ab..ae29f14aebe1 100644 --- a/share/mk/bsd.cpu.mk +++ b/share/mk/bsd.cpu.mk @@ -303,7 +303,7 @@ MACHINE_CPU = v9 ultrasparc ultrasparc3 .if ${MACHINE_CPUARCH} == "mips" CFLAGS += -G0 -.if ${TARGET_ARCH:Mmips*hf} +.if ${MACHINE_ARCH:Mmips*hf} CFLAGS += -mhard-float .endif .endif From 34168b28e99b0bb328c7bb49cd91cb942181056f Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Thu, 3 Nov 2016 20:21:34 +0000 Subject: [PATCH 018/127] Replace basename(3) by a thread-safe implementation. Now that the changes to the dirname(3) function had some time to settle, let's go ahead and use the same approach for replacing basename(3) by a simple implementation that modifies the input string, thereby making it thread-safe and guaranteed to succeed. Unlike dirname(3), this function already had a thread-safe variant basename_r(3). This function had its own set of problems, like having an upper bound on the pathname length. Keep this function around for compatibility, but remove most references from the man page. Make the man page more similar to that of dirname(3). As the basename_r(3) function is only provided by FreeBSD (and Bionic), depending on its use is even more implementation defined than assuming that basename(3) is thread-safe. Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D8382 --- include/libgen.h | 19 ++++--- lib/libc/gen/Makefile.inc | 1 + lib/libc/gen/Symbol.map | 2 +- lib/libc/gen/basename.3 | 79 ++++++++------------------ lib/libc/gen/basename.c | 101 +++++++++++++-------------------- lib/libc/gen/basename_compat.c | 81 ++++++++++++++++++++++++++ 6 files changed, 155 insertions(+), 128 deletions(-) create mode 100644 lib/libc/gen/basename_compat.c diff --git a/include/libgen.h b/include/libgen.h index 5b79f3619d80..173190f03674 100644 --- a/include/libgen.h +++ b/include/libgen.h @@ -40,21 +40,24 @@ char *dirname(char *); __END_DECLS /* - * In FreeBSD 12, the prototype of dirname() was modified to comply to - * POSIX. This function may now modify its input. Unfortunately, our - * copy of xinstall(8) shipped with previous versions of FreeBSD is - * built using the host headers and libc during the bootstrapping phase - * and depends on the old behavior. + * In FreeBSD 12, the prototypes of basename() and dirname() were + * modified to comply to POSIX. These functions may now modify their + * input. Unfortunately, our copy of xinstall(8) shipped with previous + * versions of FreeBSD is built using the host headers and libc during + * the bootstrapping phase and depends on the old behavior. * - * Apply a workaround where we explicitly link against dirname@FBSD_1.0 - * in case this function is called on constant strings, instead of - * making the program crash at runtime. + * Apply a workaround where we explicitly link against basename@FBSD_1.0 + * and dirname@FBSD_1.0 in case these functions are called on constant + * strings, instead of making the program crash at runtime. */ #if defined(__generic) && !defined(__cplusplus) __BEGIN_DECLS +char *__old_basename(char *); char *__old_dirname(char *); __END_DECLS +__sym_compat(basename, __old_basename, FBSD_1.0); __sym_compat(dirname, __old_dirname, FBSD_1.0); +#define basename(x) __generic(x, const char *, __old_basename, basename)(x) #define dirname(x) __generic(x, const char *, __old_dirname, dirname)(x) #endif diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 58f582fb4e73..ab8a8c9b7279 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -17,6 +17,7 @@ SRCS+= __getosreldate.c \ assert.c \ auxv.c \ basename.c \ + basename_compat.c \ cap_sandboxed.c \ check_utility_compat.c \ clock.c \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 151987361b8d..4b07a0067be9 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -68,7 +68,6 @@ FBSD_1.0 { arc4random_addrandom; arc4random_stir; __assert; - basename; check_utility_compat; clock; closedir; @@ -414,6 +413,7 @@ FBSD_1.4 { }; FBSD_1.5 { + basename; dirname; }; diff --git a/lib/libc/gen/basename.3 b/lib/libc/gen/basename.3 index 6de009448bda..51a90e404746 100644 --- a/lib/libc/gen/basename.3 +++ b/lib/libc/gen/basename.3 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 29, 2016 +.Dd October 29, 2016 .Dt BASENAME 3 .Os .Sh NAME @@ -26,8 +26,6 @@ .In libgen.h .Ft char * .Fn basename "char *path" -.Ft char * -.Fn basename_r "const char *path" "char *bname" .Sh DESCRIPTION The .Fn basename @@ -36,6 +34,7 @@ function returns the last component from the pathname pointed to by deleting any trailing .Sq \&/ characters. +.Sh RETURN VALUES If .Fa path consists entirely of @@ -48,48 +47,19 @@ If is a null pointer or the empty string, a pointer to the string .Qq \&. is returned. -.Pp -The -.Fn basename_r -variation accepts a buffer of at least -.Dv MAXPATHLEN -bytes in which to store the resulting component. -.Sh IMPLEMENTATION NOTES -The -.Fn basename -function -returns a pointer to internal storage space allocated on the first call -that will be overwritten -by subsequent calls. -.Pp -Other vendor implementations of -.Fn basename -may store their result in the input buffer, -making it safe to use in multithreaded applications. -Future versions of -.Fx -will follow this approach as well. -.Fn basename_r -will then become obsolete. -.Sh RETURN VALUES -On successful completion, -.Fn basename -and -.Fn basename_r -return pointers to the last component of +Otherwise, +it returns a pointer to the last component of .Fa path . -.Pp -If they fail, a null pointer is returned and the global variable -.Va errno -is set to indicate the error. -.Sh ERRORS -The following error codes may be set in -.Va errno : -.Bl -tag -width Er -.It Bq Er ENAMETOOLONG -The path component to be returned was larger than -.Dv MAXPATHLEN . -.El +.Sh IMPLEMENTATION NOTES +This implementation of +.Fn basename +uses the buffer provided by the caller to store the resulting pathname +component. +Other vendor implementations may return a pointer to internal storage +space instead. +The advantage of the former approach is that it ensures thread-safety, +while also placing no upper limit on the supported length of the +pathname. .Sh SEE ALSO .Xr basename 1 , .Xr dirname 1 , @@ -106,16 +76,13 @@ function first appeared in .Ox 2.2 and .Fx 4.2 . -.Sh AUTHORS -.An Todd C. Miller -.Sh CAVEATS -.Fn basename -returns a pointer to internal static storage space that will be overwritten -by subsequent calls. .Pp -Other vendor implementations of -.Fn basename -may modify the contents of the string passed to -.Fn basename ; -this should be taken into account when writing code which calls this function -if portability is desired. +In +.Fx 12.0 , +this function was reimplemented to store its result in the provided +input buffer. +There is no longer any need to use the +.Fn basename_r +function. +.Sh AUTHORS +.An Nuxi, the Netherlands diff --git a/lib/libc/gen/basename.c b/lib/libc/gen/basename.c index 7e21ca4aa307..7569ab9c3029 100644 --- a/lib/libc/gen/basename.c +++ b/lib/libc/gen/basename.c @@ -1,79 +1,54 @@ -/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ - -/* - * Copyright (c) 1997, 2004 Todd C. Miller +/*- + * Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); -#include #include -#include #include -#include char * -basename_r(const char *path, char *bname) +(basename)(char *path) { - const char *endp, *startp; - size_t len; + char *ptr; - /* Empty or NULL string gets treated as "." */ - if (path == NULL || *path == '\0') { - bname[0] = '.'; - bname[1] = '\0'; - return (bname); - } + /* + * If path is a null pointer or points to an empty string, + * basename() shall return a pointer to the string ".". + */ + if (path == NULL || *path == '\0') + return (__DECONST(char *, ".")); - /* Strip any trailing slashes */ - endp = path + strlen(path) - 1; - while (endp > path && *endp == '/') - endp--; + /* Find end of last pathname component and null terminate it. */ + ptr = path + strlen(path); + while (ptr > path + 1 && *(ptr - 1) == '/') + --ptr; + *ptr-- = '\0'; - /* All slashes becomes "/" */ - if (endp == path && *endp == '/') { - bname[0] = '/'; - bname[1] = '\0'; - return (bname); - } - - /* Find the start of the base */ - startp = endp; - while (startp > path && *(startp - 1) != '/') - startp--; - - len = endp - startp + 1; - if (len >= MAXPATHLEN) { - errno = ENAMETOOLONG; - return (NULL); - } - memcpy(bname, startp, len); - bname[len] = '\0'; - return (bname); -} - -char * -basename(char *path) -{ - static char *bname = NULL; - - if (bname == NULL) { - bname = (char *)malloc(MAXPATHLEN); - if (bname == NULL) - return (NULL); - } - return (basename_r(path, bname)); + /* Find beginning of last pathname component. */ + while (ptr > path && *(ptr - 1) != '/') + --ptr; + return (ptr); } diff --git a/lib/libc/gen/basename_compat.c b/lib/libc/gen/basename_compat.c new file mode 100644 index 000000000000..f6ce7f9a1f43 --- /dev/null +++ b/lib/libc/gen/basename_compat.c @@ -0,0 +1,81 @@ +/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ + +/* + * Copyright (c) 1997, 2004 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +char * +basename_r(const char *path, char *bname) +{ + const char *endp, *startp; + size_t len; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + bname[0] = '.'; + bname[1] = '\0'; + return (bname); + } + + /* Strip any trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* All slashes becomes "/" */ + if (endp == path && *endp == '/') { + bname[0] = '/'; + bname[1] = '\0'; + return (bname); + } + + /* Find the start of the base */ + startp = endp; + while (startp > path && *(startp - 1) != '/') + startp--; + + len = endp - startp + 1; + if (len >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return (NULL); + } + memcpy(bname, startp, len); + bname[len] = '\0'; + return (bname); +} + +char * +__freebsd11_basename(char *path) +{ + static char *bname = NULL; + + if (bname == NULL) { + bname = (char *)malloc(MAXPATHLEN); + if (bname == NULL) + return (NULL); + } + return (basename_r(path, bname)); +} + +__sym_compat(basename, __freebsd11_basename, FBSD_1.0); From 8a1be49ef66d408ec0591e5d86f22706ccbf76da Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Thu, 3 Nov 2016 22:50:41 +0000 Subject: [PATCH 019/127] Import tzdata2016i. Sponsored by: The FreeBSD Foundation --- CONTRIBUTING | 73 + LICENSE | 4 + Makefile | 793 ++++++++++ NEWS | 3782 +++++++++++++++++++++++++++++++++++++++++++++++ README | 71 + Theory | 840 +++++++++++ antarctica | 7 +- asia | 17 +- australasia | 18 +- backzone | 677 +++++++++ checklinks.awk | 48 + checktab.awk | 177 +++ europe | 143 +- leapseconds.awk | 76 + version | 1 + zone.tab | 3 +- zone1970.tab | 3 +- zoneinfo2tdf.pl | 52 + 18 files changed, 6711 insertions(+), 74 deletions(-) create mode 100644 CONTRIBUTING create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README create mode 100644 Theory create mode 100644 backzone create mode 100644 checklinks.awk create mode 100644 checktab.awk create mode 100644 leapseconds.awk create mode 100644 version create mode 100755 zoneinfo2tdf.pl diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 000000000000..e40102e693e3 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,73 @@ +Contributing to the tz code and data + +The time zone database is by no means authoritative: governments +change timekeeping rules erratically and sometimes with little +warning, the data entries do not cover all of civil time before +1970, and undoubtedly errors remain in the code and data. Feel +free to fill gaps or fix mistakes, and please email improvements +to tz@iana.org for use in the future. + +To email small changes, please run a POSIX shell command like +'diff -u old/europe new/europe >myfix.patch', and attach +myfix.patch to the email. + +For more-elaborate changes, please read the Theory file and browse +the mailing list archives for +examples of patches that tend to work well. Ideally, additions to +data should contain commentary citing reliable sources as +justification. + +Please submit changes against either the latest release in + or the master branch of the experimental +Git repository. If you use Git the following workflow may be helpful: + + * Copy the experimental repository. + + git clone https://github.com/eggert/tz.git + cd tz + + * Get current with the master branch. + + git checkout master + git pull + + * Switch to a new branch for the changes. Choose a different + branch name for each change set. + + git checkout -b mybranch + + * Edit source files. Include commentary that justifies the + changes by citing reliable sources. + + * Debug the changes, e.g.: + + make check + make install + ./zdump -v America/Los_Angeles + + * For each separable change, commit it in the new branch, e.g.: + + git add northamerica + git commit + + See recent 'git log' output for the commit-message style. + + * Create patch files 0001-*, 0002-*, ... + + git format-patch master + + * After reviewing the patch files, send the patches to tz@iana.org + for others to review. + + git send-email master + + * Start anew by getting current with the master branch again + (the second step above). + +Please do not create issues or pull requests on GitHub, as the +proper procedure for proposing and distributing patches is via +email as illustrated above. + +----- + +This file is in the public domain. diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..148eb232b673 --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +With a few exceptions, all files in the tz code and data (including +this one) are in the public domain. The exceptions are date.c, +newstrftime.3, and strftime.c, which contain material derived from BSD +and which use the BSD 3-clause license. diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..74b950cb58a9 --- /dev/null +++ b/Makefile @@ -0,0 +1,793 @@ +# This file is in the public domain, so clarified as of +# 2009-05-17 by Arthur David Olson. + +# Package name for the code distribution. +PACKAGE= tzcode + +# Version number for the distribution, overridden in the 'tarballs' rule below. +VERSION= unknown + +# Email address for bug reports. +BUGEMAIL= tz@iana.org + +# Change the line below for your time zone (after finding the zone you want in +# the time zone files, or adding it to a time zone file). +# Alternately, if you discover you've got the wrong time zone, you can just +# zic -l rightzone +# to correct things. +# Use the command +# make zonenames +# to get a list of the values you can use for LOCALTIME. + +LOCALTIME= GMT + +# If you want something other than Eastern United States time as a template +# for handling POSIX-style time zone environment variables, +# change the line below (after finding the zone you want in the +# time zone files, or adding it to a time zone file). +# (When a POSIX-style environment variable is handled, the rules in the +# template file are used to determine "spring forward" and "fall back" days and +# times; the environment variable itself specifies UT offsets of standard and +# summer time.) +# Alternately, if you discover you've got the wrong time zone, you can just +# zic -p rightzone +# to correct things. +# Use the command +# make zonenames +# to get a list of the values you can use for POSIXRULES. +# If you want POSIX compatibility, use "America/New_York". + +POSIXRULES= America/New_York + +# Also see TZDEFRULESTRING below, which takes effect only +# if the time zone files cannot be accessed. + +# Everything gets put in subdirectories of. . . + +TOPDIR= /usr/local + +# "Compiled" time zone information is placed in the "TZDIR" directory +# (and subdirectories). +# Use an absolute path name for TZDIR unless you're just testing the software. + +TZDIR_BASENAME= zoneinfo +TZDIR= $(TOPDIR)/etc/$(TZDIR_BASENAME) + +# Types to try, as an alternative to time_t. int64_t should be first. +TIME_T_ALTERNATIVES= int64_t int32_t uint32_t uint64_t + +# The "tzselect", "zic", and "zdump" commands get installed in. . . + +ETCDIR= $(TOPDIR)/etc + +# If you "make INSTALL", the "date" command gets installed in. . . + +BINDIR= $(TOPDIR)/bin + +# Manual pages go in subdirectories of. . . + +MANDIR= $(TOPDIR)/man + +# Library functions are put in an archive in LIBDIR. + +LIBDIR= $(TOPDIR)/lib + +# If you always want time values interpreted as "seconds since the epoch +# (not counting leap seconds)", use +# REDO= posix_only +# below. If you always want right time values interpreted as "seconds since +# the epoch" (counting leap seconds)", use +# REDO= right_only +# below. If you want both sets of data available, with leap seconds not +# counted normally, use +# REDO= posix_right +# below. If you want both sets of data available, with leap seconds counted +# normally, use +# REDO= right_posix +# below. POSIX mandates that leap seconds not be counted; for compatibility +# with it, use "posix_only" or "posix_right". + +REDO= posix_right + +# If you want out-of-scope and often-wrong data from the file 'backzone', use +# PACKRATDATA= backzone +# To omit this data, use +# PACKRATDATA= + +PACKRATDATA= + +# Since "." may not be in PATH... + +YEARISTYPE= ./yearistype + +# Non-default libraries needed to link. +LDLIBS= + +# Add the following to the end of the "CFLAGS=" line as needed. +# -DBIG_BANG=-9999999LL if the Big Bang occurred at time -9999999 (see zic.c) +# -DHAVE_DECL_ASCTIME_R=0 if does not declare asctime_r +# -DHAVE_DIRECT_H if mkdir needs (MS-Windows) +# -DHAVE_DOS_FILE_NAMES if file names have drive specifiers etc. (MS-DOS) +# -DHAVE_GETTEXT=1 if 'gettext' works (e.g., GNU/Linux, FreeBSD, Solaris) +# -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares +# ctime_r and asctime_r incompatibly with the POSIX standard +# (Solaris when _POSIX_PTHREAD_SEMANTICS is not defined). +# -DHAVE_INTTYPES_H=1 if you have a pre-C99 compiler with "inttypes.h" +# -DHAVE_LINK=0 if your system lacks a link function +# -DHAVE_LOCALTIME_R=0 if your system lacks a localtime_r function +# -DHAVE_LOCALTIME_RZ=0 if you do not want zdump to use localtime_rz +# This defaults to 1 if a working localtime_rz seems to be available. +# localtime_rz can make zdump significantly faster, but is nonstandard. +# -DHAVE_POSIX_DECLS=0 if your system's include files do not declare +# functions like 'link' or variables like 'tzname' required by POSIX +# -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h" +# -DHAVE_STRFTIME_L=1 if declares locale_t and strftime_l +# This defaults to 0 if _POSIX_VERSION < 200809, 1 otherwise. +# -DHAVE_STRDUP=0 if your system lacks the strdup function +# -DHAVE_SYMLINK=0 if your system lacks the symlink function +# -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h" +# -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h" +# -DHAVE_TZSET=0 if your system lacks a tzset function +# -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?) +# -DEPOCH_LOCAL=1 if the 'time' function returns local time not UT +# -DEPOCH_OFFSET=N if the 'time' function returns a value N greater +# than what POSIX specifies, assuming local time is UT. +# For example, N is 252460800 on AmigaOS. +# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1 +# if you do not want run time warnings about formats that may cause +# year 2000 grief +# -Dssize_t=long on ancient hosts that lack ssize_t +# -DTHREAD_SAFE=1 to make localtime.c thread-safe, as POSIX requires; +# not needed by the main-program tz code, which is single-threaded. +# Append other compiler flags as needed, e.g., -pthread on GNU/Linux. +# -Dtime_tz=\"T\" to use T as the time_t type, rather than the system time_t +# -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" +# -DTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; +# the default is system-supplied, typically "/usr/lib/locale" +# -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified +# DST transitions if the time zone files cannot be accessed +# -DUNINIT_TRAP=1 if reading uninitialized storage can cause problems +# other than simply getting garbage data +# -DUSE_LTZ=0 to build zdump with the system time zone library +# Also set TZDOBJS=zdump.o and CHECK_TIME_T_ALTERNATIVES= below. +# -DZIC_MAX_ABBR_LEN_WO_WARN=3 +# (or some other number) to set the maximum time zone abbreviation length +# that zic will accept without a warning (the default is 6) +# $(GCC_DEBUG_FLAGS) if you are using recent GCC and want lots of checking +GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-common -fstrict-aliasing \ + -Wall -Wextra \ + -Wbad-function-cast -Wcast-align -Wdate-time \ + -Wdeclaration-after-statement \ + -Wdouble-promotion \ + -Wformat=2 -Winit-self -Wjump-misses-init \ + -Wlogical-op -Wmissing-prototypes -Wnested-externs \ + -Wold-style-definition -Woverlength-strings -Wpointer-arith \ + -Wshadow -Wstrict-prototypes -Wsuggest-attribute=const \ + -Wsuggest-attribute=format -Wsuggest-attribute=noreturn \ + -Wsuggest-attribute=pure -Wtrampolines \ + -Wunused -Wwrite-strings \ + -Wno-address -Wno-format-nonliteral -Wno-sign-compare \ + -Wno-type-limits -Wno-unused-parameter +# +# If you want to use System V compatibility code, add +# -DUSG_COMPAT +# to the end of the "CFLAGS=" line. This arrange for "timezone" and "daylight" +# variables to be kept up-to-date by the time conversion functions. Neither +# "timezone" nor "daylight" is described in X3J11's work. +# +# If your system has a "GMT offset" field in its "struct tm"s +# (or if you decide to add such a field in your system's "time.h" file), +# add the name to a define such as +# -DTM_GMTOFF=tm_gmtoff +# to the end of the "CFLAGS=" line. If not defined, the code attempts to +# guess TM_GMTOFF from other macros; define NO_TM_GMTOFF to suppress this. +# Similarly, if your system has a "zone abbreviation" field, define +# -DTM_ZONE=tm_zone +# and define NO_TM_ZONE to suppress any guessing. These two fields are not +# required by POSIX, but are widely available on GNU/Linux and BSD systems. +# +# If you want functions that were inspired by early versions of X3J11's work, +# add +# -DSTD_INSPIRED +# to the end of the "CFLAGS=" line. This arranges for the functions +# "tzsetwall", "offtime", "timelocal", "timegm", "timeoff", +# "posix2time", and "time2posix" to be added to the time conversion library. +# "tzsetwall" is like "tzset" except that it arranges for local wall clock +# time (rather than the time specified in the TZ environment variable) +# to be used. +# "offtime" is like "gmtime" except that it accepts a second (long) argument +# that gives an offset to add to the time_t when converting it. +# "timelocal" is equivalent to "mktime". +# "timegm" is like "timelocal" except that it turns a struct tm into +# a time_t using UT (rather than local time as "timelocal" does). +# "timeoff" is like "timegm" except that it accepts a second (long) argument +# that gives an offset to use when converting to a time_t. +# "posix2time" and "time2posix" are described in an included manual page. +# X3J11's work does not describe any of these functions. +# Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0. +# These functions may well disappear in future releases of the time +# conversion package. +# +# If you don't want functions that were inspired by NetBSD, add +# -DNETBSD_INSPIRED=0 +# to the end of the "CFLAGS=" line. Otherwise, the functions +# "localtime_rz", "mktime_z", "tzalloc", and "tzfree" are added to the +# time library, and if STD_INSPIRED is also defined the functions +# "posix2time_z" and "time2posix_z" are added as well. +# The functions ending in "_z" (or "_rz") are like their unsuffixed +# (or suffixed-by-"_r") counterparts, except with an extra first +# argument of opaque type timezone_t that specifies the time zone. +# "tzalloc" allocates a timezone_t value, and "tzfree" frees it. +# +# If you want to allocate state structures in localtime, add +# -DALL_STATE +# to the end of the "CFLAGS=" line. Storage is obtained by calling malloc. +# +# If you want an "altzone" variable (a la System V Release 3.1), add +# -DALTZONE +# to the end of the "CFLAGS=" line. +# This variable is not described in X3J11's work. +# +# NIST-PCTS:151-2, Version 1.4, (1993-12-03) is a test suite put +# out by the National Institute of Standards and Technology +# which claims to test C and Posix conformance. If you want to pass PCTS, add +# -DPCTS +# to the end of the "CFLAGS=" line. +# +# If you want strict compliance with XPG4 as of 1994-04-09, add +# -DXPG4_1994_04_09 +# to the end of the "CFLAGS=" line. This causes "strftime" to always return +# 53 as a week number (rather than 52 or 53) for those days in January that +# before the first Monday in January when a "%V" format is used and January 1 +# falls on a Friday, Saturday, or Sunday. + +CFLAGS= + +# Linker flags. Default to $(LFLAGS) for backwards compatibility +# to release 2012h and earlier. + +LDFLAGS= $(LFLAGS) + +# For leap seconds, this Makefile uses LEAPSECONDS='-L leapseconds' in +# submake command lines. The default is no leap seconds. + +LEAPSECONDS= + +# The zic command and its arguments. + +zic= ./zic +ZIC= $(zic) $(ZFLAGS) + +ZFLAGS= + +# How to use zic to install tz binary files. + +ZIC_INSTALL= $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR) $(LEAPSECONDS) + +# The name of a Posix-compliant 'awk' on your system. +AWK= awk + +# The full path name of a Posix-compliant shell, preferably one that supports +# the Korn shell's 'select' statement as an extension. +# These days, Bash is the most popular. +# It should be OK to set this to /bin/sh, on platforms where /bin/sh +# lacks 'select' or doesn't completely conform to Posix, but /bin/bash +# is typically nicer if it works. +KSHELL= /bin/bash + +# The path where SGML DTDs are kept and the catalog file(s) to use when +# validating. The default should work on both Debian and Red Hat. +SGML_TOPDIR= /usr +SGML_DTDDIR= $(SGML_TOPDIR)/share/xml/w3c-sgml-lib/schema/dtd +SGML_SEARCH_PATH= $(SGML_DTDDIR)/REC-html401-19991224 +SGML_CATALOG_FILES= \ + $(SGML_TOPDIR)/share/doc/w3-recs/html/www.w3.org/TR/1999/REC-html401-19991224/HTML4.cat:$(SGML_TOPDIR)/share/sgml/html/4.01/HTML4.cat + +# The name, arguments and environment of a program to validate your web pages. +# See for a validator, and +# for a validation library. +VALIDATE = nsgmls +VALIDATE_FLAGS = -s -B -wall -wno-unused-param +VALIDATE_ENV = \ + SGML_CATALOG_FILES=$(SGML_CATALOG_FILES) \ + SGML_SEARCH_PATH=$(SGML_SEARCH_PATH) \ + SP_CHARSET_FIXED=YES \ + SP_ENCODING=UTF-8 + +# This expensive test requires USE_LTZ. +# To suppress it, define this macro to be empty. +CHECK_TIME_T_ALTERNATIVES = check_time_t_alternatives + +# SAFE_CHAR is a regular expression that matches a safe character. +# Some parts of this distribution are limited to safe characters; +# others can use any UTF-8 character. +# For now, the safe characters are a safe subset of ASCII. +# The caller must set the shell variable 'sharp' to the character '#', +# since Makefile macros cannot contain '#'. +# TAB_CHAR is a single tab character, in single quotes. +TAB_CHAR= ' ' +SAFE_CHARSET1= $(TAB_CHAR)' !\"'$$sharp'$$%&'\''()*+,./0123456789:;<=>?@' +SAFE_CHARSET2= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\^_`' +SAFE_CHARSET3= 'abcdefghijklmnopqrstuvwxyz{|}~' +SAFE_CHARSET= $(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3) +SAFE_CHAR= '[]'$(SAFE_CHARSET)'-]' + +# OK_CHAR matches any character allowed in the distributed files. +# This is the same as SAFE_CHAR, except that multibyte letters are +# also allowed so that commentary can contain people's names and quote +# non-English sources. For non-letters the sources are limited to +# ASCII renderings for the convenience of maintainers whose text editors +# mishandle UTF-8 by default (e.g., XEmacs 21.4.22). +OK_CHAR= '[][:alpha:]'$(SAFE_CHARSET)'-]' + +# SAFE_LINE matches a line of safe characters. +# SAFE_SHARP_LINE is similar, except any OK character can follow '#'; +# this is so that comments can contain non-ASCII characters. +# OK_LINE matches a line of OK characters. +SAFE_LINE= '^'$(SAFE_CHAR)'*$$' +SAFE_SHARP_LINE='^'$(SAFE_CHAR)'*('$$sharp$(OK_CHAR)'*)?$$' +OK_LINE= '^'$(OK_CHAR)'*$$' + +# Flags to give 'tar' when making a distribution. +# Try to use flags appropriate for GNU tar. +GNUTARFLAGS= --numeric-owner --owner=0 --group=0 --mode=go+u,go-w --sort=name +TARFLAGS= `if tar $(GNUTARFLAGS) --version >/dev/null 2>&1; \ + then echo $(GNUTARFLAGS); \ + else :; \ + fi` + +# Flags to give 'gzip' when making a distribution. +GZIPFLAGS= -9n + +############################################################################### + +#MAKE= make + +cc= cc +CC= $(cc) -DTZDIR=\"$(TZDIR)\" + +AR= ar + +# ':' on typical hosts; 'ranlib' on the ancient hosts that still need ranlib. +RANLIB= : + +TZCOBJS= zic.o +TZDOBJS= zdump.o localtime.o asctime.o +DATEOBJS= date.o localtime.o strftime.o asctime.o +LIBSRCS= localtime.c asctime.c difftime.c +LIBOBJS= localtime.o asctime.o difftime.o +HEADERS= tzfile.h private.h +NONLIBSRCS= zic.c zdump.c +NEWUCBSRCS= date.c strftime.c +SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) \ + tzselect.ksh workman.sh +MANS= newctime.3 newstrftime.3 newtzset.3 time2posix.3 \ + tzfile.5 tzselect.8 zic.8 zdump.8 +MANTXTS= newctime.3.txt newstrftime.3.txt newtzset.3.txt \ + time2posix.3.txt \ + tzfile.5.txt tzselect.8.txt zic.8.txt zdump.8.txt \ + date.1.txt +COMMON= CONTRIBUTING LICENSE Makefile NEWS README Theory version +WEB_PAGES= tz-art.htm tz-how-to.html tz-link.htm +DOCS= $(MANS) date.1 $(MANTXTS) $(WEB_PAGES) +PRIMARY_YDATA= africa antarctica asia australasia \ + europe northamerica southamerica +YDATA= $(PRIMARY_YDATA) pacificnew etcetera backward +NDATA= systemv factory +TDATA= $(YDATA) $(NDATA) +ZONETABLES= zone1970.tab zone.tab +TABDATA= iso3166.tab leapseconds $(ZONETABLES) +LEAP_DEPS= leapseconds.awk leap-seconds.list +DATA= $(YDATA) $(NDATA) backzone $(TABDATA) \ + leap-seconds.list yearistype.sh +AWK_SCRIPTS= checklinks.awk checktab.awk leapseconds.awk +MISC= $(AWK_SCRIPTS) zoneinfo2tdf.pl +TZS_YEAR= 2050 +TZS= to$(TZS_YEAR).tzs +TZS_NEW= to$(TZS_YEAR)new.tzs +TZS_DEPS= $(PRIMARY_YDATA) asctime.c localtime.c \ + private.h tzfile.h zdump.c zic.c +ENCHILADA= $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC) $(TZS) + +# Consult these files when deciding whether to rebuild the 'version' file. +# This list is not the same as the output of 'git ls-files', since +# .gitignore is not distributed. +VERSION_DEPS= \ + CONTRIBUTING LICENSE Makefile NEWS README Theory \ + africa antarctica asctime.c asia australasia \ + backward backzone \ + checklinks.awk checktab.awk \ + date.1 date.c difftime.c \ + etcetera europe factory iso3166.tab \ + leap-seconds.list leapseconds.awk localtime.c \ + newctime.3 newstrftime.3 newtzset.3 northamerica \ + pacificnew private.h \ + southamerica strftime.c systemv \ + time2posix.3 tz-art.htm tz-how-to.html tz-link.htm \ + tzfile.5 tzfile.h tzselect.8 tzselect.ksh \ + workman.sh yearistype.sh \ + zdump.8 zdump.c zic.8 zic.c \ + zone.tab zone1970.tab zoneinfo2tdf.pl + +# And for the benefit of csh users on systems that assume the user +# shell should be used to handle commands in Makefiles. . . + +SHELL= /bin/sh + +all: tzselect yearistype zic zdump libtz.a $(TABDATA) + +ALL: all date $(ENCHILADA) + +install: all $(DATA) $(REDO) $(MANS) + mkdir -p $(DESTDIR)$(ETCDIR) $(DESTDIR)$(TZDIR) \ + $(DESTDIR)$(LIBDIR) \ + $(DESTDIR)$(MANDIR)/man3 $(DESTDIR)$(MANDIR)/man5 \ + $(DESTDIR)$(MANDIR)/man8 + $(ZIC_INSTALL) -l $(LOCALTIME) -p $(POSIXRULES) + cp -f iso3166.tab $(ZONETABLES) $(DESTDIR)$(TZDIR)/. + cp tzselect zic zdump $(DESTDIR)$(ETCDIR)/. + cp libtz.a $(DESTDIR)$(LIBDIR)/. + $(RANLIB) $(DESTDIR)$(LIBDIR)/libtz.a + cp -f newctime.3 newtzset.3 $(DESTDIR)$(MANDIR)/man3/. + cp -f tzfile.5 $(DESTDIR)$(MANDIR)/man5/. + cp -f tzselect.8 zdump.8 zic.8 $(DESTDIR)$(MANDIR)/man8/. + +INSTALL: ALL install date.1 + mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man1 + cp date $(DESTDIR)$(BINDIR)/. + cp -f date.1 $(DESTDIR)$(MANDIR)/man1/. + +version: $(VERSION_DEPS) + { (type git) >/dev/null 2>&1 && \ + V=`git describe --match '[0-9][0-9][0-9][0-9][a-z]*' \ + --abbrev=7 --dirty` || \ + V=$(VERSION); } && \ + printf '%s\n' "$$V" >$@.out + mv $@.out $@ + +version.h: version + VERSION=`cat version` && printf '%s\n' \ + 'static char const PKGVERSION[]="($(PACKAGE)) ";' \ + "static char const TZVERSION[]=\"$$VERSION\";" \ + 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";' \ + >$@.out + mv $@.out $@ + +zdump: $(TZDOBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZDOBJS) $(LDLIBS) + +zic: $(TZCOBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZCOBJS) $(LDLIBS) + +yearistype: yearistype.sh + cp yearistype.sh yearistype + chmod +x yearistype + +leapseconds: $(LEAP_DEPS) + $(AWK) -f leapseconds.awk leap-seconds.list >$@.out + mv $@.out $@ + +# Arguments to pass to submakes of install_data. +# They can be overridden by later submake arguments. +INSTALLARGS = \ + DESTDIR=$(DESTDIR) \ + LEAPSECONDS='$(LEAPSECONDS)' \ + PACKRATDATA='$(PACKRATDATA)' \ + TZDIR=$(TZDIR) \ + YEARISTYPE=$(YEARISTYPE) \ + ZIC='$(ZIC)' + +# 'make install_data' installs one set of tz binary files. +# It can be tailored by setting LEAPSECONDS, PACKRATDATA, etc. +install_data: zic leapseconds yearistype $(PACKRATDATA) $(TDATA) + $(ZIC_INSTALL) $(TDATA) + $(AWK) '/^Rule/' $(TDATA) | $(ZIC_INSTALL) - $(PACKRATDATA) + +posix_only: + $(MAKE) $(INSTALLARGS) LEAPSECONDS= install_data + +right_only: + $(MAKE) $(INSTALLARGS) LEAPSECONDS='-L leapseconds' \ + install_data + +# In earlier versions of this makefile, the other two directories were +# subdirectories of $(TZDIR). However, this led to configuration errors. +# For example, with posix_right under the earlier scheme, +# TZ='right/Australia/Adelaide' got you localtime with leap seconds, +# but gmtime without leap seconds, which led to problems with applications +# like sendmail that subtract gmtime from localtime. +# Therefore, the other two directories are now siblings of $(TZDIR). +# You must replace all of $(TZDIR) to switch from not using leap seconds +# to using them, or vice versa. +right_posix: right_only + rm -fr $(DESTDIR)$(TZDIR)-leaps + ln -s $(TZDIR_BASENAME) $(DESTDIR)$(TZDIR)-leaps || \ + $(MAKE) $(INSTALLARGS) TZDIR=$(TZDIR)-leaps right_only + $(MAKE) $(INSTALLARGS) TZDIR=$(TZDIR)-posix posix_only + +posix_right: posix_only + rm -fr $(DESTDIR)$(TZDIR)-posix + ln -s $(TZDIR_BASENAME) $(DESTDIR)$(TZDIR)-posix || \ + $(MAKE) $(INSTALLARGS) TZDIR=$(TZDIR)-posix posix_only + $(MAKE) $(INSTALLARGS) TZDIR=$(TZDIR)-leaps right_only + +# This obsolescent rule is present for backwards compatibility with +# tz releases 2014g through 2015g. It should go away eventually. +posix_packrat: + $(MAKE) $(INSTALLARGS) PACKRATDATA=backzone posix_only + +zones: $(REDO) + +$(TZS_NEW): $(TDATA) zdump zic + mkdir -p tzs.dir + $(zic) -d tzs.dir $(TDATA) + $(AWK) '/^Link/{print $$1 "\t" $$2 "\t" $$3}' \ + $(TDATA) | LC_ALL=C sort >$@.out + wd=`pwd` && \ + zones=`$(AWK) -v wd="$$wd" \ + '/^Zone/{print wd "/tzs.dir/" $$2}' $(TDATA) \ + | LC_ALL=C sort` && \ + ./zdump -i -c $(TZS_YEAR) $$zones >>$@.out + sed 's,^TZ=".*tzs\.dir/,TZ=",' $@.out >$@.sed.out + rm -fr tzs.dir $@.out + mv $@.sed.out $@ + +# If $(TZS) does not already exist (e.g., old-format tarballs), create it. +# If it exists but 'make check_tzs' fails, a maintainer should inspect the +# failed output and fix the inconsistency, perhaps by running 'make force_tzs'. +$(TZS): + $(MAKE) force_tzs + +force_tzs: $(TZS_NEW) + cp $(TZS_NEW) $(TZS) + +libtz.a: $(LIBOBJS) + $(AR) ru $@ $(LIBOBJS) + $(RANLIB) $@ + +date: $(DATEOBJS) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(DATEOBJS) $(LDLIBS) + +tzselect: tzselect.ksh version + VERSION=`cat version` && sed \ + -e 's|#!/bin/bash|#!$(KSHELL)|g' \ + -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ + -e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \ + -e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \ + -e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \ + -e 's|\(TZVERSION\)=.*|\1='"$$VERSION"'|' \ + <$@.ksh >$@.out + chmod +x $@.out + mv $@.out $@ + +check: check_character_set check_white_space check_links check_sorted \ + check_tables check_tzs check_web + +check_character_set: $(ENCHILADA) + LC_ALL=en_US.utf8 && export LC_ALL && \ + sharp='#' && \ + ! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \ + $(MISC) $(SOURCES) $(WEB_PAGES) \ + CONTRIBUTING LICENSE Makefile README version && \ + ! grep -Env $(SAFE_SHARP_LINE) $(TDATA) backzone \ + leapseconds yearistype.sh zone.tab && \ + ! grep -Env $(OK_LINE) $(ENCHILADA) + +check_white_space: $(ENCHILADA) + patfmt=' \t|[\f\r\v]' && pat=`printf "$$patfmt\\n"` && \ + ! grep -En "$$pat" $(ENCHILADA) + ! grep -n '[[:space:]]$$' $(ENCHILADA) + +CHECK_CC_LIST = { n = split($$1,a,/,/); for (i=2; i<=n; i++) print a[1], a[i]; } + +check_sorted: backward backzone iso3166.tab zone.tab zone1970.tab + $(AWK) '/^Link/ {print $$3}' backward | LC_ALL=C sort -cu + $(AWK) '/^Zone/ {print $$2}' backzone | LC_ALL=C sort -cu + $(AWK) '/^[^#]/ {print $$1}' iso3166.tab | LC_ALL=C sort -cu + $(AWK) '/^[^#]/ {print $$1}' zone.tab | LC_ALL=C sort -c + $(AWK) '/^[^#]/ {print substr($$0, 1, 2)}' zone1970.tab | \ + LC_ALL=C sort -c + $(AWK) '/^[^#]/ $(CHECK_CC_LIST)' zone1970.tab | \ + LC_ALL=C sort -cu + +check_links: checklinks.awk $(TDATA) + $(AWK) -f checklinks.awk $(TDATA) + +check_tables: checktab.awk $(PRIMARY_YDATA) $(ZONETABLES) + for tab in $(ZONETABLES); do \ + $(AWK) -f checktab.awk -v zone_table=$$tab $(PRIMARY_YDATA) \ + || exit; \ + done + +check_tzs: $(TZS) $(TZS_NEW) + diff -u $(TZS) $(TZS_NEW) + +check_web: $(WEB_PAGES) + $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES) + +clean_misc: + rm -f core *.o *.out \ + date tzselect version.h zdump zic yearistype libtz.a +clean: clean_misc + rm -fr *.dir tzdb-*/ $(TZS_NEW) + +maintainer-clean: clean + @echo 'This command is intended for maintainers to use; it' + @echo 'deletes files that may need special tools to rebuild.' + rm -f leapseconds version $(MANTXTS) $(TZS) *.asc *.tar.* + +names: + @echo $(ENCHILADA) + +public: check check_public $(CHECK_TIME_T_ALTERNATIVES) \ + tarballs signatures + +date.1.txt: date.1 +newctime.3.txt: newctime.3 +newstrftime.3.txt: newstrftime.3 +newtzset.3.txt: newtzset.3 +time2posix.3.txt: time2posix.3 +tzfile.5.txt: tzfile.5 +tzselect.8.txt: tzselect.8 +zdump.8.txt: zdump.8 +zic.8.txt: zic.8 + +$(MANTXTS): workman.sh + LC_ALL=C sh workman.sh `expr $@ : '\(.*\)\.txt$$'` >$@.out + mv $@.out $@ + +# Set the time stamps to those of the git repository, if available, +# and if the files have not changed since then. +# This uses GNU 'touch' syntax 'touch -d@N FILE', +# where N is the number of seconds since 1970. +# If git or GNU 'touch' is absent, don't bother to sync with git timestamps. +# Also, set the timestamp of each prebuilt file like 'leapseconds' +# to be the maximum of the files it depends on. +set-timestamps.out: $(ENCHILADA) + rm -f $@ + if (type git) >/dev/null 2>&1 && \ + files=`git ls-files $(ENCHILADA)` && \ + touch -md @1 test.out; then \ + rm -f test.out && \ + for file in $$files; do \ + if git diff --quiet $$file; then \ + time=`git log -1 --format='tformat:%ct' $$file` && \ + touch -cmd @$$time $$file; \ + else \ + echo >&2 "$$file: warning: does not match repository"; \ + fi || exit; \ + done; \ + fi + touch -cmr `ls -t $(LEAP_DEPS) | sed 1q` leapseconds + for file in `ls $(MANTXTS) | sed 's/\.txt$$//'`; do \ + touch -cmr `ls -t $$file workman.sh | sed 1q` $$file.txt || \ + exit; \ + done + touch -cmr `ls -t $(TZS_DEPS) | sed 1q` $(TZS) + touch -cmr `ls -t $(VERSION_DEPS) | sed 1q` version + touch $@ + +# The zics below ensure that each data file can stand on its own. +# We also do an all-files run to catch links to links. + +check_public: + $(MAKE) maintainer-clean + $(MAKE) "CFLAGS=$(GCC_DEBUG_FLAGS)" ALL + mkdir -p public.dir + for i in $(TDATA) ; do \ + $(zic) -v -d public.dir $$i 2>&1 || exit; \ + done + $(zic) -v -d public.dir $(TDATA) + rm -fr public.dir + +# Check that the code works under various alternative +# implementations of time_t. +check_time_t_alternatives: + if diff -q Makefile Makefile 2>/dev/null; then \ + quiet_option='-q'; \ + else \ + quiet_option=''; \ + fi && \ + wd=`pwd` && \ + zones=`$(AWK) '/^[^#]/ { print $$3 }' time_t.dir/int64_t.out && \ + time_t.dir/$$type/etc/zdump -V -t $$range $$zones \ + >time_t.dir/$$type.out && \ + diff -u time_t.dir/int64_t.out time_t.dir/$$type.out \ + || exit; \ + done + rm -fr time_t.dir + +tarballs traditional_tarballs signatures traditional_signatures: version + VERSION=`cat version` && \ + $(MAKE) VERSION="$$VERSION" $@_version + +tarballs_version: traditional_tarballs_version tzdb-$(VERSION).tar.lz +traditional_tarballs_version: \ + tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz +signatures_version: traditional_signatures_version tzdb-$(VERSION).tar.lz.asc +traditional_signatures_version: \ + tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc \ + +tzcode$(VERSION).tar.gz: set-timestamps.out + LC_ALL=C && export LC_ALL && \ + tar $(TARFLAGS) -cf - \ + $(COMMON) $(DOCS) $(SOURCES) | \ + gzip $(GZIPFLAGS) >$@.out + mv $@.out $@ + +tzdata$(VERSION).tar.gz: set-timestamps.out + LC_ALL=C && export LC_ALL && \ + tar $(TARFLAGS) -cf - $(COMMON) $(DATA) $(MISC) | \ + gzip $(GZIPFLAGS) >$@.out + mv $@.out $@ + +tzdb-$(VERSION).tar.lz: set-timestamps.out + rm -fr tzdb-$(VERSION) + mkdir tzdb-$(VERSION) + ln $(ENCHILADA) tzdb-$(VERSION) + touch -cmr `ls -t tzdb-$(VERSION)/* | sed 1q` tzdb-$(VERSION) + LC_ALL=C && export LC_ALL && \ + tar $(TARFLAGS) -cf - tzdb-$(VERSION) | lzip -9 >$@.out + mv $@.out $@ + +tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz + gpg --armor --detach-sign $? + +tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz + gpg --armor --detach-sign $? + +tzdb-$(VERSION).tar.lz.asc: tzdb-$(VERSION).tar.lz + gpg --armor --detach-sign $? + +typecheck: + $(MAKE) clean + for i in "long long" unsigned; \ + do \ + $(MAKE) CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \ + ./zdump -v Europe/Rome ; \ + $(MAKE) clean ; \ + done + +zonenames: $(TDATA) + @$(AWK) '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA) + +asctime.o: private.h tzfile.h +date.o: private.h +difftime.o: private.h +localtime.o: private.h tzfile.h +strftime.o: private.h tzfile.h +zdump.o: version.h +zic.o: private.h tzfile.h version.h + +.KEEP_STATE: + +.PHONY: ALL INSTALL all +.PHONY: check check_character_set check_links +.PHONY: check_public check_sorted check_tables +.PHONY: check_time_t_alternatives check_tzs check_web check_white_space +.PHONY: clean clean_misc force_tzs +.PHONY: install install_data maintainer-clean names +.PHONY: posix_only posix_packrat posix_right +.PHONY: public right_only right_posix signatures signatures_version +.PHONY: tarballs tarballs_version typecheck +.PHONY: zonenames zones diff --git a/NEWS b/NEWS new file mode 100644 index 000000000000..da5c2a5717cf --- /dev/null +++ b/NEWS @@ -0,0 +1,3782 @@ +News for the tz database + +Release 2016i - 2016-11-01 23:19:52 -0700 + + Briefly: Cyprus split into two time zones on 2016-10-30, and Tonga + reintroduces DST on 2016-11-06. + + Changes to future time stamps + + Pacific/Tongatapu begins DST on 2016-11-06 at 02:00, ending on + 2017-01-15 at 03:00. Assume future observances in Tonga will be + from the first Sunday in November through the third Sunday in + January, like Fiji. (Thanks to Pulu ʻAnau.) Switch to numeric + time zone abbreviations for this zone. + + Changes to past and future time stamps + + Northern Cyprus is now +03 year round, causing a split in Cyprus + time zones starting 2016-10-30 at 04:00. This creates a zone + Asia/Famagusta. (Thanks to Even Scharning and Matt Johnson.) + + Antarctica/Casey switched from +08 to +11 on 2016-10-22. + (Thanks to Steffen Thorsen.) + + Changes to past time stamps + + Several corrections were made for pre-1975 time stamps in Italy. + These affect Europe/Malta, Europe/Rome, Europe/San_Marino, and + Europe/Vatican. + + First, the 1893-11-01 00:00 transition in Italy used the new UT + offset (+01), not the old (+00:49:56). (Thanks to Michael + Deckers.) + + Second, rules for daylight saving in Italy were changed to agree + with Italy's National Institute of Metrological Research (INRiM) + except for 1944, as follows (thanks to Pierpaolo Bernardi, Brian + Inglis, and Michael Deckers): + + The 1916-06-03 transition was at 24:00, not 00:00. + + The 1916-10-01, 1919-10-05, and 1920-09-19 transitions were at + 00:00, not 01:00. + + The 1917-09-30 and 1918-10-06 transitions were at 24:00, not + 01:00. + + The 1944-09-17 transition was at 03:00, not 01:00. This + particular change is taken from Italian law as INRiM's table, + (which says 02:00) appears to have a typo here. Also, keep the + 1944-04-03 transition for Europe/Rome, as Rome was controlled by + Germany then. + + The 1967-1970 and 1972-1974 fallback transitions were at 01:00, + not 00:00. + + Changes to code + + The code should now be buildable on AmigaOS merely by setting the + appropriate Makefile variables. (From a patch by Carsten Larsen.) + + +Release 2016h - 2016-10-19 23:17:57 -0700 + + Changes to future time stamps + + Asia/Gaza and Asia/Hebron end DST on 2016-10-29 at 01:00, not + 2016-10-21 at 00:00. (Thanks to Sharef Mustafa.) Predict that + future fall transitions will be on the last Saturday of October + at 01:00, which is consistent with predicted spring transitions + on the last Saturday of March. (Thanks to Tim Parenti.) + + Changes to past time stamps + + In Turkey, transitions in 1986-1990 were at 01:00 standard time + not at 02:00, and the spring 1994 transition was on March 20, not + March 27. (Thanks to Kıvanç Yazan.) + + Changes to past and future time zone abbreviations + + Asia/Colombo now uses numeric time zone abbreviations like "+0530" + instead of alphabetic ones like "IST" and "LKT". Various + English-language sources use "IST", "LKT" and "SLST", with no + working consensus. (Usage of "SLST" mentioned by Sadika + Sumanapala.) + + Changes to code + + zic no longer mishandles relativizing file names when creating + symbolic links like /etc/localtime, when these symbolic links + are outside the usual directory hierarchy. This fixes a bug + introduced in 2016g. (Problem reported by Andreas Stieger.) + + Changes to build procedure + + New rules 'traditional_tarballs' and 'traditional_signatures' for + building just the traditional-format distribution. (Requested by + Deborah Goldsmith.) + + The file 'version' is now put into the tzdata tarball too. + (Requested by Howard Hinnant.) + + Changes to documentation and commentary + + The 'Theory' file now has a section on interface stability. + (Requested by Paul Koning.) It also mentions features like + tm_zone and localtime_rz that have long been supported by the + reference code. + + tz-link.htm has improved coverage of time zone boundaries suitable + for geolocation. (Thanks to heads-ups from Evan Siroky and Matt + Johnson.) + + The US commentary now mentions Allen and the "day of two noons". + + The Fiji commentary mentions the government's 2016-10-03 press + release. (Thanks to Raymond Kumar.) + + +Release 2016g - 2016-09-13 08:56:38 -0700 + + Changes to future time stamps + + Turkey switched from EET/EEST (+02/+03) to permanent +03, + effective 2016-09-07. (Thanks to Burak AYDIN.) Use "+03" rather + than an invented abbreviation for the new time. + + New leap second 2016-12-31 23:59:60 UTC as per IERS Bulletin C 52. + (Thanks to Tim Parenti.) + + Changes to past time stamps + + For America/Los_Angeles, spring-forward transition times have been + corrected from 02:00 to 02:01 in 1948, and from 02:00 to 01:00 in + 1950-1966. + + For zones using Soviet time on 1919-07-01, transitions to UT-based + time were at 00:00 UT, not at 02:00 local time. The affected + zones are Europe/Kirov, Europe/Moscow, Europe/Samara, and + Europe/Ulyanovsk. (Thanks to Alexander Belopolsky.) + + Changes to past and future time zone abbreviations + + The Factory zone now uses the time zone abbreviation -00 instead + of a long English-language string, as -00 is now the normal way to + represent an undefined time zone. + + Several zones in Antarctica and the former Soviet Union, along + with zones intended for ships at sea that cannot use POSIX TZ + strings, now use numeric time zone abbreviations instead of + invented or obsolete alphanumeric abbreviations. The affected + zones are Antarctica/Casey, Antarctica/Davis, + Antarctica/DumontDUrville, Antarctica/Mawson, Antarctica/Rothera, + Antarctica/Syowa, Antarctica/Troll, Antarctica/Vostok, + Asia/Anadyr, Asia/Ashgabat, Asia/Baku, Asia/Bishkek, Asia/Chita, + Asia/Dushanbe, Asia/Irkutsk, Asia/Kamchatka, Asia/Khandyga, + Asia/Krasnoyarsk, Asia/Magadan, Asia/Omsk, Asia/Sakhalin, + Asia/Samarkand, Asia/Srednekolymsk, Asia/Tashkent, Asia/Tbilisi, + Asia/Ust-Nera, Asia/Vladivostok, Asia/Yakutsk, Asia/Yekaterinburg, + Asia/Yerevan, Etc/GMT-14, Etc/GMT-13, Etc/GMT-12, Etc/GMT-11, + Etc/GMT-10, Etc/GMT-9, Etc/GMT-8, Etc/GMT-7, Etc/GMT-6, Etc/GMT-5, + Etc/GMT-4, Etc/GMT-3, Etc/GMT-2, Etc/GMT-1, Etc/GMT+1, Etc/GMT+2, + Etc/GMT+3, Etc/GMT+4, Etc/GMT+5, Etc/GMT+6, Etc/GMT+7, Etc/GMT+8, + Etc/GMT+9, Etc/GMT+10, Etc/GMT+11, Etc/GMT+12, Europe/Kaliningrad, + Europe/Minsk, Europe/Samara, Europe/Volgograd, and + Indian/Kerguelen. For Europe/Moscow the invented abbreviation MSM + was replaced by +05, whereas MSK and MSD were kept as they are not + our invention and are widely used. + + Changes to zone names + + Rename Asia/Rangoon to Asia/Yangon, with a backward compatibility link. + (Thanks to David Massoud.) + + Changes to code + + zic no longer generates binary files containing POSIX TZ-like + strings that disagree with the local time type after the last + explicit transition in the data. This fixes a bug with + Africa/Casablanca and Africa/El_Aaiun in some year-2037 time + stamps on the reference platform. (Thanks to Alexander Belopolsky + for reporting the bug and suggesting a way forward.) + + If the installed localtime and/or posixrules files are symbolic + links, zic now keeps them symbolic links when updating them, for + compatibility with platforms like OpenSUSE where other programs + configure these files as symlinks. + + zic now avoids hard linking to symbolic links, avoids some + unnecessary mkdir and stat system calls, and uses shorter file + names internally. + + zdump has a new -i option to generate transitions in a + more-compact but still human-readable format. This option is + experimental, and the output format may change in future versions. + (Thanks to Jon Skeet for suggesting that an option was needed, + and thanks to Tim Parenti and Chris Rovick for further comments.) + + Changes to build procedure + + An experimental distribution format is available, in addition + to the traditional format which will continue to be distributed. + The new format is a tarball tzdb-VERSION.tar.lz with signature + file tzdb-VERSION.tar.lz.asc. It unpacks to a top-level directory + tzdb-VERSION containing the code and data of the traditional + two-tarball format, along with extra data that may be useful. + (Thanks to Antonio Diaz Diaz, Oscar van Vlijmen, and many others + for comments about the experimental format.) + + The release version number is now more accurate in the usual case + where releases are built from a Git repository. For example, if + 23 commits and some working-file changes have been made since + release 2016g, the version number is now something like + '2016g-23-g50556e3-dirty' instead of the misleading '2016g'. + Official releases uses the same version number format as before, + e.g., '2016g'. To support the more-accurate version number, its + specification has moved from a line in the Makefile to a new + source file 'version'. + + The experimental distribution contains a file to2050.tzs that + contains what should be the output of 'zdump -i -c 2050' on + primary zones. If this file is available, 'make check' now checks + that zdump generates this output. + + 'make check_web' now works on Fedora-like distributions. + + Changes to documentation and commentary + + tzfile.5 now documents the new restriction on POSIX TZ-like + strings that is now implemented by zic. + + Comments now cite URLs for some 1917-1921 Russian DST decrees. + (Thanks to Alexander Belopolsky.) + + tz-link.htm mentions JuliaTime (thanks to Curtis Vogt) and Time4J + (thanks to Meno Hochschild) and ThreeTen-Extra, and its + description of Java 8 has been brought up to date (thanks to + Stephen Colebourne). Its description of local time on Mars has + been updated to match current practice, and URLs have been updated + and some obsolete ones removed. + + +Release 2016f - 2016-07-05 16:26:51 +0200 + + Changes affecting future time stamps + + The Egyptian government changed its mind on short notice, and + Africa/Cairo will not introduce DST starting 2016-07-07 after all. + (Thanks to Mina Samuel.) + + Asia/Novosibirsk switches from +06 to +07 on 2016-07-24 at 02:00. + (Thanks to Stepan Golosunov.) + + Changes to past and future time stamps + + Asia/Novokuznetsk and Asia/Novosibirsk now use numeric time zone + abbreviations instead of invented ones. + + Changes affecting past time stamps + + Europe/Minsk's 1992-03-29 spring-forward transition was at 02:00 not 00:00. + (Thanks to Stepan Golosunov.) + + +Release 2016e - 2016-06-14 08:46:16 -0700 + + Changes affecting future time stamps + + Africa/Cairo observes DST in 2016 from July 7 to the end of October. + Guess October 27 and 24:00 transitions. (Thanks to Steffen Thorsen.) + For future years, guess April's last Thursday to October's last + Thursday except for Ramadan. + + Changes affecting past time stamps + + Locations while uninhabited now use '-00', not 'zzz', as a + placeholder time zone abbreviation. This is inspired by Internet + RFC 3339 and is more consistent with numeric time zone + abbreviations already used elsewhere. The change affects several + arctic and antarctic locations, e.g., America/Cambridge_Bay before + 1920 and Antarctica/Troll before 2005. + + Asia/Baku's 1992-09-27 transition from +04 (DST) to +04 (non-DST) was + at 03:00, not 23:00 the previous day. (Thanks to Michael Deckers.) + + Changes to code + + zic now outputs a dummy transition at time 2**31 - 1 in zones + whose POSIX-style TZ strings contain a '<'. This mostly works + around Qt bug 53071 . + (Thanks to Zhanibek Adilbekov for reporting the Qt bug.) + + Changes affecting documentation and commentary + + tz-link.htm says why governments should give plenty of notice for + time zone or DST changes, and refers to Matt Johnson's blog post. + + tz-link.htm mentions Tzdata for Elixir. (Thanks to Matt Johnson.) + + +Release 2016d - 2016-04-17 22:50:29 -0700 + + Changes affecting future time stamps + + America/Caracas switches from -0430 to -04 on 2016-05-01 at 02:30. + (Thanks to Alexander Krivenyshev for the heads-up.) + + Asia/Magadan switches from +10 to +11 on 2016-04-24 at 02:00. + (Thanks to Alexander Krivenyshev and Matt Johnson.) + + New zone Asia/Tomsk, split off from Asia/Novosibirsk. It covers + Tomsk Oblast, Russia, which switches from +06 to +07 on 2016-05-29 + at 02:00. (Thanks to Stepan Golosunov.) + + Changes affecting past time stamps + + New zone Europe/Kirov, split off from Europe/Volgograd. It covers + Kirov Oblast, Russia, which switched from +04/+05 to +03/+04 on + 1989-03-26 at 02:00, roughly a year after Europe/Volgograd made + the same change. (Thanks to Stepan Golosunov.) + + Russia and nearby locations had daylight-saving transitions on + 1992-03-29 at 02:00 and 1992-09-27 at 03:00, instead of on + 1992-03-28 at 23:00 and 1992-09-26 at 23:00. (Thanks to Stepan + Golosunov.) + + Many corrections to historical time in Kazakhstan from 1991 + through 2005. (Thanks to Stepan Golosunov.) Replace Kazakhstan's + invented time zone abbreviations with numeric abbreviations. + + Changes to commentary + + Mention Internet RFCs 7808 (TZDIST) and 7809 (CalDAV time zone references). + + +Release 2016c - 2016-03-23 00:51:27 -0700 + + Changes affecting future time stamps + + Azerbaijan no longer observes DST. (Thanks to Steffen Thorsen.) + + Chile reverts from permanent to seasonal DST. (Thanks to Juan + Correa for the heads-up, and to Tim Parenti for corrections.) + Guess that future transitions are August's and May's second + Saturdays at 24:00 mainland time. Also, call the period from + 2014-09-07 through 2016-05-14 daylight saving time instead of + standard time, as that seems more appropriate now. + + Changes affecting past time stamps + + Europe/Kaliningrad and Europe/Vilnius changed from +03/+04 to + +02/+03 on 1989-03-26, not 1991-03-31. Europe/Volgograd changed + from +04/+05 to +03/+04 on 1988-03-27, not 1989-03-26. + (Thanks to Stepan Golosunov.) + + Changes to commentary + + Several updates and URLs for historical and proposed Russian changes. + (Thanks to Stepan Golosunov, Matt Johnson, and Alexander Krivenyshev.) + + +Release 2016b - 2016-03-12 17:30:14 -0800 + + Compatibility note + + Starting with release 2016b, some data entries cause zic implementations + derived from tz releases 2005j through 2015e to issue warnings like + "time zone abbreviation differs from POSIX standard (+03)". + These warnings should not otherwise affect zic's output and can safely be + ignored on today's platforms, as the warnings refer to a restriction in + POSIX.1-1988 that was removed in POSIX.1-2001. One way to suppress the + warnings is to upgrade to zic derived from tz releases 2015f and later. + + Changes affecting future time stamps + + New zones Europe/Astrakhan and Europe/Ulyanovsk for Astrakhan and + Ulyanovsk Oblasts, Russia, both of which will switch from +03 to +04 on + 2016-03-27 at 02:00 local time. They need distinct zones since their + post-1970 histories disagree. New zone Asia/Barnaul for Altai Krai and + Altai Republic, Russia, which will switch from +06 to +07 on the same date + and local time. The Astrakhan change is already official; the others have + passed the first reading in the State Duma and are extremely likely. + Also, Asia/Sakhalin moves from +10 to +11 on 2016-03-27 at 02:00. + (Thanks to Alexander Krivenyshev for the heads-up, and to Matt Johnson + and Stepan Golosunov for followup.) + + As a trial of a new system that needs less information to be made up, + the new zones use numeric time zone abbreviations like "+04" + instead of invented abbreviations like "ASTT". + + Haiti will not observe DST in 2016. (Thanks to Jean Antoine via + Steffen Thorsen.) + + Palestine's spring-forward transition on 2016-03-26 is at 01:00, not 00:00. + (Thanks to Hannah Kreitem.) Guess future transitions will be March's last + Saturday at 01:00, not March's last Friday at 24:00. + + Changes affecting past time stamps + + Europe/Chisinau observed DST during 1990, and switched from +04 to + +03 at 1990-05-06 02:00, instead of switching from +03 to +02. + (Thanks to Stepan Golosunov.) + + 1991 abbreviations in Europe/Samara should be SAMT/SAMST, not + KUYT/KUYST. (Thanks to Stepan Golosunov.) + + Changes to code + + tzselect's diagnostics and checking, and checktab.awk's checking, + have been improved. (Thanks to J William Piggott.) + + tzcode now builds under MinGW. (Thanks to Ian Abbott and Esben Haabendal.) + + tzselect now tests Julian-date TZ settings more accurately. + (Thanks to J William Piggott.) + + Changes to commentary + + Comments in zone tables have been improved. (Thanks to J William Piggott.) + + tzselect again limits its menu comments so that menus fit on a + 24x80 alphanumeric display. + + A new web page tz-how-to.html. (Thanks to Bill Seymour.) + + In the Theory file, the description of possible time zone abbreviations in + tzdata has been cleaned up, as the old description was unclear and + inconsistent. (Thanks to Alain Mouette for reporting the problem.) + + +Release 2016a - 2016-01-26 23:28:02 -0800 + + Changes affecting future time stamps + + America/Cayman will not observe daylight saving this year after all. + Revert our guess that it would. (Thanks to Matt Johnson.) + + Asia/Chita switches from +0800 to +0900 on 2016-03-27 at 02:00. + (Thanks to Alexander Krivenyshev.) + + Asia/Tehran now has DST predictions for the year 2038 and later, + to be March 21 00:00 to September 21 00:00. This is likely better + than predicting no DST, albeit off by a day every now and then. + + Changes affecting past and future time stamps + + America/Metlakatla switched from PST all year to AKST/AKDT on + 2015-11-01 at 02:00. (Thanks to Steffen Thorsen.) + + America/Santa_Isabel has been removed, and replaced with a + backward compatibility link to America/Tijuana. Its contents were + apparently based on a misreading of Mexican legislation. + + Changes affecting past time stamps + + Asia/Karachi's two transition times in 2002 were off by a minute. + (Thanks to Matt Johnson.) + + Changes affecting build procedure + + An installer can now combine leap seconds with use of the backzone file, + e.g., with 'make PACKRATDATA=backzone REDO=posix_right zones'. + The old 'make posix_packrat' rule is now marked as obsolescent. + (Thanks to Ian Abbott for an initial implementation.) + + Changes affecting documentation and commentary + + A new file LICENSE makes it easier to see that the code and data + are mostly public-domain. (Thanks to James Knight.) The three + non-public-domain files now use the current (3-clause) BSD license + instead of older versions of that license. + + tz-link.htm mentions the BDE library (thanks to Andrew Paprocki), + CCTZ (thanks to Tim Parenti), TimeJones.com, and has a new section + on editing tz source files (with a mention of Sublime zoneinfo, + thanks to Gilmore Davidson). + + The Theory and asia files now mention the 2015 book "The Global + Transformation of Time, 1870-1950", and cite a couple of reviews. + + The America/Chicago entry now documents the informal use of US + central time in Fort Pierre, South Dakota. (Thanks to Rick + McDermid, Matt Johnson, and Steve Jones.) + + +Release 2015g - 2015-10-01 00:39:51 -0700 + + Changes affecting future time stamps + + Turkey's 2015 fall-back transition is scheduled for Nov. 8, not Oct. 25. + (Thanks to Fatih.) + + Norfolk moves from +1130 to +1100 on 2015-10-04 at 02:00 local time. + (Thanks to Alexander Krivenyshev.) + + Fiji's 2016 fall-back transition is scheduled for January 17, not 24. + (Thanks to Ken Rylander.) + + Fort Nelson, British Columbia will not fall back on 2015-11-01. It has + effectively been on MST (-0700) since it advanced its clocks on 2015-03-08. + New zone America/Fort_Nelson. (Thanks to Matt Johnson.) + + Changes affecting past time stamps + + Norfolk observed DST from 1974-10-27 02:00 to 1975-03-02 02:00. + + Changes affecting code + + localtime no longer mishandles America/Anchorage after 2037. + (Thanks to Bradley White for reporting the bug.) + + On hosts with signed 32-bit time_t, localtime no longer mishandles + Pacific/Fiji after 2038-01-16 14:00 UTC. + + The localtime module allows the variables 'timezone', 'daylight', + and 'altzone' to be in common storage shared with other modules, + and declares them in case the system does not. + (Problems reported by Kees Dekker.) + + On platforms with tm_zone, strftime.c now assumes it is not NULL. + This simplifies the code and is consistent with zdump.c. + (Problem reported by Christos Zoulas.) + + Changes affecting documentation + + The tzfile man page now documents that transition times denote the + starts (not the ends) of the corresponding time periods. + (Ambiguity reported by Bill Seymour.) + + +Release 2015f - 2015-08-10 18:06:56 -0700 + + Changes affecting future time stamps + + North Korea switches to +0830 on 2015-08-15. (Thanks to Steffen Thorsen.) + The abbreviation remains "KST". (Thanks to Robert Elz.) + + Uruguay no longer observes DST. (Thanks to Steffen Thorsen + and Pablo Camargo.) + + Changes affecting past and future time stamps + + Moldova starts and ends DST at 00:00 UTC, not at 01:00 UTC. + (Thanks to Roman Tudos.) + + Changes affecting data format and code + + zic's '-y YEARISTYPE' option is no longer documented. The TYPE + field of a Rule line should now be '-'; the old values 'even', + 'odd', 'uspres', 'nonpres', 'nonuspres' were already undocumented. + Although the implementation has not changed, these features do not + work in the default installation, they are not used in the data, + and they are now considered obsolescent. + + zic now checks that two rules don't take effect at the same time. + (Thanks to Jon Skeet and Arthur David Olson.) Constraints on + simultaneity are now documented. + + The two characters '%z' in a zone format now stand for the UTC + offset, e.g., '-07' for seven hours behind UTC and '+0530' for + five hours and thirty minutes ahead. This better supports time + zone abbreviations conforming to POSIX.1-2001 and later. + + Changes affecting installed data files + + Comments for America/Halifax and America/Glace_Bay have been improved. + (Thanks to Brian Inglis.) + + Data entries have been simplified for Atlantic/Canary, Europe/Simferopol, + Europe/Sofia, and Europe/Tallinn. This yields slightly smaller + installed data files for Europe/Simferopol and Europe/Tallinn. + It does not affect timestamps. (Thanks to Howard Hinnant.) + + Changes affecting code + + zdump and zic no longer warn about valid time zone abbreviations + like '-05'. + + Some Visual Studio 2013 warnings have been suppressed. + (Thanks to Kees Dekker.) + + 'date' no longer sets the time of day and its -a, -d, -n and -t + options have been removed. Long obsolescent, the implementation + of these features had porting problems. Builders no longer need + to configure HAVE_ADJTIME, HAVE_SETTIMEOFDAY, or HAVE_UTMPX_H. + (Thanks to Kees Dekker for pointing out the problem.) + + Changes affecting documentation + + The Theory file mentions naming issues earlier, as these seem to be + poorly publicized (thanks to Gilmore Davidson for reporting the problem). + + tz-link.htm mentions Time Zone Database Parser (thanks to Howard Hinnant). + + Mention that Herbert Samuel introduced the term "Summer Time". + + +Release 2015e - 2015-06-13 10:56:02 -0700 + + Changes affecting future time stamps + + Morocco will suspend DST from 2015-06-14 03:00 through 2015-07-19 02:00, + not 06-13 and 07-18 as we had guessed. (Thanks to Milamber.) + + Assume Cayman Islands will observe DST starting next year, using US rules. + Although it isn't guaranteed, it is the most likely. + + Changes affecting data format + + The file 'iso3166.tab' now uses UTF-8, so that its entries can better + spell the names of Åland Islands, Côte d'Ivoire, and Réunion. + + Changes affecting code + + When displaying data, tzselect converts it to the current locale's + encoding if the iconv command works. (Problem reported by random832.) + + tzselect no longer mishandles Dominica, fixing a bug introduced + in Release 2014f. (Problem reported by Owen Leibman.) + + zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\". + This fixes a bug introduced in Release 2014f. + (Problem reported by Leonardo Chiquitto.) + + +Release 2015d - 2015-04-24 08:09:46 -0700 + + Changes affecting future time stamps + + Egypt will not observe DST in 2015 and will consider canceling it + permanently. For now, assume no DST indefinitely. + (Thanks to Ahmed Nazmy and Tim Parenti.) + + Changes affecting past time stamps + + America/Whitehorse switched from UT -09 to -08 on 1967-05-28, not + 1966-07-01. Also, Yukon's time zone history is documented better. + (Thanks to Brian Inglis and Dennis Ferguson.) + + Change affecting past and future time zone abbreviations + + The abbreviations for Hawaii-Aleutian standard and daylight times + have been changed from HAST/HADT to HST/HDT, as per US Government + Printing Office style. This affects only America/Adak since 1983, + as America/Honolulu was already using the new style. + + Changes affecting code + + zic has some minor performance improvements. + + +Release 2015c - 2015-04-11 08:55:55 -0700 + + Changes affecting future time stamps + + Egypt's spring-forward transition is at 24:00 on April's last Thursday, + not 00:00 on April's last Friday. 2015's transition will therefore be on + Thursday, April 30 at 24:00, not Friday, April 24 at 00:00. Similar fixes + apply to 2026, 2037, 2043, etc. (Thanks to Steffen Thorsen.) + + Changes affecting past time stamps + + The following changes affect some pre-1991 Chile-related time stamps + in America/Santiago, Antarctica/Palmer, and Pacific/Easter. + + The 1910 transition was January 10, not January 1. + + The 1918 transition was September 10, not September 1. + + The UT -04 time observed from 1932 to 1942 is now considered to + be standard time, not year-round DST. + + Santiago observed DST (UT -03) from 1946-07-15 through + 1946-08-31, then reverted to standard time, then switched to -05 + on 1947-04-01. + + Assume transitions before 1968 were at 00:00, since we have no data + saying otherwise. + + The spring 1988 transition was 1988-10-09, not 1988-10-02. + The fall 1990 transition was 1990-03-11, not 1990-03-18. + + Assume no UTC offset change for Pacific/Easter on 1890-01-01, + and omit all transitions on Pacific/Easter from 1942 through 1946 + since we have no data suggesting that they existed. + + One more zone has been turned into a link, as it differed + from an existing zone only for older time stamps. As usual, + this change affects UTC offsets in pre-1970 time stamps only. + The zone's old contents have been moved to the 'backzone' file. + The affected zone is America/Montreal. + + Changes affecting commentary + + Mention the TZUpdater tool. + + Mention "The Time Now". (Thanks to Brandon Ramsey.) + + +Release 2015b - 2015-03-19 23:28:11 -0700 + + Changes affecting future time stamps + + Mongolia will start observing DST again this year, from the last + Saturday in March at 02:00 to the last Saturday in September at 00:00. + (Thanks to Ganbold Tsagaankhuu.) + + Palestine will start DST on March 28, not March 27. Also, + correct the fall 2014 transition from September 26 to October 24. + Adjust future predictions accordingly. (Thanks to Steffen Thorsen.) + + Changes affecting past time stamps + + The 1982 zone shift in Pacific/Easter has been corrected, fixing a 2015a + regression. (Thanks to Stuart Bishop for reporting the problem.) + + Some more zones have been turned into links, when they differed + from existing zones only for older time stamps. As usual, + these changes affect UTC offsets in pre-1970 time stamps only. + Their old contents have been moved to the 'backzone' file. + The affected zones are: America/Antigua, America/Cayman, + Pacific/Midway, and Pacific/Saipan. + + Changes affecting time zone abbreviations + + Correct the 1992-2010 DST abbreviation in Volgograd from "MSK" to "MSD". + (Thanks to Hank W.) + + Changes affecting code + + Fix integer overflow bug in reference 'mktime' implementation. + (Problem reported by Jörg Richter.) + + Allow -Dtime_tz=time_t compilations, and allow -Dtime_tz=... libraries + to be used in the same executable as standard-library time_t functions. + (Problems reported by Bradley White.) + + Changes affecting commentary + + Cite the recent Mexican decree changing Quintana Roo's time zone. + (Thanks to Carlos Raúl Perasso.) + + Likewise for the recent Chilean decree. (Thanks to Eduardo Romero Urra.) + + Update info about Mars time. + + +Release 2015a - 2015-01-29 22:35:20 -0800 + + Changes affecting future time stamps + + The Mexican state of Quintana Roo, represented by America/Cancun, + will shift from Central Time with DST to Eastern Time without DST + on 2015-02-01 at 02:00. (Thanks to Steffen Thorsen and Gwillim Law.) + + Chile will not change clocks in April or thereafter; its new standard time + will be its old daylight saving time. This affects America/Santiago, + Pacific/Easter, and Antarctica/Palmer. (Thanks to Juan Correa.) + + New leap second 2015-06-30 23:59:60 UTC as per IERS Bulletin C 49. + (Thanks to Tim Parenti.) + + Changes affecting past time stamps + + Iceland observed DST in 1919 and 1921, and its 1939 fallback + transition was Oct. 29, not Nov. 29. Remove incorrect data from + Shanks about time in Iceland between 1837 and 1908. + + Some more zones have been turned into links, when they differed + from existing zones only for older time stamps. As usual, + these changes affect UTC offsets in pre-1970 time stamps only. + Their old contents have been moved to the 'backzone' file. + The affected zones are: Asia/Aden, Asia/Bahrain, Asia/Kuwait, + and Asia/Muscat. + + Changes affecting code + + tzalloc now scrubs time zone abbreviations compatibly with the way + that tzset always has, by replacing invalid bytes with '_' and by + shortening too-long abbreviations. + + tzselect ports to POSIX awk implementations, no longer mishandles + POSIX TZ settings when GNU awk is used, and reports POSIX TZ + settings to the user. (Thanks to Stefan Kuhn.) + + Changes affecting build procedure + + 'make check' now checks for links to links in the data. + One such link (for Africa/Asmera) has been fixed. + (Thanks to Stephen Colebourne for pointing out the problem.) + + Changes affecting commentary + + The leapseconds file commentary now mentions the expiration date. + (Problem reported by Martin Burnicki.) + + Update Mexican Library of Congress URL. + + +Release 2014j - 2014-11-10 17:37:11 -0800 + + Changes affecting current and future time stamps + + Turks & Caicos' switch from US eastern time to UT -04 year-round + did not occur on 2014-11-02 at 02:00. It's currently scheduled + for 2015-11-01 at 02:00. (Thanks to Chris Walton.) + + Changes affecting past time stamps + + Many pre-1989 time stamps have been corrected for Asia/Seoul and + Asia/Pyongyang, based on sources for the Korean-language Wikipedia + entry for time in Korea. (Thanks to Sanghyuk Jung.) Also, no + longer guess that Pyongyang mimicked Seoul time after World War II, + as this is politically implausible. + + Some more zones have been turned into links, when they differed + from existing zones only for older time stamps. As usual, + these changes affect UTC offsets in pre-1970 time stamps only. + Their old contents have been moved to the 'backzone' file. + The affected zones are: Africa/Addis_Ababa, Africa/Asmara, + Africa/Dar_es_Salaam, Africa/Djibouti, Africa/Kampala, + Africa/Mogadishu, Indian/Antananarivo, Indian/Comoro, and + Indian/Mayotte. + + Changes affecting commentary + + The commentary is less enthusiastic about Shanks as a source, + and is more careful to distinguish UT from UTC. + + +Release 2014i - 2014-10-21 22:04:57 -0700 + + Changes affecting future time stamps + + Pacific/Fiji will observe DST from 2014-11-02 02:00 to 2015-01-18 03:00. + (Thanks to Ken Rylander for the heads-up.) Guess that future + years will use a similar pattern. + + A new Zone Pacific/Bougainville, for the part of Papua New Guinea + that plans to switch from UT +10 to +11 on 2014-12-28 at 02:00. + (Thanks to Kiley Walbom for the heads-up.) + + Changes affecting time zone abbreviations + + Since Belarus is not changing its clocks even though Moscow is, + the time zone abbreviation in Europe/Minsk is changing from FET + to its more-traditional value MSK on 2014-10-26 at 01:00. + (Thanks to Alexander Bokovoy for the heads-up about Belarus.) + + The new abbreviation IDT stands for the pre-1976 use of UT +08 in + Indochina, to distinguish it better from ICT (+07). + + Changes affecting past time stamps + + Many time stamps have been corrected for Asia/Ho_Chi_Minh before 1976 + (thanks to Trần Ngọc Quân for an indirect pointer to Trần Tiến Bình's + authoritative book). Asia/Ho_Chi_Minh has been added to + zone1970.tab, to give tzselect users in Vietnam two choices, + since north and south Vietnam disagreed after our 1970 cutoff. + + Asia/Phnom_Penh and Asia/Vientiane have been turned into links, as + they differed from existing zones only for older time stamps. As + usual, these changes affect pre-1970 time stamps only. Their old + contents have been moved to the 'backzone' file. + + Changes affecting code + + The time-related library functions now set errno on failure, and + some crashes in the new tzalloc-related library functions have + been fixed. (Thanks to Christos Zoulas for reporting most of + these problems and for suggesting fixes.) + + If USG_COMPAT is defined and the requested time stamp is standard time, + the tz library's localtime and mktime functions now set the extern + variable timezone to a value appropriate for that time stamp; and + similarly for ALTZONE, daylight saving time, and the altzone variable. + This change is a companion to the tzname change in 2014h, and is + designed to make timezone and altzone more compatible with tzname. + + The tz library's functions now set errno to EOVERFLOW if they fail + because the result cannot be represented. ctime and ctime_r now + return NULL and set errno when a time stamp is out of range, rather + than having undefined behavior. + + Some bugs associated with the new 2014g functions have been fixed. + This includes a bug that largely incapacitated the new functions + time2posix_z and posix2time_z. (Thanks to Christos Zoulas.) + It also includes some uses of uninitialized variables after tzalloc. + The new code uses the standard type 'ssize_t', which the Makefile + now gives porting advice about. + + Changes affecting commentary + + Updated URLs for NRC Canada (thanks to Matt Johnson and Brian Inglis). + + +Release 2014h - 2014-09-25 18:59:03 -0700 + + Changes affecting past time stamps + + America/Jamaica's 1974 spring-forward transition was Jan. 6, not Apr. 28. + + Shanks says Asia/Novokuznetsk switched from LMT (not "NMT") on 1924-05-01, + not 1920-01-06. The old entry was based on a misinterpretation of Shanks. + + Some more zones have been turned into links, when they differed + from existing zones only for older time stamps. As usual, + these changes affect UTC offsets in pre-1970 time stamps only. + Their old contents have been moved to the 'backzone' file. + The affected zones are: Africa/Blantyre, Africa/Bujumbura, + Africa/Gaborone, Africa/Harare, Africa/Kigali, Africa/Lubumbashi, + Africa/Lusaka, Africa/Maseru, and Africa/Mbabane. + + Changes affecting code + + zdump -V and -v now output gmtoff= values on all platforms, + not merely on platforms defining TM_GMTOFF. + + The tz library's localtime and mktime functions now set tzname to a value + appropriate for the requested time stamp, and zdump now uses this + on platforms not defining TM_ZONE, fixing a 2014g regression. + (Thanks to Tim Parenti for reporting the problem.) + + The tz library no longer sets tzname if localtime or mktime fails. + + zdump -c no longer mishandles transitions near year boundaries. + (Thanks to Tim Parenti for reporting the problem.) + + An access to uninitialized data has been fixed. + (Thanks to Jörg Richter for reporting the problem.) + + When THREAD_SAFE is defined, the code ports to the C11 memory model. + A memory leak has been fixed if ALL_STATE and THREAD_SAFE are defined + and two threads race to initialize data used by gmtime-like functions. + (Thanks to Andy Heninger for reporting the problems.) + + Changes affecting build procedure + + 'make check' now checks better for properly-sorted data. + + Changes affecting documentation and commentary + + zdump's gmtoff=N output is now documented, and its isdst=D output + is now documented to possibly output D values other than 0 or 1. + + zdump -c's treatment of years is now documented to use the + Gregorian calendar and Universal Time without leap seconds, + and its behavior at cutoff boundaries is now documented better. + (Thanks to Arthur David Olson and Tim Parenti for reporting the problems.) + + Programs are now documented to use the proleptic Gregorian calendar. + (Thanks to Alan Barrett for the suggestion.) + + Fractional-second GMT offsets have been documented for civil time + in 19th-century Chennai, Jakarta, and New York. + + +Release 2014g - 2014-08-28 12:31:23 -0700 + + Changes affecting future time stamps + + Turks & Caicos is switching from US eastern time to UT -04 + year-round, modeled as a switch on 2014-11-02 at 02:00. + [As noted in 2014j, this switch was later delayed.] + + Changes affecting past time stamps + + Time in Russia or the USSR before 1926 or so has been corrected by + a few seconds in the following zones: Asia/Irkutsk, + Asia/Krasnoyarsk, Asia/Omsk, Asia/Samarkand, Asia/Tbilisi, + Asia/Vladivostok, Asia/Yakutsk, Europe/Riga, Europe/Samara. For + Asia/Yekaterinburg the correction is a few minutes. (Thanks to + Vladimir Karpinsky.) + + The Portuguese decree of 1911-05-26 took effect on 1912-01-01. + This affects 1911 time stamps in Africa/Bissau, Africa/Luanda, + Atlantic/Azores, and Atlantic/Madeira. Also, Lisbon's pre-1912 + GMT offset was -0:36:45 (rounded from -0:36:44.68), not -0:36:32. + (Thanks to Stephen Colebourne for pointing to the decree.) + + Asia/Dhaka ended DST on 2009-12-31 at 24:00, not 23:59. + + A new file 'backzone' contains data which may appeal to + connoisseurs of old time stamps, although it is out of scope for + the tz database, is often poorly sourced, and contains some data + that is known to be incorrect. The new file is not recommended + for ordinary use and its entries are not installed by default. + (Thanks to Lester Caine for the high-quality Jersey, Guernsey, and + Isle of Man entries.) + + Some more zones have been turned into links, when they differed + from existing zones only for older time stamps. As usual, + these changes affect UTC offsets in pre-1970 time stamps only. + Their old contents have been moved to the 'backzone' file. + The affected zones are: Africa/Bangui, Africa/Brazzaville, + Africa/Douala, Africa/Kinshasa, Africa/Libreville, Africa/Luanda, + Africa/Malabo, Africa/Niamey, and Africa/Porto-Novo. + + Changes affecting code + + Unless NETBSD_INSPIRED is defined to 0, the tz library now + supplies functions for creating and using objects that represent + time zones. The new functions are tzalloc, tzfree, localtime_rz, + mktime_z, and (if STD_INSPIRED is also defined) posix2time_z and + time2posix_z. They are intended for performance: for example, + localtime_rz (unlike localtime_r) is trivially thread-safe without + locking. (Thanks to Christos Zoulas for proposing NetBSD-inspired + functions, and to Alan Barrett and Jonathan Lennox for helping to + debug the change.) + + zdump now builds with the tz library unless USE_LTZ is defined to 0, + This lets zdump use tz features even if the system library lacks them. + To build zdump with the system library, use 'make CFLAGS=-DUSE_LTZ=0 + TZDOBJS=zdump.o CHECK_TIME_T_ALTERNATIVES='. + + zdump now uses localtime_rz if available, as it's significantly faster, + and it can help zdump better diagnose invalid time zone names. + Define HAVE_LOCALTIME_RZ to 0 to suppress this. HAVE_LOCALTIME_RZ + defaults to 1 if NETBSD_INSPIRED && USE_LTZ. When localtime_rz is + not available, zdump now uses localtime_r and tzset if available, + as this is a bit cleaner and faster than plain localtime. Compile + with -DHAVE_LOCALTIME_R=0 and/or -DHAVE_TZSET=0 if your system + lacks these two functions. + + If THREAD_SAFE is defined to 1, the tz library is now thread-safe. + Although not needed for tz's own applications, which are single-threaded, + this supports POSIX better if the tz library is used in multithreaded apps. + + Some crashes have been fixed when zdump or the tz library is given + invalid or outlandish input. + + The tz library no longer mishandles leap seconds on platforms with + unsigned time_t in time zones that lack ordinary transitions after 1970. + + The tz code now attempts to infer TM_GMTOFF and TM_ZONE if not + already defined, to make it easier to configure on common platforms. + Define NO_TM_GMTOFF and NO_TM_ZONE to suppress this. + + Unless the new macro UNINIT_TRAP is defined to 1, the tz code now + assumes that reading uninitialized memory yields garbage values + but does not cause other problems such as traps. + + If TM_GMTOFF is defined and UNINIT_TRAP is 0, mktime is now + more likely to guess right for ambiguous time stamps near + transitions where tm_isdst does not change. + + If HAVE_STRFTIME_L is defined to 1, the tz library now defines + strftime_l for compatibility with recent versions of POSIX. + Only the C locale is supported, though. HAVE_STRFTIME_L defaults + to 1 on recent POSIX versions, and to 0 otherwise. + + tzselect -c now uses a hybrid distance measure that works better + in Africa. (Thanks to Alan Barrett for noting the problem.) + + The C source code now ports to NetBSD when GCC_DEBUG_FLAGS is used, + or when time_tz is defined. + + When HAVE_UTMPX_H is set the 'date' command now builds on systems + whose file does not define WTMPX_FILE, and when setting + the date it updates the wtmpx file if _PATH_WTMPX is defined. + This affects GNU/Linux and similar systems. + + For easier maintenance later, some C code has been simplified, + some lint has been removed, and the code has been tweaked so that + plain 'make' is more likely to work. + + The C type 'bool' is now used for boolean values, instead of 'int'. + + The long-obsolete LOCALE_HOME code has been removed. + + The long-obsolete 'gtime' function has been removed. + + Changes affecting build procedure + + 'zdump' no longer links in ialloc.o, as it's not needed. + + 'make check_time_t_alternatives' no longer assumes GNU diff. + + Changes affecting distribution tarballs + + The files checktab.awk and zoneinfo2tdf.pl are now distributed in + the tzdata tarball instead of the tzcode tarball, since they help + maintain the data. The NEWS and Theory files are now also + distributed in the tzdata tarball, as they're relevant for data. + (Thanks to Alan Barrett for pointing this out.) Also, the + leapseconds.awk file is no longer distributed in the tzcode + tarball, since it belongs in the tzdata tarball (where 2014f + inadvertently also distributed it). + + Changes affecting documentation and commentary + + A new file CONTRIBUTING is distributed. (Thanks to Tim Parenti for + suggesting a CONTRIBUTING file, and to Tony Finch and Walter Harms + for debugging it.) + + The man pages have been updated to use function prototypes, + to document thread-safe variants like localtime_r, and to document + the NetBSD-inspired functions tzalloc, tzfree, localtime_rz, and + mktime_z. + + The fields in Link lines have been renamed to be more descriptive + and more like the parameters of 'ln'. LINK-FROM has become TARGET, + and LINK-TO has become LINK-NAME. + + tz-link.htm mentions the IETF's tzdist working group; Windows + Runtime etc. (thanks to Matt Johnson); and HP-UX's tztab. + + Some broken URLs have been fixed in the commentary. (Thanks to + Lester Caine.) + + Commentary about Philippines DST has been updated, and commentary + on pre-1970 time in India has been added. + + +Release 2014f - 2014-08-05 17:42:36 -0700 + + Changes affecting future time stamps + + Russia will subtract an hour from most of its time zones on 2014-10-26 + at 02:00 local time. (Thanks to Alexander Krivenyshev.) + There are a few exceptions: Magadan Oblast (Asia/Magadan) and Zabaykalsky + Krai are subtracting two hours; conversely, Chukotka Autonomous Okrug + (Asia/Anadyr), Kamchatka Krai (Asia/Kamchatka), Kemerovo Oblast + (Asia/Novokuznetsk), and the Samara Oblast and the Udmurt Republic + (Europe/Samara) are not changing their clocks. The changed zones are + Europe/Kaliningrad, Europe/Moscow, Europe/Simferopol, Europe/Volgograd, + Asia/Yekaterinburg, Asia/Omsk, Asia/Novosibirsk, Asia/Krasnoyarsk, + Asia/Irkutsk, Asia/Yakutsk, Asia/Vladivostok, Asia/Khandyga, + Asia/Sakhalin, and Asia/Ust-Nera; Asia/Magadan will have two hours + subtracted; and Asia/Novokuznetsk's time zone abbreviation is affected, + but not its UTC offset. Two zones are added: Asia/Chita (split + from Asia/Yakutsk, and also with two hours subtracted) and + Asia/Srednekolymsk (split from Asia/Magadan, but with only one hour + subtracted). (Thanks to Tim Parenti for much of the above.) + + Changes affecting time zone abbreviations + + Australian eastern time zone abbreviations are now AEST/AEDT not EST, + and similarly for the other Australian zones. That is, for eastern + standard and daylight saving time the abbreviations are AEST and AEDT + instead of the former EST for both; similarly, ACST/ACDT, ACWST/ACWDT, + and AWST/AWDT are now used instead of the former CST, CWST, and WST. + This change does not affect UTC offsets, only time zone abbreviations. + (Thanks to Rich Tibbett and many others.) + + Asia/Novokuznetsk shifts from NOVT to KRAT (remaining on UT +07) + effective 2014-10-26 at 02:00 local time. + + The time zone abbreviation for Xinjiang Time (observed in Ürümqi) + has been changed from URUT to XJT. (Thanks to Luther Ma.) + + Prefer MSK/MSD for Moscow time in Russia, even in other cities. + Similarly, prefer EET/EEST for eastern European time in Russia. + + Change time zone abbreviations in (western) Samoa to use "ST" and + "DT" suffixes, as this is more likely to match common practice. + Prefix "W" to (western) Samoa time when its standard-time offset + disagrees with that of American Samoa. + + America/Metlakatla now uses PST, not MeST, to abbreviate its time zone. + + Time zone abbreviations have been updated for Japan's two time + zones used 1896-1937. JWST now stands for Western Standard + Time, and JCST for Central Standard Time (formerly this was CJT). + These abbreviations are now used for time in Korea, Taiwan, + and Sakhalin while controlled by Japan. + + Changes affecting past time stamps + + China's five zones have been simplified to two, since the post-1970 + differences in the other three seem to have been imaginary. The + zones Asia/Harbin, Asia/Chongqing, and Asia/Kashgar have been + removed; backwards-compatibility links still work, albeit with + different behaviors for time stamps before May 1980. Asia/Urumqi's + 1980 transition to UT +08 has been removed, so that it is now at + +06 and not +08. (Thanks to Luther Ma and to Alois Treindl; + Treindl sent helpful translations of two papers by Guo Qingsheng.) + + Some zones have been turned into links, when they differed from existing + zones only for older UTC offsets where data entries were likely invented. + These changes affect UTC offsets in pre-1970 time stamps only. This is + similar to the change in release 2013e, except this time for western + Africa. The affected zones are: Africa/Bamako, Africa/Banjul, + Africa/Conakry, Africa/Dakar, Africa/Freetown, Africa/Lome, + Africa/Nouakchott, Africa/Ouagadougou, Africa/Sao_Tome, and + Atlantic/St_Helena. This also affects the backwards-compatibility + link Africa/Timbuktu. (Thanks to Alan Barrett, Stephen Colebourne, + Tim Parenti, and David Patte for reporting problems in earlier + versions of this change.) + + Asia/Shanghai's pre-standard-time UT offset has been changed from + 8:05:57 to 8:05:43, the location of Xujiahui Observatory. Its + transition to standard time has been changed from 1928 to 1901. + + Asia/Taipei switched to JWST on 1896-01-01, then to JST on 1937-10-01, + then to CST on 1945-09-21 at 01:00, and did not observe DST in 1945. + In 1946 it observed DST from 05-15 through 09-30; in 1947 + from 04-15 through 10-31; and in 1979 from 07-01 through 09-30. + (Thanks to Yu-Cheng Chuang.) + + Asia/Riyadh's transition to standard time is now 1947-03-14, not 1950. + + Europe/Helsinki's 1942 fall-back transition was 10-04 at 01:00, not + 10-03 at 00:00. (Thanks to Konstantin Hyppönen.) + + Pacific/Pago_Pago has been changed from UT -11:30 to -11 for the + period from 1911 to 1950. + + Pacific/Chatham has been changed to New Zealand standard time plus + 45 minutes for the period before 1957, reflecting a 1956 remark in + the New Zealand parliament. + + Europe/Budapest has several pre-1946 corrections: in 1918 the transition + out of DST was on 09-16, not 09-29; in 1919 it was on 11-24, not 09-15; in + 1945 it was on 11-01, not 11-03; in 1941 the transition to DST was 04-08 + not 04-06 at 02:00; and there was no DST in 1920. + + Africa/Accra is now assumed to have observed DST from 1920 through 1935. + + Time in Russia before 1927 or so has been corrected by a few seconds in + the following zones: Europe/Moscow, Asia/Irkutsk, Asia/Tbilisi, + Asia/Tashkent, Asia/Vladivostok, Asia/Yekaterinburg, Europe/Helsinki, and + Europe/Riga. Also, Moscow's location has been changed to its Kilometer 0 + point. (Thanks to Vladimir Karpinsky for the Moscow changes.) + + Changes affecting data format + + A new file 'zone1970.tab' supersedes 'zone.tab' in the installed data. + The new file's extended format allows multiple country codes per zone. + The older file is still installed but is deprecated; its format is + not changing and it will still be distributed for a while, but new + applications should use the new file. + + The new file format simplifies maintenance of obscure locations. + To test this, it adds coverage for the Crozet Islands and the + Scattered Islands. (Thanks to Tobias Conradi and Antoine Leca.) + + The file 'iso3166.tab' is planned to switch from ASCII to UTF-8. + It is still ASCII now, but commentary about the switch has been added. + The new file 'zone1970.tab' already uses UTF-8. + + Changes affecting code + + 'localtime', 'mktime', etc. now use much less stack space if ALL_STATE + is defined. (Thanks to Elliott Hughes for reporting the problem.) + + 'zic' no longer mishandles input when ignoring case in locales that + are not compatible with English, e.g., unibyte Turkish locales when + compiled with HAVE_GETTEXT. + + Error diagnostics of 'zic' and 'yearistype' have been reworded so that + they no longer use ASCII '-' as if it were a dash. + + 'zic' now rejects output file names that contain '.' or '..' components. + (Thanks to Tim Parenti for reporting the problem.) + + 'zic -v' now warns about output file names that do not follow + POSIX rules, or that contain a digit or '.'. (Thanks to Arthur + David Olson for starting the ball rolling on this.) + + Some lint has been removed when using GCC_DEBUG_FLAGS with GCC 4.9.0. + + Changes affecting build procedure + + 'zic' no longer links in localtime.o and asctime.o, as they're not needed. + (Thanks to John Cochran.) + + Changes affecting documentation and commentary + + The 'Theory' file documents legacy names, the longstanding + exceptions to the POSIX-inspired file name rules. + + The 'zic' documentation clarifies the role of time types when + interpreting dates. (Thanks to Arthur David Olson.) + + Documentation and commentary now prefer UTF-8 to US-ASCII, + allowing the use of proper accents in foreign words and names. + Code and data have not changed because of this. (Thanks to + Garrett Wollman, Ian Abbott, and Guy Harris for helping to debug + this.) + + Non-HTML documentation and commentary now use plain-text URLs instead of + HTML insertions, and are more consistent about bracketing URLs when they + are not already surrounded by white space. (Thanks to suggestions by + Steffen Nurpmeso.) + + There is new commentary about Xujiahui Observatory, the five time-zone + project in China from 1918 to 1949, timekeeping in Japanese-occupied + Shanghai, and Tibet Time in the 1950s. The sharp-eyed can spot the + warlord Jin Shuren in the data. + + Commentary about the coverage of each Russian zone has been standardized. + (Thanks to Tim Parenti). + + There is new commentary about contemporary timekeeping in Ethiopia. + + Obsolete comments about a 2007 proposal for DST in Kuwait has been removed. + + There is new commentary about time in Poland in 1919. + + Proper credit has been given to DST inventor George Vernon Hudson. + + Commentary about time in Metlakatla, AK and Resolute, NU has been + improved, with a new source for the former. + + In zone.tab, Pacific/Easter no longer mentions Salas y Gómez, as it + is uninhabited. + + Commentary about permanent Antarctic bases has been updated. + + Several typos have been corrected. (Thanks to Tim Parenti for + contributing some of these fixes.) + + tz-link.htm now mentions the JavaScript libraries Moment Timezone, + TimezoneJS.Date, Walltime-js, and Timezone. (Thanks to a heads-up + from Matt Johnson.) Also, it mentions the Go 'latlong' package. + (Thanks to a heads-up from Dirkjan Ochtman.) + + The files usno1988, usno1989, usno1989a, usno1995, usno1997, and usno1998 + have been removed. These obsolescent US Naval Observatory entries were no + longer helpful for maintenance. (Thanks to Tim Parenti for the suggestion.) + + +Release 2014e - 2014-06-12 21:53:52 -0700 + + Changes affecting near-future time stamps + + Egypt's 2014 Ramadan-based transitions are June 26 and July 31 at 24:00. + (Thanks to Imed Chihi.) Guess that from 2015 on Egypt will temporarily + switch to standard time at 24:00 the last Thursday before Ramadan, and + back to DST at 00:00 the first Friday after Ramadan. + + Similarly, Morocco's are June 28 at 03:00 and August 2 at 02:00. (Thanks + to Milamber Space Network.) Guess that from 2015 on Morocco will + temporarily switch to standard time at 03:00 the last Saturday before + Ramadan, and back to DST at 02:00 the first Saturday after Ramadan. + + Changes affecting past time stamps + + The abbreviation "MSM" (Moscow Midsummer Time) is now used instead of + "MSD" for Moscow's double daylight time in summer 1921. Also, a typo + "VLASST" has been repaired to be "VLAST" for Vladivostok summer time + in 1991. (Thanks to Hank W. for reporting the problems.) + + Changes affecting commentary + + tz-link.htm now cites RFC 7265 for jCal, mentions PTP and the + draft CalDAV extension, updates URLs for TSP, TZInfo, IATA, and + removes stale pointers to World Time Explorer and WORLDTIME. + + +Release 2014d - 2014-05-27 21:34:40 -0700 + + Changes affecting code + + zic no longer generates files containing time stamps before the Big Bang. + This works around GNOME bug 730332 + . + (Thanks to Leonardo Chiquitto for reporting the bug, and to + Arthur David Olson and James Cloos for suggesting improvements to the fix.) + + Changes affecting documentation + + tz-link.htm now mentions GNOME. + + +Release 2014c - 2014-05-13 07:44:13 -0700 + + Changes affecting near-future time stamps + + Egypt observes DST starting 2014-05-15 at 24:00. + (Thanks to Ahmad El-Dardiry and Gunther Vermier.) + Details have not been announced, except that DST will not be observed + during Ramadan. Guess that DST will stop during the same Ramadan dates as + Morocco, and that Egypt's future spring and fall transitions will be the + same as 2010 when it last observed DST, namely April's last Friday at + 00:00 to September's last Thursday at 23:00 standard time. Also, guess + that Ramadan transitions will be at 00:00 standard time. + + Changes affecting code + + zic now generates transitions for minimum time values, eliminating guesswork + when handling low-valued time stamps. (Thanks to Arthur David Olson.) + + Port to Cygwin sans glibc. (Thanks to Arthur David Olson.) + + Changes affecting commentary and documentation + + Remove now-confusing comment about Jordan. (Thanks to Oleksii Nochovnyi.) + + +Release 2014b - 2014-03-24 21:28:50 -0700 + + Changes affecting near-future time stamps + + Crimea switches to Moscow time on 2014-03-30 at 02:00 local time. + (Thanks to Alexander Krivenyshev.) Move its zone.tab entry from UA to RU. + + New entry for Troll station, Antarctica. (Thanks to Paul-Inge Flakstad and + Bengt-Inge Larsson.) This is currently an approximation; a better version + will require the zic and localtime fixes mentioned below, and the plan is + to wait for a while until at least the zic fixes propagate. + + Changes affecting code + + 'zic' and 'localtime' no longer reject locations needing four transitions + per year for the foreseeable future. (Thanks to Andrew Main (Zefram).) + Also, 'zic' avoids some unlikely failures due to integer overflow. + + Changes affecting build procedure + + 'make check' now detects Rule lines defined but never used. + The NZAQ rules, an instance of this problem, have been removed. + + Changes affecting commentary and documentation + + Fix Tuesday/Thursday typo in description of time in Israel. + (Thanks to Bert Katz via Pavel Kharitonov and Mike Frysinger.) + + Microsoft Windows 8.1 doesn't support tz database names. (Thanks + to Donald MacQueen.) Instead, the Microsoft Windows Store app + library supports them. + + Add comments about Johnston Island time in the 1960s. + (Thanks to Lyle McElhaney.) + + Morocco's 2014 DST start will be as predicted. + (Thanks to Sebastien Willemijns.) + + +Release 2014a - 2014-03-07 23:30:29 -0800 + + Changes affecting near-future time stamps + + Turkey begins DST on 2014-03-31, not 03-30. (Thanks to Faruk Pasin for + the heads-up, and to Tim Parenti for simplifying the update.) + + Changes affecting past time stamps + + Fiji ended DST on 2014-01-19 at 02:00, not the previously-scheduled 03:00. + (Thanks to Steffen Thorsen.) + + Ukraine switched from Moscow to Eastern European time on 1990-07-01 + (not 1992-01-01), and observed DST during the entire next winter. + (Thanks to Vladimir in Moscow via Alois Treindl.) + + In 1988 Israel observed DST from 04-10 to 09-04, not 04-09 to 09-03. + (Thanks to Avigdor Finkelstein.) + + Changes affecting code + + A uninitialized-storage bug in 'localtime' has been fixed. + (Thanks to Logan Chien.) + + Changes affecting the build procedure + + The settings for 'make check_web' now default to Ubuntu 13.10. + + Changes affecting commentary and documentation + + The boundary of the US Pacific time zone is given more accurately. + (Thanks to Alan Mintz.) + + Chile's 2014 DST will be as predicted. (Thanks to José Miguel Garrido.) + + Paraguay's 2014 DST will be as predicted. (Thanks to Carlos Raúl Perasso.) + + Better descriptions of countries with same time zone history as + Trinidad and Tobago since 1970. (Thanks to Alan Barrett for suggestion.) + + Several changes affect tz-link.htm, the main web page. + + Mention Time.is (thanks to Even Scharning) and WX-now (thanks to + David Braverman). + + Mention xCal (Internet RFC 6321) and jCal. + + Microsoft has some support for tz database names. + + CLDR data formats include both XML and JSON. + + Mention Maggiolo's map of solar vs standard time. + (Thanks to Arthur David Olson.) + + Mention TZ4Net. (Thanks to Matt Johnson.) + + Mention the timezone-olson Haskell package. + + Mention zeitverschiebung.net. (Thanks to Martin Jäger.) + + Remove moribund links to daylight-savings-time.info and to + Simple Timer + Clocks. + + Update two links. (Thanks to Oscar van Vlijmen.) + + Fix some formatting glitches, e.g., remove random newlines from + abbr elements' title attributes. + + +Release 2013i - 2013-12-17 07:25:23 -0800 + + Changes affecting near-future time stamps: + + Jordan switches back to standard time at 00:00 on December 20, 2013. + The 2006-2011 transition schedule is planned to resume in 2014. + (Thanks to Steffen Thorsen.) + + Changes affecting past time stamps: + + In 2004, Cuba began DST on March 28, not April 4. + (Thanks to Steffen Thorsen.) + + Changes affecting code + + The compile-time flag NOSOLAR has been removed, as nowadays the + benefit of slightly shrinking runtime table size is outweighed by the + cost of disallowing potential future updates that exceed old limits. + + Changes affecting documentation and commentary + + The files solar87, solar88, and solar89 are no longer distributed. + They were a negative experiment - that is, a demonstration that + tz data can represent solar time only with some difficulty and error. + Their presence in the distribution caused confusion, as Riyadh + civil time was generally not solar time in those years. + + tz-link.htm now mentions Noda Time. (Thanks to Matt Johnson.) + + +Release 2013h - 2013-10-25 15:32:32 -0700 + + Changes affecting current and future time stamps: + + Libya has switched its UT offset back to +02 without DST, instead + of +01 with DST. (Thanks to Even Scharning.) + + Western Sahara (Africa/El_Aaiun) uses Morocco's DST rules. + (Thanks to Gwillim Law.) + + Changes affecting future time stamps: + + Acre and (we guess) western Amazonas will switch from UT -04 to -05 + on 2013-11-10. This affects America/Rio_Branco and America/Eirunepe. + (Thanks to Steffen Thorsen.) + + Add entries for DST transitions in Morocco in the year 2038. + This avoids some year-2038 glitches introduced in 2013g. + (Thanks to Yoshito Umaoka for reporting the problem.) + + Changes affecting API + + The 'tzselect' command no longer requires the 'select' command, + and should now work with /bin/sh on more platforms. It also works + around a bug in BusyBox awk before version 1.21.0. (Thanks to + Patrick 'P. J.' McDermott and Alan Barrett.) + + Changes affecting code + + Fix localtime overflow bugs with 32-bit unsigned time_t. + + zdump no longer assumes sscanf returns maximal values on overflow. + + Changes affecting the build procedure + + The builder can specify which programs to use, if any, instead of + 'ar' and 'ranlib', and libtz.a is now built locally before being + installed. (Thanks to Michael Forney.) + + A dependency typo in the 'zdump' rule has been fixed. + (Thanks to Andrew Paprocki.) + + The Makefile has been simplified by assuming that 'mkdir -p' and 'cp -f' + work as specified by POSIX.2-1992 or later; this is portable nowadays. + + 'make clean' no longer removes 'leapseconds', since it's + host-independent and is part of the distribution. + + The unused makefile macros TZCSRCS, TZDSRCS, DATESRCS have been removed. + + Changes affecting documentation and commentary + + tz-link.htm now mentions TC TIMEZONE's draft time zone service protocol + (thanks to Mike Douglass) and TimezoneJS.Date (thanks to Jim Fehrle). + + Update URLs in tz-link page. Add URLs for Microsoft Windows, since + 8.1 introduces tz support. Remove URLs for Tru64 and UnixWare (no + longer maintained) and for old advisories. SOFA now does C. + +Release 2013g - 2013-09-30 21:08:26 -0700 + + Changes affecting current and near-future time stamps + + Morocco now observes DST from the last Sunday in March to the last + Sunday in October, not April to September respectively. (Thanks + to Steffen Thorsen.) + + Changes affecting 'zic' + + 'zic' now runs on platforms that lack both hard links and symlinks. + (Thanks to Theo Veenker for reporting the problem, for MinGW.) + Also, fix some bugs on platforms that lack hard links but have symlinks. + + 'zic -v' again warns that Asia/Tehran has no POSIX environment variable + to predict the far future, fixing a bug introduced in 2013e. + + Changes affecting the build procedure + + The 'leapseconds' file is again put into the tzdata tarball. + Also, 'leapseconds.awk', so tzdata is self-contained. (Thanks to + Matt Burgess and Ian Abbott.) The timestamps of these and other + dependent files in tarballs are adjusted more consistently. + + Changes affecting documentation and commentary + + The README file is now part of the data tarball as well as the code. + It now states that files are public domain unless otherwise specified. + (Thanks to Andrew Main (Zefram) for asking for clarifications.) + Its details about the 1989 release moved to a place of honor near + the end of NEWS. + + +Release 2013f - 2013-09-24 23:37:36 -0700 + + Changes affecting near-future time stamps + + Tocantins will very likely not observe DST starting this spring. + (Thanks to Steffen Thorsen.) + + Jordan will likely stay at UT +03 indefinitely, and will not fall + back this fall. + + Palestine will fall back at 00:00, not 01:00. (Thanks to Steffen Thorsen.) + + Changes affecting API + + The types of the global variables 'timezone' and 'altzone' (if present) + have been changed back to 'long'. This is required for 'timezone' + by POSIX, and for 'altzone' by common practice, e.g., Solaris 11. + These variables were originally 'long' in the tz code, but were + mistakenly changed to 'time_t' in 1987; nobody reported the + incompatibility until now. The difference matters on x32, where + 'long' is 32 bits and 'time_t' is 64. (Thanks to Elliott Hughes.) + + Changes affecting the build procedure + + Avoid long strings in leapseconds.awk to work around a mawk bug. + (Thanks to Cyril Baurand.) + + Changes affecting documentation and commentary + + New file 'NEWS' that contains release notes like this one. + + Paraguay's law does not specify DST transition time; 00:00 is customary. + (Thanks to Waldemar Villamayor-Venialbo.) + + Minor capitalization fixes. + + Changes affecting version-control only + + The experimental GitHub repository now contains annotated and + signed tags for recent releases, e.g., '2013e' for Release 2013e. + Releases are tagged starting with 2012e; earlier releases were + done differently, and tags would either not have a simple name or + not exactly match what was released. + + 'make set-timestamps' is now simpler and a bit more portable. + + +Release 2013e - 2013-09-19 23:50:04 -0700 + + Changes affecting near-future time stamps + + This year Fiji will start DST on October 27, not October 20. + (Thanks to David Wheeler for the heads-up.) For now, guess that + Fiji will continue to spring forward the Sunday before the fourth + Monday in October. + + Changes affecting current and future time zone abbreviations + + Use WIB/WITA/WIT rather than WIT/CIT/EIT for alphabetic Indonesian + time zone abbreviations since 1932. (Thanks to George Ziegler, + Priyadi Iman Nurcahyo, Zakaria, Jason Grimes, Martin Pitt, and + Benny Lin.) This affects Asia/Dili, Asia/Jakarta, Asia/Jayapura, + Asia/Makassar, and Asia/Pontianak. + + Use ART (UT -03, standard time), rather than WARST (also -03, but + daylight saving time) for San Luis, Argentina since 2009. + + Changes affecting Godthåb time stamps after 2037 if version mismatch + + Allow POSIX-like TZ strings where the transition time's hour can + range from -167 through 167, instead of the POSIX-required 0 + through 24. E.g., TZ='FJT-12FJST,M10.3.1/146,M1.3.4/75' for the + new Fiji rules. This is a more-compact way to represent + far-future time stamps for America/Godthab, America/Santiago, + Antarctica/Palmer, Asia/Gaza, Asia/Hebron, Asia/Jerusalem, + Pacific/Easter, and Pacific/Fiji. Other zones are unaffected by + this change. (Derived from a suggestion by Arthur David Olson.) + + Allow POSIX-like TZ strings where daylight saving time is in + effect all year. E.g., TZ='WART4WARST,J1/0,J365/25' for Western + Argentina Summer Time all year. This supports a more-compact way + to represent the 2013d data for America/Argentina/San_Luis. + Because of the change for San Luis noted above this change does not + affect the current data. (Thanks to Andrew Main (Zefram) for + suggestions that improved this change.) + + Where these two TZ changes take effect, there is a minor extension + to the tz file format in that it allows new values for the + embedded TZ-format string, and the tz file format version number + has therefore been increased from 2 to 3 as a precaution. + Version-2-based client code should continue to work as before for + all time stamps before 2038. Existing version-2-based client code + (tzcode, GNU/Linux, Solaris) has been tested on version-3-format + files, and typically works in practice even for time stamps after + 2037; the only known exception is America/Godthab. + + Changes affecting time stamps before 1970 + + Pacific/Johnston is now a link to Pacific/Honolulu. This corrects + some errors before 1947. + + Some zones have been turned into links, when they differ from existing + zones only in older data entries that were likely invented or that + differ only in LMT or transitions from LMT. These changes affect + only time stamps before 1943. The affected zones are: + Africa/Juba, America/Anguilla, America/Aruba, America/Dominica, + America/Grenada, America/Guadeloupe, America/Marigot, + America/Montserrat, America/St_Barthelemy, America/St_Kitts, + America/St_Lucia, America/St_Thomas, America/St_Vincent, + America/Tortola, and Europe/Vaduz. (Thanks to Alois Treindl for + confirming that the old Europe/Vaduz zone was wrong and the new + link is better for WWII-era times.) + + Change Kingston Mean Time from -5:07:12 to -5:07:11. This affects + America/Cayman, America/Jamaica and America/Grand_Turk time stamps + from 1890 to 1912. + + Change the UT offset of Bern Mean Time from 0:29:44 to 0:29:46. + This affects Europe/Zurich time stamps from 1853 to 1894. (Thanks + to Alois Treindl). + + Change the date of the circa-1850 Zurich transition from 1849-09-12 + to 1853-07-16, overriding Shanks with data from Messerli about + postal and telegraph time in Switzerland. + + Changes affecting time zone abbreviations before 1970 + + For Asia/Jakarta, use BMT (not JMT) for mean time from 1923 to 1932, + as Jakarta was called Batavia back then. + + Changes affecting API + + The 'zic' command now outputs a dummy transition when far-future + data can't be summarized using a TZ string, and uses a 402-year + window rather than a 400-year window. For the current data, this + affects only the Asia/Tehran file. It does not affect any of the + time stamps that this file represents, so zdump outputs the same + information as before. (Thanks to Andrew Main (Zefram).) + + The 'date' command has a new '-r' option, which lets you specify + the integer time to display, a la FreeBSD. + + The 'tzselect' command has two new options '-c' and '-n', which lets you + select a zone based on latitude and longitude. + + The 'zic' command's '-v' option now warns about constructs that + require the new version-3 binary file format. (Thanks to Arthur + David Olson for the suggestion.) + + Support for floating-point time_t has been removed. + It was always dicey, and POSIX no longer requires it. + (Thanks to Eric Blake for suggesting to the POSIX committee to + remove it, and thanks to Alan Barrett, Clive D.W. Feather, Andy + Heninger, Arthur David Olson, and Alois Treindl, for reporting + bugs and elucidating some of the corners of the old floating-point + implementation.) + + The signatures of 'offtime', 'timeoff', and 'gtime' have been + changed back to the old practice of using 'long' to represent UT + offsets. This had been inadvertently and mistakenly changed to + 'int_fast32_t'. (Thanks to Christos Zoulas.) + + The code avoids undefined behavior on integer overflow in some + more places, including gmtime, localtime, mktime and zdump. + + Changes affecting the zdump utility + + zdump now outputs "UT" when referring to Universal Time, not "UTC". + "UTC" does not make sense for time stamps that predate the introduction + of UTC, whereas "UT", a more-generic term, does. (Thanks to Steve Allen + for clarifying UT vs UTC.) + + Data changes affecting behavior of tzselect and similar programs + + Country code BQ is now called the more-common name "Caribbean Netherlands" + rather than the more-official "Bonaire, St Eustatius & Saba". + + Remove from zone.tab the names America/Montreal, America/Shiprock, + and Antarctica/South_Pole, as they are equivalent to existing + same-country-code zones for post-1970 time stamps. The data entries for + these names are unchanged, so the names continue to work as before. + + Changes affecting code internals + + zic -c now runs way faster on 64-bit hosts when given large numbers. + + zic now uses vfprintf to avoid allocating and freeing some memory. + + tzselect now computes the list of continents from the data, + rather than have it hard-coded. + + Minor changes pacify GCC 4.7.3 and GCC 4.8.1. + + Changes affecting the build procedure + + The 'leapseconds' file is now generated automatically from a + new file 'leap-seconds.list', which is a copy of + . + A new source file 'leapseconds.awk' implements this. + The goal is simplification of the future maintenance of 'leapseconds'. + + When building the 'posix' or 'right' subdirectories, if the + subdirectory would be a copy of the default subdirectory, it is + now made a symbolic link if that is supported. This saves about + 2 MB of file system space. + + The links America/Shiprock and Antarctica/South_Pole have been + moved to the 'backward' file. This affects only nondefault builds + that omit 'backward'. + + Changes affecting version-control only + + .gitignore now ignores 'date'. + + Changes affecting documentation and commentary + + Changes to the 'tzfile' man page + + It now mentions that the binary file format may be extended in + future versions by appending data. + + It now refers to the 'zdump' and 'zic' man pages. + + Changes to the 'zic' man page + + It lists conditions that elicit a warning with '-v'. + + It says that the behavior is unspecified when duplicate names + are given, or if the source of one link is the target of another. + + Its examples are updated to match the latest data. + + The definition of white space has been clarified slightly. + (Thanks to Michael Deckers.) + + Changes to the 'Theory' file + + There is a new section about the accuracy of the tz database, + describing the many ways that errors can creep in, and + explaining why so many of the pre-1970 time stamps are wrong or + misleading (thanks to Steve Allen, Lester Caine, and Garrett + Wollman for discussions that contributed to this). + + The 'Theory' file describes LMT better (this follows a + suggestion by Guy Harris). + + It refers to the 2013 edition of POSIX rather than the 2004 edition. + + It's mentioned that excluding 'backward' should not affect the + other data, and it suggests at least one zone.tab name per + inhabited country (thanks to Stephen Colebourne). + + Some longstanding restrictions on names are documented, e.g., + 'America/New_York' precludes 'America/New_York/Bronx'. + + It gives more reasons for the 1970 cutoff. + + It now mentions which time_t variants are supported, such as + signed integer time_t. (Thanks to Paul Goyette for reporting + typos in an experimental version of this change.) + + (Thanks to Philip Newton for correcting typos in these changes.) + + Documentation and commentary is more careful to distinguish UT in + general from UTC in particular. (Thanks to Steve Allen.) + + Add a better source for the Zurich 1894 transition. + (Thanks to Pierre-Yves Berger.) + + Update shapefile citations in tz-link.htm. (Thanks to Guy Harris.) + + +Release 2013d - 2013-07-05 07:38:01 -0700 + + Changes affecting future time stamps: + + Morocco's midsummer transitions this year are July 7 and August 10, + not July 9 and August 8. (Thanks to Andrew Paprocki.) + + Israel now falls back on the last Sunday of October. + (Thanks to Ephraim Silverberg.) + + Changes affecting past time stamps: + + Specify Jerusalem's location more precisely; this changes the pre-1880 + times by 2 s. + + Changing affecting metadata only: + + Fix typos in the entries for country codes BQ and SX. + + Changes affecting code: + + Rework the code to fix a bug with handling Australia/Macquarie on + 32-bit hosts (thanks to Arthur David Olson). + + Port to platforms like NetBSD, where time_t can be wider than long. + + Add support for testing time_t types other than the system's. + Run 'make check_time_t_alternatives' to try this out. + Currently, the tests fail for unsigned time_t; + this should get fixed at some point. + + Changes affecting documentation and commentary: + + Deemphasize the significance of national borders. + + Update the zdump man page. + + Remove obsolete NOID comment (thanks to Denis Excoffier). + + Update several URLs and comments in the web pages. + + Spelling fixes (thanks to Kevin Lyda and Jonathan Leffler). + + Update URL for CLDR Zone->Tzid table (thanks to Yoshito Umaoka). + + +Release 2013c - 2013-04-19 16:17:40 -0700 + + Changes affecting current and future time stamps: + + Palestine observed DST starting March 29, 2013. (Thanks to + Steffen Thorsen.) From 2013 on, Gaza and Hebron both observe DST, + with the predicted rules being the last Thursday in March at 24:00 + to the first Friday on or after September 21 at 01:00. + + Assume that the recent change to Paraguay's DST rules is permanent, + by moving the end of DST to the 4th Sunday in March every year. + (Thanks to Carlos Raúl Perasso.) + + Changes affecting past time stamps: + + Fix some historical data for Palestine to agree with that of + timeanddate.com, as follows: + + The spring 2008 change in Gaza and Hebron was on 00:00 Mar 28, not + 00:00 Apr 1. + + The fall 2009 change in Gaza and Hebron on Sep 4 was at 01:00, not + 02:00. + + The spring 2010 change in Hebron was 00:00 Mar 26, not 00:01 Mar 27. + + The spring 2011 change in Gaza was 00:01 Apr 1, not 12:01 Apr 2. + + The spring 2011 change in Hebron on Apr 1 was at 00:01, not 12:01. + + The fall 2011 change in Hebron on Sep 30 was at 00:00, not 03:00. + + Fix times of habitation for Macquarie to agree with the Tasmania + Parks & Wildlife Service history, which indicates that permanent + habitation was 1899-1919 and 1948 on. + + Changing affecting metadata only: + + Macquarie Island is politically part of Australia, not Antarctica. + (Thanks to Tobias Conradi.) + + Sort Macquarie more-consistently with other parts of Australia. + (Thanks to Tim Parenti.) + + +Release 2013b - 2013-03-10 22:33:40 -0700 + + Changes affecting current and future time stamps: + + Haiti uses US daylight-saving rules this year, and presumably future years. + This changes time stamps starting today. (Thanks to Steffen Thorsen.) + + Paraguay will end DST on March 24 this year. + (Thanks to Steffen Thorsen.) For now, assume it's just this year. + + Morocco does not observe DST during Ramadan; + try to predict Ramadan in Morocco as best we can. + (Thanks to Erik Homoet for the heads-up.) + + Changes affecting commentary: + + Update URLs in tz-link page. Add URLs for webOS, BB10, iOS. + Update URL for Solaris. Mention Internet RFC 6557. + Update Internet RFCs 2445->5545, 2822->5322. + Switch from FTP to HTTP for Internet RFCs. + + +Release 2013a - 2013-02-27 09:20:35 -0800 + + Change affecting binary data format: + + The zone offset at the end of version-2-format zone files is now + allowed to be 24:00, as per POSIX.1-2008. (Thanks to Arthur David Olson.) + + Changes affecting current and future time stamps: + + Chile's 2013 rules, and we guess rules for 2014 and later, will be + the same as 2012, namely Apr Sun>=23 03:00 UTC to Sep Sun>=2 04:00 UTC. + (Thanks to Steffen Thorsen and Robert Elz.) + + New Zones Asia/Khandyga, Asia/Ust-Nera, Europe/Busingen. + (Thanks to Tobias Conradi and Arthur David Olson.) + + Many changes affect historical time stamps before 1940. + These were deduced from: Milne J. Civil time. Geogr J. 1899 + Feb;13(2):173-94 . + + Changes affecting the code: + + Fix zic bug that mishandled Egypt's 2010 changes (this also affected + the data). (Thanks to Arthur David Olson.) + + Fix localtime bug when time_t is unsigned and data files were generated + by a signed time_t system. (Thanks to Doug Bailey for reporting and + to Arthur David Olson for fixing.) + + Allow the email address for bug reports to be set by the packager. + The default is tz@iana.org, as before. (Thanks to Joseph S. Myers.) + + Update HTML checking to be compatible with Ubuntu 12.10. + + Check that files are a safe subset of ASCII. At some point we may + relax this requirement to a safe subset of UTF-8. Without the + check, some non-UTF-8 encodings were leaking into the distribution. + + Commentary changes: + + Restore a comment about copyright notices that was inadvertently deleted. + (Thanks to Arthur David Olson.) + + Improve the commentary about which districts observe what times + in Russia. (Thanks to Oscar van Vlijmen and Arthur David Olson). + + Add web page links to tz.js. + + Add "Run by the Monkeys" to tz-art. (Thanks to Arthur David Olson.) + + +Release 2012j - 2012-11-12 18:34:49 -0800 + + Libya moved to CET this weekend, but with DST planned next year. + (Thanks to Even Scharning, Steffen Thorsen, and Tim Parenti.) + + Signatures now have the extension .asc, not .sign, as that's more + standard. (Thanks to Phil Pennock.) + + The output of 'zdump --version', and of 'zic --version', now + uses a format that is more typical for --version. + (Thanks to Joseph S. Myers.) + + The output of 'tzselect --help', 'zdump --help', and 'zic --help' + now uses tz@iana.org rather than the old elsie address. + + zic -v now complains about abbreviations that are less than 3 + or more than 6 characters, as per Posix. Formerly, it checked + for abbreviations that were more than 3. + + 'make public' no longer puts its temporary directory under /tmp, + and uses the just-built zic rather than the system zic. + + Various fixes to documentation and commentary. + + +Release 2012i - 2012-11-03 12:57:09 -0700 + + Cuba switches from DST tomorrow at 01:00. (Thanks to Steffen Thorsen.) + + Linker flags can now be specified via LDFLAGS. + AWK now defaults to 'awk', not 'nawk'. + The shell in tzselect now defaults to /bin/bash, but this can + be overridden by specifying KSHELL. + The main web page now mentions the unofficial GitHub repository. + (Thanks to Mike Frysinger.) + + Tarball signatures can now be built by running 'make signatures'. + There are also new makefile rules 'tarballs', 'check_public', and + separate makefile rules for each tarball and signature file. + A few makefile rules are now more portable to strict POSIX. + + The main web page now lists the canonical IANA URL. + + +Release 2012h - 2012-10-26 22:49:10 -0700 + + Bahia no longer has DST. (Thanks to Kelley Cook.) + + Tocantins has DST. (Thanks to Rodrigo Severo.) + + Israel has new DST rules next year. (Thanks to Ephraim Silverberg.) + + Jordan stays on DST this winter. (Thanks to Steffen Thorsen.) + + Web page updates. + + More C modernization, except that at Arthur David Olson's suggestion + the instances of 'register' were kept. + + +Release 2012g - 2012-10-17 20:59:45 -0700 + + Samoa fall 2012 and later. (Thanks to Nicholas Pereira and Robert Elz.) + + Palestine fall 2012. (Thanks to Steffen Thorsen.) + + Assume C89. + + To attack the version-number problem, this release ships the file + 'Makefile' (which contains the release number) in both the tzcode and + the tzdata tarballs. The two Makefiles are identical, and should be + identical in any matching pair of tarballs, so it shouldn't matter + which order you extract the tarballs. Perhaps we can come up with a + better version-number scheme at some point; this scheme does have the + virtue of not adding more files. + + +Release 2012f - 2012-09-12 23:17:03 -0700 + + * australasia (Pacific/Fiji): Fiji DST is October 21 through January + 20 this year. (Thanks to Steffen Thorsen.) + + +Release 2012e - 2012-08-02 20:44:55 -0700 + + * australasia (Pacific/Fakaofo): Tokelau is UT +13, not +14. + (Thanks to Steffen Thorsen.) + + * Use a single version number for both code and data. + + * .gitignore: New file. + + * Remove trailing white space. + + +Release code2012c-data2012d - 2012-07-19 16:35:33 -0700 + + Changes for Morocco's time stamps, which take effect in a couple of + hours, along with infrastructure changes to accommodate how the tz + code and data are released on IANA. + + +Release data2012c - 2012-03-27 12:17:25 -0400 + + africa + Summer time changes for Morocco (to start late April 2012) + + asia + Changes for 2012 for Gaza & the West Bank (Hebron) and Syria + + northamerica + Haiti following US/Canada rules for 2012 (and we're assuming, + for now anyway, for the future). + + +Release 2012b - 2012-03-02 12:29:15 +0700 + + There is just one change to tzcode2012b (compared with 2012a): + the Makefile that was accidentally included with 2012a has been + replaced with the version that should have been there, which is + identical with the previous version (from tzcode2011i). + + There are just two changes in tzdata2012b compared with 2012a. + + Most significantly, summer time in Cuba has been delayed 3 weeks + (now starts April 1 rather than March 11). Since Mar 11 (the old start + date, as listed in 2012a) is just a little over a week away, this + change is urgent. + + Less importantly, an excess tab in one of the changes in zone.tab + in 2012a has been removed. + + +Release 2012a - 2012-03-01 18:28:10 +0700 + + The changes in tzcode2012a (compared to the previous version, 2011i) + are entirely to the README and tz-art.htm and tz-link.htm files, if + none of those concern you, you can ignore the code update. The changes + reflect the changed addresses for the mailing list and the code and + data distribution points & methods (and a link to DateTime::TimeZone::Tzfile + has been added to tz-link.htm). + + In tzdata2012a (compared to the previous release, which was 2011n) + the major changes are: + Chile 2011/2012 and 2012/2013 summer time date adjustments. + Falkland Islands onto permanent summer time (we're assuming for the + foreseeable future, though 2012 is all we're fairly certain of.) + Armenia has abolished Summer Time. + Tokelau jumped the International Date Line back last December + (just the same as their near neighbour, Samoa). + America/Creston is a new zone for a small area of British Columbia + There will be a leapsecond 2012-06-30 23:59:60 UTC. + + Other minor changes are: + Corrections to 1918 Canadian summer time end dates. + Updated URL for UK time zone history (in comments) + A few typos in Le Corre's list of free French place names (comments) + + +Release data2011n - 2011-10-30 14:57:54 +0700 + + There are three changes of note - most urgently, Cuba (America/Havana) + has extended summer time by two weeks, now to end on Nov 13, rather than + the (already past) Oct 30. Second, the Pridnestrovian Moldavian Republic + (Europe/Tiraspol) decided not to split from the rest of Moldova after + all, and consequently that zone has been removed (again) and reinstated + in the "backward" file as a link to Europe/Chisinau. And third, the + end date for Fiji's summer time this summer was moved forward from the + earlier planned Feb 26, to Jan 22. + + Apart from that, Moldova (MD) returns to a single entry in zone.tab + (and the incorrect syntax that was in the 2011m version of that file + is so fixed - it would have been fixed in a different way had this + change not happened - that's the "missing" sccs version id). + + +Release data2011m - 2011-10-24 21:42:16 +0700 + + In particular, the typos in comments in the data (2011-11-17 should have + been 2011-10-17 as Alan Barrett noted, and spelling of Tiraspol that + Tim Parenti noted) have been fixed, and the change for Ukraine has been + made in all 4 Ukrainian zones, rather than just Kiev (again, thanks to + Tim Parenti, and also Denys Gavrysh) + + In addition, I added Europe/Tiraspol to zone.tab. + + This time, all the files have new version numbers... (including the files + otherwise unchanged in 2011m that were changed in 2011l but didn't get new + version numbers there...) + + +Release data2011l - 2011-10-10 11:15:43 +0700 + + There are just 2 changes that cause different generated tzdata files from + zic, to Asia/Hebron and Pacific/Fiji - the possible change for Bahia, Brazil + is included, but commented out. Compared with the diff I sent out last week, + this version also includes attributions for the sources for the changes + (in much the same format as ado used, but the html tags have not been + checked, verified, or used in any way at all, so if there are errors there, + please let me know.) + + +Release data2011k - 2011-09-20 17:54:03 -0400 + + [not summarized] + + +Release data2011j - 2011-09-12 09:22:49 -0400 + + (contemporary changes for Samoa; past changes for Kenya, Uganda, and + Tanzania); there are also two spelling corrections to comments in + the australasia file (with thanks to Christos Zoulas). + + +Release 2011i - 2011-08-29 05:56:32 -0400 + + [not summarized] + + +Release data2011h - 2011-06-15 18:41:48 -0400 + + Russia and Curaçao changes + + +Release 2011g - 2011-04-25 09:07:22 -0400 + + update the rules for Egypt to reflect its abandonment of DST this year + + +Release 2011f - 2011-04-06 17:14:53 -0400 + + [not summarized] + + +Release 2011e - 2011-03-31 16:04:38 -0400 + + Morocco, Chile, and tz-link changes + + +Release 2011d - 2011-03-14 09:18:01 -0400 + + changes that impact present-day time stamps in Cuba, Samoa, and Turkey + + +Release 2011c - 2011-03-07 09:30:09 -0500 + + These do affect current time stamps in Chile and Annette Island, Canada. + + +Release 2011b - 2011-02-07 08:44:50 -0500 + + [not summarized] + + +Release 2011a - 2011-01-24 10:30:16 -0500 + + [not summarized] + + +Release data2010o - 2010-11-01 09:18:23 -0400 + + change to the end of DST in Fiji in 2011 + + +Release 2010n - 2010-10-25 08:19:17 -0400 + + [not summarized] + + +Release 2010m - 2010-09-27 09:24:48 -0400 + + Hong Kong, Vostok, and zic.c changes + + +Release 2010l - 2010-08-16 06:57:25 -0400 + + [not summarized] + + +Release 2010k - 2010-07-26 10:42:27 -0400 + + [not summarized] + + +Release 2010j - 2010-05-10 09:07:48 -0400 + + changes for Bahía de Banderas and for version naming + + +Release data2010i - 2010-04-16 18:50:45 -0400 + + the end of DST in Morocco on 2010-08-08 + + +Release data2010h - 2010-04-05 09:58:56 -0400 + + [not summarized] + + +Release data2010g - 2010-03-24 11:14:53 -0400 + + [not summarized] + + +Release 2010f - 2010-03-22 09:45:46 -0400 + + [not summarized] + + +Release data2010e - 2010-03-08 14:24:27 -0500 + + corrects the Dhaka bug found by Danvin Ruangchan + + +Release data2010d - 2010-03-06 07:26:01 -0500 + + [not summarized] + + +Release 2010c - 2010-03-01 09:20:58 -0500 + + changes including KRE's suggestion for earlier initialization of + "goahead" and "goback" structure elements + + +Release code2010a - 2010-02-16 10:40:04 -0500 + + [not summarized] + + +Release data2010b - 2010-01-20 12:37:01 -0500 + + Mexico changes + + +Release data2010a - 2010-01-18 08:30:04 -0500 + + changes to Dhaka + + +Release data2009u - 2009-12-26 08:32:28 -0500 + + changes to DST in Bangladesh + + +Release 2009t - 2009-12-21 13:24:27 -0500 + + [not summarized] + + +Release data2009s - 2009-11-14 10:26:32 -0500 + + (cosmetic) Antarctica change and the DST-in-Fiji-in-2009-and-2010 change + + +Release 2009r - 2009-11-09 10:10:31 -0500 + + "antarctica" and "tz-link.htm" changes + + +Release 2009q - 2009-11-02 09:12:40 -0500 + + with two corrections as reported by Eric Muller and Philip Newton + + +Release data2009p - 2009-10-23 15:05:27 -0400 + + Argentina (including San Luis) changes (with the correction from + Mariano Absatz) + + +Release data2009o - 2009-10-14 16:49:38 -0400 + + Samoa (commentary only), Pakistan, and Bangladesh changes + + +Release data2009n - 2009-09-22 15:13:38 -0400 + + added commentary for Argentina and a change to the end of DST in + 2009 in Pakistan + + +Release data2009m - 2009-09-03 10:23:43 -0400 + + Samoa and Palestine changes + + +Release data2009l - 2009-08-14 09:13:07 -0400 + + Samoa (comments only) and Egypt + + +Release 2009k - 2009-07-20 09:46:08 -0400 + + [not summarized] + + +Release data2009j - 2009-06-15 06:43:59 -0400 + + Bangladesh change (with a short turnaround since the DST change is + impending) + + +Release 2009i - 2009-06-08 09:21:22 -0400 + + updating for DST in Bangladesh this year + + +Release 2009h - 2009-05-26 09:19:14 -0400 + + [not summarized] + + +Release data2009g - 2009-04-20 16:34:07 -0400 + + Cairo + + +Release data2009f - 2009-04-10 11:00:52 -0400 + + correct DST in Pakistan + + +Release 2009e - 2009-04-06 09:08:11 -0400 + + [not summarized] + + +Release 2009d - 2009-03-23 09:38:12 -0400 + + Morocco, Tunisia, Argentina, and American Astronomical Society changes + + +Release data2009c - 2009-03-16 09:47:51 -0400 + + change to the start of Cuban DST + + +Release 2009b - 2009-02-09 11:15:22 -0500 + + [not summarized] + + +Release 2009a - 2009-01-21 10:09:39 -0500 + + [not summarized] + + +Release data2008i - 2008-10-21 12:10:25 -0400 + + southamerica and zone.tab files, with Argentina DST rule changes and + United States zone reordering and recommenting + + +Release 2008h - 2008-10-13 07:33:56 -0400 + + [not summarized] + + +Release 2008g - 2008-10-06 09:03:18 -0400 + + Fix a broken HTML anchor and update Brazil's DST transitions; + there's also a slight reordering of information in tz-art.htm. + + +Release data2008f - 2008-09-09 22:33:26 -0400 + + [not summarized] + + +Release 2008e - 2008-07-28 14:11:17 -0400 + + changes by Arthur David Olson and Jesper Nørgaard Welen + + +Release data2008d - 2008-07-07 09:51:38 -0400 + + changes by Arthur David Olson, Paul Eggert, and Rodrigo Severo + + +Release data2008c - 2008-05-19 17:48:03 -0400 + + Pakistan, Morocco, and Mongolia + + +Release data2008b - 2008-03-24 08:30:59 -0400 + + including renaming Asia/Calcutta to Asia/Kolkata, with a backward + link provided + + +Release 2008a - 2008-03-08 05:42:16 -0500 + + [not summarized] + + +Release 2007k - 2007-12-31 10:25:22 -0500 + + most importantly, changes to the "southamerica" file based on + Argentina's readoption of daylight saving time + + +Release 2007j - 2007-12-03 09:51:01 -0500 + + 1. eliminate the "P" (parameter) macro; + + 2. the "noncontroversial" changes circulated on the time zone + mailing list (less the changes to "logwtmp.c"); + + 3. eliminate "too many transition" errors when "min" is used in time + zone rules; + + 4. changes by Paul Eggert (including updated information for Venezuela). + + +Release data2007i - 2007-10-30 10:28:11 -0400 + + changes for Cuba and Syria + + +Release 2007h - 2007-10-01 10:05:51 -0400 + + changes by Paul Eggert, as well as an updated link to the ICU + project in tz-link.htm + + +Release 2007g - 2007-08-20 10:47:59 -0400 + + changes by Paul Eggert + + The "leapseconds" file has been updated to incorporate the most + recent International Earth Rotation and Reference Systems Service + (IERS) bulletin. + + There's an addition to tz-art.htm regarding the television show "Medium". + + +Release 2007f - 2007-05-07 10:46:46 -0400 + + changes by Paul Eggert (including Haiti, Turks and Caicos, and New + Zealand) + + changes to zic.c to allow hour values greater than 24 (along with + Paul's improved time value overflow checking) + + +Release 2007e - 2007-04-02 10:11:52 -0400 + + Syria and Honduras changes by Paul Eggert + + zic.c variable renaming changes by Arthur David Olson + + +Release 2007d - 2007-03-20 08:48:30 -0400 + + changes by Paul Eggert + + the elimination of white space at the ends of lines + + +Release 2007c - 2007-02-26 09:09:37 -0500 + + changes by Paul Eggert + + +Release 2007b - 2007-02-12 09:34:20 -0500 + + Paul Eggert's proposed change to the quotation handling logic in zic.c. + + changes to the commentary in "leapseconds" reflecting the IERS + announcement that there is to be no positive leap second at the end + of June 2007. + + +Release 2007a - 2007-01-08 12:28:29 -0500 + + changes by Paul Eggert + + Derick Rethan's Asmara change + + Oscar van Vlijmen's Easter Island local mean time change + + symbolic link changes + + +Release 2006p - 2006-11-27 08:54:27 -0500 + + changes by Paul Eggert + + +Release 2006o - 2006-11-06 09:18:07 -0500 + + changes by Paul Eggert + + +Release 2006n - 2006-10-10 11:32:06 -0400 + + changes by Paul Eggert + + +Release 2006m - 2006-10-02 15:32:35 -0400 + + changes for Uruguay, Palestine, and Egypt by Paul Eggert + + (minimalist) changes to zic.8 to clarify "until" information + + +Release data2006l - 2006-09-18 12:58:11 -0400 + + Paul's best-effort work on this coming weekend's Egypt time change + + +Release 2006k - 2006-08-28 12:19:09 -0400 + + changes by Paul Eggert + + +Release 2006j - 2006-08-21 09:56:32 -0400 + + changes by Paul Eggert + + +Release code2006i - 2006-08-07 12:30:55 -0400 + + localtime.c fixes + + Ken Pizzini's conversion script + + +Release code2006h - 2006-07-24 09:19:37 -0400 + + adds public domain notices to four files + + includes a fix for transition times being off by a second + + adds a new recording to the "arts" file (information courtesy Colin Bowern) + + +Release 2006g - 2006-05-08 17:18:09 -0400 + + northamerica changes by Paul Eggert + + +Release 2006f - 2006-05-01 11:46:00 -0400 + + a missing version number problem is fixed (with thanks to Bradley + White for catching the problem) + + +Release 2006d - 2006-04-17 14:33:43 -0400 + + changes by Paul Eggert + + added new items to tz-arts.htm that were found by Paul + + +Release 2006c - 2006-04-03 10:09:32 -0400 + + two sets of data changes by Paul Eggert + + a fencepost error fix in zic.c + + changes to zic.c and the "europe" file to minimize differences + between output produced by the old 32-bit zic and the new 64-bit + version + + +Release 2006b - 2006-02-20 10:08:18 -0500 + [tz32code2006b + tz64code2006b + tzdata2006b] + + 64-bit code + + All SCCS IDs were bumped to "8.1" for this release. + + +Release 2006a - 2006-01-30 08:59:31 -0500 + + changes by Paul Eggert (in particular, Indiana time zone moves) + + an addition to the zic manual page to describe how special-case + transitions are handled + + +Release 2005r - 2005-12-27 09:27:13 -0500 + + Canadian changes by Paul Eggert + + They also add "
" directives to time zone data files and reflect
+  changes to warning message logic in "zdump.c" (but with calls to
+  "gettext" kept unbundled at the suggestion of Ken Pizzini).
+
+
+Release 2005q - 2005-12-13 09:17:09 -0500
+
+  Nothing earth-shaking here:
+	1.  Electronic mail addresses have been removed.
+	2.  Casts of the return value of exit have been removed.
+	3.  Casts of the argument of is.* macros have been added.
+	4.  Indentation in one section of zic.c has been fixed.
+	5.  References to dead URLs in the data files have been dealt with.
+
+
+Release 2005p - 2005-12-05 10:30:53 -0500
+
+  "systemv", "tz-link.htm", and "zdump.c" changes
+  (less the casts of arguments to the is* macros)
+
+
+Release 2005o - 2005-11-28 10:55:26 -0500
+
+  Georgia, Cuba, Nicaragua, and Jordan changes by Paul Eggert
+
+  zdump.c lint fixes by Arthur David Olson
+
+
+Release 2005n - 2005-10-03 09:44:09 -0400
+
+  changes by Paul Eggert (both the Uruguay changes and the Kyrgyzstan
+  et al. changes)
+
+
+Release 2005m - 2005-08-29 12:15:40 -0400
+
+  changes by Paul Eggert (with a small tweak to the tz-art change)
+
+  a declaration of an unused variable has been removed from zdump.c
+
+
+Release 2005l - 2005-08-22 12:06:39 -0400
+
+  changes by Paul Eggert
+
+  overflow/underflow checks by Arthur David Olson, minus changes to
+  the "Theory" file about the pending addition of 64-bit data (I grow
+  less confident of the changes being accepted with each passing day,
+  and the changes no longer increase the data files nine-fold--there's
+  less than a doubling in size by my local Sun's reckoning)
+
+
+Release 2005k - 2005-07-14 14:14:24 -0400
+
+  The "leapseconds" file has been edited to reflect the recently
+  announced leap second at the end of 2005.
+
+  I've also deleted electronic mail addresses from the files as an
+  anti-spam measure.
+
+
+Release 2005j - 2005-06-13 14:34:13 -0400
+
+  These reflect changes to limit the length of time zone abbreviations
+  and the characters used in those abbreviations.
+
+  There are also changes to handle POSIX-style "quoted" time zone
+  environment variables.
+
+  The changes were circulated on the time zone mailing list; the only
+  change since then was the removal of a couple of minimum-length of
+  abbreviation checks.
+
+
+Release data2005i - 2005-04-21 15:04:16 -0400
+
+  changes (most importantly to Nicaragua and Haiti) by Paul Eggert
+
+
+Release 2005h - 2005-04-04 11:24:47 -0400
+
+  changes by Paul Eggert
+
+  minor changes to Makefile and zdump.c to produce more useful output
+  when doing a "make typecheck"
+
+
+Release 2005g - 2005-03-14 10:11:21 -0500
+
+  changes by Paul Eggert (a change to current DST rules in Uruguay and
+  an update to a link to time zone software)
+
+
+Release 2005f - 2005-03-01 08:45:32 -0500
+
+  data and documentation changes by Paul Eggert
+
+
+Release 2005e - 2005-02-10 15:59:44 -0500
+
+  [not summarized]
+
+
+Release code2005d - 2005-01-31 09:21:47 -0500
+
+  make zic complain about links to links if the -v flag is used
+
+  have "make public" do more code checking
+
+  add an include to "localtime.c" for the benefit of gcc systems
+
+
+Release 2005c - 2005-01-17 18:36:29 -0500
+
+  get better results when mktime runs on a system where time_t is double
+
+  changes to the data files (most importantly to Paraguay)
+
+
+Release 2005b - 2005-01-10 09:19:54 -0500
+
+  Get localtime and gmtime working on systems with exotic time_t types.
+
+  Update the leap second commentary in the "leapseconds" file.
+
+
+Release 2005a - 2005-01-01 13:13:44 -0500
+
+  [not summarized]
+
+
+Release code2004i - 2004-12-14 13:42:58 -0500
+
+  Deal with systems where time_t is unsigned.
+
+
+Release code2004h - 2004-12-07 11:40:18 -0500
+
+  64-bit-time_t changes
+
+
+Release 2004g - 2004-11-02 09:06:01 -0500
+
+  update to Cuba (taking effect this weekend)
+
+  other changes by Paul Eggert
+
+  correction of the spelling of Oslo
+
+  changed versions of difftime.c and private.h
+
+
+Release code2004f - 2004-10-21 10:25:22 -0400
+
+  Cope with wide-ranging tm_year values.
+
+
+Release 2004e - 2004-10-11 14:47:21 -0400
+
+  Brazil/Argentina/Israel changes by Paul Eggert
+
+  changes to tz-link.htm by Paul
+
+  one small fix to Makefile
+
+
+Release 2004d - 2004-09-22 08:27:29 -0400
+
+  Avoid overflow problems when TM_YEAR_BASE is added to an integer.
+
+
+Release 2004c - 2004-08-11 12:06:26 -0400
+
+  asctime-related changes
+
+  (variants of) some of the documentation changes suggested by Paul Eggert
+
+
+Release 2004b - 2004-07-19 14:33:35 -0400
+
+  data changes by Paul Eggert - most importantly, updates for Argentina
+
+
+Release 2004a - 2004-05-27 12:00:47 -0400
+
+  changes by Paul Eggert
+
+  Handle DST transitions that occur at the end of a month in some
+  years but at the start of the following month in other years.
+
+  Add a copy of the correspondence that's the basis for claims about
+  DST in the Navajo Nation.
+
+
+Release 2003e - 2003-12-15 09:36:47 -0500
+
+  changes by Arthur David Olson (primarily code changes)
+
+  changes by Paul Eggert (primarily data changes)
+
+  minor changes to "Makefile" and "northamerica" (in the latter case,
+  optimization of the "Toronto" rules)
+
+
+Release 2003d - 2003-10-06 09:34:44 -0400
+
+  changes by Paul Eggert
+
+
+Release 2003c - 2003-09-16 10:47:05 -0400
+
+  Fix bad returns in zic.c's inleap function.
+  Thanks to Bradley White for catching the problem!
+
+
+Release 2003b - 2003-09-16 07:13:44 -0400
+
+  Add a "--version" option (and documentation) to the zic and zdump commands.
+
+  changes to overflow/underflow checking in zic
+
+  a localtime typo fix.
+
+  Update the leapseconds and tz-art.htm files.
+
+
+Release 2003a - 2003-03-24 09:30:54 -0500
+
+  changes by Paul Eggert
+
+  a few additions and modifications to the tz-art.htm file
+
+
+Release 2002d - 2002-10-15 13:12:42 -0400
+
+  changes by Paul Eggert, less the "Britain (UK)" change in iso3166.tab
+
+  There's also a new time zone quote in "tz-art.htm".
+
+
+Release 2002c - 2002-04-04 11:55:20 -0500
+
+  changes by Paul Eggert
+
+  Change zic.c to avoid creating symlinks to files that don't exist.
+
+
+Release 2002b - 2002-01-28 12:56:03 -0500
+
+  [These change notes are for Release 2002a, which was corrupted.
+  2002b was a corrected version of 2002a.]
+
+  changes by Paul Eggert
+
+  Update the "leapseconds" file to note that there'll be no leap
+  second at the end of June, 2002.
+
+  Change "zic.c" to deal with a problem in handling the "Asia/Bishkek" zone.
+
+  Change to "difftime.c" to avoid sizeof problems.
+
+
+Release 2001d - 2001-10-09 13:31:32 -0400
+
+  changes by Paul Eggert
+
+
+Release 2001c - 2001-06-05 13:59:55 -0400
+
+  changes by Paul Eggert and Andrew Brown
+
+
+Release 2001b - 2001-04-05 16:44:38 -0400
+
+  changes by Paul Eggert (modulo jnorgard's typo fix)
+
+  tz-art.htm has been HTMLified.
+
+
+Release 2001a - 2001-03-13 12:57:44 -0500
+
+  changes by Paul Eggert
+
+  An addition to the "leapseconds" file: comments with the text of the
+  latest IERS leap second notice.
+
+  Trailing white space has been removed from data file lines, and
+  repeated spaces in "Rule Jordan" lines in the "asia" file have been
+  converted to tabs.
+
+
+Release 2000h - 2000-12-14 15:33:38 -0500
+
+  changes by Paul Eggert
+
+  one typo fix in the "art" file
+
+  With providence, this is the last update of the millennium.
+
+
+Release 2000g - 2000-10-10 11:35:22 -0400
+
+  changes by Paul Eggert
+
+  correction of John Mackin's name submitted by Robert Elz
+
+  Garry Shandling's Daylight Saving Time joke (!?!) from the recent
+  Emmy Awards broadcast.
+
+
+Release 2000f - 2000-08-10 09:31:58 -0400
+
+  changes by Paul Eggert
+
+  Added information in "tz-art.htm" on a Seinfeld reference to DST.
+
+  Error checking and messages in the "yearistype" script have been
+  improved.
+
+
+Release 2000e - 2000-07-31 09:27:54 -0400
+
+  data changes by Paul Eggert
+
+  a change to the default value of the defined constant HAVE_STRERROR
+
+  the addition of a Dave Barry quote on DST to the tz-arts file
+
+
+Release 2000d - 2000-04-20 15:43:04 -0400
+
+  changes to the documentation and code of strftime for C99 conformance
+
+  a bug fix for date.c
+
+  These are based on (though modified from) changes by Paul Eggert.
+
+
+Release 2000c - 2000-03-04 10:31:43 -0500
+
+  changes by Paul Eggert
+
+
+Release 2000b - 2000-02-21 12:16:29 -0500
+
+  changes by Paul Eggert and Joseph Myers
+
+  modest tweaks to the tz-art.htm and tz-link.htm files
+
+
+Release 2000a - 2000-01-18 09:21:26 -0500
+
+  changes by Paul Eggert
+
+  The two hypertext documents have also been renamed.
+
+
+Release code1999i-data1999j - 1999-11-15 18:43:22 -0500
+
+  Paul Eggert's changes
+
+  additions to the "zic" manual page and the "Arts.htm" file
+
+
+Release code1999h-data1999i - 1999-11-08 14:55:21 -0500
+
+  [not summarized]
+
+
+Release data1999h - 1999-10-07 03:50:29 -0400
+
+  changes by Paul Eggert to "europe" (most importantly, fixing
+  Lithuania and Estonia)
+
+
+Release 1999g - 1999-09-28 11:06:18 -0400
+
+  data changes by Paul Eggert (most importantly, the change for
+  Lebanon that buys correctness for this coming Sunday)
+
+  The "code" file contains changes to "Makefile" and "checktab.awk" to
+  allow better checking of time zone files before they are published.
+
+
+Release 1999f - 1999-09-23 09:48:14 -0400
+
+  changes by Arthur David Olson and Paul Eggert
+
+
+Release 1999e - 1999-08-17 15:20:54 -0400
+
+  changes circulated by Paul Eggert, although the change to handling
+  of DST-specifying time zone names has been commented out for now
+  (search for "XXX" in "localtime.c" for details).  These files also
+  do not make any changes to the start of DST in Brazil.
+
+  In addition to Paul's changes, there are updates to "Arts.htm" and
+  cleanups of URLs.
+
+
+Release 1999d - 1999-03-30 11:31:07 -0500
+
+  changes by Paul Eggert
+
+  The Makefile's "make public" rule has also been changed to do a test
+  compile of each individual time zone data file (which should help
+  avoid problems such as the one we had with Nicosia).
+
+
+Release 1999c - 1999-03-25 09:47:47 -0500
+
+  changes by Paul Eggert, most importantly the change for Chile.
+
+
+Release 1999b - 1999-02-01 17:51:44 -0500
+
+  changes by Paul Eggert
+
+  code changes (suggested by Mani Varadarajan, mani at be.com) for
+  correct handling of symbolic links when building using a relative directory
+
+  code changes to generate correct messages for failed links
+
+  updates to the URLs in Arts.htm
+
+
+Release 1999a - 1999-01-19 16:20:29 -0500
+
+  error message internationalizations and corrections in zic.c and
+  zdump.c (as suggested by Vladimir Michl, vladimir.michl at upol.cz,
+  to whom thanks!)
+
+
+Release code1998h-data1998i - 1998-10-01 09:56:10 -0400
+
+  changes for Brazil, Chile, and Germany
+
+  support for use of "24:00" in the input files for the time zone compiler
+
+
+Release code1998g-data1998h - 1998-09-24 10:50:28 -0400
+
+  changes by Paul Eggert
+
+  correction to a define in the "private.h" file
+
+
+Release data1998g - 1998-08-11 03:28:35 -0000
+  [tzdata1998g.tar.gz is missing!]
+
+  Lithuanian change provided by mgedmin at pub.osf.it
+
+  Move creation of the GMT link with Etc/GMT to "etcetera" (from
+  "backward") to ensure that the GMT file is created even where folks
+  don't want the "backward" links (as suggested by Paul Eggert).
+
+
+Release data1998f - 1998-07-20 13:50:00 -0000
+  [tzdata1998f.tar.gz is missing!]
+
+  Update the "leapseconds" file to include the newly-announced
+  insertion at the end of 1998.
+
+
+Release code1998f - 1998-06-01 10:18:31 -0400
+
+  addition to localtime.c by Guy Harris
+
+
+Release 1998e - 1998-05-28 09:56:26 -0400
+
+  The Makefile is changed to produce zoneinfo-posix rather than
+  zoneinfo/posix, and to produce zoneinfo-leaps rather than
+  zoneinfo/right.
+
+  data changes by Paul Eggert
+
+  changes from Guy Harris to provide asctime_r and ctime_r
+
+  A usno1998 file (substantially identical to usno1997) has been added.
+
+
+Release 1998d - 1998-05-14 11:58:34 -0400
+
+  changes to comments (in particular, elimination of references to CIA maps).
+  "Arts.htm", "WWW.htm", "asia", and "australasia" are the only places
+  where changes occur.
+
+
+Release 1998c - 1998-02-28 12:32:26 -0500
+
+  changes by Paul Eggert (save the "French correction," on which I'll
+  wait for the dust to settle)
+
+  symlink changes
+
+  changes and additions to Arts.htm
+
+
+Release 1998b - 1998-01-17 14:31:51 -0500
+
+  URL cleanups and additions
+
+
+Release 1998a - 1998-01-13 12:37:35 -0500
+
+  changes by Paul Eggert
+
+
+Release code1997i-data1997k - 1997-12-29 09:53:41 -0500
+
+  changes by Paul Eggert, with minor modifications from Arthur David
+  Olson to make the files more browser friendly
+
+
+Release code1997h-data1997j - 1997-12-18 17:47:35 -0500
+
+  minor changes to put "TZif" at the start of each time zone information file
+
+  a rule has also been added to the Makefile so you can
+	make zones
+  to just recompile the zone information files (rather than doing a
+  full "make install" with its other effects).
+
+
+Release data1997i - 1997-10-07 08:45:38 -0400
+
+  changes to Africa by Paul Eggert
+
+
+Release code1997g-data1997h - 1997-09-04 16:56:54 -0400
+
+  corrections for Uruguay (and other locations)
+
+  Arthur David Olson's simple-minded fix allowing mktime to both
+  correctly handle leap seconds and correctly handle tm_sec values
+  upon which arithmetic has been performed.
+
+
+Release code1997f-data1997g - 1997-07-19 13:15:02 -0400
+
+  Paul Eggert's updates
+
+  a small change to a function prototype;
+
+  "Music" has been renamed "Arts.htm", HTMLified, and augmented to
+  include information on Around the World in Eighty Days.
+
+
+Release code1997e-data1997f - 1997-05-03 18:52:34 -0400
+
+  fixes to zic's error handling
+
+  changes inspired by the item circulated on Slovenia
+
+  The description of Web resources has been HTMLified for browsing
+  convenience.
+
+  A new piece of tz-related music has been added to the "Music" file.
+
+
+Release code1997d-data1997e - 1997-03-29 12:48:52 -0500
+
+  Paul Eggert's latest suggestions
+
+
+Release code1997c-data1997d - 1997-03-07 20:37:54 -0500
+
+  changes to "zic.c" to correct performance of the "-s" option
+
+  a new file "usno1997"
+
+
+Release data1997c - 1997-03-04 09:58:18 -0500
+
+  changes in Israel
+
+
+Release 1997b - 1997-02-27 18:34:19 -0500
+
+  The data file incorporates the 1997 leap second.
+
+  The code file incorporates Arthur David Olson's take on the
+  zic/multiprocessor/directory-creation situation.
+
+
+Release 1997a - 1997-01-21 09:11:10 -0500
+
+  Paul Eggert's Antarctica (and other changes)
+
+  Arthur David Olson finessed the "getopt" issue by checking against
+  both -1 and EOF (regardless of POSIX, SunOS 4.1.1's manual says -1
+  is returned while SunOS 5.5's manual says EOF is returned).
+
+
+Release code1996o-data1996n - 1996-12-27 21:42:05 -0500
+
+  Paul Eggert's latest changes
+
+
+Release code1996n - 1996-12-16 09:42:02 -0500
+
+  link snapping fix from Bruce Evans (via Garrett Wollman)
+
+
+Release data1996m - 1996-11-24 02:37:34 -0000
+  [tzdata1996m.tar.gz is missing!]
+
+  Paul Eggert's batch of changes
+
+
+Release code1996m-data1996l - 1996-11-05 14:00:12 -0500
+
+  No functional changes here; the files have simply been changed to
+  make more use of ISO style dates in comments. The names of the above
+  files now include the year in full.
+
+
+Release code96l - 1996-09-08 17:12:20 -0400
+
+  tzcode96k was missing a couple of pieces.
+
+
+Release 96k - 1996-09-08 16:06:22 -0400
+
+  the latest round of changes from Paul Eggert
+
+  the recent Year 2000 material
+
+
+Release code96j - 1996-07-30 13:18:53 -0400
+
+  Set sp->typecnt as suggested by Timothy Patrick Murphy.
+
+
+Release code96i - 1996-07-27 20:11:35 -0400
+
+  Paul's suggested patch for strftime %V week numbers
+
+
+Release data96i - 1996-07-01 18:13:04 -0400
+
+  "northamerica" and "europe" changes by Paul Eggert
+
+
+Release code96h - 1996-06-05 08:02:21 -0400
+
+  fix for handling transitions specified in Universal Time
+
+  Some "public domain" notices have also been added.
+
+
+Release code96g - 1996-05-16 14:00:26 -0400
+
+  fix for the simultaneous-DST-and-zone-change challenge
+
+
+Release data96h - 1996-05-09 17:40:51 -0400
+
+  changes by Paul Eggert
+
+
+Release code96f-data96g - 1996-05-03 03:09:59 -0000
+  [tzcode96f.tar.gz + tzdata96g.tar.gz are both missing!]
+
+  The changes get us some of the way to fixing the problems noted in Paul
+  Eggert's letter yesterday (in addition to a few others).  The approach
+  has been to make zic a bit smarter about figuring out what time zone
+  abbreviations apply just after the time specified in the "UNTIL" part
+  of a zone line.  Putting the smarts in zic means avoiding having
+  transition times show up in both "Zone" lines and "Rule" lines, which
+  in turn avoids multiple transition time entries in time zone files.
+  (This also makes the zic input files such as "europe" a bit shorter and
+  should ease maintenance.)
+
+
+Release data96f - 1996-04-19 19:20:03 -0000
+  [tzdata96f.tar.gz is missing!]
+
+  The only changes are to the "northamerica" file; the time zone
+  abbreviation for Denver is corrected to MST (and MDT), and the
+  comments for Mexico have been updated.
+
+
+Release data96e - 1996-03-19 17:37:26 -0500
+
+  Proposals by Paul Eggert, in particular the Portugal change that
+  comes into play at the end of this month.
+
+
+Release data96d - 1996-03-18 20:49:39 -0500
+
+  [not summarized]
+
+
+Release code96e - 1996-02-29 15:43:27 -0000
+  [tzcode96e.tar.gz is missing!]
+
+  internationalization changes and the fix to the documentation for strftime
+
+
+Release code96d-data96c - 1996-02-12 11:05:27 -0500
+
+  The "code" file simply updates Bob Kridle's electronic address.
+
+  The "data" file updates rules for Mexico.
+
+
+Release data96b - 1996-01-27 15:44:42 -0500
+
+  Kiribati change
+
+
+Release code96c - 1996-01-16 16:58:15 -0500
+
+  leap-year streamlining and binary-search changes
+
+  fix to newctime.3
+
+
+Release code96b - 1996-01-10 20:42:39 -0500
+
+  fixes and enhancements from Paul Eggert, including code that
+  emulates the behavior of recent versions of the SunOS "date"
+  command.
+
+
+Release 96a - 1996-01-06 09:08:24 -0500
+
+  Israel updates
+
+  fixes to strftime.c for correct ISO 8601 week number generation,
+  plus support for two new formats ('G' and 'g') to give ISO 8601 year
+  numbers (which are not necessarily the same as calendar year numbers)
+
+
+Release code95i-data95m - 1995-12-21 12:46:47 -0500
+
+  The latest revisions from Paul Eggert are included, the usno1995
+  file has been updated, and a new file ("WWW") covering useful URLs
+  has been added.
+
+
+Release code95h-data95l - 1995-12-19 18:10:12 -0500
+
+  A simplification of a macro definition, a change to data for Sudan,
+  and (for last minute shoppers) notes in the "Music" file on the CD
+  "Old Man Time".
+
+
+Release code95g-data95k - 1995-10-30 10:32:47 -0500
+
+  (slightly reformatted) 8-bit-clean proposed patch
+
+  minor patch: US/Eastern -> America/New_York
+
+  snapshot of the USNO's latest data ("usno1995")
+
+  some other minor cleanups
+
+
+Release code95f-data95j - 1995-10-28 21:01:34 -0000
+  [tzcode95f.tar.gz + tzdata95j.tar.gz are both missing!]
+
+  European cleanups
+
+  support for 64-bit time_t's
+
+  optimization in localtime.c
+
+
+Release code95e - 1995-10-13 13:23:57 -0400
+
+  the mktime change to scan from future to past when trying to find time zone
+  offsets
+
+
+Release data95i - 1995-09-26 10:43:26 -0400
+
+  For Canada/Central, guess that the Sun customer's "one week too
+  early" was just a approximation, and the true error is one month
+  too early.  This is consistent with the rest of Canada.
+
+
+Release data95h - 1995-09-21 11:26:48 -0400
+
+  latest changes from Paul Eggert
+
+
+Release code95d - 1995-09-14 11:14:45 -0400
+
+  the addition of a "Music" file, which documents four recorded
+  versions of the tune "Save That Time".
+
+
+Release data95g - 1995-09-01 17:21:36 -0400
+
+  "yearistype" correction
+
+
+Release data95f - 1995-08-28 20:46:56 -0400
+
+  Paul Eggert's change to the australasia file
+
+
+Release data95e - 1995-07-08 18:02:34 -0400
+
+  The only change is a leap second at the end of this year.
+  Thanks to Bradley White for forwarding news on the leap second.
+
+
+Release data95d - 1995-07-03 13:26:22 -0400
+
+  Paul Eggert's changes
+
+
+Release data95c - 1995-07-02 19:19:28 -0400
+
+  changes to "asia", "backward", "europe", and "southamerica"
+  (read: northamericacentrics need not apply)
+
+
+Release code95c - 1995-03-13 14:00:46 -0500
+
+  one-line fix for sign extension problems in detzcode
+
+
+Release 95b - 1995-03-04 11:22:38 -0500
+
+  Minor changes in both:
+
+  The "code" file contains a workaround for the lack of "unistd.h" in
+  Microsoft C++ version 7.
+
+  The "data" file contains a fixed "Link" for America/Shiprock.
+
+
+Release 94h - 1994-12-10 12:51:14 -0500
+
+  The files:
+
+  *	incorporate the changes to "zdump" and "date" to make changes to
+	the "TZ" environment variable permanent;
+
+  *	incorporate the table changes by Paul Eggert;
+
+  *	include (and document) support for universal time specifications in
+	data files - but do not (yet) include use of this feature in the
+	data files.
+
+  Think of this as "TZ Classic" - the software has been set up not to break if
+  universal time shows up in its input, and data entries have been
+  left as is so as not to break existing implementations.
+
+
+Release data94f - 1994-08-20 12:56:09 -0400
+
+  (with thanks!) the latest data updates from Paul Eggert
+
+
+Release data94e - 1994-06-04 13:13:53 -0400
+
+  [not summarized]
+
+
+Release code94g - 1994-05-05 12:14:07 -0400
+
+  fix missing "optind.c" and a reference to it in the Makefile
+
+
+Release code94f - 1994-05-05 13:00:33 -0000
+  [tzcode94f.tar.gz is missing!]
+
+  changes to avoid overflow in difftime, as well as changes to cope
+  with the 52/53 challenge in strftime
+
+
+Release code94e - 1994-03-30 23:32:59 -0500
+
+  change for the benefit of PCTS
+
+
+Release 94d - 1994-02-24 15:42:25 -0500
+
+  Avoid clashes with POSIX semantics for zones such as GMT+4.
+
+  Some other very minor housekeeping is also present.
+
+
+Release code94c - 1994-02-10 08:52:40 -0500
+
+  Fix bug where mkdirs was broken unless you compile with
+  -fwritable-strings (which is generally losing to do).
+
+
+Release 94b - 1994-02-07 10:04:33 -0500
+
+  work by Paul Eggert who notes:
+
+  I found another book of time zone histories by E W Whitman; it's not
+  as extensive as Shanks but has a few goodies of its own.  I used it
+  to update the tables.  I also fixed some more as a result of
+  correspondence with Adam David and Peter Ilieve, and move some stray
+  links from 'europe' to 'backward'.  I corrected some scanning errors
+  in usno1989.
+
+  As far as the code goes, I fixed zic to allow years in the range
+  INT_MIN to INT_MAX; this fixed a few boundary conditions around 1900.
+  And I cleaned up the zic documentation a little bit.
+
+
+Release data94a - 1994-02-03 08:58:54 -0500
+
+  It simply incorporates the recently announced leap second into the
+  "leapseconds" file.
+
+
+Release 93g - 1993-11-22 17:28:27 -0500
+
+  Paul Eggert has provided a good deal of historic information (based
+  on Shanks), and there are some code changes to deal with the buglets
+  that crawled out in dealing with the new information.
+
+
+Release 93f - 1993-10-15 12:27:46 -0400
+
+  Paul Eggert's changes
+
+
+Release 93e - 1993-09-05 21:21:44 -0400
+
+  This has updated data for Israel, England, and Kwajalein.  There's
+  also an update to "zdump" to cope with Kwajalein's 24-hour jump.
+  Thanks to Paul Eggert and Peter Ilieve for the changes.
+
+
+Release 93d - 1993-06-17 23:34:17 -0400
+
+  new fix and new data on Israel
+
+
+Release 93c - 1993-06-06 19:31:55 -0400
+
+  [not summarized]
+
+
+Release 93b - 1993-02-02 14:53:58 -0500
+
+  updated "leapseconds" file
+
+
+Release 93 - 1993-01-08 07:01:06 -0500
+
+  At kre's suggestion, the package has been split in two - a code piece
+  (which also includes documentation) that's only of use to folks who
+  want to recompile things and a data piece useful to anyone who can
+  run "zic".
+
+  The new version has a few changes to the data files, a few
+  portability changes, and an off-by-one fix (with thanks to
+  Tom Karzes at deshaw.com for providing a description and a
+  solution).
+
+
+Release 92c - 1992-11-21 17:35:36 -0000
+  [tz92c.tar.Z is missing!]
+
+  The fallout from the latest round of DST transitions.
+
+  There are changes for Portugal, Saskatchewan, and "Pacific-New";
+  there's also a change to "zic.c" that makes it portable to more systems.
+
+
+Release 92 - 1992-04-25 18:17:03 -0000
+  [tz92.tar.Z is missing!]
+
+  By popular demand (well, at any rate, following a request by kre at munnari)
+
+
+The 1989 update of the time zone package featured:
+
+  *	POSIXization (including interpretation of POSIX-style TZ environment
+	variables, provided by Guy Harris),
+  *	ANSIfication (including versions of "mktime" and "difftime"),
+  *	SVIDulation (an "altzone" variable)
+  *	MACHination (the "gtime" function)
+  *	corrections to some time zone data (including corrections to the rules
+	for Great Britain and New Zealand)
+  *	reference data from the United States Naval Observatory for folks who
+	want to do additional time zones
+  *	and the 1989 data for Saudi Arabia.
+
+  (Since this code will be treated as "part of the implementation" in some
+  places and as "part of the application" in others, there's no good way to
+  name functions, such as timegm, that are not part of the proposed ANSI C
+  standard; such functions have kept their old, underscore-free names in this
+  update.)
+
+  And the "dysize" function has disappeared; it was present to allow
+  compilation of the "date" command on old BSD systems, and a version of "date"
+  is now provided in the package.  The "date" command is not created when you
+  "make all" since it may lack options provided by the version distributed with
+  your operating system, or may not interact with the system in the same way
+  the native version does.
+
+  Since POSIX frowns on correct leap second handling, the default behavior of
+  the "zic" command (in the absence of a "-L" option) has been changed to omit
+  leap second information from its output files.
+
+
+-----
+Notes
+
+This file contains copies of the part of each release announcement
+that talks about the changes in that release.  The text has been
+adapted and reformatted for the purposes of this file.
+
+Traditionally a release R consists of a pair of tarball files,
+tzcodeR.tar.gz and tzdataR.tar.gz.  However, some releases (e.g.,
+code2010a, data2012c) consist of just one or the other tarball, and a
+few (e.g., code2012c-data2012d) have tarballs with mixed version
+numbers.  Recent releases also come in an experimental format
+consisting of a single tarball tzdb-R.tar.lz with extra data.
+
+Release time stamps are taken from the release's commit (for newer,
+Git-based releases), from the newest file in the tarball (for older
+releases, where this info is available) or from the email announcing
+the release (if all else fails; these are marked with a time zone of
+-0000 and an "is missing!" comment).
+
+Earlier versions of the code and data were not announced on the tz
+list and are not summarized here.
+
+This file is in the public domain.
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/README b/README
new file mode 100644
index 000000000000..8a09aa2cb9f1
--- /dev/null
+++ b/README
@@ -0,0 +1,71 @@
+README for the tz distribution
+
+"What time is it?" -- Richard Deacon as The King
+"Any time you want it to be." -- Frank Baxter as The Scientist
+					(from the Bell System film "About Time")
+
+The Time Zone Database (often called tz or zoneinfo) contains code and
+data that represent the history of local time for many representative
+locations around the globe.  It is updated periodically to reflect
+changes made by political bodies to time zone boundaries, UTC offsets,
+and daylight-saving rules.
+
+Here is a recipe for acquiring, building, installing, and testing the
+tz distribution on a GNU/Linux or similar host.
+
+To acquire the distribution, run the following shell commands:
+
+	mkdir tz
+	cd tz
+	wget --retr-symlinks 'ftp://ftp.iana.org/tz/tz*-latest.tar.gz'
+	gzip -dc tzcode-latest.tar.gz | tar -xf -
+	gzip -dc tzdata-latest.tar.gz | tar -xf -
+
+Alternatively, the following shell commands acquire the same
+distribution, with extra data useful for regression testing:
+
+	wget --retr-symlinks 'ftp://ftp.iana.org/tz/tzdb-latest.tar.lz'
+	lzip -dc tzdb-latest.tar.lz | tar -xf -
+
+Be sure to read the comments in "Makefile" and make any changes needed
+to make things right for your system, especially if you are using some
+platform other than GNU/Linux.  Then run the following commands,
+substituting your desired installation directory for "$HOME/tzdir":
+
+	make TOPDIR=$HOME/tzdir install
+	$HOME/tzdir/etc/zdump -v America/Los_Angeles
+
+Historical local time information has been included here to:
+
+*	provide a compendium of data about the history of civil time
+	that is useful even if not 100% accurate;
+
+*	give an idea of the variety of local time rules that have
+	existed in the past and thus an idea of the variety that may be
+	expected in the future;
+
+*	provide a test of the generality of the local time rule description
+	system.
+
+The information in the time zone data files is by no means authoritative;
+fixes and enhancements are welcome.  Please see the file CONTRIBUTING
+for details.
+
+Thanks to these Time Zone Caballeros who've made major contributions to the
+time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
+Guy Harris; Mark Horton; John Mackin; and Bradley White.  Thanks also to
+Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales
+for testing work, and to Gwillim Law for checking local mean time data.
+Thanks in particular to Arthur David Olson, the project's founder and first
+maintainer, to whom the time zone community owes the greatest debt of all.
+None of them are responsible for remaining errors.
+
+Look in  for updated versions of these files.
+
+Please send comments or information to tz@iana.org.
+
+-----
+
+This file is in the public domain, so clarified as of 2009-05-17 by
+Arthur David Olson.  The other files in this distribution are either
+public domain or BSD licensed; see the file LICENSE for details.
diff --git a/Theory b/Theory
new file mode 100644
index 000000000000..677baf6f8c72
--- /dev/null
+++ b/Theory
@@ -0,0 +1,840 @@
+Theory and pragmatics of the tz code and data
+
+
+----- Outline -----
+
+	Scope of the tz database
+	Names of time zone rules
+	Time zone abbreviations
+	Accuracy of the tz database
+	Time and date functions
+	Calendrical issues
+	Time and time zones on Mars
+
+
+----- Scope of the tz database -----
+
+The tz database attempts to record the history and predicted future of
+all computer-based clocks that track civil time.  To represent this
+data, the world is partitioned into regions whose clocks all agree
+about time stamps that occur after the somewhat-arbitrary cutoff point
+of the POSIX Epoch (1970-01-01 00:00:00 UTC).  For each such region,
+the database records all known clock transitions, and labels the region
+with a notable location.  Although 1970 is a somewhat-arbitrary
+cutoff, there are significant challenges to moving the cutoff earlier
+even by a decade or two, due to the wide variety of local practices
+before computer timekeeping became prevalent.
+
+Clock transitions before 1970 are recorded for each such location,
+because most systems support time stamps before 1970 and could
+misbehave if data entries were omitted for pre-1970 transitions.
+However, the database is not designed for and does not suffice for
+applications requiring accurate handling of all past times everywhere,
+as it would take far too much effort and guesswork to record all
+details of pre-1970 civil timekeeping.
+
+As described below, reference source code for using the tz database is
+also available.  The tz code is upwards compatible with POSIX, an
+international standard for UNIX-like systems.  As of this writing, the
+current edition of POSIX is:
+
+  The Open Group Base Specifications Issue 7
+  IEEE Std 1003.1, 2013 Edition
+  
+
+
+
+----- Names of time zone rules -----
+
+Each of the database's time zone rules has a unique name.
+Inexperienced users are not expected to select these names unaided.
+Distributors should provide documentation and/or a simple selection
+interface that explains the names; for one example, see the 'tzselect'
+program in the tz code.  The Unicode Common Locale Data Repository
+ contains data that may be useful for other
+selection interfaces.
+
+The time zone rule naming conventions attempt to strike a balance
+among the following goals:
+
+ * Uniquely identify every region where clocks have agreed since 1970.
+   This is essential for the intended use: static clocks keeping local
+   civil time.
+
+ * Indicate to experts where that region is.
+
+ * Be robust in the presence of political changes.  For example, names
+   of countries are ordinarily not used, to avoid incompatibilities
+   when countries change their name (e.g. Zaire->Congo) or when
+   locations change countries (e.g. Hong Kong from UK colony to
+   China).
+
+ * Be portable to a wide variety of implementations.
+
+ * Use a consistent naming conventions over the entire world.
+
+Names normally have the form AREA/LOCATION, where AREA is the name
+of a continent or ocean, and LOCATION is the name of a specific
+location within that region.  North and South America share the same
+area, 'America'.  Typical names are 'Africa/Cairo', 'America/New_York',
+and 'Pacific/Honolulu'.
+
+Here are the general rules used for choosing location names,
+in decreasing order of importance:
+
+	Use only valid POSIX file name components (i.e., the parts of
+		names other than '/').  Do not use the file name
+		components '.' and '..'.  Within a file name component,
+		use only ASCII letters, '.', '-' and '_'.  Do not use
+		digits, as that might create an ambiguity with POSIX
+		TZ strings.  A file name component must not exceed 14
+		characters or start with '-'.  E.g., prefer 'Brunei'
+		to 'Bandar_Seri_Begawan'.  Exceptions: see the discussion
+		of legacy names below.
+	A name must not be empty, or contain '//', or start or end with '/'.
+	Do not use names that differ only in case.  Although the reference
+		implementation is case-sensitive, some other implementations
+		are not, and they would mishandle names differing only in case.
+	If one name A is an initial prefix of another name AB (ignoring case),
+		then B must not start with '/', as a regular file cannot have
+		the same name as a directory in POSIX.  For example,
+		'America/New_York' precludes 'America/New_York/Bronx'.
+	Uninhabited regions like the North Pole and Bouvet Island
+		do not need locations, since local time is not defined there.
+	There should typically be at least one name for each ISO 3166-1
+		officially assigned two-letter code for an inhabited country
+		or territory.
+	If all the clocks in a region have agreed since 1970,
+		don't bother to include more than one location
+		even if subregions' clocks disagreed before 1970.
+		Otherwise these tables would become annoyingly large.
+	If a name is ambiguous, use a less ambiguous alternative;
+		e.g. many cities are named San José and Georgetown, so
+		prefer 'Costa_Rica' to 'San_Jose' and 'Guyana' to 'Georgetown'.
+	Keep locations compact.  Use cities or small islands, not countries
+		or regions, so that any future time zone changes do not split
+		locations into different time zones.  E.g. prefer 'Paris'
+		to 'France', since France has had multiple time zones.
+	Use mainstream English spelling, e.g. prefer 'Rome' to 'Roma', and
+		prefer 'Athens' to the Greek 'Αθήνα' or the Romanized 'Athína'.
+		The POSIX file name restrictions encourage this rule.
+	Use the most populous among locations in a zone,
+		e.g. prefer 'Shanghai' to 'Beijing'.  Among locations with
+		similar populations, pick the best-known location,
+		e.g. prefer 'Rome' to 'Milan'.
+	Use the singular form, e.g. prefer 'Canary' to 'Canaries'.
+	Omit common suffixes like '_Islands' and '_City', unless that
+		would lead to ambiguity.  E.g. prefer 'Cayman' to
+		'Cayman_Islands' and 'Guatemala' to 'Guatemala_City',
+		but prefer 'Mexico_City' to 'Mexico' because the country
+		of Mexico has several time zones.
+	Use '_' to represent a space.
+	Omit '.' from abbreviations in names, e.g. prefer 'St_Helena'
+		to 'St._Helena'.
+	Do not change established names if they only marginally
+		violate the above rules.  For example, don't change
+		the existing name 'Rome' to 'Milan' merely because
+		Milan's population has grown to be somewhat greater
+		than Rome's.
+	If a name is changed, put its old spelling in the 'backward' file.
+		This means old spellings will continue to work.
+
+The file 'zone1970.tab' lists geographical locations used to name time
+zone rules.  It is intended to be an exhaustive list of names for
+geographic regions as described above; this is a subset of the names
+in the data.  Although a 'zone1970.tab' location's longitude
+corresponds to its LMT offset with one hour for every 15 degrees east
+longitude, this relationship is not exact.
+
+Older versions of this package used a different naming scheme,
+and these older names are still supported.
+See the file 'backward' for most of these older names
+(e.g., 'US/Eastern' instead of 'America/New_York').
+The other old-fashioned names still supported are
+'WET', 'CET', 'MET', and 'EET' (see the file 'europe').
+
+Older versions of this package defined legacy names that are
+incompatible with the first rule of location names, but which are
+still supported.  These legacy names are mostly defined in the file
+'etcetera'.  Also, the file 'backward' defines the legacy names
+'GMT0', 'GMT-0', 'GMT+0' and 'Canada/East-Saskatchewan', and the file
+'northamerica' defines the legacy names 'EST5EDT', 'CST6CDT',
+'MST7MDT', and 'PST8PDT'.
+
+Excluding 'backward' should not affect the other data.  If
+'backward' is excluded, excluding 'etcetera' should not affect the
+remaining data.
+
+
+----- Time zone abbreviations -----
+
+When this package is installed, it generates time zone abbreviations
+like 'EST' to be compatible with human tradition and POSIX.
+Here are the general rules used for choosing time zone abbreviations,
+in decreasing order of importance:
+
+	Use three or more characters that are ASCII alphanumerics or '+' or '-'.
+		Previous editions of this database also used characters like
+		' ' and '?', but these characters have a special meaning to
+		the shell and cause commands like
+			set `date`
+		to have unexpected effects.
+		Previous editions of this rule required upper-case letters,
+		but the Congressman who introduced Chamorro Standard Time
+		preferred "ChST", so lower-case letters are now allowed.
+		Also, POSIX from 2001 on relaxed the rule to allow '-', '+',
+		and alphanumeric characters from the portable character set
+		in the current locale.  In practice ASCII alphanumerics and
+		'+' and '-' are safe in all locales.
+
+		In other words, in the C locale the POSIX extended regular
+		expression [-+[:alnum:]]{3,} should match the abbreviation.
+		This guarantees that all abbreviations could have been
+		specified by a POSIX TZ string.
+
+	Use abbreviations that are in common use among English-speakers,
+		e.g. 'EST' for Eastern Standard Time in North America.
+		We assume that applications translate them to other languages
+		as part of the normal localization process; for example,
+		a French application might translate 'EST' to 'HNE'.
+
+	For zones whose times are taken from a city's longitude, use the
+		traditional xMT notation, e.g. 'PMT' for Paris Mean Time.
+		The only name like this in current use is 'GMT'.
+
+	Use 'LMT' for local mean time of locations before the introduction
+		of standard time; see "Scope of the tz database".
+
+	If there is no common English abbreviation, use numeric offsets like
+		-05 and +0830 that are generated by zic's %z notation.
+
+    [The remaining guidelines predate the introduction of %z.
+    They are problematic as they mean tz data entries invent
+    notation rather than record it.  These guidelines are now
+    deprecated and the plan is to gradually move to %z for
+    inhabited locations and to "-00" for uninhabited locations.]
+
+	If there is no common English abbreviation, abbreviate the English
+		translation of the usual phrase used by native speakers.
+		If this is not available or is a phrase mentioning the country
+		(e.g. "Cape Verde Time"), then:
+
+		When a country is identified with a single or principal zone,
+			append 'T' to the country's ISO	code, e.g. 'CVT' for
+			Cape Verde Time.  For summer time append 'ST';
+			for double summer time append 'DST'; etc.
+		Otherwise, take the first three letters of an English place
+			name identifying each zone and append 'T', 'ST', etc.
+			as before; e.g. 'VLAST' for VLAdivostok Summer Time.
+
+	Use UT (with time zone abbreviation '-00') for locations while
+		uninhabited.  The leading '-' is a flag that the time
+		zone is in some sense undefined; this notation is
+		derived from Internet RFC 3339.
+
+Application writers should note that these abbreviations are ambiguous
+in practice: e.g. 'CST' has a different meaning in China than
+it does in the United States.  In new applications, it's often better
+to use numeric UT offsets like '-0600' instead of time zone
+abbreviations like 'CST'; this avoids the ambiguity.
+
+
+----- Accuracy of the tz database -----
+
+The tz database is not authoritative, and it surely has errors.
+Corrections are welcome and encouraged; see the file CONTRIBUTING.
+Users requiring authoritative data should consult national standards
+bodies and the references cited in the database's comments.
+
+Errors in the tz database arise from many sources:
+
+ * The tz database predicts future time stamps, and current predictions
+   will be incorrect after future governments change the rules.
+   For example, if today someone schedules a meeting for 13:00 next
+   October 1, Casablanca time, and tomorrow Morocco changes its
+   daylight saving rules, software can mess up after the rule change
+   if it blithely relies on conversions made before the change.
+
+ * The pre-1970 entries in this database cover only a tiny sliver of how
+   clocks actually behaved; the vast majority of the necessary
+   information was lost or never recorded.  Thousands more zones would
+   be needed if the tz database's scope were extended to cover even
+   just the known or guessed history of standard time; for example,
+   the current single entry for France would need to split into dozens
+   of entries, perhaps hundreds.  And in most of the world even this
+   approach would be misleading due to widespread disagreement or
+   indifference about what times should be observed.  In her 2015 book
+   "The Global Transformation of Time, 1870-1950", Vanessa Ogle writes
+   "Outside of Europe and North America there was no system of time
+   zones at all, often not even a stable landscape of mean times,
+   prior to the middle decades of the twentieth century".  See:
+   Timothy Shenk, Booked: A Global History of Time. Dissent 2015-12-17
+   https://www.dissentmagazine.org/blog/booked-a-global-history-of-time-vanessa-ogle
+
+ * Most of the pre-1970 data entries come from unreliable sources, often
+   astrology books that lack citations and whose compilers evidently
+   invented entries when the true facts were unknown, without
+   reporting which entries were known and which were invented.
+   These books often contradict each other or give implausible entries,
+   and on the rare occasions when they are checked they are
+   typically found to be incorrect.
+
+ * For the UK the tz database relies on years of first-class work done by
+   Joseph Myers and others; see .
+   Other countries are not done nearly as well.
+
+ * Sometimes, different people in the same city would maintain clocks
+   that differed significantly.  Railway time was used by railroad
+   companies (which did not always agree with each other),
+   church-clock time was used for birth certificates, etc.
+   Often this was merely common practice, but sometimes it was set by law.
+   For example, from 1891 to 1911 the UT offset in France was legally
+   0:09:21 outside train stations and 0:04:21 inside.
+
+ * Although a named location in the tz database stands for the
+   containing region, its pre-1970 data entries are often accurate for
+   only a small subset of that region.  For example, Europe/London
+   stands for the United Kingdom, but its pre-1847 times are valid
+   only for locations that have London's exact meridian, and its 1847
+   transition to GMT is known to be valid only for the L&NW and the
+   Caledonian railways.
+
+ * The tz database does not record the earliest time for which a zone's
+   data entries are thereafter valid for every location in the region.
+   For example, Europe/London is valid for all locations in its
+   region after GMT was made the standard time, but the date of
+   standardization (1880-08-02) is not in the tz database, other than
+   in commentary.  For many zones the earliest time of validity is
+   unknown.
+
+ * The tz database does not record a region's boundaries, and in many
+   cases the boundaries are not known.  For example, the zone
+   America/Kentucky/Louisville represents a region around the city of
+   Louisville, the boundaries of which are unclear.
+
+ * Changes that are modeled as instantaneous transitions in the tz
+   database were often spread out over hours, days, or even decades.
+
+ * Even if the time is specified by law, locations sometimes
+   deliberately flout the law.
+
+ * Early timekeeping practices, even assuming perfect clocks, were
+   often not specified to the accuracy that the tz database requires.
+
+ * Sometimes historical timekeeping was specified more precisely
+   than what the tz database can handle.  For example, from 1909 to
+   1937 Netherlands clocks were legally UT +00:19:32.13, but the tz
+   database cannot represent the fractional second.
+
+ * Even when all the timestamp transitions recorded by the tz database
+   are correct, the tz rules that generate them may not faithfully
+   reflect the historical rules.  For example, from 1922 until World
+   War II the UK moved clocks forward the day following the third
+   Saturday in April unless that was Easter, in which case it moved
+   clocks forward the previous Sunday.  Because the tz database has no
+   way to specify Easter, these exceptional years are entered as
+   separate tz Rule lines, even though the legal rules did not change.
+
+ * The tz database models pre-standard time using the proleptic Gregorian
+   calendar and local mean time (LMT), but many people used other
+   calendars and other timescales.  For example, the Roman Empire used
+   the Julian calendar, and had 12 varying-length daytime hours with a
+   non-hour-based system at night.
+
+ * Early clocks were less reliable, and data entries do not represent
+   this unreliability.
+
+ * As for leap seconds, civil time was not based on atomic time before
+   1972, and we don't know the history of earth's rotation accurately
+   enough to map SI seconds to historical solar time to more than
+   about one-hour accuracy.  See: Morrison LV, Stephenson FR.
+   Historical values of the Earth's clock error Delta T and the
+   calculation of eclipses. J Hist Astron. 2004;35:327-36
+   ;
+   Historical values of the Earth's clock error. J Hist Astron. 2005;36:339
+   .
+
+ * The relationship between POSIX time (that is, UTC but ignoring leap
+   seconds) and UTC is not agreed upon after 1972.  Although the POSIX
+   clock officially stops during an inserted leap second, at least one
+   proposed standard has it jumping back a second instead; and in
+   practice POSIX clocks more typically either progress glacially during
+   a leap second, or are slightly slowed while near a leap second.
+
+ * The tz database does not represent how uncertain its information is.
+   Ideally it would contain information about when data entries are
+   incomplete or dicey.  Partial temporal knowledge is a field of
+   active research, though, and it's not clear how to apply it here.
+
+In short, many, perhaps most, of the tz database's pre-1970 and future
+time stamps are either wrong or misleading.  Any attempt to pass the
+tz database off as the definition of time should be unacceptable to
+anybody who cares about the facts.  In particular, the tz database's
+LMT offsets should not be considered meaningful, and should not prompt
+creation of zones merely because two locations differ in LMT or
+transitioned to standard time at different dates.
+
+
+----- Time and date functions -----
+
+The tz code contains time and date functions that are upwards
+compatible with those of POSIX.
+
+POSIX has the following properties and limitations.
+
+*	In POSIX, time display in a process is controlled by the
+	environment variable TZ.  Unfortunately, the POSIX TZ string takes
+	a form that is hard to describe and is error-prone in practice.
+	Also, POSIX TZ strings can't deal with other (for example, Israeli)
+	daylight saving time rules, or situations where more than two
+	time zone abbreviations are used in an area.
+
+	The POSIX TZ string takes the following form:
+
+		stdoffset[dst[offset][,date[/time],date[/time]]]
+
+	where:
+
+	std and dst
+		are 3 or more characters specifying the standard
+		and daylight saving time (DST) zone names.
+		Starting with POSIX.1-2001, std and dst may also be
+		in a quoted form like ""; this allows
+		"+" and "-" in the names.
+	offset
+		is of the form '[+-]hh:[mm[:ss]]' and specifies the
+		offset west of UT.  'hh' may be a single digit; 0<=hh<=24.
+		The default DST offset is one hour ahead of standard time.
+	date[/time],date[/time]
+		specifies the beginning and end of DST.  If this is absent,
+		the system supplies its own rules for DST, and these can
+		differ from year to year; typically US DST rules are used.
+	time
+		takes the form 'hh:[mm[:ss]]' and defaults to 02:00.
+		This is the same format as the offset, except that a
+		leading '+' or '-' is not allowed.
+	date
+		takes one of the following forms:
+		Jn (1<=n<=365)
+			origin-1 day number not counting February 29
+		n (0<=n<=365)
+			origin-0 day number counting February 29 if present
+		Mm.n.d (0[Sunday]<=d<=6[Saturday], 1<=n<=5, 1<=m<=12)
+			for the dth day of week n of month m of the year,
+			where week 1 is the first week in which day d appears,
+			and '5' stands for the last week in which day d appears
+			(which may be either the 4th or 5th week).
+			Typically, this is the only useful form;
+			the n and Jn forms are rarely used.
+
+	Here is an example POSIX TZ string, for US Pacific time using rules
+	appropriate from 1987 through 2006:
+
+		TZ='PST8PDT,M4.1.0/02:00,M10.5.0/02:00'
+
+	This POSIX TZ string is hard to remember, and mishandles time stamps
+	before 1987 and after 2006.  With this package you can use this
+	instead:
+
+		TZ='America/Los_Angeles'
+
+*	POSIX does not define the exact meaning of TZ values like "EST5EDT".
+	Typically the current US DST rules are used to interpret such values,
+	but this means that the US DST rules are compiled into each program
+	that does time conversion.  This means that when US time conversion
+	rules change (as in the United States in 1987), all programs that
+	do time conversion must be recompiled to ensure proper results.
+
+*	The TZ environment variable is process-global, which makes it hard
+	to write efficient, thread-safe applications that need access
+	to multiple time zones.
+
+*	In POSIX, there's no tamper-proof way for a process to learn the
+	system's best idea of local wall clock.  (This is important for
+	applications that an administrator wants used only at certain times -
+	without regard to whether the user has fiddled the "TZ" environment
+	variable.  While an administrator can "do everything in UTC" to get
+	around the problem, doing so is inconvenient and precludes handling
+	daylight saving time shifts - as might be required to limit phone
+	calls to off-peak hours.)
+
+*	POSIX provides no convenient and efficient way to determine the UT
+	offset and time zone abbreviation of arbitrary time stamps,
+	particularly for time zone settings that do not fit into the
+	POSIX model.
+
+*	POSIX requires that systems ignore leap seconds.
+
+*	The tz code attempts to support all the time_t implementations
+	allowed by POSIX.  The time_t type represents a nonnegative count of
+	seconds since 1970-01-01 00:00:00 UTC, ignoring leap seconds.
+	In practice, time_t is usually a signed 64- or 32-bit integer; 32-bit
+	signed time_t values stop working after 2038-01-19 03:14:07 UTC, so
+	new implementations these days typically use a signed 64-bit integer.
+	Unsigned 32-bit integers are used on one or two platforms,
+	and 36-bit and 40-bit integers are also used occasionally.
+	Although earlier POSIX versions allowed time_t to be a
+	floating-point type, this was not supported by any practical
+	systems, and POSIX.1-2013 and the tz code both require time_t
+	to be an integer type.
+
+These are the extensions that have been made to the POSIX functions:
+
+*	The "TZ" environment variable is used in generating the name of a file
+	from which time zone information is read (or is interpreted a la
+	POSIX); "TZ" is no longer constrained to be a three-letter time zone
+	name followed by a number of hours and an optional three-letter
+	daylight time zone name.  The daylight saving time rules to be used
+	for a particular time zone are encoded in the time zone file;
+	the format of the file allows U.S., Australian, and other rules to be
+	encoded, and allows for situations where more than two time zone
+	abbreviations are used.
+
+	It was recognized that allowing the "TZ" environment variable to
+	take on values such as "America/New_York" might cause "old" programs
+	(that expect "TZ" to have a certain form) to operate incorrectly;
+	consideration was given to using some other environment variable
+	(for example, "TIMEZONE") to hold the string used to generate the
+	time zone information file name.  In the end, however, it was decided
+	to continue using "TZ": it is widely used for time zone purposes;
+	separately maintaining both "TZ" and "TIMEZONE" seemed a nuisance;
+	and systems where "new" forms of "TZ" might cause problems can simply
+	use TZ values such as "EST5EDT" which can be used both by
+	"new" programs (a la POSIX) and "old" programs (as zone names and
+	offsets).
+
+*	The code supports platforms with a UT offset member in struct tm,
+	e.g., tm_gmtoff.
+
+*	The code supports platforms with a time zone abbreviation member in
+	struct tm, e.g., tm_zone.
+
+*	Since the "TZ" environment variable can now be used to control time
+	conversion, the "daylight" and "timezone" variables are no longer
+	needed.  (These variables are defined and set by "tzset"; however, their
+	values will not be used by "localtime.")
+
+*	Functions tzalloc, tzfree, localtime_rz, and mktime_z for
+	more-efficient thread-safe applications that need to use
+	multiple time zones.  The tzalloc and tzfree functions
+	allocate and free objects of type timezone_t, and localtime_rz
+	and mktime_z are like localtime_r and mktime with an extra
+	timezone_t argument.  The functions were inspired by NetBSD.
+
+*	A function "tzsetwall" has been added to arrange for the system's
+	best approximation to local wall clock time to be delivered by
+	subsequent calls to "localtime."  Source code for portable
+	applications that "must" run on local wall clock time should call
+	"tzsetwall();" if such code is moved to "old" systems that don't
+	provide tzsetwall, you won't be able to generate an executable program.
+	(These time zone functions also arrange for local wall clock time to be
+	used if tzset is called - directly or indirectly - and there's no "TZ"
+	environment variable; portable applications should not, however, rely
+	on this behavior since it's not the way SVR2 systems behave.)
+
+*	Negative time_t values are supported, on systems where time_t is signed.
+
+*	These functions can account for leap seconds, thanks to Bradley White.
+
+Points of interest to folks with other systems:
+
+*	Code compatible with this package is already part of many platforms,
+	including GNU/Linux, Android, the BSDs, Chromium OS, Cygwin, AIX, iOS,
+	BlackBery 10, macOS, Microsoft Windows, OpenVMS, and Solaris.
+	On such hosts, the primary use of this package
+	is to update obsolete time zone rule tables.
+	To do this, you may need to compile the time zone compiler
+	'zic' supplied with this package instead of using the system 'zic',
+	since the format of zic's input is occasionally extended,
+	and a platform may still be shipping an older zic.
+
+*	The UNIX Version 7 "timezone" function is not present in this package;
+	it's impossible to reliably map timezone's arguments (a "minutes west
+	of GMT" value and a "daylight saving time in effect" flag) to a
+	time zone abbreviation, and we refuse to guess.
+	Programs that in the past used the timezone function may now examine
+	tzname[localtime(&clock)->tm_isdst] to learn the correct time
+	zone abbreviation to use.  Alternatively, use
+	localtime(&clock)->tm_zone if this has been enabled.
+
+*	The 4.2BSD gettimeofday function is not used in this package.
+	This formerly let users obtain the current UTC offset and DST flag,
+	but this functionality was removed in later versions of BSD.
+
+*	In SVR2, time conversion fails for near-minimum or near-maximum
+	time_t values when doing conversions for places that don't use UT.
+	This package takes care to do these conversions correctly.
+	A comment in the source code tells how to get compatibly wrong
+	results.
+
+The functions that are conditionally compiled if STD_INSPIRED is defined
+should, at this point, be looked on primarily as food for thought.  They are
+not in any sense "standard compatible" - some are not, in fact, specified in
+*any* standard.  They do, however, represent responses of various authors to
+standardization proposals.
+
+Other time conversion proposals, in particular the one developed by folks at
+Hewlett Packard, offer a wider selection of functions that provide capabilities
+beyond those provided here.  The absence of such functions from this package
+is not meant to discourage the development, standardization, or use of such
+functions.  Rather, their absence reflects the decision to make this package
+contain valid extensions to POSIX, to ensure its broad acceptability.  If
+more powerful time conversion functions can be standardized, so much the
+better.
+
+
+----- Interface stability -----
+
+The tz code and data supply the following interfaces:
+
+ * A set of zone names as per "Names of time zone rules" above.
+
+ * Library functions described in "Time and date functions" above.
+
+ * The programs tzselect, zdump, and zic, documented in their man pages.
+
+ * The format of zic input files, documented in the zic man page.
+
+ * The format of zic output files, documented in the tzfile man page.
+
+ * The format of zone table files, documented in zone1970.tab.
+
+ * The format of the country code file, documented in iso3166.tab.
+
+When these interfaces are changed, an effort is made to preserve
+backward compatibility.  For example, tz data files typically do not
+rely on recently-added zic features, so that users can run older zic
+versions to process newer data files.
+
+Interfaces not listed above are less stable.  For example, users
+should not rely on particular UT offsets or abbreviations for time
+stamps, as data entries are often based on guesswork and these guesses
+may be corrected or improved.
+
+
+----- Calendrical issues -----
+
+Calendrical issues are a bit out of scope for a time zone database,
+but they indicate the sort of problems that we would run into if we
+extended the time zone database further into the past.  An excellent
+resource in this area is Nachum Dershowitz and Edward M. Reingold,
+Calendrical Calculations: Third Edition, Cambridge University Press (2008)
+.
+Other information and sources are given below.  They sometimes disagree.
+
+
+France
+
+Gregorian calendar adopted 1582-12-20.
+French Revolutionary calendar used 1793-11-24 through 1805-12-31,
+and (in Paris only) 1871-05-06 through 1871-05-23.
+
+
+Russia
+
+From Chris Carrier (1996-12-02):
+On 1929-10-01 the Soviet Union instituted an "Eternal Calendar"
+with 30-day months plus 5 holidays, with a 5-day week.
+On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
+Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
+reverted to the 7-day week.  With the 6-day week the usual days
+off were the 6th, 12th, 18th, 24th and 30th of the month.
+(Source: Evitiar Zerubavel, _The Seven Day Circle_)
+
+
+Mark Brader reported a similar story in "The Book of Calendars", edited
+by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377.  But:
+
+From: Petteri Sulonen (via Usenet)
+Date: 14 Jan 1999 00:00:00 GMT
+...
+
+If your source is correct, how come documents between 1929 and 1940 were
+still dated using the conventional, Gregorian calendar?
+
+I can post a scan of a document dated December 1, 1934, signed by
+Yenukidze, the secretary, on behalf of Kalinin, the President of the
+Executive Committee of the Supreme Soviet, if you like.
+
+
+
+Sweden (and Finland)
+
+From: Mark Brader
+Subject: Re: Gregorian reform - a part of locale?
+
+Date: 1996-07-06
+
+In 1700, Denmark made the transition from Julian to Gregorian.  Sweden
+decided to *start* a transition in 1700 as well, but rather than have one of
+those unsightly calendar gaps :-), they simply decreed that the next leap
+year after 1696 would be in 1744 - putting the whole country on a calendar
+different from both Julian and Gregorian for a period of 40 years.
+
+However, in 1704 something went wrong and the plan was not carried through;
+they did, after all, have a leap year that year.  And one in 1708.  In 1712
+they gave it up and went back to Julian, putting 30 days in February that
+year!...
+
+Then in 1753, Sweden made the transition to Gregorian in the usual manner,
+getting there only 13 years behind the original schedule.
+
+(A previous posting of this story was challenged, and Swedish readers
+produced the following references to support it: "Tideräkning och historia"
+by Natanael Beckman (1924) and "Tid, en bok om tideräkning och
+kalenderväsen" by Lars-Olof Lodén (1968).
+
+
+Grotefend's data
+
+From: "Michael Palmer" [with one obvious typo fixed]
+Subject: Re: Gregorian Calendar (was Re: Another FHC related question
+Newsgroups: soc.genealogy.german
+Date: Tue, 9 Feb 1999 02:32:48 -800
+...
+
+The following is a(n incomplete) listing, arranged chronologically, of
+European states, with the date they converted from the Julian to the
+Gregorian calendar:
+
+04/15 Oct 1582 - Italy (with exceptions), Spain, Portugal, Poland (Roman
+                 Catholics and Danzig only)
+09/20 Dec 1582 - France, Lorraine
+
+21 Dec 1582/
+   01 Jan 1583 - Holland, Brabant, Flanders, Hennegau
+10/21 Feb 1583 - bishopric of Liege (Lüttich)
+13/24 Feb 1583 - bishopric of Augsburg
+04/15 Oct 1583 - electorate of Trier
+05/16 Oct 1583 - Bavaria, bishoprics of Freising, Eichstedt, Regensburg,
+                 Salzburg, Brixen
+13/24 Oct 1583 - Austrian Oberelsaß and Breisgau
+20/31 Oct 1583 - bishopric of Basel
+02/13 Nov 1583 - duchy of Jülich-Berg
+02/13 Nov 1583 - electorate and city of Köln
+04/15 Nov 1583 - bishopric of Würzburg
+11/22 Nov 1583 - electorate of Mainz
+16/27 Nov 1583 - bishopric of Strassburg and the margraviate of Baden
+17/28 Nov 1583 - bishopric of Münster and duchy of Cleve
+14/25 Dec 1583 - Steiermark
+
+06/17 Jan 1584 - Austria and Bohemia
+11/22 Jan 1584 - Lucerne, Uri, Schwyz, Zug, Freiburg, Solothurn
+12/23 Jan 1584 - Silesia and the Lausitz
+22 Jan/
+   02 Feb 1584 - Hungary (legally on 21 Oct 1587)
+      Jun 1584 - Unterwalden
+01/12 Jul 1584 - duchy of Westfalen
+
+16/27 Jun 1585 - bishopric of Paderborn
+
+14/25 Dec 1590 - Transylvania
+
+22 Aug/
+   02 Sep 1612 - duchy of Prussia
+
+13/24 Dec 1614 - Pfalz-Neuburg
+
+          1617 - duchy of Kurland (reverted to the Julian calendar in
+                 1796)
+
+          1624 - bishopric of Osnabrück
+
+          1630 - bishopric of Minden
+
+15/26 Mar 1631 - bishopric of Hildesheim
+
+          1655 - Kanton Wallis
+
+05/16 Feb 1682 - city of Strassburg
+
+18 Feb/
+   01 Mar 1700 - Protestant Germany (including Swedish possessions in
+                 Germany), Denmark, Norway
+30 Jun/
+   12 Jul 1700 - Gelderland, Zutphen
+10 Nov/
+   12 Dec 1700 - Utrecht, Overijssel
+
+31 Dec 1700/
+   12 Jan 1701 - Friesland, Groningen, Zürich, Bern, Basel, Geneva,
+                 Turgau, and Schaffhausen
+
+          1724 - Glarus, Appenzell, and the city of St. Gallen
+
+01 Jan 1750    - Pisa and Florence
+
+02/14 Sep 1752 - Great Britain
+
+17 Feb/
+   01 Mar 1753 - Sweden
+
+1760-1812      - Graubünden
+
+The Russian empire (including Finland and the Baltic states) did not
+convert to the Gregorian calendar until the Soviet revolution of 1917.
+
+Source: H. Grotefend, _Taschenbuch der Zeitrechnung des deutschen
+Mittelalters und der Neuzeit_, herausgegeben von Dr. O. Grotefend
+(Hannover: Hahnsche Buchhandlung, 1941), pp. 26-28.
+
+
+----- Time and time zones on Mars -----
+
+Some people's work schedules use Mars time.  Jet Propulsion Laboratory
+(JPL) coordinators have kept Mars time on and off at least since 1997
+for the Mars Pathfinder mission.  Some of their family members have
+also adapted to Mars time.  Dozens of special Mars watches were built
+for JPL workers who kept Mars time during the Mars Exploration
+Rovers mission (2004).  These timepieces look like normal Seikos and
+Citizens but use Mars seconds rather than terrestrial seconds.
+
+A Mars solar day is called a "sol" and has a mean period equal to
+about 24 hours 39 minutes 35.244 seconds in terrestrial time.  It is
+divided into a conventional 24-hour clock, so each Mars second equals
+about 1.02749125 terrestrial seconds.
+
+The prime meridian of Mars goes through the center of the crater
+Airy-0, named in honor of the British astronomer who built the
+Greenwich telescope that defines Earth's prime meridian.  Mean solar
+time on the Mars prime meridian is called Mars Coordinated Time (MTC).
+
+Each landed mission on Mars has adopted a different reference for
+solar time keeping, so there is no real standard for Mars time zones.
+For example, the Mars Exploration Rover project (2004) defined two
+time zones "Local Solar Time A" and "Local Solar Time B" for its two
+missions, each zone designed so that its time equals local true solar
+time at approximately the middle of the nominal mission.  Such a "time
+zone" is not particularly suited for any application other than the
+mission itself.
+
+Many calendars have been proposed for Mars, but none have achieved
+wide acceptance.  Astronomers often use Mars Sol Date (MSD) which is a
+sequential count of Mars solar days elapsed since about 1873-12-29
+12:00 GMT.
+
+The tz database does not currently support Mars time, but it is
+documented here in the hopes that support will be added eventually.
+
+Sources:
+
+Michael Allison and Robert Schmunk,
+"Technical Notes on Mars Solar Time as Adopted by the Mars24 Sunclock"
+ (2012-08-08).
+
+Jia-Rui Chong, "Workdays Fit for a Martian", Los Angeles Times
+
+(2004-01-14), pp A1, A20-A21.
+
+Tom Chmielewski, "Jet Lag Is Worse on Mars", The Atlantic (2015-02-26)
+
+
+-----
+
+This file is in the public domain, so clarified as of 2009-05-17 by
+Arthur David Olson.
+
+-----
+Local Variables:
+coding: utf-8
+End:
diff --git a/antarctica b/antarctica
index 0995835752c1..6da1aef87f17 100644
--- a/antarctica
+++ b/antarctica
@@ -64,13 +64,18 @@
 # Background:
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
 
+# From Steffen Thorsen (2016-10-28):
+# Australian Antarctica Division informed us that Casey changed time
+# zone to UTC+11 in "the morning of 22nd October 2016".
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Casey	0	-	-00	1969
 			8:00	-	+08	2009 Oct 18  2:00
 			11:00	-	+11	2010 Mar  5  2:00
 			8:00	-	+08	2011 Oct 28  2:00
 			11:00	-	+11	2012 Feb 21 17:00u
-			8:00	-	+08
+			8:00	-	+08	2016 Oct 22
+			11:00	-	+11
 Zone Antarctica/Davis	0	-	-00	1957 Jan 13
 			7:00	-	+07	1964 Nov
 			0	-	-00	1969 Feb
diff --git a/asia b/asia
index b2c993085319..67164b3d8930 100644
--- a/asia
+++ b/asia
@@ -771,9 +771,19 @@ Zone	Asia/Macau	7:34:20 -	LMT	1912 Jan  1
 ###############################################################################
 
 # Cyprus
-#
+
 # Milne says the Eastern Telegraph Company used 2:14:00.  Stick with LMT.
+# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+
+# From Paul Eggert (2016-09-09):
+# Yesterday's Cyprus Mail reports that Northern Cyprus followed Turkey's
+# lead and switched from +02/+03 to +03 year-round.
+# http://cyprus-mail.com/2016/09/08/two-time-zones-cyprus-turkey-will-not-turn-clocks-back-next-month/
 #
+# From Even Scharning (2016-10-31):
+# Looks like the time zone split in Cyprus went through last night.
+# http://cyprus-mail.com/2016/10/30/cyprus-new-division-two-time-zones-now-reality/
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Cyprus	1975	only	-	Apr	13	0:00	1:00	S
 Rule	Cyprus	1975	only	-	Oct	12	0:00	0	-
@@ -788,7 +798,10 @@ Rule	Cyprus	1981	1998	-	Mar	lastSun	0:00	1:00	S
 Zone	Asia/Nicosia	2:13:28 -	LMT	1921 Nov 14
 			2:00	Cyprus	EE%sT	1998 Sep
 			2:00	EUAsia	EE%sT
-# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+Zone	Asia/Famagusta	2:15:48	-	LMT	1921 Nov 14
+			2:00	Cyprus	EE%sT	1998 Sep
+			2:00	EUAsia	EE%sT	2016 Sep  8
+			3:00	-	+03
 
 # Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72.
 # However, for various reasons many users expect to find it under Europe.
diff --git a/australasia b/australasia
index 85d363295b88..0bca53e2ee3f 100644
--- a/australasia
+++ b/australasia
@@ -702,11 +702,13 @@ Rule	Tonga	1999	only	-	Oct	 7	2:00s	1:00	S
 Rule	Tonga	2000	only	-	Mar	19	2:00s	0	-
 Rule	Tonga	2000	2001	-	Nov	Sun>=1	2:00	1:00	S
 Rule	Tonga	2001	2002	-	Jan	lastSun	2:00	0	-
+Rule	Tonga	2016	max	-	Nov	Sun>=1	2:00	1:00	S
+Rule	Tonga	2017	max	-	Jan	Sun>=15	3:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Tongatapu	12:19:20 -	LMT	1901
-			12:20	-	TOT	1941 # Tonga Time
-			13:00	-	TOT	1999
-			13:00	Tonga	TO%sT
+			12:20	-	+1220	1941
+			13:00	-	+13	1999
+			13:00	Tonga	+13/+14
 
 # Tuvalu
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1712,9 +1714,17 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # of January the standard time in the Kingdom shall be moved backward by one
 # hour to 1:00am.
 
-# From Pulu 'Anau (2002-11-05):
+# From Pulu ʻAnau (2002-11-05):
 # The law was for 3 years, supposedly to get renewed.  It wasn't.
 
+# From Pulu ʻAnau (2016-10-27):
+# http://mic.gov.to/news-today/press-releases/6375-daylight-saving-set-to-run-from-6-november-2016-to-15-january-2017
+# Cannot find anyone who knows the rules, has seen the duration or has seen
+# the cabinet decision, but it appears we are following Fiji's rule set.
+#
+# From Tim Parenti (2016-10-26):
+# Assume Tonga will observe DST from the first Sunday in November at 02:00
+# through the third Sunday in January at 03:00, like Fiji, for now.
 
 # Wake
 
diff --git a/backzone b/backzone
new file mode 100644
index 000000000000..4a5085f42295
--- /dev/null
+++ b/backzone
@@ -0,0 +1,677 @@
+# Zones that go back beyond the scope of the tz database
+
+# This file is in the public domain.
+
+# This file is by no means authoritative; if you think you know
+# better, go ahead and edit it (and please send any changes to
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
+
+
+# From Paul Eggert (2014-10-31):
+
+# This file contains data outside the normal scope of the tz database,
+# in that its zones do not differ from normal tz zones after 1970.
+# Links in this file point to zones in this file, superseding links in
+# the file 'backward'.
+
+# Although zones in this file may be of some use for analyzing
+# pre-1970 time stamps, they are less reliable, cover only a tiny
+# sliver of the pre-1970 era, and cannot feasibly be improved to cover
+# most of the era.  Because the zones are out of normal scope for the
+# database, less effort is put into maintaining this file.  Many of
+# the zones were formerly in other source files, but were removed or
+# replaced by links as their data entries were questionable and/or they
+# differed from other zones only in pre-1970 time stamps.
+
+# Unless otherwise specified, the source for data through 1990 is:
+# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
+# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
+
+# This file is not intended to be compiled standalone, as it
+# assumes rules from other files.  In the tz distribution, use
+# 'make PACKRATDATA=backzone zones' to compile and install this file.
+
+# Zones are sorted by zone name.  Each zone is preceded by the
+# name of the country that the zone is in, along with any other
+# commentary and rules associated with the entry.
+#
+# As explained in the zic man page, the zone columns are:
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+
+# Ethiopia
+# From Paul Eggert (2014-07-31):
+# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
+# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
+# 02:00 or 14:00.  Keep this in mind when you ask the time in Amharic.
+#
+# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
+# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
+# 1890, and that they switched to 3:00 on 1936-05-05.  Perhaps 38E50
+# was for Adis Dera.  Quite likely the Shanks data entries are wrong
+# anyway.
+Zone Africa/Addis_Ababa	2:34:48 -	LMT	1870
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
+			3:00	-	EAT
+
+# Eritrea
+Zone	Africa/Asmara	2:35:32 -	LMT	1870
+			2:35:32	-	AMT	1890        # Asmara Mean Time
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
+			3:00	-	EAT
+Link Africa/Asmara Africa/Asmera
+
+# Mali (southern)
+Zone	Africa/Bamako	-0:32:00 -	LMT	1912
+			 0:00	-	GMT	1934 Feb 26
+			-1:00	-	WAT	1960 Jun 20
+			 0:00	-	GMT
+
+# Central African Republic
+Zone	Africa/Bangui	1:14:20	-	LMT	1912
+			1:00	-	WAT
+
+# Gambia
+Zone	Africa/Banjul	-1:06:36 -	LMT	1912
+			-1:06:36 -	BMT	1935 # Banjul Mean Time
+			-1:00	-	WAT	1964
+			 0:00	-	GMT
+
+# Malawi
+Zone	Africa/Blantyre	2:20:00 -	LMT	1903 Mar
+			2:00	-	CAT
+
+# Republic of the Congo
+Zone Africa/Brazzaville	1:01:08 -	LMT	1912
+			1:00	-	WAT
+
+# Burundi
+Zone Africa/Bujumbura	1:57:28	-	LMT	1890
+			2:00	-	CAT
+
+# Guinea
+Zone	Africa/Conakry	-0:54:52 -	LMT	1912
+			 0:00	-	GMT	1934 Feb 26
+			-1:00	-	WAT	1960
+			 0:00	-	GMT
+
+# Senegal
+Zone	Africa/Dakar	-1:09:44 -	LMT	1912
+			-1:00	-	WAT	1941 Jun
+			 0:00	-	GMT
+
+# Tanzania
+Zone Africa/Dar_es_Salaam 2:37:08 -	LMT	1931
+			3:00	-	EAT	1948
+			2:45	-	BEAUT	1961
+			3:00	-	EAT
+
+# Djibouti
+Zone	Africa/Djibouti	2:52:36 -	LMT	1911 Jul
+			3:00	-	EAT
+
+# Cameroon
+# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
+Zone	Africa/Douala	0:38:48	-	LMT	1912
+			1:00	-	WAT
+# Sierra Leone
+# From Paul Eggert (2014-08-12):
+# The following table is from Shanks & Pottenger, but it can't be right.
+# Whitman gives Mar 31 - Aug 31 for 1931 on.
+# The International Hydrographic Bulletin, 1932-33, p 63 says that
+# Sierra Leone would advance its clocks by 20 minutes on 1933-10-01.
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	SL	1935	1942	-	Jun	 1	0:00	0:40	SLST
+Rule	SL	1935	1942	-	Oct	 1	0:00	0	WAT
+Rule	SL	1957	1962	-	Jun	 1	0:00	1:00	SLST
+Rule	SL	1957	1962	-	Sep	 1	0:00	0	GMT
+Zone	Africa/Freetown	-0:53:00 -	LMT	1882
+			-0:53:00 -	FMT	1913 Jun # Freetown Mean Time
+			-1:00	SL	%s	1957
+			 0:00	SL	%s
+
+# Botswana
+# From Paul Eggert (2013-02-21):
+# Milne says they were regulated by the Cape Town Signal in 1899;
+# assume they switched to 2:00 when Cape Town did.
+Zone	Africa/Gaborone	1:43:40 -	LMT	1885
+			1:30	-	SAST	1903 Mar
+			2:00	-	CAT	1943 Sep 19  2:00
+			2:00	1:00	CAST	1944 Mar 19  2:00
+			2:00	-	CAT
+
+# Zimbabwe
+Zone	Africa/Harare	2:04:12 -	LMT	1903 Mar
+			2:00	-	CAT
+
+# South Sudan
+Zone	Africa/Juba	2:06:24 -	LMT	1931
+			2:00	Sudan	CA%sT	2000 Jan 15 12:00
+			3:00	-	EAT
+
+# Uganda
+Zone	Africa/Kampala	2:09:40 -	LMT	1928 Jul
+			3:00	-	EAT	1930
+			2:30	-	BEAT	1948
+			2:45	-	BEAUT	1957
+			3:00	-	EAT
+
+# Rwanda
+Zone	Africa/Kigali	2:00:16 -	LMT	1935 Jun
+			2:00	-	CAT
+
+# Democratic Republic of the Congo (west)
+Zone Africa/Kinshasa	1:01:12 -	LMT	1897 Nov  9
+			1:00	-	WAT
+
+# Gabon
+Zone Africa/Libreville	0:37:48 -	LMT	1912
+			1:00	-	WAT
+
+# Togo
+Zone	Africa/Lome	0:04:52 -	LMT	1893
+			0:00	-	GMT
+
+# Angola
+#
+# Shanks gives 1911-05-26 for the transition to WAT,
+# evidently confusing the date of the Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# with the date that it took effect, namely 1912-01-01.
+#
+Zone	Africa/Luanda	0:52:56	-	LMT	1892
+			0:52:04	-	AOT	1912 Jan  1 # Angola Time
+			1:00	-	WAT
+
+# Democratic Republic of the Congo (east)
+Zone Africa/Lubumbashi	1:49:52 -	LMT	1897 Nov 9
+			2:00	-	CAT
+
+# Zambia
+Zone	Africa/Lusaka	1:53:08 -	LMT	1903 Mar
+			2:00	-	CAT
+
+# Equatorial Guinea
+#
+# Although Shanks says that Malabo switched from UT +00 to +01 on 1963-12-15,
+# a Google Books search says that London Calling, Issues 432-465 (1948), p 19,
+# says that Spanish Guinea was at +01 back then.  The Shanks data entries
+# are most likely wrong, but we have nothing better; use them here for now.
+#
+Zone	Africa/Malabo	0:35:08 -	LMT	1912
+			0:00	-	GMT	1963 Dec 15
+			1:00	-	WAT
+
+# Lesotho
+Zone	Africa/Maseru	1:50:00 -	LMT	1903 Mar
+			2:00	-	SAST	1943 Sep 19  2:00
+			2:00	1:00	SAST	1944 Mar 19  2:00
+			2:00	-	SAST
+
+# Swaziland
+Zone	Africa/Mbabane	2:04:24 -	LMT	1903 Mar
+			2:00	-	SAST
+
+# Somalia
+Zone Africa/Mogadishu	3:01:28 -	LMT	1893 Nov
+			3:00	-	EAT	1931
+			2:30	-	BEAT	1957
+			3:00	-	EAT
+
+# Niger
+Zone	Africa/Niamey	 0:08:28 -	LMT	1912
+			-1:00	-	WAT	1934 Feb 26
+			 0:00	-	GMT	1960
+			 1:00	-	WAT
+
+# Mauritania
+Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
+			 0:00	-	GMT	1934 Feb 26
+			-1:00	-	WAT	1960 Nov 28
+			 0:00	-	GMT
+
+# Burkina Faso
+Zone Africa/Ouagadougou	-0:06:04 -	LMT	1912
+			 0:00	-	GMT
+
+# Benin
+# Whitman says they switched to 1:00 in 1946, not 1934;
+# go with Shanks & Pottenger.
+Zone Africa/Porto-Novo	0:10:28	-	LMT	1912 Jan  1
+			0:00	-	GMT	1934 Feb 26
+			1:00	-	WAT
+
+# São Tomé and Príncipe
+Zone	Africa/Sao_Tome	 0:26:56 -	LMT	1884
+			-0:36:32 -	LMT	1912 # Lisbon Mean Time
+			 0:00	-	GMT
+
+# Mali (northern)
+Zone	Africa/Timbuktu	-0:12:04 -	LMT	1912
+			 0:00	-	GMT
+
+# Anguilla
+Zone America/Anguilla	-4:12:16 -	LMT	1912 Mar  2
+			-4:00	-	AST
+
+# Antigua and Barbuda
+Zone	America/Antigua	-4:07:12 -	LMT	1912 Mar 2
+			-5:00	-	EST	1951
+			-4:00	-	AST
+
+# Chubut, Argentina
+# The name "Comodoro Rivadavia" exceeds the 14-byte POSIX limit.
+Zone America/Argentina/ComodRivadavia -4:30:00 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May
+			-4:00	-	ART	1930 Dec
+			-4:00	Arg	AR%sT	1969 Oct  5
+			-3:00	Arg	AR%sT	1991 Mar  3
+			-4:00	-	WART	1991 Oct 20
+			-3:00	Arg	AR%sT	1999 Oct  3
+			-4:00	Arg	AR%sT	2000 Mar  3
+			-3:00	-	ART	2004 Jun  1
+			-4:00	-	WART	2004 Jun 20
+			-3:00	-	ART
+
+# Aruba
+Zone	America/Aruba	-4:40:24 -	LMT	1912 Feb 12 # Oranjestad
+			-4:30	-	ANT	1965 # Netherlands Antilles Time
+			-4:00	-	AST
+
+# Cayman Is
+Zone	America/Cayman	-5:25:32 -	LMT	1890     # Georgetown
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
+			-5:00	-	EST
+
+# Canada
+Zone America/Coral_Harbour -5:32:40 -	LMT	1884
+			-5:00	NT_YK	E%sT	1946
+			-5:00	-	EST
+
+# Dominica
+Zone America/Dominica	-4:05:36 -	LMT	1911 Jul  1  0:01 # Roseau
+			-4:00	-	AST
+
+# Baja California
+# See 'northamerica' for why this entry is here rather than there.
+Zone America/Ensenada	-7:46:28 -	LMT	1922 Jan  1  0:13:32
+			-8:00	-	PST	1927 Jun 10 23:00
+			-7:00	-	MST	1930 Nov 16
+			-8:00	-	PST	1942 Apr
+			-7:00	-	MST	1949 Jan 14
+			-8:00	-	PST	1996
+			-8:00	Mexico	P%sT
+
+# Grenada
+Zone	America/Grenada	-4:07:00 -	LMT	1911 Jul # St George's
+			-4:00	-	AST
+
+# Guadeloupe
+Zone America/Guadeloupe	-4:06:08 -	LMT	1911 Jun  8 # Pointe-à-Pitre
+			-4:00	 -	AST
+
+# Canada
+#
+# From Paul Eggert (2015-03-24):
+# Since 1970 most of Quebec has been like Toronto; see
+# America/Toronto.  However, earlier versions of the tz database
+# mistakenly relied on data from Shanks & Pottenger saying that Quebec
+# differed from Ontario after 1970, and the following rules and zone
+# were created for most of Quebec from the incorrect Shanks &
+# Pottenger data.  The post-1970 entries have been corrected, but the
+# pre-1970 entries are unchecked and probably have errors.
+#
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
+Rule	Mont	1917	only	-	Apr	24	0:00	0	S
+Rule	Mont	1919	only	-	Mar	31	2:30	1:00	D
+Rule	Mont	1919	only	-	Oct	25	2:30	0	S
+Rule	Mont	1920	only	-	May	 2	2:30	1:00	D
+Rule	Mont	1920	1922	-	Oct	Sun>=1	2:30	0	S
+Rule	Mont	1921	only	-	May	 1	2:00	1:00	D
+Rule	Mont	1922	only	-	Apr	30	2:00	1:00	D
+Rule	Mont	1924	only	-	May	17	2:00	1:00	D
+Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
+Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
+Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
+Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
+Rule	Mont	1938	1940	-	Apr	lastSun	0:00	1:00	D
+Rule	Mont	1938	1939	-	Sep	lastSun	0:00	0	S
+Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
+Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
+Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
+Rule	Mont	1951	1956	-	Sep	lastSun	2:00	0	S
+Rule	Mont	1957	1973	-	Oct	lastSun	2:00	0	S
+Zone America/Montreal	-4:54:16 -	LMT	1884
+			-5:00	Mont	E%sT	1918
+			-5:00	Canada	E%sT	1919
+			-5:00	Mont	E%sT	1942 Feb  9  2:00s
+			-5:00	Canada	E%sT	1946
+			-5:00	Mont	E%sT	1974
+			-5:00	Canada	E%sT
+
+# Montserrat
+# From Paul Eggert (2006-03-22):
+# In 1995 volcanic eruptions forced evacuation of Plymouth, the capital.
+# world.gazetteer.com says Cork Hill is the most populous location now.
+Zone America/Montserrat	-4:08:52 -	LMT	1911 Jul  1  0:01 # Cork Hill
+			-4:00	-	AST
+
+# Argentina
+# This entry was intended for the following areas, but has been superseded by
+# more detailed zones.
+# Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN), Chaco (CC),
+# Formosa (FM), La Pampa (LP), Chubut (CH)
+Zone America/Rosario	-4:02:40 -	LMT	1894 Nov
+			-4:16:44 -	CMT	1920 May
+			-4:00	-	ART	1930 Dec
+			-4:00	Arg	AR%sT	1969 Oct  5
+			-3:00	Arg	AR%sT	1991 Jul
+			-3:00	-	ART	1999 Oct  3  0:00
+			-4:00	Arg	AR%sT	2000 Mar  3  0:00
+			-3:00	-	ART
+
+# St Kitts-Nevis
+Zone America/St_Kitts	-4:10:52 -	LMT	1912 Mar  2 # Basseterre
+			-4:00	-	AST
+
+# St Lucia
+Zone America/St_Lucia	-4:04:00 -	LMT	1890 # Castries
+			-4:04:00 -	CMT	1912 # Castries Mean Time
+			-4:00	-	AST
+
+# Virgin Is
+Zone America/St_Thomas	-4:19:44 -	LMT	1911 Jul # Charlotte Amalie
+			-4:00	-	AST
+
+# St Vincent and the Grenadines
+Zone America/St_Vincent	-4:04:56 -	LMT	1890 # Kingstown
+			-4:04:56 -	KMT	1912 # Kingstown Mean Time
+			-4:00	-	AST
+
+# British Virgin Is
+Zone America/Tortola	-4:18:28 -	LMT	1911 Jul # Road Town
+			-4:00	-	AST
+
+# McMurdo, Ross Island, since 1955-12
+Zone Antarctica/McMurdo	0	-	-00	1956
+			12:00	NZ	NZ%sT
+Link Antarctica/McMurdo Antarctica/South_Pole
+
+# Yemen
+# Milne says 2:59:54 was the meridian of the saluting battery at Aden,
+# and that Yemen was at 1:55:56, the meridian of the Hagia Sophia.
+Zone	Asia/Aden	2:59:54	-	LMT	1950
+			3:00	-	AST
+
+# Bahrain
+Zone	Asia/Bahrain	3:22:20 -	LMT	1920     # Manamah
+			4:00	-	GST	1972 Jun
+			3:00	-	AST
+
+# India
+#
+# From Paul Eggert (2014-09-06):
+# The 1876 Report of the Secretary of the [US] Navy, p 305 says that Madras
+# civil time was 5:20:57.3.
+#
+# From Paul Eggert (2014-08-21):
+# In tomorrow's The Hindu, Nitya Menon reports that India had two civil time
+# zones starting in 1884, one in Bombay and one in Calcutta, and that railways
+# used a third time zone based on Madras time (80 deg. 18'30" E).  Also,
+# in 1881 Bombay briefly switched to Madras time, but switched back.  See:
+# http://www.thehindu.com/news/cities/chennai/madras-375-when-madras-clocked-the-time/article6339393.ece
+#Zone	  Asia/Chennai  [not enough info to complete]
+
+# China
+# Long-shu Time (probably due to Long and Shu being two names of that area)
+# Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
+# most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
+# counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
+# Yangchun, Yangjiang, Yu'nan, and Yunfu.
+Zone	Asia/Chongqing	7:06:20	-	LMT	1928     # or Chungking
+			7:00	-	LONT	1980 May # Long-shu Time
+			8:00	PRC	C%sT
+Link Asia/Chongqing Asia/Chungking
+
+# Vietnam
+# From Paul Eggert (2014-10-13):
+# See Asia/Ho_Chi_Minh for the source for this data.
+# Trần's book says the 1954-55 transition to 07:00 in Hanoi was in
+# October 1954, with exact date and time unspecified.
+Zone	Asia/Hanoi	7:03:24 -	LMT	1906 Jul  1
+			7:06:30	-	PLMT	1911 May  1
+			7:00	-	ICT	1942 Dec 31 23:00
+			8:00	-	IDT	1945 Mar 14 23:00
+			9:00	-	JST	1945 Sep  2
+			7:00	-	ICT	1947 Apr  1
+			8:00	-	IDT	1954 Oct
+			7:00	-	ICT
+
+# China
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
+# Heilongjiang (except Mohe county), Jilin
+Zone	Asia/Harbin	8:26:44	-	LMT	1928     # or Haerbin
+			8:30	-	CHAT	1932 Mar # Changbai Time
+			8:00	-	CST	1940
+			9:00	-	CHAT	1966 May
+			8:30	-	CHAT	1980 May
+			8:00	PRC	C%sT
+
+# far west China
+Zone	Asia/Kashgar	5:03:56	-	LMT	1928     # or Kashi or Kaxgar
+			5:30	-	KAST	1940     # Kashgar Time
+			5:00	-	KAST	1980 May
+			8:00	PRC	C%sT
+
+# Kuwait
+Zone	Asia/Kuwait	3:11:56 -	LMT	1950
+			3:00	-	AST
+
+
+# Oman
+# Milne says 3:54:24 was the meridian of the Muscat Tidal Observatory.
+Zone	Asia/Muscat	3:54:24 -	LMT	1920
+			4:00	-	GST
+
+# India
+# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
+# According to a Portuguese decree (1911-05-26)
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# Portuguese India switched to UT +05 on 1912-01-01.
+#Zone	Asia/Panaji	[not enough info to complete]
+
+# Cambodia
+# From Paul Eggert (2014-10-11):
+# See Asia/Ho_Chi_Minh for the source for most of this data.  Also, guess
+# (1) Cambodia reverted to UT +07 on 1945-09-02, when Vietnam did, and
+# (2) they also reverted to +07 on 1953-11-09, the date of independence.
+# These guesses are probably wrong but they're better than guessing no
+# transitions there.
+Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jul  1
+			7:06:30	-	PLMT	1911 May  1
+			7:00	-	ICT	1942 Dec 31 23:00
+			8:00	-	IDT	1945 Mar 14 23:00
+			9:00	-	JST	1945 Sep  2
+			7:00	-	ICT	1947 Apr  1
+			8:00	-	IDT	1953 Nov  9
+			7:00	-	ICT
+
+# Israel
+Zone	Asia/Tel_Aviv	2:19:04 -	LMT	1880
+			2:21	-	JMT	1918
+			2:00	Zion	I%sT
+
+# Laos
+# From Paul Eggert (2014-10-11):
+# See Asia/Ho_Chi_Minh for the source for most of this data.
+# Trần's book says that Laos reverted to UT +07 on 1955-04-15.
+# Also, guess that Laos reverted to +07 on 1945-09-02, when Vietnam did;
+# this is probably wrong but it's better than guessing no transition.
+Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jul  1
+			7:06:30	-	PLMT	1911 May  1
+			7:00	-	ICT	1942 Dec 31 23:00
+			8:00	-	IDT	1945 Mar 14 23:00
+			9:00	-	JST	1945 Sep  2
+			7:00	-	ICT	1947 Apr  1
+			8:00	-	IDT	1955 Apr 15
+			7:00	-	ICT
+
+# Jan Mayen
+# From Whitman:
+Zone Atlantic/Jan_Mayen	-1:00	-	EGT
+
+# St Helena
+Zone Atlantic/St_Helena	-0:22:48 -	LMT	1890 # Jamestown
+			-0:22:48 -	JMT	1951 # Jamestown Mean Time
+			 0:00	-	GMT
+
+# Northern Ireland
+Zone	Europe/Belfast	-0:23:40 -	LMT	1880 Aug  2
+			-0:25:21 -	DMT	1916 May 21  2:00
+						# DMT = Dublin/Dunsink MT
+			-0:25:21 1:00	IST	1916 Oct  1  2:00s
+						# IST = Irish Summer Time
+			 0:00	GB-Eire	%s	1968 Oct 27
+			 1:00	-	BST	1971 Oct 31  2:00u
+			 0:00	GB-Eire	%s	1996
+			 0:00	EU	GMT/BST
+
+# Guernsey
+# Data from Joseph S. Myers
+# http://mm.icann.org/pipermail/tz/2013-September/019883.html
+# References to be added
+# LMT Location - 49.27N -2.33E - St.Peter Port
+Zone	Europe/Guernsey	-0:09:19 -	LMT	1913 Jun 18
+			 0:00	GB-Eire	%s	1940 Jul  2
+			 1:00	C-Eur	CE%sT	1945 May  8
+			 0:00	GB-Eire	%s	1968 Oct 27
+			 1:00	-	BST	1971 Oct 31  2:00u
+			 0:00	GB-Eire	%s	1996
+			 0:00	EU	GMT/BST
+
+# Isle of Man
+#
+# From Lester Caine (2013-09-04):
+# The Isle of Man legislation is now on-line at
+# , starting with the original Statutory
+# Time Act in 1883 and including additional confirmation of some of
+# the dates of the 'Summer Time' orders originating at
+# Westminster.  There is a little uncertainty as to the starting date
+# of the first summer time in 1916 which may have be announced a
+# couple of days late.  There is still a substantial number of
+# documents to work through, but it is thought that every GB change
+# was also implemented on the island.
+#
+# AT4 of 1883 - The Statutory Time et cetera Act 1883 -
+# LMT Location - 54.1508N -4.4814E - Tynwald Hill ( Manx parliament )
+Zone Europe/Isle_of_Man	-0:17:55 -	LMT	1883 Mar 30  0:00s
+			 0:00	GB-Eire	%s	1968 Oct 27
+			 1:00	-	BST	1971 Oct 31  2:00u
+			 0:00	GB-Eire	%s	1996
+			 0:00	EU	GMT/BST
+
+# Jersey
+# Data from Joseph S. Myers
+# http://mm.icann.org/pipermail/tz/2013-September/019883.html
+# References to be added
+# LMT Location - 49.187N -2.107E - St. Helier
+Zone	Europe/Jersey	-0:08:25 -	LMT	1898 Jun 11 16:00u
+			 0:00	GB-Eire	%s	1940 Jul  2
+			 1:00	C-Eur	CE%sT	1945 May  8
+			 0:00	GB-Eire	%s	1968 Oct 27
+			 1:00	-	BST	1971 Oct 31  2:00u
+			 0:00	GB-Eire	%s	1996
+			 0:00	EU	GMT/BST
+
+# Slovenia
+Zone Europe/Ljubljana	0:58:04	-	LMT	1884
+			1:00	-	CET	1941 Apr 18 23:00
+			1:00	C-Eur	CE%sT	1945 May  8  2:00s
+			1:00	1:00	CEST	1945 Sep 16  2:00s
+			1:00	-	CET	1982 Nov 27
+			1:00	EU	CE%sT
+
+# Bosnia and Herzegovina
+Zone	Europe/Sarajevo	1:13:40	-	LMT	1884
+			1:00	-	CET	1941 Apr 18 23:00
+			1:00	C-Eur	CE%sT	1945 May  8  2:00s
+			1:00	1:00	CEST	1945 Sep 16  2:00s
+			1:00	-	CET	1982 Nov 27
+			1:00	EU	CE%sT
+
+# Macedonia
+Zone	Europe/Skopje	1:25:44	-	LMT	1884
+			1:00	-	CET	1941 Apr 18 23:00
+			1:00	C-Eur	CE%sT	1945 May  8  2:00s
+			1:00	1:00	CEST	1945 Sep 16  2:00s
+			1:00	-	CET	1982 Nov 27
+			1:00	EU	CE%sT
+
+# Moldova / Transnistria
+Zone	Europe/Tiraspol	1:58:32	-	LMT	1880
+			1:55	-	CMT	1918 Feb 15 # Chisinau MT
+			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
+			2:00	Romania	EE%sT	1940 Aug 15
+			2:00	1:00	EEST	1941 Jul 17
+			1:00	C-Eur	CE%sT	1944 Aug 24
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00
+			2:00	Russia	EE%sT	1992 Jan 19  2:00
+			3:00	Russia	MSK/MSD
+
+# Liechtenstein
+Zone	Europe/Vaduz	0:38:04 -	LMT	1894 Jun
+			1:00	-	CET	1981
+			1:00	EU	CE%sT
+
+# Croatia
+Zone	Europe/Zagreb	1:03:52	-	LMT	1884
+			1:00	-	CET	1941 Apr 18 23:00
+			1:00	C-Eur	CE%sT	1945 May  8  2:00s
+			1:00	1:00	CEST	1945 Sep 16  2:00s
+			1:00	-	CET	1982 Nov 27
+			1:00	EU	CE%sT
+
+# Madagascar
+Zone Indian/Antananarivo 3:10:04 -	LMT	1911 Jul
+			3:00	-	EAT	1954 Feb 27 23:00s
+			3:00	1:00	EAST	1954 May 29 23:00s
+			3:00	-	EAT
+
+# Comoros
+Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul # Moroni, Gran Comoro
+			3:00	-	EAT
+
+# Mayotte
+Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul # Mamoutzou
+			3:00	-	EAT
+
+# US minor outlying islands
+Zone Pacific/Johnston	-10:00	-	HST
+
+# US minor outlying islands
+#
+# From Mark Brader (2005-01-23):
+# [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
+# published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
+# reproduced a Pan American Airways timetable from 1936, for their weekly
+# "Orient Express" flights between San Francisco and Manila, and connecting
+# flights to Chicago and the US East Coast.  As it uses some time zone
+# designations that I've never seen before:....
+# Fri. 6:30A Lv. HONOLOLU (Pearl Harbor), H.I.   H.L.T. Ar. 5:30P Sun.
+#  "   3:00P Ar. MIDWAY ISLAND . . . . . . . . . M.L.T. Lv. 6:00A  "
+#
+Zone Pacific/Midway	-11:49:28 -	LMT	1901
+			-11:00	-	NST	1956 Jun  3
+			-11:00	1:00	NDT	1956 Sep  2
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
+
+# N Mariana Is
+Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
+			 9:43:00 -	LMT	1901
+			 9:00	-	MPT	1969 Oct    # N Mariana Is Time
+			10:00	-	MPT	2000 Dec 23
+			10:00	-	ChST	# Chamorro Standard Time
diff --git a/checklinks.awk b/checklinks.awk
new file mode 100644
index 000000000000..5b3e1571d9f4
--- /dev/null
+++ b/checklinks.awk
@@ -0,0 +1,48 @@
+# Check links in tz tables.
+
+# Contributed by Paul Eggert.  This file is in the public domain.
+
+BEGIN {
+    # Special marker indicating that the name is defined as a Zone.
+    # It is a newline so that it cannot match a valid name.
+    # It is not null so that its slot does not appear unset.
+    Zone = "\n"
+}
+
+/^Zone/ {
+    if (defined[$2]) {
+	if (defined[$2] == Zone) {
+	    printf "%s: Zone has duplicate definition\n", $2
+	} else {
+	    printf "%s: Link with same name as Zone\n", $2
+	}
+	status = 1
+    }
+    defined[$2] = Zone
+}
+
+/^Link/ {
+    if (defined[$3]) {
+	if (defined[$3] == Zone) {
+	    printf "%s: Link with same name as Zone\n", $3
+	} else if (defined[$3] == $2) {
+	    printf "%s: Link has duplicate definition\n", $3
+	} else {
+	    printf "%s: Link to both %s and %s\n", $3, defined[$3], $2
+	}
+	status = 1
+    }
+    used[$2] = 1
+    defined[$3] = $2
+}
+
+END {
+    for (tz in used) {
+	if (defined[tz] != Zone) {
+	    printf "%s: Link to non-zone\n", tz
+	    status = 1
+	}
+    }
+
+    exit status
+}
diff --git a/checktab.awk b/checktab.awk
new file mode 100644
index 000000000000..2397673e92a9
--- /dev/null
+++ b/checktab.awk
@@ -0,0 +1,177 @@
+# Check tz tables for consistency.
+
+# Contributed by Paul Eggert.  This file is in the public domain.
+
+BEGIN {
+	FS = "\t"
+
+	if (!iso_table) iso_table = "iso3166.tab"
+	if (!zone_table) zone_table = "zone1970.tab"
+	if (!want_warnings) want_warnings = -1
+
+	while (getline >"/dev/stderr"
+			status = 1
+		}
+		cc = $1
+		name = $2
+		if (cc !~ /^[A-Z][A-Z]$/) {
+			printf "%s:%d: invalid country code '%s'\n", \
+				iso_table, iso_NR, cc >>"/dev/stderr"
+			status = 1
+		}
+		if (cc <= cc0) {
+			if (cc == cc0) {
+				s = "duplicate";
+			} else {
+				s = "out of order";
+			}
+
+			printf "%s:%d: country code '%s' is %s\n", \
+				iso_table, iso_NR, cc, s \
+				>>"/dev/stderr"
+			status = 1
+		}
+		cc0 = cc
+		if (name2cc[name]) {
+			printf "%s:%d: '%s' and '%s' have the same name\n", \
+				iso_table, iso_NR, name2cc[name], cc \
+				>>"/dev/stderr"
+			status = 1
+		}
+		name2cc[name] = cc
+		cc2name[cc] = name
+		cc2NR[cc] = iso_NR
+	}
+
+	cc0 = ""
+
+	while (getline >"/dev/stderr"
+			status = 1
+		}
+		split($1, cca, /,/)
+		cc = cca[1]
+		coordinates = $2
+		tz = $3
+		comments = $4
+		if (cc < cc0) {
+			printf "%s:%d: country code '%s' is out of order\n", \
+				zone_table, zone_NR, cc >>"/dev/stderr"
+			status = 1
+		}
+		cc0 = cc
+		tztab[tz] = 1
+		tz2comments[tz] = comments
+		tz2NR[tz] = zone_NR
+		for (i in cca) {
+		    cc = cca[i]
+		    cctz = cc tz
+		    cctztab[cctz] = 1
+		    if (cc2name[cc]) {
+			cc_used[cc]++
+		    } else {
+			printf "%s:%d: %s: unknown country code\n", \
+				zone_table, zone_NR, cc >>"/dev/stderr"
+			status = 1
+		    }
+		}
+		if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
+		    && coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) {
+			printf "%s:%d: %s: invalid coordinates\n", \
+				zone_table, zone_NR, coordinates >>"/dev/stderr"
+			status = 1
+		}
+	}
+
+	for (cctz in cctztab) {
+		cc = substr (cctz, 1, 2)
+		tz = substr (cctz, 3)
+		if (1 < cc_used[cc]) {
+			comments_needed[tz] = cc
+		}
+	}
+	for (cctz in cctztab) {
+	  cc = substr (cctz, 1, 2)
+	  tz = substr (cctz, 3)
+	  if (!comments_needed[tz] && tz2comments[tz]) {
+	    printf "%s:%d: unnecessary comment '%s'\n", \
+		zone_table, tz2NR[tz], tz2comments[tz] \
+		>>"/dev/stderr"
+	    tz2comments[tz] = 0
+	    status = 1
+	  } else if (comments_needed[tz] && !tz2comments[tz]) {
+	    printf "%s:%d: missing comment for %s\n", \
+	      zone_table, tz2NR[tz], comments_needed[tz] \
+	      >>"/dev/stderr"
+	    tz2comments[tz] = 1
+	    status = 1
+	  }
+	}
+	FS = " "
+}
+
+$1 ~ /^#/ { next }
+
+{
+	tz = rules = ""
+	if ($1 == "Zone") {
+		tz = $2
+		ruleUsed[$4] = 1
+	} else if ($1 == "Link" && zone_table == "zone.tab") {
+		# Ignore Link commands if source and destination basenames
+		# are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
+		src = $2
+		dst = $3
+		while ((i = index(src, "/"))) src = substr(src, i+1)
+		while ((i = index(dst, "/"))) dst = substr(dst, i+1)
+		if (src != dst) tz = $3
+	} else if ($1 == "Rule") {
+		ruleDefined[$2] = 1
+	} else {
+		ruleUsed[$2] = 1
+	}
+	if (tz && tz ~ /\//) {
+		if (!tztab[tz]) {
+			printf "%s: no data for '%s'\n", zone_table, tz \
+				>>"/dev/stderr"
+			status = 1
+		}
+		zoneSeen[tz] = 1
+	}
+}
+
+END {
+	for (tz in ruleDefined) {
+		if (!ruleUsed[tz]) {
+			printf "%s: Rule never used\n", tz
+			status = 1
+		}
+	}
+	for (tz in tztab) {
+		if (!zoneSeen[tz]) {
+			printf "%s:%d: no Zone table for '%s'\n", \
+				zone_table, tz2NR[tz], tz >>"/dev/stderr"
+			status = 1
+		}
+	}
+	if (0 < want_warnings) {
+		for (cc in cc2name) {
+			if (!cc_used[cc]) {
+				printf "%s:%d: warning: " \
+					"no Zone entries for %s (%s)\n", \
+					iso_table, cc2NR[cc], cc, cc2name[cc]
+			}
+		}
+	}
+
+	exit status
+}
diff --git a/europe b/europe
index a7dc350d1ebf..4709cc742c1a 100644
--- a/europe
+++ b/europe
@@ -1500,73 +1500,84 @@ Zone Atlantic/Reykjavik	-1:28	-	LMT	1908
 # But these events all occurred before the 1970 cutoff,
 # so record only the time in Rome.
 #
-# From Paul Eggert (2006-03-22):
-# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
-# F. Pollastri
-# Day-light Saving Time in Italy (2006-02-03)
-# http://toi.iriti.cnr.it/uk/ienitlt.html
-# ('FP' below), taken from an Italian National Electrotechnical Institute
-# publication. When the three sources disagree, guess who's right, as follows:
+# From Michael Deckers (2016-10-24):
+# http://www.ac-ilsestante.it/MERIDIANE/ora_legale quotes a law of 1893-08-10
+# ... [translated as] "The preceding dispositions will enter into
+# force at the instant at which, according to the time specified in
+# the 1st article, the 1st of November 1893 will begin...."
 #
-# year	FP	Shanks&P. (S)	Whitman (W)	Go with:
-# 1916	06-03	06-03 24:00	06-03 00:00	FP & W
-#	09-30	09-30 24:00	09-30 01:00	FP; guess 24:00s
-# 1917	04-01	03-31 24:00	03-31 00:00	FP & S
-#	09-30	09-29 24:00	09-30 01:00	FP & W
-# 1918	03-09	03-09 24:00	03-09 00:00	FP & S
-#	10-06	10-05 24:00	10-06 01:00	FP & W
-# 1919	03-01	03-01 24:00	03-01 00:00	FP & S
-#	10-04	10-04 24:00	10-04 01:00	FP; guess 24:00s
-# 1920	03-20	03-20 24:00	03-20 00:00	FP & S
-#	09-18	09-18 24:00	10-01 01:00	FP; guess 24:00s
-# 1944	04-02	04-03 02:00			S (see C-Eur)
-#	09-16	10-02 03:00			FP; guess 24:00s
-# 1945	09-14	09-16 24:00			FP; guess 24:00s
-# 1970	05-21	05-31 00:00			S
-#	09-20	09-27 00:00			S
+# From Pierpaolo Bernardi (2016-10-20):
+# The authoritative source for time in Italy is the national metrological
+# institute, which has a summary page of historical DST data at
+# http://www.inrim.it/res/tf/ora_legale_i.shtml
+# (2016-10-24):
+# http://www.renzobaldini.it/le-ore-legali-in-italia/
+# has still different data for 1944.  It divides Italy in two, as
+# there were effectively two governments at the time, north of Gothic
+# Line German controlled territory, official government RSI, and south
+# of the Gothic Line, controlled by allied armies.
+#
+# From Brian Inglis (2016-10-23):
+# Viceregal LEGISLATIVE DECREE. 14 September 1944, no. 219.
+# Restoration of Standard Time. (044U0219) (OJ 62 of 30.9.1944) ...
+# Given the R. law decreed on 1944-03-29, no. 92, by which standard time is
+# advanced to sixty minutes later starting at hour two on 1944-04-02; ...
+# Starting at hour three on the date 1944-09-17 standard time will be resumed.
+#
+# From Paul Eggert (2016-10-27):
+# Go with INRiM for DST rules, except as corrected by Inglis for 1944
+# for the Kingdom of Italy.  This is consistent with Renzo Baldini.
+# Model Rome's occupation by using using C-Eur rules from 1943-09-10
+# to 1944-06-04; although Rome was an open city during this period, it
+# was effectively controlled by Germany.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Italy	1916	only	-	Jun	 3	0:00s	1:00	S
-Rule	Italy	1916	only	-	Oct	 1	0:00s	0	-
-Rule	Italy	1917	only	-	Apr	 1	0:00s	1:00	S
-Rule	Italy	1917	only	-	Sep	30	0:00s	0	-
-Rule	Italy	1918	only	-	Mar	10	0:00s	1:00	S
-Rule	Italy	1918	1919	-	Oct	Sun>=1	0:00s	0	-
-Rule	Italy	1919	only	-	Mar	 2	0:00s	1:00	S
-Rule	Italy	1920	only	-	Mar	21	0:00s	1:00	S
-Rule	Italy	1920	only	-	Sep	19	0:00s	0	-
-Rule	Italy	1940	only	-	Jun	15	0:00s	1:00	S
-Rule	Italy	1944	only	-	Sep	17	0:00s	0	-
-Rule	Italy	1945	only	-	Apr	 2	2:00	1:00	S
-Rule	Italy	1945	only	-	Sep	15	0:00s	0	-
-Rule	Italy	1946	only	-	Mar	17	2:00s	1:00	S
-Rule	Italy	1946	only	-	Oct	 6	2:00s	0	-
-Rule	Italy	1947	only	-	Mar	16	0:00s	1:00	S
-Rule	Italy	1947	only	-	Oct	 5	0:00s	0	-
-Rule	Italy	1948	only	-	Feb	29	2:00s	1:00	S
-Rule	Italy	1948	only	-	Oct	 3	2:00s	0	-
-Rule	Italy	1966	1968	-	May	Sun>=22	0:00	1:00	S
-Rule	Italy	1966	1969	-	Sep	Sun>=22	0:00	0	-
-Rule	Italy	1969	only	-	Jun	 1	0:00	1:00	S
-Rule	Italy	1970	only	-	May	31	0:00	1:00	S
-Rule	Italy	1970	only	-	Sep	lastSun	0:00	0	-
-Rule	Italy	1971	1972	-	May	Sun>=22	0:00	1:00	S
-Rule	Italy	1971	only	-	Sep	lastSun	1:00	0	-
-Rule	Italy	1972	only	-	Oct	 1	0:00	0	-
-Rule	Italy	1973	only	-	Jun	 3	0:00	1:00	S
-Rule	Italy	1973	1974	-	Sep	lastSun	0:00	0	-
-Rule	Italy	1974	only	-	May	26	0:00	1:00	S
-Rule	Italy	1975	only	-	Jun	 1	0:00s	1:00	S
-Rule	Italy	1975	1977	-	Sep	lastSun	0:00s	0	-
-Rule	Italy	1976	only	-	May	30	0:00s	1:00	S
-Rule	Italy	1977	1979	-	May	Sun>=22	0:00s	1:00	S
-Rule	Italy	1978	only	-	Oct	 1	0:00s	0	-
-Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
+Rule	Italy	1916	only	-	Jun	 3	24:00	1:00	S
+Rule	Italy	1916	1917	-	Sep	30	24:00	0	-
+Rule	Italy	1917	only	-	Mar	31	24:00	1:00	S
+Rule	Italy	1918	only	-	Mar	 9	24:00	1:00	S
+Rule	Italy	1918	only	-	Oct	 6	24:00	0	-
+Rule	Italy	1919	only	-	Mar	 1	24:00	1:00	S
+Rule	Italy	1919	only	-	Oct	 4	24:00	0	-
+Rule	Italy	1920	only	-	Mar	20	24:00	1:00	S
+Rule	Italy	1920	only	-	Sep	18	24:00	0	-
+Rule	Italy	1940	only	-	Jun	14	24:00	1:00	S
+Rule	Italy	1942	only	-	Nov	 2	 2:00s	0	-
+Rule	Italy	1943	only	-	Mar	29	 2:00s	1:00	S
+Rule	Italy	1943	only	-	Oct	 4	 2:00s	0	-
+Rule	Italy	1944	only	-	Apr	 2	 2:00s	1:00	S
+Rule	Italy	1944	only	-	Sep	17	 2:00s	0	-
+Rule	Italy	1945	only	-	Apr	 2	 2:00	1:00	S
+Rule	Italy	1945	only	-	Sep	15	 1:00	0	-
+Rule	Italy	1946	only	-	Mar	17	 2:00s	1:00	S
+Rule	Italy	1946	only	-	Oct	 6	 2:00s	0	-
+Rule	Italy	1947	only	-	Mar	16	 0:00s	1:00	S
+Rule	Italy	1947	only	-	Oct	 5	 0:00s	0	-
+Rule	Italy	1948	only	-	Feb	29	 2:00s	1:00	S
+Rule	Italy	1948	only	-	Oct	 3	 2:00s	0	-
+Rule	Italy	1966	1968	-	May	Sun>=22	 0:00s	1:00	S
+Rule	Italy	1966	only	-	Sep	24	24:00	0	-
+Rule	Italy	1967	1969	-	Sep	Sun>=22	 0:00s	0	-
+Rule	Italy	1969	only	-	Jun	 1	 0:00s	1:00	S
+Rule	Italy	1970	only	-	May	31	 0:00s	1:00	S
+Rule	Italy	1970	only	-	Sep	lastSun	 0:00s	0	-
+Rule	Italy	1971	1972	-	May	Sun>=22	 0:00s	1:00	S
+Rule	Italy	1971	only	-	Sep	lastSun	 0:00s	0	-
+Rule	Italy	1972	only	-	Oct	 1	 0:00s	0	-
+Rule	Italy	1973	only	-	Jun	 3	 0:00s	1:00	S
+Rule	Italy	1973	1974	-	Sep	lastSun	 0:00s	0	-
+Rule	Italy	1974	only	-	May	26	 0:00s	1:00	S
+Rule	Italy	1975	only	-	Jun	 1	 0:00s	1:00	S
+Rule	Italy	1975	1977	-	Sep	lastSun	 0:00s	0	-
+Rule	Italy	1976	only	-	May	30	 0:00s	1:00	S
+Rule	Italy	1977	1979	-	May	Sun>=22	 0:00s	1:00	S
+Rule	Italy	1978	only	-	Oct	 1	 0:00s	0	-
+Rule	Italy	1979	only	-	Sep	30	 0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
-			0:49:56	-	RMT	1893 Nov  1  0:00s # Rome Mean
-			1:00	Italy	CE%sT	1942 Nov  2  2:00s
-			1:00	C-Eur	CE%sT	1944 Jul
+			0:49:56	-	RMT	1893 Oct 31 23:49:56 # Rome Mean
+			1:00	Italy	CE%sT	1943 Sep 10
+			1:00	C-Eur	CE%sT	1944 Jun  4
 			1:00	Italy	CE%sT	1980
 			1:00	EU	CE%sT
 
@@ -1765,6 +1776,10 @@ Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
 # See Europe/Belgrade.
 
 # Malta
+#
+# From Paul Eggert (2016-10-21):
+# Assume 1900-1972 was like Rome, overriding Shanks.
+#
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Malta	1973	only	-	Mar	31	0:00s	1:00	S
 Rule	Malta	1973	only	-	Sep	29	0:00s	0	-
@@ -1775,8 +1790,6 @@ Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
 Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
-			1:00	Italy	CE%sT	1942 Nov  2  2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
 			1:00	Italy	CE%sT	1973 Mar 31
 			1:00	Malta	CE%sT	1981
 			1:00	EU	CE%sT
@@ -1908,7 +1921,7 @@ Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
 # Amsterdam mean time.
 
 # The data entries before 1945 are taken from
-# http://www.staff.science.uu.nl/~gent0113/idl/idl.htm
+# http://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
diff --git a/leapseconds.awk b/leapseconds.awk
new file mode 100644
index 000000000000..21fe540791b5
--- /dev/null
+++ b/leapseconds.awk
@@ -0,0 +1,76 @@
+# Generate the 'leapseconds' file from 'leap-seconds.list'.
+
+# This file is in the public domain.
+
+BEGIN {
+  print "# Allowance for leap seconds added to each time zone file."
+  print ""
+  print "# This file is in the public domain."
+  print ""
+  print "# This file is generated automatically from the data in the public-domain"
+  print "# leap-seconds.list file available from most NIST time servers."
+  print "# If the URL  does not work,"
+  print "# you should be able to pick up leap-seconds.list from a secondary NIST server."
+  print "# See  for a list of secondary servers."
+  print "# For more about leap-seconds.list, please see"
+  print "# The NTP Timescale and Leap Seconds"
+  print "# http://www.eecis.udel.edu/~mills/leap.html"
+  print ""
+  print "# The International Earth Rotation and Reference Systems Service"
+  print "# periodically uses leap seconds to keep UTC to within 0.9 s of UT1"
+  print "# (which measures the true angular orientation of the earth in space); see"
+  print "# Terry J Quinn, The BIPM and the accurate measure of time,"
+  print "# Proc IEEE 79, 7 (July 1991), 894-905 ."
+  print "# There were no leap seconds before 1972, because the official mechanism"
+  print "# accounting for the discrepancy between atomic time and the earth's rotation"
+  print "# did not exist until the early 1970s."
+  print ""
+  print "# The correction (+ or -) is made at the given time, so lines"
+  print "# will typically look like:"
+  print "#	Leap	YEAR	MON	DAY	23:59:60	+	R/S"
+  print "# or"
+  print "#	Leap	YEAR	MON	DAY	23:59:59	-	R/S"
+  print ""
+  print "# If the leapsecond is Rolling (R) the given time is local time."
+  print "# If the leapsecond is Stationary (S) the given time is UTC."
+  print ""
+  print "# Leap	YEAR	MONTH	DAY	HH:MM:SS	CORR	R/S"
+}
+
+/^ *$/ { next }
+
+/^#\tUpdated through/ || /^#\tFile expires on:/ {
+    last_lines = last_lines $0 "\n"
+}
+
+/^#/ { next }
+
+{
+    NTP_timestamp = $1
+    TAI_minus_UTC = $2
+    hash_mark = $3
+    one = $4
+    month = $5
+    year = $6
+    if (old_TAI_minus_UTC) {
+	if (old_TAI_minus_UTC < TAI_minus_UTC) {
+	    sign = "23:59:60\t+"
+	} else {
+	    sign = "23:59:59\t-"
+	}
+	if (month == "Jan") {
+	    year--;
+	    month = "Dec";
+	    day = 31
+	} else if (month == "Jul") {
+	    month = "Jun";
+	    day = 30
+	}
+	printf "Leap\t%s\t%s\t%s\t%s\tS\n", year, month, day, sign
+    }
+    old_TAI_minus_UTC = TAI_minus_UTC
+}
+
+END {
+    printf "\n%s", last_lines
+}
diff --git a/version b/version
new file mode 100644
index 000000000000..bc96124d710f
--- /dev/null
+++ b/version
@@ -0,0 +1 @@
+2016i
diff --git a/zone.tab b/zone.tab
index cf774b5dc20c..f4969d29b838 100644
--- a/zone.tab
+++ b/zone.tab
@@ -152,7 +152,8 @@ CU	+2308-08222	America/Havana
 CV	+1455-02331	Atlantic/Cape_Verde
 CW	+1211-06900	America/Curacao
 CX	-1025+10543	Indian/Christmas
-CY	+3510+03322	Asia/Nicosia
+CY	+3510+03322	Asia/Nicosia	Cyprus (most areas)
+CY	+3507+03357	Asia/Famagusta	Northern Cyprus
 CZ	+5005+01426	Europe/Prague
 DE	+5230+01322	Europe/Berlin	Germany (most areas)
 DE	+4742+00841	Europe/Busingen	Busingen
diff --git a/zone1970.tab b/zone1970.tab
index b7372cf671b8..f48f7a6b56be 100644
--- a/zone1970.tab
+++ b/zone1970.tab
@@ -144,7 +144,8 @@ CU	+2308-08222	America/Havana
 CV	+1455-02331	Atlantic/Cape_Verde
 CW,AW,BQ,SX	+1211-06900	America/Curacao
 CX	-1025+10543	Indian/Christmas
-CY	+3510+03322	Asia/Nicosia
+CY	+3510+03322	Asia/Nicosia	Cyprus (most areas)
+CY	+3507+03357	Asia/Famagusta	Northern Cyprus
 CZ,SK	+5005+01426	Europe/Prague
 DE	+5230+01322	Europe/Berlin	Germany (most areas)
 DK	+5540+01235	Europe/Copenhagen
diff --git a/zoneinfo2tdf.pl b/zoneinfo2tdf.pl
new file mode 100755
index 000000000000..e05ec010082a
--- /dev/null
+++ b/zoneinfo2tdf.pl
@@ -0,0 +1,52 @@
+#! /usr/bin/perl -w
+
+# Courtesy Ken Pizzini.
+
+use strict;
+
+#This file released to the public domain.
+
+# Note: error checking is poor; trust the output only if the input
+# has been checked by zic.
+
+my $contZone = '';
+while (<>) {
+  my $origline = $_;
+  my @fields = ();
+  while (s/^\s*((?:"[^"]*"|[^\s#])+)//) {
+    push @fields, $1;
+  }
+  next unless @fields;
+
+  my $type = lc($fields[0]);
+  if ($contZone) {
+    @fields >= 3 or warn "bad continuation line";
+    unshift @fields, '+', $contZone;
+    $type = 'zone';
+  }
+
+  $contZone = '';
+  if ($type eq 'zone') {
+    # Zone  NAME  GMTOFF  RULES/SAVE  FORMAT  [UNTIL]
+    my $nfields = @fields;
+    $nfields >= 5 or warn "bad zone line";
+    if ($nfields > 6) {
+      #this splice is optional, depending on one's preference
+      #(one big date-time field, or componentized date and time):
+      splice(@fields, 5, $nfields-5, "@fields[5..$nfields-1]");
+    }
+    $contZone = $fields[1] if @fields > 5;
+  } elsif ($type eq 'rule') {
+    # Rule  NAME  FROM  TO  TYPE  IN  ON  AT  SAVE  LETTER/S
+    @fields == 10 or warn "bad rule line";
+  } elsif ($type eq 'link') {
+    # Link  TARGET  LINK-NAME
+    @fields == 3 or warn "bad link line";
+  } elsif ($type eq 'leap') {
+    # Leap  YEAR  MONTH  DAY  HH:MM:SS  CORR  R/S
+    @fields == 7 or warn "bad leap line";
+  } else {
+    warn "Fubar at input line $.: $origline";
+  }
+  print join("\t", @fields), "\n";
+}

From 0cbe6805b238b41fadbff2b11c18af44c983e316 Mon Sep 17 00:00:00 2001
From: Adrian Chadd 
Date: Thu, 3 Nov 2016 23:05:39 +0000
Subject: [PATCH 020/127] [ath] add the MIMO per-chain RSSI and noise floor
 information.

This is a long time coming.  The general pieces have been floating around
in a local repo since circa 2012 when I dropped the net80211 support
into the tree.

This allows the per-chain RSSI and NF to show up in 'ifconfig wlanX list sta'.
I haven't yet implemented the EVM hookups so that'll show up; that'll come
later.

Thanks to Susie Hellings  who did the original work
on this a looong time ago for a company we both worked at.
---
 sys/dev/ath/if_ath_rx.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index cacd8f8c721f..54572d10d763 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -635,7 +635,9 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
     struct mbuf *m)
 {
 	uint64_t rstamp;
-	int len, type;
+	/* XXX TODO: make this an mbuf tag? */
+	struct ieee80211_rx_stats rxs;
+	int len, type, i;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_node *ni;
 	int is_good = 0;
@@ -904,6 +906,33 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
 		sc->sc_stats.ast_rx_agg++;
 #endif /* AH_SUPPORT_AR5416 */
 
+
+	/*
+	 * Populate the per-chain RSSI values where appropriate.
+	 */
+	bzero(&rxs, sizeof(rxs));
+	rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI |
+	    IEEE80211_R_C_CHAIN |
+	    IEEE80211_R_C_NF |
+	    IEEE80211_R_C_RSSI |
+	    IEEE80211_R_TSF64 |
+	    IEEE80211_R_TSF_START;	/* XXX TODO: validate */
+	rxs.c_rssi = rs->rs_rssi;
+	rxs.c_nf = nf;
+	rxs.c_chain = 3;	/* XXX TODO: check */
+	rxs.c_rx_tsf = rstamp;
+
+	for (i = 0; i < 3; i++) {
+		rxs.c_rssi_ctl[i] = rs->rs_rssi_ctl[i];
+		rxs.c_rssi_ext[i] = rs->rs_rssi_ext[i];
+		/*
+		 * XXX note: we currently don't track
+		 * per-chain noisefloor.
+		 */
+		rxs.c_nf_ctl[i] = nf;
+		rxs.c_nf_ext[i] = nf;
+	}
+
 	if (ni != NULL) {
 		/*
 		 * Only punt packets for ampdu reorder processing for
@@ -916,7 +945,8 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
 		/*
 		 * Sending station is known, dispatch directly.
 		 */
-		type = ieee80211_input(ni, m, rs->rs_rssi, nf);
+		(void) ieee80211_add_rx_params(m, &rxs);
+		type = ieee80211_input_mimo(ni, m);
 		ieee80211_free_node(ni);
 		m = NULL;
 		/*
@@ -929,7 +959,8 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
 		    rs->rs_keyix != HAL_RXKEYIX_INVALID)
 			is_good = 1;
 	} else {
-		type = ieee80211_input_all(ic, m, rs->rs_rssi, nf);
+		(void) ieee80211_add_rx_params(m, &rxs);
+		type = ieee80211_input_mimo_all(ic, m);
 		m = NULL;
 	}
 

From 7cfecbb95b9adcb85efef92cbc33c6030483fc9a Mon Sep 17 00:00:00 2001
From: Adrian Chadd 
Date: Thu, 3 Nov 2016 23:11:33 +0000
Subject: [PATCH 021/127] Add a witness check to enforce that no non-sleeping
 locks are held when they shouldn't be.

I used this during driver bring-up to find that the Linux driver holds a
whole lot of locks whilst doing their equivalent of busdma operations.

If this works out well, it should be added to the other architecture busdma
implementations to aid in similar debugging.

Tested:

* bounce buffer and dmar busdma, Lenovo X230 laptop, all the internal
  hardware
* ath(4) too

Discussed with: jhb
---
 sys/x86/x86/busdma_machdep.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/sys/x86/x86/busdma_machdep.c b/sys/x86/x86/busdma_machdep.c
index c96b26d579f2..aa9e36d3e977 100644
--- a/sys/x86/x86/busdma_machdep.c
+++ b/sys/x86/x86/busdma_machdep.c
@@ -197,6 +197,8 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 	struct bus_dma_tag_common *tc;
 	int error;
 
+	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s", __func__);
+
 	if (parent == NULL) {
 		error = bus_dma_bounce_impl.tag_create(parent, alignment,
 		    boundary, lowaddr, highaddr, filter, filterarg, maxsize,
@@ -228,6 +230,8 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
 {
 	struct bus_dma_tag_common *tc;
 
+	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s", __func__);
+
 	tc = (struct bus_dma_tag_common *)dmat;
 	return (tc->impl->map_create(dmat, flags, mapp));
 }
@@ -257,6 +261,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
 {
 	struct bus_dma_tag_common *tc;
 
+	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s", __func__);
+
 	tc = (struct bus_dma_tag_common *)dmat;
 	return (tc->impl->mem_alloc(dmat, vaddr, flags, mapp));
 }

From 16025c357f31adf44cd6f57af385b1c0e742b883 Mon Sep 17 00:00:00 2001
From: Jared McNeill 
Date: Thu, 3 Nov 2016 23:22:04 +0000
Subject: [PATCH 022/127] Add support for Allwinner H3 audio codec.

The audio controller in the H3 is more or less the same as A10/A20 except
some registers are shuffled around. The mixer interface, however, is
completely different between SoCs. Separate a10_mixer_class and
h3_mixer_class implementations are now made available. This will also make
adding support for other SoCs easier in the future.

Reviewed by:		andrew, ganbold
Relnotes:		yes
Differential Revision:	https://reviews.freebsd.org/D8425
---
 sys/arm/allwinner/a10_codec.c | 681 +++++++++++++++++++++++++---------
 1 file changed, 499 insertions(+), 182 deletions(-)

diff --git a/sys/arm/allwinner/a10_codec.c b/sys/arm/allwinner/a10_codec.c
index af9f41c54fc5..ae89984d980e 100644
--- a/sys/arm/allwinner/a10_codec.c
+++ b/sys/arm/allwinner/a10_codec.c
@@ -27,7 +27,7 @@
  */
 
 /*
- * Allwinner A10/A20 Audio Codec
+ * Allwinner A10/A20 and H3 Audio Codec
  */
 
 #include 
@@ -50,19 +50,46 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+
 #include 
+#include 
 
 #include "sunxi_dma_if.h"
 #include "mixer_if.h"
-#include "gpio_if.h"
+
+struct a10codec_info;
+
+struct a10codec_config {
+	/* mixer class */
+	struct kobj_class *mixer_class;
+
+	/* toggle DAC/ADC mute */
+	void		(*mute)(struct a10codec_info *, int, int);
+
+	/* DRQ types */
+	u_int		drqtype_codec;
+	u_int		drqtype_sdram;
+
+	/* register map */
+	bus_size_t	DPC,
+			DAC_FIFOC,
+			DAC_FIFOS,
+			DAC_TXDATA,
+			ADC_FIFOC,
+			ADC_FIFOS,
+			ADC_RXDATA,
+			DAC_CNT,
+			ADC_CNT;
+};
 
 #define	TX_TRIG_LEVEL	0xf
 #define	RX_TRIG_LEVEL	0x7
 #define	DRQ_CLR_CNT	0x3
 
-#define	AC_DAC_DPC	0x00
+#define	AC_DAC_DPC(_sc)		((_sc)->cfg->DPC)	
 #define	 DAC_DPC_EN_DA			0x80000000
-#define	AC_DAC_FIFOC	0x04
+#define	AC_DAC_FIFOC(_sc)	((_sc)->cfg->DAC_FIFOC)
 #define	 DAC_FIFOC_FS_SHIFT		29
 #define	 DAC_FIFOC_FS_MASK		(7U << DAC_FIFOC_FS_SHIFT)
 #define	  DAC_FS_48KHZ			0
@@ -86,17 +113,9 @@ __FBSDID("$FreeBSD$");
 #define	 DAC_FIFOC_TX_BITS		(1U << 5)
 #define	 DAC_FIFOC_DRQ_EN		(1U << 4)
 #define	 DAC_FIFOC_FIFO_FLUSH		(1U << 0)
-#define	AC_DAC_FIFOS	0x08
-#define	AC_DAC_TXDATA	0x0c
-#define	AC_DAC_ACTL	0x10
-#define	 DAC_ACTL_DACAREN		(1U << 31)
-#define	 DAC_ACTL_DACALEN		(1U << 30)
-#define	 DAC_ACTL_MIXEN			(1U << 29)
-#define	 DAC_ACTL_DACPAS		(1U << 8)
-#define	 DAC_ACTL_PAMUTE		(1U << 6)
-#define	 DAC_ACTL_PAVOL_SHIFT		0
-#define	 DAC_ACTL_PAVOL_MASK		(0x3f << DAC_ACTL_PAVOL_SHIFT)
-#define	AC_ADC_FIFOC	0x1c
+#define	AC_DAC_FIFOS(_sc)	((_sc)->cfg->DAC_FIFOS)
+#define	AC_DAC_TXDATA(_sc)	((_sc)->cfg->DAC_TXDATA)
+#define	AC_ADC_FIFOC(_sc)	((_sc)->cfg->ADC_FIFOC)
 #define	 ADC_FIFOC_FS_SHIFT		29
 #define	 ADC_FIFOC_FS_MASK		(7U << ADC_FIFOC_FS_SHIFT)
 #define	  ADC_FS_48KHZ		0
@@ -108,33 +127,10 @@ __FBSDID("$FreeBSD$");
 #define	 ADC_FIFOC_RX_BITS		(1U << 6)
 #define	 ADC_FIFOC_DRQ_EN		(1U << 4)
 #define	 ADC_FIFOC_FIFO_FLUSH		(1U << 1)
-#define	AC_ADC_FIFOS	0x20
-#define	AC_ADC_RXDATA	0x24
-#define	AC_ADC_ACTL	0x28
-#define	 ADC_ACTL_ADCREN		(1U << 31)
-#define	 ADC_ACTL_ADCLEN		(1U << 30)
-#define	 ADC_ACTL_PREG1EN		(1U << 29)
-#define	 ADC_ACTL_PREG2EN		(1U << 28)
-#define	 ADC_ACTL_VMICEN		(1U << 27)
-#define	 ADC_ACTL_ADCG_SHIFT		20
-#define	 ADC_ACTL_ADCG_MASK		(7U << ADC_ACTL_ADCG_SHIFT)
-#define	 ADC_ACTL_ADCIS_SHIFT		17
-#define	 ADC_ACTL_ADCIS_MASK		(7U << ADC_ACTL_ADCIS_SHIFT)
-#define	  ADC_IS_LINEIN			0
-#define	  ADC_IS_FMIN			1
-#define	  ADC_IS_MIC1			2
-#define	  ADC_IS_MIC2			3
-#define	  ADC_IS_MIC1_L_MIC2_R		4
-#define	  ADC_IS_MIC1_LR_MIC2_LR	5
-#define	  ADC_IS_OMIX			6
-#define	  ADC_IS_LINEIN_L_MIC1_R	7
-#define	 ADC_ACTL_LNRDF			(1U << 16)
-#define	 ADC_ACTL_LNPREG_SHIFT		13
-#define	 ADC_ACTL_LNPREG_MASK		(7U << ADC_ACTL_LNPREG_SHIFT)
-#define	 ADC_ACTL_PA_EN			(1U << 4)
-#define	 ADC_ACTL_DDE			(1U << 3)
-#define	AC_DAC_CNT	0x30
-#define	AC_ADC_CNT	0x34
+#define	AC_ADC_FIFOS(_sc)	((_sc)->cfg->ADC_FIFOS)
+#define	AC_ADC_RXDATA(_sc)	((_sc)->cfg->ADC_RXDATA)
+#define	AC_DAC_CNT(_sc)		((_sc)->cfg->DAC_CNT)
+#define	AC_ADC_CNT(_sc)		((_sc)->cfg->ADC_CNT)
 
 static uint32_t a10codec_fmt[] = {
 	SND_FORMAT(AFMT_S16_LE, 1, 0),
@@ -168,14 +164,13 @@ struct a10codec_chinfo {
 
 struct a10codec_info {
 	device_t		dev;
-	struct resource		*res[2];
+	struct resource		*res[3];
 	struct mtx		*lock;
 	bus_dma_tag_t		dmat;
 	unsigned		dmasize;
 	void			*ih;
 
-	unsigned		drqtype_codec;
-	unsigned		drqtype_sdram;
+	struct a10codec_config	*cfg;
 
 	struct a10codec_chinfo	play;
 	struct a10codec_chinfo	rec;
@@ -183,6 +178,7 @@ struct a10codec_info {
 
 static struct resource_spec a10codec_spec[] = {
 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
+	{ SYS_RES_MEMORY,	1,	RF_ACTIVE | RF_OPTIONAL },
 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
 	{ -1, 0 }
 };
@@ -191,127 +187,417 @@ static struct resource_spec a10codec_spec[] = {
 #define	CODEC_WRITE(sc, reg, val)	bus_write_4((sc)->res[0], (reg), (val))
 
 /*
- * Mixer interface
+ * A10/A20 mixer interface
  */
 
+#define	A10_DAC_ACTL	0x10
+#define	 A10_DACAREN			(1U << 31)
+#define	 A10_DACALEN			(1U << 30)
+#define	 A10_MIXEN			(1U << 29)
+#define	 A10_DACPAS			(1U << 8)
+#define	 A10_PAMUTE			(1U << 6)
+#define	 A10_PAVOL_SHIFT		0
+#define	 A10_PAVOL_MASK			(0x3f << A10_PAVOL_SHIFT)
+#define	A10_ADC_ACTL	0x28
+#define	 A10_ADCREN			(1U << 31)
+#define	 A10_ADCLEN			(1U << 30)
+#define	 A10_PREG1EN			(1U << 29)
+#define	 A10_PREG2EN			(1U << 28)
+#define	 A10_VMICEN			(1U << 27)
+#define	 A10_ADCG_SHIFT			20
+#define	 A10_ADCG_MASK			(7U << A10_ADCG_SHIFT)
+#define	 A10_ADCIS_SHIFT		17
+#define	 A10_ADCIS_MASK			(7U << A10_ADCIS_SHIFT)
+#define	  A10_ADC_IS_LINEIN			0
+#define	  A10_ADC_IS_FMIN			1
+#define	  A10_ADC_IS_MIC1			2
+#define	  A10_ADC_IS_MIC2			3
+#define	  A10_ADC_IS_MIC1_L_MIC2_R		4
+#define	  A10_ADC_IS_MIC1_LR_MIC2_LR		5
+#define	  A10_ADC_IS_OMIX			6
+#define	  A10_ADC_IS_LINEIN_L_MIC1_R		7
+#define	 A10_LNRDF			(1U << 16)
+#define	 A10_LNPREG_SHIFT		13
+#define	 A10_LNPREG_MASK		(7U << A10_LNPREG_SHIFT)
+#define	 A10_PA_EN			(1U << 4)
+#define	 A10_DDE			(1U << 3)
+
 static int
-a10codec_mixer_init(struct snd_mixer *m)
+a10_mixer_init(struct snd_mixer *m)
 {
 	struct a10codec_info *sc = mix_getdevinfo(m);
-	pcell_t prop[4];
-	phandle_t node;
-	device_t gpio;
 	uint32_t val;
-	ssize_t len;
-	int pin;
 
 	mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_RECLEV);
 	mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC);
 
 	/* Unmute input source to PA */
-	val = CODEC_READ(sc, AC_DAC_ACTL);
-	val |= DAC_ACTL_PAMUTE;
-	CODEC_WRITE(sc, AC_DAC_ACTL, val);
+	val = CODEC_READ(sc, A10_DAC_ACTL);
+	val |= A10_PAMUTE;
+	CODEC_WRITE(sc, A10_DAC_ACTL, val);
 
 	/* Enable PA */
-	val = CODEC_READ(sc, AC_ADC_ACTL);
-	val |= ADC_ACTL_PA_EN;
-	CODEC_WRITE(sc, AC_ADC_ACTL, val);
-
-	/* Unmute PA */
-	node = ofw_bus_get_node(sc->dev);
-	len = OF_getencprop(node, "allwinner,pa-gpios", prop, sizeof(prop));
-	if (len > 0 && (len / sizeof(prop[0])) == 4) {
-		gpio = OF_device_from_xref(prop[0]);
-		if (gpio != NULL) {
-			pin = prop[1] * 32 + prop[2];
-			GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
-			GPIO_PIN_SET(gpio, pin, GPIO_PIN_LOW);
-		}
-	}
+	val = CODEC_READ(sc, A10_ADC_ACTL);
+	val |= A10_PA_EN;
+	CODEC_WRITE(sc, A10_ADC_ACTL, val);
 
 	return (0);
 }
 
-static const struct a10codec_mixer {
+static const struct a10_mixer {
 	unsigned reg;
 	unsigned mask;
 	unsigned shift;
-} a10codec_mixers[SOUND_MIXER_NRDEVICES] = {
-	[SOUND_MIXER_VOLUME]	= { AC_DAC_ACTL, DAC_ACTL_PAVOL_MASK,
-				    DAC_ACTL_PAVOL_SHIFT },
-	[SOUND_MIXER_LINE]	= { AC_ADC_ACTL, ADC_ACTL_LNPREG_MASK,
-				    ADC_ACTL_LNPREG_SHIFT },
-	[SOUND_MIXER_RECLEV]	= { AC_ADC_ACTL, ADC_ACTL_ADCG_MASK,
-				    ADC_ACTL_ADCG_SHIFT },
+} a10_mixers[SOUND_MIXER_NRDEVICES] = {
+	[SOUND_MIXER_VOLUME]	= { A10_DAC_ACTL, A10_PAVOL_MASK,
+				    A10_PAVOL_SHIFT },
+	[SOUND_MIXER_LINE]	= { A10_ADC_ACTL, A10_LNPREG_MASK,
+				    A10_LNPREG_SHIFT },
+	[SOUND_MIXER_RECLEV]	= { A10_ADC_ACTL, A10_ADCG_MASK,
+				    A10_ADCG_SHIFT },
 }; 
 
 static int
-a10codec_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left,
+a10_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left,
     unsigned right)
 {
 	struct a10codec_info *sc = mix_getdevinfo(m);
 	uint32_t val;
 	unsigned nvol, max;
 
-	max = a10codec_mixers[dev].mask >> a10codec_mixers[dev].shift;
+	max = a10_mixers[dev].mask >> a10_mixers[dev].shift;
 	nvol = (left * max) / 100;
 
-	val = CODEC_READ(sc, a10codec_mixers[dev].reg);
-	val &= ~a10codec_mixers[dev].mask;
-	val |= (nvol << a10codec_mixers[dev].shift);
-	CODEC_WRITE(sc, a10codec_mixers[dev].reg, val);
+	val = CODEC_READ(sc, a10_mixers[dev].reg);
+	val &= ~a10_mixers[dev].mask;
+	val |= (nvol << a10_mixers[dev].shift);
+	CODEC_WRITE(sc, a10_mixers[dev].reg, val);
 
 	left = right = (left * 100) / max;
 	return (left | (right << 8));
 }
 
 static uint32_t
-a10codec_mixer_setrecsrc(struct snd_mixer *m, uint32_t src)
+a10_mixer_setrecsrc(struct snd_mixer *m, uint32_t src)
 {
 	struct a10codec_info *sc = mix_getdevinfo(m);
 	uint32_t val;
 
-	val = CODEC_READ(sc, AC_ADC_ACTL);
+	val = CODEC_READ(sc, A10_ADC_ACTL);
 
 	switch (src) {
 	case SOUND_MASK_LINE:	/* line-in */
-		val &= ~ADC_ACTL_ADCIS_MASK;
-		val |= (ADC_IS_LINEIN << ADC_ACTL_ADCIS_SHIFT);
+		val &= ~A10_ADCIS_MASK;
+		val |= (A10_ADC_IS_LINEIN << A10_ADCIS_SHIFT);
 		break;
 	case SOUND_MASK_MIC:	/* MIC1 */
-		val &= ~ADC_ACTL_ADCIS_MASK;
-		val |= (ADC_IS_MIC1 << ADC_ACTL_ADCIS_SHIFT);
+		val &= ~A10_ADCIS_MASK;
+		val |= (A10_ADC_IS_MIC1 << A10_ADCIS_SHIFT);
 		break;
 	case SOUND_MASK_LINE1:	/* MIC2 */
-		val &= ~ADC_ACTL_ADCIS_MASK;
-		val |= (ADC_IS_MIC2 << ADC_ACTL_ADCIS_SHIFT);
+		val &= ~A10_ADCIS_MASK;
+		val |= (A10_ADC_IS_MIC2 << A10_ADCIS_SHIFT);
 		break;
 	default:
 		break;
 	}
 
-	CODEC_WRITE(sc, AC_ADC_ACTL, val);
+	CODEC_WRITE(sc, A10_ADC_ACTL, val);
 
-	switch ((val & ADC_ACTL_ADCIS_MASK) >> ADC_ACTL_ADCIS_SHIFT) {
-	case ADC_IS_LINEIN:
+	switch ((val & A10_ADCIS_MASK) >> A10_ADCIS_SHIFT) {
+	case A10_ADC_IS_LINEIN:
 		return (SOUND_MASK_LINE);
-	case ADC_IS_MIC1:
+	case A10_ADC_IS_MIC1:
 		return (SOUND_MASK_MIC);
-	case ADC_IS_MIC2:
+	case A10_ADC_IS_MIC2:
 		return (SOUND_MASK_LINE1);
 	default:
 		return (0);
 	}
 }
 
-static kobj_method_t a10codec_mixer_methods[] = {
-	KOBJMETHOD(mixer_init,		a10codec_mixer_init),
-	KOBJMETHOD(mixer_set,		a10codec_mixer_set),
-	KOBJMETHOD(mixer_setrecsrc,	a10codec_mixer_setrecsrc),
+static void
+a10_mute(struct a10codec_info *sc, int mute, int dir)
+{
+	uint32_t val;
+
+	if (dir == PCMDIR_PLAY) {
+		val = CODEC_READ(sc, A10_DAC_ACTL);
+		if (mute) {
+			/* Disable DAC analog l/r channels and output mixer */
+			val &= ~A10_DACAREN;
+			val &= ~A10_DACALEN;
+			val &= ~A10_DACPAS;
+		} else {
+			/* Enable DAC analog l/r channels and output mixer */
+			val |= A10_DACAREN;
+			val |= A10_DACALEN;
+			val |= A10_DACPAS;
+		}
+		CODEC_WRITE(sc, A10_DAC_ACTL, val);
+	} else {
+		val = CODEC_READ(sc, A10_ADC_ACTL);
+		if (mute) {
+			/* Disable ADC analog l/r channels, MIC1 preamp,
+			 * and VMIC pin voltage
+			 */
+			val &= ~A10_ADCREN;
+			val &= ~A10_ADCLEN;
+			val &= ~A10_PREG1EN;
+			val &= ~A10_VMICEN;
+		} else {
+			/* Enable ADC analog l/r channels, MIC1 preamp,
+			 * and VMIC pin voltage
+			 */
+			val |= A10_ADCREN;
+			val |= A10_ADCLEN;
+			val |= A10_PREG1EN;
+			val |= A10_VMICEN;
+		}
+		CODEC_WRITE(sc, A10_ADC_ACTL, val);
+	}
+}
+
+static kobj_method_t a10_mixer_methods[] = {
+	KOBJMETHOD(mixer_init,		a10_mixer_init),
+	KOBJMETHOD(mixer_set,		a10_mixer_set),
+	KOBJMETHOD(mixer_setrecsrc,	a10_mixer_setrecsrc),
 	KOBJMETHOD_END
 };
-MIXER_DECLARE(a10codec_mixer);
+MIXER_DECLARE(a10_mixer);
+
+
+/*
+ * H3 mixer interface
+ */
+
+#define	H3_PR_CFG		0x00
+#define	 H3_AC_PR_RST		(1 << 18)
+#define	 H3_AC_PR_RW		(1 << 24)
+#define	 H3_AC_PR_ADDR_SHIFT	16
+#define	 H3_AC_PR_ADDR_MASK	(0x1f << H3_AC_PR_ADDR_SHIFT)
+#define	 H3_ACDA_PR_WDAT_SHIFT	8
+#define	 H3_ACDA_PR_WDAT_MASK	(0xff << H3_ACDA_PR_WDAT_SHIFT)
+#define	 H3_ACDA_PR_RDAT_SHIFT	0
+#define	 H3_ACDA_PR_RDAT_MASK	(0xff << H3_ACDA_PR_RDAT_SHIFT)
+
+#define	H3_LOMIXSC		0x01
+#define	 H3_LOMIXSC_LDAC	(1 << 1)
+#define	H3_ROMIXSC		0x02
+#define	 H3_ROMIXSC_RDAC	(1 << 1)
+#define	H3_DAC_PA_SRC		0x03
+#define	 H3_DACAREN		(1 << 7)
+#define	 H3_DACALEN		(1 << 6)
+#define	 H3_RMIXEN		(1 << 5)
+#define	 H3_LMIXEN		(1 << 4)
+#define	H3_LINEIN_GCTR		0x05
+#define	 H3_LINEING_SHIFT	4
+#define	 H3_LINEING_MASK	(0x7 << H3_LINEING_SHIFT)
+#define	H3_MIC_GCTR		0x06
+#define	 H3_MIC1_GAIN_SHIFT	4
+#define	 H3_MIC1_GAIN_MASK	(0x7 << H3_MIC1_GAIN_SHIFT)
+#define	 H3_MIC2_GAIN_SHIFT	0
+#define	 H3_MIC2_GAIN_MASK	(0x7 << H3_MIC2_GAIN_SHIFT)
+#define	H3_PAEN_CTR		0x07
+#define	 H3_LINEOUTEN		(1 << 7)
+#define	H3_LINEOUT_VOLC		0x09
+#define	 H3_LINEOUTVOL_SHIFT	3
+#define	 H3_LINEOUTVOL_MASK	(0x1f << H3_LINEOUTVOL_SHIFT)
+#define	H3_MIC2G_LINEOUT_CTR	0x0a
+#define	 H3_LINEOUT_LSEL	(1 << 3)
+#define	 H3_LINEOUT_RSEL	(1 << 2)
+#define	H3_LADCMIXSC		0x0c
+#define	H3_RADCMIXSC		0x0d
+#define	 H3_ADCMIXSC_MIC1	(1 << 6)
+#define	 H3_ADCMIXSC_MIC2	(1 << 5)
+#define	 H3_ADCMIXSC_LINEIN	(1 << 2)
+#define	 H3_ADCMIXSC_OMIXER	(3 << 0)
+#define	H3_ADC_AP_EN		0x0f
+#define	 H3_ADCREN		(1 << 7)
+#define	 H3_ADCLEN		(1 << 6)
+#define	 H3_ADCG_SHIFT		0
+#define	 H3_ADCG_MASK		(0x7 << H3_ADCG_SHIFT)
+
+static u_int 
+h3_pr_read(struct a10codec_info *sc, u_int addr)
+{
+	uint32_t val;
+
+	/* Read current value */
+	val = bus_read_4(sc->res[1], H3_PR_CFG);
+
+	/* De-assert reset */
+	val |= H3_AC_PR_RST;
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+
+	/* Read mode */
+	val &= ~H3_AC_PR_RW;
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+
+	/* Set address */
+	val &= ~H3_AC_PR_ADDR_MASK;
+	val |= (addr << H3_AC_PR_ADDR_SHIFT);
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+
+	/* Read data */
+	return (bus_read_4(sc->res[1], H3_PR_CFG) & H3_ACDA_PR_RDAT_MASK);
+}
+
+static void
+h3_pr_write(struct a10codec_info *sc, u_int addr, u_int data)
+{
+	uint32_t val;
+
+	/* Read current value */
+	val = bus_read_4(sc->res[1], H3_PR_CFG);
+
+	/* De-assert reset */
+	val |= H3_AC_PR_RST;
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+
+	/* Set address */
+	val &= ~H3_AC_PR_ADDR_MASK;
+	val |= (addr << H3_AC_PR_ADDR_SHIFT);
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+
+	/* Write data */
+	val &= ~H3_ACDA_PR_WDAT_MASK;
+	val |= (data << H3_ACDA_PR_WDAT_SHIFT);
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+
+	/* Write mode */
+	val |= H3_AC_PR_RW;
+	bus_write_4(sc->res[1], H3_PR_CFG, val);
+}
+
+static void
+h3_pr_set_clear(struct a10codec_info *sc, u_int addr, u_int set, u_int clr)
+{
+	u_int old, new;
+
+	old = h3_pr_read(sc, addr);
+	new = set | (old & ~clr);
+	h3_pr_write(sc, addr, new);
+}
+
+static int
+h3_mixer_init(struct snd_mixer *m)
+{
+	struct a10codec_info *sc = mix_getdevinfo(m);
+
+	mix_setdevs(m, SOUND_MASK_PCM | SOUND_MASK_VOLUME | SOUND_MASK_RECLEV |
+	    SOUND_MASK_MIC | SOUND_MASK_LINE | SOUND_MASK_LINE1);
+	mix_setrecdevs(m, SOUND_MASK_MIC | SOUND_MASK_LINE | SOUND_MASK_LINE1 |
+	    SOUND_MASK_IMIX);
+
+	pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL);
+
+	/* Right & Left LINEOUT enable */
+	h3_pr_set_clear(sc, H3_PAEN_CTR, H3_LINEOUTEN, 0);
+	h3_pr_set_clear(sc, H3_MIC2G_LINEOUT_CTR,
+	    H3_LINEOUT_LSEL | H3_LINEOUT_RSEL, 0);
+
+	return (0);
+}
+
+static const struct h3_mixer {
+	unsigned reg;
+	unsigned mask;
+	unsigned shift;
+} h3_mixers[SOUND_MIXER_NRDEVICES] = {
+	[SOUND_MIXER_VOLUME]	= { H3_LINEOUT_VOLC, H3_LINEOUTVOL_MASK,
+				    H3_LINEOUTVOL_SHIFT },
+	[SOUND_MIXER_RECLEV]	= { H3_ADC_AP_EN, H3_ADCG_MASK,
+				    H3_ADCG_SHIFT },
+	[SOUND_MIXER_LINE]	= { H3_LINEIN_GCTR, H3_LINEING_MASK,
+				    H3_LINEING_SHIFT },
+	[SOUND_MIXER_MIC]	= { H3_MIC_GCTR, H3_MIC1_GAIN_MASK,
+				    H3_MIC1_GAIN_SHIFT },
+	[SOUND_MIXER_LINE1]	= { H3_MIC_GCTR, H3_MIC2_GAIN_MASK,
+				    H3_MIC2_GAIN_SHIFT },
+};
+
+static int
+h3_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left,
+    unsigned right)
+{
+	struct a10codec_info *sc = mix_getdevinfo(m);
+	unsigned nvol, max;
+
+	max = h3_mixers[dev].mask >> h3_mixers[dev].shift;
+	nvol = (left * max) / 100;
+
+	h3_pr_set_clear(sc, h3_mixers[dev].reg,
+	    nvol << h3_mixers[dev].shift, h3_mixers[dev].mask);
+
+	left = right = (left * 100) / max;
+	return (left | (right << 8));
+}
+
+static uint32_t
+h3_mixer_setrecsrc(struct snd_mixer *m, uint32_t src)
+{
+	struct a10codec_info *sc = mix_getdevinfo(m);
+	uint32_t val;
+
+	val = 0;
+	src &= (SOUND_MASK_LINE | SOUND_MASK_MIC |
+	    SOUND_MASK_LINE1 | SOUND_MASK_IMIX);
+
+	if ((src & SOUND_MASK_LINE) != 0)	/* line-in */
+		val |= H3_ADCMIXSC_LINEIN;
+	if ((src & SOUND_MASK_MIC) != 0)	/* MIC1 */
+		val |= H3_ADCMIXSC_MIC1;
+	if ((src & SOUND_MASK_LINE1) != 0)	/* MIC2 */
+		val |= H3_ADCMIXSC_MIC2;
+	if ((src & SOUND_MASK_IMIX) != 0)	/* l/r output mixer */
+		val |= H3_ADCMIXSC_OMIXER;
+
+	h3_pr_write(sc, H3_LADCMIXSC, val);
+	h3_pr_write(sc, H3_RADCMIXSC, val);
+
+	return (src);
+}
+
+static void
+h3_mute(struct a10codec_info *sc, int mute, int dir)
+{
+	if (dir == PCMDIR_PLAY) {
+		if (mute) {
+			/* Mute DAC l/r channels to output mixer */
+			h3_pr_set_clear(sc, H3_LOMIXSC, 0, H3_LOMIXSC_LDAC);
+			h3_pr_set_clear(sc, H3_ROMIXSC, 0, H3_ROMIXSC_RDAC);
+			/* Disable DAC analog l/r channels and output mixer */
+			h3_pr_set_clear(sc, H3_DAC_PA_SRC,
+			    0, H3_DACAREN | H3_DACALEN | H3_RMIXEN | H3_LMIXEN);
+		} else {
+			/* Enable DAC analog l/r channels and output mixer */
+			h3_pr_set_clear(sc, H3_DAC_PA_SRC,
+			    H3_DACAREN | H3_DACALEN | H3_RMIXEN | H3_LMIXEN, 0);
+			/* Unmute DAC l/r channels to output mixer */
+			h3_pr_set_clear(sc, H3_LOMIXSC, H3_LOMIXSC_LDAC, 0);
+			h3_pr_set_clear(sc, H3_ROMIXSC, H3_ROMIXSC_RDAC, 0);
+		}
+	} else {
+		if (mute) {
+			/* Disable ADC analog l/r channels */
+			h3_pr_set_clear(sc, H3_ADC_AP_EN,
+			    0, H3_ADCREN | H3_ADCLEN);
+		} else {
+			/* Enable ADC analog l/r channels */
+			h3_pr_set_clear(sc, H3_ADC_AP_EN,
+			    H3_ADCREN | H3_ADCLEN, 0);
+		}
+	}
+}
+
+static kobj_method_t h3_mixer_methods[] = {
+	KOBJMETHOD(mixer_init,		h3_mixer_init),
+	KOBJMETHOD(mixer_set,		h3_mixer_set),
+	KOBJMETHOD(mixer_setrecsrc,	h3_mixer_setrecsrc),
+	KOBJMETHOD_END
+};
+MIXER_DECLARE(h3_mixer);
 
 
 /*
@@ -364,12 +650,12 @@ a10codec_dmaconfig(struct a10codec_chinfo *ch)
 
 	if (ch->dir == PCMDIR_PLAY) {
 		conf.dst_noincr = true;
-		conf.src_drqtype = sc->drqtype_sdram;
-		conf.dst_drqtype = sc->drqtype_codec;
+		conf.src_drqtype = sc->cfg->drqtype_sdram;
+		conf.dst_drqtype = sc->cfg->drqtype_codec;
 	} else {
 		conf.src_noincr = true;
-		conf.src_drqtype = sc->drqtype_codec;
-		conf.dst_drqtype = sc->drqtype_sdram;
+		conf.src_drqtype = sc->cfg->drqtype_codec;
+		conf.dst_drqtype = sc->cfg->drqtype_sdram;
 	}
 
 	SUNXI_DMA_SET_CONFIG(ch->dmac, ch->dmachan, &conf);
@@ -428,23 +714,20 @@ a10codec_start(struct a10codec_chinfo *ch)
 
 	if (ch->dir == PCMDIR_PLAY) {
 		/* Flush DAC FIFO */
-		CODEC_WRITE(sc, AC_DAC_FIFOC, DAC_FIFOC_FIFO_FLUSH);
+		CODEC_WRITE(sc, AC_DAC_FIFOC(sc), DAC_FIFOC_FIFO_FLUSH);
 
 		/* Clear DAC FIFO status */
-		CODEC_WRITE(sc, AC_DAC_FIFOS, CODEC_READ(sc, AC_DAC_FIFOS));
+		CODEC_WRITE(sc, AC_DAC_FIFOS(sc),
+		    CODEC_READ(sc, AC_DAC_FIFOS(sc)));
 
-		/* Enable DAC analog left/right channels and output mixer */
-		val = CODEC_READ(sc, AC_DAC_ACTL);
-		val |= DAC_ACTL_DACAREN;
-		val |= DAC_ACTL_DACALEN;
-		val |= DAC_ACTL_DACPAS;
-		CODEC_WRITE(sc, AC_DAC_ACTL, val);
+		/* Unmute output */
+		sc->cfg->mute(sc, 0, ch->dir);
 
 		/* Configure DAC DMA channel */
 		a10codec_dmaconfig(ch);
 
 		/* Configure DAC FIFO */
-		CODEC_WRITE(sc, AC_DAC_FIFOC,
+		CODEC_WRITE(sc, AC_DAC_FIFOC(sc),
 		    (AFMT_CHANNEL(ch->format) == 1 ? DAC_FIFOC_MONO_EN : 0) |
 		    (a10codec_fs(ch) << DAC_FIFOC_FS_SHIFT) |
 		    (FIFO_MODE_16_15_0 << DAC_FIFOC_FIFO_MODE_SHIFT) |
@@ -452,31 +735,25 @@ a10codec_start(struct a10codec_chinfo *ch)
 		    (TX_TRIG_LEVEL << DAC_FIFOC_TX_TRIG_LEVEL_SHIFT));
 
 		/* Enable DAC DRQ */
-		val = CODEC_READ(sc, AC_DAC_FIFOC);
+		val = CODEC_READ(sc, AC_DAC_FIFOC(sc));
 		val |= DAC_FIFOC_DRQ_EN;
-		CODEC_WRITE(sc, AC_DAC_FIFOC, val);
+		CODEC_WRITE(sc, AC_DAC_FIFOC(sc), val);
 	} else {
 		/* Flush ADC FIFO */
-		CODEC_WRITE(sc, AC_ADC_FIFOC, ADC_FIFOC_FIFO_FLUSH);
+		CODEC_WRITE(sc, AC_ADC_FIFOC(sc), ADC_FIFOC_FIFO_FLUSH);
 
 		/* Clear ADC FIFO status */
-		CODEC_WRITE(sc, AC_ADC_FIFOS, CODEC_READ(sc, AC_ADC_FIFOS));
+		CODEC_WRITE(sc, AC_ADC_FIFOS(sc),
+		    CODEC_READ(sc, AC_ADC_FIFOS(sc)));
 
-		/* Enable ADC analog left/right channels, MIC1 preamp,
-		 * and VMIC pin voltage
-		 */
-		val = CODEC_READ(sc, AC_ADC_ACTL);
-		val |= ADC_ACTL_ADCREN;
-		val |= ADC_ACTL_ADCLEN;
-		val |= ADC_ACTL_PREG1EN;
-		val |= ADC_ACTL_VMICEN;
-		CODEC_WRITE(sc, AC_ADC_ACTL, val);
+		/* Unmute input */
+		sc->cfg->mute(sc, 0, ch->dir);
 
 		/* Configure ADC DMA channel */
 		a10codec_dmaconfig(ch);
 
 		/* Configure ADC FIFO */
-		CODEC_WRITE(sc, AC_ADC_FIFOC,
+		CODEC_WRITE(sc, AC_ADC_FIFOC(sc),
 		    ADC_FIFOC_EN_AD |
 		    ADC_FIFOC_RX_FIFO_MODE |
 		    (AFMT_CHANNEL(ch->format) == 1 ? ADC_FIFOC_MONO_EN : 0) |
@@ -484,9 +761,9 @@ a10codec_start(struct a10codec_chinfo *ch)
 		    (RX_TRIG_LEVEL << ADC_FIFOC_RX_TRIG_LEVEL_SHIFT));
 
 		/* Enable ADC DRQ */
-		val = CODEC_READ(sc, AC_ADC_FIFOC);
+		val = CODEC_READ(sc, AC_ADC_FIFOC(sc));
 		val |= ADC_FIFOC_DRQ_EN;
-		CODEC_WRITE(sc, AC_ADC_FIFOC, val);
+		CODEC_WRITE(sc, AC_ADC_FIFOC(sc), val);
 	}
 
 	/* Start DMA transfer */
@@ -497,34 +774,18 @@ static void
 a10codec_stop(struct a10codec_chinfo *ch)
 {
 	struct a10codec_info *sc = ch->parent;
-	uint32_t val;
 
 	/* Disable DMA channel */
 	SUNXI_DMA_HALT(ch->dmac, ch->dmachan);
 
+	sc->cfg->mute(sc, 1, ch->dir);
+
 	if (ch->dir == PCMDIR_PLAY) {
-		/* Disable DAC analog left/right channels and output mixer */
-		val = CODEC_READ(sc, AC_DAC_ACTL);
-		val &= ~DAC_ACTL_DACAREN;
-		val &= ~DAC_ACTL_DACALEN;
-		val &= ~DAC_ACTL_DACPAS;
-		CODEC_WRITE(sc, AC_DAC_ACTL, val);
-
 		/* Disable DAC DRQ */
-		CODEC_WRITE(sc, AC_DAC_FIFOC, 0);
+		CODEC_WRITE(sc, AC_DAC_FIFOC(sc), 0);
 	} else {
-		/* Disable ADC analog left/right channels, MIC1 preamp,
-		 * and VMIC pin voltage
-		 */
-		val = CODEC_READ(sc, AC_ADC_ACTL);
-		val &= ~ADC_ACTL_ADCREN;
-		val &= ~ADC_ACTL_ADCLEN;
-		val &= ~ADC_ACTL_PREG1EN;
-		val &= ~ADC_ACTL_VMICEN;
-		CODEC_WRITE(sc, AC_ADC_ACTL, val);
-
 		/* Disable ADC DRQ */
-		CODEC_WRITE(sc, AC_ADC_FIFOC, 0);
+		CODEC_WRITE(sc, AC_ADC_FIFOC(sc), 0);
 	}
 }
 
@@ -534,18 +795,30 @@ a10codec_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
 {
 	struct a10codec_info *sc = devinfo;
 	struct a10codec_chinfo *ch = dir == PCMDIR_PLAY ? &sc->play : &sc->rec;
-	int error;
+	phandle_t xref;
+	pcell_t *cells;
+	int ncells, error;
+
+	error = ofw_bus_parse_xref_list_alloc(ofw_bus_get_node(sc->dev),
+	    "dmas", "#dma-cells", dir == PCMDIR_PLAY ? 1 : 0,
+	    &xref, &ncells, &cells);
+	if (error != 0) {
+		device_printf(sc->dev, "cannot parse 'dmas' property\n");
+		return (NULL);
+	}
+	OF_prop_free(cells);
 
 	ch->parent = sc;
 	ch->channel = c;
 	ch->buffer = b;
 	ch->dir = dir;
 	ch->fifo = rman_get_start(sc->res[0]) +
-	    (dir == PCMDIR_REC ? AC_ADC_RXDATA : AC_DAC_TXDATA);
+	    (dir == PCMDIR_REC ? AC_ADC_RXDATA(sc) : AC_DAC_TXDATA(sc));
 
-	ch->dmac = devclass_get_device(devclass_find("a10dmac"), 0);
+	ch->dmac = OF_device_from_xref(xref);
 	if (ch->dmac == NULL) {
 		device_printf(sc->dev, "cannot find DMA controller\n");
+		device_printf(sc->dev, "xref = 0x%x\n", (u_int)xref);
 		return (NULL);
 	}
 	ch->dmachan = SUNXI_DMA_ALLOC(ch->dmac, false, a10codec_dmaintr, ch);
@@ -720,10 +993,43 @@ CHANNEL_DECLARE(a10codec_chan);
  * Device interface
  */
 
+static const struct a10codec_config a10_config = {
+	.mixer_class	= &a10_mixer_class,
+	.mute		= a10_mute,
+	.drqtype_codec	= 19,
+	.drqtype_sdram	= 22,
+	.DPC		= 0x00,
+	.DAC_FIFOC	= 0x04,
+	.DAC_FIFOS	= 0x08,
+	.DAC_TXDATA	= 0x0c,
+	.ADC_FIFOC	= 0x1c,
+	.ADC_FIFOS	= 0x20,
+	.ADC_RXDATA	= 0x24,
+	.DAC_CNT	= 0x30,
+	.ADC_CNT	= 0x34,
+};
+
+static const struct a10codec_config h3_config = {
+	.mixer_class	= &h3_mixer_class,
+	.mute		= h3_mute,
+	.drqtype_codec	= 15,
+	.drqtype_sdram	= 1,
+	.DPC		= 0x00,
+	.DAC_FIFOC	= 0x04,
+	.DAC_FIFOS	= 0x08,
+	.DAC_TXDATA	= 0x20,
+	.ADC_FIFOC	= 0x10,
+	.ADC_FIFOS	= 0x14,
+	.ADC_RXDATA	= 0x18,
+	.DAC_CNT	= 0x40,
+	.ADC_CNT	= 0x44,
+};
+
 static struct ofw_compat_data compat_data[] = {
-	{"allwinner,sun4i-a10-codec", 1},
-	{"allwinner,sun7i-a20-codec", 1},
-	{NULL, 0},
+	{ "allwinner,sun4i-a10-codec",	(uintptr_t)&a10_config },
+	{ "allwinner,sun7i-a20-codec",	(uintptr_t)&a10_config },
+	{ "allwinner,sun8i-h3-codec",	(uintptr_t)&h3_config },
+	{ NULL, 0 }
 };
 
 static int
@@ -744,11 +1050,17 @@ a10codec_attach(device_t dev)
 {
 	struct a10codec_info *sc;
 	char status[SND_STATUSLEN];
-	clk_t clk_apb, clk_codec;
+	struct gpiobus_pin *pa_pin;
+	phandle_t node;
+	clk_t clk_bus, clk_codec;
+	hwreset_t rst;
 	uint32_t val;
 	int error;
 
+	node = ofw_bus_get_node(dev);
+
 	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+	sc->cfg = (void *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
 	sc->dev = dev;
 	sc->lock = snd_mtxcreate(device_get_nameunit(dev), "a10codec softc");
 
@@ -758,17 +1070,6 @@ a10codec_attach(device_t dev)
 		goto fail;
 	}
 
-	/* XXX DRQ types should come from FDT, but how? */
-	if (ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-codec") ||
-	    ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-codec")) {
-		sc->drqtype_codec = 19;
-		sc->drqtype_sdram = 22;
-	} else {
-		device_printf(dev, "DRQ types not known for this SoC\n");
-		error = ENXIO;
-		goto fail;
-	}
-
 	sc->dmasize = 131072;
 	error = bus_dma_tag_create(
 	    bus_get_dma_tag(dev),
@@ -786,21 +1087,19 @@ a10codec_attach(device_t dev)
 	}
 
 	/* Get clocks */
-	error = clk_get_by_ofw_name(dev, 0, "apb", &clk_apb);
-	if (error != 0) {
-		device_printf(dev, "cannot find apb clock\n");
+	if (clk_get_by_ofw_name(dev, 0, "apb", &clk_bus) != 0 &&
+	    clk_get_by_ofw_name(dev, 0, "ahb", &clk_bus) != 0) {
+		device_printf(dev, "cannot find bus clock\n");
 		goto fail;
 	}
-	error = clk_get_by_ofw_name(dev, 0, "codec", &clk_codec);
-	if (error != 0) {
+	if (clk_get_by_ofw_name(dev, 0, "codec", &clk_codec) != 0) {
 		device_printf(dev, "cannot find codec clock\n");
 		goto fail;
 	}
 
-	/* Gating APB clock for codec */
-	error = clk_enable(clk_apb);
-	if (error != 0) {
-		device_printf(dev, "cannot enable apb clock\n");
+	/* Gating bus clock for codec */
+	if (clk_enable(clk_bus) != 0) {
+		device_printf(dev, "cannot enable bus clock\n");
 		goto fail;
 	}
 	/* Activate audio codec clock. According to the A10 and A20 user
@@ -824,10 +1123,20 @@ a10codec_attach(device_t dev)
 		goto fail;
 	}
 
+	/* De-assert hwreset */
+	if (hwreset_get_by_ofw_name(dev, 0, "apb", &rst) == 0 ||
+	    hwreset_get_by_ofw_name(dev, 0, "ahb", &rst) == 0) {
+		error = hwreset_deassert(rst);
+		if (error != 0) {
+			device_printf(dev, "cannot de-assert reset\n");
+			goto fail;
+		}
+	}
+
 	/* Enable DAC */
-	val = CODEC_READ(sc, AC_DAC_DPC);
+	val = CODEC_READ(sc, AC_DAC_DPC(sc));
 	val |= DAC_DPC_EN_DA;
-	CODEC_WRITE(sc, AC_DAC_DPC, val);
+	CODEC_WRITE(sc, AC_DAC_DPC(sc), val);
 
 #ifdef notdef
 	error = snd_setup_intr(dev, sc->irq, INTR_MPSAFE, a10codec_intr, sc,
@@ -838,11 +1147,19 @@ a10codec_attach(device_t dev)
 	}
 #endif
 
-	if (mixer_init(dev, &a10codec_mixer_class, sc)) {
+	if (mixer_init(dev, sc->cfg->mixer_class, sc)) {
 		device_printf(dev, "mixer_init failed\n");
 		goto fail;
 	}
 
+	/* Unmute PA */
+	if (gpio_pin_get_by_ofw_property(dev, node, "allwinner,pa-gpios",
+	    &pa_pin) == 0) {
+		error = gpio_pin_set_active(pa_pin, 1);
+		if (error != 0)
+			device_printf(dev, "failed to unmute PA\n");
+	}
+
 	pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
 
 	if (pcm_register(dev, sc, 1, 1)) {
@@ -863,7 +1180,7 @@ a10codec_attach(device_t dev)
 	snd_mtxfree(sc->lock);
 	free(sc, M_DEVBUF);
 
-	return (error);
+	return (ENXIO);
 }
 
 static device_method_t a10codec_pcm_methods[] = {

From afe30aa97f9429946b7ac46c6abeaa5b02d322af Mon Sep 17 00:00:00 2001
From: Sepherosa Ziehau 
Date: Fri, 4 Nov 2016 01:14:41 +0000
Subject: [PATCH 023/127] hyperv/vmbus: Reset ch_dev, once the child is
 deleted.

So it will not be mis-used later on, e.g. in vmbus_chan_printf().

Submitted by:	dexuan
Reported by:	dexuan
MFC after:	1 week
Sponsored by:	Microsoft
---
 sys/dev/hyperv/vmbus/vmbus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index 6c153335c57c..11be35ba4d73 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -954,6 +954,7 @@ vmbus_delete_child(struct vmbus_channel *chan)
 	if (chan->ch_dev != NULL) {
 		error = device_delete_child(chan->ch_vmbus->vmbus_dev,
 		    chan->ch_dev);
+		chan->ch_dev = NULL;
 	}
 	mtx_unlock(&Giant);
 	return (error);

From bccf7982785f87df2ee2146b6ed3dd541b75b3f4 Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 04:47:08 +0000
Subject: [PATCH 024/127] Add Allwinner UP SoC support to GENERIC on armv6

Relnotes:	yes
---
 sys/arm/conf/GENERIC | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC
index 53f1c09a04c2..f32f2e5fd17e 100644
--- a/sys/arm/conf/GENERIC
+++ b/sys/arm/conf/GENERIC
@@ -30,6 +30,9 @@ options 	KERNVIRTADDR=0xc0000000
 
 include 	"std.armv6"
 files		"../allwinner/files.allwinner"
+files		"../allwinner/files.allwinner_up"
+files		"../allwinner/a10/files.a10"
+files		"../allwinner/a13/files.a13"
 files		"../allwinner/a20/files.a20"
 files		"../allwinner/a31/files.a31"
 files		"../allwinner/a83t/files.a83t"
@@ -41,6 +44,8 @@ files		"../qemu/files.qemu"
 files		"../ti/files.ti"
 files		"../ti/am335x/files.am335x"
 
+options 	SOC_ALLWINNER_A10
+options 	SOC_ALLWINNER_A13
 options 	SOC_ALLWINNER_A20
 options 	SOC_ALLWINNER_A31
 options 	SOC_ALLWINNER_A31S
@@ -180,7 +185,7 @@ device		vlan			# 802.1Q VLAN support
 device		mii
 device		bpf
 
-#device		emac			# 10/100 integrated EMAC controller
+device		emac			# 10/100 integrated EMAC controller
 device		dwc			# 10/100/1000 integrated GMAC controller
 device		awg			# 10/100/1000 integrated EMAC controller
 

From 47a232c660e354877c06266484dca97a7733a2ad Mon Sep 17 00:00:00 2001
From: Michal Meloun 
Date: Fri, 4 Nov 2016 11:39:19 +0000
Subject: [PATCH 025/127] TEGRA: Add basic driver for memory controller. For
 now, it only reports memory and SMMU access errors.

---
 sys/arm/nvidia/tegra124/files.tegra124 |   1 +
 sys/arm/nvidia/tegra_mc.c              | 311 +++++++++++++++++++++++++
 2 files changed, 312 insertions(+)
 create mode 100644 sys/arm/nvidia/tegra_mc.c

diff --git a/sys/arm/nvidia/tegra124/files.tegra124 b/sys/arm/nvidia/tegra124/files.tegra124
index 7d9fcbaaf36d..8eaa009a4150 100644
--- a/sys/arm/nvidia/tegra124/files.tegra124
+++ b/sys/arm/nvidia/tegra124/files.tegra124
@@ -33,6 +33,7 @@ arm/nvidia/tegra_efuse.c		standard
 arm/nvidia/tegra_soctherm_if.m		standard
 arm/nvidia/tegra_soctherm.c		standard
 arm/nvidia/tegra_lic.c			standard
+arm/nvidia/tegra_mc.c			standard
 #arm/nvidia/tegra_hda.c			optional	snd_hda
 #arm/nvidia/drm2/hdmi.c			optional	drm2
 #arm/nvidia/drm2/tegra_drm_if.m		optional	drm2
diff --git a/sys/arm/nvidia/tegra_mc.c b/sys/arm/nvidia/tegra_mc.c
new file mode 100644
index 000000000000..82455ab475cb
--- /dev/null
+++ b/sys/arm/nvidia/tegra_mc.c
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+/*
+ * Memory controller driver for Tegra SoCs.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "clock_if.h"
+
+#define	MC_INTSTATUS			0x000
+#define	MC_INTMASK			0x004
+#define	 MC_INT_DECERR_MTS			(1 << 16)
+#define	 MC_INT_SECERR_SEC			(1 << 13)
+#define	 MC_INT_DECERR_VPR			(1 << 12)
+#define	 MC_INT_INVALID_APB_ASID_UPDATE		(1 << 11)
+#define	 MC_INT_INVALID_SMMU_PAGE		(1 << 10)
+#define	 MC_INT_ARBITRATION_EMEM		(1 << 9)
+#define	 MC_INT_SECURITY_VIOLATION		(1 << 8)
+#define	 MC_INT_DECERR_EMEM			(1 << 6)
+#define	 MC_INT_INT_MASK	(MC_INT_DECERR_MTS |			\
+				 MC_INT_SECERR_SEC |			\
+				 MC_INT_DECERR_VPR |			\
+				 MC_INT_INVALID_APB_ASID_UPDATE |	\
+				 MC_INT_INVALID_SMMU_PAGE |		\
+				 MC_INT_ARBITRATION_EMEM |		\
+				 MC_INT_SECURITY_VIOLATION |		\
+				 MC_INT_DECERR_EMEM)
+
+#define	MC_ERR_STATUS			0x008
+#define	 MC_ERR_TYPE(x)				(((x) >> 28) & 0x7)
+#define	 MC_ERR_TYPE_DECERR_EMEM		2
+#define	 MC_ERR_TYPE_SECURITY_TRUSTZONE		3
+#define	 MC_ERR_TYPE_SECURITY_CARVEOUT		4
+#define	 MC_ERR_TYPE_INVALID_SMMU_PAGE		6
+#define	 MC_ERR_INVALID_SMMU_PAGE_READABLE 	(1 << 27)
+#define	 MC_ERR_INVALID_SMMU_PAGE_WRITABLE	(1 << 26)
+#define	 MC_ERR_INVALID_SMMU_PAGE_NONSECURE	(1 << 25)
+#define	 MC_ERR_ADR_HI(x)			(((x) >> 20) & 0x3)
+#define	 MC_ERR_SWAP				(1 << 18)
+#define	 MC_ERR_SECURITY			(1 << 17)
+#define	 MC_ERR_RW				(1 << 16)
+#define	 MC_ERR_ADR1(x)				(((x) >> 12) & 0x7)
+#define	 MC_ERR_ID(x)				(((x) >> 0) & 07F)
+
+#define	MC_ERR_ADDR			0x00C
+#define	MC_EMEM_CFG			0x050
+#define	MC_EMEM_ADR_CFG			0x054
+#define	 MC_EMEM_NUMDEV(x)			(((x) >> 0 ) & 0x1)
+
+#define	MC_EMEM_ADR_CFG_DEV0		0x058
+#define	MC_EMEM_ADR_CFG_DEV1		0x05C
+#define	 EMEM_DEV_DEVSIZE(x)			(((x) >> 16) & 0xF)
+#define	 EMEM_DEV_BANKWIDTH(x)			(((x) >>  8) & 0x3)
+#define	 EMEM_DEV_COLWIDTH(x)			(((x) >>  8) & 0x3)
+
+#define	WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res, (_r), (_v))
+#define	RD4(_sc, _r)		bus_read_4((_sc)->mem_res, (_r))
+
+#define	LOCK(_sc)		mtx_lock(&(_sc)->mtx)
+#define	UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
+#define	SLEEP(_sc, timeout)	mtx_sleep(sc, &sc->mtx, 0, "tegra_mc", timeout);
+#define	LOCK_INIT(_sc)							\
+	mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_mc", MTX_DEF)
+#define	LOCK_DESTROY(_sc)	mtx_destroy(&_sc->mtx)
+#define	ASSERT_LOCKED(_sc)	mtx_assert(&_sc->mtx, MA_OWNED)
+#define	ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->mtx, MA_NOTOWNED)
+
+static struct ofw_compat_data compat_data[] = {
+	{"nvidia,tegra124-mc",	1},
+	{NULL,			0}
+};
+
+struct tegra_mc_softc {
+	device_t		dev;
+	struct mtx		mtx;
+
+	struct resource		*mem_res;
+	struct resource		*irq_res;
+	void			*irq_h;
+
+	clk_t			clk;
+};
+
+static char *smmu_err_tbl[16] = {
+	"reserved",		/*  0 */
+	"reserved",		/*  1 */
+	"DRAM decode",		/*  2 */
+	"Trustzome Security",	/*  3 */
+	"Security carveout",	/*  4 */
+	"reserved",		/*  5 */
+	"Invalid SMMU page",	/*  6 */
+	"reserved",	/*  7 */
+};
+
+static void
+tegra_mc_intr(void *arg)
+{
+	struct tegra_mc_softc *sc;
+	uint32_t stat, err;
+	uint64_t addr;
+
+	sc = (struct tegra_mc_softc *)arg;
+
+	stat = RD4(sc, MC_INTSTATUS);
+	if ((stat & MC_INT_INT_MASK) == 0) {
+		WR4(sc, MC_INTSTATUS, stat);
+		return;
+	}
+
+	device_printf(sc->dev, "Memory Controller Interrupt:\n");
+	if (stat & MC_INT_DECERR_MTS)
+		printf(" - MTS carveout violation\n");
+	if (stat & MC_INT_SECERR_SEC)
+		printf(" - SEC carveout violation\n");
+	if (stat & MC_INT_DECERR_VPR)
+		printf(" - VPR requirements violated\n");
+	if (stat & MC_INT_INVALID_APB_ASID_UPDATE)
+		printf(" - ivalid APB ASID update\n");
+	if (stat & MC_INT_INVALID_SMMU_PAGE)
+		printf(" - SMMU address translation error\n");
+	if (stat & MC_INT_ARBITRATION_EMEM)
+		printf(" - arbitration deadlock-prevention threshold hit\n");
+	if (stat & MC_INT_SECURITY_VIOLATION)
+		printf(" - SMMU address translation security error\n");
+	if (stat & MC_INT_DECERR_EMEM)
+		printf(" - SMMU address decode error\n");
+
+	if ((stat & (MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
+	   MC_INT_DECERR_EMEM)) != 0) {
+		err = RD4(sc, MC_ERR_STATUS);
+		addr = RD4(sc, MC_ERR_STATUS);
+		addr |= (uint64_t)(MC_ERR_ADR_HI(err)) << 32;
+		printf(" at 0x%012llX [%s %s %s]  - %s error.\n",
+		    addr,
+		    stat & MC_ERR_SWAP ? "Swap, " : "",
+		    stat & MC_ERR_SECURITY ? "Sec, " : "",
+		    stat & MC_ERR_RW ? "Write" : "Read",
+		    smmu_err_tbl[MC_ERR_TYPE(err)]);
+	}
+	WR4(sc, MC_INTSTATUS, stat);
+}
+
+static void
+tegra_mc_init_hw(struct tegra_mc_softc *sc)
+{
+
+	/* Disable and acknowledge all interrupts */
+	WR4(sc, MC_INTMASK, 0);
+	WR4(sc, MC_INTSTATUS, MC_INT_INT_MASK);
+}
+
+static int
+tegra_mc_probe(device_t dev)
+{
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+		return (ENXIO);
+	device_set_desc(dev, "Tegra Memory Controller");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_mc_attach(device_t dev)
+{
+	int rv, rid;
+	struct tegra_mc_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	LOCK_INIT(sc);
+
+	/* Get the memory resource for the register mapping. */
+	rid = 0;
+	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE);
+	if (sc->mem_res == NULL) {
+		device_printf(dev, "Cannot map registers.\n");
+		rv = ENXIO;
+		goto fail;
+	}
+
+	/* Allocate our IRQ resource. */
+	rid = 0;
+	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_ACTIVE);
+	if (sc->irq_res == NULL) {
+		device_printf(dev, "Cannot allocate interrupt.\n");
+		rv = ENXIO;
+		goto fail;
+	}
+
+	/* OFW resources. */
+	rv = clk_get_by_ofw_name(dev, 0, "mc", &sc->clk);
+	if (rv != 0) {
+		device_printf(dev, "Cannot get mc clock: %d\n", rv);
+		goto fail;
+	}
+	rv = clk_enable(sc->clk);
+	if (rv != 0) {
+		device_printf(dev, "Cannot enable clock: %d\n", rv);
+		goto fail;
+	}
+
+	/* Init hardware. */
+	tegra_mc_init_hw(sc);
+
+	/* Setup  interrupt */
+	rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+	    NULL, tegra_mc_intr, sc, &sc->irq_h);
+	if (rv) {
+		device_printf(dev, "Cannot setup interrupt.\n");
+		goto fail;
+	}
+
+	/* Enable Interrupts */
+	WR4(sc, MC_INTMASK, MC_INT_INT_MASK);
+
+	return (bus_generic_attach(dev));
+
+fail:
+	if (sc->clk != NULL)
+		clk_release(sc->clk);
+	if (sc->irq_h != NULL)
+		bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+	if (sc->irq_res != NULL)
+		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+	if (sc->mem_res != NULL)
+		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+	LOCK_DESTROY(sc);
+
+	return (rv);
+}
+
+static int
+tegra_mc_detach(device_t dev)
+{
+	struct tegra_mc_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (sc->irq_h != NULL)
+		bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+	if (sc->irq_res != NULL)
+		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+	if (sc->mem_res != NULL)
+		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+	LOCK_DESTROY(sc);
+	return (bus_generic_detach(dev));
+}
+
+static device_method_t tegra_mc_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		tegra_mc_probe),
+	DEVMETHOD(device_attach,	tegra_mc_attach),
+	DEVMETHOD(device_detach,	tegra_mc_detach),
+
+
+	DEVMETHOD_END
+};
+
+static devclass_t tegra_mc_devclass;
+static DEFINE_CLASS_0(mc, tegra_mc_driver, tegra_mc_methods,
+    sizeof(struct tegra_mc_softc));
+DRIVER_MODULE(tegra_mc, simplebus, tegra_mc_driver, tegra_mc_devclass,
+    NULL, NULL);

From 7961a970c782ae73ce6b1c7b73ce82d9d5635bf1 Mon Sep 17 00:00:00 2001
From: Michal Meloun 
Date: Fri, 4 Nov 2016 11:40:11 +0000
Subject: [PATCH 026/127] TEGRA: Fix numerous issues in clock code. Define and
 export clocks related to XUSB driver.

---
 sys/arm/nvidia/tegra124/tegra124_car.c     |  12 +-
 sys/arm/nvidia/tegra124/tegra124_clk_per.c | 233 +++++++++++----------
 sys/arm/nvidia/tegra124/tegra124_clk_pll.c |  38 +++-
 3 files changed, 159 insertions(+), 124 deletions(-)

diff --git a/sys/arm/nvidia/tegra124/tegra124_car.c b/sys/arm/nvidia/tegra124/tegra124_car.c
index 4a9549f54816..da366440f495 100644
--- a/sys/arm/nvidia/tegra124/tegra124_car.c
+++ b/sys/arm/nvidia/tegra124/tegra124_car.c
@@ -191,13 +191,13 @@ PLIST(mux_plle_src) = {"pllE_src1", "pllREFE_out"};
 PLIST(mux_plld_out0_plld2_out0) = {"pllD_out0", "pllD2_out0"};
 PLIST(mux_pllmcp_clkm) = {"pllM_out0", "pllC_out0", "pllP_out0", "clk_m",
     "pllM_UD", "pllC2_out0", "pllC3_out0", "pllC_UD"};
-PLIST(mux_xusb_hs) = {"pc_xusb_ss", "pllU_60"};
+PLIST(mux_xusb_hs) = {"xusb_ss_div2", "pllU_60"};
 PLIST(mux_xusb_ss) = {"pc_xusb_ss", "osc_div_clk"};
 
 
 /* Clocks ajusted online. */
 static struct clk_fixed_def fixed_clk_m =
-	FRATE(0, "clk_m", 12000000);
+	FRATE(TEGRA124_CLK_CLK_M, "clk_m", 12000000);
 static struct clk_fixed_def fixed_osc_div_clk =
 	FACT(0, "osc_div_clk", "clk_m", 1, 1);
 
@@ -222,6 +222,10 @@ static struct clk_fixed_def tegra124_fixed_clks[] = {
 	FRATE(0, "audio3", 10000000),
 	FRATE(0, "audio4", 10000000),
 	FRATE(0, "ext_vimclk", 10000000),
+
+	/* XUSB */
+	FACT(TEGRA124_CLK_XUSB_SS_DIV2, "xusb_ss_div2", "xusb_ss", 1, 2),
+
 };
 
 
@@ -239,7 +243,7 @@ static struct clk_mux_def tegra124_mux_clks[] = {
 	MUX(0, "emc_mux", mux_pllmcp_clkm, CLK_SOURCE_EMC, 29, 3),
 
 	/* USB. */
-	MUX(0, "xusb_hs", mux_xusb_hs, CLK_SOURCE_XUSB_SS, 25, 1),
+	MUX(TEGRA124_CLK_XUSB_HS_SRC, "xusb_hs", mux_xusb_hs, CLK_SOURCE_XUSB_SS, 25, 1),
 	MUX(0, "xusb_ss_mux", mux_xusb_ss, CLK_SOURCE_XUSB_SS, 24, 1),
 
 };
@@ -249,7 +253,7 @@ static struct clk_gate_def tegra124_gate_clks[] = {
 	/* Core clocks. */
 	GATE_PLL(0, "pllC_out1", "pllC_out1_div", PLLC_OUT, 0),
 	GATE_PLL(0, "pllM_out1", "pllM_out1_div", PLLM_OUT, 0),
-	GATE_PLL(0, "pllU_480", "pllU_out", PLLU_BASE, 22),
+	GATE_PLL(TEGRA124_CLK_PLL_U_480M, "pllU_480", "pllU_out", PLLU_BASE, 22),
 	GATE_PLL(0, "pllP_outX0", "pllP_outX0_div", PLLP_RESHIFT, 0),
 	GATE_PLL(0, "pllP_out1", "pllP_out1_div", PLLP_OUTA, 0),
 	GATE_PLL(0, "pllP_out2", "pllP_out2_div", PLLP_OUTA, 16),
diff --git a/sys/arm/nvidia/tegra124/tegra124_clk_per.c b/sys/arm/nvidia/tegra124/tegra124_clk_per.c
index 65ae5d9dbeab..7d0c9e5241f6 100644
--- a/sys/arm/nvidia/tegra124/tegra124_clk_per.c
+++ b/sys/arm/nvidia/tegra124/tegra124_clk_per.c
@@ -41,6 +41,15 @@ __FBSDID("$FreeBSD$");
 #include 
 #include "tegra124_car.h"
 
+/* The TEGRA124_CLK_XUSB_GATE is missing in current
+ * DT bindings, define it localy
+ */
+#ifdef TEGRA124_CLK_XUSB_GATE
+#error "TEGRA124_CLK_XUSB_GATE is now defined, revisit XUSB code!"
+#else
+#define TEGRA124_CLK_XUSB_GATE 143
+#endif
+
 /* Bits in base register. */
 #define	PERLCK_AMUX_MASK	0x0F
 #define	PERLCK_AMUX_SHIFT	16
@@ -175,7 +184,7 @@ PLIST(mux_sep_audio) =
     "spdif_in", "i2s0", "i2s1", "i2s2",
     "i2s4", "pllA_out0", "ext_vimclk"};
 
-static uint32_t clk_enabale_reg[] = {
+static uint32_t clk_enable_reg[] = {
 	CLK_OUT_ENB_L,
 	CLK_OUT_ENB_H,
 	CLK_OUT_ENB_U,
@@ -285,7 +294,7 @@ static struct pgate_def pgate_def[] = {
 	GATE(CSUS, "sus_out", "clk_m", U(28)),
 	/* GATE(DEVD2_OUT, "devd2_out", "clk_m", U(29)), */
 	/* GATE(DEVD1_OUT, "devd1_out", "clk_m", U(30)), */
-	GATE(XUSB_DEV_SRC, "xusb_core_dev", "pc_xusb_core_dev", U(31)),
+	GATE(XUSB_DEV, "xusb_core_dev", "pc_xusb_core_dev", U(31)),
 
 	/* bank V  -> 96-127 */
 	/* GATE(CPUG, "cpug", "clk_m", V(0)), */
@@ -328,7 +337,7 @@ static struct pgate_def pgate_def[] = {
 	/* GATE(HDMI_IOBIST, "hdmi_iobist", "clk_m", W(11)), */
 	/* GATE(SATA_IOBIST, "sata_iobist", "clk_m", W(12)), */
 	/* GATE(MIPI_IOBIST, "mipi_iobist", "clk_m", W(13)), */
-	/* GATE(XUSB_IOBIST, "xusb_iobist", "clk_m", W(15)), */
+	GATE(XUSB_GATE, "xusb_gate", "clk_m", W(15)),
 	GATE(CILAB, "cilab", "pc_cilab", W(16)),
 	GATE(CILCD, "cilcd", "pc_cilcd", W(17)),
 	GATE(CILE, "cile", "pc_cile", W(18)),
@@ -337,10 +346,10 @@ static struct pgate_def pgate_def[] = {
 	GATE(ENTROPY, "entropy", "pc_entropy", W(21)),
 	GATE(AMX, "amx", "pc_amx", W(25)),
 	GATE(ADX, "adx", "pc_adx", W(26)),
-	GATE(DFLL_REF, "dvfs_ref", "pc_dvfs_ref", X(27)),
-	GATE(DFLL_SOC, "dvfs_soc", "pc_dvfs_soc",  X(27)),
-	GATE(XUSB_SS_SRC, "xusb_ss", "xusb_ss_mux", X(28)),
-	/* GATE(EMC_LATENCY, "emc_latency", "pc_emc_latency", X(29)), */
+	GATE(DFLL_REF, "dvfs_ref", "pc_dvfs_ref", W(27)),
+	GATE(DFLL_SOC, "dvfs_soc", "pc_dvfs_soc",  W(27)),
+	GATE(XUSB_SS, "xusb_ss", "xusb_ss_mux", W(28)),
+	/* GATE(EMC_LATENCY, "emc_latency", "pc_emc_latency", W(29)), */
 
 	/* bank X -> 160-191*/
 	/* GATE(SPARE, "spare", "clk_m", X(0)), */
@@ -391,111 +400,115 @@ static struct pgate_def pgate_def[] = {
 }
 
 /* Mux with fractional 8.1 divider. */
-#define	CLK_8_1(cn, pl, r,  f)						\
-	PER_CLK(0, cn, pl, r,  8, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+#define	CLK_8_1(id, cn, pl, r,  f)					\
+	PER_CLK(id, cn, pl, r,  8, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+
 /* Mux with fractional 16.1 divider. */
-#define	CLK16_1(cn, pl, r,  f)						\
-	PER_CLK(0, cn, pl, r,  16, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+#define	CLK16_1(id, cn, pl, r,  f)					\
+	PER_CLK(id, cn, pl, r,  16, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
 /* Mux with integer 16bits divider. */
-#define	CLK16_0(cn, pl, r,  f)						\
-	PER_CLK(0, cn, pl, r,  16, 0, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+#define	CLK16_0(id, cn, pl, r,  f)					\
+	PER_CLK(id, cn, pl, r,  16, 0, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
 /* Mux wihout divider. */
-#define	CLK_0_0(cn, pl, r,  f)						\
-	PER_CLK(0, cn, pl, r,  0, 0, (f) | DCF_HAVE_MUX)
+#define	CLK_0_0(id, cn, pl, r,  f)					\
+	PER_CLK(id, cn, pl, r,  0, 0, (f) | DCF_HAVE_MUX)
 
 static struct periph_def periph_def[] = {
-	CLK_8_1("pc_i2s1", mux_a_N_audio1_N_p_N_clkm, CLK_SOURCE_I2S1, DCF_HAVE_ENA),
-	CLK_8_1("pc_i2s2", mux_a_N_audio2_N_p_N_clkm, CLK_SOURCE_I2S2, DCF_HAVE_ENA),
-	CLK_8_1("pc_spdif_out", mux_a_N_audio_N_p_N_clkm, CLK_SOURCE_SPDIF_OUT, 0),
-	CLK_8_1("pc_spdif_in", mux_p_c2_c_c3_m, CLK_SOURCE_SPDIF_IN, 0),
-	CLK_8_1("pc_pwm", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_PWM, 0),
-	CLK_8_1("pc_spi2", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI2, 0),
-	CLK_8_1("pc_spi3", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI3, 0),
-	CLK16_0("pc_i2c5", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C5, 0),
-	CLK16_0("pc_i2c1", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C1, 0),
-	CLK_8_1("pc_spi1", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI1, 0),
-	CLK_0_0("pc_disp1", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_DISP1, 0),
-	CLK_0_0("pc_disp2", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_DISP2, 0),
-	CLK_8_1("pc_isp", mux_m_c_p_a_c2_c3_clkm_c4, CLK_SOURCE_ISP, 0),
-	CLK_8_1("pc_vi", mux_m_c2_c_c3_p_N_a_c4, CLK_SOURCE_VI, DCF_IS_VI),
-	CLK_8_1("pc_sdmmc1", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC1, 0),
-	CLK_8_1("pc_sdmmc2", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC2, 0),
-	CLK_8_1("pc_sdmmc4", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC4, 0),
-	CLK_8_1("pc_vfir", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_VFIR, 0),
-	CLK_8_1("pc_hsi", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HSI, 0),
-	CLK16_1("pc_uarta", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTA, DCF_IS_UART),
-	CLK16_1("pc_uartb", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTB, DCF_IS_UART),
-	CLK_8_1("pc_host1x", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HOST1X, DCF_IS_HOST1X),
-	CLK_8_1("pc_hdmi", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_HDMI, 0),
-	CLK16_0("pc_i2c2", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C2, 0),
+	CLK_8_1(0, "pc_i2s1", mux_a_N_audio1_N_p_N_clkm, CLK_SOURCE_I2S1, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_i2s2", mux_a_N_audio2_N_p_N_clkm, CLK_SOURCE_I2S2, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_spdif_out", mux_a_N_audio_N_p_N_clkm, CLK_SOURCE_SPDIF_OUT, 0),
+	CLK_8_1(0, "pc_spdif_in", mux_p_c2_c_c3_m, CLK_SOURCE_SPDIF_IN, 0),
+	CLK_8_1(0, "pc_pwm", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_PWM, 0),
+	CLK_8_1(0, "pc_spi2", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI2, 0),
+	CLK_8_1(0, "pc_spi3", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI3, 0),
+	CLK16_0(0, "pc_i2c5", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C5, 0),
+	CLK16_0(0, "pc_i2c1", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C1, 0),
+	CLK_8_1(0, "pc_spi1", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI1, 0),
+	CLK_0_0(0, "pc_disp1", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_DISP1, 0),
+	CLK_0_0(0, "pc_disp2", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_DISP2, 0),
+	CLK_8_1(0, "pc_isp", mux_m_c_p_a_c2_c3_clkm_c4, CLK_SOURCE_ISP, 0),
+	CLK_8_1(0, "pc_vi", mux_m_c2_c_c3_p_N_a_c4, CLK_SOURCE_VI, DCF_IS_VI),
+	CLK_8_1(0, "pc_sdmmc1", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC1, 0),
+	CLK_8_1(0, "pc_sdmmc2", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC2, 0),
+	CLK_8_1(0, "pc_sdmmc4", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC4, 0),
+	CLK_8_1(0, "pc_vfir", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_VFIR, 0),
+	CLK_8_1(0, "pc_hsi", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HSI, 0),
+	CLK16_1(0, "pc_uarta", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTA, DCF_IS_UART),
+	CLK16_1(0, "pc_uartb", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTB, DCF_IS_UART),
+	CLK_8_1(0, "pc_host1x", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HOST1X, DCF_IS_HOST1X),
+	CLK_8_1(0, "pc_hdmi", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_HDMI, 0),
+	CLK16_0(0, "pc_i2c2", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C2, 0),
 /* EMC  8 */
-	CLK16_1("pc_uartc", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTC, DCF_IS_UART),
-	CLK_8_1("pc_vi_sensor", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_VI_SENSOR, 0),
-	CLK_8_1("pc_spi4", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI4, 0),
-	CLK16_0("pc_i2c3", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C3, 0),
-	CLK_8_1("pc_sdmmc3", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC3, 0),
-	CLK16_1("pc_uartd", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTD, DCF_IS_UART),
-	CLK_8_1("pc_vde", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_VDE, 0),
-	CLK_8_1("pc_owr", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_OWR, 0),
-	CLK_8_1("pc_snor", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_NOR, 0),
-	CLK_8_1("pc_csite", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_CSITE, 0),
-	CLK_8_1("pc_i2s0", mux_a_N_audio0_N_p_N_clkm, CLK_SOURCE_I2S0, 0),
+	CLK16_1(0, "pc_uartc", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTC, DCF_IS_UART),
+	CLK_8_1(0, "pc_vi_sensor", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_VI_SENSOR, 0),
+	CLK_8_1(0, "pc_spi4", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI4, 0),
+	CLK16_0(0, "pc_i2c3", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C3, 0),
+	CLK_8_1(0, "pc_sdmmc3", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC3, 0),
+	CLK16_1(0, "pc_uartd", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTD, DCF_IS_UART),
+	CLK_8_1(0, "pc_vde", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_VDE, 0),
+	CLK_8_1(0, "pc_owr", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_OWR, 0),
+	CLK_8_1(0, "pc_snor", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_NOR, 0),
+	CLK_8_1(0, "pc_csite", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_CSITE, 0),
+	CLK_8_1(0, "pc_i2s0", mux_a_N_audio0_N_p_N_clkm, CLK_SOURCE_I2S0, 0),
 /* DTV xxx */
-	CLK_8_1("pc_msenc", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_MSENC, 0),
-	CLK_8_1("pc_tsec", mux_p_c2_c_c3_m_a_clkm, CLK_SOURCE_TSEC, 0),
+	CLK_8_1(0, "pc_msenc", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_MSENC, 0),
+	CLK_8_1(0, "pc_tsec", mux_p_c2_c_c3_m_a_clkm, CLK_SOURCE_TSEC, 0),
 /* SPARE2 */
 
 
-	CLK_8_1("pc_mselect", mux_p_c2_c_c3_m_clks_clkm, CLK_SOURCE_MSELECT, 0),
-	CLK_8_1("pc_tsensor", mux_p_c2_c_c3_clkm_N_clks, CLK_SOURCE_TSENSOR, 0),
-	CLK_8_1("pc_i2s3", mux_a_N_audio3_N_p_N_clkm, CLK_SOURCE_I2S3, DCF_HAVE_ENA),
-	CLK_8_1("pc_i2s4", mux_a_N_audio4_N_p_N_clkm, CLK_SOURCE_I2S4, DCF_HAVE_ENA),
-	CLK16_0("pc_i2c4", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C4, 0),
-	CLK_8_1("pc_spi5", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI5, 0),
-	CLK_8_1("pc_spi6", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI6, 0),
-	CLK_8_1("pc_audio", mux_sep_audio, CLK_SOURCE_AUDIO, DCF_IS_AUDIO),
-	CLK_8_1("pc_dam0", mux_sep_audio, CLK_SOURCE_DAM0, DCF_IS_AUDIO),
-	CLK_8_1("pc_dam1", mux_sep_audio, CLK_SOURCE_DAM1, DCF_IS_AUDIO),
-	CLK_8_1("pc_dam2",  mux_sep_audio, CLK_SOURCE_DAM2, DCF_IS_AUDIO),
-	CLK_8_1("pc_hda2codec_2x", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HDA2CODEC_2X, 0),
-	CLK_8_1("pc_actmon", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_ACTMON, 0),
-	CLK_8_1("pc_extperiph1", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH1, 0),
-	CLK_8_1("pc_extperiph2", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH2,  0),
-	CLK_8_1("pc_extperiph3", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH3, 0),
-	CLK_8_1("pc_i2c_slow", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_I2C_SLOW, 0),
+	CLK_8_1(0, "pc_mselect", mux_p_c2_c_c3_m_clks_clkm, CLK_SOURCE_MSELECT, 0),
+	CLK_8_1(0, "pc_tsensor", mux_p_c2_c_c3_clkm_N_clks, CLK_SOURCE_TSENSOR, 0),
+	CLK_8_1(0, "pc_i2s3", mux_a_N_audio3_N_p_N_clkm, CLK_SOURCE_I2S3, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_i2s4", mux_a_N_audio4_N_p_N_clkm, CLK_SOURCE_I2S4, DCF_HAVE_ENA),
+	CLK16_0(0, "pc_i2c4", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C4, 0),
+	CLK_8_1(0, "pc_spi5", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI5, 0),
+	CLK_8_1(0, "pc_spi6", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI6, 0),
+	CLK_8_1(0, "pc_audio", mux_sep_audio, CLK_SOURCE_AUDIO, DCF_IS_AUDIO),
+	CLK_8_1(0, "pc_dam0", mux_sep_audio, CLK_SOURCE_DAM0, DCF_IS_AUDIO),
+	CLK_8_1(0, "pc_dam1", mux_sep_audio, CLK_SOURCE_DAM1, DCF_IS_AUDIO),
+	CLK_8_1(0, "pc_dam2",  mux_sep_audio, CLK_SOURCE_DAM2, DCF_IS_AUDIO),
+	CLK_8_1(0, "pc_hda2codec_2x", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HDA2CODEC_2X, 0),
+	CLK_8_1(0, "pc_actmon", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_ACTMON, 0),
+	CLK_8_1(0, "pc_extperiph1", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH1, 0),
+	CLK_8_1(0, "pc_extperiph2", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH2,  0),
+	CLK_8_1(0, "pc_extperiph3", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH3, 0),
+	CLK_8_1(0, "pc_i2c_slow", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_I2C_SLOW, 0),
 /* SYS */
-	CLK_8_1("pc_sor0", mux_p_m_d_a_c_d2_clkm,  CLK_SOURCE_SOR0, DCF_IS_SOR0),
-	CLK_8_1("pc_sata_oob", mux_p_N_c_N_m_N_clkm, CLK_SOURCE_SATA_OOB, 0),
-	CLK_8_1("pc_sata", mux_p_N_c_N_m_N_clkm, CLK_SOURCE_SATA, FDS_IS_SATA),
-	CLK_8_1("pc_hda", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HDA, 0),
-
-
-	CLK_8_1("pc_xusb_core_host", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_CORE_HOST, 0),
-	CLK_8_1("pc_xusb_falcon", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_FALCON, 0),
-	CLK_8_1("pc_xusb_fs", mux_clkm_N_u48_N_p_N_u480, CLK_SOURCE_XUSB_FS, 0),
-	CLK_8_1("pc_xusb_core_dev", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_CORE_DEV, 0),
-	CLK_8_1("pc_xusb_ss", mux_clkm_refe_clks_u480_c_c2_c3_oscdiv, CLK_SOURCE_XUSB_SS, DCF_IS_XUSB_SS),
-	CLK_8_1("pc_cilab", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILAB, 0),
-	CLK_8_1("pc_cilcd", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILCD, 0),
-	CLK_8_1("pc_cile", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILE, 0),
-	CLK_8_1("pc_dsia_lp", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_DSIA_LP, 0),
-	CLK_8_1("pc_dsib_lp", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_DSIB_LP, 0),
-	CLK_8_1("pc_entropy", mux_p_clkm_clks_E, CLK_SOURCE_ENTROPY, 0),
-	CLK_8_1("pc_dvfs_ref", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_DVFS_REF, DCF_HAVE_ENA),
-	CLK_8_1("pc_dvfs_soc", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_DVFS_SOC, DCF_HAVE_ENA),
-	CLK_8_1("pc_traceclkin", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_TRACECLKIN, 0),
-	CLK_8_1("pc_adx", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_ADX, DCF_HAVE_ENA),
-	CLK_8_1("pc_amx", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_AMX, DCF_HAVE_ENA),
-	CLK_8_1("pc_emc_latency", mux_m_c_p_clkm_mud_c2_c3, CLK_SOURCE_EMC_LATENCY, 0),
-	CLK_8_1("pc_soc_therm", mux_m_c_p_a_c2_c3, CLK_SOURCE_SOC_THERM, 0),
-	CLK_8_1("pc_vi_sensor2", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_VI_SENSOR2, 0),
-	CLK16_0("pc_i2c6", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C6, 0),
-	CLK_8_1("pc_emc_dll", mux_m_c_p_clkm_mud_c2_c3, CLK_SOURCE_EMC_DLL, DCF_IS_EMC_DLL),
-	CLK_8_1("pc_hdmi_audio", mux_p_c_c2_clkm, CLK_SOURCE_HDMI_AUDIO, 0),
-	CLK_8_1("pc_clk72mhz", mux_p_c_c2_clkm, CLK_SOURCE_CLK72MHZ, 0),
-	CLK_8_1("pc_adx1", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_ADX1, DCF_HAVE_ENA),
-	CLK_8_1("pc_amx1", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_AMX1, DCF_HAVE_ENA),
-	CLK_8_1("pc_vic", mux_m_c_p_a_c2_c3_clkm, CLK_SOURCE_VIC, DCF_IS_VIC),
+	CLK_8_1(0, "pc_sor0", mux_p_m_d_a_c_d2_clkm,  CLK_SOURCE_SOR0, DCF_IS_SOR0),
+	CLK_8_1(0, "pc_sata_oob", mux_p_N_c_N_m_N_clkm, CLK_SOURCE_SATA_OOB, 0),
+	CLK_8_1(0, "pc_sata", mux_p_N_c_N_m_N_clkm, CLK_SOURCE_SATA, FDS_IS_SATA),
+	CLK_8_1(0, "pc_hda", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HDA, 0),
+	CLK_8_1(TEGRA124_CLK_XUSB_HOST_SRC,
+		   "pc_xusb_core_host", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_CORE_HOST, 0),
+	CLK_8_1(TEGRA124_CLK_XUSB_FALCON_SRC,
+		   "pc_xusb_falcon", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_FALCON, 0),
+	CLK_8_1(TEGRA124_CLK_XUSB_FS_SRC,
+		   "pc_xusb_fs", mux_clkm_N_u48_N_p_N_u480, CLK_SOURCE_XUSB_FS, 0),
+	CLK_8_1(TEGRA124_CLK_XUSB_DEV_SRC,
+		   "pc_xusb_core_dev", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_CORE_DEV, 0),
+	CLK_8_1(TEGRA124_CLK_XUSB_SS_SRC,
+		   "pc_xusb_ss", mux_clkm_refe_clks_u480_c_c2_c3_oscdiv, CLK_SOURCE_XUSB_SS, DCF_IS_XUSB_SS),
+	CLK_8_1(0, "pc_cilab", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILAB, 0),
+	CLK_8_1(0, "pc_cilcd", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILCD, 0),
+	CLK_8_1(0, "pc_cile", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILE, 0),
+	CLK_8_1(0, "pc_dsia_lp", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_DSIA_LP, 0),
+	CLK_8_1(0, "pc_dsib_lp", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_DSIB_LP, 0),
+	CLK_8_1(0, "pc_entropy", mux_p_clkm_clks_E, CLK_SOURCE_ENTROPY, 0),
+	CLK_8_1(0, "pc_dvfs_ref", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_DVFS_REF, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_dvfs_soc", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_DVFS_SOC, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_traceclkin", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_TRACECLKIN, 0),
+	CLK_8_1(0, "pc_adx", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_ADX, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_amx", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_AMX, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_emc_latency", mux_m_c_p_clkm_mud_c2_c3, CLK_SOURCE_EMC_LATENCY, 0),
+	CLK_8_1(0, "pc_soc_therm", mux_m_c_p_a_c2_c3, CLK_SOURCE_SOC_THERM, 0),
+	CLK_8_1(0, "pc_vi_sensor2", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_VI_SENSOR2, 0),
+	CLK16_0(0, "pc_i2c6", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C6, 0),
+	CLK_8_1(0, "pc_emc_dll", mux_m_c_p_clkm_mud_c2_c3, CLK_SOURCE_EMC_DLL, DCF_IS_EMC_DLL),
+	CLK_8_1(0, "pc_hdmi_audio", mux_p_c_c2_clkm, CLK_SOURCE_HDMI_AUDIO, 0),
+	CLK_8_1(0, "pc_clk72mhz", mux_p_c_c2_clkm, CLK_SOURCE_CLK72MHZ, 0),
+	CLK_8_1(0, "pc_adx1", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_ADX1, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_amx1", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_AMX1, DCF_HAVE_ENA),
+	CLK_8_1(0, "pc_vic", mux_m_c_p_a_c2_c3_clkm, CLK_SOURCE_VIC, DCF_IS_VIC),
 };
 
 static int periph_init(struct clknode *clk, device_t dev);
@@ -528,6 +541,7 @@ static clknode_method_t periph_methods[] = {
 };
 DEFINE_CLASS_1(tegra124_periph, tegra124_periph_class, periph_methods,
    sizeof(struct periph_sc), clknode_class);
+
 static int
 periph_init(struct clknode *clk, device_t dev)
 {
@@ -637,14 +651,13 @@ periph_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
 		divider++;
 
 	if (divider < (1 << sc->div_f_width))
-		 divider = 1 << sc->div_f_width;
+		 divider = 1 << (sc->div_f_width - 1);
 
-	if ((*stop != 0) &&
-	    ((flags & (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)) == 0) &&
-	    (*fout != (tmp / divider)))
-		return (ERANGE);
-
-	if ((flags & CLK_SET_DRYRUN) == 0) {
+	if (flags & CLK_SET_DRYRUN) {
+		if (((flags & (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)) == 0) &&
+		    (*fout != (tmp / divider)))
+			return (ERANGE);
+	} else {
 		DEVICE_LOCK(sc);
 		MD4(sc, sc->base_reg, sc->div_mask,
 		    (divider - (1 << sc->div_f_width)));
@@ -703,9 +716,9 @@ DEFINE_CLASS_1(tegra124_pgate, tegra124_pgate_class, pgate_methods,
 static uint32_t
 get_enable_reg(int idx)
 {
-	KASSERT(idx / 32 < nitems(clk_enabale_reg),
+	KASSERT(idx / 32 < nitems(clk_enable_reg),
 	    ("Invalid clock index for enable: %d", idx));
-	return (clk_enabale_reg[idx / 32]);
+	return (clk_enable_reg[idx / 32]);
 }
 
 static uint32_t
diff --git a/sys/arm/nvidia/tegra124/tegra124_clk_pll.c b/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
index 1d89e10c8eeb..89234552e9ae 100644
--- a/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
+++ b/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
@@ -205,6 +205,16 @@ static struct pdiv_table pllu_map[] = {
 	{0, 0}
 };
 
+static struct pdiv_table pllrefe_map[] = {
+	{1, 0},
+	{2, 1},
+	{3, 2},
+	{4, 3},
+	{5, 4},
+	{6, 5},
+	{0, 0},
+};
+
 static struct clk_pll_def pll_clks[] = {
 /* PLLM: 880 MHz Clock source for EMC 2x clock */
 	{
@@ -342,6 +352,7 @@ static struct clk_pll_def pll_clks[] = {
 		.lock_enable = PLLRE_MISC_LOCK_ENABLE,
 		.iddq_reg = PLLRE_MISC,
 		.iddq_mask = 1 << PLLRE_IDDQ_BIT,
+		.pdiv_table = pllrefe_map,
 		.mnp_bits = {8, 8, 4, 16},
 	},
 /* PLLE: generate the 100 MHz reference clock for USB 3.0 (spread spectrum) */
@@ -433,14 +444,14 @@ pdiv_to_reg(struct pll_sc *sc, uint32_t p_div)
 
 	tbl = sc->pdiv_table;
 	if (tbl == NULL)
-		return (ffs(p_div));
+		return (ffs(p_div) - 1);
 
 	while (tbl->divider != 0) {
 		if (p_div <= tbl->divider)
 			return (tbl->value);
 		tbl++;
 	}
-	return ~0;
+	return (0xFFFFFFFF);
 }
 
 static uint32_t
@@ -449,15 +460,15 @@ reg_to_pdiv(struct pll_sc *sc, uint32_t reg)
 	struct pdiv_table *tbl;
 
 	tbl = sc->pdiv_table;
-	if (tbl != NULL) {
-		while (tbl->divider) {
-			if (reg == tbl->value)
-				return (tbl->divider);
-			tbl++;
-		}
-		return (0);
+	if (tbl == NULL)
+		return (1 << reg);
+
+	while (tbl->divider) {
+		if (reg == tbl->value)
+			return (tbl->divider);
+		tbl++;
 	}
-	return (1 << reg);
+	return (0);
 }
 
 static uint32_t
@@ -790,6 +801,7 @@ pllrefe_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
 	m = 1;
 	p = 1;
 	n = *fout * p * m / fin;
+	dprintf("%s: m: %d, n: %d, p: %d\n", __func__, m, n, p);
 	return (pll_set_std(sc, fin, fout, flags, m, n, p));
 }
 
@@ -902,6 +914,7 @@ tegra124_pll_set_freq(struct clknode *clknode, uint64_t fin, uint64_t *fout,
 		rv = ENXIO;
 		break;
 	}
+
 	return (rv);
 }
 
@@ -921,6 +934,11 @@ tegra124_pll_init(struct clknode *clk, device_t dev)
 		reg |= sc->lock_enable;
 		WR4(sc, sc->misc_reg, reg);
 	}
+	if (sc->type == PLL_REFE) {
+		RD4(sc, sc->misc_reg, ®);
+		reg &= ~(1 << 29);	/* Diasble lock override */
+		WR4(sc, sc->misc_reg, reg);
+	}
 
 	clknode_init_parent_idx(clk, 0);
 	return(0);

From 1771e987ca6a2d0a04c129b9e828c2a55af3c54e Mon Sep 17 00:00:00 2001
From: Konstantin Belousov 
Date: Fri, 4 Nov 2016 12:58:50 +0000
Subject: [PATCH 027/127] Do not sleep in vm_wait() if pagedaemon did not yet
 started.  Panic instead.

Requests which cannot be satisfied by allocators at boot time often
have unrealizable parameters.  Waiting for the pagedaemon' start would
hang the boot if done in the thread0 context and just never succeed if
executed from another thread.  In fact, for very early stages, sleep
attempt panics with obscure diagnostic about the scheduler state, and
explicit panic in vm_wait() makes the investigation much shorter by
cut off the examination of the thread and scheduler.

Theoretically, some subsystem might grab a resource to exhaustion, and
free it later in the boot process.  If this unlikely scenario does
appear for real, the way to diagnose the trouble can be revisited.

Reported by:	emaste
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D8421
---
 sys/vm/vm_page.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 407a046f9471..a012a1697f2f 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -2738,6 +2738,8 @@ vm_wait(void)
 		msleep(&vm_pageout_pages_needed, &vm_page_queue_free_mtx,
 		    PDROP | PSWP, "VMWait", 0);
 	} else {
+		if (__predict_false(pageproc == NULL))
+			panic("vm_wait in early boot");
 		if (!vm_pageout_wanted) {
 			vm_pageout_wanted = true;
 			wakeup(&vm_pageout_wanted);

From 426b08bcd3a2bbb8af3b52c30b1a85bff6c1682f Mon Sep 17 00:00:00 2001
From: Ruslan Bukin 
Date: Fri, 4 Nov 2016 13:07:54 +0000
Subject: [PATCH 028/127] System Binary Interface (SBI) page was moved in
 latest version of Berkeley Boot Loader (BBL) due to code size increase.

We will need to dehardcode this somehow.

Sponsored by:	DARPA, AFRL
Sponsored by:	HEIF5
---
 sys/riscv/riscv/locore.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S
index 2b36e2e8aeb8..5edbf7887885 100644
--- a/sys/riscv/riscv/locore.S
+++ b/sys/riscv/riscv/locore.S
@@ -137,7 +137,7 @@ _start:
 
 	/* Create an L3 page for SBI */
 	la	s1, pagetable_l3_sbi
-	li	s2, 0x80009000
+	li	s2, 0x8000b000
 	srli	s2, s2, PAGE_SHIFT
 	li	a5, 511
 	li	t4, PTE_V | PTE_RX | PTE_W

From fa97669261eeccc1a7055da95f73695ff3dd74a5 Mon Sep 17 00:00:00 2001
From: Eric van Gyzen 
Date: Fri, 4 Nov 2016 15:11:51 +0000
Subject: [PATCH 029/127] Fix grammar in a fortune.

---
 usr.bin/fortune/datfiles/fortunes | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/usr.bin/fortune/datfiles/fortunes b/usr.bin/fortune/datfiles/fortunes
index 1aa54b557b15..d80f9e6f1e6f 100644
--- a/usr.bin/fortune/datfiles/fortunes
+++ b/usr.bin/fortune/datfiles/fortunes
@@ -58947,7 +58947,7 @@ You're not drunk if you can lie on the floor without holding on.
 %
 You're not my type.  For that matter, you're not even my species!!!
 %
-You're reasoning is excellent -- it's
+Your reasoning is excellent -- it's
 only your basic assumptions that are wrong.
 %
 You're ugly and your mother dresses you funny.

From e8664a318d8beef34af151969f20fd5f6a9bddd0 Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Fri, 4 Nov 2016 15:44:00 +0000
Subject: [PATCH 030/127] libgcc_s: make unspecified shlib symbols local

We want only symbols explicitly specified in the Version.map.

Sponsored by:	The FreeBSD Foundation
---
 lib/libgcc_s/Version.map | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/libgcc_s/Version.map b/lib/libgcc_s/Version.map
index b592c8746cdc..bd3eb93c685b 100644
--- a/lib/libgcc_s/Version.map
+++ b/lib/libgcc_s/Version.map
@@ -3,6 +3,7 @@
  */
 
 GCC_3.0 {
+global:
 	__absvdi2;
 	__absvsi2;
 	__addvdi3;
@@ -62,6 +63,8 @@ GCC_3.0 {
 	_Unwind_Resume;
 	_Unwind_SetGR;
 	_Unwind_SetIP;
+local:
+	*;
 };
 
 GCC_3.3 {

From 95a3636709a320c128705e73a30a40719d338a4e Mon Sep 17 00:00:00 2001
From: Oleksandr Tymoshenko 
Date: Fri, 4 Nov 2016 16:24:38 +0000
Subject: [PATCH 031/127] [gpio] Add GPIO driver for Intel Bay Trail SoC

Bay Trail has three banks of GPIOs exposed to userland as /dev/gpiocN,
where N is 1, 2, and 3. Pins in each bank are pre-named to match names
on boards schematics: GPIO_S0_SCnn, GPIO_S0_NCnn, and GPIO_S5_nn.

Controller supports edge-triggered and level-triggered interrupts but
current version of the driver does not have interrupts support
---
 sys/conf/files.amd64   |   1 +
 sys/conf/files.i386    |   1 +
 sys/dev/gpio/bytgpio.c | 435 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 437 insertions(+)
 create mode 100644 sys/dev/gpio/bytgpio.c

diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index a601dafe8a79..99d4aef326b1 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -270,6 +270,7 @@ dev/fdc/fdc.c			optional	fdc
 dev/fdc/fdc_acpi.c		optional	fdc
 dev/fdc/fdc_isa.c		optional	fdc isa
 dev/fdc/fdc_pccard.c		optional	fdc pccard
+dev/gpio/bytgpio.c		optional	bytgpio
 dev/hpt27xx/hpt27xx_os_bsd.c	optional	hpt27xx
 dev/hpt27xx/hpt27xx_osm_bsd.c	optional	hpt27xx
 dev/hpt27xx/hpt27xx_config.c	optional	hpt27xx
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index d2637b1951e6..681b81f218be 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -225,6 +225,7 @@ dev/fe/if_fe_isa.c		optional fe isa
 dev/glxiic/glxiic.c		optional glxiic
 dev/glxsb/glxsb.c		optional glxsb
 dev/glxsb/glxsb_hash.c		optional glxsb
+dev/gpio/bytgpio.c		optional	bytgpio
 dev/hpt27xx/hpt27xx_os_bsd.c	optional hpt27xx
 dev/hpt27xx/hpt27xx_osm_bsd.c	optional hpt27xx
 dev/hpt27xx/hpt27xx_config.c	optional hpt27xx
diff --git a/sys/dev/gpio/bytgpio.c b/sys/dev/gpio/bytgpio.c
new file mode 100644
index 000000000000..93a291eb04e7
--- /dev/null
+++ b/sys/dev/gpio/bytgpio.c
@@ -0,0 +1,435 @@
+/*-
+ * Copyright (c) 2016 Oleksandr Tymoshenko 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include "opt_acpi.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "gpio_if.h"
+
+/**
+ *	Macros for driver mutex locking
+ */
+#define	BYTGPIO_LOCK(_sc)		mtx_lock_spin(&(_sc)->sc_mtx)
+#define	BYTGPIO_UNLOCK(_sc)		mtx_unlock_spin(&(_sc)->sc_mtx)
+#define	BYTGPIO_LOCK_INIT(_sc)		\
+	mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
+	    "bytgpio", MTX_SPIN)
+#define	BYTGPIO_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
+#define	BYTGPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+#define	BYTGPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
+
+struct bytgpio_softc {
+	ACPI_HANDLE		sc_handle;
+	device_t		sc_dev;
+	device_t		sc_busdev;
+	struct mtx		sc_mtx;
+	int			sc_mem_rid;
+	struct resource		*sc_mem_res;
+	int			sc_npins;
+	const char*		sc_bank_prefix;
+	const int		*sc_pinpad_map;
+};
+
+static int	bytgpio_probe(device_t dev);
+static int	bytgpio_attach(device_t dev);
+
+#define SCORE_UID		1
+#define SCORE_BANK_PREFIX	"GPIO_S0_SC"
+const int bytgpio_score_pins[] = {
+	85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 36, 38, 39, 35, 40,
+	84, 62, 61, 64, 59, 54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
+	52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 95, 105, 70, 68, 67,
+	66, 69, 71, 65, 72, 86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
+	80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 2, 1, 0, 4, 6, 7, 9,
+	8, 33, 32, 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 24, 22, 5,
+	3, 10, 11, 106, 87, 91, 104, 97, 100
+};
+#define SCORE_PINS	nitems(bytgpio_score_pins)
+
+#define NCORE_UID		2
+#define NCORE_BANK_PREFIX	"GPIO_S0_NC"
+const int bytgpio_ncore_pins[] = {
+	19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 14, 15, 12, 26, 27,
+	1, 4, 8, 11, 0, 3, 6, 10, 13, 2, 5, 9, 7
+};
+#define	NCORE_PINS	nitems(bytgpio_ncore_pins)
+
+#define SUS_UID		3
+#define SUS_BANK_PREFIX	"GPIO_S5_"
+const int bytgpio_sus_pins[] = {
+        29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1,
+	8, 10, 19, 12, 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 26, 51,
+	56, 54, 49, 55, 48, 57, 50, 58, 52, 53, 59, 40
+};
+#define	SUS_PINS	nitems(bytgpio_sus_pins)
+
+#define	BYGPIO_PIN_REGISTER(sc, pin, reg)	((sc)->sc_pinpad_map[(pin)] * 16 + (reg))
+#define	BYTGPIO_PCONF0		0x0000
+#define	BYTGPIO_PAD_VAL		0x0008
+#define		BYTGPIO_PAD_VAL_LEVEL		(1 << 0)	
+#define		BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED	(1 << 1)
+#define		BYTGPIO_PAD_VAL_I_INPUT_ENABLED	(1 << 2)
+#define		BYTGPIO_PAD_VAL_DIR_MASK		(3 << 1)
+
+static inline uint32_t
+bytgpio_read_4(struct bytgpio_softc *sc, bus_size_t off)
+{
+	return (bus_read_4(sc->sc_mem_res, off));
+}
+
+static inline void
+bytgpio_write_4(struct bytgpio_softc *sc, bus_size_t off,
+    uint32_t val)
+{
+	bus_write_4(sc->sc_mem_res, off, val);
+}
+
+static device_t
+bytgpio_get_bus(device_t dev)
+{
+	struct bytgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	return (sc->sc_busdev);
+}
+
+static int
+bytgpio_pin_max(device_t dev, int *maxpin)
+{
+	struct bytgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	*maxpin = sc->sc_npins - 1;
+
+	return (0);
+}
+
+static int
+bytgpio_valid_pin(struct bytgpio_softc *sc, int pin)
+{
+
+	if (pin >= sc->sc_npins || sc->sc_mem_res == NULL)
+		return (EINVAL);
+
+	return (0);
+}
+
+static int
+bytgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+	struct bytgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+
+	return (0);
+}
+
+static int
+bytgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+	struct bytgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	/* Get the current pin state */
+	BYTGPIO_LOCK(sc);
+	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
+	val = bytgpio_read_4(sc, reg);
+	*flags = 0;
+	if ((val & BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED) == 0)
+		*flags |= GPIO_PIN_OUTPUT;
+	/*
+	 * this bit can be cleared to read current output value
+	 * sou output bit takes precedense
+	 */
+	else if ((val & BYTGPIO_PAD_VAL_I_INPUT_ENABLED) == 0)
+		*flags |= GPIO_PIN_INPUT;
+	BYTGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+bytgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+	struct bytgpio_softc *sc;
+	uint32_t reg, val;
+	uint32_t allowed;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+
+	/* 
+	 * Only directtion flag allowed
+	 */
+	if (flags & ~allowed)
+		return (EINVAL);
+
+	/* 
+	 * Not both directions simultaneously
+	 */
+	if ((flags & allowed) == allowed)
+		return (EINVAL);
+
+	/* Set the GPIO mode and state */
+	BYTGPIO_LOCK(sc);
+	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
+	val = bytgpio_read_4(sc, reg);
+	val = val | BYTGPIO_PAD_VAL_DIR_MASK;
+	if (flags & GPIO_PIN_INPUT)
+		val = val & ~BYTGPIO_PAD_VAL_I_INPUT_ENABLED;
+	if (flags & GPIO_PIN_OUTPUT)
+		val = val & ~BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED;
+	bytgpio_write_4(sc, reg, val);
+	BYTGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+bytgpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+	struct bytgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	/* Set a very simple name */
+	snprintf(name, GPIOMAXNAME, "%s%u", sc->sc_bank_prefix, pin);
+	name[GPIOMAXNAME - 1] = '\0';
+
+	return (0);
+}
+
+static int
+bytgpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+	struct bytgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	BYTGPIO_LOCK(sc);
+	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
+	val = bytgpio_read_4(sc, reg);
+	if (value == GPIO_PIN_LOW)
+		val = val & ~BYTGPIO_PAD_VAL_LEVEL;
+	else
+		val = val | BYTGPIO_PAD_VAL_LEVEL;
+	bytgpio_write_4(sc, reg, val);
+	BYTGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+bytgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
+{
+	struct bytgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	BYTGPIO_LOCK(sc);
+	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
+	/*
+	 * Enable input to read current value
+	 */
+	val = bytgpio_read_4(sc, reg);
+	val = val & ~BYTGPIO_PAD_VAL_I_INPUT_ENABLED;
+	bytgpio_write_4(sc, reg, val);
+	/*
+	 * And read actual value
+	 */
+	val = bytgpio_read_4(sc, reg);
+	if (val & BYTGPIO_PAD_VAL_LEVEL)
+		*value = GPIO_PIN_HIGH;
+	else
+		*value = GPIO_PIN_LOW;
+	BYTGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+bytgpio_pin_toggle(device_t dev, uint32_t pin)
+{
+	struct bytgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+	if (bytgpio_valid_pin(sc, pin) != 0)
+		return (EINVAL);
+
+	/* Toggle the pin */
+	BYTGPIO_LOCK(sc);
+	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
+	val = bytgpio_read_4(sc, reg);
+	val = val ^ BYTGPIO_PAD_VAL_LEVEL;
+	bytgpio_write_4(sc, reg, val);
+	BYTGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+bytgpio_probe(device_t dev)
+{
+	static char *gpio_ids[] = { "INT33FC", NULL };
+
+	if (acpi_disabled("gpio") ||
+	    ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL)
+	return (ENXIO);
+
+	device_set_desc(dev, "Intel Baytrail GPIO Controller");
+	return (0);
+}
+
+static int
+bytgpio_attach(device_t dev)
+{
+	struct bytgpio_softc	*sc;
+	ACPI_STATUS status;
+	int uid;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_handle = acpi_get_handle(dev);
+	status = acpi_GetInteger(sc->sc_handle, "_UID", &uid);
+	if (ACPI_FAILURE(status)) {
+		device_printf(dev, "failed to read _UID\n");
+		return (ENXIO);
+	}
+
+	switch (uid) {
+	case SCORE_UID:
+		sc->sc_npins = SCORE_PINS;
+		sc->sc_bank_prefix = SCORE_BANK_PREFIX;
+		sc->sc_pinpad_map = bytgpio_score_pins;
+		break;
+	case NCORE_UID:
+		sc->sc_npins = NCORE_PINS;
+		sc->sc_bank_prefix = NCORE_BANK_PREFIX;
+		sc->sc_pinpad_map = bytgpio_ncore_pins;
+		break;
+	case SUS_UID:
+		sc->sc_npins = SUS_PINS;
+		sc->sc_bank_prefix = SUS_BANK_PREFIX;
+		sc->sc_pinpad_map = bytgpio_sus_pins;
+		break;
+	default:
+		device_printf(dev, "invalid _UID value: %d\n", uid);
+	}
+
+	sc->sc_mem_rid = 0;
+	sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev,
+	    SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE);
+	if (sc->sc_mem_res == NULL) {
+		device_printf(dev, "can't allocate resource\n");
+		goto error;
+	}
+
+	BYTGPIO_LOCK_INIT(sc);
+
+	sc->sc_busdev = gpiobus_attach_bus(dev);
+	if (sc->sc_busdev == NULL) {
+		BYTGPIO_LOCK_DESTROY(sc);
+		bus_release_resource(dev, SYS_RES_MEMORY,
+		    sc->sc_mem_rid, sc->sc_mem_res);
+		return (ENXIO);
+	}
+
+	return (0);
+
+error:
+	return (ENXIO);
+}
+
+static device_method_t bytgpio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, bytgpio_probe),
+	DEVMETHOD(device_attach, bytgpio_attach),
+
+	/* GPIO protocol */
+	DEVMETHOD(gpio_get_bus, bytgpio_get_bus),
+	DEVMETHOD(gpio_pin_max, bytgpio_pin_max),
+	DEVMETHOD(gpio_pin_getname, bytgpio_pin_getname),
+	DEVMETHOD(gpio_pin_getflags, bytgpio_pin_getflags),
+	DEVMETHOD(gpio_pin_getcaps, bytgpio_pin_getcaps),
+	DEVMETHOD(gpio_pin_setflags, bytgpio_pin_setflags),
+	DEVMETHOD(gpio_pin_get, bytgpio_pin_get),
+	DEVMETHOD(gpio_pin_set, bytgpio_pin_set),
+	DEVMETHOD(gpio_pin_toggle, bytgpio_pin_toggle),
+
+	DEVMETHOD_END
+};
+
+static driver_t bytgpio_driver = {
+	"gpio",
+	bytgpio_methods,
+	sizeof(struct bytgpio_softc),
+};
+
+static devclass_t bytgpio_devclass;
+DRIVER_MODULE(bytgpio, acpi, bytgpio_driver, bytgpio_devclass, 0, 0);
+MODULE_DEPEND(bytgpio, acpi, 1, 1, 1);
+MODULE_DEPEND(bytgpio, gpio, 1, 1, 1);

From b575f33f67cfb4592fa534c7e874cfe3b80a8624 Mon Sep 17 00:00:00 2001
From: Scott Long 
Date: Fri, 4 Nov 2016 16:56:36 +0000
Subject: [PATCH 032/127] asc/ascq 44/0 is typically a non-transient, permanent
 error (at least until the components are reset).  Therefore retries are
 pointless.  This is very visible in SATL systems, for example an LSI SAS
 controller and a SATA HDD/SSD.

Reviewed by:	ken
Obtained from:	Netflix
MFC after:	3 days
---
 sys/cam/scsi/scsi_all.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index 9a89ae910b5d..ee45852811c7 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -2331,7 +2331,7 @@ static struct asc_table_entry asc_table[] = {
 	{ SST(0x43, 0x00, SS_RDEF,
 	    "Message error") },
 	/* DTLPWROMAEBKVF */
-	{ SST(0x44, 0x00, SS_RDEF,
+	{ SST(0x44, 0x00, SS_FATAL | EIO,
 	    "Internal target failure") },
 	/* DT P   MAEBKVF */
 	{ SST(0x44, 0x01, SS_RDEF,	/* XXX TBD */

From e98bb55f0b6a228c63ff5d11cde0d5634ce48bfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= 
Date: Fri, 4 Nov 2016 17:02:42 +0000
Subject: [PATCH 033/127] Use what(1) instead of strings(1).  It's simpler and
 always available.

PR:		213665
Submitted by:	Pawel Worach 
MFC after:	1 week
---
 bin/freebsd-version/freebsd-version.sh.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/bin/freebsd-version/freebsd-version.sh.in b/bin/freebsd-version/freebsd-version.sh.in
index a830d264916b..16034104d5cf 100644
--- a/bin/freebsd-version/freebsd-version.sh.in
+++ b/bin/freebsd-version/freebsd-version.sh.in
@@ -36,7 +36,7 @@ USERLAND_VERSION="@@REVISION@@-@@BRANCH@@"
 : ${LOADER_CONF_FILES:=$LOADER_DIR/defaults/loader.conf $LOADER_DIR/loader.conf $LOADER_DIR/loader.conf.local}
 LOADER_RE1='^\([A-Z_a-z][0-9A-Z_a-z]*=[-./0-9A-Z_a-z]\{1,\}\).*$'
 LOADER_RE2='^\([A-Z_a-z][0-9A-Z_a-z]*="[-./0-9A-Z_a-z]\{1,\}"\).*$'
-KERNEL_RE='^@(#)@@TYPE@@ \([-.0-9A-Za-z]\{1,\}\) .*$'
+KERNEL_RE='^@@TYPE@@ \([-.0-9A-Za-z]\{1,\}\) .*$'
 
 progname=$(basename $0)
 
@@ -67,7 +67,7 @@ kernel_version() {
 	if [ ! -f "$kernfile" -o ! -r "$kernfile" ] ; then
 		error "unable to locate kernel"
 	fi
-	strings "$kernfile" | sed -n "s/$KERNEL_RE/\\1/p"
+	what -qs "$kernfile" | sed -n "s/$KERNEL_RE/\\1/p"
 }
 
 #

From 90aabaafa55a7a3d48bf27db160b8f058298015d Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 17:04:45 +0000
Subject: [PATCH 034/127] Add clk_set_assigned

assigned-clock-parents are DT properties used to configure
some default parent clocks on one node.

Reviewed by:	mmel
MFC after:	2 weeks
---
 sys/dev/extres/clk/clk.c | 50 ++++++++++++++++++++++++++++++++++++++--
 sys/dev/extres/clk/clk.h |  2 ++
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/sys/dev/extres/clk/clk.c b/sys/dev/extres/clk/clk.c
index bcb0a263027e..9c189fa86699 100644
--- a/sys/dev/extres/clk/clk.c
+++ b/sys/dev/extres/clk/clk.c
@@ -1196,7 +1196,47 @@ clk_get_by_id(device_t dev, struct clkdom *clkdom, intptr_t id, clk_t *clk)
 #ifdef FDT
 
 int
-clk_get_by_ofw_index(device_t dev, phandle_t cnode, int idx, clk_t *clk)
+clk_set_assigned(device_t dev, phandle_t node)
+{
+	clk_t clk, clk_parent;
+	int error, nclocks, i;
+
+	error = ofw_bus_parse_xref_list_get_length(node,
+	    "assigned-clock-parents", "#clock-cells", &nclocks);
+
+	if (error != 0) {
+		device_printf(dev, "cannot parse assigned-clock-parents property\n");
+		return (error);
+	}
+
+	for (i = 0; i < nclocks; i++) {
+		error = clk_get_by_ofw_index_prop(dev, 0,
+		    "assigned-clock-parents", i, &clk_parent);
+		if (error != 0) {
+			device_printf(dev, "cannot get parent %d\n", i);
+			return (error);
+		}
+
+		error = clk_get_by_ofw_index_prop(dev, 0, "assigned-clocks",
+		    i, &clk);
+		if (error != 0) {
+			device_printf(dev, "cannot get assigned clock %d\n", i);
+			clk_release(clk_parent);
+			return (error);
+		}
+
+		error = clk_set_parent_by_clk(clk, clk_parent);
+		clk_release(clk_parent);
+		clk_release(clk);
+		if (error != 0)
+			return (error);
+	}
+
+	return (0);
+}
+
+int
+clk_get_by_ofw_index_prop(device_t dev, phandle_t cnode, const char *prop, int idx, clk_t *clk)
 {
 	phandle_t parent, *cells;
 	device_t clockdev;
@@ -1214,7 +1254,7 @@ clk_get_by_ofw_index(device_t dev, phandle_t cnode, int idx, clk_t *clk)
 	}
 
 
-	rv = ofw_bus_parse_xref_list_alloc(cnode, "clocks", "#clock-cells", idx,
+	rv = ofw_bus_parse_xref_list_alloc(cnode, prop, "#clock-cells", idx,
 	    &parent, &ncells, &cells);
 	if (rv != 0) {
 		return (rv);
@@ -1246,6 +1286,12 @@ clk_get_by_ofw_index(device_t dev, phandle_t cnode, int idx, clk_t *clk)
 	return (rv);
 }
 
+int
+clk_get_by_ofw_index(device_t dev, phandle_t cnode, int idx, clk_t *clk)
+{
+	return (clk_get_by_ofw_index_prop(dev, cnode, "clocks", idx, clk));
+}
+
 int
 clk_get_by_ofw_name(device_t dev, phandle_t cnode, const char *name, clk_t *clk)
 {
diff --git a/sys/dev/extres/clk/clk.h b/sys/dev/extres/clk/clk.h
index 60b8d2b77b75..9bd259997977 100644
--- a/sys/dev/extres/clk/clk.h
+++ b/sys/dev/extres/clk/clk.h
@@ -129,7 +129,9 @@ int clk_set_parent_by_clk(clk_t clk, clk_t parent);
 const char *clk_get_name(clk_t clk);
 
 #ifdef FDT
+int clk_set_assigned(device_t dev, phandle_t node);
 int clk_get_by_ofw_index(device_t dev, phandle_t node, int idx, clk_t *clk);
+int clk_get_by_ofw_index_prop(device_t dev, phandle_t cnode, const char *prop, int idx, clk_t *clk);
 int clk_get_by_ofw_name(device_t dev, phandle_t node, const char *name,
      clk_t *clk);
 int clk_parse_ofw_out_names(device_t dev, phandle_t node,

From 34cc1bf804d35d9c00b83cecc6b00e27e6e28f46 Mon Sep 17 00:00:00 2001
From: Scott Long 
Date: Fri, 4 Nov 2016 17:08:52 +0000
Subject: [PATCH 035/127] If the da periph probe state machine gets an asc=0x44
 error, the periph is not going to recover until the system is reset.  Treat
 it as a special case and don't allow it to fall through to quasi-success.

Reviewed by:	ken, imp
Obtained from:	Netflix
MFC after:	3 days
---
 sys/cam/scsi/scsi_da.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 16d8ef7b07ca..ffceb23a7c66 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -4310,8 +4310,14 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
 				 * direct access or optical disk device,
 				 * as long as it doesn't return a "Logical
 				 * unit not supported" (0x25) error.
+				 * "Internal Target Failure" (0x44) is also
+				 * special and typically means that the
+				 * device is a SATA drive behind a SATL
+				 * translation that's fallen into a
+				 * terminally fatal state.
 				 */
-				if ((have_sense) && (asc != 0x25)
+				if ((have_sense)
+				 && (asc != 0x25) && (asc != 0x44)
 				 && (error_code == SSD_CURRENT_ERROR)) {
 					const char *sense_key_desc;
 					const char *asc_desc;

From e3454ae8b34d72353bfa5421a225d1a80557651e Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 17:13:47 +0000
Subject: [PATCH 036/127] For AHB clock we need to set the assigned parents for
 cpufreq(4) to work.

MFC after:	2 weeks
---
 sys/arm/allwinner/clk/aw_ahbclk.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/sys/arm/allwinner/clk/aw_ahbclk.c b/sys/arm/allwinner/clk/aw_ahbclk.c
index 8edc52691650..451ad7e1ef66 100644
--- a/sys/arm/allwinner/clk/aw_ahbclk.c
+++ b/sys/arm/allwinner/clk/aw_ahbclk.c
@@ -350,6 +350,12 @@ aw_ahbclk_attach(device_t dev)
 		goto fail;
 	}
 
+	error = clk_set_assigned(dev, node);
+	if (error != 0) {
+		device_printf(dev, "cannot set assigned parents: %d\n", error);
+		goto fail;
+	}
+
 	if (bootverbose)
 		clkdom_dump(clkdom);
 

From 694cb8b8150d85a3dd18beb588920b43841791d2 Mon Sep 17 00:00:00 2001
From: Scott Long 
Date: Fri, 4 Nov 2016 17:25:47 +0000
Subject: [PATCH 037/127] Record the LogInfo field when reporting the
 IOCStatus.  Helps in debugging errors.

Submitted by:	slm
Obtained from:	Netflix
MFC after:	3 days
---
 sys/dev/mpr/mpr_sas.c | 10 ++++++----
 sys/dev/mps/mps_sas.c | 10 ++++++----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c
index d44e5026169d..bb5c7ee1aabe 100644
--- a/sys/dev/mpr/mpr_sas.c
+++ b/sys/dev/mpr/mpr_sas.c
@@ -2496,8 +2496,9 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
 		 */
 		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
 		mprsas_log_command(cm, MPR_INFO,
-		    "terminated ioc %x scsi %x state %x xfer %u\n",
-		    le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+		    "terminated ioc %x loginfo %x scsi %x state %x xfer %u\n",
+		    le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
+		    rep->SCSIStatus, rep->SCSIState,
 		    le32toh(rep->TransferCount));
 		break;
 	case MPI2_IOCSTATUS_INVALID_FUNCTION:
@@ -2512,8 +2513,9 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
 	case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
 	default:
 		mprsas_log_command(cm, MPR_XINFO,
-		    "completed ioc %x scsi %x state %x xfer %u\n",
-		    le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+		    "completed ioc %x loginfo %x scsi %x state %x xfer %u\n",
+		    le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
+		    rep->SCSIStatus, rep->SCSIState,
 		    le32toh(rep->TransferCount));
 		csio->resid = cm->cm_length;
 		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index 2ff4389a1a25..f39945b67877 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -2446,8 +2446,9 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
 		 */
 		mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
 		mpssas_log_command(cm, MPS_INFO,
-		    "terminated ioc %x scsi %x state %x xfer %u\n",
-		    le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+		    "terminated ioc %x loginfo %x scsi %x state %x xfer %u\n",
+		    le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
+		    rep->SCSIStatus, rep->SCSIState,
 		    le32toh(rep->TransferCount));
 		break;
 	case MPI2_IOCSTATUS_INVALID_FUNCTION:
@@ -2462,8 +2463,9 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
 	case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
 	default:
 		mpssas_log_command(cm, MPS_XINFO,
-		    "completed ioc %x scsi %x state %x xfer %u\n",
-		    le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+		    "completed ioc %x loginfo %x scsi %x state %x xfer %u\n",
+		    le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
+		    rep->SCSIStatus, rep->SCSIState,
 		    le32toh(rep->TransferCount));
 		csio->resid = cm->cm_length;
 		mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);

From 1ca819f642bbc371356f22aa7a9f5c88506a20e3 Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 19:21:11 +0000
Subject: [PATCH 038/127] Set rst_apb to NULL to avoid panic when release.

---
 sys/arm/allwinner/aw_cir.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sys/arm/allwinner/aw_cir.c b/sys/arm/allwinner/aw_cir.c
index 19f49fbe7761..4691ab0389e4 100644
--- a/sys/arm/allwinner/aw_cir.c
+++ b/sys/arm/allwinner/aw_cir.c
@@ -390,6 +390,7 @@ aw_ir_attach(device_t dev)
 	uint32_t val = 0;
 
 	clk_ir = clk_gate = NULL;
+	rst_abp = NULL;
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;

From 73e62e8c5c62e4067714aabb36a6dcbda0f25d91 Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 19:23:52 +0000
Subject: [PATCH 039/127] Fix r308306 by spelling variable correctly.

---
 sys/arm/allwinner/aw_cir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/arm/allwinner/aw_cir.c b/sys/arm/allwinner/aw_cir.c
index 4691ab0389e4..926109a4d123 100644
--- a/sys/arm/allwinner/aw_cir.c
+++ b/sys/arm/allwinner/aw_cir.c
@@ -390,7 +390,7 @@ aw_ir_attach(device_t dev)
 	uint32_t val = 0;
 
 	clk_ir = clk_gate = NULL;
-	rst_abp = NULL;
+	rst_apb = NULL;
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;

From c7fbd7722d7c6640bee5fbf8af3a0b1343eefd8b Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Fri, 4 Nov 2016 19:35:49 +0000
Subject: [PATCH 040/127] Connect new LLVM-based libgcc_eh & libgcc_s to the
 build

Compiler-rt and LLVM's libunwind provide a suitable replacement for
libgcc.a, libgcc_eh.a, and libgcc_s.so.

Remove the now-unused LLVM_LIBUNWIND block from gnu/lib/libgcc.

PR:		213480 [exp-run]
Reviewed by:	brooks, ed
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D8189
---
 Makefile.inc1           | 19 +++++++++++++++++--
 gnu/lib/Makefile        |  6 ++++--
 gnu/lib/libgcc/Makefile | 39 ---------------------------------------
 lib/Makefile            |  2 ++
 4 files changed, 23 insertions(+), 43 deletions(-)

diff --git a/Makefile.inc1 b/Makefile.inc1
index 2b00ff1422b8..eaa3d3fcbdf3 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -2001,7 +2001,7 @@ libraries: .MAKE .PHONY
 #
 # static libgcc.a prerequisite for shared libc
 #
-_prereq_libs= gnu/lib/libgcc lib/libcompiler_rt
+_prereq_libs= lib/libcompiler_rt
 .if ${MK_SSP} != "no"
 _prereq_libs+= gnu/lib/libssp/libssp_nonshared
 .endif
@@ -2013,7 +2013,6 @@ _prereq_libs+= gnu/lib/libssp/libssp_nonshared
 #
 _startup_libs=	gnu/lib/csu
 _startup_libs+=	lib/csu
-_startup_libs+=	gnu/lib/libgcc
 _startup_libs+=	lib/libcompiler_rt
 _startup_libs+=	lib/libc
 _startup_libs+=	lib/libc_nonshared
@@ -2021,11 +2020,27 @@ _startup_libs+=	lib/libc_nonshared
 _startup_libs+=	lib/libcxxrt
 .endif
 
+.if ${MK_LLVM_LIBUNWIND} != "no"
+_prereq_libs+=	lib/libgcc_eh lib/libgcc_s
+_startup_libs+=	lib/libgcc_eh lib/libgcc_s
+
+lib/libgcc_s__L: lib/libc__L
+lib/libgcc_s__L: lib/libc_nonshared__L
+.if ${MK_LIBCPLUSPLUS} != "no"
+lib/libcxxrt__L: lib/libgcc_s__L
+.endif
+
+.else # MK_LLVM_LIBUNWIND == no
+
+_prereq_libs+=	gnu/lib/libgcc
+_startup_libs+=	gnu/lib/libgcc
+
 gnu/lib/libgcc__L: lib/libc__L
 gnu/lib/libgcc__L: lib/libc_nonshared__L
 .if ${MK_LIBCPLUSPLUS} != "no"
 lib/libcxxrt__L: gnu/lib/libgcc__L
 .endif
+.endif
 
 _prebuild_libs=	${_kerberos5_lib_libasn1} \
 		${_kerberos5_lib_libhdb} \
diff --git a/gnu/lib/Makefile b/gnu/lib/Makefile
index 0e17c229ed23..036c42f89edb 100644
--- a/gnu/lib/Makefile
+++ b/gnu/lib/Makefile
@@ -3,8 +3,6 @@
 .include 
 
 SUBDIR=			csu
-SUBDIR+=		libgcc
-
 SUBDIR.${MK_DIALOG}+=	libdialog
 SUBDIR.${MK_GCC}+=	libgcov libgomp
 SUBDIR.${MK_SSP}+=	libssp
@@ -19,6 +17,10 @@ SUBDIR+=	libreadline
 SUBDIR+=		libregex
 .endif
 
+.if ${MK_LLVM_LIBUNWIND} == "no"
+SUBDIR+=		libgcc
+.endif
+
 # libsupc++ uses libstdc++ headers, although 'make includes' should
 # have taken care of that already.
 .if ${MK_GNUCXX} != "no"
diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile
index 6c32c367829f..0d53c12c843c 100644
--- a/gnu/lib/libgcc/Makefile
+++ b/gnu/lib/libgcc/Makefile
@@ -4,9 +4,6 @@ PACKAGE=	clibs
 GCCDIR=	${.CURDIR}/../../../contrib/gcc
 GCCLIB=	${.CURDIR}/../../../contrib/gcclibs
 CCDIR=	${.CURDIR}/../../usr.bin/cc
-COMPILERRTDIR=	${.CURDIR}/../../../contrib/compiler-rt
-UNWINDINCDIR=	${.CURDIR}/../../../contrib/llvm/projects/libunwind/include
-UNWINDSRCDIR=	${.CURDIR}/../../../contrib/llvm/projects/libunwind/src
 
 SHLIB_NAME=	libgcc_s.so.1
 SHLIBDIR?=	/lib
@@ -74,33 +71,6 @@ LIB2FUNCS+= _floatdi${mode} _floatundi${mode}
 LIB2ADD = $(LIB2FUNCS_EXTRA)
 LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
 
-# Additional sources to handle exceptions; overridden by targets as needed.
-.if ${MK_LLVM_LIBUNWIND} != "no"
-
-.PATH: ${COMPILERRTDIR}/lib/builtins
-.PATH: ${UNWINDSRCDIR}
-LIB2ADDEH = gcc_personality_v0.c \
-	int_util.c \
-	Unwind-EHABI.cpp \
-	Unwind-sjlj.c \
-	UnwindLevel1-gcc-ext.c \
-	UnwindLevel1.c \
-	UnwindRegistersRestore.S \
-	UnwindRegistersSave.S \
-	libunwind.cpp
-
-CFLAGS+=	-I${UNWINDINCDIR} -I${.CURDIR} -D_LIBUNWIND_IS_NATIVE_ONLY
-.if empty(CXXFLAGS:M-std=*)
-CXXFLAGS+=	-std=c++11
-.endif
-CXXFLAGS+=	-fno-rtti
-STATIC_CXXFLAGS+= -fvisibility=hidden -fPIC
-.if ${MK_DIRDEPS_BUILD} == "yes"
-# Avoid dependency on lib/libc++
-CFLAGS+=	-I${SRCTOP}/contrib/libc++/include
-.endif
-
-.else # MK_LLVM_LIBUNWIND
 
 .if ${TARGET_CPUARCH} == "arm"
 LIB2ADDEH =	unwind-arm.c libunwind-arm.S pr-support.c unwind-c.c
@@ -109,8 +79,6 @@ LIB2ADDEH = unwind-dw2.c unwind-dw2-fde-glibc.c unwind-sjlj.c gthr-gnat.c \
 	unwind-c.c
 .endif
 
-.endif # MK_LLVM_LIBUNWIND
-
 LIB2ADDEHSTATIC = $(LIB2ADDEH)
 LIB2ADDEHSHARED = $(LIB2ADDEH)
 
@@ -202,14 +170,7 @@ LIB2_DIVMOD_FUNCS:= ${LIB2_DIVMOD_FUNCS:S/${sym}//g}
 .endif
 
 COMMONHDRS=	tm.h tconfig.h options.h gthr-default.h
-.if ${MK_LLVM_LIBUNWIND} != "no"
-# unwind.h is a generated file when MK_LLVM_LIBUNWIND == "no", and a stale
-# copy may be left behind in OBJDIR when switching, so remove it explicitly.
-beforebuild:
-	@rm -f ${.OBJDIR}/unwind.h
-.else
 COMMONHDRS+=	unwind.h
-.endif
 
 #-----------------------------------------------------------------------
 #
diff --git a/lib/Makefile b/lib/Makefile
index 3dc1258051fd..f2f3b8594c4a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -160,6 +160,8 @@ _libcplusplus=	libc++
 
 SUBDIR.${MK_EFI}+=	libefivar
 SUBDIR.${MK_LIBTHR}+=	libthr
+SUBDIR.${MK_LLVM_LIBUNWIND}+=	libgcc_eh
+SUBDIR.${MK_LLVM_LIBUNWIND}+=	libgcc_s
 SUBDIR.${MK_NAND}+=	libnandfs
 SUBDIR.${MK_NETGRAPH}+=	libnetgraph
 SUBDIR.${MK_NIS}+=	libypclnt

From 6988dd5e618fe2c0f1034b59b977289060c6d90f Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 20:02:52 +0000
Subject: [PATCH 041/127] Add support for AXP221 Power Management Unit.

AXP221 is used on board with A31/A31S and is mostly compatible with AXP209.
Regulators, GPIO and Sensors are supported.

MFC after:	2 weeks
---
 sys/arm/allwinner/axp209.c    | 1155 +++++++++++++++++++++++----------
 sys/arm/allwinner/axp209reg.h |  228 ++++---
 2 files changed, 954 insertions(+), 429 deletions(-)

diff --git a/sys/arm/allwinner/axp209.c b/sys/arm/allwinner/axp209.c
index 2c007424e9fb..845c316ca03e 100644
--- a/sys/arm/allwinner/axp209.c
+++ b/sys/arm/allwinner/axp209.c
@@ -27,9 +27,11 @@
 
 #include 
 __FBSDID("$FreeBSD$");
+
 /*
-* X-Power AXP209 PMU for Allwinner SoCs
+* X-Power AXP209/AXP211 PMU for Allwinner SoCs
 */
+
 #include 
 #include 
 #include 
@@ -61,9 +63,9 @@ __FBSDID("$FreeBSD$");
 #include "gpio_if.h"
 #include "regdev_if.h"
 
-MALLOC_DEFINE(M_AXP209_REG, "Axp209 regulator", "Axp209 power regulator");
+MALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
 
-struct axp209_regdef {
+struct axp2xx_regdef {
 	intptr_t		id;
 	char			*name;
 	uint8_t			enable_reg;
@@ -77,7 +79,7 @@ struct axp209_regdef {
 	int			voltage_nstep;
 };
 
-static struct axp209_regdef axp209_regdefs[] = {
+static struct axp2xx_regdef axp209_regdefs[] = {
 	{
 		.id = AXP209_REG_ID_DCDC2,
 		.name = "dcdc2",
@@ -129,36 +131,503 @@ static struct axp209_regdef axp209_regdefs[] = {
 	},
 };
 
-struct axp209_reg_sc {
+static struct axp2xx_regdef axp221_regdefs[] = {
+	{
+		.id = AXP221_REG_ID_DLDO1,
+		.name = "dldo1",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO1,
+		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DLDO2,
+		.name = "dldo2",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO2,
+		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DLDO3,
+		.name = "dldo3",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO3,
+		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DLDO4,
+		.name = "dldo4",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO4,
+		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ELDO1,
+		.name = "eldo1",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_ELDO1,
+		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ELDO2,
+		.name = "eldo2",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_ELDO2,
+		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ELDO3,
+		.name = "eldo3",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_ELDO3,
+		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DC5LDO,
+		.name = "dc5ldo",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DC5LDO,
+		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
+		.voltage_mask = 0x3,
+		.voltage_min = 700,
+		.voltage_max = 1400,
+		.voltage_step = 100,
+		.voltage_nstep = 7,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC1,
+		.name = "dcdc1",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC1,
+		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 1600,
+		.voltage_max = 3400,
+		.voltage_step = 100,
+		.voltage_nstep = 18,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC2,
+		.name = "dcdc2",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC2,
+		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
+		.voltage_mask = 0x3f,
+		.voltage_min = 600,
+		.voltage_max = 1540,
+		.voltage_step = 20,
+		.voltage_nstep = 47,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC3,
+		.name = "dcdc3",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC3,
+		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
+		.voltage_mask = 0x3f,
+		.voltage_min = 600,
+		.voltage_max = 1860,
+		.voltage_step = 20,
+		.voltage_nstep = 63,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC4,
+		.name = "dcdc4",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC4,
+		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
+		.voltage_mask = 0x3f,
+		.voltage_min = 600,
+		.voltage_max = 1540,
+		.voltage_step = 20,
+		.voltage_nstep = 47,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC5,
+		.name = "dcdc5",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC5,
+		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 1000,
+		.voltage_max = 2550,
+		.voltage_step = 50,
+		.voltage_nstep = 31,
+	},
+	{
+		.id = AXP221_REG_ID_ALDO1,
+		.name = "aldo1",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_ALDO1,
+		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ALDO2,
+		.name = "aldo2",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_ALDO2,
+		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ALDO3,
+		.name = "aldo3",
+		.enable_reg = AXP221_POWERCTL_3,
+		.enable_mask = AXP221_POWERCTL3_ALDO3,
+		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DC1SW,
+		.name = "dc1sw",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DC1SW,
+	},
+};
+
+struct axp2xx_reg_sc {
 	struct regnode		*regnode;
 	device_t		base_dev;
-	struct axp209_regdef	*def;
+	struct axp2xx_regdef	*def;
 	phandle_t		xref;
 	struct regnode_std_param *param;
 };
 
-struct axp209_softc {
+struct axp2xx_pins {
+	const char	*name;
+	uint8_t		ctrl_reg;
+	uint8_t		status_reg;
+	uint8_t		status_mask;
+	uint8_t		status_shift;
+};
+
+/* GPIO3 is different, don't expose it for now */
+static const struct axp2xx_pins axp209_pins[] = {
+	{
+		.name = "GPIO0",
+		.ctrl_reg = AXP2XX_GPIO0_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x10,
+		.status_shift = 4,
+	},
+	{
+		.name = "GPIO1",
+		.ctrl_reg = AXP2XX_GPIO1_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x20,
+		.status_shift = 5,
+	},
+	{
+		.name = "GPIO2",
+		.ctrl_reg = AXP209_GPIO2_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x40,
+		.status_shift = 6,
+	},
+};
+
+static const struct axp2xx_pins axp221_pins[] = {
+	{
+		.name = "GPIO0",
+		.ctrl_reg = AXP2XX_GPIO0_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x1,
+		.status_shift = 0x0,
+	},
+	{
+		.name = "GPIO1",
+		.ctrl_reg = AXP2XX_GPIO0_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x2,
+		.status_shift = 0x1,
+	},
+};
+
+struct axp2xx_sensors {
+	int		id;
+	const char	*name;
+	const char	*desc;
+	const char	*format;
+	uint8_t		enable_reg;
+	uint8_t		enable_mask;
+	uint8_t		value_reg;
+	uint8_t		value_size;
+	uint8_t		h_value_mask;
+	uint8_t		h_value_shift;
+	uint8_t		l_value_mask;
+	uint8_t		l_value_shift;
+	int		value_step;
+	int		value_convert;
+};
+
+static const struct axp2xx_sensors axp209_sensors[] = {
+	{
+		.id = AXP209_ACVOLT,
+		.name = "acvolt",
+		.desc = "AC Voltage (microvolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_ACVOLT,
+		.value_reg = AXP209_ACIN_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_VOLT_STEP,
+	},
+	{
+		.id = AXP209_ACCURRENT,
+		.name = "accurrent",
+		.desc = "AC Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_ACCURRENT,
+		.value_reg = AXP209_ACIN_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_ACCURRENT_STEP,
+	},
+	{
+		.id = AXP209_VBUSVOLT,
+		.name = "vbusvolt",
+		.desc = "VBUS Voltage (microVolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_VBUSVOLT,
+		.value_reg = AXP209_VBUS_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_VOLT_STEP,
+	},
+	{
+		.id = AXP209_VBUSCURRENT,
+		.name = "vbuscurrent",
+		.desc = "VBUS Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_VBUSCURRENT,
+		.value_reg = AXP209_VBUS_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_VBUSCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_BATVOLT,
+		.name = "batvolt",
+		.desc = "Battery Voltage (microVolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATVOLT,
+		.value_reg = AXP2XX_BAT_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATVOLT_STEP,
+	},
+	{
+		.id = AXP2XX_BATCHARGECURRENT,
+		.name = "batchargecurrent",
+		.desc = "Battery Charging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_BATDISCHARGECURRENT,
+		.name = "batdischargecurrent",
+		.desc = "Battery Discharging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_TEMP,
+		.name = "temp",
+		.desc = "Internal Temperature",
+		.format = "IK",
+		.enable_reg = AXP209_ADC_ENABLE2,
+		.enable_mask = AXP209_ADC2_TEMP,
+		.value_reg = AXP209_TEMPMON,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = 1,
+		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
+	},
+};
+
+static const struct axp2xx_sensors axp221_sensors[] = {
+	{
+		.id = AXP2XX_BATVOLT,
+		.name = "batvolt",
+		.desc = "Battery Voltage (microVolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATVOLT,
+		.value_reg = AXP2XX_BAT_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATVOLT_STEP,
+	},
+	{
+		.id = AXP2XX_BATCHARGECURRENT,
+		.name = "batchargecurrent",
+		.desc = "Battery Charging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_BATDISCHARGECURRENT,
+		.name = "batdischargecurrent",
+		.desc = "Battery Discharging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_TEMP,
+		.name = "temp",
+		.desc = "Internal Temperature",
+		.format = "IK",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP221_ADC1_TEMP,
+		.value_reg = AXP221_TEMPMON,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = 1,
+		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
+	},
+};
+
+enum AXP2XX_TYPE {
+	AXP209 = 1,
+	AXP221,
+};
+
+struct axp2xx_softc {
 	device_t		dev;
 	uint32_t		addr;
 	struct resource *	res[1];
 	void *			intrcookie;
 	struct intr_config_hook	intr_hook;
-	device_t		gpiodev;
 	struct mtx		mtx;
+	uint8_t			type;
+
+	/* GPIO */
+	device_t		gpiodev;
+	int			npins;
+	const struct axp2xx_pins	*pins;
+
+	/* Sensors */
+	const struct axp2xx_sensors	*sensors;
+	int				nsensors;
 
 	/* Regulators */
-	struct axp209_reg_sc	**regs;
+	struct axp2xx_reg_sc	**regs;
 	int			nregs;
+	struct axp2xx_regdef	*regdefs;
 };
 
-/* GPIO3 is different, don't expose it for now */
-static const struct {
-	const char *name;
-	uint8_t	ctrl_reg;
-} axp209_pins[] = {
-	{ "GPIO0", AXP209_GPIO0_CTRL },
-	{ "GPIO1", AXP209_GPIO1_CTRL },
-	{ "GPIO2", AXP209_GPIO2_CTRL },
+static struct ofw_compat_data compat_data[] = {
+	{ "x-powers,axp209",		AXP209 },
+	{ "x-powers,axp221",		AXP221 },
+	{ NULL,				0 }
 };
 
 static struct resource_spec axp_res_spec[] = {
@@ -170,9 +639,9 @@ static struct resource_spec axp_res_spec[] = {
 #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
 
 static int
-axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
+axp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
 {
-	struct axp209_softc *sc = device_get_softc(dev);
+	struct axp2xx_softc *sc = device_get_softc(dev);
 	struct iic_msg msg[2];
 
 	msg[0].slave = sc->addr;
@@ -189,43 +658,62 @@ axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
 }
 
 static int
-axp209_write(device_t dev, uint8_t reg, uint8_t data)
+axp2xx_write(device_t dev, uint8_t reg, uint8_t data)
 {
 	uint8_t buffer[2];
-	struct axp209_softc *sc = device_get_softc(dev);
-	struct iic_msg msg;
+	struct axp2xx_softc *sc = device_get_softc(dev);
+	struct iic_msg msg[2];
+	int nmsgs = 0;
 
-	buffer[0] = reg;
-	buffer[1] = data;
+	if (sc->type == AXP209) {
+		buffer[0] = reg;
+		buffer[1] = data;
 
-	msg.slave = sc->addr;
-	msg.flags = IIC_M_WR;
-	msg.len = 2;
-	msg.buf = buffer;
+		msg[0].slave = sc->addr;
+		msg[0].flags = IIC_M_WR;
+		msg[0].len = 2;
+		msg[0].buf = buffer;
 
-	return (iicbus_transfer(dev, &msg, 1));
+		nmsgs = 1;
+	}
+	else if (sc->type == AXP221) {
+		msg[0].slave = sc->addr;
+		msg[0].flags = IIC_M_WR;
+		msg[0].len = 1;
+		msg[0].buf = ®
+
+		msg[1].slave = sc->addr;
+		msg[1].flags = IIC_M_WR;
+		msg[1].len = 1;
+		msg[1].buf = &data;
+		nmsgs = 2;
+	}
+	else
+		return (EINVAL);
+
+	return (iicbus_transfer(dev, msg, nmsgs));
 }
 
 static int
-axp209_regnode_init(struct regnode *regnode)
+axp2xx_regnode_init(struct regnode *regnode)
 {
 	return (0);
 }
 
 static int
-axp209_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
+axp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
 {
-	struct axp209_reg_sc *sc;
+	struct axp2xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
 
-	axp209_read(sc->base_dev, sc->def->enable_reg, &val, 1);
+	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
 	if (enable)
 		val |= sc->def->enable_mask;
 	else
 		val &= ~sc->def->enable_mask;
-	axp209_write(sc->base_dev, sc->def->enable_reg, val);
+	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
 
 	*udelay = 0;
 
@@ -233,7 +721,7 @@ axp209_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
 }
 
 static void
-axp209_regnode_reg_to_voltage(struct axp209_reg_sc *sc, uint8_t val, int *uv)
+axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
 {
 	if (val < sc->def->voltage_nstep)
 		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
@@ -244,7 +732,7 @@ axp209_regnode_reg_to_voltage(struct axp209_reg_sc *sc, uint8_t val, int *uv)
 }
 
 static int
-axp209_regnode_voltage_to_reg(struct axp209_reg_sc *sc, int min_uvolt,
+axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
     int max_uvolt, uint8_t *val)
 {
 	uint8_t nval;
@@ -266,10 +754,10 @@ axp209_regnode_voltage_to_reg(struct axp209_reg_sc *sc, int min_uvolt,
 }
 
 static int
-axp209_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
+axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
     int max_uvolt, int *udelay)
 {
-	struct axp209_reg_sc *sc;
+	struct axp2xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
@@ -277,10 +765,10 @@ axp209_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
 	if (!sc->def->voltage_step)
 		return (ENXIO);
 
-	if (axp209_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
+	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
 		return (ERANGE);
 
-	axp209_write(sc->base_dev, sc->def->voltage_reg, val);
+	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
 
 	*udelay = 0;
 
@@ -288,9 +776,9 @@ axp209_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
 }
 
 static int
-axp209_regnode_get_voltage(struct regnode *regnode, int *uvolt)
+axp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
 {
-	struct axp209_reg_sc *sc;
+	struct axp2xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
@@ -298,106 +786,60 @@ axp209_regnode_get_voltage(struct regnode *regnode, int *uvolt)
 	if (!sc->def->voltage_step)
 		return (ENXIO);
 
-	axp209_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
-	axp209_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
+	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
+	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
 
 	return (0);
 }
 
-static regnode_method_t axp209_regnode_methods[] = {
+static regnode_method_t axp2xx_regnode_methods[] = {
 	/* Regulator interface */
-	REGNODEMETHOD(regnode_init,		axp209_regnode_init),
-	REGNODEMETHOD(regnode_enable,		axp209_regnode_enable),
-	REGNODEMETHOD(regnode_set_voltage,	axp209_regnode_set_voltage),
-	REGNODEMETHOD(regnode_get_voltage,	axp209_regnode_get_voltage),
+	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
+	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
+	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
+	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
 	REGNODEMETHOD_END
 };
-DEFINE_CLASS_1(axp209_regnode, axp209_regnode_class, axp209_regnode_methods,
-    sizeof(struct axp209_reg_sc), regnode_class);
+DEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
+    sizeof(struct axp2xx_reg_sc), regnode_class);
 
 static int
-axp209_sysctl(SYSCTL_HANDLER_ARGS)
+axp2xx_sysctl(SYSCTL_HANDLER_ARGS)
 {
+	struct axp2xx_softc *sc;
 	device_t dev = arg1;
-	enum axp209_sensor sensor = arg2;
+	enum axp2xx_sensor sensor = arg2;
 	uint8_t data[2];
-	int val, error;
+	int val, error, i, found;
 
-	switch (sensor) {
-	case AXP209_TEMP:
-		error = axp209_read(dev, AXP209_TEMPMON, data, 2);
-		if (error != 0)
-			return (error);
+	sc = device_get_softc(dev);
 
-		/* Temperature is between -144.7C and 264.8C, step +0.1C */
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) -
-		    AXP209_TEMPMON_MIN + AXP209_0C_TO_K;
-		break;
-	case AXP209_ACVOLT:
-		error = axp209_read(dev, AXP209_ACIN_VOLTAGE, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_VOLT_STEP;
-		break;
-	case AXP209_ACCURRENT:
-		error = axp209_read(dev, AXP209_ACIN_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_ACCURRENT_STEP;
-		break;
-	case AXP209_VBUSVOLT:
-		error = axp209_read(dev, AXP209_VBUS_VOLTAGE, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_VOLT_STEP;
-		break;
-	case AXP209_VBUSCURRENT:
-		error = axp209_read(dev, AXP209_VBUS_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_VBUSCURRENT_STEP;
-		break;
-	case AXP209_BATVOLT:
-		error = axp209_read(dev, AXP209_BAT_VOLTAGE, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_BATVOLT_STEP;
-		break;
-	case AXP209_BATCHARGECURRENT:
-		error = axp209_read(dev, AXP209_BAT_CHARGE_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_BATCURRENT_STEP;
-		break;
-	case AXP209_BATDISCHARGECURRENT:
-		error = axp209_read(dev, AXP209_BAT_DISCHARGE_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_BAT_H(data[0]) |
-		    AXP209_SENSOR_BAT_L(data[1])) * AXP209_BATCURRENT_STEP;
-		break;
-	default:
-		return (ENOENT);
+	for (found = 0, i = 0; i < sc->nsensors; i++) {
+		if (sc->sensors[i].id == sensor) {
+			found = 1;
+			break;
+		}
 	}
 
+	if (found == 0)
+		return (ENOENT);
+
+	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
+	if (error != 0)
+		return (error);
+
+	val = ((data[0] & sc->sensors[i].h_value_mask) <<
+	    sc->sensors[i].h_value_shift);
+	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
+	    sc->sensors[i].l_value_shift);
+	val *= sc->sensors[i].value_step;
+	val += sc->sensors[i].value_convert;
+
 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
 }
 
 static void
-axp209_shutdown(void *devp, int howto)
+axp2xx_shutdown(void *devp, int howto)
 {
 	device_t dev;
 
@@ -406,77 +848,77 @@ axp209_shutdown(void *devp, int howto)
 	dev = (device_t)devp;
 
 	if (bootverbose)
-		device_printf(dev, "Shutdown AXP209\n");
+		device_printf(dev, "Shutdown AXP2xx\n");
 
-	axp209_write(dev, AXP209_SHUTBAT, AXP209_SHUTBAT_SHUTDOWN);
+	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
 }
 
 static void
-axp_intr(void *arg)
+axp2xx_intr(void *arg)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t reg;
 
 	sc = arg;
 
-	axp209_read(sc->dev, AXP209_IRQ1_STATUS, ®, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, ®, 1);
 	if (reg) {
-		if (reg & AXP209_IRQ1_AC_OVERVOLT)
+		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
 			devctl_notify("PMU", "AC", "overvoltage", NULL);
-		if (reg & AXP209_IRQ1_VBUS_OVERVOLT)
+		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
 			devctl_notify("PMU", "USB", "overvoltage", NULL);
-		if (reg & AXP209_IRQ1_VBUS_LOW)
+		if (reg & AXP2XX_IRQ1_VBUS_LOW)
 			devctl_notify("PMU", "USB", "undervoltage", NULL);
-		if (reg & AXP209_IRQ1_AC_CONN)
+		if (reg & AXP2XX_IRQ1_AC_CONN)
 			devctl_notify("PMU", "AC", "plugged", NULL);
-		if (reg & AXP209_IRQ1_AC_DISCONN)
+		if (reg & AXP2XX_IRQ1_AC_DISCONN)
 			devctl_notify("PMU", "AC", "unplugged", NULL);
-		if (reg & AXP209_IRQ1_VBUS_CONN)
+		if (reg & AXP2XX_IRQ1_VBUS_CONN)
 			devctl_notify("PMU", "USB", "plugged", NULL);
-		if (reg & AXP209_IRQ1_VBUS_DISCONN)
+		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
 			devctl_notify("PMU", "USB", "unplugged", NULL);
-		axp209_write(sc->dev, AXP209_IRQ1_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ2_STATUS, ®, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, ®, 1);
 	if (reg) {
-		if (reg & AXP209_IRQ2_BATT_CHARGED)
+		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
 			devctl_notify("PMU", "Battery", "charged", NULL);
-		if (reg & AXP209_IRQ2_BATT_CHARGING)
+		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
 			devctl_notify("PMU", "Battery", "charging", NULL);
-		if (reg & AXP209_IRQ2_BATT_CONN)
+		if (reg & AXP2XX_IRQ2_BATT_CONN)
 			devctl_notify("PMU", "Battery", "connected", NULL);
-		if (reg & AXP209_IRQ2_BATT_DISCONN)
+		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
 			devctl_notify("PMU", "Battery", "disconnected", NULL);
-		if (reg & AXP209_IRQ2_BATT_TEMP_LOW)
+		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
 			devctl_notify("PMU", "Battery", "low temp", NULL);
-		if (reg & AXP209_IRQ2_BATT_TEMP_OVER)
+		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
 			devctl_notify("PMU", "Battery", "high temp", NULL);
-		axp209_write(sc->dev, AXP209_IRQ2_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ3_STATUS, ®, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, ®, 1);
 	if (reg) {
-		if (reg & AXP209_IRQ3_PEK_SHORT)
+		if (reg & AXP2XX_IRQ3_PEK_SHORT)
 			shutdown_nice(RB_POWEROFF);
-		axp209_write(sc->dev, AXP209_IRQ3_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ4_STATUS, ®, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, ®, 1);
 	if (reg) {
-		axp209_write(sc->dev, AXP209_IRQ4_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ5_STATUS, ®, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, ®, 1);
 	if (reg) {
-		axp209_write(sc->dev, AXP209_IRQ5_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
 	}
 }
 
 static device_t
-axp209_gpio_get_bus(device_t dev)
+axp2xx_gpio_get_bus(device_t dev)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 
 	sc = device_get_softc(dev);
 
@@ -484,17 +926,25 @@ axp209_gpio_get_bus(device_t dev)
 }
 
 static int
-axp209_gpio_pin_max(device_t dev, int *maxpin)
+axp2xx_gpio_pin_max(device_t dev, int *maxpin)
 {
-	*maxpin = nitems(axp209_pins) - 1;
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	*maxpin = sc->npins - 1;
 
 	return (0);
 }
 
 static int
-axp209_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+axp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
-	if (pin >= nitems(axp209_pins))
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (pin >= sc->npins)
 		return (EINVAL);
 
 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
@@ -503,9 +953,13 @@ axp209_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 }
 
 static int
-axp209_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+axp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
-	if (pin >= nitems(axp209_pins))
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (pin >= sc->npins)
 		return (EINVAL);
 
 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
@@ -514,25 +968,25 @@ axp209_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 }
 
 static int
-axp209_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+axp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp209_pins))
-		return (EINVAL);
-
 	sc = device_get_softc(dev);
 
+	if (pin >= sc->npins)
+		return (EINVAL);
+
 	AXP_LOCK(sc);
-	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
+	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
-		func = data & AXP209_GPIO_FUNC_MASK;
-		if (func == AXP209_GPIO_FUNC_INPUT)
+		func = data & AXP2XX_GPIO_FUNC_MASK;
+		if (func == AXP2XX_GPIO_FUNC_INPUT)
 			*flags = GPIO_PIN_INPUT;
-		else if (func == AXP209_GPIO_FUNC_DRVLO ||
-		    func == AXP209_GPIO_FUNC_DRVHI)
+		else if (func == AXP2XX_GPIO_FUNC_DRVLO ||
+		    func == AXP2XX_GPIO_FUNC_DRVHI)
 			*flags = GPIO_PIN_OUTPUT;
 		else
 			*flags = 0;
@@ -543,26 +997,26 @@ axp209_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 }
 
 static int
-axp209_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+axp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t data;
 	int error;
 
-	if (pin >= nitems(axp209_pins))
-		return (EINVAL);
-
 	sc = device_get_softc(dev);
 
+	if (pin >= sc->npins)
+		return (EINVAL);
+
 	AXP_LOCK(sc);
-	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
+	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
-		data &= ~AXP209_GPIO_FUNC_MASK;
+		data &= ~AXP2XX_GPIO_FUNC_MASK;
 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
 			if ((flags & GPIO_PIN_OUTPUT) == 0)
-				data |= AXP209_GPIO_FUNC_INPUT;
+				data |= AXP2XX_GPIO_FUNC_INPUT;
 		}
-		error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data);
+		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
 	}
 	AXP_UNLOCK(sc);
 
@@ -570,32 +1024,35 @@ axp209_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 }
 
 static int
-axp209_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+axp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp209_pins))
-		return (EINVAL);
-
 	sc = device_get_softc(dev);
 
+	if (pin >= sc->npins)
+		return (EINVAL);
+
 	AXP_LOCK(sc);
-	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
+	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
-		func = data & AXP209_GPIO_FUNC_MASK;
+		func = data & AXP2XX_GPIO_FUNC_MASK;
 		switch (func) {
-		case AXP209_GPIO_FUNC_DRVLO:
+		case AXP2XX_GPIO_FUNC_DRVLO:
 			*val = 0;
 			break;
-		case AXP209_GPIO_FUNC_DRVHI:
+		case AXP2XX_GPIO_FUNC_DRVHI:
 			*val = 1;
 			break;
-		case AXP209_GPIO_FUNC_INPUT:
-			error = axp209_read(dev, AXP209_GPIO_STATUS, &data, 1);
-			if (error == 0)
-				*val = (data & AXP209_GPIO_DATA(pin)) ? 1 : 0;
+		case AXP2XX_GPIO_FUNC_INPUT:
+			error = axp2xx_read(dev, sc->pins[pin].status_reg,
+			    &data, 1);
+			if (error == 0) {
+				*val = (data & sc->pins[pin].status_mask);
+				*val >>= sc->pins[pin].status_shift;
+			}
 			break;
 		default:
 			error = EIO;
@@ -608,30 +1065,30 @@ axp209_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
 }
 
 static int
-axp209_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
+axp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp209_pins))
-		return (EINVAL);
-
 	sc = device_get_softc(dev);
 
+	if (pin >= sc->npins)
+		return (EINVAL);
+
 	AXP_LOCK(sc);
-	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
+	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
-		func = data & AXP209_GPIO_FUNC_MASK;
+		func = data & AXP2XX_GPIO_FUNC_MASK;
 		switch (func) {
-		case AXP209_GPIO_FUNC_DRVLO:
-		case AXP209_GPIO_FUNC_DRVHI:
+		case AXP2XX_GPIO_FUNC_DRVLO:
+		case AXP2XX_GPIO_FUNC_DRVHI:
 			/* GPIO2 can't be set to 1 */
 			if (pin == 2 && val == 1) {
 				error = EINVAL;
 				break;
 			}
-			data &= ~AXP209_GPIO_FUNC_MASK;
+			data &= ~AXP2XX_GPIO_FUNC_MASK;
 			data |= val;
 			break;
 		default:
@@ -640,7 +1097,7 @@ axp209_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
 		}
 	}
 	if (error == 0)
-		error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data);
+		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
 	AXP_UNLOCK(sc);
 
 	return (error);
@@ -648,34 +1105,34 @@ axp209_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
 
 
 static int
-axp209_gpio_pin_toggle(device_t dev, uint32_t pin)
+axp2xx_gpio_pin_toggle(device_t dev, uint32_t pin)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp209_pins))
-		return (EINVAL);
-
 	sc = device_get_softc(dev);
 
+	if (pin >= sc->npins)
+		return (EINVAL);
+
 	AXP_LOCK(sc);
-	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
+	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
-		func = data & AXP209_GPIO_FUNC_MASK;
+		func = data & AXP2XX_GPIO_FUNC_MASK;
 		switch (func) {
-		case AXP209_GPIO_FUNC_DRVLO:
+		case AXP2XX_GPIO_FUNC_DRVLO:
 			/* Pin 2 can't be set to 1*/
 			if (pin == 2) {
 				error = EINVAL;
 				break;
 			}
-			data &= ~AXP209_GPIO_FUNC_MASK;
-			data |= AXP209_GPIO_FUNC_DRVHI;
+			data &= ~AXP2XX_GPIO_FUNC_MASK;
+			data |= AXP2XX_GPIO_FUNC_DRVHI;
 			break;
-		case AXP209_GPIO_FUNC_DRVHI:
-			data &= ~AXP209_GPIO_FUNC_MASK;
-			data |= AXP209_GPIO_FUNC_DRVLO;
+		case AXP2XX_GPIO_FUNC_DRVHI:
+			data &= ~AXP2XX_GPIO_FUNC_MASK;
+			data |= AXP2XX_GPIO_FUNC_DRVLO;
 			break;
 		default:
 			error = EIO;
@@ -683,17 +1140,21 @@ axp209_gpio_pin_toggle(device_t dev, uint32_t pin)
 		}
 	}
 	if (error == 0)
-		error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data);
+		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
 	AXP_UNLOCK(sc);
 
 	return (error);
 }
 
 static int
-axp209_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
+axp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
 {
-	if (gpios[0] >= nitems(axp209_pins))
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(bus);
+
+	if (gpios[0] >= sc->npins)
 		return (EINVAL);
 
 	*pin = gpios[0];
@@ -703,16 +1164,16 @@ axp209_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
 }
 
 static phandle_t
-axp209_get_node(device_t dev, device_t bus)
+axp2xx_get_node(device_t dev, device_t bus)
 {
 	return (ofw_bus_get_node(dev));
 }
 
-static struct axp209_reg_sc *
-axp209_reg_attach(device_t dev, phandle_t node,
-    struct axp209_regdef *def)
+static struct axp2xx_reg_sc *
+axp2xx_reg_attach(device_t dev, phandle_t node,
+    struct axp2xx_regdef *def)
 {
-	struct axp209_reg_sc *reg_sc;
+	struct axp2xx_reg_sc *reg_sc;
 	struct regnode_init_def initdef;
 	struct regnode *regnode;
 
@@ -727,7 +1188,7 @@ axp209_reg_attach(device_t dev, phandle_t node,
 		initdef.std_param.max_uvolt = def->voltage_max * 1000;
 	initdef.id = def->id;
 	initdef.ofw_node = node;
-	regnode = regnode_create(dev, &axp209_regnode_class, &initdef);
+	regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef);
 	if (regnode == NULL) {
 		device_printf(dev, "cannot create regulator\n");
 		return (NULL);
@@ -746,10 +1207,10 @@ axp209_reg_attach(device_t dev, phandle_t node,
 }
 
 static int
-axp209_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
+axp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
     intptr_t *num)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	int i;
 
 	sc = device_get_softc(dev);
@@ -766,12 +1227,13 @@ axp209_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
 }
 
 static void
-axp209_start(void *pdev)
+axp2xx_start(void *pdev)
 {
 	device_t dev;
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
-	uint8_t data;
+	int i;
+	uint8_t reg, data;
 	uint8_t pwr_src;
 
 	dev = pdev;
@@ -786,123 +1248,96 @@ axp209_start(void *pdev)
 		 * Shift the AC presence into bit 0.
 		 * Shift the Battery presence into bit 1.
 		 */
-		axp209_read(dev, AXP209_PSR, &data, 1);
-		pwr_src = ((data & AXP209_PSR_ACIN) >> AXP209_PSR_ACIN_SHIFT) |
-		    ((data & AXP209_PSR_VBUS) >> (AXP209_PSR_VBUS_SHIFT - 1));
+		axp2xx_read(dev, AXP2XX_PSR, &data, 1);
+		pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) |
+		    ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1));
 
-		device_printf(dev, "AXP209 Powered by %s\n",
+		device_printf(dev, "Powered by %s\n",
 		    pwr_name[pwr_src]);
 	}
 
 	/* Only enable interrupts that we are interested in */
-	axp209_write(dev, AXP209_IRQ1_ENABLE,
-	    AXP209_IRQ1_AC_OVERVOLT |
-	    AXP209_IRQ1_AC_DISCONN |
-	    AXP209_IRQ1_AC_CONN |
-	    AXP209_IRQ1_VBUS_OVERVOLT |
-	    AXP209_IRQ1_VBUS_DISCONN |
-	    AXP209_IRQ1_VBUS_CONN);
-	axp209_write(dev, AXP209_IRQ2_ENABLE,
-	    AXP209_IRQ2_BATT_CONN |
-	    AXP209_IRQ2_BATT_DISCONN |
-	    AXP209_IRQ2_BATT_CHARGE_ACCT_ON |
-	    AXP209_IRQ2_BATT_CHARGE_ACCT_OFF |
-	    AXP209_IRQ2_BATT_CHARGING |
-	    AXP209_IRQ2_BATT_CHARGED |
-	    AXP209_IRQ2_BATT_TEMP_OVER |
-	    AXP209_IRQ2_BATT_TEMP_LOW);
-	axp209_write(dev, AXP209_IRQ3_ENABLE,
-	    AXP209_IRQ3_PEK_SHORT | AXP209_IRQ3_PEK_LONG);
-	axp209_write(dev, AXP209_IRQ4_ENABLE, AXP209_IRQ4_APS_LOW_2);
-	axp209_write(dev, AXP209_IRQ5_ENABLE, 0x0);
+	axp2xx_write(dev, AXP2XX_IRQ1_ENABLE,
+	    AXP2XX_IRQ1_AC_OVERVOLT |
+	    AXP2XX_IRQ1_AC_DISCONN |
+	    AXP2XX_IRQ1_AC_CONN |
+	    AXP2XX_IRQ1_VBUS_OVERVOLT |
+	    AXP2XX_IRQ1_VBUS_DISCONN |
+	    AXP2XX_IRQ1_VBUS_CONN);
+	axp2xx_write(dev, AXP2XX_IRQ2_ENABLE,
+	    AXP2XX_IRQ2_BATT_CONN |
+	    AXP2XX_IRQ2_BATT_DISCONN |
+	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON |
+	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF |
+	    AXP2XX_IRQ2_BATT_CHARGING |
+	    AXP2XX_IRQ2_BATT_CHARGED |
+	    AXP2XX_IRQ2_BATT_TEMP_OVER |
+	    AXP2XX_IRQ2_BATT_TEMP_LOW);
+	axp2xx_write(dev, AXP2XX_IRQ3_ENABLE,
+	    AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG);
+	axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2);
+	axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0);
 
-	EVENTHANDLER_REGISTER(shutdown_final, axp209_shutdown, dev,
+	EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev,
 	    SHUTDOWN_PRI_LAST);
 
 	/* Enable ADC sensors */
-	if (axp209_write(dev, AXP209_ADC_ENABLE1,
-	    AXP209_ADC1_BATVOLT | AXP209_ADC1_BATCURRENT |
-	    AXP209_ADC1_ACVOLT | AXP209_ADC1_ACCURRENT |
-	    AXP209_ADC1_VBUSVOLT | AXP209_ADC1_VBUSCURRENT) != -1) {
+	for (i = 0; i < sc->nsensors; i++) {
+		if (axp2xx_read(dev, sc->sensors[i].enable_reg, ®, 1) == -1) {
+			device_printf(dev, "Cannot enable sensor '%s'\n",
+			    sc->sensors[i].name);
+			continue;
+		}
+		reg |= sc->sensors[i].enable_mask;
+		if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) {
+			device_printf(dev, "Cannot enable sensor '%s'\n",
+			    sc->sensors[i].name);
+			continue;
+		}
 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "acvolt",
+		    OID_AUTO, sc->sensors[i].name,
 		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_ACVOLT, axp209_sysctl, "I",
-		    "AC Voltage (microVolt)");
-		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "accurrent",
-		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_ACCURRENT, axp209_sysctl, "I",
-		    "AC Current (microAmpere)");
-		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "vbusvolt",
-		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_VBUSVOLT, axp209_sysctl, "I",
-		    "VBUS Voltage (microVolt)");
-		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "vbuscurrent",
-		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_VBUSCURRENT, axp209_sysctl, "I",
-		    "VBUS Current (microAmpere)");
-		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "batvolt",
-		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_BATVOLT, axp209_sysctl, "I",
-		    "Battery Voltage (microVolt)");
-		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "batchargecurrent",
-		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_BATCHARGECURRENT, axp209_sysctl, "I",
-		    "Battery Charging Current (microAmpere)");
-		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-		    OID_AUTO, "batdischargecurrent",
-		    CTLTYPE_INT | CTLFLAG_RD,
-		    dev, AXP209_BATDISCHARGECURRENT, axp209_sysctl, "I",
-		    "Battery Discharging Current (microAmpere)");
-	} else {
-		device_printf(dev, "Couldn't enable ADC sensors\n");
+		    dev, sc->sensors[i].id, axp2xx_sysctl,
+		    sc->sensors[i].format,
+		    sc->sensors[i].desc);
 	}
 
-	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-	    OID_AUTO, "temp",
-	    CTLTYPE_INT | CTLFLAG_RD,
-	    dev, AXP209_TEMP, axp209_sysctl, "IK", "Internal temperature");
-
 	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
-	      NULL, axp_intr, sc, &sc->intrcookie)))
+	      NULL, axp2xx_intr, sc, &sc->intrcookie)))
 		device_printf(dev, "unable to register interrupt handler\n");
 
 	config_intrhook_disestablish(&sc->intr_hook);
 }
 
 static int
-axp209_probe(device_t dev)
+axp2xx_probe(device_t dev)
 {
 
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
-	if (!ofw_bus_is_compatible(dev, "x-powers,axp209"))
+	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+	{
+	case AXP209:
+		device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
+		break;
+	case AXP221:
+		device_set_desc(dev, "X-Powers AXP221 Power Management Unit");
+		break;
+	default:
 		return (ENXIO);
-
-	device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
+	}
 
 	return (BUS_PROBE_DEFAULT);
 }
 
 static int
-axp209_attach(device_t dev)
+axp2xx_attach(device_t dev)
 {
-	struct axp209_softc *sc;
-	struct axp209_reg_sc *reg;
+	struct axp2xx_softc *sc;
+	struct axp2xx_reg_sc *reg;
+	struct axp2xx_regdef *regdefs;
 	phandle_t rnode, child;
 	int i;
 
@@ -914,80 +1349,106 @@ axp209_attach(device_t dev)
 		return (ENXIO);
 	}
 
-	sc->intr_hook.ich_func = axp209_start;
+	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+	switch (sc->type) {
+	case AXP209:
+		sc->pins = axp209_pins;
+		sc->npins = nitems(axp209_pins);
+		sc->gpiodev = gpiobus_attach_bus(dev);
+
+		sc->sensors = axp209_sensors;
+		sc->nsensors = nitems(axp209_sensors);
+
+		regdefs = axp209_regdefs;
+		sc->nregs = nitems(axp209_regdefs);
+		break;
+	case AXP221:
+		sc->pins = axp221_pins;
+		sc->npins = nitems(axp221_pins);
+		sc->gpiodev = gpiobus_attach_bus(dev);
+
+		sc->sensors = axp221_sensors;
+		sc->nsensors = nitems(axp221_sensors);
+
+		regdefs = axp221_regdefs;
+		sc->nregs = nitems(axp221_regdefs);
+		break;
+	}
+
+	sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs,
+	    M_AXP2XX_REG, M_WAITOK | M_ZERO);
+
+	sc->intr_hook.ich_func = axp2xx_start;
 	sc->intr_hook.ich_arg = dev;
 
 	if (config_intrhook_establish(&sc->intr_hook) != 0)
 		return (ENOMEM);
 
-	sc->nregs = nitems(axp209_regdefs);
-	sc->regs = malloc(sizeof(struct axp209_reg_sc *) * sc->nregs,
-	    M_AXP209_REG, M_WAITOK | M_ZERO);
-
 	/* Attach known regulators that exist in the DT */
 	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
 	if (rnode > 0) {
 		for (i = 0; i < sc->nregs; i++) {
 			child = ofw_bus_find_child(rnode,
-			    axp209_regdefs[i].name);
+			    regdefs[i].name);
 			if (child == 0)
 				continue;
-			reg = axp209_reg_attach(dev, child, &axp209_regdefs[i]);
+			reg = axp2xx_reg_attach(dev, child, ®defs[i]);
 			if (reg == NULL) {
 				device_printf(dev,
 				    "cannot attach regulator %s\n",
-				    axp209_regdefs[i].name);
+				    regdefs[i].name);
 				continue;
 			}
 			sc->regs[i] = reg;
+			if (bootverbose)
+				device_printf(dev, "Regulator %s attached\n",
+				    regdefs[i].name);
 		}
 	}
 
-	sc->gpiodev = gpiobus_attach_bus(dev);
-
 	return (0);
 }
 
-static device_method_t axp209_methods[] = {
-	DEVMETHOD(device_probe,		axp209_probe),
-	DEVMETHOD(device_attach,	axp209_attach),
+static device_method_t axp2xx_methods[] = {
+	DEVMETHOD(device_probe,		axp2xx_probe),
+	DEVMETHOD(device_attach,	axp2xx_attach),
 
 	/* GPIO interface */
-	DEVMETHOD(gpio_get_bus,		axp209_gpio_get_bus),
-	DEVMETHOD(gpio_pin_max,		axp209_gpio_pin_max),
-	DEVMETHOD(gpio_pin_getname,	axp209_gpio_pin_getname),
-	DEVMETHOD(gpio_pin_getcaps,	axp209_gpio_pin_getcaps),
-	DEVMETHOD(gpio_pin_getflags,	axp209_gpio_pin_getflags),
-	DEVMETHOD(gpio_pin_setflags,	axp209_gpio_pin_setflags),
-	DEVMETHOD(gpio_pin_get,		axp209_gpio_pin_get),
-	DEVMETHOD(gpio_pin_set,		axp209_gpio_pin_set),
-	DEVMETHOD(gpio_pin_toggle,	axp209_gpio_pin_toggle),
-	DEVMETHOD(gpio_map_gpios,	axp209_gpio_map_gpios),
+	DEVMETHOD(gpio_get_bus,		axp2xx_gpio_get_bus),
+	DEVMETHOD(gpio_pin_max,		axp2xx_gpio_pin_max),
+	DEVMETHOD(gpio_pin_getname,	axp2xx_gpio_pin_getname),
+	DEVMETHOD(gpio_pin_getcaps,	axp2xx_gpio_pin_getcaps),
+	DEVMETHOD(gpio_pin_getflags,	axp2xx_gpio_pin_getflags),
+	DEVMETHOD(gpio_pin_setflags,	axp2xx_gpio_pin_setflags),
+	DEVMETHOD(gpio_pin_get,		axp2xx_gpio_pin_get),
+	DEVMETHOD(gpio_pin_set,		axp2xx_gpio_pin_set),
+	DEVMETHOD(gpio_pin_toggle,	axp2xx_gpio_pin_toggle),
+	DEVMETHOD(gpio_map_gpios,	axp2xx_gpio_map_gpios),
 
 	/* Regdev interface */
-	DEVMETHOD(regdev_map,		axp209_regdev_map),
+	DEVMETHOD(regdev_map,		axp2xx_regdev_map),
 
 	/* OFW bus interface */
-	DEVMETHOD(ofw_bus_get_node,	axp209_get_node),
+	DEVMETHOD(ofw_bus_get_node,	axp2xx_get_node),
 
 	DEVMETHOD_END
 };
 
-static driver_t axp209_driver = {
-	"axp209_pmu",
-	axp209_methods,
-	sizeof(struct axp209_softc),
+static driver_t axp2xx_driver = {
+	"axp2xx_pmu",
+	axp2xx_methods,
+	sizeof(struct axp2xx_softc),
 };
 
-static devclass_t axp209_devclass;
+static devclass_t axp2xx_devclass;
 extern devclass_t ofwgpiobus_devclass, gpioc_devclass;
 extern driver_t ofw_gpiobus_driver, gpioc_driver;
 
-EARLY_DRIVER_MODULE(axp209, iicbus, axp209_driver, axp209_devclass,
+EARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, axp2xx_devclass,
   0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
-EARLY_DRIVER_MODULE(ofw_gpiobus, axp209_pmu, ofw_gpiobus_driver,
+EARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver,
     ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
-DRIVER_MODULE(gpioc, axp209_pmu, gpioc_driver, gpioc_devclass,
+DRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, gpioc_devclass,
     0, 0);
-MODULE_VERSION(axp209, 1);
-MODULE_DEPEND(axp209, iicbus, 1, 1, 1);
+MODULE_VERSION(axp2xx, 1);
+MODULE_DEPEND(axp2xx, iicbus, 1, 1, 1);
diff --git a/sys/arm/allwinner/axp209reg.h b/sys/arm/allwinner/axp209reg.h
index 38e540145c54..c2e94fdf28de 100644
--- a/sys/arm/allwinner/axp209reg.h
+++ b/sys/arm/allwinner/axp209reg.h
@@ -29,34 +29,37 @@
 #define	_AXP209REG_H_
 
 /* Power State Register */
-#define	AXP209_PSR		0x00
-#define	AXP209_PSR_ACIN		0x80
-#define	AXP209_PSR_ACIN_SHIFT	7
-#define	AXP209_PSR_VBUS		0x20
-#define	AXP209_PSR_VBUS_SHIFT	5
+#define	AXP2XX_PSR		0x00
+#define	AXP2XX_PSR_ACIN		0x80
+#define	AXP2XX_PSR_ACIN_SHIFT	7
+#define	AXP2XX_PSR_VBUS		0x20
+#define	AXP2XX_PSR_VBUS_SHIFT	5
 
 /* Shutdown and battery control */
-#define	AXP209_SHUTBAT		0x32
-#define	AXP209_SHUTBAT_SHUTDOWN	0x80
+#define	AXP2XX_SHUTBAT		0x32
+#define	AXP2XX_SHUTBAT_SHUTDOWN	0x80
 
 /* Voltage/Current Monitor */
 #define	AXP209_ACIN_VOLTAGE		0x56
 #define	AXP209_ACIN_CURRENT		0x58
 #define	AXP209_VBUS_VOLTAGE		0x5A
 #define	AXP209_VBUS_CURRENT		0x5C
-#define	AXP209_BAT_VOLTAGE		0x78
-#define	AXP209_BAT_CHARGE_CURRENT	0x7A
-#define	AXP209_BAT_DISCHARGE_CURRENT	0x7C
+#define	AXP2XX_BAT_VOLTAGE		0x78
+#define	AXP2XX_BAT_CHARGE_CURRENT	0x7A
+#define	AXP2XX_BAT_DISCHARGE_CURRENT	0x7C
 
 #define	AXP209_VOLT_STEP	1700
-#define	AXP209_BATVOLT_STEP	1100
+#define	AXP2XX_BATVOLT_STEP	1100
 #define	AXP209_ACCURRENT_STEP	625
 #define	AXP209_VBUSCURRENT_STEP	375
-#define	AXP209_BATCURRENT_STEP	500
+#define	AXP2XX_BATCURRENT_STEP	500
 
 /* Temperature monitor */
 #define	AXP209_TEMPMON		0x5e
 #define	AXP209_TEMPMON_MIN	1447	/* -144.7C */
+#define	AXP221_TEMPMON_MIN	2437	/* -243.7C */
+
+#define	AXP221_TEMPMON		0x56
 
 /* Sensors conversion macros */
 #define	AXP209_SENSOR_H(a)	((a) << 4)
@@ -67,110 +70,154 @@
 #define	AXP209_0C_TO_K		2732
 
 /* ADC Sensors */
-#define	AXP209_ADC_ENABLE1	0x82
+#define	AXP2XX_ADC_ENABLE1	0x82
 #define	AXP209_ADC_ENABLE2	0x83
 
-#define	AXP209_ADC1_BATVOLT	(1 << 7)
-#define	AXP209_ADC1_BATCURRENT	(1 << 6)
+#define	AXP2XX_ADC1_BATVOLT	(1 << 7)
+#define	AXP2XX_ADC1_BATCURRENT	(1 << 6)
 #define	AXP209_ADC1_ACVOLT	(1 << 5)
+#define	AXP221_ADC1_TEMP	(1 << 5)
 #define	AXP209_ADC1_ACCURRENT	(1 << 4)
 #define	AXP209_ADC1_VBUSVOLT	(1 << 3)
 #define	AXP209_ADC1_VBUSCURRENT	(1 << 2)
+#define	AXP221_ADC1_TS_PIN	(1 << 0)
+
+#define	AXP209_ADC2_TEMP	(1 << 7)
 
 /* Interrupt related registers */
-#define	AXP209_IRQ1_ENABLE	0x40
-#define	AXP209_IRQ1_STATUS	0x48
-#define	 AXP209_IRQ1_AC_OVERVOLT	(1 << 7)
-#define	 AXP209_IRQ1_AC_CONN		(1 << 6)
-#define	 AXP209_IRQ1_AC_DISCONN		(1 << 5)
-#define	 AXP209_IRQ1_VBUS_OVERVOLT	(1 << 4)
-#define	 AXP209_IRQ1_VBUS_CONN		(1 << 3)
-#define	 AXP209_IRQ1_VBUS_DISCONN	(1 << 2)
-#define	 AXP209_IRQ1_VBUS_LOW		(1 << 1)
+#define	AXP2XX_IRQ1_ENABLE	0x40
+#define	AXP2XX_IRQ1_STATUS	0x48
+#define	 AXP2XX_IRQ1_AC_OVERVOLT	(1 << 7)
+#define	 AXP2XX_IRQ1_AC_CONN		(1 << 6)
+#define	 AXP2XX_IRQ1_AC_DISCONN		(1 << 5)
+#define	 AXP2XX_IRQ1_VBUS_OVERVOLT	(1 << 4)
+#define	 AXP2XX_IRQ1_VBUS_CONN		(1 << 3)
+#define	 AXP2XX_IRQ1_VBUS_DISCONN	(1 << 2)
+#define	 AXP2XX_IRQ1_VBUS_LOW		(1 << 1)
 
-#define	AXP209_IRQ2_ENABLE	0x41
-#define	AXP209_IRQ2_STATUS	0x49
-#define	 AXP209_IRQ2_BATT_CONN			(1 << 7)
-#define	 AXP209_IRQ2_BATT_DISCONN		(1 << 6)
-#define	 AXP209_IRQ2_BATT_CHARGE_ACCT_ON	(1 << 5)
-#define	 AXP209_IRQ2_BATT_CHARGE_ACCT_OFF	(1 << 4)
-#define	 AXP209_IRQ2_BATT_CHARGING		(1 << 3)
-#define	 AXP209_IRQ2_BATT_CHARGED		(1 << 2)
-#define	 AXP209_IRQ2_BATT_TEMP_OVER		(1 << 1)
-#define	 AXP209_IRQ2_BATT_TEMP_LOW		(1 << 0)
+#define	AXP2XX_IRQ2_ENABLE	0x41
+#define	AXP2XX_IRQ2_STATUS	0x49
+#define	 AXP2XX_IRQ2_BATT_CONN			(1 << 7)
+#define	 AXP2XX_IRQ2_BATT_DISCONN		(1 << 6)
+#define	 AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON	(1 << 5)
+#define	 AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF	(1 << 4)
+#define	 AXP2XX_IRQ2_BATT_CHARGING		(1 << 3)
+#define	 AXP2XX_IRQ2_BATT_CHARGED		(1 << 2)
+#define	 AXP2XX_IRQ2_BATT_TEMP_OVER		(1 << 1)
+#define	 AXP2XX_IRQ2_BATT_TEMP_LOW		(1 << 0)
 
-#define	AXP209_IRQ3_ENABLE	0x42
-#define	AXP209_IRQ3_STATUS	0x4A
-#define	 AXP209_IRQ3_TEMP_OVER		(1 << 7)
-#define	 AXP209_IRQ3_CHARGE_CURRENT_LOW	(1 << 6)
-#define	 AXP209_IRQ3_DCDC2_LOW		(1 << 4)
-#define	 AXP209_IRQ3_DCDC3_LOW		(1 << 3)
-#define	 AXP209_IRQ3_LDO3_LOW		(1 << 2)
-#define	 AXP209_IRQ3_PEK_SHORT		(1 << 1)
-#define	 AXP209_IRQ3_PEK_LONG		(1 << 0)
+#define	AXP2XX_IRQ3_ENABLE	0x42
+#define	AXP2XX_IRQ3_STATUS	0x4A
+#define	 AXP2XX_IRQ3_TEMP_OVER		(1 << 7)
+#define	 AXP2XX_IRQ3_CHARGE_CURRENT_LOW	(1 << 6)
+#define	 AXP2XX_IRQ3_DCDC2_LOW		(1 << 4)
+#define	 AXP2XX_IRQ3_DCDC3_LOW		(1 << 3)
+#define	 AXP2XX_IRQ3_LDO3_LOW		(1 << 2)
+#define	 AXP2XX_IRQ3_PEK_SHORT		(1 << 1)
+#define	 AXP2XX_IRQ3_PEK_LONG		(1 << 0)
 
-#define	AXP209_IRQ4_ENABLE	0x43
-#define	AXP209_IRQ4_STATUS	0x4B
-#define	 AXP209_IRQ4_NOE_START		(1 << 7)
-#define	 AXP209_IRQ4_NOE_SHUT		(1 << 6)
-#define	 AXP209_IRQ4_VBUS_VALID		(1 << 5)
-#define	 AXP209_IRQ4_VBUS_INVALID	(1 << 4)
-#define	 AXP209_IRQ4_VBUS_SESSION	(1 << 3)
-#define	 AXP209_IRQ4_VBUS_SESSION_END	(1 << 2)
-#define	 AXP209_IRQ4_APS_LOW_1		(1 << 1)
-#define	 AXP209_IRQ4_APS_LOW_2		(1 << 0)
+#define	AXP2XX_IRQ4_ENABLE	0x43
+#define	AXP2XX_IRQ4_STATUS	0x4B
+#define	 AXP2XX_IRQ4_NOE_START		(1 << 7)
+#define	 AXP2XX_IRQ4_NOE_SHUT		(1 << 6)
+#define	 AXP2XX_IRQ4_VBUS_VALID		(1 << 5)
+#define	 AXP2XX_IRQ4_VBUS_INVALID	(1 << 4)
+#define	 AXP2XX_IRQ4_VBUS_SESSION	(1 << 3)
+#define	 AXP2XX_IRQ4_VBUS_SESSION_END	(1 << 2)
+#define	 AXP2XX_IRQ4_APS_LOW_1		(1 << 1)
+#define	 AXP2XX_IRQ4_APS_LOW_2		(1 << 0)
 
-#define	AXP209_IRQ5_ENABLE	0x44
-#define	AXP209_IRQ5_STATUS	0x4C
-#define	 AXP209_IRQ5_TIMER_EXPIRE	(1 << 7)
-#define	 AXP209_IRQ5_PEK_RISE_EDGE	(1 << 6)
-#define	 AXP209_IRQ5_PEK_FALL_EDGE	(1 << 5)
-#define	 AXP209_IRQ5_GPIO3	(1 << 3)
-#define	 AXP209_IRQ5_GPIO2	(1 << 2)
-#define	 AXP209_IRQ5_GPIO1	(1 << 1)
-#define	 AXP209_IRQ5_GPIO0	(1 << 0)
+#define	AXP2XX_IRQ5_ENABLE	0x44
+#define	AXP2XX_IRQ5_STATUS	0x4C
+#define	 AXP2XX_IRQ5_TIMER_EXPIRE	(1 << 7)
+#define	 AXP2XX_IRQ5_PEK_RISE_EDGE	(1 << 6)
+#define	 AXP2XX_IRQ5_PEK_FALL_EDGE	(1 << 5)
+#define	 AXP2XX_IRQ5_GPIO3	(1 << 3)
+#define	 AXP2XX_IRQ5_GPIO2	(1 << 2)
+#define	 AXP2XX_IRQ5_GPIO1	(1 << 1)
+#define	 AXP2XX_IRQ5_GPIO0	(1 << 0)
 
-#define	AXP209_IRQ_ACK		0xff
+#define	AXP2XX_IRQ_ACK		0xff
 
 /* GPIOs registers */
-#define	AXP209_GPIO_FUNC_MASK		0x7
+#define	AXP2XX_GPIO_FUNC_MASK		0x7
 
-#define	AXP209_GPIO_FUNC_DRVLO		0x0
-#define	AXP209_GPIO_FUNC_DRVHI		0x1
-#define	AXP209_GPIO_FUNC_INPUT		0x2
+#define	AXP2XX_GPIO_FUNC_DRVLO		0x0
+#define	AXP2XX_GPIO_FUNC_DRVHI		0x1
+#define	AXP2XX_GPIO_FUNC_INPUT		0x2
 
-#define	AXP209_GPIO0_CTRL	0x90
-#define	AXP209_GPIO1_CTRL	0x92
+#define	AXP2XX_GPIO0_CTRL	0x90
+#define	AXP2XX_GPIO1_CTRL	0x92
 #define	AXP209_GPIO2_CTRL	0x93
-#define	AXP209_GPIO_STATUS	0x94
-
-#define	AXP209_GPIO_DATA(x)	(1 << (x + 4))
+#define	AXP2XX_GPIO_STATUS	0x94
 
 /* Regulators registers */
 #define	AXP209_POWERCTL			0x12
-#define	 AXP209_POWERCTL_DCDC3		(1 << 1)
-#define	 AXP209_POWERCTL_LDO2		(1 << 2)
-#define	 AXP209_POWERCTL_LDO4		(1 << 3)
-#define	 AXP209_POWERCTL_DCDC2		(1 << 4)
 #define	 AXP209_POWERCTL_LDO3		(1 << 6)
+#define	 AXP209_POWERCTL_DCDC2		(1 << 4)
+#define	 AXP209_POWERCTL_LDO4		(1 << 3)
+#define	 AXP209_POWERCTL_LDO2		(1 << 2)
+#define	 AXP209_POWERCTL_DCDC3		(1 << 1)
+
+#define	AXP221_POWERCTL_1		0x10
+#define	 AXP221_POWERCTL1_ALDO2		(1 << 7)
+#define	 AXP221_POWERCTL1_ALDO1		(1 << 6)
+#define	 AXP221_POWERCTL1_DCDC5		(1 << 5)
+#define	 AXP221_POWERCTL1_DCDC4		(1 << 4)
+#define	 AXP221_POWERCTL1_DCDC3		(1 << 3)
+#define	 AXP221_POWERCTL1_DCDC2		(1 << 2)
+#define	 AXP221_POWERCTL1_DCDC1		(1 << 1)
+#define	 AXP221_POWERCTL1_DC5LDO	(1 << 0)
+
+#define	AXP221_POWERCTL_2		0x12
+#define	 AXP221_POWERCTL2_DC1SW		(1 << 7)
+#define	 AXP221_POWERCTL2_DLDO4		(1 << 6)
+#define	 AXP221_POWERCTL2_DLDO3		(1 << 5)
+#define	 AXP221_POWERCTL2_DLDO2		(1 << 4)
+#define	 AXP221_POWERCTL2_DLDO1		(1 << 3)
+#define	 AXP221_POWERCTL2_ELDO3		(1 << 2)
+#define	 AXP221_POWERCTL2_ELDO2		(1 << 1)
+#define	 AXP221_POWERCTL2_ELDO1		(1 << 0)
+
+#define	AXP221_POWERCTL_3		0x14
+#define	 AXP221_POWERCTL3_ALDO3		(1 << 7)
 
 #define	AXP209_REG_DCDC2_VOLTAGE	0x23
 #define	AXP209_REG_DCDC3_VOLTAGE	0x27
 #define	AXP209_REG_LDO24_VOLTAGE	0x28
 #define	AXP209_REG_LDO3_VOLTAGE		0x29
 
-enum axp209_sensor {
-	AXP209_TEMP,
+#define	AXP221_REG_DLDO1_VOLTAGE	0x15
+#define	AXP221_REG_DLDO2_VOLTAGE	0x16
+#define	AXP221_REG_DLDO3_VOLTAGE	0x17
+#define	AXP221_REG_DLDO4_VOLTAGE	0x18
+#define	AXP221_REG_ELDO1_VOLTAGE	0x19
+#define	AXP221_REG_ELDO2_VOLTAGE	0x1A
+#define	AXP221_REG_ELDO3_VOLTAGE	0x1B
+#define	AXP221_REG_DC5LDO_VOLTAGE	0x1C
+#define	AXP221_REG_DCDC1_VOLTAGE	0x21
+#define	AXP221_REG_DCDC2_VOLTAGE	0x22
+#define	AXP221_REG_DCDC3_VOLTAGE	0x23
+#define	AXP221_REG_DCDC4_VOLTAGE	0x24
+#define	AXP221_REG_DCDC5_VOLTAGE	0x25
+#define	AXP221_REG_DCDC23_VRC		0x27
+#define	AXP221_REG_ALDO1_VOLTAGE	0x28
+#define	AXP221_REG_ALDO2_VOLTAGE	0x29
+#define	AXP221_REG_ALDO3_VOLTAGE	0x2A
+
+
+enum axp2xx_sensor {
 	AXP209_ACVOLT,
 	AXP209_ACCURRENT,
 	AXP209_VBUSVOLT,
 	AXP209_VBUSCURRENT,
-	AXP209_BATVOLT,
-	AXP209_BATCHARGECURRENT,
-	AXP209_BATDISCHARGECURRENT,
+	AXP2XX_TEMP,
+	AXP2XX_BATVOLT,
+	AXP2XX_BATCHARGECURRENT,
+	AXP2XX_BATDISCHARGECURRENT,
 };
 
-enum axp209_regulators {
+enum axp2xx_regulators {
 	AXP209_REG_ID_DCDC2,
 	AXP209_REG_ID_DCDC3,
 	AXP209_REG_ID_LDO1,
@@ -179,6 +226,23 @@ enum axp209_regulators {
 	/* LDO4 is weird, need to find a correct way to handle it */
 	/* AXP209_REG_ID_LDO4, */
 	AXP209_REG_ID_LDO5,
+	AXP221_REG_ID_DLDO1,
+	AXP221_REG_ID_DLDO2,
+	AXP221_REG_ID_DLDO3,
+	AXP221_REG_ID_DLDO4,
+	AXP221_REG_ID_ELDO1,
+	AXP221_REG_ID_ELDO2,
+	AXP221_REG_ID_ELDO3,
+	AXP221_REG_ID_DC5LDO,
+	AXP221_REG_ID_DCDC1,
+	AXP221_REG_ID_DCDC2,
+	AXP221_REG_ID_DCDC3,
+	AXP221_REG_ID_DCDC4,
+	AXP221_REG_ID_DCDC5,
+	AXP221_REG_ID_ALDO1,
+	AXP221_REG_ID_ALDO2,
+	AXP221_REG_ID_ALDO3,
+	AXP221_REG_ID_DC1SW,
 };
 
 #endif /* _AXP209REG_H_ */

From 25da7a9dc584a8284a1016e58dbdc66fd7eac676 Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Fri, 4 Nov 2016 20:06:32 +0000
Subject: [PATCH 042/127] Add AXP221 node in our BananaPi M2 dts.

---
 sys/boot/fdt/dts/arm/bananapim2.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/sys/boot/fdt/dts/arm/bananapim2.dts b/sys/boot/fdt/dts/arm/bananapim2.dts
index b241111cd111..39f6ee629991 100644
--- a/sys/boot/fdt/dts/arm/bananapim2.dts
+++ b/sys/boot/fdt/dts/arm/bananapim2.dts
@@ -31,3 +31,15 @@
 &mmc2 {
 	status = "disabled";
 };
+
+&p2wi {
+	status = "okay";
+	axp22x: pmic@68 {
+		compatible = "x-powers,axp221";
+		reg = <0x68>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+#include "axp22x.dtsi"

From aba6e414954ad6c965b771d5c2ae45791baed06b Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Fri, 4 Nov 2016 20:32:49 +0000
Subject: [PATCH 043/127] vidcontrol: improve error handling in vt(4) font
 loading

PR:		209078
Reported by:	ecturt@gmail.com
Reviewed by:	Oliver Pinter
Differential Revision:	https://reviews.freebsd.org/D8176
---
 usr.sbin/vidcontrol/vidcontrol.c | 44 +++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/usr.sbin/vidcontrol/vidcontrol.c b/usr.sbin/vidcontrol/vidcontrol.c
index 1dba9cb0dd58..9807de818be9 100644
--- a/usr.sbin/vidcontrol/vidcontrol.c
+++ b/usr.sbin/vidcontrol/vidcontrol.c
@@ -393,11 +393,15 @@ load_vt4mappingtable(unsigned int nmappings, FILE *f)
 	if (nmappings == 0)
 		return (NULL);
 
-	t = malloc(sizeof *t * nmappings);
+	if ((t = malloc(sizeof *t * nmappings)) == NULL) {
+		warn("malloc");
+		return (NULL);
+	}
 
 	if (fread(t, sizeof *t * nmappings, 1, f) != 1) {
-		perror("mappings");
-		exit(1);
+		warn("read mappings");
+		free(t);
+		return (NULL);
 	}
 
 	for (i = 0; i < nmappings; i++) {
@@ -422,7 +426,7 @@ load_default_vt4font(void)
 	}
 }
 
-static int
+static void
 load_vt4font(FILE *f)
 {
 	struct vt4font_header fh;
@@ -431,13 +435,13 @@ load_vt4font(FILE *f)
 	unsigned int i;
 
 	if (fread(&fh, sizeof fh, 1, f) != 1) {
-		perror("file_header");
-		return (1);
+		warn("read file_header");
+		return;
 	}
 
 	if (memcmp(fh.magic, "VFNT0002", 8) != 0) {
-		fprintf(stderr, "Bad magic\n");
-		return (1);
+		warnx("bad magic in font file\n");
+		return;
 	}
 
 	for (i = 0; i < VFNT_MAPS; i++)
@@ -447,21 +451,26 @@ load_vt4font(FILE *f)
 	vfnt.height = fh.height;
 
 	glyphsize = howmany(vfnt.width, 8) * vfnt.height * vfnt.glyph_count;
-	vfnt.glyphs = malloc(glyphsize);
+	if ((vfnt.glyphs = malloc(glyphsize)) == NULL) {
+		warn("malloc");
+		return;
+	}
 
 	if (fread(vfnt.glyphs, glyphsize, 1, f) != 1) {
-		perror("glyphs");
-		return (1);
+		warn("read glyphs");
+		free(vfnt.glyphs);
+		return;
 	}
 
 	for (i = 0; i < VFNT_MAPS; i++)
 		vfnt.map[i] = load_vt4mappingtable(vfnt.map_count[i], f);
 
-	if (ioctl(STDIN_FILENO, PIO_VFONT, &vfnt) == -1) {
-		perror("PIO_VFONT");
-		return (1);
-	}
-	return (0);
+	if (ioctl(STDIN_FILENO, PIO_VFONT, &vfnt) == -1)
+		warn("PIO_VFONT");
+
+	for (i = 0; i < VFNT_MAPS; i++)
+		free(vfnt.map[i]);
+	free(vfnt.glyphs);
 }
 
 /*
@@ -511,8 +520,7 @@ load_font(const char *type, const char *filename)
 	}
 
 	if (vt4_mode) {
-		if(load_vt4font(fd))
-			warn("failed to load font \"%s\"", filename);
+		load_vt4font(fd);
 		fclose(fd);
 		return;
 	}

From b780b03cbefa2bcbc9a39005e8544aeb304554a1 Mon Sep 17 00:00:00 2001
From: "Pedro F. Giffuni" 
Date: Fri, 4 Nov 2016 20:49:59 +0000
Subject: [PATCH 044/127] sed(1): add LEGACY_BSDSED_COMPAT compile-time flag.

In r297602, which included a __FreeBSD_version bump to 1100105, we changed
sed 'i' and 'a' from discarding whitespaces to conform with what GNU and
sysvish sed do.

There are arguments in favor of keeping the old behavior but the new
behavior is also useful for migration purposes. It seems important to at
least consider the case of developers depending on the previous behavior,
so add a CFLAG to enable the old behaviour.

PR:		213474
MFC after:	5 days
---
 usr.bin/sed/compile.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c
index bafb339a4b5d..f05d45fc6b40 100644
--- a/usr.bin/sed/compile.c
+++ b/usr.bin/sed/compile.c
@@ -746,6 +746,9 @@ compile_text(void)
 	while (cu_fgets(lbuf, sizeof(lbuf), NULL) != NULL) {
 		op = s = text + size;
 		p = lbuf;
+#ifdef LEGACY_BSDSED_COMPAT
+		EATSPACE();
+#endif
 		for (esc_nl = 0; *p != '\0'; p++) {
 			if (*p == '\\' && p[1] != '\0' && *++p == '\n')
 				esc_nl = 1;

From a304ad90e9ae16b7b4e135e84fc347d8bdd844af Mon Sep 17 00:00:00 2001
From: Colin Percival 
Date: Sat, 5 Nov 2016 06:33:39 +0000
Subject: [PATCH 045/127] Reduce the bogosity of ministat's % difference
 calculations.

The previous calculation used an approximation which was only valid in
cases where the means being compared were similar; this resulted in very
odd claims being made, e.g. that 0 +/- 0 is a difference of -100% +/- 1%
from 100 +/- 1.

The new calculation scales sample standard deviations by the means, and
yields approximately correct percentage difference bounds providing that
the reference population is bounded away from zero.  (In the case where
the values being compared are not sufficiently bounded away from zero,
the distribution of ratios becomes much harder to calculate, and is not
likely to be useful anyway.)

Note that when ministat is used for its intended purpose of determining
whether two samples are statistically different, this change is unlikely
to have any noticeable effect; in such cases the means will be similar
enough that the correction applied here will be minimal.
---
 usr.bin/ministat/ministat.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/usr.bin/ministat/ministat.c b/usr.bin/ministat/ministat.c
index a7f7182ce420..02b5025a436c 100644
--- a/usr.bin/ministat/ministat.c
+++ b/usr.bin/ministat/ministat.c
@@ -232,6 +232,7 @@ static void
 Relative(struct dataset *ds, struct dataset *rs, int confidx)
 {
 	double spool, s, d, e, t;
+	double re;
 	int i;
 
 	i = ds->n + rs->n - 2;
@@ -246,11 +247,16 @@ Relative(struct dataset *ds, struct dataset *rs, int confidx)
 	d = Avg(ds) - Avg(rs);
 	e = t * s;
 
+	re = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs) *
+	    (Avg(ds) * Avg(ds)) / (Avg(rs) * Avg(rs));
+	re *= (ds->n + rs->n) / (ds->n * rs->n * (ds->n + rs->n - 2.0));
+	re = t * sqrt(re);
+
 	if (fabs(d) > e) {
 	
 		printf("Difference at %.1f%% confidence\n", studentpct[confidx]);
 		printf("	%g +/- %g\n", d, e);
-		printf("	%g%% +/- %g%%\n", d * 100 / Avg(rs), e * 100 / Avg(rs));
+		printf("	%g%% +/- %g%%\n", d * 100 / Avg(rs), re * 100 / Avg(rs));
 		printf("	(Student's t, pooled s = %g)\n", spool);
 	} else {
 		printf("No difference proven at %.1f%% confidence\n",

From becf2d11e84158ff003f0a8f2e05b1b15b33a94e Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Sat, 5 Nov 2016 11:19:55 +0000
Subject: [PATCH 046/127] vidcontrol: use calloc where appropriate

Reported by:	kib
---
 usr.sbin/vidcontrol/vidcontrol.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/usr.sbin/vidcontrol/vidcontrol.c b/usr.sbin/vidcontrol/vidcontrol.c
index 9807de818be9..6d79863be0cf 100644
--- a/usr.sbin/vidcontrol/vidcontrol.c
+++ b/usr.sbin/vidcontrol/vidcontrol.c
@@ -393,8 +393,8 @@ load_vt4mappingtable(unsigned int nmappings, FILE *f)
 	if (nmappings == 0)
 		return (NULL);
 
-	if ((t = malloc(sizeof *t * nmappings)) == NULL) {
-		warn("malloc");
+	if ((t = calloc(nmappings, sizeof(*t))) == NULL) {
+		warn("calloc");
 		return (NULL);
 	}
 

From a79e9d0fecf091a948c24b30d2563414102cca62 Mon Sep 17 00:00:00 2001
From: Edward Tomasz Napierala 
Date: Sat, 5 Nov 2016 12:30:10 +0000
Subject: [PATCH 047/127] Value returned by taskqueue_enqueue_timeout(9) is not
 an error; don't treat it as such.

MFC after:	1 month
---
 sys/fs/autofs/autofs.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index e339c80c196c..5389b1c4b168 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -442,12 +442,8 @@ autofs_trigger_one(struct autofs_node *anp,
 
 		TIMEOUT_TASK_INIT(taskqueue_thread, &ar->ar_task, 0,
 		    autofs_task, ar);
-		error = taskqueue_enqueue_timeout(taskqueue_thread,
-		    &ar->ar_task, autofs_timeout * hz);
-		if (error != 0) {
-			AUTOFS_WARN("taskqueue_enqueue_timeout() failed "
-			    "with error %d", error);
-		}
+		taskqueue_enqueue_timeout(taskqueue_thread, &ar->ar_task,
+		    autofs_timeout * hz);
 		refcount_init(&ar->ar_refcount, 1);
 		TAILQ_INSERT_TAIL(&autofs_softc->sc_requests, ar, ar_next);
 	}

From bcad3423b8a026796e5eae0aeaf9f461367efc06 Mon Sep 17 00:00:00 2001
From: Eric van Gyzen 
Date: Sat, 5 Nov 2016 14:08:14 +0000
Subject: [PATCH 048/127] ncal: fix a reference to an out-of-scope stack buffer

PR:		214237
Submitted by:	Jonathan de Boyne Pollard
MFC after:	3 days
Sponsored by:	Dell EMC
---
 usr.bin/ncal/ncal.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/usr.bin/ncal/ncal.c b/usr.bin/ncal/ncal.c
index 5a5cbc3553ab..25bc76f771ae 100644
--- a/usr.bin/ncal/ncal.c
+++ b/usr.bin/ncal/ncal.c
@@ -1110,7 +1110,8 @@ highlight(char *dst, char *src, int len, int *extralen)
 	static const char *term_so, *term_se;
 
 	if (first) {
-		char tbuf[1024], cbuf[512], *b;
+		static char cbuf[512];
+		char tbuf[1024], *b;
 
 		term_se = term_so = NULL;
 

From 17194cd8e4bce70745b61c54e5fd85b4db6766a2 Mon Sep 17 00:00:00 2001
From: Eric van Gyzen 
Date: Sat, 5 Nov 2016 15:01:41 +0000
Subject: [PATCH 049/127] Fix sorting after r308293, using the ../tools/do_sort
 script.

Is this a pointy-hat offense?

Reported by:	jhb
---
 usr.bin/fortune/datfiles/fortunes | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/usr.bin/fortune/datfiles/fortunes b/usr.bin/fortune/datfiles/fortunes
index d80f9e6f1e6f..f8aaadabb37e 100644
--- a/usr.bin/fortune/datfiles/fortunes
+++ b/usr.bin/fortune/datfiles/fortunes
@@ -58856,6 +58856,9 @@ Your present plans will be successful.
 %
 Your program is sick!  Shoot it and put it out of its memory.
 %
+Your reasoning is excellent -- it's
+only your basic assumptions that are wrong.
+%
 Your reasoning powers are good, and you are a fairly good planner.
 %
 Your responsibility as a parent is not as great as you might imagine.  You
@@ -58947,9 +58950,6 @@ You're not drunk if you can lie on the floor without holding on.
 %
 You're not my type.  For that matter, you're not even my species!!!
 %
-Your reasoning is excellent -- it's
-only your basic assumptions that are wrong.
-%
 You're ugly and your mother dresses you funny.
 %
 You're using a keyboard!  How quaint!

From 4f3a4c0163ce66fdd5cfa65df599486aa1de2ac1 Mon Sep 17 00:00:00 2001
From: Sean Bruno 
Date: Sat, 5 Nov 2016 16:17:07 +0000
Subject: [PATCH 050/127] r266979 missed a call to enable capabilities of the
 hw leading to an inability to enable features of the device.

PR:             213845
Submitted by:   pherman@frenchfries.net
MFC after:      1 week
---
 sys/dev/bxe/bxe.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index 98978da9a53f..9f86e8f2ab36 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -12691,6 +12691,7 @@ bxe_init_ifnet(struct bxe_softc *sc)
          IFCAP_WOL_MAGIC);
 #endif
     if_setcapabilitiesbit(ifp, capabilities, 0); /* XXX */
+    if_setcapenable(ifp, if_getcapabilities(ifp));
     if_setbaudrate(ifp, IF_Gbps(10));
 /* XXX */
     if_setsendqlen(ifp, sc->tx_ring_size);

From 4ad8d73326f5120275499b44420f87f72f35b1e7 Mon Sep 17 00:00:00 2001
From: Marcel Moolenaar 
Date: Sat, 5 Nov 2016 16:23:33 +0000
Subject: [PATCH 051/127] Assign a random number to di_gen (for FFS), instead
 of extracting it from struct stat.  We don't necessarily have permissions to
 see the generation number and the host OS may not have st_gen in struct stat
 anyway.  Since the kernel assigns random numbers, there's nothing meaningful
 about the generation that requires us to preserve it when the file system
 image is created.  With this change, all generation numbers come from
 random() and that makes it easier to add support for reproducible builds at
 some time in the future (i.e. by adding an argument to makefs that changes
 the behaviour of random() so that it always returns 0 or some predictable
 sequence).

Differential Revision:	https://reviews.freebsd.org/D8418
---
 usr.sbin/makefs/Makefile | 1 -
 usr.sbin/makefs/ffs.c    | 8 ++------
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/usr.sbin/makefs/Makefile b/usr.sbin/makefs/Makefile
index a02458044d25..ac59e3c58a3d 100644
--- a/usr.sbin/makefs/Makefile
+++ b/usr.sbin/makefs/Makefile
@@ -20,7 +20,6 @@ WARNS?=	2
 .include "${SRCDIR}/ffs/Makefile.inc"
 
 CFLAGS+=-DHAVE_STRUCT_STAT_ST_FLAGS=1
-CFLAGS+=-DHAVE_STRUCT_STAT_ST_GEN=1
 
 .PATH: ${SRCTOP}/contrib/mtree
 CFLAGS+=-I${SRCTOP}/contrib/mtree
diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c
index 8ed7f1f11259..16d60b495bd6 100644
--- a/usr.sbin/makefs/ffs.c
+++ b/usr.sbin/makefs/ffs.c
@@ -666,9 +666,7 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
 #if HAVE_STRUCT_STAT_ST_FLAGS
 	dinp->di_flags = cur->inode->st.st_flags;
 #endif
-#if HAVE_STRUCT_STAT_ST_GEN
-	dinp->di_gen = cur->inode->st.st_gen;
-#endif
+	dinp->di_gen = random();
 	dinp->di_uid = cur->inode->st.st_uid;
 	dinp->di_gid = cur->inode->st.st_gid;
 
@@ -716,9 +714,7 @@ ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
 #if HAVE_STRUCT_STAT_ST_FLAGS
 	dinp->di_flags = cur->inode->st.st_flags;
 #endif
-#if HAVE_STRUCT_STAT_ST_GEN
-	dinp->di_gen = cur->inode->st.st_gen;
-#endif
+	dinp->di_gen = random();
 	dinp->di_uid = cur->inode->st.st_uid;
 	dinp->di_gid = cur->inode->st.st_gid;
 

From b1b6afa587761c5d56b0a5410a2a8ea9c2248a57 Mon Sep 17 00:00:00 2001
From: Sean Bruno 
Date: Sat, 5 Nov 2016 16:30:42 +0000
Subject: [PATCH 052/127] r295133 attempted to deactivate TSO in the 100Mbit
 link case with this adapter to work around bugs in TSO handling at this
 speed.

em_init_locked is called during first boot of the adapter and will
see that link_speed is unitialized, effectively turning off tso for
all cards at all speeds, which I believe was *not* the intent.

Move the handling of TSO deactivation to the link handler where we can
more effectively make the decision about what to do.  In addition,
completely purge the TSO capabilities instead of disabling just CSUM_TSO.

Thanks to jhb for explanation of the hw capabilites api.

Thanks to royger and cognet for testing the 100Mbit failure case to
ensure that their adapters do indeed still work.

MFC after:	1 week
Sponsored by:	Limelight Networks
---
 sys/dev/e1000/if_em.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 9df560ad3199..fd602bf482f2 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -369,11 +369,6 @@ MODULE_DEPEND(em, netmap, 1, 1, 1);
 #define MAX_INTS_PER_SEC	8000
 #define DEFAULT_ITR		(1000000000/(MAX_INTS_PER_SEC * 256))
 
-/* Allow common code without TSO */
-#ifndef CSUM_TSO
-#define CSUM_TSO	0
-#endif
-
 #define TSO_WORKAROUND	4
 
 static SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters");
@@ -1396,15 +1391,9 @@ em_init_locked(struct adapter *adapter)
 	if_clearhwassist(ifp);
 	if (if_getcapenable(ifp) & IFCAP_TXCSUM)
 		if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0);
-	/* 
-	** There have proven to be problems with TSO when not
-	** at full gigabit speed, so disable the assist automatically
-	** when at lower speeds.  -jfv
-	*/
-	if (if_getcapenable(ifp) & IFCAP_TSO4) {
-		if (adapter->link_speed == SPEED_1000)
-			if_sethwassistbits(ifp, CSUM_TSO, 0);
-	}
+
+	if (if_getcapenable(ifp) & IFCAP_TSO4)
+		if_sethwassistbits(ifp, CSUM_TSO, 0);
 
 	/* Configure for OS presence */
 	em_init_manageability(adapter);
@@ -2412,6 +2401,18 @@ em_update_link_status(struct adapter *adapter)
 	if (link_check && (adapter->link_active == 0)) {
 		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
 		    &adapter->link_duplex);
+		/* 
+		** There have proven to be problems with TSO when not
+		** at full gigabit speed, so disable the assist automatically
+		** when at lower speeds.  -jfv
+		*/
+		if (adapter->link_speed != SPEED_1000) {
+			if_sethwassistbits(ifp, 0, CSUM_TSO);
+			if_setcapenablebit(ifp, 0, IFCAP_TSO4);
+        		if_setcapabilitiesbit(ifp, 0, IFCAP_TSO4);
+
+		}
+
 		/* Check if we must disable SPEED_MODE bit on PCI-E */
 		if ((adapter->link_speed != SPEED_1000) &&
 		    ((hw->mac.type == e1000_82571) ||

From 161ab37d24e40dea535714b4d3473a65879e5c9a Mon Sep 17 00:00:00 2001
From: Hiroki Sato 
Date: Sat, 5 Nov 2016 18:00:36 +0000
Subject: [PATCH 053/127] Fix an infinite loop at an non-responding hop when
 other echo replies are kept arriving in the waittime time window.

Submitted by:	Denny Page
PR:		210286
MFC after:	3 days
---
 usr.sbin/traceroute6/traceroute6.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c
index d9dbb40d3590..62dfc6a05f05 100644
--- a/usr.sbin/traceroute6/traceroute6.c
+++ b/usr.sbin/traceroute6/traceroute6.c
@@ -955,6 +955,9 @@ main(argc, argv)
 						break;
 					}
 					break;
+				} else if (deltaT(&t1, &t2) > waittime * 1000) {
+					cc = 0;
+					break;
 				}
 			}
 			if (cc == 0)

From 374d225e54087ead8c8b0f4d919bea0556f2bbbb Mon Sep 17 00:00:00 2001
From: Hiroki Sato 
Date: Sat, 5 Nov 2016 19:51:13 +0000
Subject: [PATCH 054/127] Add link-layer address option in RA even for
 IFT_L2VLAN and IFT_BRIDGE.

Reported by:	philip
MFC after:	3 days
---
 usr.sbin/rtadvd/if.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/usr.sbin/rtadvd/if.c b/usr.sbin/rtadvd/if.c
index 6013e9ba08c1..72ea36a8f64f 100644
--- a/usr.sbin/rtadvd/if.c
+++ b/usr.sbin/rtadvd/if.c
@@ -114,6 +114,8 @@ lladdropt_length(struct sockaddr_dl *sdl)
 {
 	switch (sdl->sdl_type) {
 	case IFT_ETHER:
+	case IFT_L2VLAN:
+	case IFT_BRIDGE:
 		return (ROUNDUP8(ETHER_ADDR_LEN + 2));
 	default:
 		return (0);
@@ -129,6 +131,8 @@ lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
 
 	switch (sdl->sdl_type) {
 	case IFT_ETHER:
+	case IFT_L2VLAN:
+	case IFT_BRIDGE:
 		ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
 		addr = (char *)(ndopt + 1);
 		memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);

From ee9d294b3669bc8cbe3d782967bb547c73429f2f Mon Sep 17 00:00:00 2001
From: Adrian Chadd 
Date: Sat, 5 Nov 2016 22:41:22 +0000
Subject: [PATCH 055/127] [net80211] begin fleshing out new hardware crypto
 offload features.

* extend the keycache flag word to be 32 bits, not 16 bits
* add new key flags for transmit:
  + IEEE80211_KEY_NOIV: Don't insert IV in the payload when transmitting data frames;
  + IEEE80211_KEY_NOIVMGT:  Don't insert IV in the payload when transmitting MIC frames;
  + IEEE80211_KEY_NOMIC: Don't insert MIC in the payload when transmitting data frames;
  + IEEE80211_KEY_NOMICMGT: don't insert MIC in the payload when transmitting management
    frames.

* teach ieee80211_crypto_demic() about hardware decrypted frames:
  + if frames are hardware decrypted and the frame has failed MIC, treat it as a
     michael failure.
  + if frames are hardware decrypted and the frame has stripped MIC, we can't check the
    MIC in the payload - we don't have anything to compare it against.

This is only part of the work required to successfully transmit/receive
hardware crypto frames such as the qualcomm atheros 11ac offload chips.

There will be further work in the transmit and receive path before this
can be done by default.

Reviewed by:	avos
Differential Revision:	https://reviews.freebsd.org/D8364
---
 sys/net80211/ieee80211_crypto.c | 55 +++++++++++++++++++++++++++++++++
 sys/net80211/ieee80211_crypto.h | 46 +++++++++++++--------------
 2 files changed, 76 insertions(+), 25 deletions(-)

diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 6e558475f39a..28bbddaf87ca 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -633,6 +633,61 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
 #undef IEEE80211_WEP_HDRLEN
 }
 
+
+/*
+ * Check and remove any MIC.
+ */
+int
+ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+    struct mbuf *m, int force)
+{
+	const struct ieee80211_cipher *cip;
+	const struct ieee80211_rx_stats *rxs;
+	struct ieee80211_frame *wh;
+
+	rxs = ieee80211_get_rx_params_ptr(m);
+	wh = mtod(m, struct ieee80211_frame *);
+
+	/*
+	 * Handle demic / mic errors from hardware-decrypted offload devices.
+	 */
+	if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) {
+		if (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC) {
+			/*
+			 * Hardware has said MIC failed.  We don't care about
+			 * whether it was stripped or not.
+			 *
+			 * Eventually - teach the demic methods in crypto
+			 * modules to handle a NULL key and not to dereference
+			 * it.
+			 */
+			ieee80211_notify_michael_failure(vap, wh, -1);
+			return (0);
+		}
+
+		if (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP) {
+			/*
+			 * Hardware has decrypted and not indicated a
+			 * MIC failure and has stripped the MIC.
+			 * We may not have a key, so for now just
+			 * return OK.
+			 */
+			return (1);
+		}
+	}
+
+	/*
+	 * If we don't have a key at this point then we don't
+	 * have to demic anything.
+	 */
+	if (k == NULL)
+		return (1);
+
+	cip = k->wk_cipher;
+	return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1);
+}
+
+
 static void
 load_ucastkey(void *arg, struct ieee80211_node *ni)
 {
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index a996af14cfe0..3d1f8cc5e002 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -73,19 +73,25 @@ typedef uint16_t ieee80211_keyix;	/* h/w key index */
 
 struct ieee80211_key {
 	uint8_t		wk_keylen;	/* key length in bytes */
-	uint8_t		wk_pad;
-	uint16_t	wk_flags;
-#define	IEEE80211_KEY_XMIT	0x0001	/* key used for xmit */
-#define	IEEE80211_KEY_RECV	0x0002	/* key used for recv */
-#define	IEEE80211_KEY_GROUP	0x0004	/* key used for WPA group operation */
-#define	IEEE80211_KEY_NOREPLAY	0x0008	/* ignore replay failures */
-#define	IEEE80211_KEY_SWENCRYPT	0x0010	/* host-based encrypt */
-#define	IEEE80211_KEY_SWDECRYPT	0x0020	/* host-based decrypt */
-#define	IEEE80211_KEY_SWENMIC	0x0040	/* host-based enmic */
-#define	IEEE80211_KEY_SWDEMIC	0x0080	/* host-based demic */
-#define	IEEE80211_KEY_DEVKEY	0x0100	/* device key request completed */
-#define	IEEE80211_KEY_CIPHER0	0x1000	/* cipher-specific action 0 */
-#define	IEEE80211_KEY_CIPHER1	0x2000	/* cipher-specific action 1 */
+	uint8_t		wk_pad;		/* .. some drivers use this. Fix that. */
+	uint8_t		wk_pad1[2];
+	uint32_t	wk_flags;
+#define	IEEE80211_KEY_XMIT	0x00000001	/* key used for xmit */
+#define	IEEE80211_KEY_RECV	0x00000002	/* key used for recv */
+#define	IEEE80211_KEY_GROUP	0x00000004	/* key used for WPA group operation */
+#define	IEEE80211_KEY_NOREPLAY	0x00000008	/* ignore replay failures */
+#define	IEEE80211_KEY_SWENCRYPT	0x00000010	/* host-based encrypt */
+#define	IEEE80211_KEY_SWDECRYPT	0x00000020	/* host-based decrypt */
+#define	IEEE80211_KEY_SWENMIC	0x00000040	/* host-based enmic */
+#define	IEEE80211_KEY_SWDEMIC	0x00000080	/* host-based demic */
+#define	IEEE80211_KEY_DEVKEY	0x00000100	/* device key request completed */
+#define	IEEE80211_KEY_CIPHER0	0x00001000	/* cipher-specific action 0 */
+#define	IEEE80211_KEY_CIPHER1	0x00002000	/* cipher-specific action 1 */
+#define	IEEE80211_KEY_NOIV	0x00004000	/* don't insert IV/MIC for !mgmt */
+#define	IEEE80211_KEY_NOIVMGT	0x00008000	/* don't insert IV/MIC for mgmt */
+#define	IEEE80211_KEY_NOMIC	0x00010000	/* don't insert MIC for !mgmt */
+#define	IEEE80211_KEY_NOMICMGT	0x00020000	/* don't insert MIC for mgmt */
+
 	ieee80211_keyix	wk_keyix;	/* h/w key index */
 	ieee80211_keyix	wk_rxkeyix;	/* optional h/w rx key index */
 	uint8_t		wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
@@ -203,18 +209,8 @@ struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
 		struct mbuf *);
 struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
 		struct mbuf *, int);
-
-/*
- * Check and remove any MIC.
- */
-static __inline int
-ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
-	struct mbuf *m, int force)
-{
-	const struct ieee80211_cipher *cip = k->wk_cipher;
-	return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1);
-}
-
+int ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+		struct mbuf *, int);
 /*
  * Add any MIC.
  */

From 8361f9cd07f97be39fee9e9e6f90a9e7bb0da145 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sat, 5 Nov 2016 22:47:09 +0000
Subject: [PATCH 056/127] rtwn: pause beacon queue during scanning.

Tested with RTL8821AU, AP + AP mode.
---
 sys/dev/rtwn/if_rtwn.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c
index 54381cf1642f..355a269ee7ab 100644
--- a/sys/dev/rtwn/if_rtwn.c
+++ b/sys/dev/rtwn/if_rtwn.c
@@ -1513,6 +1513,8 @@ rtwn_scan_start(struct ieee80211com *ic)
 	struct rtwn_softc *sc = ic->ic_softc;
 
 	RTWN_LOCK(sc);
+	/* Pause beaconing. */
+	rtwn_setbits_1(sc, R92C_TXPAUSE, 0, R92C_TX_QUEUE_BCN);
 	/* Receive beacons / probe responses from any BSSID. */
 	if (sc->bcn_vaps == 0)
 		rtwn_set_rx_bssid_all(sc, 1);
@@ -1547,6 +1549,9 @@ rtwn_scan_end(struct ieee80211com *ic)
 
 	/* Restore basic rates mask. */
 	rtwn_calc_basicrates(sc);
+
+	/* Resume beaconing. */
+	rtwn_setbits_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_BCN, 0);
 	RTWN_UNLOCK(sc);
 }
 

From c15d869233cec56dfa0b54fd5287120f609d9577 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sat, 5 Nov 2016 23:21:30 +0000
Subject: [PATCH 057/127] rtwn: fix Rx filter setup for some multi-vap
 configuratons.

- Correctly refresh Rx filter when AP (IBSS) vap is created after STA vap.
- Block any RCR updates during TSF correction (IBSS mode).
- Set CBSSID* bits during vap creation, not when it was started / stopped.
- Cache current state to prevent unnecessary register reads.

Tested with RTL8188CE, STA + AP mode.
---
 sys/dev/rtwn/if_rtwn.c            | 17 +++------
 sys/dev/rtwn/if_rtwn_rx.c         | 60 ++++++++++++++++++-------------
 sys/dev/rtwn/if_rtwn_rx.h         |  1 +
 sys/dev/rtwn/if_rtwnvar.h         |  1 +
 sys/dev/rtwn/rtl8812a/r12a_caps.c | 17 ++++-----
 5 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c
index 355a269ee7ab..77cb7d9607c9 100644
--- a/sys/dev/rtwn/if_rtwn.c
+++ b/sys/dev/rtwn/if_rtwn.c
@@ -917,6 +917,9 @@ rtwn_tsf_sync_adhoc_task(void *arg, int pending)
 	/* Accept beacons with the same BSSID. */
 	rtwn_set_rx_bssid_all(sc, 0);
 
+	/* Deny RCR updates. */
+	sc->sc_flags |= RTWN_RCR_LOCKED;
+
 	/* Enable synchronization. */
 	rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id),
 	    R92C_BCN_CTRL_DIS_TSF_UDT0, 0);
@@ -929,6 +932,7 @@ rtwn_tsf_sync_adhoc_task(void *arg, int pending)
 	    0, R92C_BCN_CTRL_DIS_TSF_UDT0);
 
 	/* Accept all beacons. */
+	sc->sc_flags &= ~RTWN_RCR_LOCKED;
 	rtwn_set_rx_bssid_all(sc, 1);
 
 	/* Schedule next TSF synchronization. */
@@ -1193,7 +1197,6 @@ rtwn_run(struct rtwn_softc *sc, struct ieee80211vap *vap)
 	struct ieee80211com *ic = vap->iv_ic;
 	struct rtwn_vap *uvp = RTWN_VAP(vap);
 	struct ieee80211_node *ni;
-	uint32_t reg;
 	uint8_t mode;
 	int error;
 
@@ -1246,18 +1249,6 @@ rtwn_run(struct rtwn_softc *sc, struct ieee80211vap *vap)
 		rtwn_write_1(sc, R92C_TXPAUSE, 0);
 	}
 
-	/* Allow Rx from our BSSID only. */
-	if (ic->ic_promisc == 0) {
-		reg = rtwn_read_4(sc, R92C_RCR);
-
-		if (sc->bcn_vaps == 0)
-			reg |= R92C_RCR_CBSSID_BCN;
-		if (sc->ap_vaps == 0)
-			reg |= R92C_RCR_CBSSID_DATA;
-
-		rtwn_write_4(sc, R92C_RCR, reg);
-	}
-
 #ifndef RTWN_WITHOUT_UCODE
 	/* Upload (QoS) Null Data frame to firmware. */
 	/* Note: do this for port 0 only. */
diff --git a/sys/dev/rtwn/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c
index 6ee05a3ff4a1..1dea7a6d607a 100644
--- a/sys/dev/rtwn/if_rtwn_rx.c
+++ b/sys/dev/rtwn/if_rtwn_rx.c
@@ -362,7 +362,7 @@ rtwn_rxfilter_update_mgt(struct rtwn_softc *sc)
 {
 	uint16_t filter;
 
-	filter = 0x7f3f;
+	filter = 0x7f7f;
 	if (sc->bcn_vaps == 0) {	/* STA and/or MONITOR mode vaps */
 		filter &= ~(
 		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
@@ -393,7 +393,6 @@ rtwn_rxfilter_update(struct rtwn_softc *sc)
 void
 rtwn_rxfilter_init(struct rtwn_softc *sc)
 {
-	uint32_t rcr;
 
 	RTWN_ASSERT_LOCKED(sc);
 
@@ -406,47 +405,60 @@ rtwn_rxfilter_init(struct rtwn_softc *sc)
 	/* Reject all data frames. */
 	rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
 
-	rcr = sc->rcr;
-	rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
-	       R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
-	       R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
-
-	/* Set Rx filter. */
-	rtwn_write_4(sc, R92C_RCR, rcr);
+	/* Append generic Rx filter bits. */
+	sc->rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
+	    R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
+	    R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
 
 	/* Update dynamic Rx filter parts. */
 	rtwn_rxfilter_update(sc);
 }
 
+void
+rtwn_rxfilter_set(struct rtwn_softc *sc)
+{
+	if (!(sc->sc_flags & RTWN_RCR_LOCKED))
+		rtwn_write_4(sc, R92C_RCR, sc->rcr);
+}
+
 void
 rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable)
 {
+
 	if (enable)
-		rtwn_setbits_4(sc, R92C_RCR, R92C_RCR_CBSSID_BCN, 0);
+		sc->rcr &= ~R92C_RCR_CBSSID_BCN;
 	else
-		rtwn_setbits_4(sc, R92C_RCR, 0, R92C_RCR_CBSSID_BCN);
+		sc->rcr |= R92C_RCR_CBSSID_BCN;
+	rtwn_rxfilter_set(sc);
 }
 
 void
 rtwn_set_promisc(struct rtwn_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
-	uint32_t mask1, mask2;
+	uint32_t mask_all, mask_min;
 
 	RTWN_ASSERT_LOCKED(sc);
 
-	mask1 = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
-	mask2 = R92C_RCR_APM;
+	mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
+	mask_min = R92C_RCR_APM;
 
-	if (sc->vaps_running != 0) {
-		if (sc->bcn_vaps == 0)
-			mask2 |= R92C_RCR_CBSSID_BCN;
-		if (sc->ap_vaps == 0)
-			mask2 |= R92C_RCR_CBSSID_DATA;
+	if (sc->bcn_vaps == 0)
+		mask_min |= R92C_RCR_CBSSID_BCN;
+	if (sc->ap_vaps == 0)
+		mask_min |= R92C_RCR_CBSSID_DATA;
+
+	if (ic->ic_promisc == 0 && sc->mon_vaps == 0) {
+		if (sc->bcn_vaps != 0)
+			mask_all |= R92C_RCR_CBSSID_BCN;
+		if (sc->ap_vaps != 0)	/* for Null data frames */
+			mask_all |= R92C_RCR_CBSSID_DATA;
+
+		sc->rcr &= ~mask_all;
+		sc->rcr |= mask_min;
+	} else {
+		sc->rcr &= ~mask_min;
+		sc->rcr |= mask_all;
 	}
-
-	if (ic->ic_promisc == 0 && sc->mon_vaps == 0)
-		rtwn_setbits_4(sc, R92C_RCR, mask1, mask2);
-	else
-		rtwn_setbits_4(sc, R92C_RCR, mask2, mask1);
+	rtwn_rxfilter_set(sc);
 }
diff --git a/sys/dev/rtwn/if_rtwn_rx.h b/sys/dev/rtwn/if_rtwn_rx.h
index 1f2031cf889a..dfdcc4bfe107 100644
--- a/sys/dev/rtwn/if_rtwn_rx.h
+++ b/sys/dev/rtwn/if_rtwn_rx.h
@@ -32,6 +32,7 @@ void	rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
 void	rtwn_set_multi(struct rtwn_softc *);
 void	rtwn_rxfilter_update(struct rtwn_softc *);
 void	rtwn_rxfilter_init(struct rtwn_softc *);
+void	rtwn_rxfilter_set(struct rtwn_softc *);
 void	rtwn_set_rx_bssid_all(struct rtwn_softc *, int);
 void	rtwn_set_promisc(struct rtwn_softc *);
 
diff --git a/sys/dev/rtwn/if_rtwnvar.h b/sys/dev/rtwn/if_rtwnvar.h
index c07fd2f5002e..198391fa6207 100644
--- a/sys/dev/rtwn/if_rtwnvar.h
+++ b/sys/dev/rtwn/if_rtwnvar.h
@@ -186,6 +186,7 @@ struct rtwn_softc {
 #define RTWN_RUNNING		0x10
 #define RTWN_FW_LOADED		0x20
 #define RTWN_TEMP_MEASURED	0x40
+#define RTWN_RCR_LOCKED		0x80
 
 #define RTWN_CHIP_HAS_BCNQ1(_sc)	\
 	((_sc)->bcn_status_reg[0] != (_sc)->bcn_status_reg[1])
diff --git a/sys/dev/rtwn/rtl8812a/r12a_caps.c b/sys/dev/rtwn/rtl8812a/r12a_caps.c
index a8b738e7f887..aa1c755cb138 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_caps.c
+++ b/sys/dev/rtwn/rtl8812a/r12a_caps.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
 
 #include 
 #include 
@@ -89,19 +90,13 @@ r12a_ioctl_net(struct ieee80211com *ic, u_long cmd, void *data)
 			changed = 1;
 		}
 		if (changed) {
-			if (rxmask == 0) {
+			if (rxmask == 0)
 				sc->rcr &= ~R12A_RCR_TCP_OFFLD_EN;
-				if (sc->sc_flags & RTWN_RUNNING) {
-					rtwn_setbits_4(sc, R92C_RCR,
-					    R12A_RCR_TCP_OFFLD_EN, 0);
-				}
-			} else {
+			else
 				sc->rcr |= R12A_RCR_TCP_OFFLD_EN;
-				if (sc->sc_flags & RTWN_RUNNING) {
-					rtwn_setbits_4(sc, R92C_RCR,
-					    0, R12A_RCR_TCP_OFFLD_EN);
-				}
-			}
+
+			if (sc->sc_flags & RTWN_RUNNING)
+				rtwn_rxfilter_set(sc);
 		}
 		RTWN_UNLOCK(sc);
 

From 8432fa5fd916be34f9dccfbdf35ff322054f655c Mon Sep 17 00:00:00 2001
From: "Andrey V. Elsukov" 
Date: Sun, 6 Nov 2016 02:33:04 +0000
Subject: [PATCH 058/127] Initialize ip6 pointer before use.

PR:		214169
MFC after:	1 week
---
 sys/netinet/tcp_subr.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 77e2d31d0b18..f0e76bf18470 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2731,6 +2731,7 @@ tcp_signature_do_compute(struct mbuf *m, int len, int optlen,
 	 * Note: Upper-Layer Packet Length comes before Next Header.
 	 */
 	case (IPV6_VERSION >> 4):
+		ip6 = mtod(m, struct ip6_hdr *);
 		in6 = ip6->ip6_src;
 		in6_clearscope(&in6);
 		MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));

From 10652ae062c0ae5463c905978c6603da2aba3245 Mon Sep 17 00:00:00 2001
From: Dimitry Andric 
Date: Sun, 6 Nov 2016 16:27:09 +0000
Subject: [PATCH 059/127] Pull in r278002 from upstream llvm trunk (by Silviu
 Baranga):

  [AArch64] PR28877: Don't assume we're running after legalization when
  creating vcvtfp2fxs

  Summary:
  The DAG combine transformation that was generating the
  aarch64_neon_vcvtfp2fxs node was assuming that all inputs where legal
  and wasn't accounting that the input could be a v4f64 if we're trying
  to do the transformation before legalization. We now bail out in this
  case.

  All illegal types besides v4f64 were already rejected.

  Fixes https://llvm.org/bugs/show_bug.cgi?id=28877

  Reviewers: jmolloy

  Subscribers: aemerson, rengolin, llvm-commits

  Differential Revision: https://reviews.llvm.org/D23261

This fixes several ports on AArch64.

Requested by:   andrew
MFC after:      3 days
---
 .../llvm/lib/Target/AArch64/AArch64ISelLowering.cpp   | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 92cf1cd71970..9cbf48820e99 100644
--- a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -7562,6 +7562,7 @@ static SDValue performIntToFpCombine(SDNode *N, SelectionDAG &DAG,
 /// Fold a floating-point multiply by power of two into floating-point to
 /// fixed-point conversion.
 static SDValue performFpToIntCombine(SDNode *N, SelectionDAG &DAG,
+                                     TargetLowering::DAGCombinerInfo &DCI,
                                      const AArch64Subtarget *Subtarget) {
   if (!Subtarget->hasNEON())
     return SDValue();
@@ -7604,10 +7605,16 @@ static SDValue performFpToIntCombine(SDNode *N, SelectionDAG &DAG,
     ResTy = FloatBits == 32 ? MVT::v2i32 : MVT::v2i64;
     break;
   case 4:
-    ResTy = MVT::v4i32;
+    ResTy = FloatBits == 32 ? MVT::v4i32 : MVT::v4i64;
     break;
   }
 
+  if (ResTy == MVT::v4i64 && DCI.isBeforeLegalizeOps())
+    return SDValue();
+
+  assert((ResTy != MVT::v4i64 || DCI.isBeforeLegalizeOps()) &&
+         "Illegal vector type after legalization");
+
   SDLoc DL(N);
   bool IsSigned = N->getOpcode() == ISD::FP_TO_SINT;
   unsigned IntrinsicOpcode = IsSigned ? Intrinsic::aarch64_neon_vcvtfp2fxs
@@ -9711,7 +9718,7 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
     return performIntToFpCombine(N, DAG, Subtarget);
   case ISD::FP_TO_SINT:
   case ISD::FP_TO_UINT:
-    return performFpToIntCombine(N, DAG, Subtarget);
+    return performFpToIntCombine(N, DAG, DCI, Subtarget);
   case ISD::FDIV:
     return performFDivCombine(N, DAG, Subtarget);
   case ISD::OR:

From 1318032e9aec0360d2d2baa7c57c2304f4a8f6f2 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sun, 6 Nov 2016 17:12:02 +0000
Subject: [PATCH 060/127] rtwn: reset watchdog timer on device shutdown.

---
 sys/dev/rtwn/if_rtwn.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c
index 77cb7d9607c9..0c9e81f8cbd5 100644
--- a/sys/dev/rtwn/if_rtwn.c
+++ b/sys/dev/rtwn/if_rtwn.c
@@ -1966,6 +1966,7 @@ rtwn_stop(struct rtwn_softc *sc)
 
 #ifndef D4054
 	callout_stop(&sc->sc_watchdog_to);
+	sc->sc_tx_timer = 0;
 #endif
 	sc->sc_flags &= ~(RTWN_STARTED | RTWN_RUNNING | RTWN_FW_LOADED);
 	sc->sc_flags &= ~RTWN_TEMP_MEASURED;

From 7f35637063f1be8a14e58393a8c39bfbed90ed79 Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Sun, 6 Nov 2016 17:21:26 +0000
Subject: [PATCH 061/127] add __divdi3 and __udivdi3 to libgcc_s symbol version
 map

After r308294 they were missing on i386 (and previously were exported
only accidentally).

Reported by:	antoine
---
 lib/libgcc_s/Version.map | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/libgcc_s/Version.map b/lib/libgcc_s/Version.map
index bd3eb93c685b..c997b7a3406b 100644
--- a/lib/libgcc_s/Version.map
+++ b/lib/libgcc_s/Version.map
@@ -15,6 +15,7 @@ global:
 	__deregister_frame;
 	__deregister_frame_info;
 	__deregister_frame_info_bases;
+	__divdi3;
 	__divti3;
 	__ffsdi2;
 	__ffsti2;
@@ -47,6 +48,7 @@ global:
 	__subvdi3;
 	__subvsi3;
 	__ucmpti2;
+	__udivdi3;
 	__udivmodti4;
 	__udivti3;
 	__umodti3;

From 1acd7ad907c388d72ce6bf1da9e4473ccfd16a01 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sun, 6 Nov 2016 17:24:16 +0000
Subject: [PATCH 062/127] rtwn: reduce shutdown time for RTL8188CE.

---
 sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c
index b7f8d4ac2f34..b28104463b6c 100644
--- a/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c
+++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c
@@ -69,6 +69,7 @@ r92ce_fw_reset(struct rtwn_softc *sc, int reason)
 	 * We must sleep for one second to let the firmware settle.
 	 * Accessing registers too early will hang the whole system.
 	 */
-	rtwn_delay(sc, 1000 * 1000);
+	if (reason == RTWN_FW_RESET_DOWNLOAD)
+		rtwn_delay(sc, 1000 * 1000);
 }
 #endif

From 519e6c0fc222192a1862c66b66a78a9b8a983e73 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sun, 6 Nov 2016 18:11:19 +0000
Subject: [PATCH 063/127] rtwn: fix Tx ring cleanup.

Do not try to clear stale Tx descriptor entries when there are some
running vaps; just free node references - rtwn_pci_tx_done() will free
mbufs without creating holes in the Tx descriptor space.
Also, reset only 2 first entries in the beacon ring - other will not be
used anyway.

Tested with RTL8188CE, STA + STA mode.
---
 sys/dev/rtwn/pci/rtwn_pci_attach.c | 124 ++++++++++++++++++++++-------
 1 file changed, 94 insertions(+), 30 deletions(-)

diff --git a/sys/dev/rtwn/pci/rtwn_pci_attach.c b/sys/dev/rtwn/pci/rtwn_pci_attach.c
index e48ae8141291..4db4427a5f89 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_attach.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_attach.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -75,6 +76,8 @@ static int	rtwn_pci_alloc_rx_list(struct rtwn_softc *);
 static void	rtwn_pci_reset_rx_list(struct rtwn_softc *);
 static void	rtwn_pci_free_rx_list(struct rtwn_softc *);
 static int	rtwn_pci_alloc_tx_list(struct rtwn_softc *, int);
+static void	rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *, int);
+static void	rtwn_pci_reset_beacon_ring(struct rtwn_softc *, int);
 static void	rtwn_pci_reset_tx_list(struct rtwn_softc *,
 		    struct ieee80211vap *, int);
 static void	rtwn_pci_free_tx_list(struct rtwn_softc *, int);
@@ -312,48 +315,109 @@ rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid)
 }
 
 static void
-rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
-    int qid)
+rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *sc, int qid)
 {
-	struct rtwn_vap *uvp = RTWN_VAP(vap);
 	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
-	struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
-	int i, id;
-
-	id = (uvp != NULL ? uvp->id : RTWN_VAP_ID_INVALID);
+	struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
+	int i;
 
 	for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
-		struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i];
+		struct rtwn_tx_data *data = &ring->tx_data[i];
+		void *desc = (uint8_t *)ring->desc + sc->txdesc_len * i;
 
-		if (vap == NULL || (tx_data->ni == NULL &&
-		    (tx_data->id == id || id == RTWN_VAP_ID_INVALID)) ||
-		    (tx_data->ni != NULL && tx_data->ni->ni_vap == vap)) {
-			void *tx_desc =
-			    (uint8_t *)tx_ring->desc + sc->txdesc_len * i;
+		rtwn_pci_copy_tx_desc(pc, desc, NULL);
 
-			rtwn_pci_copy_tx_desc(pc, tx_desc, NULL);
-
-			if (tx_data->m != NULL) {
-				bus_dmamap_sync(tx_ring->data_dmat,
-				    tx_data->map, BUS_DMASYNC_POSTWRITE);
-				bus_dmamap_unload(tx_ring->data_dmat,
-				    tx_data->map);
-				m_freem(tx_data->m);
-				tx_data->m = NULL;
-			}
-			if (tx_data->ni != NULL) {
-				ieee80211_free_node(tx_data->ni);
-				tx_data->ni = NULL;
-			}
+		if (data->m != NULL) {
+			bus_dmamap_sync(ring->data_dmat, data->map,
+			    BUS_DMASYNC_POSTWRITE);
+			bus_dmamap_unload(ring->data_dmat, data->map);
+			m_freem(data->m);
+			data->m = NULL;
+		}
+		if (data->ni != NULL) {
+			ieee80211_free_node(data->ni);
+			data->ni = NULL;
 		}
 	}
 
-	bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map,
+	bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
 	    BUS_DMASYNC_POSTWRITE);
 
 	sc->qfullmsk &= ~(1 << qid);
-	tx_ring->queued = 0;
-	tx_ring->last = tx_ring->cur = 0;
+	ring->queued = 0;
+	ring->last = ring->cur = 0;
+}
+
+/*
+ * Clear entry 0 (or 1) in the beacon queue (other are not used).
+ */
+static void
+rtwn_pci_reset_beacon_ring(struct rtwn_softc *sc, int id)
+{
+	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+	struct rtwn_tx_ring *ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
+	struct rtwn_tx_data *data = &ring->tx_data[id];
+	struct rtwn_tx_desc_common *txd = (struct rtwn_tx_desc_common *)
+	    ((uint8_t *)ring->desc + id * sc->txdesc_len);
+
+	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
+	if (txd->flags0 & RTWN_FLAGS0_OWN) {
+		/* Clear OWN bit. */
+		txd->flags0 &= ~RTWN_FLAGS0_OWN;
+		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+		    BUS_DMASYNC_PREWRITE);
+
+		/* Unload mbuf. */
+		bus_dmamap_sync(ring->data_dmat, data->map,
+		    BUS_DMASYNC_POSTWRITE);
+		bus_dmamap_unload(ring->data_dmat, data->map);
+	}
+}
+
+/*
+ * Drop stale entries from Tx ring before the vap will be deleted.
+ * In case if vap is NULL just free everything and reset cur / last pointers.
+ */
+static void
+rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
+    int qid)
+{
+	int i;
+
+	if (vap == NULL) {
+		if (qid != RTWN_PCI_BEACON_QUEUE) {
+			/*
+			 * Device was stopped; just clear all entries.
+			 */
+			rtwn_pci_reset_tx_ring_stopped(sc, qid);
+		} else {
+			for (i = 0; i < RTWN_PORT_COUNT; i++)
+				rtwn_pci_reset_beacon_ring(sc, i);
+		}
+	} else if (qid == RTWN_PCI_BEACON_QUEUE &&
+		   (vap->iv_opmode == IEEE80211_M_HOSTAP ||
+		    vap->iv_opmode == IEEE80211_M_IBSS)) {
+		struct rtwn_vap *uvp = RTWN_VAP(vap);
+
+		rtwn_pci_reset_beacon_ring(sc, uvp->id);
+	} else {
+		struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+		struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
+
+		for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
+			struct rtwn_tx_data *data = &ring->tx_data[i];
+			if (data->ni != NULL && data->ni->ni_vap == vap) {
+				/*
+				 * NB: if some vap is still running
+				 * rtwn_pci_tx_done() will free the mbuf;
+				 * otherwise, rtwn_stop() will reset all rings
+				 * after device shutdown.
+				 */
+				ieee80211_free_node(data->ni);
+				data->ni = NULL;
+			}
+		}
+	}
 }
 
 static void

From 0cc02885295b46d05709f54350106a588b92c429 Mon Sep 17 00:00:00 2001
From: Adrian Chadd 
Date: Sun, 6 Nov 2016 19:16:46 +0000
Subject: [PATCH 064/127] [net80211] add a method to also explicitly tear down
 RX A-MPDU.

The ath10k firmware API doesn't pass up the ADDBA/DELBA frames, only
WMI firmware notifications.

Tested:

* ath10k (QCA9880), doing actual (ha!) 11n!
---
 sys/net80211/ieee80211_ht.c | 13 +++++++++++++
 sys/net80211/ieee80211_ht.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index cdba429b96ed..a3ef87c7c438 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -596,6 +596,19 @@ ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, int seq, int ba
 	return 0;
 }
 
+/*
+ * Public function; manually stop the RX AMPDU state.
+ */
+void
+ieee80211_ampdu_rx_stop_ext(struct ieee80211_node *ni, int tid)
+{
+	struct ieee80211_rx_ampdu *rap;
+
+	/* XXX TODO: sanity check tid, seq, baw */
+	rap = &ni->ni_rx_ampdu[tid];
+	ampdu_rx_stop(ni, rap);
+}
+
 /*
  * Stop A-MPDU rx processing for the specified TID.
  */
diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h
index 1ad2d2616860..629971d1bdc9 100644
--- a/sys/net80211/ieee80211_ht.h
+++ b/sys/net80211/ieee80211_ht.h
@@ -220,6 +220,7 @@ void	ieee80211_ht_update_beacon(struct ieee80211vap *,
 		struct ieee80211_beacon_offsets *);
 int	ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid,
 	    int seq, int baw);
+void	ieee80211_ampdu_rx_stop_ext(struct ieee80211_node *ni, int tid);
 int	ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid);
 int	ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni,
 	    int tid, int status);

From 77cbc4795866351d9fbcd59d6f3b69b0b2d9b3d7 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sun, 6 Nov 2016 19:17:39 +0000
Subject: [PATCH 065/127] rtwn_pci: omit tx_done() stage if device is not
 running. rtwn_usb: drain USB transfers during device shutdown; this fixes
 possible panic with 'options IEEE80211_SUPPORT_SUPERG' during device detach.

Tested with RTL8188CE, STA mode.
---
 sys/dev/rtwn/pci/rtwn_pci_rx.c     | 12 +++++++-----
 sys/dev/rtwn/usb/rtwn_usb_attach.c |  4 +++-
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/sys/dev/rtwn/pci/rtwn_pci_rx.c b/sys/dev/rtwn/pci/rtwn_pci_rx.c
index 4425b4005a1a..df375a197605 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_rx.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_rx.c
@@ -274,13 +274,14 @@ rtwn_pci_intr(void *arg)
 	status = rtwn_classify_intr(sc, &tx_rings, 0);
 	RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: status %08X, tx_rings %08X\n",
 	    __func__, status, tx_rings);
-	if (status == 0 && tx_rings == 0) {
-		RTWN_UNLOCK(sc);
-		return;
-	}
+	if (status == 0 && tx_rings == 0)
+		goto unlock;
 
-	if (status & RTWN_PCI_INTR_RX)
+	if (status & RTWN_PCI_INTR_RX) {
 		rtwn_pci_rx_done(sc);
+		if (!(sc->sc_flags & RTWN_RUNNING))
+			goto unlock;
+	}
 
 	if (tx_rings != 0)
 		for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
@@ -289,5 +290,6 @@ rtwn_pci_intr(void *arg)
 
 	if (sc->sc_flags & RTWN_RUNNING)
 		rtwn_pci_enable_intr(pc);
+unlock:
 	RTWN_UNLOCK(sc);
 }
diff --git a/sys/dev/rtwn/usb/rtwn_usb_attach.c b/sys/dev/rtwn/usb/rtwn_usb_attach.c
index a47797b56af7..ee0ed22cff2f 100644
--- a/sys/dev/rtwn/usb/rtwn_usb_attach.c
+++ b/sys/dev/rtwn/usb/rtwn_usb_attach.c
@@ -273,8 +273,10 @@ rtwn_usb_abort_xfers(struct rtwn_softc *sc)
 	RTWN_ASSERT_LOCKED(sc);
 
 	/* abort any pending transfers */
+	RTWN_UNLOCK(sc);
 	for (i = 0; i < RTWN_N_TRANSFER; i++)
-		usbd_transfer_stop(uc->uc_xfer[i]);
+		usbd_transfer_drain(uc->uc_xfer[i]);
+	RTWN_LOCK(sc);
 }
 
 static int

From 2b668041d1d6721bf256c0fc6e6bb6bc2599c593 Mon Sep 17 00:00:00 2001
From: Adrian Chadd 
Date: Sun, 6 Nov 2016 19:18:25 +0000
Subject: [PATCH 066/127] [net80211] extend the net80211 ALQ code to support
 variable payloads.

Also - allow driver specific bits to be added, rather than just net80211.

This still isn't as useful as it should be by default; it needs to
be a standalone struct/instance so it can be done before net80211
registration occurs, and it can log per-device items.

But, it's getting there.
---
 sys/net80211/ieee80211_alq.c | 53 ++++++++++++++++++++++++------------
 sys/net80211/ieee80211_alq.h | 22 +++++++++------
 2 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/sys/net80211/ieee80211_alq.c b/sys/net80211/ieee80211_alq.c
index a52103aef1b0..2cb04ec0c531 100644
--- a/sys/net80211/ieee80211_alq.c
+++ b/sys/net80211/ieee80211_alq.c
@@ -79,14 +79,13 @@ ieee80211_alq_setlogging(int enable)
 		    ieee80211_alq_logfile,
 		    curthread->td_ucred,
 		    ALQ_DEFAULT_CMODE,
-		    sizeof (struct ieee80211_alq_rec),
-		    ieee80211_alq_qsize);
+		    ieee80211_alq_qsize, 0);
 		ieee80211_alq_lost = 0;
 		ieee80211_alq_logged = 0;
 		printf("net80211: logging to %s enabled; "
 		    "struct size %d bytes\n",
 		    ieee80211_alq_logfile,
-		    sizeof(struct ieee80211_alq_rec));
+		    (int) sizeof(struct ieee80211_alq_rec));
 	} else {
 		if (ieee80211_alq)
 			alq_close(ieee80211_alq);
@@ -113,18 +112,19 @@ sysctl_ieee80211_alq_log(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_net_wlan, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
 	0, 0, sysctl_ieee80211_alq_log, "I", "Enable net80211 alq logging");
 SYSCTL_INT(_net_wlan, OID_AUTO, alq_size, CTLFLAG_RW,
-	&ieee80211_alq_qsize, 0, "In-memory log size (#records)");
+	&ieee80211_alq_qsize, 0, "In-memory log size (bytes)");
 SYSCTL_INT(_net_wlan, OID_AUTO, alq_lost, CTLFLAG_RW,
 	&ieee80211_alq_lost, 0, "Debugging operations not logged");
 SYSCTL_INT(_net_wlan, OID_AUTO, alq_logged, CTLFLAG_RW,
 	&ieee80211_alq_logged, 0, "Debugging operations logged");
 
 static struct ale *
-ieee80211_alq_get(void)
+ieee80211_alq_get(size_t len)
 {
 	struct ale *ale;
 
-	ale = alq_get(ieee80211_alq, ALQ_NOWAIT);
+	ale = alq_getn(ieee80211_alq, len + sizeof(struct ieee80211_alq_rec),
+	    ALQ_NOWAIT);
 	if (!ale)
 		ieee80211_alq_lost++;
 	else
@@ -132,25 +132,44 @@ ieee80211_alq_get(void)
 	return ale;
 }
 
-void
-ieee80211_alq_log(struct ieee80211vap *vap, uint8_t op, u_char *p, int l)
+int
+ieee80211_alq_log(struct ieee80211com *ic, struct ieee80211vap *vap,
+    uint32_t op, uint32_t flags, uint16_t srcid, const uint8_t *src,
+    size_t len)
 {
 	struct ale *ale;
 	struct ieee80211_alq_rec *r;
+	char *dst;
 
+	/* Don't log if we're disabled */
 	if (ieee80211_alq == NULL)
-		return;
+		return (0);
 
-	ale = ieee80211_alq_get();
+	if (len > IEEE80211_ALQ_MAX_PAYLOAD)
+		return (ENOMEM);
+
+	ale = ieee80211_alq_get(len);
 	if (! ale)
-		return;
+		return (ENOMEM);
 
 	r = (struct ieee80211_alq_rec *) ale->ae_data;
-	r->r_timestamp = htonl(ticks);
-	r->r_version = 1;
-	r->r_wlan = htons(vap->iv_ifp->if_dunit);
-	r->r_op = op;
-	r->r_threadid = htonl((uint32_t) curthread->td_tid);
-	memcpy(&r->r_payload, p, MIN(l, sizeof(r->r_payload)));
+	dst = ((char *) r) + sizeof(struct ieee80211_alq_rec);
+	r->r_timestamp = htobe64(ticks);
+	if (vap != NULL) {
+		r->r_wlan = htobe16(vap->iv_ifp->if_dunit);
+	} else {
+		r->r_wlan = 0xffff;
+	}
+	r->r_src = htobe16(srcid);
+	r->r_flags = htobe32(flags);
+	r->r_op = htobe32(op);
+	r->r_len = htobe32(len + sizeof(struct ieee80211_alq_rec));
+	r->r_threadid = htobe32((uint32_t) curthread->td_tid);
+
+	if (src != NULL)
+		memcpy(dst, src, len);
+
 	alq_post(ieee80211_alq, ale);
+
+	return (0);
 }
diff --git a/sys/net80211/ieee80211_alq.h b/sys/net80211/ieee80211_alq.h
index 112c6b1d2120..7537e9332a1f 100644
--- a/sys/net80211/ieee80211_alq.h
+++ b/sys/net80211/ieee80211_alq.h
@@ -27,7 +27,7 @@
 #ifndef	__IEEE80211_ALQ_H__
 #define	__IEEE80211_ALQ_H__
 
-#define	IEEE80211_ALQ_PAYLOAD_SIZE	24
+#define	IEEE80211_ALQ_MAX_PAYLOAD	1024
 
 /*
  * timestamp
@@ -36,18 +36,24 @@
  * sub-operation
  * rest of structure - operation specific
  */
+
+#define	IEEE80211_ALQ_SRC_NET80211	0x0001
+/* Drivers define their own numbers above 0xff */
+
 struct ieee80211_alq_rec {
-	uint32_t	r_timestamp;	/* XXX may wrap! */
+	uint64_t	r_timestamp;	/* XXX may wrap! */
 	uint32_t	r_threadid;	/* current thread id */
 	uint16_t	r_wlan;		/* wlan interface number */
-	uint8_t		r_version;	/* version */
-	uint8_t		r_op;		/* top-level operation id */
-	u_char		r_payload[IEEE80211_ALQ_PAYLOAD_SIZE];
-					/* operation-specific payload */
+	uint16_t	r_src;		/* source - driver, net80211 */
+	uint32_t	r_flags;	/* flags */
+	uint32_t	r_op;		/* top-level operation id */
+	uint32_t	r_len;		/* length of hdr + payload */
+	/* Operation payload follows here */
 };
 
 /* General logging function */
-extern	void ieee80211_alq_log(struct ieee80211vap *vap, uint8_t op,
-	    u_char *p, int l);
+extern	int ieee80211_alq_log(struct ieee80211com *ic,
+	    struct ieee80211vap *vap, uint32_t op, uint32_t flags,
+	    uint16_t srcid, const uint8_t *src, size_t len);
 
 #endif	/* __IEEE80211_ALQ_H__ */

From 319f1fd2eab9f593f379f163b5ce2d1b3f27faca Mon Sep 17 00:00:00 2001
From: Edward Tomasz Napierala 
Date: Sun, 6 Nov 2016 19:37:22 +0000
Subject: [PATCH 067/127] Document that getfsstat(2) called with MNT_NOWAIT
 skips file systems that are in the process of being unmounted.

Reviewed by:	des@ (earlier version)
MFC after:	1 month
---
 lib/libc/sys/getfsstat.2 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/libc/sys/getfsstat.2 b/lib/libc/sys/getfsstat.2
index c27c6c295a9b..9d1328007af7 100644
--- a/lib/libc/sys/getfsstat.2
+++ b/lib/libc/sys/getfsstat.2
@@ -28,7 +28,7 @@
 .\"	@(#)getfsstat.2	8.3 (Berkeley) 5/25/95
 .\" $FreeBSD$
 .\"
-.Dd November 20, 2003
+.Dd November 6, 2016
 .Dt GETFSSTAT 2
 .Os
 .Sh NAME
@@ -88,6 +88,8 @@ Thus, some of the information will be out of date, but
 .Fn getfsstat
 will not block waiting for information from a file system that is
 unable to respond.
+It will also skip any file system that is in the process of being
+unmounted, even if the unmount would eventually fail.
 .Sh RETURN VALUES
 Upon successful completion, the number of
 .Fa statfs

From fafbeccf90d23d757c550096ea9e67f7bc1e2d74 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sun, 6 Nov 2016 19:51:01 +0000
Subject: [PATCH 068/127] Fix device driver name if devd.conf + move it into
 appropriate place.

Noticed by:	Idwer Vollering 
---
 etc/devd.conf | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/etc/devd.conf b/etc/devd.conf
index e4bd915d6ab3..164ab6e76c2e 100644
--- a/etc/devd.conf
+++ b/etc/devd.conf
@@ -23,8 +23,8 @@ options {
 		esp|ida|iir|ips|isp|mlx|mly|mpt|ncr|ncv|nsp|stg|sym|trm)\
 		[0-9]+";
 	set wifi-driver-regex
-		"(ath|bwi|bwn|ipw|iwi|iwm|iwn|malo|mwl|ral|rsu|rum|run|uath|\
-		upgt|ural|urtw|rtwn_usb|wi|wpi|wtap|zyd)[0-9]+";
+		"(ath|bwi|bwn|ipw|iwi|iwm|iwn|malo|mwl|ral|rsu|rtwn|rum|run|\
+		uath|upgt|ural|urtw|wi|wpi|wtap|zyd)[0-9]+";
 };
 
 # Note that the attach/detach with the highest value wins, so that one can

From d067ef0f0d92d1c39f68fbd48f276b529176bf12 Mon Sep 17 00:00:00 2001
From: Andriy Voskoboinyk 
Date: Sun, 6 Nov 2016 23:13:13 +0000
Subject: [PATCH 069/127] rtwn: add HOSTAP / IBSS mode support for RTL8188CE.

NOTE: some multi-vap configurations (e.g., STA+IBSS) are not stable;
that will be fixed later.

Tested with:
 - RTL8188CE, STA + AP mode;
 - RTL8188CE, IBSS mode;
 - RTL8188CUS, IBSS mode;
 - RTL8188EU, IBSS mode.

Relnotes:	yes
---
 sys/dev/rtwn/if_rtwn.c                   | 14 ++--
 sys/dev/rtwn/if_rtwn_beacon.c            |  9 ++-
 sys/dev/rtwn/if_rtwnvar.h                | 14 ++++
 sys/dev/rtwn/pci/rtwn_pci_attach.c       | 30 ++++++++
 sys/dev/rtwn/pci/rtwn_pci_tx.c           | 96 ++++++++++++++++++------
 sys/dev/rtwn/pci/rtwn_pci_var.h          |  1 -
 sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c | 10 ++-
 sys/dev/rtwn/rtl8192c/r92c_beacon.c      |  1 +
 sys/dev/rtwn/usb/rtwn_usb_attach.c       |  6 ++
 9 files changed, 144 insertions(+), 37 deletions(-)

diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c
index 0c9e81f8cbd5..7b92b5cdaae3 100644
--- a/sys/dev/rtwn/if_rtwn.c
+++ b/sys/dev/rtwn/if_rtwn.c
@@ -628,10 +628,10 @@ rtwn_vap_delete(struct ieee80211vap *vap)
 	ieee80211_draintask(ic, &ic->ic_parent_task);
 
 	RTWN_LOCK(sc);
-	if (uvp->bcn_mbuf != NULL)
-		m_freem(uvp->bcn_mbuf);
 	/* Cancel any unfinished Tx. */
 	rtwn_reset_lists(sc, vap);
+	if (uvp->bcn_mbuf != NULL)
+		m_freem(uvp->bcn_mbuf);
 	rtwn_vap_decrement_counters(sc, vap->iv_opmode, uvp->id);
 	rtwn_set_ic_opmode(sc);
 	if (sc->sc_flags & RTWN_RUNNING)
@@ -822,8 +822,10 @@ rtwn_push_nulldata(struct rtwn_softc *sc, struct ieee80211vap *vap)
 	rtwn_setbits_1_shift(sc, R92C_FWHW_TXQ_CTRL,
 	    R92C_FWHW_TXQ_CTRL_REAL_BEACON, 0, 2);
 
-	if (uvp->bcn_mbuf != NULL)
+	if (uvp->bcn_mbuf != NULL) {
+		rtwn_beacon_unload(sc, uvp->id);
 		m_freem(uvp->bcn_mbuf);
+	}
 
 	m->m_pkthdr.len = m->m_len = required_size - sc->txdesc_len;
 	uvp->bcn_mbuf = m;
@@ -1268,6 +1270,9 @@ rtwn_run(struct rtwn_softc *sc, struct ieee80211vap *vap)
 	}
 #endif
 
+	/* Enable TSF synchronization. */
+	rtwn_tsf_sync_enable(sc, vap);
+
 	if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
 	    vap->iv_opmode == IEEE80211_M_IBSS) {
 		error = rtwn_setup_beacon(sc, ni);
@@ -1282,9 +1287,6 @@ rtwn_run(struct rtwn_softc *sc, struct ieee80211vap *vap)
 	/* Set ACK preamble type. */
 	rtwn_set_ack_preamble(sc);
 
-	/* Enable TSF synchronization. */
-	rtwn_tsf_sync_enable(sc, vap);
-
 	/* Set basic rates mask. */
 	rtwn_calc_basicrates(sc);
 
diff --git a/sys/dev/rtwn/if_rtwn_beacon.c b/sys/dev/rtwn/if_rtwn_beacon.c
index c2329ad517a0..c10dd4e381c3 100644
--- a/sys/dev/rtwn/if_rtwn_beacon.c
+++ b/sys/dev/rtwn/if_rtwn_beacon.c
@@ -54,6 +54,7 @@ rtwn_reset_beacon_valid(struct rtwn_softc *sc, int id)
 
 	KASSERT (id == 0 || id == 1, ("wrong port id %d\n", id));
 
+	/* XXX cannot be cleared on RTL8188CE */
 	rtwn_setbits_1_shift(sc, sc->bcn_status_reg[id],
 	    R92C_TDECTRL_BCN_VALID, 0, 2);
 
@@ -79,7 +80,7 @@ rtwn_check_beacon_valid(struct rtwn_softc *sc, int id)
 			    __func__, id);
 			break;
 		}
-		rtwn_delay(sc, 100);
+		rtwn_delay(sc, sc->bcn_check_interval);
 	}
 	if (ntries == 10)
 		return (ETIMEDOUT);
@@ -123,8 +124,10 @@ rtwn_setup_beacon(struct rtwn_softc *sc, struct ieee80211_node *ni)
 		return (ENOMEM);
 	}
 
-	if (uvp->bcn_mbuf != NULL)
+	if (uvp->bcn_mbuf != NULL) {
+		rtwn_beacon_unload(sc, uvp->id);
 		m_freem(uvp->bcn_mbuf);
+	}
 
 	uvp->bcn_mbuf = m;
 
@@ -173,6 +176,7 @@ rtwn_update_beacon(struct ieee80211vap *vap, int item)
 			return;
 		}
 	}
+	rtwn_beacon_update_begin(sc, vap);
 	RTWN_UNLOCK(sc);
 
 	if (item == IEEE80211_BEACON_TIM)
@@ -183,6 +187,7 @@ rtwn_update_beacon(struct ieee80211vap *vap, int item)
 
 	RTWN_LOCK(sc);
 	rtwn_tx_beacon(sc, uvp);
+	rtwn_beacon_update_end(sc, vap);
 	RTWN_UNLOCK(sc);
 }
 
diff --git a/sys/dev/rtwn/if_rtwnvar.h b/sys/dev/rtwn/if_rtwnvar.h
index 198391fa6207..80c7f4c45418 100644
--- a/sys/dev/rtwn/if_rtwnvar.h
+++ b/sys/dev/rtwn/if_rtwnvar.h
@@ -277,6 +277,14 @@ struct rtwn_softc {
 	uint16_t	(*sc_get_qmap)(struct rtwn_softc *);
 	void		(*sc_set_desc_addr)(struct rtwn_softc *);
 	void		(*sc_drop_incorrect_tx)(struct rtwn_softc *);
+	void		(*sc_beacon_update_begin)(struct rtwn_softc *,
+			    struct ieee80211vap *);
+	void		(*sc_beacon_update_end)(struct rtwn_softc *,
+			    struct ieee80211vap *);
+	void		(*sc_beacon_unload)(struct rtwn_softc *, int);
+
+	/* XXX drop checks for PCIe? */
+	int		bcn_check_interval;
 
 	/* Device-specific. */
 	uint32_t	(*sc_rf_read)(struct rtwn_softc *, int, uint8_t);
@@ -445,6 +453,12 @@ void	rtwn_suspend(struct rtwn_softc *);
 	(((_sc)->sc_set_desc_addr)((_sc)))
 #define rtwn_drop_incorrect_tx(_sc) \
 	(((_sc)->sc_drop_incorrect_tx)((_sc)))
+#define rtwn_beacon_update_begin(_sc, _vap) \
+	(((_sc)->sc_beacon_update_begin)((_sc), (_vap)))
+#define rtwn_beacon_update_end(_sc, _vap) \
+	(((_sc)->sc_beacon_update_end)((_sc), (_vap)))
+#define rtwn_beacon_unload(_sc, _id) \
+	(((_sc)->sc_beacon_unload)((_sc), (_id)))
 
 /* Aliases. */
 #define	rtwn_bb_write		rtwn_write_4
diff --git a/sys/dev/rtwn/pci/rtwn_pci_attach.c b/sys/dev/rtwn/pci/rtwn_pci_attach.c
index 4db4427a5f89..00dcacc50f5a 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_attach.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_attach.c
@@ -87,6 +87,10 @@ static int	rtwn_pci_fw_write_block(struct rtwn_softc *,
 		    const uint8_t *, uint16_t, int);
 static uint16_t	rtwn_pci_get_qmap(struct rtwn_softc *);
 static void	rtwn_pci_set_desc_addr(struct rtwn_softc *);
+static void	rtwn_pci_beacon_update_begin(struct rtwn_softc *,
+		    struct ieee80211vap *);
+static void	rtwn_pci_beacon_update_end(struct rtwn_softc *,
+		    struct ieee80211vap *);
 static void	rtwn_pci_attach_methods(struct rtwn_softc *);
 
 
@@ -538,6 +542,27 @@ rtwn_pci_set_desc_addr(struct rtwn_softc *sc)
 	rtwn_pci_write_4(sc, R92C_RX_DESA, pc->rx_ring.paddr);
 }
 
+static void
+rtwn_pci_beacon_update_begin(struct rtwn_softc *sc, struct ieee80211vap *vap)
+{
+	struct rtwn_vap *rvp = RTWN_VAP(vap);
+
+	RTWN_ASSERT_LOCKED(sc);
+
+	rtwn_beacon_enable(sc, rvp->id, 0);
+}
+
+static void
+rtwn_pci_beacon_update_end(struct rtwn_softc *sc, struct ieee80211vap *vap)
+{
+	struct rtwn_vap *rvp = RTWN_VAP(vap);
+
+	RTWN_ASSERT_LOCKED(sc);
+
+	if (rvp->curr_mode != R92C_MSR_NOLINK)
+		rtwn_beacon_enable(sc, rvp->id, 1);
+}
+
 static void
 rtwn_pci_attach_methods(struct rtwn_softc *sc)
 {
@@ -555,6 +580,11 @@ rtwn_pci_attach_methods(struct rtwn_softc *sc)
 	sc->sc_get_qmap		= rtwn_pci_get_qmap;
 	sc->sc_set_desc_addr	= rtwn_pci_set_desc_addr;
 	sc->sc_drop_incorrect_tx = rtwn_nop_softc;
+	sc->sc_beacon_update_begin = rtwn_pci_beacon_update_begin;
+	sc->sc_beacon_update_end = rtwn_pci_beacon_update_end;
+	sc->sc_beacon_unload	= rtwn_pci_reset_beacon_ring;
+
+	sc->bcn_check_interval	= 25000;
 }
 
 static int
diff --git a/sys/dev/rtwn/pci/rtwn_pci_tx.c b/sys/dev/rtwn/pci/rtwn_pci_tx.c
index c1da8f648554..d3e18083fdda 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_tx.c
+++ b/sys/dev/rtwn/pci/rtwn_pci_tx.c
@@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$");
 
 
 static int
-rtwn_pci_tx_start_common(struct rtwn_softc *sc, struct ieee80211_node *ni,
-    struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
+rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
+    struct mbuf *m, uint8_t *tx_desc, uint8_t type)
 {
 	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
 	struct rtwn_tx_ring *ring;
@@ -75,16 +75,13 @@ rtwn_pci_tx_start_common(struct rtwn_softc *sc, struct ieee80211_node *ni,
 	switch (type) {
 	case IEEE80211_FC0_TYPE_CTL:
 	case IEEE80211_FC0_TYPE_MGT:
-		qid = RTWN_PCI_VO_QUEUE;
+		qid = RTWN_PCI_MGNT_QUEUE;
 		break;
 	default:
 		qid = M_WME_GETAC(m);
 		break;
 	}
 
-	if (ni == NULL)		/* beacon frame */
-		qid = RTWN_PCI_BEACON_QUEUE;
-
 	ring = &pc->tx_ring[qid];
 	data = &ring->tx_data[ring->cur];
 	if (data->m != NULL) {
@@ -151,19 +148,16 @@ rtwn_pci_tx_start_common(struct rtwn_softc *sc, struct ieee80211_node *ni,
 
 	data->m = m;
 	data->ni = ni;
-	data->id = id;
 
 	ring->cur = (ring->cur + 1) % RTWN_PCI_TX_LIST_COUNT;
 
-	if (qid != RTWN_PCI_BEACON_QUEUE) {
-		ring->queued++;
-		if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1))
-			sc->qfullmsk |= (1 << qid);
+	ring->queued++;
+	if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1))
+		sc->qfullmsk |= (1 << qid);
 
 #ifndef D4054
-		sc->sc_tx_timer = 5;
+	sc->sc_tx_timer = 5;
 #endif
-	}
 
 	/* Kick TX. */
 	rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid));
@@ -171,25 +165,77 @@ rtwn_pci_tx_start_common(struct rtwn_softc *sc, struct ieee80211_node *ni,
 	return (0);
 }
 
+static int
+rtwn_pci_tx_start_beacon(struct rtwn_softc *sc, struct mbuf *m,
+    uint8_t *tx_desc, int id)
+{
+	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+	struct rtwn_tx_ring *ring;
+	struct rtwn_tx_data *data;
+	struct rtwn_tx_desc_common *txd;
+	bus_dma_segment_t segs[1];
+	int nsegs, error, own;
+
+	RTWN_ASSERT_LOCKED(sc);
+
+	KASSERT(id == 0 || id == 1, ("bogus vap id %d\n", id));
+
+	ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
+	data = &ring->tx_data[id];
+	txd = (struct rtwn_tx_desc_common *)
+	    ((uint8_t *)ring->desc + id * sc->txdesc_len);
+
+	bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+	    BUS_DMASYNC_POSTREAD);
+	own = !!(txd->flags0 & RTWN_FLAGS0_OWN);
+	error = 0;
+	if (!own || txd->pktlen != htole16(m->m_pkthdr.len)) {
+		if (!own) {
+			/* Copy Tx descriptor. */
+			rtwn_pci_copy_tx_desc(pc, txd, tx_desc);
+			txd->offset = sc->txdesc_len;
+		} else {
+			/* Reload mbuf. */
+			bus_dmamap_unload(ring->data_dmat, data->map);
+		}
+
+		error = bus_dmamap_load_mbuf_sg(ring->data_dmat,
+		    data->map, m, segs, &nsegs, BUS_DMA_NOWAIT);
+		if (error != 0) {
+			device_printf(sc->sc_dev,
+			    "can't map beacon (error %d)\n", error);
+			txd->flags0 &= ~RTWN_FLAGS0_OWN;
+			goto end;
+		}
+
+		txd->pktlen = htole16(m->m_pkthdr.len);
+		rtwn_pci_tx_postsetup(pc, txd, segs);
+		txd->flags0 |= RTWN_FLAGS0_OWN;
+end:
+		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+		    BUS_DMASYNC_PREWRITE);
+	}
+
+	/* Dump Tx descriptor. */
+	rtwn_dump_tx_desc(sc, txd);
+
+	bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
+
+	return (0);
+}
+
 int
 rtwn_pci_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
     struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
 {
 	int error = 0;
 
-	if (ni == NULL) {	/* beacon frame */
-		m = m_dup(m, M_NOWAIT);
-		if (__predict_false(m == NULL)) {
-			device_printf(sc->sc_dev,
-			    "%s: could not copy beacon frame\n", __func__);
-			return (ENOMEM);
-		}
+	RTWN_ASSERT_LOCKED(sc);
 
-		error = rtwn_pci_tx_start_common(sc, ni, m, tx_desc, type, id);
-		if (error != 0)
-			m_freem(m);
-	} else
-		error = rtwn_pci_tx_start_common(sc, ni, m, tx_desc, type, id);
+	if (ni == NULL)		/* beacon frame */
+		error = rtwn_pci_tx_start_beacon(sc, m, tx_desc, id);
+	else
+		error = rtwn_pci_tx_start_frame(sc, ni, m, tx_desc, type);
 
 	return (error);
 }
diff --git a/sys/dev/rtwn/pci/rtwn_pci_var.h b/sys/dev/rtwn/pci/rtwn_pci_var.h
index 4a6d54c21da8..5a9e64e73bb5 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_var.h
+++ b/sys/dev/rtwn/pci/rtwn_pci_var.h
@@ -50,7 +50,6 @@ struct rtwn_tx_data {
 	bus_dmamap_t		map;
 	struct mbuf		*m;
 	struct ieee80211_node	*ni;
-	uint8_t			id;
 };
 
 struct rtwn_tx_ring {
diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
index b324d5c2022b..65e98a0399c9 100644
--- a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
+++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
@@ -141,9 +141,7 @@ r92ce_adj_devcaps(struct rtwn_softc *sc)
 	/* XXX TODO: test everything that removed here before enabling. */
 	/* XX do NOT enable PMGT until RSVD_PAGE command will not be fixed. */
 	ic->ic_caps &= ~(
-		  IEEE80211_C_IBSS	/* check beaconing / tsf */
-		| IEEE80211_C_HOSTAP	/* the same */
-		| IEEE80211_C_PMGT	/* check null frame / device usability */
+		  IEEE80211_C_PMGT	/* check null frame / device usability */
 		| IEEE80211_C_SWAMSDUTX
 		| IEEE80211_C_FF
 	);
@@ -256,6 +254,12 @@ r92ce_attach(struct rtwn_pci_softc *pc)
 	sc->temp_delta			= R92C_CALIB_THRESHOLD;
 
 	sc->bcn_status_reg[0]		= R92C_TDECTRL;
+	/*
+	 * TODO: some additional setup is required
+	 * to maintain few beacons at the same time.
+	 *
+	 * XXX BCNQ1 mechanism is not needed here; move it to the USB module.
+	 */
 	sc->bcn_status_reg[1]		= R92C_TDECTRL;
 	sc->rcr				= 0;
 
diff --git a/sys/dev/rtwn/rtl8192c/r92c_beacon.c b/sys/dev/rtwn/rtl8192c/r92c_beacon.c
index 54b882b6707c..15af77a06fea 100644
--- a/sys/dev/rtwn/rtl8192c/r92c_beacon.c
+++ b/sys/dev/rtwn/rtl8192c/r92c_beacon.c
@@ -68,6 +68,7 @@ r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id)
 	rtwn_r92c_tx_setup_macid(sc, buf, id);
 	txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
 	txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id));
+	txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, id));
 	txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_CCK1));
 }
 
diff --git a/sys/dev/rtwn/usb/rtwn_usb_attach.c b/sys/dev/rtwn/usb/rtwn_usb_attach.c
index ee0ed22cff2f..9a3ba9ea1ea8 100644
--- a/sys/dev/rtwn/usb/rtwn_usb_attach.c
+++ b/sys/dev/rtwn/usb/rtwn_usb_attach.c
@@ -81,6 +81,7 @@ static void	rtwn_usb_start_xfers(struct rtwn_softc *);
 static void	rtwn_usb_abort_xfers(struct rtwn_softc *);
 static int	rtwn_usb_fw_write_block(struct rtwn_softc *,
 		    const uint8_t *, uint16_t, int);
+static void	rtwn_usb_drop_incorrect_tx(struct rtwn_softc *);
 static void	rtwn_usb_attach_methods(struct rtwn_softc *);
 
 #define RTWN_CONFIG_INDEX	0
@@ -318,6 +319,11 @@ rtwn_usb_attach_methods(struct rtwn_softc *sc)
 	sc->sc_get_qmap		= rtwn_usb_get_qmap;
 	sc->sc_set_desc_addr	= rtwn_nop_softc;
 	sc->sc_drop_incorrect_tx = rtwn_usb_drop_incorrect_tx;
+	sc->sc_beacon_update_begin = rtwn_nop_softc_vap;
+	sc->sc_beacon_update_end = rtwn_nop_softc_vap;
+	sc->sc_beacon_unload	= rtwn_nop_softc_int;
+
+	sc->bcn_check_interval	= 100;
 }
 
 static int

From 59b591b1b17668b03950a8197800f39a65f1770f Mon Sep 17 00:00:00 2001
From: Michal Meloun 
Date: Mon, 7 Nov 2016 05:34:44 +0000
Subject: [PATCH 070/127] Rework NVIDIA Tegra124 XUSBPAD driver.  - Adapt it
 for new, incompatible, DT bindings introduced by r306197.  - Add support for
 USB super speed pads/ports.

MFC after: 3 weeks
---
 sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c | 1175 +++++++++++++----
 1 file changed, 893 insertions(+), 282 deletions(-)

diff --git a/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c b/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
index d61f3cb09f2b..2b1c9f57a7a3 100644
--- a/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
+++ b/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
@@ -39,26 +39,57 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 #include 
 
 #include "phy_if.h"
 
+/* FUSE calibration data. */
+#define	FUSE_XUSB_CALIB				0x0F0
+#define	  FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(x)		(((x) >> 15) & 0x3F);
+#define	  FUSE_XUSB_CALIB_HS_IREF_CAP(x)		(((x) >> 13) & 0x03);
+#define	  FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(x)		(((x) >> 11) & 0x03);
+#define	  FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(x)		(((x) >>  7) & 0x0F);
+#define	  FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(x)		(((x) >>  0) & 0x3F);
+
+
+/* Registers. */
 #define	XUSB_PADCTL_USB2_PAD_MUX		0x004
 
+#define	XUSB_PADCTL_USB2_PORT_CAP		0x008
+#define	 USB2_PORT_CAP_ULPI_PORT_INTERNAL		(1 << 25)
+#define	 USB2_PORT_CAP_ULPI_PORT_CAP			(1 << 24)
+#define	 USB2_PORT_CAP_PORT_REVERSE_ID(p)		(1 << (3 + (p) * 4))
+#define	 USB2_PORT_CAP_PORT_INTERNAL(p)			(1 << (2 + (p) * 4))
+#define	 USB2_PORT_CAP_PORT_CAP(p, x)			(((x) & 3) << ((p) * 4))
+#define	  USB2_PORT_CAP_PORT_CAP_OTG			0x3
+#define	  USB2_PORT_CAP_PORT_CAP_DEVICE			0x2
+#define	  USB2_PORT_CAP_PORT_CAP_HOST			0x1
+#define	  USB2_PORT_CAP_PORT_CAP_DISABLED		0x0
+
+#define	XUSB_PADCTL_SS_PORT_MAP			0x014
+#define	 SS_PORT_MAP_PORT_INTERNAL(p)			(1 << (3 + (p) * 4))
+#define	 SS_PORT_MAP_PORT_MAP(p, x)			(((x) & 7) << ((p) * 4))
+
 #define	XUSB_PADCTL_ELPG_PROGRAM		0x01C
 #define	 ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN		(1 << 26)
 #define	 ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY	(1 << 25)
 #define	 ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN		(1 << 24)
+#define	 ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(x) 		(1 << (18 + (x) * 4))
+#define	 ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(x) 	(1 << (17 + (x) * 4))
+#define	 ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(x)		(1 << (16 + (x) * 4))
 
 #define	XUSB_PADCTL_IOPHY_PLL_P0_CTL1		0x040
 #define	 IOPHY_PLL_P0_CTL1_PLL0_LOCKDET			(1 << 19)
-#define	 IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK		(0xf<< 12)
+#define	 IOPHY_PLL_P0_CTL1_REFCLK_SEL(x)		(((x) & 0xF) << 12)
 #define	 IOPHY_PLL_P0_CTL1_PLL_RST			(1 << 1)
 
 #define	XUSB_PADCTL_IOPHY_PLL_P0_CTL2		0x044
@@ -66,8 +97,59 @@
 #define	 IOPHY_PLL_P0_CTL2_TXCLKREF_EN			(1 << 5)
 #define	 IOPHY_PLL_P0_CTL2_TXCLKREF_SEL			(1 << 4)
 
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(x) 	(0x058 + (x) * 4)
+#define	 IOPHY_USB3_PAD_CTL2_CDR_CNTL(x)		(((x) & 0x00FF) <<  4)
+#define	 IOPHY_USB3_PAD_CTL2_RX_EQ(x)			(((x) & 0xFFFF) <<  8)
+#define	 IOPHY_USB3_PAD_CTL2_RX_WANDER(x)		(((x) & 0x000F) <<  4)
+#define	 IOPHY_USB3_PAD_CTL2_RX_TERM_CNTL(x)		(((x) & 0x0003) <<  2)
+#define	 IOPHY_USB3_PAD_CTL2_TX_TERM_CNTL(x)		(((x) & 0x0003) <<  0)
+
+
+#define	XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(x)	(0x068 + (x) * 4)
+
+#define	XUSB_PADCTL_USB2_OTG_PAD_CTL0(x) 	(0x0A0 + (x) * 4)
+#define	 USB2_OTG_PAD_CTL0_LSBIAS_SEL			(1 << 23)
+#define	 USB2_OTG_PAD_CTL0_DISCON_DETECT_METHOD		(1 << 22)
+#define	 USB2_OTG_PAD_CTL0_PD_ZI			(1 << 21)
+#define	 USB2_OTG_PAD_CTL0_PD2				(1 << 20)
+#define	 USB2_OTG_PAD_CTL0_PD				(1 << 19)
+#define	 USB2_OTG_PAD_CTL0_TERM_EN			(1 << 18)
+#define	 USB2_OTG_PAD_CTL0_LS_LS_FSLEW(x)		(((x) & 0x03) << 16)
+#define	 USB2_OTG_PAD_CTL0_LS_RSLEW(x)			(((x) & 0x03) << 14)
+#define	 USB2_OTG_PAD_CTL0_FS_SLEW(x)			(((x) & 0x03) << 12)
+#define	 USB2_OTG_PAD_CTL0_HS_SLEW(x)			(((x) & 0x3F) <<  6)
+#define	 USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(x)		(((x) & 0x3F) <<  0)
+
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1(x) 	(0x0AC + (x) * 4)
+#define	 USB2_OTG_PAD_CTL1_RPU_RANGE_ADJ(x)		(((x) & 0x3) << 11)
+#define	 USB2_OTG_PAD_CTL1_HS_IREF_CAP(x)		(((x) & 0x3) <<  9)
+#define	 USB2_OTG_PAD_CTL1_SPARE(x)			(((x) & 0x3) <<  7)
+#define	 USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(x)		(((x) & 0xF) <<  3)
+#define	 USB2_OTG_PAD_CTL1_PD_DR			(1 <<  2)
+#define	 USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP	(1 <<  1)
+#define	 USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP	(1 <<  0)
+
+#define	XUSB_PADCTL_USB2_BIAS_PAD_CTL0		0x0B8
+#define	 USB2_BIAS_PAD_CTL0_ADJRPU(x)			(((x) & 0x7) << 14)
+#define	 USB2_BIAS_PAD_CTL0_PD_TRK			(1 << 13)
+#define	 USB2_BIAS_PAD_CTL0_PD				(1 << 12)
+#define	 USB2_BIAS_PAD_CTL0_TERM_OFFSETL(x)		(((x) & 0x3) <<  9)
+#define	 USB2_BIAS_PAD_CTL0_VBUS_LEVEL(x)		(((x) & 0x3) <<  7)
+#define	 USB2_BIAS_PAD_CTL0_HS_CHIRP_LEVEL(x)		(((x) & 0x3) <<  5)
+#define	 USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(x)		(((x) & 0x7) <<  2)
+#define	 USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(x)		(((x) & 0x3) <<  0)
+
+#define	XUSB_PADCTL_HSIC_PAD0_CTL0		0x0C8
+#define	 HSIC_PAD0_CTL0_HSIC_OPT(x)			(((x) & 0xF) << 16)
+#define	 HSIC_PAD0_CTL0_TX_SLEWN(x)			(((x) & 0xF) << 12)
+#define	 HSIC_PAD0_CTL0_TX_SLEWP(x)			(((x) & 0xF) <<  8)
+#define	 HSIC_PAD0_CTL0_TX_RTUNEN(x)			(((x) & 0xF) <<  4)
+#define	 HSIC_PAD0_CTL0_TX_RTUNEP(x)			(((x) & 0xF) <<  0)
 
 #define	XUSB_PADCTL_USB3_PAD_MUX		0x134
+#define	 USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) 		(1 << (1 + (x)))
+#define	 USB3_PAD_MUX_SATA_IDDQ_DISABLE 		(1 << 6)
+
 
 #define	XUSB_PADCTL_IOPHY_PLL_S0_CTL1		0x138
 #define	 IOPHY_PLL_S0_CTL1_PLL1_LOCKDET			(1 << 27)
@@ -90,17 +172,25 @@
 #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5	0x158
 #define	XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6	0x15C
 
-struct lane_cfg {
-	char	*function;
-	char 	**lanes;
-	int 	iddq;
-};
 
-struct xusbpadctl_softc {
+#define	WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res, (_r), (_v))
+#define	RD4(_sc, _r)		bus_read_4((_sc)->mem_res, (_r))
+
+
+struct padctl_softc {
 	device_t	dev;
 	struct resource	*mem_res;
-	hwreset_t		rst;
+	hwreset_t	rst;
 	int		phy_ena_cnt;
+
+	/* Fuses calibration data */
+	uint32_t	hs_curr_level_0;
+	uint32_t	hs_curr_level_123;
+	uint32_t	hs_iref_cap;
+	uint32_t	hs_term_range_adj;
+	uint32_t	hs_squelch_level;
+
+	uint32_t	hs_curr_level_offset;
 };
 
 static struct ofw_compat_data compat_data[] = {
@@ -108,274 +198,295 @@ static struct ofw_compat_data compat_data[] = {
 	{NULL,				0},
 };
 
-struct padctl_lane {
-	const char *name;
-	bus_size_t reg;
-	uint32_t shift;
-	uint32_t mask;
-	int iddq;
-	char **mux;
-	int nmux;
+/* Ports. */
+enum padctl_port_type {
+	PADCTL_PORT_USB2,
+	PADCTL_PORT_ULPI,
+	PADCTL_PORT_HSIC,
+	PADCTL_PORT_USB3,
 };
 
+struct padctl_lane;
+struct padctl_port {
+	enum padctl_port_type	type;
+	const char		*name;
+	const char		*base_name;
+	int			idx;
+	int			(*init)(struct padctl_softc *sc,
+				    struct padctl_port *port);
+
+	/* Runtime data. */
+	phandle_t		xref;
+	bool			enabled;
+	regulator_t		supply_vbus;	/* USB2, USB3 */
+	bool			internal;	/* ULPI, USB2, USB3 */
+	uint32_t		companion;	/* USB3 */
+	struct padctl_lane	*lane;
+};
+
+static int usb3_port_init(struct padctl_softc *sc, struct padctl_port *port);
+
+#define	PORT(t, n, p, i) {						\
+	.type = t,							\
+	.name = n "-" #p,						\
+	.base_name = n,							\
+	.idx = p,							\
+	.init = i,							\
+}
+static struct padctl_port ports_tbl[] = {
+	PORT(PADCTL_PORT_USB2, "usb2", 0, NULL),
+	PORT(PADCTL_PORT_USB2, "usb2", 1, NULL),
+	PORT(PADCTL_PORT_USB2, "usb2", 2, NULL),
+	PORT(PADCTL_PORT_ULPI, "ulpi", 0, NULL),
+	PORT(PADCTL_PORT_HSIC, "hsic", 0, NULL),
+	PORT(PADCTL_PORT_HSIC, "hsic", 1, NULL),
+	PORT(PADCTL_PORT_USB3, "usb3", 0, usb3_port_init),
+	PORT(PADCTL_PORT_USB3, "usb3", 1, usb3_port_init),
+};
+
+/* Pads - a group of lannes. */
+enum padctl_pad_type {
+	PADCTL_PAD_USB2,
+	PADCTL_PAD_ULPI,
+	PADCTL_PAD_HSIC,
+	PADCTL_PAD_PCIE,
+	PADCTL_PAD_SATA,
+};
+
+struct padctl_lane;
+struct padctl_pad {
+	const char		*name;
+	enum padctl_pad_type	type;
+	int			(*powerup)(struct padctl_softc *sc,
+				    struct padctl_lane *lane);
+	int			(*powerdown)(struct padctl_softc *sc,
+				    struct padctl_lane *lane);
+	/* Runtime data. */
+	bool			enabled;
+	struct padctl_lane	*lanes[8]; 	/* Safe maximum value. */
+	int			nlanes;
+};
+
+static int usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane);
+static int usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);
+static int pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane);
+static int pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);
+static int sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane);
+static int sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);
+
+#define	PAD(n, t, u, d) {						\
+	.name = n,							\
+	.type = t,							\
+	.powerup = u,							\
+	.powerdown = d,							\
+}
+static struct padctl_pad pads_tbl[] = {
+	PAD("usb2", PADCTL_PAD_USB2, usb2_powerup, usb2_powerdown),
+	PAD("ulpi", PADCTL_PAD_ULPI, NULL, NULL),
+	PAD("hsic", PADCTL_PAD_HSIC, NULL, NULL),
+	PAD("pcie", PADCTL_PAD_PCIE, pcie_powerup, pcie_powerdown),
+	PAD("sata", PADCTL_PAD_SATA, sata_powerup, sata_powerdown),
+};
+
+/* Lanes. */
 static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"};
 static char *usb_mux[] = {"snps", "xusb"};
-static char *pci_mux[] = {"pcie", "usb3", "sata", "rsvd"};
+static char *pci_mux[] = {"pcie", "usb3-ss", "sata", "rsvd"};
 
-#define	LANE(n, r, s, m, i, mx)					\
-{								\
-	.name = n,						\
-	.reg = r,						\
-	.shift = s,						\
-	.mask = m,						\
-	.iddq = i,						\
-	.mux = mx,						\
-	.nmux = nitems(mx),					\
-}
+struct padctl_lane {
+	const char		*name;
+	int			idx;
+	bus_size_t		reg;
+	uint32_t		shift;
+	uint32_t		mask;
+	char			**mux;
+	int			nmux;
+	/* Runtime data. */
+	bool			enabled;
+	phandle_t		xref;
+	struct padctl_pad	*pad;
+	struct padctl_port	*port;
+	int			mux_idx;
 
-static const struct padctl_lane lanes_tbl[] = {
-	LANE("otg-0",  XUSB_PADCTL_USB2_PAD_MUX,  0, 0x3, -1, otg_mux),
-	LANE("otg-1",  XUSB_PADCTL_USB2_PAD_MUX,  2, 0x3, -1, otg_mux),
-	LANE("otg-2",  XUSB_PADCTL_USB2_PAD_MUX,  4, 0x3, -1, otg_mux),
-	LANE("ulpi-0", XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, -1, usb_mux),
-	LANE("hsic-0", XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, -1, usb_mux),
-	LANE("hsic-1", XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, -1, usb_mux),
-	LANE("pcie-0", XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3,  1, pci_mux),
-	LANE("pcie-1", XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3,  2, pci_mux),
-	LANE("pcie-2", XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3,  3, pci_mux),
-	LANE("pcie-3", XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3,  4, pci_mux),
-	LANE("pcie-4", XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3,  5, pci_mux),
-	LANE("sata-0", XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3,  6, pci_mux),
 };
 
-static int
-xusbpadctl_mux_function(const struct padctl_lane *lane, char *fnc_name)
-{
-	int i;
-
-	for (i = 0; i < lane->nmux; i++) {
-		if (strcmp(fnc_name, lane->mux[i]) == 0)
-			return 	(i);
-	}
-
-	return (-1);
+#define	LANE(n, p, r, s, m, mx) {					\
+	.name = n "-" #p,						\
+	.idx = p,							\
+	.reg = r,							\
+	.shift = s,							\
+	.mask = m,							\
+	.mux = mx,							\
+	.nmux = nitems(mx),						\
 }
+static struct padctl_lane lanes_tbl[] = {
+	LANE("usb2", 0, XUSB_PADCTL_USB2_PAD_MUX,  0, 0x3, otg_mux),
+	LANE("usb2", 1, XUSB_PADCTL_USB2_PAD_MUX,  2, 0x3, otg_mux),
+	LANE("usb2", 2, XUSB_PADCTL_USB2_PAD_MUX,  4, 0x3, otg_mux),
+	LANE("ulpi", 0, XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, usb_mux),
+	LANE("hsic", 0, XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, usb_mux),
+	LANE("hsic", 1, XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, usb_mux),
+	LANE("pcie", 0, XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, pci_mux),
+	LANE("pcie", 1, XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, pci_mux),
+	LANE("pcie", 2, XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, pci_mux),
+	LANE("pcie", 3, XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, pci_mux),
+	LANE("pcie", 4, XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, pci_mux),
+	LANE("sata", 0, XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, pci_mux),
+};
 
+/* Define all possible mappings for USB3 port lanes */
+struct padctl_lane_map {
+	int			port_idx;
+	enum padctl_pad_type	pad_type;
+	int			lane_idx;
+};
+
+#define	LANE_MAP(pi, pt, li) {						\
+	.port_idx = pi,							\
+	.pad_type = pt,							\
+	.lane_idx = li,							\
+}
+static struct padctl_lane_map lane_map_tbl[] = {
+	LANE_MAP(0, PADCTL_PAD_PCIE, 0), 	/* port USB3-0 -> lane PCIE-0 */
+	LANE_MAP(1, PADCTL_PAD_PCIE, 1), 	/* port USB3-1 -> lane PCIE-1 */
+						/* -- or -- */
+	LANE_MAP(1, PADCTL_PAD_SATA, 0), 	/* port USB3-1 -> lane SATA-0 */
+};
+
+static struct padctl_port *search_lane_port(struct padctl_softc *sc,
+    struct padctl_lane *lane);
+/* -------------------------------------------------------------------------
+ *
+ *   PHY functions
+ */
 static int
-xusbpadctl_config_lane(struct xusbpadctl_softc *sc, char *lane_name,
-    const struct padctl_lane *lane, struct lane_cfg *cfg)
+usb3_port_init(struct padctl_softc *sc, struct padctl_port *port)
 {
-
-	int tmp;
 	uint32_t reg;
 
-	reg = bus_read_4(sc->mem_res, lane->reg);
-	if (cfg->function != NULL) {
-		tmp = xusbpadctl_mux_function(lane, cfg->function);
-		if (tmp == -1) {
-			device_printf(sc->dev,
-			    "Unknown function %s for lane %s\n", cfg->function,
-			    lane_name);
-			return (EINVAL);
-		}
-		reg &= ~(lane->mask << lane->shift);
-		reg |=  (tmp & lane->mask) << lane->shift;
-	}
-	if (cfg->iddq != -1) {
-		if (lane->iddq == -1) {
-			device_printf(sc->dev, "Invalid IDDQ for lane %s\n",
-			lane_name);
-			return (EINVAL);
-		}
-		if (cfg->iddq != 0)
-			reg &= ~(1 << lane->iddq);
-		else
-			reg |= 1 << lane->iddq;
-	}
+	reg = RD4(sc, XUSB_PADCTL_SS_PORT_MAP);
+	if (port->internal)
+		reg &= ~SS_PORT_MAP_PORT_INTERNAL(port->idx);
+	else
+		reg |= SS_PORT_MAP_PORT_INTERNAL(port->idx);
+	reg &= ~SS_PORT_MAP_PORT_MAP(port->idx, ~0);
+	reg |= SS_PORT_MAP_PORT_MAP(port->idx, port->companion);
+	WR4(sc, XUSB_PADCTL_SS_PORT_MAP, reg);
 
-	bus_write_4(sc->mem_res, lane->reg, reg);
-	return (0);
-}
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx));
+	reg &= ~IOPHY_USB3_PAD_CTL2_CDR_CNTL(~0);
+	reg &= ~IOPHY_USB3_PAD_CTL2_RX_EQ(~0);
+	reg &= ~IOPHY_USB3_PAD_CTL2_RX_WANDER(~0);
+	reg |= IOPHY_USB3_PAD_CTL2_CDR_CNTL(0x24);
+	reg |= IOPHY_USB3_PAD_CTL2_RX_EQ(0xF070);
+	reg |= IOPHY_USB3_PAD_CTL2_RX_WANDER(0xF);
+	WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx), reg);
 
-static const struct padctl_lane *
-xusbpadctl_search_lane(char *lane_name)
-{
-	int i;
+	WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(port->idx),
+	    0x002008EE);
 
-	for (i = 0; i < nitems(lanes_tbl); i++) {
-		if (strcmp(lane_name, lanes_tbl[i].name) == 0)
-			return 	(&lanes_tbl[i]);
-	}
-
-	return (NULL);
-}
-
-static int
-xusbpadctl_config_node(struct xusbpadctl_softc *sc, char *lane_name,
-    struct lane_cfg *cfg)
-{
-	const struct padctl_lane *lane;
-	int rv;
-
-	lane = xusbpadctl_search_lane(lane_name);
-	if (lane == NULL) {
-		device_printf(sc->dev, "Unknown lane: %s\n", lane_name);
-		return (ENXIO);
-	}
-	rv = xusbpadctl_config_lane(sc, lane_name, lane, cfg);
-	return (rv);
-}
-
-static int
-xusbpadctl_read_node(struct xusbpadctl_softc *sc, phandle_t node,
-    struct lane_cfg *cfg, char **lanes, int *llanes)
-{
-	int rv;
-
-	*llanes = OF_getprop_alloc(node, "nvidia,lanes", 1, (void **)lanes);
-	if (*llanes <= 0)
-		return (ENOENT);
-
-	/* Read function (mux) settings. */
-	rv = OF_getprop_alloc(node, "nvidia,function", 1,
-	    (void **)&cfg->function);
-	if (rv <= 0)
-		cfg->function = NULL;
-	/* Read numeric properties. */
-	rv = OF_getencprop(node, "nvidia,iddq", &cfg->iddq,
-	    sizeof(cfg->iddq));
-	if (rv <= 0)
-		cfg->iddq = -1;
-	return (0);
-}
-
-static int
-xusbpadctl_process_node(struct xusbpadctl_softc *sc, phandle_t node)
-{
-	struct lane_cfg cfg;
-	char *lanes, *lname;
-	int i, len, llanes, rv;
-
-	rv = xusbpadctl_read_node(sc, node, &cfg, &lanes, &llanes);
-	if (rv != 0)
-		return (rv);
-
-	len = 0;
-	lname = lanes;
-	do {
-		i = strlen(lname) + 1;
-		rv = xusbpadctl_config_node(sc, lname, &cfg);
-		if (rv != 0)
-			device_printf(sc->dev,
-			    "Cannot configure lane: %s: %d\n", lname, rv);
-
-		len += i;
-		lname += i;
-	} while (len < llanes);
-
-	if (lanes != NULL)
-		OF_prop_free(lanes);
-	if (cfg.function != NULL)
-		OF_prop_free(cfg.function);
-	return (rv);
-}
-
-
-static int
-xusbpadctl_pinctrl_cfg(device_t dev, phandle_t cfgxref)
-{
-	struct xusbpadctl_softc *sc;
-	phandle_t node, cfgnode;
-	int rv;
-
-	sc = device_get_softc(dev);
-	cfgnode = OF_node_from_xref(cfgxref);
-
-	rv = 0;
-	for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
-		if (!fdt_is_enabled(node))
-			continue;
-		rv = xusbpadctl_process_node(sc, node);
-		if (rv != 0)
-			return (rv);
-	}
-
-	return (rv);
-}
-
-static int
-xusbpadctl_phy_pcie_powerup(struct xusbpadctl_softc *sc)
-{
-	uint32_t reg;
-	int i;
-
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-	reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+	reg &= ~ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(port->idx);
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
 	DELAY(100);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+	reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(port->idx);
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	DELAY(100);
+
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+	reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(port->idx);
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	DELAY(100);
+
+	return (0);
+}
+
+static int
+pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane)
+{
+	uint32_t reg;
+	int i;
+
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL(~0);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+	DELAY(100);
+
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
 	reg |= IOPHY_PLL_P0_CTL2_REFCLKBUF_EN;
 	reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_EN;
 	reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);
 	DELAY(100);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 	reg |= IOPHY_PLL_P0_CTL1_PLL_RST;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
 	DELAY(100);
 
-	for (i = 0; i < 100; i++) {
-		reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	for (i = 100; i > 0; i--) {
+		reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 		if (reg & IOPHY_PLL_P0_CTL1_PLL0_LOCKDET)
-			return (0);
+			break;
 		DELAY(10);
 	}
+	if (i <= 0) {
+		device_printf(sc->dev, "Failed to power up PCIe phy\n");
+		return (ETIMEDOUT);
+	}
+	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+	reg |= USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);
+	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
 
-	return (ETIMEDOUT);
+	return (0);
 }
 
-
 static int
-xusbpadctl_phy_pcie_powerdown(struct xusbpadctl_softc *sc)
+pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)
 {
 	uint32_t reg;
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+	reg &= ~USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);
+	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 	reg &= ~IOPHY_PLL_P0_CTL1_PLL_RST;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
 	DELAY(100);
+
 	return (0);
 
 }
 
 static int
-xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *sc)
+sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane)
 {
 	uint32_t reg;
 	int i;
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
 	reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
 	reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 	reg &= ~IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
 	reg &= ~IOPHY_PLL_S0_CTL1_PLL_IDDQ;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 	reg |= IOPHY_PLL_S0_CTL1_PLL1_MODE;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 	reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
 
 	for (i = 100; i >= 0; i--) {
-		reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+		reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 		if (reg & IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)
 			break;
 		DELAY(100);
@@ -384,81 +495,188 @@ xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *sc)
 		device_printf(sc->dev, "Failed to power up SATA phy\n");
 		return (ETIMEDOUT);
 	}
+	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+	reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;
+	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+
+	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+	reg |= USB3_PAD_MUX_SATA_IDDQ_DISABLE;
+	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
 
 	return (0);
 }
 
 static int
-xusbpadctl_phy_sata_powerdown(struct xusbpadctl_softc *sc)
+sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)
 {
 	uint32_t reg;
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+	reg &= ~USB3_PAD_MUX_SATA_IDDQ_DISABLE;
+	WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 	reg &= ~IOPHY_PLL_S0_CTL1_PLL_RST_L;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
 	DELAY(100);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 	reg &= ~IOPHY_PLL_S0_CTL1_PLL1_MODE;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
 	DELAY(100);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 	reg |= IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
 	reg |= IOPHY_PLL_S0_CTL1_PLL_IDDQ;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
 	DELAY(100);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+	reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
 	reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
 	reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
+	WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
 	DELAY(100);
 
 	return (0);
 }
 
 static int
-xusbpadctl_phy_powerup(struct xusbpadctl_softc *sc)
+usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane)
+{
+	uint32_t reg;
+	struct padctl_port *port;
+	int rv;
+
+	port = search_lane_port(sc, lane);
+	if (port == NULL) {
+		device_printf(sc->dev, "Cannot find port for lane: %s\n",
+		    lane->name);
+	}
+	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	reg &= ~USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(~0);
+	reg &= ~USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(~0);
+	reg |= USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(sc->hs_squelch_level);
+	reg |= USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(5);
+	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
+
+	reg = RD4(sc, XUSB_PADCTL_USB2_PORT_CAP);
+	reg &= ~USB2_PORT_CAP_PORT_CAP(lane->idx, ~0);
+	reg |= USB2_PORT_CAP_PORT_CAP(lane->idx, USB2_PORT_CAP_PORT_CAP_HOST);
+	WR4(sc, XUSB_PADCTL_USB2_PORT_CAP, reg);
+
+	reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx));
+	reg &= ~USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(~0);
+	reg &= ~USB2_OTG_PAD_CTL0_HS_SLEW(~0);
+	reg &= ~USB2_OTG_PAD_CTL0_LS_RSLEW(~0);
+	reg &= ~USB2_OTG_PAD_CTL0_PD;
+	reg &= ~USB2_OTG_PAD_CTL0_PD2;
+	reg &= ~USB2_OTG_PAD_CTL0_PD_ZI;
+
+	reg |= USB2_OTG_PAD_CTL0_HS_SLEW(14);
+	if (lane->idx == 0) {
+		reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_0);
+		reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(3);
+	} else {
+		reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_123);
+		reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(0);
+	}
+	WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx), reg);
+
+	reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx));
+	reg &= ~USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(~0);
+	reg &= ~USB2_OTG_PAD_CTL1_HS_IREF_CAP(~0);
+	reg &= ~USB2_OTG_PAD_CTL1_PD_DR;
+	reg &= ~USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP;
+	reg &= ~USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP;
+
+	reg |= USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(sc->hs_term_range_adj);
+	reg |= USB2_OTG_PAD_CTL1_HS_IREF_CAP(sc->hs_iref_cap);
+	WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx), reg);
+
+	if (port != NULL && port->supply_vbus != NULL) {
+		rv = regulator_enable(port->supply_vbus);
+		if (rv != 0) {
+			device_printf(sc->dev,
+			    "Cannot enable vbus regulator\n");
+			return (rv);
+		}
+	}
+	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	reg &= ~USB2_BIAS_PAD_CTL0_PD;
+	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
+
+	return (0);
+}
+
+static int
+usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)
+{
+	uint32_t reg;
+	struct padctl_port *port;
+	int rv;
+
+	port = search_lane_port(sc, lane);
+	if (port == NULL) {
+		device_printf(sc->dev, "Cannot find port for lane: %s\n",
+		    lane->name);
+	}
+	reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	reg |= USB2_BIAS_PAD_CTL0_PD;
+	WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
+
+	if (port != NULL && port->supply_vbus != NULL) {
+		rv = regulator_enable(port->supply_vbus);
+		if (rv != 0) {
+			device_printf(sc->dev,
+			    "Cannot disable vbus regulator\n");
+			return (rv);
+		}
+	}
+	return (0);
+}
+
+
+static int
+phy_powerup(struct padctl_softc *sc)
 {
 	uint32_t reg;
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
-	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
-	DELAY(100);
-
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
-	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
-	DELAY(100);
-
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
 	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	DELAY(100);
+
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	DELAY(100);
+
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+	reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
 	DELAY(100);
 
 	return (0);
 }
 
 static int
-xusbpadctl_phy_powerdown(struct xusbpadctl_softc *sc)
+phy_powerdown(struct padctl_softc *sc)
 {
 	uint32_t reg;
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
-	reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
-	DELAY(100);
-
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
 	reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
 	DELAY(100);
 
-	reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
 	reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
-	bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+	DELAY(100);
+
+	reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+	reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+	WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
 	DELAY(100);
 
 	return (0);
@@ -467,45 +685,43 @@ xusbpadctl_phy_powerdown(struct xusbpadctl_softc *sc)
 static int
 xusbpadctl_phy_enable(device_t dev, intptr_t id, bool enable)
 {
-	struct xusbpadctl_softc *sc;
+	struct padctl_softc *sc;
+	struct padctl_lane *lane;
+	struct padctl_pad *pad;
 	int rv;
 
 	sc = device_get_softc(dev);
 
-	if ((id != TEGRA_XUSB_PADCTL_PCIE) &&
-	    (id != TEGRA_XUSB_PADCTL_SATA)) {
+	if (id < 0 || id >= nitems(lanes_tbl)) {
 		device_printf(dev, "Unknown phy: %d\n", id);
 		return (ENXIO);
 	}
-
-	rv = 0;
+	lane = lanes_tbl + id;
+	if (!lane->enabled) {
+		device_printf(dev, "Lane is not enabled/configured: %s\n",
+		    lane->name);
+		return (ENXIO);
+	}
+	pad = lane->pad;
 	if (enable) {
 		if (sc->phy_ena_cnt == 0) {
-			rv = xusbpadctl_phy_powerup(sc);
+			rv = phy_powerup(sc);
 			if (rv != 0)
 				return (rv);
 		}
 		sc->phy_ena_cnt++;
 	}
 
-	if (id == TEGRA_XUSB_PADCTL_PCIE) {
-		if (enable)
-			rv = xusbpadctl_phy_pcie_powerup(sc);
-		else
-			rv = xusbpadctl_phy_pcie_powerdown(sc);
-		if (rv != 0)
-			return (rv);
-	} else if (id == TEGRA_XUSB_PADCTL_SATA) {
-		if (enable)
-			rv = xusbpadctl_phy_sata_powerup(sc);
-		else
-			rv = xusbpadctl_phy_sata_powerdown(sc);
-		if (rv != 0)
-			return (rv);
-	}
+	if (enable)
+		rv = pad->powerup(sc, lane);
+	else
+		rv = pad->powerdown(sc, lane);
+	if (rv != 0)
+		return (rv);
+
 	if (!enable) {
 		 if (sc->phy_ena_cnt == 1) {
-			rv = xusbpadctl_phy_powerdown(sc);
+			rv = phy_powerdown(sc);
 			if (rv != 0)
 				return (rv);
 		}
@@ -515,6 +731,387 @@ xusbpadctl_phy_enable(device_t dev, intptr_t id, bool enable)
 	return (0);
 }
 
+static int
+xusbpadctl_phy_map(device_t provider, phandle_t xref, int ncells,
+    pcell_t *cells, intptr_t *id)
+{
+	int i;
+
+	if (ncells != 0)
+		return  (ERANGE);
+
+	for (i = 0; i < nitems(lanes_tbl); i++) {
+		if (lanes_tbl[i].xref == xref) {
+			*id = i;
+			return (0);
+		}
+	}
+	return (ENXIO);
+}
+
+/* -------------------------------------------------------------------------
+ *
+ *   FDT processing
+ */
+static struct padctl_port *
+search_port(struct padctl_softc *sc, char *port_name)
+{
+	int i;
+
+	for (i = 0; i < nitems(ports_tbl); i++) {
+		if (strcmp(port_name, ports_tbl[i].name) == 0)
+			return (&ports_tbl[i]);
+	}
+	return (NULL);
+}
+
+static struct padctl_port *
+search_lane_port(struct padctl_softc *sc, struct padctl_lane *lane)
+{
+	int i;
+
+	for (i = 0; i < nitems(ports_tbl); i++) {
+		if (!ports_tbl[i].enabled)
+			continue;
+		if (ports_tbl[i].lane == lane)
+			return (ports_tbl + i);
+	}
+	return (NULL);
+}
+
+static struct padctl_lane *
+search_lane(struct padctl_softc *sc, char *lane_name)
+{
+	int i;
+
+	for (i = 0; i < nitems(lanes_tbl); i++) {
+		if (strcmp(lane_name, lanes_tbl[i].name) == 0)
+			return 	(lanes_tbl + i);
+	}
+	return (NULL);
+}
+
+static struct padctl_lane *
+search_pad_lane(struct padctl_softc *sc, enum padctl_pad_type type, int idx)
+{
+	int i;
+
+	for (i = 0; i < nitems(lanes_tbl); i++) {
+		if (!lanes_tbl[i].enabled)
+			continue;
+		if (type == lanes_tbl[i].pad->type && idx == lanes_tbl[i].idx)
+			return 	(lanes_tbl + i);
+	}
+	return (NULL);
+}
+
+static struct padctl_lane *
+search_usb3_pad_lane(struct padctl_softc *sc, int idx)
+{
+	int i;
+	struct padctl_lane *lane, *tmp;
+
+	lane = NULL;
+	for (i = 0; i < nitems(lane_map_tbl); i++) {
+		if (idx != lane_map_tbl[i].port_idx)
+			continue;
+		tmp = search_pad_lane(sc, lane_map_tbl[i].pad_type,
+		    lane_map_tbl[i].lane_idx);
+		if (tmp == NULL)
+			continue;
+		if (strcmp(tmp->mux[tmp->mux_idx], "usb3-ss") != 0)
+			continue;
+		if (lane != NULL) {
+			device_printf(sc->dev, "Duplicated mappings found for"
+			 " lanes: %s and %s\n", lane->name, tmp->name);
+			return (NULL);
+		}
+		lane = tmp;
+	}
+	return (lane);
+}
+
+static struct padctl_pad *
+search_pad(struct padctl_softc *sc, char *pad_name)
+{
+	int i;
+
+	for (i = 0; i < nitems(pads_tbl); i++) {
+		if (strcmp(pad_name, pads_tbl[i].name) == 0)
+			return 	(pads_tbl + i);
+	}
+	return (NULL);
+}
+
+static int
+search_mux(struct padctl_softc *sc, struct padctl_lane *lane, char *fnc_name)
+{
+	int i;
+
+	for (i = 0; i < lane->nmux; i++) {
+		if (strcmp(fnc_name, lane->mux[i]) == 0)
+			return 	(i);
+	}
+	return (-1);
+}
+
+static int
+config_lane(struct padctl_softc *sc, struct padctl_lane *lane)
+{
+	uint32_t reg;
+
+	reg = RD4(sc, lane->reg);
+	reg &= ~(lane->mask << lane->shift);
+	reg |=  (lane->mux_idx & lane->mask) << lane->shift;
+	WR4(sc, lane->reg, reg);
+	return (0);
+}
+
+static int
+process_lane(struct padctl_softc *sc, phandle_t node, struct padctl_pad *pad)
+{
+	struct padctl_lane *lane;
+	char *name;
+	char *function;
+	int rv;
+
+	name = NULL;
+	function = NULL;
+	rv = OF_getprop_alloc(node, "name", 1, (void **)&name);
+	if (rv <= 0) {
+		device_printf(sc->dev, "Cannot read lane name.\n");
+		return (ENXIO);
+	}
+
+	lane = search_lane(sc, name);
+	if (lane == NULL) {
+		device_printf(sc->dev, "Unknown lane: %s\n", name);
+		rv = ENXIO;
+		goto end;
+	}
+
+	/* Read function (mux) settings. */
+	rv = OF_getprop_alloc(node, "nvidia,function", 1, (void **)&function);
+	if (rv <= 0) {
+		device_printf(sc->dev, "Cannot read lane function.\n");
+		rv = ENXIO;
+		goto end;
+	}
+
+	lane->mux_idx = search_mux(sc, lane, function);
+	if (lane->mux_idx == ~0) {
+		device_printf(sc->dev, "Unknown function %s for lane %s\n",
+		    function, name);
+		rv = ENXIO;
+		goto end;
+	}
+
+	rv = config_lane(sc, lane);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot configure lane: %s: %d\n",
+		    name, rv);
+		rv = ENXIO;
+		goto end;
+	}
+	lane->xref = OF_xref_from_node(node);
+	lane->pad = pad;
+	lane->enabled = true;
+	pad->lanes[pad->nlanes++] = lane;
+	rv = 0;
+
+end:
+	if (name != NULL)
+		OF_prop_free(name);
+	if (function != NULL)
+		OF_prop_free(function);
+	return (rv);
+}
+
+static int
+process_pad(struct padctl_softc *sc, phandle_t node)
+{
+	phandle_t  xref;
+	struct padctl_pad *pad;
+	char *name;
+	int rv;
+
+	name = NULL;
+	rv = OF_getprop_alloc(node, "name", 1, (void **)&name);
+	if (rv <= 0) {
+		device_printf(sc->dev, "Cannot read pad name.\n");
+		return (ENXIO);
+	}
+	pad = search_pad(sc, name);
+	if (pad == NULL) {
+		device_printf(sc->dev, "Unknown pad: %s\n", name);
+		rv = ENXIO;
+		goto end;
+	}
+
+	/* Read and process associated lanes. */
+	node = ofw_bus_find_child(node, "lanes");
+	if (node <= 0) {
+		device_printf(sc->dev, "Cannot find regulators subnode\n");
+		rv = ENXIO;
+		goto end;
+	}
+
+	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+		if (!fdt_is_enabled(node))
+			continue;
+
+		rv = process_lane(sc, node, pad);
+		if (rv != 0)
+			goto end;
+
+		xref = OF_xref_from_node(node);
+		OF_device_register_xref(xref, sc->dev);
+	}
+	pad->enabled = true;
+	rv = 0;
+end:
+	if (name != NULL)
+		OF_prop_free(name);
+	return (rv);
+}
+
+static int
+process_port(struct padctl_softc *sc, phandle_t node)
+{
+
+	struct padctl_port *port;
+	char *name;
+	int rv;
+
+	name = NULL;
+	rv = OF_getprop_alloc(node, "name", 1, (void **)&name);
+	if (rv <= 0) {
+		device_printf(sc->dev, "Cannot read port name.\n");
+		return (ENXIO);
+	}
+
+	port = search_port(sc, name);
+	if (port == NULL) {
+		device_printf(sc->dev, "Unknown port: %s\n", name);
+		rv = ENXIO;
+		goto end;
+	}
+
+	if (port->type == PADCTL_PORT_USB3) {
+		rv = OF_getencprop(node,  "nvidia,usb2-companion",
+		   &(port->companion), sizeof(port->companion));
+		if (rv <= 0) {
+			device_printf(sc->dev,
+			    "Missing 'nvidia,usb2-companion' property "
+			    "for port: %s\n", name);
+			rv = ENXIO;
+			goto end;
+		}
+	}
+
+	if (OF_hasprop(node, "vbus-supply")) {
+		rv = regulator_get_by_ofw_property(sc->dev, 0,
+		    "vbus-supply", &port->supply_vbus);
+		if (rv <= 0) {
+			device_printf(sc->dev,
+			    "Cannot get 'vbus-supply' regulator "
+			    "for port: %s\n", name);
+			rv = ENXIO;
+			goto end;
+		}
+	}
+
+	if (OF_hasprop(node, "nvidia,internal"))
+		port->internal = true;
+	/* Find assigned lane */
+	if (port->lane == NULL) {
+		switch(port->type) {
+		/* Routing is fixed for USB2, ULPI AND HSIC. */
+		case PADCTL_PORT_USB2:
+			port->lane = search_pad_lane(sc, PADCTL_PAD_USB2,
+			    port->idx);
+			break;
+		case PADCTL_PORT_ULPI:
+			port->lane = search_pad_lane(sc, PADCTL_PAD_ULPI,
+			    port->idx);
+			break;
+		case PADCTL_PORT_HSIC:
+			port->lane = search_pad_lane(sc, PADCTL_PAD_HSIC,
+			    port->idx);
+			break;
+		case PADCTL_PORT_USB3:
+			port->lane = search_usb3_pad_lane(sc, port->idx);
+			break;
+		}
+	}
+	if (port->lane == NULL) {
+		device_printf(sc->dev, "Cannot find lane for port: %s\n", name);
+		rv = ENXIO;
+		goto end;
+	}
+	port->enabled = true;
+	rv = 0;
+end:
+	if (name != NULL)
+		OF_prop_free(name);
+	return (rv);
+}
+
+static int
+parse_fdt(struct padctl_softc *sc, phandle_t base_node)
+{
+	phandle_t node;
+	int rv;
+
+	rv = 0;
+	node = ofw_bus_find_child(base_node, "pads");
+
+	if (node <= 0) {
+		device_printf(sc->dev, "Cannot find pads subnode.\n");
+		return (ENXIO);
+	}
+	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+		if (!fdt_is_enabled(node))
+			continue;
+		rv = process_pad(sc, node);
+		if (rv != 0)
+			return (rv);
+	}
+
+	node = ofw_bus_find_child(base_node, "ports");
+	if (node <= 0) {
+		device_printf(sc->dev, "Cannot find ports subnode.\n");
+		return (ENXIO);
+	}
+	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+		if (!fdt_is_enabled(node))
+			continue;
+		rv = process_port(sc, node);
+		if (rv != 0)
+			return (rv);
+	}
+
+	return (0);
+}
+
+static void
+load_calibration(struct padctl_softc *sc)
+{
+	uint32_t reg;
+
+	/* All XUSB pad calibrations are packed into single dword.*/
+	reg = tegra_fuse_read_4(FUSE_XUSB_CALIB);
+	sc->hs_curr_level_0 = FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(reg);
+	sc->hs_curr_level_123 = FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(reg);
+	sc->hs_iref_cap = FUSE_XUSB_CALIB_HS_IREF_CAP(reg);
+	sc->hs_squelch_level = FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(reg);
+	sc->hs_term_range_adj = FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(reg);
+}
+
+/* -------------------------------------------------------------------------
+ *
+ *   BUS functions
+ */
 static int
 xusbpadctl_probe(device_t dev)
 {
@@ -540,12 +1137,14 @@ xusbpadctl_detach(device_t dev)
 static int
 xusbpadctl_attach(device_t dev)
 {
-	struct xusbpadctl_softc * sc;
-	int rid, rv;
+	struct padctl_softc * sc;
+	int i, rid, rv;
+	struct padctl_port *port;
 	phandle_t node;
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
+	node = ofw_bus_get_node(dev);
 
 	rid = 0;
 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -555,7 +1154,6 @@ xusbpadctl_attach(device_t dev)
 		return (ENXIO);
 	}
 
-	node = ofw_bus_get_node(dev);
 	rv = hwreset_get_by_ofw_name(dev, 0, "padctl", &sc->rst);
 	if (rv != 0) {
 		device_printf(dev, "Cannot get 'padctl' reset: %d\n", rv);
@@ -567,11 +1165,26 @@ xusbpadctl_attach(device_t dev)
 		return (rv);
 	}
 
-	/* Register as a pinctrl device and use default configuration */
-	fdt_pinctrl_register(dev, NULL);
-	fdt_pinctrl_configure_by_name(dev, "default");
-	phy_register_provider(dev);
+	load_calibration(sc);
 
+	rv = parse_fdt(sc, node);
+	if (rv != 0) {
+		device_printf(dev, "Cannot parse fdt configuration: %d\n", rv);
+		return (rv);
+	}
+	for (i = 0; i < nitems(ports_tbl); i++) {
+		port = ports_tbl + i;
+		if (!port->enabled)
+			continue;
+		if (port->init == NULL)
+			continue;
+		rv = port->init(sc, port);
+		if (rv != 0) {
+			device_printf(dev, "Cannot init port '%s'\n",
+			    port->name);
+			return (rv);
+		}
+	}
 	return (0);
 }
 
@@ -581,17 +1194,15 @@ static device_method_t tegra_xusbpadctl_methods[] = {
 	DEVMETHOD(device_attach,        xusbpadctl_attach),
 	DEVMETHOD(device_detach,        xusbpadctl_detach),
 
-	/* fdt_pinctrl interface */
-	DEVMETHOD(fdt_pinctrl_configure, xusbpadctl_pinctrl_cfg),
-
 	/* phy interface */
 	DEVMETHOD(phy_enable,		xusbpadctl_phy_enable),
+	DEVMETHOD(phy_map,		xusbpadctl_phy_map),
 
 	DEVMETHOD_END
 };
 
 static devclass_t tegra_xusbpadctl_devclass;
 static DEFINE_CLASS_0(xusbpadctl, tegra_xusbpadctl_driver,
-    tegra_xusbpadctl_methods, sizeof(struct xusbpadctl_softc));
+    tegra_xusbpadctl_methods, sizeof(struct padctl_softc));
 EARLY_DRIVER_MODULE(tegra_xusbpadctl, simplebus, tegra_xusbpadctl_driver,
     tegra_xusbpadctl_devclass, NULL, NULL, 73);

From ccf5e68e5bb2cdabb4686d81c2d63c2f6304d0a4 Mon Sep 17 00:00:00 2001
From: Michal Meloun 
Date: Mon, 7 Nov 2016 05:37:10 +0000
Subject: [PATCH 071/127] Add NVIDIA Tegra XHCI driver and coresponding
 firmware blob.

MFC after: 3 weeks
Approved by: core@ (NVIDIA license)
---
 sys/arm/conf/TEGRA124                         |    4 +-
 sys/arm/nvidia/tegra124/files.tegra124        |   21 +-
 sys/arm/nvidia/tegra_xhci.c                   | 1160 +++++++
 .../fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts  |    4 +-
 sys/contrib/dev/nvidia/LICENCE.nvidia         |  131 +
 sys/contrib/dev/nvidia/tegra124_xusb.bin.uu   | 2996 +++++++++++++++++
 6 files changed, 4311 insertions(+), 5 deletions(-)
 create mode 100644 sys/arm/nvidia/tegra_xhci.c
 create mode 100644 sys/contrib/dev/nvidia/LICENCE.nvidia
 create mode 100644 sys/contrib/dev/nvidia/tegra124_xusb.bin.uu

diff --git a/sys/arm/conf/TEGRA124 b/sys/arm/conf/TEGRA124
index d5ebe8679eea..19a6bbbcb5b6 100644
--- a/sys/arm/conf/TEGRA124
+++ b/sys/arm/conf/TEGRA124
@@ -50,7 +50,7 @@ device		vlan			# 802.1Q VLAN support
 #device		tun			# Packet tunnel.
 device		md			# Memory "disks"
 #device		gif			# IPv6 and IPv4 tunneling
-#device		firmware		# firmware assist module
+device		firmware		# firmware assist module
 device		ether			# Ethernet support
 device		miibus			# Required for ethernet
 device		bpf			# Berkeley packet filter (required for DHCP)
@@ -86,6 +86,8 @@ device		pass			# Passthrough device (direct ATA/SCSI access)
 # USB support
 options 	USB_HOST_ALIGN=64	# Align usb buffers to cache line size.
 device		ehci			# EHCI USB interface
+device		xhci			# XHCI USB interface
+device		tegra124_xusb_fw	# Tegra XUSB firmware
 device		usb			# USB Bus (required)
 device		umass			# Disks/Mass storage - Requires scbus and da
 device		uhid			# "Human Interface Devices"
diff --git a/sys/arm/nvidia/tegra124/files.tegra124 b/sys/arm/nvidia/tegra124/files.tegra124
index 8eaa009a4150..ac662f86bf8e 100644
--- a/sys/arm/nvidia/tegra124/files.tegra124
+++ b/sys/arm/nvidia/tegra124/files.tegra124
@@ -24,6 +24,7 @@ arm/nvidia/tegra_uart.c			optional	uart
 arm/nvidia/tegra_sdhci.c		optional	sdhci
 arm/nvidia/tegra_gpio.c			optional	gpio
 arm/nvidia/tegra_ehci.c			optional	ehci
+arm/nvidia/tegra_xhci.c			optional	xhci
 arm/nvidia/tegra_ahci.c			optional	ahci
 arm/nvidia/tegra_pcie.c			optional	pci
 arm/nvidia/tegra_i2c.c			optional	iic
@@ -45,11 +46,25 @@ arm/nvidia/tegra_mc.c			standard
 #arm/nvidia/drm2/tegra_fb.c		optional	drm2
 #arm/nvidia/drm2/tegra_bo.c		optional	drm2
 #
-# Optional devices.
+# Firmware
 #
-
+tegra124_xusb_fw.c			optional tegra124_xusb_fw	\
+	dependency	"$S/arm/nvidia/tegra124/files.tegra124"		\
+	compile-with	"${AWK} -f $S/tools/fw_stub.awk tegra124_xusb.fw:tegra124_xusb_fw -mtegra124_xusb_fw -c${.TARGET}" \
+	no-implicit-rule before-depend local				\
+	clean		"tegra124_xusb_fw.c"
+tegra124_xusb.fwo			optional tegra124_xusb_fw	\
+	dependency	"tegra124_xusb.fw"				\
+	compile-with	"${NORMAL_FWO}"					\
+	no-implicit-rule						\
+	clean		"tegra124_xusb.fwo"
+tegra124_xusb.fw			optional tegra124_xusb_fw	\
+	dependency	"$S/contrib/dev/nvidia/tegra124_xusb.bin.uu"	\
+	compile-with	"${NORMAL_FW}"					\
+	no-obj no-implicit-rule						\
+	clean		"tegra124_xusb.fw"
 #
-# Temporary/ to be moved stuff
+# Temporary/to be moved stuff
 #
 arm/nvidia/as3722.c			optional	iic
 arm/nvidia/as3722_regulators.c		optional	iic
diff --git a/sys/arm/nvidia/tegra_xhci.c b/sys/arm/nvidia/tegra_xhci.c
new file mode 100644
index 000000000000..a9d3ca6a3ff3
--- /dev/null
+++ b/sys/arm/nvidia/tegra_xhci.c
@@ -0,0 +1,1160 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+/*
+ * XHCI driver for Tegra SoCs.
+ */
+#include "opt_bus.h"
+#include "opt_platform.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "usbdevs.h"
+
+/* FPCI address space */
+#define	T_XUSB_CFG_0				0x000
+#define	T_XUSB_CFG_1				0x004
+#define	 CFG_1_BUS_MASTER				(1 << 2)
+#define	 CFG_1_MEMORY_SPACE				(1 << 1)
+#define	 CFG_1_IO_SPACE					(1 << 0)
+
+#define	T_XUSB_CFG_2				0x008
+#define	T_XUSB_CFG_3				0x00C
+#define	T_XUSB_CFG_4				0x010
+#define	 CFG_4_BASE_ADDRESS(x)				(((x) & 0x1FFFF) << 15)
+
+#define	T_XUSB_CFG_5				0x014
+#define	T_XUSB_CFG_ARU_MAILBOX_CMD		0x0E4
+#define  ARU_MAILBOX_CMD_INT_EN				(1U << 31)
+#define  ARU_MAILBOX_CMD_DEST_XHCI			(1  << 30)
+#define  ARU_MAILBOX_CMD_DEST_SMI			(1  << 29)
+#define  ARU_MAILBOX_CMD_DEST_PME			(1  << 28)
+#define  ARU_MAILBOX_CMD_DEST_FALC			(1  << 27)
+
+#define	T_XUSB_CFG_ARU_MAILBOX_DATA_IN		0x0E8
+#define	 ARU_MAILBOX_DATA_IN_DATA(x)			(((x) & 0xFFFFFF) <<  0)
+#define	 ARU_MAILBOX_DATA_IN_TYPE(x)			(((x) & 0x0000FF) << 24)
+
+#define	T_XUSB_CFG_ARU_MAILBOX_DATA_OUT		0x0EC
+#define	 ARU_MAILBOX_DATA_OUT_DATA(x)			(((x) >>  0) & 0xFFFFFF)
+#define	 ARU_MAILBOX_DATA_OUT_TYPE(x)			(((x) >> 24) & 0x0000FF)
+
+#define	T_XUSB_CFG_ARU_MAILBOX_OWNER		0x0F0
+#define	 ARU_MAILBOX_OWNER_SW				2
+#define	 ARU_MAILBOX_OWNER_FW				1
+#define	 ARU_MAILBOX_OWNER_NONE				0
+
+#define	XUSB_CFG_ARU_C11_CSBRANGE		0x41C	/* ! UNDOCUMENTED ! */
+#define	 ARU_C11_CSBRANGE_PAGE(x)			((x) >> 9)
+#define	 ARU_C11_CSBRANGE_ADDR(x)			(0x800 + ((x) & 0x1FF))
+#define	XUSB_CFG_ARU_SMI_INTR			0x428	/* ! UNDOCUMENTED ! */
+#define  ARU_SMI_INTR_EN				(1 << 3)
+#define  ARU_SMI_INTR_FW_HANG				(1 << 1)
+#define	XUSB_CFG_ARU_RST			0x42C	/* ! UNDOCUMENTED ! */
+#define	 ARU_RST_RESET					(1 << 0)
+
+#define	XUSB_HOST_CONFIGURATION			0x180
+#define	 CONFIGURATION_CLKEN_OVERRIDE			(1U<< 31)
+#define	 CONFIGURATION_PW_NO_DEVSEL_ERR_CYA		(1 << 19)
+#define	 CONFIGURATION_INITIATOR_READ_IDLE		(1 << 18)
+#define	 CONFIGURATION_INITIATOR_WRITE_IDLE		(1 << 17)
+#define	 CONFIGURATION_WDATA_LEAD_CYA			(1 << 15)
+#define	 CONFIGURATION_WR_INTRLV_CYA			(1 << 14)
+#define	 CONFIGURATION_TARGET_READ_IDLE			(1 << 11)
+#define	 CONFIGURATION_TARGET_WRITE_IDLE		(1 << 10)
+#define	 CONFIGURATION_MSI_VEC_EMPTY			(1 <<  9)
+#define	 CONFIGURATION_UFPCI_MSIAW			(1 <<  7)
+#define	 CONFIGURATION_UFPCI_PWPASSPW			(1 <<  6)
+#define	 CONFIGURATION_UFPCI_PASSPW			(1 <<  5)
+#define	 CONFIGURATION_UFPCI_PWPASSNPW			(1 <<  4)
+#define	 CONFIGURATION_DFPCI_PWPASSNPW			(1 <<  3)
+#define	 CONFIGURATION_DFPCI_RSPPASSPW			(1 <<  2)
+#define	 CONFIGURATION_DFPCI_PASSPW			(1 <<  1)
+#define	 CONFIGURATION_EN_FPCI				(1 <<  0)
+
+/* IPFS address space */
+#define	XUSB_HOST_FPCI_ERROR_MASKS		0x184
+#define	 FPCI_ERROR_MASTER_ABORT			(1 <<  2)
+#define	 FPCI_ERRORI_DATA_ERROR				(1 <<  1)
+#define	 FPCI_ERROR_TARGET_ABORT			(1 <<  0)
+
+#define	XUSB_HOST_INTR_MASK			0x188
+#define	 INTR_IP_INT_MASK				(1 << 16)
+#define	 INTR_MSI_MASK					(1 <<  8)
+#define	 INTR_INT_MASK					(1 <<  0)
+
+#define	XUSB_HOST_CLKGATE_HYSTERESIS		0x1BC
+
+ /* CSB Falcon CPU */
+#define	XUSB_FALCON_CPUCTL			0x100
+#define	 CPUCTL_STOPPED					(1 << 5)
+#define	 CPUCTL_HALTED					(1 << 4)
+#define	 CPUCTL_HRESET					(1 << 3)
+#define	 CPUCTL_SRESET					(1 << 2)
+#define	 CPUCTL_STARTCPU				(1 << 1)
+#define	 CPUCTL_IINVAL					(1 << 0)
+
+#define	XUSB_FALCON_BOOTVEC			0x104
+#define	XUSB_FALCON_DMACTL			0x10C
+#define	XUSB_FALCON_IMFILLRNG1			0x154
+#define	 IMFILLRNG1_TAG_HI(x)				(((x) & 0xFFF) << 16)
+#define	 IMFILLRNG1_TAG_LO(x)				(((x) & 0xFFF) <<  0)
+#define	XUSB_FALCON_IMFILLCTL			0x158
+
+/* CSB mempool */
+#define	XUSB_CSB_MEMPOOL_APMAP			0x10181C
+#define	 APMAP_BOOTPATH					(1U << 31)
+
+#define	XUSB_CSB_MEMPOOL_ILOAD_ATTR		0x101A00
+#define	XUSB_CSB_MEMPOOL_ILOAD_BASE_LO		0x101A04
+#define	XUSB_CSB_MEMPOOL_ILOAD_BASE_HI		0x101A08
+#define	XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE		0x101A10
+#define	 L2IMEMOP_SIZE_OFFSET(x)			(((x) & 0x3FF) <<  8)
+#define	 L2IMEMOP_SIZE_SIZE(x)				(((x) & 0x0FF) << 24)
+
+#define	XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG		0x101A14
+#define	 L2IMEMOP_INVALIDATE_ALL			(0x40 << 24)
+#define	 L2IMEMOP_LOAD_LOCKED_RESULT			(0x11 << 24)
+
+#define	XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT        0x101A18
+#define	 L2IMEMOP_RESULT_VLD       (1U << 31)
+
+#define XUSB_CSB_IMEM_BLOCK_SIZE	256
+
+#define	TEGRA_XHCI_SS_HIGH_SPEED	120000000
+#define	TEGRA_XHCI_SS_LOW_SPEED		 12000000
+
+/* MBOX commands. */
+#define	MBOX_CMD_MSG_ENABLED			 1
+#define	MBOX_CMD_INC_FALC_CLOCK			 2
+#define	MBOX_CMD_DEC_FALC_CLOCK			 3
+#define	MBOX_CMD_INC_SSPI_CLOCK			 4
+#define	MBOX_CMD_DEC_SSPI_CLOCK			 5
+#define	MBOX_CMD_SET_BW				 6
+#define	MBOX_CMD_SET_SS_PWR_GATING		 7
+#define	MBOX_CMD_SET_SS_PWR_UNGATING		 8
+#define	MBOX_CMD_SAVE_DFE_CTLE_CTX		 9
+#define	MBOX_CMD_AIRPLANE_MODE_ENABLED		10
+#define	MBOX_CMD_AIRPLANE_MODE_DISABLED		11
+#define	MBOX_CMD_START_HSIC_IDLE		12
+#define	MBOX_CMD_STOP_HSIC_IDLE			13
+#define	MBOX_CMD_DBC_WAKE_STACK			14
+#define	MBOX_CMD_HSIC_PRETEND_CONNECT		15
+#define	MBOX_CMD_RESET_SSPI			16
+#define	MBOX_CMD_DISABLE_SS_LFPS_DETECTION	17
+#define	MBOX_CMD_ENABLE_SS_LFPS_DETECTION	18
+
+/* MBOX responses. */
+#define	MBOX_CMD_ACK				(0x80 + 0)
+#define	MBOX_CMD_NAK				(0x80 + 1)
+
+
+#define	IPFS_WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res_ipfs, (_r), (_v))
+#define	IPFS_RD4(_sc, _r)	bus_read_4((_sc)->mem_res_ipfs, (_r))
+#define	FPCI_WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res_fpci, (_r), (_v))
+#define	FPCI_RD4(_sc, _r)	bus_read_4((_sc)->mem_res_fpci, (_r))
+
+#define	LOCK(_sc)		mtx_lock(&(_sc)->mtx)
+#define	UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
+#define	SLEEP(_sc, timeout)						\
+    mtx_sleep(sc, &sc->mtx, 0, "tegra_xhci", timeout);
+#define	LOCK_INIT(_sc)							\
+    mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_xhci", MTX_DEF)
+#define	LOCK_DESTROY(_sc)	mtx_destroy(&_sc->mtx)
+#define	ASSERT_LOCKED(_sc)	mtx_assert(&_sc->mtx, MA_OWNED)
+#define	ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->mtx, MA_NOTOWNED)
+
+struct tegra_xusb_fw_hdr {
+	uint32_t	boot_loadaddr_in_imem;
+	uint32_t	boot_codedfi_offset;
+	uint32_t	boot_codetag;
+	uint32_t	boot_codesize;
+
+	uint32_t	phys_memaddr;
+	uint16_t	reqphys_memsize;
+	uint16_t	alloc_phys_memsize;
+
+	uint32_t	rodata_img_offset;
+	uint32_t	rodata_section_start;
+	uint32_t	rodata_section_end;
+	uint32_t	main_fnaddr;
+
+	uint32_t	fwimg_cksum;
+	uint32_t	fwimg_created_time;
+
+	uint32_t	imem_resident_start;
+	uint32_t	imem_resident_end;
+	uint32_t	idirect_start;
+	uint32_t	idirect_end;
+	uint32_t	l2_imem_start;
+	uint32_t	l2_imem_end;
+	uint32_t	version_id;
+	uint8_t		init_ddirect;
+	uint8_t		reserved[3];
+	uint32_t	phys_addr_log_buffer;
+	uint32_t	total_log_entries;
+	uint32_t	dequeue_ptr;
+	uint32_t	dummy[2];
+	uint32_t	fwimg_len;
+	uint8_t		magic[8];
+	uint32_t	ss_low_power_entry_timeout;
+	uint8_t		num_hsic_port;
+	uint8_t		ss_portmap;
+	uint8_t		build;
+	uint8_t		padding[137]; /* Pad to 256 bytes */
+};
+
+/* Compatible devices. */
+static struct ofw_compat_data compat_data[] = {
+	{"nvidia,tegra124-xusb",	1},
+	{NULL,		 		0}
+};
+
+struct tegra_xhci_softc {
+	struct xhci_softc 	xhci_softc;
+	device_t		dev;
+	struct mtx		mtx;
+	struct resource		*mem_res_fpci;
+	struct resource		*mem_res_ipfs;
+	struct resource		*irq_res_mbox;
+	void			*irq_hdl_mbox;
+
+	clk_t			clk_xusb_host;
+	clk_t			clk_xusb_gate;
+	clk_t			clk_xusb_falcon_src;
+	clk_t			clk_xusb_ss;
+	clk_t			clk_xusb_hs_src;
+	clk_t			clk_xusb_fs_src;
+	hwreset_t		hwreset_xusb_host;
+	hwreset_t		hwreset_xusb_ss;
+	regulator_t		supply_avddio_pex;
+	regulator_t		supply_dvddio_pex;
+	regulator_t		supply_avdd_usb;
+	regulator_t		supply_avdd_pll_utmip;
+	regulator_t		supply_avdd_pll_erefe;
+	regulator_t		supply_avdd_usb_ss_pll;
+	regulator_t		supply_hvdd_usb_ss;
+	regulator_t		supply_hvdd_usb_ss_pll_e;
+	phy_t 			phy_usb2_0;
+	phy_t 			phy_usb2_1;
+	phy_t 			phy_usb2_2;
+	phy_t 			phy_usb3_0;
+
+	struct intr_config_hook	irq_hook;
+	bool			xhci_inited;
+	char			*fw_name;
+	vm_offset_t		fw_vaddr;
+	vm_size_t		fw_size;
+};
+
+static uint32_t
+CSB_RD4(struct tegra_xhci_softc *sc, uint32_t addr)
+{
+
+	FPCI_WR4(sc, XUSB_CFG_ARU_C11_CSBRANGE, ARU_C11_CSBRANGE_PAGE(addr));
+	return (FPCI_RD4(sc, ARU_C11_CSBRANGE_ADDR(addr)));
+}
+
+static void
+CSB_WR4(struct tegra_xhci_softc *sc, uint32_t addr, uint32_t val)
+{
+
+	FPCI_WR4(sc, XUSB_CFG_ARU_C11_CSBRANGE, ARU_C11_CSBRANGE_PAGE(addr));
+	FPCI_WR4(sc, ARU_C11_CSBRANGE_ADDR(addr), val);
+}
+
+static int
+get_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node)
+{
+	int rv;
+
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "avddio-pex-supply",
+	    &sc->supply_avddio_pex);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'avddio-pex' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "dvddio-pex-supply",
+	    &sc->supply_dvddio_pex);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'dvddio-pex' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-usb-supply",
+	    &sc->supply_avdd_usb);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'avdd-usb' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-utmip-supply",
+	    &sc->supply_avdd_pll_utmip);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'avdd-pll-utmip' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-erefe-supply",
+	    &sc->supply_avdd_pll_erefe);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'avdd-pll-erefe' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-usb-ss-pll-supply",
+	    &sc->supply_avdd_usb_ss_pll);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'avdd-usb-ss-pll' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-usb-ss-supply",
+	    &sc->supply_hvdd_usb_ss);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'hvdd-usb-ss' regulator\n");
+		return (ENXIO);
+	}
+	rv = regulator_get_by_ofw_property(sc->dev, 0,
+	    "hvdd-usb-ss-pll-e-supply", &sc->supply_hvdd_usb_ss_pll_e);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot get 'hvdd-usb-ss-pll-e' regulator\n");
+		return (ENXIO);
+	}
+
+	rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_host",
+	    &sc->hwreset_xusb_host);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_host' reset\n");
+		return (ENXIO);
+	}
+	rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_ss",
+	    &sc->hwreset_xusb_ss);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_ss' reset\n");
+		return (ENXIO);
+	}
+
+	rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-0", &sc->phy_usb2_0);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'usb2-0' phy\n");
+		return (ENXIO);
+	}
+	rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-1", &sc->phy_usb2_1);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'usb2-1' phy\n");
+		return (ENXIO);
+	}
+	rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-2", &sc->phy_usb2_2);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'usb2-2' phy\n");
+		return (ENXIO);
+	}
+	rv = phy_get_by_ofw_name(sc->dev, 0, "usb3-0", &sc->phy_usb3_0);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'usb3-0' phy\n");
+		return (ENXIO);
+	}
+
+	rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_host",
+	    &sc->clk_xusb_host);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_host' clock\n");
+		return (ENXIO);
+	}
+	rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_falcon_src",
+	    &sc->clk_xusb_falcon_src);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_falcon_src' clock\n");
+		return (ENXIO);
+	}
+	rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_ss",
+	    &sc->clk_xusb_ss);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_ss' clock\n");
+		return (ENXIO);
+	}
+	rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_hs_src",
+	    &sc->clk_xusb_hs_src);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_hs_src' clock\n");
+		return (ENXIO);
+	}
+	rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_fs_src",
+	    &sc->clk_xusb_fs_src);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_fs_src' clock\n");
+		return (ENXIO);
+	}
+	rv = clk_get_by_ofw_index_prop(sc->dev, 0, "freebsd,clock-xusb-gate", 0,
+	    &sc->clk_xusb_gate);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot get 'xusb_gate' clock\n");
+		return (ENXIO);
+	}
+	return (0);
+}
+
+static int
+enable_fdt_resources(struct tegra_xhci_softc *sc)
+{
+	int rv;
+
+	rv = hwreset_assert(sc->hwreset_xusb_host);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot reset 'xusb_host' reset\n");
+		return (rv);
+	}
+	rv = hwreset_assert(sc->hwreset_xusb_ss);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot reset 'xusb_ss' reset\n");
+		return (rv);
+	}
+
+	rv = regulator_enable(sc->supply_avddio_pex);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'avddio_pex' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_dvddio_pex);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'dvddio_pex' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_avdd_usb);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'avdd_usb' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_avdd_pll_utmip);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'avdd_pll_utmip-5v' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_avdd_pll_erefe);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'avdd_pll_erefe' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_avdd_usb_ss_pll);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'avdd_usb_ss_pll' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_hvdd_usb_ss);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'hvdd_usb_ss' regulator\n");
+		return (rv);
+	}
+	rv = regulator_enable(sc->supply_hvdd_usb_ss_pll_e);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'hvdd_usb_ss_pll_e' regulator\n");
+		return (rv);
+	}
+
+	/* Power off XUSB host and XUSB SS domains. */
+	rv = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot powerdown  'xusba' domain\n");
+		return (rv);
+	}
+	rv = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot powerdown  'xusbc' domain\n");
+		return (rv);
+	}
+
+	/* Setup XUSB ss_src clock first */
+	clk_set_freq(sc->clk_xusb_ss, TEGRA_XHCI_SS_HIGH_SPEED, 0);
+	if (rv != 0)
+		return (rv);
+
+	/* The XUSB gate clock must be enabled before XUSBA can be powered. */
+	rv = clk_enable(sc->clk_xusb_gate);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'xusb_gate' clock\n");
+		return (rv);
+	}
+
+	/* Power on XUSB host and XUSB SS domains. */
+	rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC,
+	    sc->clk_xusb_host, sc->hwreset_xusb_host);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot powerup 'xusbc' domain\n");
+		return (rv);
+	}
+	rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBA,
+	    sc->clk_xusb_ss, sc->hwreset_xusb_ss);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot powerup 'xusba' domain\n");
+		return (rv);
+	}
+
+	/* Enable rest of clocks */
+	rv = clk_enable(sc->clk_xusb_falcon_src);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'xusb_falcon_src' clock\n");
+		return (rv);
+	}
+	rv = clk_enable(sc->clk_xusb_fs_src);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'xusb_fs_src' clock\n");
+		return (rv);
+	}
+	rv = clk_enable(sc->clk_xusb_hs_src);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Cannot enable 'xusb_hs_src' clock\n");
+		return (rv);
+	}
+
+	rv = phy_enable(sc->dev, sc->phy_usb2_0);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot enable USB2_0 phy\n");
+		return (rv);
+	}
+	rv = phy_enable(sc->dev, sc->phy_usb2_1);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot enable USB2_1 phy\n");
+		return (rv);
+	}
+	rv = phy_enable(sc->dev, sc->phy_usb2_2);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot enable USB2_2 phy\n");
+		return (rv);
+	}
+	rv = phy_enable(sc->dev, sc->phy_usb3_0);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot enable USB3_0 phy\n");
+		return (rv);
+	}
+
+	return (0);
+}
+
+/* Respond by ACK/NAK back to FW */
+static void
+mbox_send_ack(struct tegra_xhci_softc *sc, uint32_t cmd, uint32_t data)
+{
+	uint32_t reg;
+
+	reg = ARU_MAILBOX_DATA_IN_TYPE(cmd) | ARU_MAILBOX_DATA_IN_DATA(data);
+	FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_IN, reg);
+
+	reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD);
+	reg |= ARU_MAILBOX_CMD_DEST_FALC | ARU_MAILBOX_CMD_INT_EN;
+	FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg);
+}
+
+/* Sent command to FW */
+static int
+mbox_send_cmd(struct tegra_xhci_softc *sc, uint32_t cmd, uint32_t data)
+{
+	uint32_t reg;
+	int i;
+
+	reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER);
+	if (reg != ARU_MAILBOX_OWNER_NONE) {
+		device_printf(sc->dev,
+		    "CPU mailbox is busy: 0x%08X\n", reg);
+		return (EBUSY);
+	}
+	/* XXX Is this right? Retry loop? Wait before send? */
+	FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER, ARU_MAILBOX_OWNER_SW);
+	reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER);
+	if (reg != ARU_MAILBOX_OWNER_SW) {
+		device_printf(sc->dev,
+		    "Cannot acquire CPU mailbox: 0x%08X\n", reg);
+		return (EBUSY);
+	}
+	reg = ARU_MAILBOX_DATA_IN_TYPE(cmd) | ARU_MAILBOX_DATA_IN_DATA(data);
+	FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_IN, reg);
+
+	reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD);
+	reg |= ARU_MAILBOX_CMD_DEST_FALC | ARU_MAILBOX_CMD_INT_EN;
+	FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg);
+
+	for (i = 250; i > 0; i--) {
+		reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER);
+		if (reg == ARU_MAILBOX_OWNER_NONE)
+			break;
+		DELAY(100);
+	}
+	if (i <= 0) {
+		device_printf(sc->dev,
+		    "Command response timeout: 0x%08X\n", reg);
+		return (ETIMEDOUT);
+	}
+
+	return(0);
+}
+
+static void
+process_msg(struct tegra_xhci_softc *sc, uint32_t req_cmd, uint32_t req_data,
+    uint32_t *resp_cmd, uint32_t *resp_data)
+{
+	uint64_t freq;
+	int rv;
+
+	/* In most cases, data are echoed back. */
+	*resp_data = req_data;
+	switch (req_cmd) {
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+		rv = clk_set_freq(sc->clk_xusb_falcon_src, req_data * 1000ULL,
+		    0);
+		if (rv == 0) {
+			rv = clk_get_freq(sc->clk_xusb_falcon_src, &freq);
+			*resp_data = (uint32_t)(freq / 1000);
+		}
+		*resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK;
+		break;
+
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+		rv = clk_set_freq(sc->clk_xusb_ss, req_data * 1000ULL,
+		    0);
+		if (rv == 0) {
+			rv = clk_get_freq(sc->clk_xusb_ss, &freq);
+			*resp_data = (uint32_t)(freq / 1000);
+		}
+		*resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK;
+		break;
+
+	case MBOX_CMD_SET_BW:
+		/* No respense is expected. */
+		*resp_cmd = 0;
+		break;
+
+	case MBOX_CMD_SET_SS_PWR_GATING:
+	case MBOX_CMD_SET_SS_PWR_UNGATING:
+		*resp_cmd = MBOX_CMD_NAK;
+		break;
+
+	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
+		/* Not implemented yet. */
+		*resp_cmd = MBOX_CMD_ACK;
+		break;
+
+
+	case MBOX_CMD_START_HSIC_IDLE:
+	case MBOX_CMD_STOP_HSIC_IDLE:
+		/* Not implemented yet. */
+		*resp_cmd = MBOX_CMD_NAK;
+		break;
+
+	case MBOX_CMD_DISABLE_SS_LFPS_DETECTION:
+	case MBOX_CMD_ENABLE_SS_LFPS_DETECTION:
+		/* Not implemented yet. */
+		*resp_cmd = MBOX_CMD_NAK;
+		break;
+
+	case MBOX_CMD_AIRPLANE_MODE_ENABLED:
+	case MBOX_CMD_AIRPLANE_MODE_DISABLED:
+	case MBOX_CMD_DBC_WAKE_STACK:
+	case MBOX_CMD_HSIC_PRETEND_CONNECT:
+	case MBOX_CMD_RESET_SSPI:
+		device_printf(sc->dev,
+		    "Received unused/unexpected command: %u\n", req_cmd);
+		*resp_cmd = 0;
+		break;
+
+	default:
+		device_printf(sc->dev,
+		    "Received unknown command: %u\n", req_cmd);
+	}
+}
+
+static void
+intr_mbox(void *arg)
+{
+	struct tegra_xhci_softc *sc;
+	uint32_t reg, msg, resp_cmd, resp_data;
+
+	sc = (struct tegra_xhci_softc *)arg;
+
+	/* Clear interrupt first */
+	reg = FPCI_RD4(sc, XUSB_CFG_ARU_SMI_INTR);
+	FPCI_WR4(sc, XUSB_CFG_ARU_SMI_INTR, reg);
+	if (reg & ARU_SMI_INTR_FW_HANG) {
+		device_printf(sc->dev,
+		    "XUSB CPU firmware hang!!! CPUCTL: 0x%08X\n",
+		    CSB_RD4(sc, XUSB_FALCON_CPUCTL));
+	}
+
+	msg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_OUT);
+	resp_cmd = 0;
+	process_msg(sc, ARU_MAILBOX_DATA_OUT_TYPE(msg),
+	   ARU_MAILBOX_DATA_OUT_DATA(msg), &resp_cmd, &resp_data);
+	if (resp_cmd != 0)
+		mbox_send_ack(sc, resp_cmd, resp_data);
+	else
+		FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER,
+		    ARU_MAILBOX_OWNER_NONE);
+
+	reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD);
+	reg &= ~ARU_MAILBOX_CMD_DEST_SMI;
+	FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg);
+
+}
+
+static int
+load_fw(struct tegra_xhci_softc *sc)
+{
+	const struct firmware *fw;
+	const struct tegra_xusb_fw_hdr *fw_hdr;
+	vm_paddr_t fw_paddr, fw_base;
+	vm_offset_t fw_vaddr;
+	vm_size_t fw_size;
+	uint32_t code_tags, code_size;
+	struct clocktime fw_clock;
+	struct timespec	fw_timespec;
+	int i;
+
+	/* Reset ARU */
+	FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET);
+	DELAY(3000);
+
+	/* Check if FALCON already runs */
+	if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) {
+		device_printf(sc->dev,
+		    "XUSB CPU is already loaded, CPUCTL: 0x%08X\n",
+			 CSB_RD4(sc, XUSB_FALCON_CPUCTL));
+		return (0);
+	}
+
+	fw = firmware_get(sc->fw_name);
+	if (fw == NULL) {
+		device_printf(sc->dev, "Cannot read xusb firmware\n");
+		return (ENOENT);
+	}
+
+	/* Allocate uncached memory and copy firmware into. */
+	fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data;
+	fw_size = fw_hdr->fwimg_len;
+
+	fw_vaddr = kmem_alloc_contig(kernel_arena, fw_size,
+	    M_WAITOK, 0, -1UL, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
+	fw_paddr = vtophys(fw_vaddr);
+	fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr;
+	memcpy((void *)fw_vaddr, fw->data, fw_size);
+
+	firmware_put(fw, FIRMWARE_UNLOAD);
+	sc->fw_vaddr = fw_vaddr;
+	sc->fw_size = fw_size;
+
+	/* Setup firmware physical address and size. */
+	fw_base = fw_paddr + sizeof(*fw_hdr);
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size);
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF);
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32);
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH);
+
+	/* Invalidate full L2IMEM context. */
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG,
+	    L2IMEMOP_INVALIDATE_ALL);
+
+	/* Program load of L2IMEM by boot code. */
+	code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE);
+	code_size = howmany(fw_hdr->boot_codesize, XUSB_CSB_IMEM_BLOCK_SIZE);
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE,
+	    L2IMEMOP_SIZE_OFFSET(code_tags) |
+	    L2IMEMOP_SIZE_SIZE(code_size));
+
+	/* Execute L2IMEM boot code fetch. */
+	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG,
+	    L2IMEMOP_LOAD_LOCKED_RESULT);
+
+	/* Program FALCON auto-fill range and block count */
+	CSB_WR4(sc, XUSB_FALCON_IMFILLCTL, code_size);
+	CSB_WR4(sc, XUSB_FALCON_IMFILLRNG1,
+	    IMFILLRNG1_TAG_LO(code_tags) |
+	    IMFILLRNG1_TAG_HI(code_tags + code_size));
+
+	CSB_WR4(sc, XUSB_FALCON_DMACTL, 0);
+	/* Wait for CPU */
+	for (i = 500; i > 0; i--) {
+		if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT) &
+		     L2IMEMOP_RESULT_VLD)
+			break;
+		DELAY(100);
+	}
+	if (i <= 0) {
+		device_printf(sc->dev, "Timedout while wating for DMA, "
+		    "state: 0x%08X\n",
+		    CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT));
+		return (ETIMEDOUT);
+	}
+
+	/* Boot FALCON cpu */
+	CSB_WR4(sc, XUSB_FALCON_BOOTVEC, fw_hdr->boot_codetag);
+	CSB_WR4(sc, XUSB_FALCON_CPUCTL, CPUCTL_STARTCPU);
+
+	/* Wait for CPU */
+	for (i = 50; i > 0; i--) {
+		if (CSB_RD4(sc, XUSB_FALCON_CPUCTL) == CPUCTL_STOPPED)
+			break;
+		DELAY(100);
+	}
+	if (i <= 0) {
+		device_printf(sc->dev, "Timedout while wating for FALCON cpu, "
+		    "state: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL));
+		return (ETIMEDOUT);
+	}
+
+	fw_timespec.tv_sec = fw_hdr->fwimg_created_time;
+	fw_timespec.tv_nsec = 0;
+	clock_ts_to_ct(&fw_timespec, &fw_clock);
+	device_printf(sc->dev,
+	    " Falcon firmware version: %02X.%02X.%04X,"
+	    " (%d/%d/%d %d:%02d:%02d UTC)\n",
+	    (fw_hdr->version_id >> 24) & 0xFF,(fw_hdr->version_id >> 15) & 0xFF,
+	    fw_hdr->version_id & 0xFFFF,
+	    fw_clock.day, fw_clock.mon, fw_clock.year,
+	    fw_clock.hour, fw_clock.min, fw_clock.sec);
+
+	return (0);
+}
+
+static int
+init_hw(struct tegra_xhci_softc *sc)
+{
+	int rv;
+	uint32_t reg;
+	rman_res_t base_addr;
+
+	base_addr = rman_get_start(sc->xhci_softc.sc_io_res);
+
+	/* Enable FPCI access */
+	reg = IPFS_RD4(sc, XUSB_HOST_CONFIGURATION);
+	reg |= CONFIGURATION_EN_FPCI;
+	IPFS_WR4(sc, XUSB_HOST_CONFIGURATION, reg);
+	IPFS_RD4(sc, XUSB_HOST_CONFIGURATION);
+
+
+	/* Program bar for XHCI base address */
+	reg = FPCI_RD4(sc, T_XUSB_CFG_4);
+	reg &= ~CFG_4_BASE_ADDRESS(~0);
+	reg |= CFG_4_BASE_ADDRESS((uint32_t)base_addr >> 15);
+	FPCI_WR4(sc, T_XUSB_CFG_4, reg);
+	FPCI_WR4(sc, T_XUSB_CFG_5, (uint32_t)((uint64_t)(base_addr) >> 32));
+
+	/* Enable bus master */
+	reg = FPCI_RD4(sc, T_XUSB_CFG_1);
+	reg |= CFG_1_IO_SPACE;
+	reg |= CFG_1_MEMORY_SPACE;
+	reg |= CFG_1_BUS_MASTER;
+	FPCI_WR4(sc, T_XUSB_CFG_1, reg);
+
+	/* Enable Interrupts */
+	reg = IPFS_RD4(sc, XUSB_HOST_INTR_MASK);
+	reg |= INTR_IP_INT_MASK;
+	IPFS_WR4(sc, XUSB_HOST_INTR_MASK, reg);
+
+	/* Set hysteresis */
+	IPFS_WR4(sc, XUSB_HOST_CLKGATE_HYSTERESIS, 128);
+
+	rv = load_fw(sc);
+	if (rv != 0)
+		return rv;
+	return (0);
+}
+
+static int
+tegra_xhci_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+		device_set_desc(dev, "Nvidia Tegra XHCI controller");
+		return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+static int
+tegra_xhci_detach(device_t dev)
+{
+	struct tegra_xhci_softc *sc;
+	struct xhci_softc *xsc;
+
+	sc = device_get_softc(dev);
+	xsc = &sc->xhci_softc;
+
+	/* during module unload there are lots of children leftover */
+	device_delete_children(dev);
+	if (sc->xhci_inited) {
+		usb_callout_drain(&xsc->sc_callout);
+		xhci_halt_controller(xsc);
+	}
+
+	if (xsc->sc_irq_res && xsc->sc_intr_hdl) {
+		bus_teardown_intr(dev, xsc->sc_irq_res, xsc->sc_intr_hdl);
+		xsc->sc_intr_hdl = NULL;
+	}
+	if (xsc->sc_irq_res) {
+		bus_release_resource(dev, SYS_RES_IRQ,
+		    rman_get_rid(xsc->sc_irq_res), xsc->sc_irq_res);
+		xsc->sc_irq_res = NULL;
+	}
+	if (xsc->sc_io_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY,
+		    rman_get_rid(xsc->sc_io_res), xsc->sc_io_res);
+		xsc->sc_io_res = NULL;
+	}
+	if (sc->xhci_inited)
+		xhci_uninit(xsc);
+	if (sc->irq_hdl_mbox != NULL)
+		bus_teardown_intr(dev, sc->irq_res_mbox, sc->irq_hdl_mbox);
+	if (sc->fw_vaddr != 0)
+		kmem_free(kernel_arena, sc->fw_vaddr, sc->fw_size);
+	LOCK_DESTROY(sc);
+	return (0);
+}
+
+static int
+tegra_xhci_attach(device_t dev)
+{
+	struct tegra_xhci_softc *sc;
+	struct xhci_softc *xsc;
+	int rv, rid;
+	phandle_t node;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	sc->fw_name = "tegra124_xusb_fw";
+	node = ofw_bus_get_node(dev);
+	xsc = &sc->xhci_softc;
+	LOCK_INIT(sc);
+
+	rv = get_fdt_resources(sc, node);
+	if (rv != 0) {
+		rv = ENXIO;
+		goto error;
+	}
+	rv = enable_fdt_resources(sc);
+	if (rv != 0) {
+		rv = ENXIO;
+		goto error;
+	}
+
+	/* Allocate resources. */
+	rid = 0;
+	xsc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE);
+	if (xsc->sc_io_res == NULL) {
+		device_printf(dev,
+		    "Could not allocate HCD memory resources\n");
+		rv = ENXIO;
+		goto error;
+	}
+	rid = 1;
+	sc->mem_res_fpci = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE);
+	if (sc->mem_res_fpci == NULL) {
+		device_printf(dev,
+		    "Could not allocate FPCI memory resources\n");
+		rv = ENXIO;
+		goto error;
+	}
+	rid = 2;
+	sc->mem_res_ipfs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE);
+	if (sc->mem_res_ipfs == NULL) {
+		device_printf(dev,
+		    "Could not allocate IPFS memory resources\n");
+		rv = ENXIO;
+		goto error;
+	}
+
+	rid = 0;
+	xsc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_ACTIVE);
+	if (xsc->sc_irq_res == NULL) {
+		device_printf(dev, "Could not allocate HCD IRQ resources\n");
+		rv = ENXIO;
+		goto error;
+	}
+	rid = 1;
+	sc->irq_res_mbox = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_ACTIVE);
+	if (sc->irq_res_mbox == NULL) {
+		device_printf(dev, "Could not allocate MBOX IRQ resources\n");
+		rv = ENXIO;
+		goto error;
+	}
+
+	rv = init_hw(sc);
+	if (rv != 0) {
+		device_printf(dev, "Could not initialize  XUSB hardware\n");
+		goto error;
+	}
+
+	/* Wakeup and enable firmaware */
+	rv = mbox_send_cmd(sc, MBOX_CMD_MSG_ENABLED, 0);
+	if (rv != 0) {
+		device_printf(sc->dev, "Could not enable XUSB firmware\n");
+		goto error;
+	}
+
+	/* Fill data for XHCI driver. */
+	xsc->sc_bus.parent = dev;
+	xsc->sc_bus.devices = xsc->sc_devices;
+	xsc->sc_bus.devices_max = XHCI_MAX_DEVICES;
+
+	xsc->sc_io_tag = rman_get_bustag(xsc->sc_io_res);
+	xsc->sc_io_hdl = rman_get_bushandle(xsc->sc_io_res);
+	xsc->sc_io_size = rman_get_size(xsc->sc_io_res);
+	strlcpy(xsc->sc_vendor, "Nvidia", sizeof(xsc->sc_vendor));
+
+	/* Add USB bus device. */
+	xsc->sc_bus.bdev = device_add_child(sc->dev, "usbus", -1);
+	if (xsc->sc_bus.bdev == NULL) {
+		device_printf(sc->dev, "Could not add USB device\n");
+		rv = ENXIO;
+		goto error;
+	}
+	device_set_ivars(xsc->sc_bus.bdev, &xsc->sc_bus);
+	device_set_desc(xsc->sc_bus.bdev, "Nvidia USB 3.0 controller");
+
+	rv = xhci_init(xsc, sc->dev, 1);
+	if (rv != 0) {
+		device_printf(sc->dev, "USB init failed: %d\n", rv);
+		goto error;
+	}
+	sc->xhci_inited = true;
+	rv = xhci_start_controller(xsc);
+	if (rv != 0) {
+		device_printf(sc->dev,
+		    "Could not start XHCI controller: %d\n", rv);
+		goto error;
+	}
+
+	rv = bus_setup_intr(dev, sc->irq_res_mbox, INTR_TYPE_MISC | INTR_MPSAFE,
+	    NULL, intr_mbox, sc, &sc->irq_hdl_mbox);
+	if (rv != 0) {
+		device_printf(dev, "Could not setup error IRQ: %d\n",rv);
+		xsc->sc_intr_hdl = NULL;
+		goto error;
+	}
+
+	rv = bus_setup_intr(dev, xsc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+	    NULL, (driver_intr_t *)xhci_interrupt, xsc, &xsc->sc_intr_hdl);
+	if (rv != 0) {
+		device_printf(dev, "Could not setup error IRQ: %d\n",rv);
+		xsc->sc_intr_hdl = NULL;
+		goto error;
+	}
+
+	/* Probe the bus. */
+	rv = device_probe_and_attach(xsc->sc_bus.bdev);
+	if (rv != 0) {
+		device_printf(sc->dev, "Could not initialize USB: %d\n", rv);
+		goto error;
+	}
+
+	return (0);
+
+error:
+panic("XXXXX");
+	tegra_xhci_detach(dev);
+	return (rv);
+}
+
+static device_method_t xhci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, tegra_xhci_probe),
+	DEVMETHOD(device_attach, tegra_xhci_attach),
+	DEVMETHOD(device_detach, tegra_xhci_detach),
+	DEVMETHOD(device_suspend, bus_generic_suspend),
+	DEVMETHOD(device_resume, bus_generic_resume),
+	DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+	DEVMETHOD_END
+};
+
+static devclass_t xhci_devclass;
+static DEFINE_CLASS_0(xhci, xhci_driver, xhci_methods,
+    sizeof(struct tegra_xhci_softc));
+DRIVER_MODULE(tegra_xhci, simplebus, xhci_driver, xhci_devclass, NULL, NULL);
+MODULE_DEPEND(tegra_xhci, usb, 1, 1, 1);
diff --git a/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts b/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts
index 902616b7374d..1e571eedd4ce 100644
--- a/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts
+++ b/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts
@@ -42,5 +42,7 @@
 /*		reg = <0x0 0x80000000 0x0 0x80000000>; */
 		reg = <0x0 0x80000000 0x0 0x70000000>;
 	};
-
+	usb@0,70090000 {
+		freebsd,clock-xusb-gate = <&tegra_car 143>;
+	};
 };
diff --git a/sys/contrib/dev/nvidia/LICENCE.nvidia b/sys/contrib/dev/nvidia/LICENCE.nvidia
new file mode 100644
index 000000000000..b99d5a349718
--- /dev/null
+++ b/sys/contrib/dev/nvidia/LICENCE.nvidia
@@ -0,0 +1,131 @@
+           License For Customer Use of NVIDIA Software
+
+
+IMPORTANT NOTICE -- READ CAREFULLY: This License For Customer Use of
+NVIDIA Software ("LICENSE") is the agreement which governs use of
+the software of NVIDIA Corporation and its subsidiaries ("NVIDIA")
+downloadable herefrom, including computer software and associated
+printed materials ("SOFTWARE").  By downloading, installing, copying,
+or otherwise using the SOFTWARE, you agree to be bound by the terms
+of this LICENSE.  If you do not agree to the terms of this LICENSE,
+do not download the SOFTWARE.
+
+RECITALS
+
+Use of NVIDIA's products requires three elements: the SOFTWARE, the
+hardware, and a personal computer. The SOFTWARE is protected by copyright
+laws and international copyright treaties, as well as other intellectual
+property laws and treaties.  The SOFTWARE may be protected by various
+patents, and is not sold, and instead is only licensed for use, strictly
+in accordance with this document.  The hardware is protected by various
+patents, and is sold, but this agreement does not cover that sale, since
+it may not necessarily be sold as a package with the SOFTWARE.  This
+agreement sets forth the terms and conditions of the SOFTWARE LICENSE only.
+
+1.  DEFINITIONS
+
+1.1  Customer.  Customer means the entity or individual that
+downloads or otherwise obtains the SOFTWARE.
+
+2.  GRANT OF LICENSE
+
+2.1  Rights and Limitations of Grant.  NVIDIA hereby grants Customer
+the following non-exclusive, non-transferable right to use the
+SOFTWARE, with the following limitations:
+
+2.1.1  Rights.  Customer may install and use multiple copies of the
+SOFTWARE on a shared computer or concurrently on different computers,
+and make multiple back-up copies of the SOFTWARE, solely for Customer's
+use within Customer's Enterprise. "Enterprise" shall mean individual use
+by Customer or any legal entity (such as a corporation or university)
+and the subsidiaries it owns by more than fifty percent (50%).
+
+2.1.2  Open Source Exception.  Notwithstanding the foregoing terms
+of Section 2.1.1, SOFTWARE may be copied and redistributed solely for
+use on operating systems distributed under the terms of an OSI-approved
+open source license as listed by the Open Source Initiative at
+http://opensource.org, provided that the binary files thereof are not
+modified, and Customer provides a copy of this license with the SOFTWARE.
+
+2.1.3  Limitations.
+
+No Reverse Engineering.  Customer may not reverse engineer,
+decompile, or disassemble the SOFTWARE, nor attempt in any other
+manner to obtain the source code.
+
+Usage. SOFTWARE is licensed only for use with microprocessor(s) which have
+been (i) designed by NVIDIA and (ii) either (a) sold by or (b) licensed by
+NVIDIA. Customer shall not use SOFTWARE in conjunction with, nor cause
+SOFTWARE to be executed by, any other microprocessor.
+
+No Translation. Customer shall not translate SOFTWARE, nor cause or permit
+SOFTWARE to be translated, from the architecture or language in which it is
+originally provided by NVIDIA, into any other architecture or language.
+
+No Rental.  Customer may not rent or lease the SOFTWARE to someone
+else.
+
+3.  TERMINATION
+
+This LICENSE will automatically terminate if Customer fails to
+comply with any of the terms and conditions hereof.  In such event,
+Customer must destroy all copies of the SOFTWARE and all of its
+component parts.
+
+Defensive Suspension.  If Customer commences or participates in any legal
+proceeding against NVIDIA, then NVIDIA may, in its sole discretion,
+suspend or terminate all license grants and any other rights provided
+under this LICENSE during the pendency of such legal proceedings.
+
+4.  COPYRIGHT
+
+All title and copyrights in and to the SOFTWARE (including but
+not limited to all images, photographs, animations, video, audio,
+music, text, and other information incorporated into the SOFTWARE),
+the accompanying printed materials, and any copies of the SOFTWARE,
+are owned by NVIDIA, or its suppliers.  The SOFTWARE is protected
+by copyright laws and international treaty provisions.  Accordingly,
+Customer is required to treat the SOFTWARE like any other copyrighted
+material, except as otherwise allowed pursuant to this LICENSE
+and that it may make one copy of the SOFTWARE solely for backup or
+archive purposes.
+
+5.  APPLICABLE LAW
+
+This agreement shall be deemed to have been made in, and shall be
+construed pursuant to, the laws of the State of California.
+
+6.  DISCLAIMER OF WARRANTIES AND LIMITATION ON LIABILITY
+
+6.1  No Warranties.  TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE
+LAW, THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA AND ITS SUPPLIERS
+DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT
+NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE.
+
+6.2  No Liability for Consequential Damages.  TO THE MAXIMUM
+EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL NVIDIA OR
+ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
+DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS
+OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT
+OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NVIDIA HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7.  MISCELLANEOUS
+
+The United Nations Convention on Contracts for the International
+Sale of Goods is specifically disclaimed.  If any provision of this
+LICENSE is inconsistent with, or cannot be fully enforced under,
+the law, such provision will be construed as limited to the extent
+necessary to be consistent with and fully enforceable under the law.
+This agreement is the final, complete and exclusive agreement between
+the parties relating to the subject matter hereof, and supersedes
+all prior or contemporaneous understandings and agreements relating
+to such subject matter, whether oral or written.  Customer agrees
+that it will not ship, transfer or export the SOFTWARE into any
+country, or use the SOFTWARE in any manner, prohibited by the
+United States Bureau of Export Administration or any export laws,
+restrictions or regulations.  This LICENSE may only be modified in
+writing signed by an authorized officer of NVIDIA.
+
diff --git a/sys/contrib/dev/nvidia/tegra124_xusb.bin.uu b/sys/contrib/dev/nvidia/tegra124_xusb.bin.uu
new file mode 100644
index 000000000000..3a51e793fd81
--- /dev/null
+++ b/sys/contrib/dev/nvidia/tegra124_xusb.bin.uu
@@ -0,0 +1,2996 @@
+begin 644 tegra124_xusb.bin
+M`%L````(`@``"`(```4``````````````````````````````.$``+O4``#_
+MFQ=4`&\``&#$`````0``GFX```#%```U`0(``@!&10$`````````````````
+M```````````````.`@!855-"1E<``$!"#P``_R`!`@0``(`@!0``````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````/0@<`#T($``]"#,`/0@
+M0`#T($``]"!``/0@H`#T($``]"!``/0@0`#T($``]"!``/0@0`#T($``]"!`
+M`/0@0`#YD/F@^;#YP/G0^>#Y\/Z*`?F@?A!P`/R@_J@`]#(!_/#\X/S0_,#\
+ML/R@_)#X`0#YD/F@^;#YP/G0^>#Y\/Z*`?F@?NRI`/R@_J@`]#(!_/#\X/S0
+M_,#\L/R@_)#X`0#YD/F@^;#YP/G0^>#Y\/Z*`?F@?M9W`/R@_J@`_/#\X/S0
+M_,#\L/R@_)#X`?F0^:#YL/G`^=#YX/GP_HH!^:!^M+H`_*#^J`#T,@'\\/S@
+M_-#\P/RP_*#\D/@!^/CX^/CX`+:E&+/``$+?X!D``'_Y\)408/FSI!%NV0"I
+M`0"FV?0;#M^)7```/_D^7P$`V0"G`0"FV?0;#M^)7```/_D^>@$`^`CX`+.D
+M$3S9`*D!`*;9]!L4WXE<```_^?"5!/"4]SY]`0#9`*V1P:```\FKG9'QH``#R:N=G\&0``O)JY
+M^`#9(AH``#WT/)^YV24:```\G[F]]-D4&@``O)^Y^`"8J0B5GQS'F6BVE`*S
+M]``-WS1;```^X0$`WTQ;``"\G]"_V;.0`&8/\/V?!+B>`"``IJ[T&T*8KPG'
+M^0'T"PN]E*#9/@P"`*#?F*D(O?0^(P(`IJGT&QN8J0FUZ0F8J0BUKPF/___]
+M_9\$M:D(^`"RGCXZ`@"R_9CO"?_]E,?_`;B9`"``L_``S?@`V?`9``"\FJB8
+MJ3CQE/\/]!L)O=0^A@(`F+D!Q,__Y-[__PT!M:DZF+D"M:D[M:\\M:X]O[FU
+MJ3FRVO@`^0*RT++ML+8(]`T%^`C?_`8``)+>`;SND+R>D+:4!+R?D`__-9\!
+MLZ``%K/)!(X`L\D#@P"S!`!^/DD#`-DP&0``/YG$G_^FO_0(%=DN&0``/YGP
+ME/^\GY"FN?0(7MDQ&0``WR\9```_F3__\)3_\/3_O+F2II_T"`7X"-\(:!$!
+MMI0$O)^0N)\`"`"_G+__LP``#<3)#["6`_0,7L3)#["6`_0-$,3Y#["6`_0-
+M$SZ"`P`*`3Y+`P"]I#Y+`P`*`KSND+R>D-[\!@``MI0$O)Z0-9H!V7@$``"4
+MKP2\^?`8^0'>``0``+S>T!"9`37Y`37;G#Z&`P"*__\`^P&\JI#?S`8``+R:
+MD+:4!+R?D!B9`?"4_[.:_P`JE)\$V7@$``"\^?`8^0$SD``*$ID!-?D!WP`$
+M```)_[ROH#6IG/@`V1P:``#Y(CR:Z-D?&@``/)KXLJ"RLB;O]!@%^`C9R34`
+M`#^9,Y``(MG(-0``/YDSE``7V#`$0`9"O0+^ID*H$H.FFK_0;]_@`F*DA
+M]##\_D\!H/F8J2*@^9BI(Z#YF*DDH/F8J26@^?0P!/@`^``2N00PE@'T#0`9``!_
+MW_E2WO1@``"]E+_B\?3_W_0P_*#I8-^]!+T4U10:``#4/AH``-,8&@``LR``
+M<<0I`?0+6=[\&0``O!Z0OYRSP``KWSX:``"\#Y`_F<2?`?0;&MX(&@``O!Z0
+MOYVR"K#Q``L'O>1^-+D`LP0`(;]1^
+M-+D`D``!D!$$LP`#"[8E`3Z,!@#T,`3[4=DX%``!OYFSI``+QY]$/B<'`+.D
+M`0W'GRR]I#XG!P#'GS"2J@()`;N:!/V?!/"L"_"F`?@`^1*8H`.)!_S?LJ%]
+MM/\)E+W$M:D#?@`^`,<`PY@?`[8$`S.D`!Q)!_S_^93_"96R&K49`WY:N``*
+M`3Z7!P#=X!D``'_>20?\O:3_^93QY0`0CP``(&#>_9\%_9`%M1D#^Q'9_&``
+M`/D"OYD^Q0<`E)H$V3!:``"\J:"8H`/'"17T"PM^-P<`LZ``&,<)P[.4?^'?
+MX!D``'_Y\93_[V#Y^P'Y$K*_LL&RT,2I`_0+!?@(LJNR_`H%?I5X`+RA"?L1
+M^1+9+!D``#^?\*3_LKX)![++LM&\F@(S\``JL`8!]`T%^`B4&0*S!``-WS1;
+M```^+P@`WTQ;``"\GY"_F;.0`&;'Z0+T"Q\)\/_IE+B9`"``F)\,WO____[]
+M_@2UGPP^B@@`L`8!]`T%^`BS!``-V6@:```^=`@`V70:``"\D9@*\-S____^
+M_^JD_YS$#0Q^V`<`V?`9``"\D?@)`;N0!+7Y"/L1]##X^3*RH)BJ"_0P^+*S
+M_D$!_D(!D!$2@&GX[P@"SI``&^`BS,`!(F`\+F`D,E?$8E9`;LAJR
+M"W[^N`"SH``,?C<'`#XZ"0#9Y&$``+^9LY!_&Y0)$`K_E!T8LJO_G=6RK'X+
+MN``^.@D`^`CT,`C[-0B8KPCY`K*@Q_D1]`L3B0``$/_YE;6I"+VD/GP)`'[A
+M>`"8#PC9\!D```X!LNK'_6B\G9BV]1R[[P2UG@C[`9BO!HG___V8K0K]^02U
+MKP:SL`=VL[0"&-_)-0``/_D2F0$@^7Z>4P`^SPD`L[0%*=S(-0``V^`9```_
+MSW^^/=39RC4``!+_`?#E`B"=(,]@OKVD^`#'V5C$GP+T"Q[9+!D``#^9,Y``
+M,9BI!K:5&+.0`B=^0`D`^`#PE`3T"PK9RC4``""?W\@U```_^;VD$ID!(/GX
+M`+VD^`"8KPR8K@>8K0B]E)BK"K6I";6I#MG____^_?D$B?__W[6O#/WI!(G_
+M__FUK@?]V02UK0C'N5CT"PL+`GY^"0#X`,>Y%_0+,YBI!K:5&+"6!_0-#YBI
+M!K:5&+"6"_0-&]X`!```W>`9``"_Z7_?\)4"\/4"H.E@W_@`^3+9+!D``#^9
+M,Y``=+"F`?0-!?@(MK0"LZ0`#=DT6P``/KL*`-E,6P``O+D0OQ"S``!V`_""
+M___]_P.4N)\`(`"8_@BR^ICP"96/0+"WX8"@`^``L`M?D)
+M_^*4LOJU^0A^_GD`QPD!]`O'O92@&3XV"P#>X!D``'_IW0`@``#?.QH``)C<
+M`3S[^/&5``%@Z0D!NY\$_9P%M=D!^S'Y`K*PLZ0`*MDT6P``O)N8LY``"'Z1
+M"@#9:!H``)0.`KWTO.G@V31;```^B`L`V4Q;``"\FYBSD``(?I$*`-ET&@``
+ME`X"O?2\Z>#93%L``+R?";_IW_____[]GP2@Z?L!^8+9+!D``#^9]##\LK(S
+ME``&^`CPI/^2J0:PE@'T#0GX"#[X#`#9/AH``#R2Z`L'#P&\NG*[]P3P]/\Y
+M_P#]_@0\GRFS=``HV?P9``"\DOBS]``,LBN]I#[T#``)\+*X__F4N)8`(``^
+M'@P`V10:``"\DOBS^0#C``GP"`;_^92XE@`@`+)ZLBNR87Z'`0"]1+U4O328
+M&0:R&K:5&/0+%9@9!K"6`/0>#)@9",>9%/0+-G[#`0"R&G[A>`"S1``(LA6R
+M%)@?#L49!+B9`"`"D#,!M5D."?"R%?WY!+CQ`"``/I,,`)@0#@GPLAK]"01^
+M&`H`N```(`"R`:86]!N9LT``6+A)`"`"Q9P$LW0`'=G\&0``O)PIV1P:```\
+MDRG9'QH``#[6#`#9%!H``+R<*=DB&@``/),IV24:```\DRG%R0BU60Z]E+*+
+ML)$`LBJ]U+WD?C2Y`+)ZLBM^.`L`]#`$^X$)_/VI!+.N0`0_E;D8LY`"-[.4
+M`RW9)!0``;^?N)DE%`+_N93T"PKP]00^,`T`"?O]^039)!0``:"?/D$-`+.4
+M`0;X"-D`$``!O*F@H*OX`/EBV
+M_Z;>]`@6/RFY[P"\\+#PE/^\GI"FV?0((#])Q)[_IM[T"!T_.;GO`+SPL/"4
+M_[R>D*;9]!@*$`H!?H4T`)```9`1.#]I\)3_I@GT"*G[8;BJ``P"L*8#]`P?
+MWN`9``#=``0``'_IO]_PE0+P]0%@Z:#??EZK`/@`V2`@``&_G]TD(``!O][T
+M,/A)V2`@``%/?OS_C_2@G]GH&0``H,Z@G_#5
+M"MD@`!`!(+U/@0"@GWY2X0"TD`D0``&@-Z`6H%FTD`H@(*!)/DH3`,0I`?0;
+M"3T4/OL0`,3O`<2)`?4+NP"S^0`A`=G`90``/YDSD`!VV1!B```_F3.0`![9
+M+AD``#^9W11B``"]Y-\(8!$!Q)O_/D$0`-T@6@``O]])__WE#@`$_^D$D/\!
+MV1`!$`&@GZ#?/D80`+_9O_R0[@&0_X"0W13'F1GT&Q?$R0^SE`41#P'9H6``
+M`""?/D80`*;K]`C7V:%@```_GTG^_/V)!-D@(``!H)C9Z!D``*"8V20@``&@
+MD#/T`'U^30T`"?X]%/T)!#[G$`"S\``*/10^T!``2?_\_8D$V2`@``&@F-XX
+M(``!\`4!H-"_Z=WL&0``/]_<,``0`?V;!*#IO\[P]0D@WPG[_>D$H,[9Z!D`
+M`*"83X$`V2``$`$!`:"?V20```&_F=_\80``D)D!H/D^YQ``/13'*0P9```_G>4/
+M``C9)"```:"?2?S\W^@9``#_B92@^<6>@-D@(``!H)[$V0CT&PU/@0#9(``0
+M`:"?Q=\,V>P9```@GW[^5P`S$``="@%^!5$`V0`$``"_GT[_[_W^!*"?/H`1
+M`+VDO;2]Q'Z.2@!^4N$`,Q``#@H"?@51`#Y*$P!^LDL`/DH3`.2)``+U"ZH`
+MV`9``"8Z0]_W_"5`O'U``2UZ0]@WTG__/V)!.2)``'T"WK$"0'T"Q*5
+M"0F5#PC]GP7PE`'T"R7=(%H``+_?V1`!$`'E#@`$D/\!H)_9)"```:">H-\^
+MP!(`WB0@``&_Z=_090``/_T/]_V?!/&5``&@Z3/0`0;X"-X`!```W>`9``"8
+MZ0]_W_"5`?'U``2UZ0]@WTG__OV)!.0I``CT"T;DB0`(]`LEV4!8``#>`%H`
+M`+^?D)DXL/8"]`T'L_0,)Z:>]!OO/A`3`-]`6```W@!:``"_^9#_.+"6`O0,
+M"*;^]!OSY"D`!/0+*.2)``3T"Q/?,``0`;_Y\)4@H/D^/!,`V3``$`&_GP[?
+M_?X$H)_9Z!D``*"8V2`@``&@F/N%"/D"V>P9```_F;+-,Y``!O@(QZ]H#/_T
+M"R6]Y$#_`,3Y`?0+#+P.E+F9`/W)!)#N"+/@(`NV]0$^:Q,`\*3_LZN``,\`
+ML::``/0,$+.@!R*SK0C6`#[7$P"SJY``A`"SJI$`8+.O@0#"`#X]%`#9!"8`
+M`;^?W@```$#]_@6@G_'T`$#U"Z,`/O$3`-D$)@`!OY_>````@/W^!:"?\?0`
+M@'/Y`(8`V40`$`'>)"@``0\!H)^_Z?&4__^@Z3YR%`"RNK+;?N^G`-[L&0``
+M/^_$^0CT"Q3$^?<@Z3YR%`"RNK+;?OT,`$^!`-D@`!`!/E04`-D`(``!O+FP
+MO[_9)``0`:"?3X``DID$H)\^@9``"_F?&4``3T"R+?````
+M`=D@7```M9\"CP"<`+*:M9\#?;3^3`%^`#X`]#`$^`#Y0K*BF*H(B0``#)@N
+M!M___P'P_Z_T_?D%V2@:``"5\1R\DD$M2X&
+MQ_MHQ"D/E+`"O,`PO-!`LY``!O@(WD`A``"S%`$/"0:UZ1H)`CZ#%0`)![7I
+M&@D!M>D0"$``+,4`17?
+M(AH``-KL80``//N8/B06`-\<&@``//N8VLQA``"\"@"UX#\0F0$\^;F_,]E`
+M(0``#P&UDCRUDSJ_1+6?.+6=/KWTM90[M9P]M9\Y"BG[0=E`(0``F)D"F*\(
+MLJW'GI#9__\?_/WY!)3I%?^?Q;6L",?)$_0;"VY!O?____![+:_9\$_>D%M=X'
+M/LD6`+/T!!#'R13T"PE^&14`^``*`_@`V4`A``#T,/#Y@K*3]##XF)`4_D8!
+MO138/AH``-0`!```U>`9``"'_W__D&8L/M0>`+,)$FP&L`82]`Q@LPD(`P.P
+M!@CT#"RS"02;`;`&!/0,$;,)`:\`LPT#F08^XA<`LPD&>`*P!@;U#*<"/O,8
+M`+,)#A8'L`8.]`P1LPD,EP2S#0UP!CXB'`"S"1#[!;`&$/4,N`4^2QP`LPDC
+MV`.P!B/T##&S"17B!K`&%?0,$;,)$S,&LPT4/`8^`AX`LPD7^0:P!A?U".(&
+MLPT8)P8^GQX`LPDJBP.P!BKT#!&S"2AD`[,-*0X&/H<;`+,+CP`1!+,+(`/;
+M`[,/C@#Y!3ZT&P"]E+(!M3D8M3D6/M(>`+W4"1+^G0ST,A+T,A+T,A*SU`$-
+M#P'9*%H``*"?F#D8L)8!]`P6V=QA``"_G]GH80``OYFF^?0;0]SX8```/\X/
+M`=E`(0``M9\4,^``%=D$$!`!OY\]Y"#.\?4`"*"?"@&FVO4;GP:]]-DH6@``
+MH)_T,1*RVC[D'@"SU`$0O?39*%H``*"?]#$2V]QA``"_OM\,80``F#T8`0.\
+M[I"\GI"0G`&VE`*\GY"_GY#N`9#=`?#D#[4_`=\,80``O/S(M3T8``2U/`*8
+MF0*@OK4Y`S[4'@"8.0'PE!^SG00)!I@Y`O"4#[.0!B6PE@;T#!&2F0*PE@'U
+M#.X%/N,8`+.=".8%`00`!3[4'@"R`0`//M0>`)@Y`9@Z%I6;&?0+#7[`4@"R
+MH3XZ&0"8/R:S\``=Q?D$N)D`(`*R`;4Y+[4_+KV4M3DP/J49`-D$80``?YEP
+ME@#U'Y<%Q)'_LQD`D`68.0+'GX<5^0'T&P4/`<3R_X\``!^4*1#]GP24'QC]
+MGP6R&K4Y%WYYJP"SJ0!A!509!O&4P!_$+S_=#`0``/WY!;V4M3TM=3]9-3FP
+MM3DNVO`A``!^9K0`LZ0`#+(!``8^U!X`L@$`!S[4'@"83P/D^0"```$'/M0>``$'`!8^U!X`
+MF#HNF*X(Q^D-]1NU!+^OQ/D'LYT!K`28J0''FR.SN0&A!+.T`PO'Z1'U"Y4$
+MQ_F*]`L,`0A`(`,^U!X`F#\"Q/D/LY0"$-\````(_^^5/NT:`,?I&_4+:028
+MJ0K'F3CU&U\$L[0#?\?_D,?I$_0;6)BI!K:5&+"6!_0-3)BI!K:5&+"6"_0,
+M0)BN!YBM")BL!MG___\'_>D$V?__`?#]V02)```*MO0;_=D%_?X%V?___P"R
+ML/W)!+6O![6M"+6L!CZX'@"4^17?__\?_/_O]/V?!=\````$_9\%M:D(/M`>
+M`'Y6%@"RH+.I`[X#F#DOQYD"]1NS`PD'`0@U.;`^*AL`F#DOQYD"]`L)L@$^
+MF1L`"0>R`34YL``J/M0>`-KP(0``L@%^"S<`LZD`F0,^F1L`F#H9F#X;"0$\
+MBOB[G@3]^00S\``:V?`9``"\FOB8.1RR`0`#M?D(/M0>`)@[&I@\+Y@],+V4
+MO>2PD0!^-+D`/LH>`-H@(@``L@%^*40`LZD`0@,!*0`C/M0>`)@Z+MM$(0``
+M02`#?N%#`+*@/M0>`)@Y+T&.`,>9`O0;(@D'08X`-3FP0(\`/M0>`-KP(0``
+ML@%^"S<`LZD`^@(`##[4'@"8/RZ]E-U@(@``M=D!H-G9````"K79`ICY#)C^
+M"[(!WP```/^VE1O][P2VE!#QY0"```W]G@6UV0,^U!X`F#DNVF`B``#<#`0`
+M`)B;#;:U%GX`/@`SI``,`0T`#C[4'@`/#3Y-'@"8/@*8.0&8.A;'[625FQFS
+MU`-:V3@`$`&_G\3]?S/0`!;$V?^FN?4;00+'^6BFFO4;.`+91!D``'^?MN40
+M?/[P8)\SU``;Q*D/MI0(CP``?_^_]?WY!=DX`!`!H)]^L:<```,!#S[4'@"_
+M/PD!NYT$_9\$]0L,`G[`4@"RH;.I``("?GFK`+.I`/D!M3$7L!8D]`PRO!&0
+MW=@&``"\D9"YF0&0F0&VE`2YF0&\G9!_GPG_9OGT"P^4^1:R`;4Y!C[\'0#$
+M&0&R`;4Y'P`1/M0>`)@Z%YA/,9A+,@G^_:D$O92PD0`)`K:D`S"1!+ROH-S`
+M(0``#1#>**L```$1?CO"`+.I`(@!`!`^U!X`F$\#Y/D`@'.0`&7_]Y2R`;5)
+M`P`2/M0>`)@_'[V4L)$`"0+>0"$``#"1!)3Y`[R>D+;T`YB;(=G`(0``O/GP
+MO_K<4"$```U`WBBK``"R`7X[P@"SJ0`J`0`3/M0>`)A.`Y@_%^3I`(!SE``*
+ML@$^U!X`_^>4M4D#`1.P]B3T#"B8/@:2_P'=V`8``+S_D+;E%KR?D+:4!+R=
+MD'6>$%@^"@$3=9X1`!0^U!X`F#\"F#T#F#D7F#L&Q/[PM6T!MI08W0````'Q
+ME0"8MO4(MO0(_>\%M6T"M6D#MK46H&ZR:MP,!```?@`^`#.D``P!%``5/M0>
+M``\4V4`A``"UGQ0^XAX`F$X#Y.D`0/0+:G]?2?^_L@'_Z93Q]/?_M4D#8%\^
+MTAX`F#HN`!`-KP(0``
+M`1A^"S<`LZ``*C[2'@`!#S[2'@`!"#[4'@`!!C[4'@`!!#[2'@"R`3[2'@`!
+M"``#IA#U&R[XV4`A``"UD12]I/0P"/N%$/DBO>3?!&`1`=(N&0``T?__`,[0
+M````"(H```(+[SXF'P"_^9#N`?V1!/V0!:#YO]F0_X#]F@7]FP2@V3\IDOT$
+MQ)S_INST"-R]Y-\`8!$!C0``!#YD'P"_^9#N`9#_@/V=!/0+%[WDWP!@$0'<
+M+AD``(WO__T^@A\`INST"-R]I#Z.'P"_^9#N`?V=!*#YF/D"M?D"D/^`/\GP
+ME/^FZ?0(Y@H%^R'9Y!```;^9MI4?LY0!=]DP&0``/Y_9+AD``#^;O=3P]/_>
+M"&`1`<2Y_[R?P#[7'P"_Z9#_`9#N@/"4#Y*9`["6`_0,!I#=`:;\]`CGQ+G_
+MIMGT&R?9`%@``#^9,Y0`'=_$8```O_FSE``;V20```&_F9"9`:#Y^`"]]-G$
+M8```H)_X`+.Y`"P!L[0$%=X$8!$!E*D'O)Z0OYX^2B``E*X$L[0#$-\$:!$!
+MO._@/D@@`-D$Z4J00^'R$`DKD!E*X$L)8!]`P1V01P$0&\Z>"@[3X1(0#?!&@1`;SO
+MX*#MN.D`"`"@G3X1(0")P"("O*F@E*D'/@TA`+.T`Q*.@!81O*Z@E*D$/@TA
+M`(X`%Q&2N0&\KO"PE@'T#0^)@!81O*F@E*D$H)R4^02@G/@`C@`7$8\`Z>Z\
+MKJ"4J02\KZ"_GI3/!4D?_O'TX`'_Z93P]1#_^<6SM`2E/LX@`/@`V3`9```_
+MF9"M`<2?_Z;?]`@DV2X9```_F<2>_[SOD*;9]!@2O*^2D)P!IL[T""@^DR$`
+MV3$9``#?+QD``#^9/__PE/_P]/^\J9*0G`&FS_0(!?@(V01P$0&4S@2\Z="_
+MV=\$:!$!O._@CP`7$;S/P(\``/_]GP3PE8"@Z:#9E,T$O]E/'_Z2SH"VY`3Q
+ME1`"_9\$\)6@H.F@V=DD```!OYZ4J0.4KP:[^0+90%@``+SY\)C]!)#N`3V4
+MM?X(D/X,->D#"=C_V92U^03QU``"]`L%^`CX`-DP&0``/YGT,/R0K0'$G_^F
+MW_0()-DN&0``/YG$GO^\[Y"FV?08$KRODI";`::^]`@H/FPB`-DQ&0``WR\9
+M```_F3__\)3_\/3_O*F2D)L!IK_T"`7X")2Y!-X$
+MD-[__P#._?X$\/6QH)^@WXP``""0F02/`!<1H)R\O["XF0`(`*"!'`1`;S^\+_^
+MC0``"/_ME/0+*]G__P#.E*\$_^F4_9T%L[0#$-X$:!$!O/[PH/GX`-X$`9``"8Z11_W_&5`!#P]2"UZ11@W_@`V?__
+M_P#]J02_K__YY*;>]`L%^`BV]1C$^0'T&P7X",3Y_K/$``?PE0*VE!C]G@6@
+MJ?@`O_FFV?0;$[/$`!#?X&```#_Y\)3](/GX`-DP&0``/YFSL`!H\)3_DID!
+MW418``"\FO"\_Y"4_@2\Z9*VE`*\G9`_F3.4`%>4^0:V]`.[GP+?0%@``+R?
+MD)B9!/"4"/0;/-DD)``!O.G@O^_=#&`1`92I![R=D/#T_Y"=!*"?O^GQE`#_
+MH-GX`)2I!]\,8!$!O)^0H)N0F02@F_@`L*8/]`PFL*8%]`T%^`C9U&```'R:
+M^-YL8```E*D"O)Z0Y/K__Z"Y^`"2JA"PI@7T#07X"-E<8```?)KXWH1@``"4
+MJ0*\GI#D^O__H+GX`/0P^/F"O23T,/S^1P&0=R@^?"8```&[`@3_"93U"R
+MT&```+D)`/V?!*#IL"8/]`P\WS$9``#>+QD``#_Y/^^R+O#T__"4_Y*1`;P?
+M4)0?`P0!E!D&NTX$O)\"$D8!WUA8``"\#P`^^R4`WC`9```_Z=XN&0``/^^2
+M+A`^H24`/PGPE/__293T"PZR&ODU/PG]E@0@"9`1`9``.*85]`CBL'$`LCJR
+MBPPAW0```"'>OB,``'Z&1P"_>;.0``;X"+3P"][___\`O_G]G@0^!)#N`?V>!:#YD"(!LR`@$-_08```O_FSG0##_MG08```
+MOYGT,`2PE@#PK`OPI@'[A0CY0MDP&0``/YFRK)"M`<2?_Z;?]`@DV2X9```_
+MF<2>_[SOD*;9]!@2O*^2D)$!IA[T""@^]"8`V3$9``#?+QD``#^9/__PE/_P
+M]/^\R9*0D0&F'_0(!?@(O20)$OZ2#/0R$O0R$O0R$K,D`0O9*%H``*"2V>!A
+M``"_FI3$!I3#`WXI;@`)?L&```*#I\/3_DO`!E`D&E`\#LN:\GQ*]
+M)-EH6```U2X9``"\&1#4)````0,!/@(H`+\?L_``&;])IOGT'0VR"GZ>)@`^
+M_"<`H&.R,I```9`1.#]9\)3_I@GT"-BR*OMA"@B]M-Q?C`$`?LM.``D#LZ`!
+M#]G,8```#P&@G[V4LIKX``\!V>1@```*!*"?B\#4`=R=C`$`?LM.`+.D`2'>
+M6&```-W@&0``O^E_WPH#\)40\?4`"*#I8-_X`+.D`!396&```+^?#N_]_@2@
+MG_@`^`B]I/@`V>`9``!_F?D2\90`"/0+!?@(V5A@``"_G]'`8```"0&@&<3P
+M(/0;$7[J'@"SI`4*H!`^&BD`"@5+X"[<>(L!`'[+3@"SI`$CWEA@``#=X!D`
+M`+_I?]\*`_"5(/'U``B@Z6#?/AHI`+.D`"K=6&```+_?V:1@``!.X"Z@G@G?
+M_?D$H-_9/``0`4],':"?/AHI`/@(O:3[$?0P\-DP&0``^7(_GK*@LL?$ZO^F
+M"O0(%]DN&0``/YD-,/"4_[R:D*8)]`@QV3$9```_F<2?_Z8/]`@5V2\9```_
+MF?"4_[R?D*8)]`@)^`@^-RX`#2"F"O0(']DN&0``/Y_$Z?_P]/^\^9"F"?08
+M"KP*(CZI*0#9,1D``-\O&0``/YD___"4__#T_[P)(J8O]`@%^`B2`0&SW3!A
+M`HG__P'$OO__N32QYG\`]`T(L^[_`#.\$9"4'P2[^0+91%@``+;T`KSY\#_Y
+M,Y0`*_#D_Y0I!]\,8!$!O)^0H)X^#RH`WA0D``&4"02\GI"_F<2>_\OCX+#F
+M`/"<"_"6`<<^Z)26`;/@``?P902\$9"4'P2[^0+91%@``+;T`KSY\#_Y,Y0`
+M%)3O")0I!]X08!$!O)Z0H)^S<``*O40^`"L`_DH!/;20JB`,$'ZL-P#9`"@`
+M`=\P&0``OYD__Y"9`?#T_Y24!*8/]`@5V2X9```_F?"4_[R?D*8)]`@%^`C^
+M20''/^B0F2"V]`GP]4"RFZ"?O:0R+')-?DX"`)0?`Y09!K.D`"B\G_+93%@`
+M`+SY\!CY`=[@&0``\)4"-?D!?^GPE2!@Z3X`*P"\G_+>3%@``+S^\!CY`;(J
+M"P2]Q/"4_37Y`7X3(`#?%"0``90%!+Q?4+]9CP```?\YEOV?!/4+V0")00(0
+MO`D`E`D$OYF.O_WOO`X`QYD)]0NX`+-]`+0`_DH!/;20JB`,$'ZL-P"S1``1
+MV0`H``&_F9"9`924!-DP&0``/YG$G_^F#_0(%=DN&0``/YGPE/^\GY"F"?0(
+M!?@(_DD!QS\0D)D@MO0)\/4@LIN@GW)-O:0R+'Y.`@"4&0:4'P.SI``HO)_R
+MV4Q8``"\^?`8^0'>X!D``/"5`37Y`7_I\)4@8.D^\"L`O)_RWDQ8``"\_O`8
+M^0&R*@L$O<3PE/XU^0%^$R``/O`K`(G___[].02S8``>WP1@$0&4*0>\GY"_
+MG][__P#._?X$_V_UH)^@4SXW+@")00(0CK_][[P)`)0)!+^9O`X`WQ0D``&4
+M!`2\3T"_3I0?`\>59909!KN?`M],6```O)^0Q[80&)<#B0```?WI!/0+"S-@
+M`!D^-RX`,V``$3-0``W9^/\`\#YV+`#9^/\!\/^Y!)4#'/4+IP`S4`08V?__
+M_P_?````\/\)E/^?!3XC+0"S.0^+`+VD?KEM`-D$:!$!E"X$O.G@O^F/@!81
+MO"\@W___`,[]GP3QE0`(E"T$H.F_V4\?_HZ`Z>Z\+B#]GP3QE7`!H-G9)```
+M`;^?E!X#E!D&NYX"D/\!WD!8``"\GI"UGPO?____#_T/!`\.H)^\$?"UDPR4
+M&02[GP+?1%@``+:4`KR?D`\--9\!H$`S8`!L,UT`K0#'">CT"PW$FO]^2*L`
+MQ*G_\)1_Y9H`$#-T`QN)D!81CG#I[KPI()0I!+PN(*":/G,M`(\0%Q&\+R"4
+M*02@FHGPZ.Z\*2"4'P.4&0;>0%@``+N?`KR>D)B?!/#U0+6?!#[6+0"4&0.4
+M'P:[^0+90%@``+SY\)CY!/"40/0++C-4`@^R*L1[_[W$?A,@`)09`]Y`6```
+ME!\&N_D"O/[PF/D$#K_]G@2U^03'"62PE@'T#0FR"S[N+0!)#___"93%FR`S
+M8``3,W`##XG___[_N90^`RX`LKF4*@3?#&@1`;ROH*"IV?27[OZ\J:`S8``3
+M,W0##XG___[_N90^+2X`LKG>#'`1`;RNH*"I^W40V6`"$`'T,/SY@K^8LJ*R
+MMK+%O:1^N6T`V3`9```_F[@A(`0"E1`$$`T!)MOT""O9+AD``#^9Q+S_Q-[_
+MQ)__O/R0INGT'Q.\[**FK_0>!?@(LJ0^N2X`V3$9```_G]DO&0``/YG$WO_P
+M]/^\[Z+PE/^FJ?0>!?@(LJ0FV_0('=DN&0``/YG$O__$WO\#,/"4_[R?D*;I
+M]!XKV3$9```_GR;?]0A@!=DO&0``/YGP]/_$WO\#(/"4_[R?D*;I]1]%!=D`
+M(``!O"EPOW[_5K3$&0^SF03`!+.9#,@$LYT`)P4S-#`-V?+#_XX^+"\`V?+#
+M=P[_N139``#^`/\9])7Y$?0;"[+B/50^32\`N?D`!0'_GB3_'I;'F5GU"[<`
+MQQE9WO____&VE!G_+O3^2@'_^27]'@20JB0S-#!`W@1@$0&430>\WM"_V=__
+M_P#.W@````;_+N2@J;^I!0']GP2@J;^IW_____G]GP3]Z06@KK^IH-D^"C``
+ME$X$WP1H$0&\[]"_V=S__P#.V_____G?````!J"IOZG_+_35!'`1`;SEX/V<
+M!*"IOZD%`?V;!/_YE:"IOZF@V;_IH*F_J?V0%@``)0)!KN?`KR>
+MD!B?&+61!0X!\/4!-9\8V=!@``"_F3,T,`B.```!_^GUV=!@``"@G[/=`-8#
+ME`D#E`\&N_D"V4!8``"\^?"8^02@_?&4`!#T"PNR2@L!?F`D`-Y$6```O`#P
+ME`D$NY\"MI0"O)Z0&)X!E`\#E`D&NY\"WT!8``"\GY"]]+6?!!+N"S#F`?0,
+M#]_N8```/_D2F0$@^=GN8```/YDPE@#T'P7X"+P`\)0)!-Y$6```NY\"#P&V
+ME`*\GI`UGP$^-C0`\`3_L_0`/Y0)`Y0/!KOY`ME`6```O/GPO_FSD``&^`B4
+M"02\`/#>1%@``+N?`K:4`KR>D!B9`3.9`0<#^`@^-C0`O`"0E`\$N_D"V418
+M``"V]`*\^?`8^0$SF0KE`I1)!-X(`#,T,"V420??"&`1`;R?D+^9\)0/LYD$
+MB`+9T&```+^?C@```OW^!:"?/A$R`#,](&\"L^T!:@*4"0.4#P:[^0+90%@`
+M`+SY\+_YLYT(4@+?T&```+_Y\)4$H/G>0%@``)0/`Y0)!KN?`KR>D+61!0X"
+M&)D8,S`P!@X$E`\#_>D%E`D&NY\"WT!8``"\GY`UGA@)[_TI!#XZ-`#'&03T
+M"WPS-"`DQ"D!]`MRL^0!;\-`"420?>"&`1
+M`;R>D+^?QRD$]!M%Q/D/LY`$/]G08```OY^.```(_?X%H)\^7C0`E`\#_=D%
+ME`D&NY\"WT!8``"\GY#$+@$UG1@UG@X%`0G]_RF4Q9(1QQD0]0N5`)0)`Y0/
+M!KOY`ME`6```O/GPF/D$\90`$/0+"[)*"P%^8"0`E`\#WD!8``"4"0:[GP*\
+MGI"8GP2UD05.U^_]_@2UGP39T&````\(OYDS-#`(CP``$/WY!=G08```H)^4
+M#P.4"08.$+N?`M]`6```O)^0&)D8,S`P!@X(E`\#_>D%E`D&NY\"WT!8``"\
+MGY`UGA@S/3#/`)1)!]X(8!$!O)Z0OYJP%@#U'[H`QRD$]1NS`,2I#[.9!*P`
+ME`\#E`D&NY\"WT!8``"\GY`8GQBUD07>T&```/#U!#6?&+_OV?W___[_*93%
+MDA&)```$_?D%H.\^.C0`Q-K_O<1^'"D`/CPT`#,T(&3$V?_5%"0``;:4!+R5
+MD+^9CP```?V?!/0;2>2Y_S]/`,#_[_3_^;7'N6JPE@'T#0FROSX<-`!)_\/_
+MN93EGP`(E$D$W@1I$0&\GI"@G[*RN)D`"`"@GSXZ-``S4``&H'+$B0'T"T/?
+M8`(0`;_Y\)4!H/D^@C0`V>W__W_]&00^4#(`E`\#E`D&NY\"WT!8``"\GY"U
+MD04-`AB9&#,],#'^#0@^J#(`^X4$V20@``&_G[B9)"`"^2(RHMHP6```Q"'_
+MM:D"E!D8H*F)`(@`M:D#\/0!DA`!L_T`(P%]M-Q0!```?@`^`#.M`!,!E`D#
+ME`\&N_D"V4!8``"\^?`8^0PSE`$0WZ!@```_^1*9`2#YV:!@```_F3"6`/0?
+M!?@(E`\#E`D&NY\"WT!8``"\GY`]]#6?#-DP&0``/YTF+?0(*=DN&0``/YG$
+MWO_$G_^\_I"F&?0?%+P>DJ:?]!X%^`@\+>(^:#4`V3$9```_GMDO&0``/Y_$
+MZ?^\&9+P]/^FG_0>!?@(/"[B)BWT""?9+AD``#^9Q-__\)3_O)^0IAGT'Q+$
+MZ?_?!&`1`;:4!SZ[-0"4"0.4#P:[^0+93%@``+SY\!CY`\3O_S.4`Q"4^03?
+M!&@1`3Z[-0"4^03?!'`1`;R?D+^?D)D$OYF)0@(0O`D`E`D$OYD^_C4`E`D&
+ME`\#O)_BWT!8``"\[^`8Z0PSE``5"0'?H&```#7I##_Y$)D!(/G9)"```;^?
+M#O?]_@3P]1"@G_LA\*,`Q*T_QZK&L-8?]`T%^`BPIB3T#0>]I/@`DJ\!O/^0
+MO)^0W]@&``"2W0&VE`2\GY`\G?@._SR>V=E`.```\/('"@&V]`:\^?"]E*#Y
+M^`"PIB3T#"F2J0&\F?"\^?"4^03?V`8``+R?D)B?"K/P``^@OYB9"PH!H,GX
+M`+VD^`#Y,N2I__^RL\>1QK`6)/0,:,22/[`F(/0-!?@(?OE[`+.@``H+0'Z_
+M-P#?0#@``#T$O_F0_T"SE``YV4`X``"R.\0*_PQ`MJ0&O*F@?E0W`)(?`0H!
+MO/^0O)^0W]<&``"VE`2\*9"\GY`@D#X)-P`0``$S!$:_O:3[,?D"/ZGT,/BR
+MH#.0`#DSD`<."@$SE`@O/D\W`)@)`9BJ`Y@+!)@,`K"1``D!#4`PD03>3;0`
+M`'X[P@"SH``("0@@";VD]#`(^P'Y`L2I`[+`ML4"LY0`*\2Y`_0;)+WT/G@W
+M`+_ND/\!D)D$H-Z\J="\N>"F_/0([K+)/HLW`+V4E)\"O+^PO*^0/J4W`#^^
+MD/\!D+L!()Z0F0&F\/0(\?L!O90^N#<`/*N9D)D!IIST"/CX`+*OE;X"Q*D#
+M]`L)O90^YS<`O92]U#[@-P"@_9"9`9#_!*:>]`CVLNF4GP(]Y+ROD#[[-P`@
+MGI#_`9"9`:;[]`CV^``/`=GP8```()])``&]]*"?D)D$LYY``?OX`/D2LJ"R
+ML;&F_Q_T#1O$J0/T&Q65N0;T"P_$J3^\N9*PEC_T#`NR"K(;/ILX`-GP8```
+M/YDSE``(?@(X`+(/O>0^93@`H/Z0_P3$^3_T&_B\`9"R^KN?`HX``02RFSZ&
+M.`#Z_@:0_T"2NT"PMC_T#/2VE0:VE`:\J:#X`[.P``A^OS<`^Q&_KK*ME>D0
+M]`L@"@&FF_0+)_^^]8D``/_P\P#_Z92]I/WY!:#?^`"4N1#D[____9\%H*D*
+M`?@`OZR5R1#T&P7X".3-___U"YD`E9X!O?0^*CD`D/\!_^V4]`LFN>\`B0``
+M___?]/_)E/WY!:"OL^`0.[/J``%*L^0(6#XV.0"VY0&P]A#T#07X"+/D`,F.
+M`(``/O,X`-\`!```F/D#\94`!+7Y`SYQ.0#?``0``)CY"_&5``2U^0L^<3D`
+MWP`$``"8^07QE0`$M?D%/G$Y`/@(W^`9``!_^;+M_9X%8/F_J93?$/&4___]
+M^06@K_@`^```````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````#>``0``)CO$/0PW/F"]##X
+M<_``-]DP*``!OYG40`0``-"@7```/62PD1'9-"@``;^9L)$2V3@H``&_GI"9
+M!+^9L)$3/GDZ`-E`)@`!OYF8[Q'41`0``-"P70``L)$1V40F``&_F08!L)$2
+MV4@F``&_GI"9!+^9L)$3Y/D`0/'T__^SE``O"?#_Z920##"PD0NPP0^0"1`]
+M=+"1#+VDN`4``0#3``0``-C@&0``/FT]`/@(/H4Z`!@)(3.4`!K9Z!D``+^9
+M\)0!]`L,,V0`"0D$-0DAOTVTP`^)``#__]F4E=X0H$G'[\'DTO__E/D$\.0!
+MD)D,MN0*O,G`D/\#L,$0MO0$L.$-O`_PL/$./F(]`,0I$/4+H@$8`2$)[_TI
+M!#`6!O0,%S`6!?48J``S$`)@,QT#)0(^4CL`,QT('`*R"G[:L`"SK0#``0D'
+M-0DA/E4]`%@)@[2@$;2P$K3`#+:4$`$"L)$`,!$$#1#>B+$``'X[P@"SI``1
+M?XD*`?"5`6")/E<]`#4!(3Y5/0"8#P58"0R8#@3<````@/W\!74)!;4/`3V4
+M??2@#C4)('4/!#-D`!'1`#]9,Y``7K3`$)@/`;\!6`V#O\G$_/^V
+M]1^TH`[]G@2TX!#]GP6T\`WQU/\#H.FR&__]U7Z/L`"SH``4W^`9``!_^0H!
+M\)4!/HD]`%@)!3]>D!\0H`]2F0$2[@%U"04@7@D$-0DA,V0`)[\^F#T+F#\4
+M?XQ)_]_]Z03]^03]V03PQ0*@/K4_%+4]"V","@$0=P$P=@7T#07X"+,M`*[]
+MOTGDG___L_T`2?W9``0``%B9(G.4`!'?X!D``'_Y\93^_V#Y]#`(^X4D````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````"?#T,-#Y@G*T]##XLJ;^3P&RQY#_/__Y%.2Y
+M_P.0$A!SGOX#,-DX)@`!OYB0F0B_E9"9!+^9T+!=``"PD0O93"8``;^9V4@F
+M``&_DSYW/@#9*"@``;^8D)D(OY60F02_F="@7```L)$+V3PH``&_F=DX*``!
+MOY,,$+(JL@M^5#<`LAJR:PP0?E0W`+(*?BRQ`+.D`&&8+`&8&0-8+04._I7/
+M'_V>!/WY!;4?`\=&"I@;!%@D!'#6`?0-><0Y!V:4]!L5"?#_.?2FO_0,"Y"Y
+M$*:?]`M?6`F#Q&T!\,3_MM0*\93_`[(:_=D%?H^P`+.@``HRK3X;0`!8*068
+M'P2R"K(K4ID!D/\0=2D%M1\$#!!^5#<`OWG?X!D``'_^/=3QE0!`H'G'F?#]
+MG@5@^3X;0`!SW0&J`%@)@9`/,+(;#!#$D0PRD\0:_[:D!+SZH'Y4-P#D2?__
+MY(___Y"9`::?]!X+LEH"!CYR/P"VE`0"!;Q9H%@/@[2P"\1N`<09#+;D"+;T
+M$+:4"?V?!?V>!;"1``D"#1`PD020#!#>B+$``'X[P@`-`[.@`':X#P`!`#_Y
+M$!H!$)D!(/DSI`P&/:2_?\0Y\SW4_ZF5\?4`0*!_\)3_-0(A=0F!/AM``+(*
+M?MJP``D(LZ0`!@D'-0DAW0`$``#;X!D``+_9F-X+F-P4?[_QE0`@\>4`(*#9
+M\/4RM=X+\<4`(&"_M=P4#0$RVO0P"/N%,+/$`%C9____`-\`Q@``_ZF4II_T
+M&U*5J1@/`;.0$18/`K.0(1`/`[.000JSE%`/#P39`6(``""?^`#?`6(``+.4
+M8!$)!2#YV8@=``"@F_@`"08@^?@(^`"SQ`$-#P;9`F(``""?^`"]U`D2_IT,
+M]#(2]#(2]#(2L]0!"]DH6@``H)W9@!H``+^?V7P:``"_F:;Y]!MDV=QA``"_
+MG]GH80``OYFF^?0;4=X,$!`!O^G?____?_V?!*#I#__9$!`0`:"?WHB(B(B2
+MF0R@GKWTV2@9``"@G]D($!`!H)[^B0'PE0+^F`"SU`$.V2A:``"@G_0Q$O0H
+M`?@`?93?X!D```H!8/F]M+W$?HY*`+.@``;X"`\"V7D:```@GWX6W`!^O-P`
+M?I/;`-T0%``!O]O>%!0``;VDO^R@VDD`$*#I#S#96!8``:"?H-N@[+B9'`("
+MOY_9^&$```T!()W]_039P&4``""?WA!B``#9ZF```#/P``P@FB#J/J%!`"#M
+M()I^Z=X`O928F0GYE/@`F*\-Q_DTLY`!#+.4`U\^X$$`"?YFN?0;4XD```'_
+M^96/___/_9\$CP``(/V?!3X40@"8K@J)___^__F4CP``!/V?!>7O__^UKPJ/
+M___/_9\$CP``(/'D___]GP6/``#__9\$_9X%M:D-"@/X`)BO"IBM#9BL"(X`
+M`/___I3QE?[_M:D*B?__S_W>!/'T___]_07]^02)```0_?D%V?____>UKPW]
+MR02UK`CX`)BI`;*MF*\-QYD']`L-Q_D0]!M7/K1"`,?Y$_0+1\?Y$O0;,>2\
+M__]FO_0;*)BI"H[___W__N2/``#__9\$_\F5M:D*B0``,/WI!;6N#0H"^`#'
+M^1#T&Q.RVGX;0@`^J$(`^`@*`?@`"@'X`)BO#8D```C]^06UKPW'^32SD`$6
+ML)8!]`@3LY`"&+.4`R@^_D(`LIKX`'X;0@`*`O@`?EI"`/@`B0```O_YE;6I
+M#0H!^`#X"`H!^`#Y`IB@",<)&_4+NP"8J0V8O@+'G#2SQ`$5F*D)C_[_`/&4
+M__^FG_4;G0"8N0%R[<>;D/0+&+/$`AD)_6;I]0R&`'/I`((`/FY#`+/``GG'
+M"1/T"PNSP`,(L\0!:^3<___'"1/T&S>8J0J8K@V8K0B/``#__9\$_\F5M:D*
+MB0``,/WI!;6N#9$W*^]`L:F*D)\.,`CP``_PH#_9\$
+M_>D%M=X)^`!^KD$`^`!^$D,`^`#9+!D``#^>F*D"#_"RK)BK!/V?!+B=`"``
+M,^0`!O@(F-D.#_<*`?V?!+6Y#IC.!9C9#KWTM=\/\)0(_9X%M=D.^``)`36I
+M,/@`"0$UJ3SX``D!-:D0^`"]I/@`^0*RO[+`Q*D#]`L%^`BRJ[+\"@A^E7@`
+MWP````'9____^/\)E/V?!;6I"O@#^P&VI1BSP``^LZ01-ME$8```OYFFV?0;
+M*=W@&0``V_9>``!_V3^_W!@9``"_SO"50/#T_F#9D.X!(+^@SO@`^`CX`+.D
+M$2_91&```+^9IMGT&R#>X!D``-WV7@``?^D_W_"50/#T_F#I\/4"(-_X`/@(
+M^`#9'!H0`;^9^5+$D0?U"Z4`V9`=``#5`,4``+^2U!`:$`'9E!T``-,4&A`!
+MOYL^N44`O\ZFY?08!?@(6,\"DND!E>H(O03P\P"\GY"VE0B0F0&FFO0-!KR:
+M`EC-!%C.`^2O_P^4"1BV]`C]GP6@2?'D_P.VE0BVU!BVY`AUR0K][06@/I"[
+M`;"V$/0-!;VTDA$!]`L9O+N0O)N0E)P#V=P;``"\R<"FLO0;BMF4'0``H)O9
+ME!T``+^?V9`=``"_F:;Y]!L0W^`9``!_^?&4^_]@^;VD^U&]])CY$/0P\/F"
+ML+$+<,$5L.$)
+M`G20%;3@#G7;!'79`[7>!)#)`:#YL)80]`T'O92@^=D<&A`!OYGPE`?T"PU^
+M)44`O:0^@T<`WYP=``"_^;VDD)D!H/G[A1#Y4K*A]##XLK"RPK+4LN.T4`FS
+MM``&^`BS)!$6LAJR"W[HPP"@6K.@`R"SH`<8'0``U(P=``#6@!T``#Y92@"_<;,4
+M``;X"+]+V80=``"_D+]BO+N0O)N0E)H#V=P;``"\J:!8K`2]A'/`(`USP$`)
+M<\T0P@!SQ$`-O>1//P$^3T@`OZZ8C1!8J0*2[P&[[0+PDP"VY0B\^?"[_0*V
+M]0B0^0&[G@)SQ!`AO`D`IB#T&`6R`ABI"O"4`?0;!;+O#`$)`3Z22`"["0)S
+MQ"`5&*D*\)0!]!L+LN\]Q#Z22``]Q+V4Q)H!V9P:``"\Z=`_V9#N`?"4_O^I
+ME2#9,\0`"?"4OR#9D-T!IN_T#>60NP&PMA#T#06]M+R[D+R;D)(1`92:`]G<
+M&P``O*F@6*P$,UD`.__9A!T``*!BH)"@<:!+V2P:$`&_F5BO"N>9:`%UJ0MF
+M^?0+!?@(WP```$#9&!H0`:"?<\`A#G/)0=X`<\T1"0'9`````?\YE/0+0W/$
+M(2"_K]D`Z0``IOGT"S/?'!D``+_YD)D!H/D^)4H`<\01(-X<&0``W0!B``"_
+MZ3_?D)D!$/\!H.D@WSXG2@"_KKV46*\"F)T0DND!T(0=``#P\P"[G0*\GY"[
+M[0*5D0BVY0@)`;N>`KR1L'/$$1R_";]O#0&\N9"@"::?]`T4H&D-`3Z]20"_
+M"3W4NYL"H`D8J0KPE`'T&P6RX=F<&@``Q-P!O.GP/_F0[@'PE/[_R94@^3/4
+M``GPE+\@^9#_`:;A]`WE/B=*`-F$'0``OY_>G!H``#_I\)2^(.F0[@'9W!L`
+M`*;I]!OON/]``0+9A!T``*"?/B=*`/@(OWF_3Y*9`9#_`:!YH$^P]A#T#0>]
+ME*!)F*D$OZV8J@/'/!CG.R@!!0'YE=D8&A`!OY.P-@#U'I/]V9@=``"_F;.0
+M`"/9D!T``+^?V90=``"_F:;Y]`L/W^`9``!_^?"5!&#YO:3[@?0P_/E"]##X
+MLZ0`5MG@8```/YG$G__'^0'T&PK$^0'U"_(`V9Q@``"_G]GL8```?YO9____
+M`++Z_?D$_DD!D)D<\+,`W0```"&PD0#__=4,(=Z^(P``?H9'`#Z?2P#?`,8`
+M`-EAZ```O)^R#P'9(T```##Q!+"1`-D!8@``WP#&```]Y++Z()[9____`/WY
+M!-X````1?<3__N4-$7[Z10#^20&0F1R@FD&8.K.@``GX"$&8.M(!8@``!/_3
+M&!H0`3\I,Y`!.`!D/G!+`+\YL)8`]!\1?M%'`#\I,Y`!$#.0!@R2``&F!/0;
+MY3\I,Y`!#I(1`?0;S3Z,2P"S%``&^`@]]-D!8@``O:0@G_0P"/M%!-\`Q@``
+MV]E*#9O93>F!T``)B?$+_I/<2\#_*2F0&@Z97Y"+SQ\+*=E?H(WYP:
+M``"\GY`^:4P`()R0W0&0F0&FVO0-]CZ"3``-_]P8&A`!DNX!INWU&WS_O:3T
+M,`C[$96I&+/)`*,`LYT1D`#9C%P``+^9IMGT&R#=X!D``'_9VY!<``#<"!D`
+M`#^_O\[QE0`!/A--`-D`M@$`IMGT&Q'?,%P``#_Y\)3^/HI-`-D`X0``IMGT
+M&Q'?$!D``+_YD)D!H/GX`-D`O`$`IMGU&[X`W>`9``#;8&8``'_9W!09```_
+MO[_.\94`!	\/3^(+^0[@&@SO@`V0@!$`&@FI"9"*"=^`"SG1&%`-F,7```
+MOYFFV?0;(=[@&0``W9!<``!_Z3_?\94``?#T_F#I\/4"(-_X`-D`M@$`IMGT
+M&Q'?,%P``#_Y\)3^/H=-`-D`X0``IMGT&Q'?>1H``#_Y\)4"(/GX`-D`O`$`
+MIMGT&Q_>X!D``-U@9@``?^D_W_&5``3P]/Y@Z?#U`B#?^`"]I/@`O:3X`+VD
+M^`#X`-GP$``!OY_Y`K*:O<39:&8``/#T_YB;`K^=F)X!``$^N4X`L]`"4+#6
+M`O0,#+/=`<0`/@=.`+/0`UBSW06W`#XC3@"SY``&^`BS\`$,#`$-`CZY3@#X
+M"`T"LOP^N4X`L_`!#++<#0$^N4X`LMRR^SZY3@"@H+^IQ)__L_0!#++<#0,^
+MN4X`LMP+`3ZY3@"]]-GH$``!H)_=Y!```9"9!*">O]_9````()7L&)+.`OWY
+M!:#?L.8#]`T9L\`(%K/`!Q*SP`D.L\`-"@X%L\0,%MEH9@``F)D##@2SE``(
+M^`@.!-]H9@``O92@_K7Y`C[)3@#X"++00
+M``&_F;*N"@*5GQ^S]`$VV6AF``"_F;.0`0RSD`4(LOKX`-]H9@``MN08V?__
+M_P#_N93]G@6U_`.U^0%^Q$T`O:3X`+.D$2/9`(D!`*;9]!L8W[1F```_^?"4
+M_B#YL\0`"?"5`B#Y^`#9Y&```+^9^0*SD``,?C(H`#Y=4`#9P&```+^9LY``
+M#'Z%*``^75``V5A@``"_G^3Y``+T"V/9,!D``#^?V2X9```_G<3[_Y2_`\39
+M_[R;P)2Y!KR?\MD86```O/GP/J]/`+_YD/\XY)X``?"4@#.0``BSX``,D+L!
+MIKST".?$V?^FN?0-!?@(DKL!``G9`?0+!?@(V8E,``"PD0#9____
+M`-\`X0``VV'H``"R^KN_`OWY!#V4W@```!$PD03__N5]Q`T101`G?OI%`+.@
+M``GX"$$0)_Y#`=)Y&@``!?_4&!H0`9`S(#\IQYD!]!L\0!`G/K%1`+])H#F_
+M.;"6`/0?#W[11P`_*<>9`?0;"Y(``:8%]!OC/RG'F0'T&PV2$0'T&\8^,5(`
+MLQ0`:#XQ4@"SI`)>V7D:```_F<>9`;.0`0;X"-F)3```L)$`V?___P#?`.$`
+M`-MAZ```LOJ[OP+]^00]E-X````A,)$$__[E?<0-(7[Z10"SH``&^`C?>1H`
+M`#_Y\)3](/D^,U(`^`CT,`C[502SH#@-LZT\@0`^FE(`V3@@``&_F0_'_[_T
+M\)0(]!LHW@`C``"8[2RV]0;$N0&V]`;PU0&UZ3.U[RVU[2RU[S&U[R_X`,3]
+M!C/0`#[9X!D``'^?W@`C```U[1CP]0)@G_@`V3@@``&_F?"4"/0;&MD`(P``
+MF)\LM9LNM9LRM9LP\/4"M9\L^`#9520``#^9LJS>6"0```H!Q)W_/O-2`'_I
+MD.X"Y)___\?Y9Z;)]!L+Q/E_IKGT"PV0J@&FK?0-XKVD^`"PIB3T#!V2KP&\
+M_Y"\GY#?V`8``+:4!+R?D+6<"[6;"O@`LZ0$&]_880``O_F\N9"@^;&61@#T
+M#1SX"/@`WP!A``"_^;RYD*#YL99&`/0-!?@(^`"8J02RKK^M"@3$G__T"T")
+M__\/Q]IT_]F4]!L+L_0!(3Z:4P"S]`$9&.D(,Y0`$K.@`QVSH`$9LZ0"$_@`
+MDJD!L)8!]`T)"@'X``H#^`#9`",``)B9:\>9JK.0#SJPE@_T#!"2F0JPE@+T
+M#%H^%U0`LY`05[.4$4^_KIBO"@GX_>D$V?____B@KOWY!+6O"CX75`#9+!D`
+M`#^9,Y0`+;^OQ/D'LY`"#@GX__F4\)4#H*F8J0K?____^/V?!+6I"CX75`#X
+M"/@`V3`SY:5`"]]-D`!```F)D:W@"$UQ>\Z9*\^9"\
+MF?"\^?"V]0&F_O0-!;+OB4!"#__YO+.T``VP]@#PO`OPM@'?"&$``+_YIKGT
+M"RJ@^PH&O<1^RTX`LZ0!'=Y88```W>`9``"_Z7_?\)5`\?4`"*#I8-_X`-\`
+M+@``^5+$I3^260&VE`:\GP#?P"4```P4O)\0L@NRH[(:?E0W`+\?F!X!"?B8
+M"@K]^02]E/#U`;49!:`?Q^Q#Q,L!]!L,W0````$^&U4`W0````.8'P&]E+49
+M#[49";49#L?YZ)"9`;:4&\?_(;49![;T$HD``"#_V97]GP7>`",``+49!ICI
+MI)COHL2=_Y39".2>``\S\``(\>4`$+.P`"?9````(/_I];/4`"^PQ@3T#2C9
+M____#__YE-\````P/IU5`++OL]0`$K#&!/0-"]D````0_?D%M1\(L[``&-D`
+M(P``F)FB,Y``#.2O__\^O54`O?2)```(__F5M1D*V0`C``"8F:+PE/_T&PF]
+MQ#[O50"VE`'?5"0``+R?D%B9`?"4?Y2<"-D`(P``WS`9``"8GJ$_])B=H\?N
+M\,1"_Z;B]`@0^&%<`
+MF#FAQY[PIN+T"!_9+AD``#^?Q$G_\/3_O/F0INGT&`J[X@(^]58`V3$9``#?
+M+QD``#^9/__PE/_P]/^[Z0*F[_0(!?@(V91<```\GIB/```#Y-X`__WL!;:4
+M$/V?!/WI!8___S^)``#`_^_T_]F4_?D%M1\-^U'9`",``)B?!]YH(P``^1+T
+M,/B4^0*\GI"V]`*_D=E$(P``O/GPO_"R&[(*?NC#`+.D!PKX"#YK5P"SH`,Y
+MWM"K``#9````$;#A`-[___\`_P[D_>D%/92R&S"1!+(*?<0-$7[Z10"SH`(,
+MV0`C``"UD`3T,`C[$?D2LJ#T,/BRL;.D``;X"+,4``;X"+(*LAM^Z,,`LZ0'
+M"O@(/OE7`+.D`RW9T*L``+"1`-D````AWO___P#_#N3]Z04]E+(*LALPD01]
+MQ`TA?OI%`/0P"/L1V="K``#T,/BPD0#9____`-\`Z0``VY51`0"R^KN_`OWY
+M!`D!W@```"$PD03__N5]Q`TA?OI%`+.@``;X"/0P"/@`^1*\NA+T,/BRH+(;
+M?NC#`+.D!PKX"#Y>6`"SH`,*O:0^FU@`V="K``"PD0#9````(=[___\`_P[D
+M_>D%/92R&S"1!+(*?<0-(7[Z10"SH`(.V0`C```*`;60!/0P"/L1^1*\NA+T
+M,/BRH+(;?NC#`+*ILZ0'"O@(/L)8``H!LY`#.]G0JP``L)$`V0```!'>____
+M`/\.Y/WI!3V4LALPD02R"GW$#1%^^D4`LZ`"#MD`(P``O:2UD`3T,`C[$?E"
+M"?^RL[*@LL(+_R;9]`L+"0&[G022FP$_"<31_P0!/IE9`+N4`I2=`MDL3```
+MO-G0/]GPE`^FD?0+7UC?`;Q)E/\YS>3Z__\^DED`&`D!E*X%E*\"O.^BQYD$
+M]`L,V7Q2```^;ED`O.^BV?0-``"\J:!8J0'PDP#_N92FG/0;$+,@`"*8J0*V
+ME03T&Q@8J03$FO^SI`"Y&-D!\)3_]!N&O:3[03^[,[0`"+VD^``_K0\!Q+G_
+MNY\"LOP]Y)2?`MDL3```O/GP/_GPE`\FG?0(,B:=]!L--:X!-:L""@'X`!CY
+M`3*^,Y``'3*;\)3_NYP"E)\"V2Q,``"\^?`^QED`,KDUK@$UJ0*]I/@`/93T
+M,/SY0K*S_D`!LJN0`!6RQ++A(`TU"0$U"0*T(`>R"GZC60"SI``*^`@^J%H`
+M&`D"WRA,```]Y/"4_[:4`KR?D!B:`CZ>6@#$J?^S1`,6E)\%MI0"N_D"V7Q2
+M```^?%H`E)\%MI0"N_D"V?0-``"\^?!8^0'PDP"FD_0;#2`:("X*`3ZH6@"F
+MD_0,##*N&/H$,Z0`MR`:("Z]I/M%!)BI"9B_"0SPLJZVE1B5_1@^VUH`F*D.
+MLJ[_G/3PE`*X_P`@`+.4`!&8^0FR^K:5&*:=]`SBF+D.LY0`"ICI#K6Y#L6Y
+M!+B9`"`"M>D.^`"8J068OP4,\+*N\)3_Q/W_/BI;`)BI!K*N_YST\)0"N/\`
+M(`"SE``1F/D%LOKPE/^FG?0,XIBY!K.4``J8Z0:UN0;%N02XF0`@`K7I!O@`
+MOZFSD`!)#_#]GP2XG@`@`*:^]!L:F+L.E;D$]`L'H*OX`*"I^`"R_CYW6P"R
+M_9CI#O^=]+:5!+C_`"``LY``#Z:_]!ODF+L.M>L.^`"_J0_P_9\$N)X`(`"F
+MOO0;&IB[!I6Y!/0+!Z"K^`"@J?@`LOX^P%L`LOV8Z0;_G?2VE02X_P`@`+.0
+M``^FO_0;Y)B[!K7K!O@`F*D%]##L^1+%KP3'F8R4G@6VE`*\Z0+9?%(``+P)
+M`)@)`K*AN/\`(`*FG_4;C@"8O`C9"`X``!B[)_Y/`9`_0+6`GW_^F4M0D"F-D&\)4(M=D&
+M/LA<`+4,`C[(7`"]E+4)`C[(7`"VE03T"Q"0"@BR&WZ66P`^R%P`VI@6``"R
+M&WZ66P#9F!8``+^?L_0`"]F5%@``()^8&08/]_V?!+49!OL5%)BI"/0P[/DB
+MLJ''F1'T&PF]!#[570#?9!H``#_YQ:X$N.X`(`(2F0$@^9BB"<#L?M`?0;+`GP_^F4N)D`(`"8GPF8&0FV]1BV
+ME1BF^?0;"K4.`CZ,70"U#0(^C%T`O92U"0(^C%T`D`H(LAM^25L`F!\(F!X*
+MF!T)B?___?WY!-G____WM1\(_>D$M1X*Q-H/``'T"R;9P$D````!LAN[H`*V
+MI`6\J:!^WUL`F!D*C_\`__V?!+49"K(*^R44^2+9?%0``+^0LJ&S!``&^`C9
+M@%0``+^2LB\^`EX`O_FFD?0+#IC_`K/T`/8^#%X`^`B8&PB8'`&R&L>[:,?,
+M0WZ,@P"8#P+9?%0``/"D_[RJH*"?V9P6``"U`@*\J:#9@%0``*`!H)`)_W4)
+M`C^J/93?91H``#4)!C4*!S_Y$)D!(/G[(3YM7@"_J::;]`L*F*H"LZ0`]O@`
+M/H%>`+^IIIOT"PJ8J@*SI`#V^`"8KPTS\``3F*D,QYD9,Y``"97Z"/@`/:3X
+M`/0PW/F"L*$.&*D!L+$-L,$,L-$+Q)`/,P`!!O@(M*`-Q`G_E)8"V?P-``"\
+M:6!^M($`S:B\S**\\`)(N
+M`7#Q(><9@P$%"+"1$;TTMI0#O420F0:]!+"1#[#A"C[%7P"T\`JF#_0;"7.`
+M``9RA[20"[.4`!*R:N0;__]^B($`/DE?`+)JQ!L!?O2*`+3@"=\@3```O32\
+M_ICD?___NYH"II_T'@4#`;20"[.4`">TH`ZTL`VTP!'D'?__?BB8`$Z\`.1Y
+M__^\ZJ*FJ?!,"/!&`;,P`!:S0``2LP0`!W`1(9```3ZF7P"]!*8"]`LRM/`/
+M4!$!Y!G__Z:?]`P9DE4!O""2IEGT"`ZF`O4(5O^F(/0+#0H(LS``'#[L7P"S
+M0``2=.`AM)`,"@%@GC[N7P`*(_N%)/E2VO@-```+!'Z_-P#:_`T```L,?K\W
+M`-H(#@``"P1^OS<`V@P.```+!'Z_-P#:+$P``$N0`'Z_-P#:$`X``$N``WZ_
+M-P#:[$P``$NJ!7Z_-P#:F%(``$O<`7Z_-P#:P$D``$L@`GZ_-P#:%!,``$N`
+M`7Z_-P#:A%0```L@?K\W`-J4$0``2X`!?K\W`-K@2P``"T!^OS<`V714``#?
+ME!$``*"?/?39A%4``-X4$P``()_9E!8``""?WZ`1``"2^02@GY#_#*;^]!OV
+MWQ03``#9?%0``*"?O?39>%0``-Z4%```H)_?(!,``)+Y!*"?D/\,IO[T&_;9
+M@%0``+T$VI04``"@D$L``GZ_-P#9F`T``-J<#0``()`+7'Z_-P`/`=F<#0``
+MO>2UGP:]M+W$184$T2!,``!$7AJ#NML`T/@-``#:"`X```+_V?P-``"\R?`8
+M^0'$[0_PE/#_V94U^0&SY``E&`\!&*D!H!/P]/#_W_4U#P'PE/#_V97PE1`U
+MJ0$^I6$`L^0!)=D,#@``M10!E+\"O/GP&/D!D+L!\)3P_]F5-?D!/J5A`-\@
+M3```O,^0H)7?D!$``+SOD""2D.X!D,P$L^0#A3WTV946```@G[WTV9@6``"@
+MG_M1^1*SJ0.B`+"F`_0,$+.@`1NSK0(N`3XO8@"SJ02[`+.M!2`!/M9B`-\L
+M3```O00_^9`!`9#_!#"6`/0>'MDL3```M@0""P2\"0"R"GX<.`"R&@F`/F%B
+M`+(0LQ0PU3X,8P#>$`X``+WT/^F0\0&0[ASPE`'T&R:4^0*4\`6["0+9$`X`
+M`+P)``LF%(``+WT/^F0\0&0
+M[ASPE`'T&Q64^0*4\`6["0+9F%(``#Y28@"R'[,4$=X^#&,`W\!)``"]I+_Y
+MD*`!D/\@LY0`&]G`20``MJ0%"R"\J:!^'#@`L@H^#F,`L@JS!!#;/@QC`-[L
+M3```O?0_Z9#Q`9#ND?"4`?0;'I3Y!Y3P!$N1`+P)`-GL3```O`\`O`D`/E=B
+M`+(?LQ0*U;VD^Q'%J03T,*#Y8KB3`"`"LJ&8I@FRLOY``0M+(,?G>C`+\)LY`!!O@(
+MLAI^=IP`V0`H``&_F>1/___DGO\_IO[U&(,`IN+T&'V8&0;?____`-V$5```
+MO;3]GP3?`````_V?!;49!K_9D-T(LY0`1]J$50``/ZW?A%0``)2Y`[R?D*"3
+MV8A4``!2[@&5;!B\N_"V]`*\^?`)`KN``"`_<\$_P[D_9P%#^_][P3]G@7_G07_"\;$R0+T
+M"P['#P'9P%4``+6?`<3)!/0+.L0)!/0+,<0)`?0+(M[`50``W>`9``!8Z0Y_
+MW_&5`!#P]4!UZ0Y@WS[R90`)^_T)!#[R90#P!03$R0CT"SK$"0CT"S'$"0'T
+M"R+>P%4``-W@&0``6.D-?]_QE0`0\/5`=>D-8-\^+V8`"??]"00^+V8`\`4(
+ML,8`]1\"`K`&`/0>&+WDWP1@$0'<+AD``-W__P"./N%F`-X`@!$!O^_9````
+M@+W$W01@$0']^07;+AD``*#OW@```$#?__\`SCZ,9@"_V9#,`?V>!?V?!*#9
+MD-V`/[GPE/^FR?0(Z=W`50``6-D$VU@F``'4`!/#50+7)!=\`6```?91US@1@K2#Y
+M/C1H`+\MORF_+K\LQ`L"\93Q/;D?`/W^!-X``.(`_?D%_=X$_PZ4_?L%N9D`
+M_=D$__T%_PS&\,0"]0N^`-S`50``F,D%DID!L)8!]`U.Q`D"V^`9``#T"Q=8
+MS@0/`W^]6,D!M<\%\.4!/KMG`%C.!'^]6,D!#P7QY0`$M<\%\),`\-5`C\`B
+M`G7.!+R?D&"]MI0'OYD^-&@`"?W]"00^-&@`"?#]"039P%4``+60-SXT:`#9
+MP%4``+60.#XT:`")_P#__0D$V``"5#Q`UD`?9$%@``'6?!#XT:`#?$%@`
+M`)4)$'7P!77Y!CXT:`#X"#XT:`"]!*`@^R'T,/SY$L?9JK*QLL"SE#\OW`9``!8Z0Q_W_"5!/#U0'7I#&#?/B)I`+.4`A.)___@CP```__9
+ME#[F:`"SE`,2B?__X(\```+_V93_G]79L%T``%B;@[6:/+61/;60/K6=/_Y/
+M`;V4D/\(VJ!>``"R_*#Y?@`^`#.D`!#?5"8``;_Y\)4!H/G[%03T,/SY(M+V
+M7@``/RF]]/0P_/Y!`9`1$*`?Q)__Q_D!]!MVQ/D!]1O/`-E$8```OY_90&``
+M`'^;V?___P"R^OWY!+`1`/"S`-T````1#!'__=7>LT0``'Z&1P"_&;.4`!X_
+M*=[@&0``?^^]!/"5`2`I\?2__V#O/AMJ`+.4`A'?X!D``+T$?_D^!6H`LY0'
+M:?@(/AEJ`'ZK``+91&```+^?V4!@``!_F["F`/`,"_`&`=G___\`LOK]^02P
+M$0#PLP#=````(0PA__W5WK-$``!^AD<`OQFSE`(4W^`9``!_^?"50&#Y/AMJ
+M`#\I\)3]("D^&VH`O02R"O0P!/LE!/@`V2X9```_F?"4_Z:I]`@%^`B0KQ#>
+M$!0``0D!NY\$H.F]]-D4%``!H)^XF30#`*";H._X`-DP&0``/YF/0-W]\)3_
+MDID!O)K`B<`B`KRIH)2I![^=V01@$0&\KZ"VI`>\J:"_J9"J!+^IQYX,Q)\/
+M]!L'L^0`7)+Y`;"6`O0-4K/P#T^S\`A+L_`'3;/T``RSX`!%/LQJ`+/T!@JR
+M_C[[:@`.`K/P!3/DV0`"]!L)O>0^^VH`#@>S\`H@#@ZS\`L:#@&S\`04^`@.
+M#3[[:@`."#[[:@`.!93/`Y3)!KN?`M]`6```O)^0H)X-`;/@``P-`[/@`@8-
+M![S,\)3)!+N?`M]$6```MI0"O)^0-9T!^`#Y$MGJ8```/YDSD``&^`C9,!D`
+M`#^;V2X9```_F=T48@``Q+__W`1@$0'PE/_1````0+R?H(```#@^U6L`B4$"
+M$+SIX)3I!+^?B;[][[SIX)3I!*#?WB0D``&\GI"_GY"9!+7?`;^>M=X$F,D"
+ME>\0M=D"F,D#M=D#]`L%^`B_R9+/!!"[`9#,@/V1!/V>!;79!+___?`$_?D%
+MM=\$D-T4Q+[_INKT'IC[$=X0%``!W104``&_ZDD``?0P_/F"O]"@Z=P`%@`!
+MO92@V;_/V>I@```_FPF__?D$H,^@ZJ#0,[``!O@(V3`9``#3%&(``#^6O732
+M!&`1`3YY;0")00(0O!D0E!@$OXR_.9@K`;\DL,$)W0`"``Z.O_WO_9T$LLJ\
+M'A#]J06P1@#T'Q$+!;W4O02]5+WD/GUL`,>P#,>U<,=-T?"T#[(.QZD4]`L)
+M2?_]_:D$$FD!\)3_E)\&MI0#N_D"V4!8``"\^?"8_`2460H/_;;4$?W9!0G^
+M_ZF4_9`%_9\$3Q_^O.[@MK0%\.0"\,2`_9X%_9\$3__#_9L%_9\$_]D%,\0`
+M':"`QPG1]`L4M,`)Q\G1]!L+,FHR>WZ%-`"8/P3=__\`SMP````._TV4_PSD
+MW0```$#]_03]GP7]G@6@*9@[`<1J_PP!$&8!?API`)(M!+_9C````>0/``*4
+M'@3]G`6,___'_9P$_?D%">_]^02@WY@Y!-T8)``!O.W@LGKQE/__H.F8.0*0
+M=P&U*0*8.0.0,Q2U*0.0(H!^66H`WBX9``#<,!D``#_I/\_$8?_PE/_P]/^\
+MGY"F&?4>G/[>\!D``+_OF/E`\94``;7Y0+_OF/D@\94`@+7Y(/N%!+.D`!39
+M8`(0`;^?#O[]_@2@G_@`O908F70SD``OV:Q@``!_F;WDY)___S[P;0"2^0&0
+M[@']^02S]`#W&/ET\)3_INGT"P6]I-EE&@``/YDSE``?V60:```_F3.4`!2S
+MI`$0WV`"$`&_^?"5`:#Y^`#9)````;^?V:A@``"_F;NO`NR9Z`/_J:SX`+*I
+MLJ^PI@#T'BNRNK"V`/0>$__ZK/^YEO0>!?@`N:H!^`"YN@'_^JS_N9;T'_`^
+M8&X`N:\!LKJPM@#T']@^96X`E:\0E;D0_ZF1_[J@_;\!O+FPMK00O+J@^`#X
+M`/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/@```#YD/F@^;#YP/G0^>#Y\/Z*`?F@?M-O`/R@_J@`_/#\X/S0
+M_,#\L/R@_)#X`?F0_LD!QYETL)8/]!L3]#(8_LD!_9D&_IP`_)#X`?F@^;#Y
+MP/G0^>#Y\'[M;P#T,AC\\/S@_-#\P/RP_*#\D/@!````^0#Y$/D@^3#Y0/E0
+M^6#Y#!`0`:"?O^G?````@/V?!:#I^`"SE`$UW@P0$`&_
+M[]E(&0``OYW9____?_WY!*#OL]0`#D\-#MD$$!`!H)^]]-D($!`!H)_X`-X,
+M$!`!O^G?____?]V(B(B(_9\$H.G9!!`0`:"=D)D$H)WX`/0P_-G@8```^0(_
+MF?0P_,2?_\?Y`?0;"<3Y`?0+3MF<8```OY_9[&```'^;V?___P"R^OWY!/Y`
+M`?"S`)``"-T````AL`$`__W5#"'>OB,``'Z&1P"_";.0``;X"-_@8```/_GP
+ME/P@^7[^5P`*`7X%40#T,`3[!03T,/`*`OF"]##\?@51`-G`90``/Y[?`,J:
+M.]DT```!H)\/`9"9!*"?,^``"'XP5`#?____`-D`J0$`_Y_DWP```!'_[_7^
+M1@&P\0J]5-][K0$`O72[^0+8-````=D````AL/$,_>D%D&8TL.$+/IQQ`+UT
+MOXFSE``&^`C9#!`0`=\`RIH[H(^_DMDH&0``OYFSD`$&^`C9[!D``#^0,PT`
+MY@31>!H``#\9,Y``"G[)%``@$-E\&@``OY_9@!H``+^9IOGT&PF]%#X7<@!^
+MQ78`WT@9``"_^0$!II'T&Q.RD;V4H/E/#0[9!!`0`:"?V5@9``"_G]E<&0``
+MOYFF^?0+$-DL&0``/YDSE``&!0'9X!D``'^9\90`$/0+!WZ9!P#9X!D``'^9
+M\90`(/0+!WY`9``!_F?"4$/4+KP#0B5P``#\)O?2@;\2?_\?Y
+M`O0;-,?Y`_4;E`"TL`RTT`JP80#:`*D!``P1W@(!``!^AD<`OVFSE`!U/PGP
+ME0@@"3XF=`!^`*D!LZ0`"KU4/M!S``$!V<`V``"_F;.4`4_0X!D``'\)\)00
+M]!M!LU0`/K2P#+30"[!A`-H`J0$`#"'>`@$``'Z&1P"_:;.4`@]_"?"5$&`)
+M/B9T`+.4`!#?B5P``#_Y\)3S(/E^7U``V6AF``"8F0*SD``&`0'=X!D``'_>
+MY.D`"/0+'-E88```OY_DZ?_W8-D!`;/P``I^-D\``0'9T&```+^9LY``"WXR
+M)0#]&@79L&```+^9LY``"WZD)P#]&@7D.0`!]!L]Q#F`,Y``#]GJ8```/YDS
+MD``LV>`9``!_F?"4(/0;'MGN8```/YDPE@#T'!'9H&```#^9,)8`]1W9`-J@
+M7```?BRQ`+.M`,P`T.!@```_":!J\)0!]!M!V9Q@``"_G=GL8```?YO?````
+M$=G___\`LMJP80#]V03PLP#]WP4,$=Z^(P``?H9'`+]ILY0`"S\)\)4!(`F_
+M:;.4`UY^6W@!V9Q@``"_G=GL8```?YO?````(=G___\`LMJP80#]V03PLP#]
+MWP4,(=Z^(P``?H9'`+]ILY0"$=_@&0```0%_^3Z*=0#?X&```#_Y`0'PE/T@
+M^3Z9=0"SE`(4W^`9``!_^?"5(&#Y/IEU`+.4!P;X"-#$8```OPJSH`!'?BEN
+M`+WTF/D`9``!_F7.0`$?PE`'T"PU^`#H`LZ``!@$!V>`9``!_F?"4
+M`O0+*=KD&0``"P)^H3@`LZ``&WX;K@"SH``*`0$^6'8`VN09``!^V#@`V>`9
+M``!_F?"40/0+#'XE:0"SK0`Q^[,=`"S[D'>CP]!\)`;N?!/V>!/0+5-E8&0``ORJ_G9"I`<2;
+M'Z:]]`LPOQF.'P#_Q,__MO0&_9X$__GE/I-W`+Q=^)#9`<2='Z;O]`L9#/0+'IBO!9BN!MG____[_?D$B?]__K6O
+M!?WI!+6N!IBO!IBN"-P$80``?\V)___]_?D$V?__`?"UKP;]Z02)```,_>D%
+MM:X(<]``&)BI"\3?_[:5&*:?]!L)Y=D`@&#)F*D&W____P#]GP2UJ0;X`-GP
+M&0``]##\O)KHO=0)$OZ=#/0R$O0R$O0R$K/=`8(`V2A:``"@G;_IY)__#_0;
+M(K/4`0[9*%H``*"?]#$2O92]U+"1`+WD?C2Y`#[Y>0"UZP&]]+7O`[7O!+7O
+M!;7L`K/4`0[9*%H``*"?]#$2V3X:```\FNC$O_\)![N?`@\!O/FTQ.G__[F4
+M]`L%^`C_Z_79/AH``#R?J3[Y>0#X"#Y]>0#T,`3X`/DRLJ"8HPA^X7@`F`D(
+MQS\2QYIHE9$LQ0!#=\E&@``/JYZ`-\?&@``//J8$)D!//FIV3X:```\FI@/
+M`;OQ!/"4___YE/0+$MGP&0``O)J8M9\(/O)Z`,4)!+B<`"`"]!L%^`@+![NQ
+M`GY6>0#[,?DRTE@9``"_+]E@&0``O)\XP"8'0C9```*"/_9E/0+(MY8&0``O^^)```0"@'_V960_P&U&0CP
+M]!^@[S[W>P"R&G[^>0`^YGL`O00)$OZ0#/0R$O0R$O0R$K,$`0O9*%H``*"0
+MLAJ]M'[2GP"S!`$0O?39*%H``*"?]#$2WU@9``"_^0H!O)J0\)0?H/G[,>2N
+M___'Z<:2GP&P]B/T##O$Z3^2G@&PYA_T#07X"+S_D+R?D-_8!@``MI0$O)^0
+M/)Z8,)8`]!YA\)('E)H&V4`X``"\J:#X`.2L___=0#@``+WDVP```/^_W__[
+ME/0+"?@(/F-\`+/P`";?0#@``)3J!KROH)BI"YBO#+:5&+;U&[:4!OV?!:;)
+M]`L/D.X!D-U`L^1&QKVD^`#9`!00`;^9LJ\*`?V:!/0+.^3Y__]R^M[Z80``
+MD)\0E?D0]`L9?^EFJ?0,![VD^`"]I&:?]`T5"@'X`'_IO:3PDP"FG_0-!0H!
+M^`"]E/0P_/Y.`:#IV1@4$`&_G]F@7```M9H\M9L]M9P^M9T_Y/L`!/Y,`=J0
+M70``?@`^``D!\*3_]`L)L*8"\)P+LIKT,`3X`+_)O[_YP"SI``&^`B8J0'P
+ME`CT&QN_J<>9BO0+$YBI"H_]_P#QE/__II_T#!"_64\`__V?!/0+!?@(OSK'
+MJ:JSG2"?`)()`K"6!/0-#+,`(@FS#22-`,>DD)6B&%0J!OVD!7[Y>P"SI``&
+M^`B8J0''G4/$W@'T&R6_J<>9BO0+'9BI"H_]_P#QE/__II_T#0V@?J!>`0$^
+M[WT`O13$V0.SE`$(LP0%/;(JLDM^_K@`LZ``#'Y:N``^,WX`V>1A``"_F;.0
+M?Q:_>K];OVR_/7X+N``*`3[8?@#X"#XS?@"]%+\_Q_FJLY0@?,?YD)7Z&':D
+M!OVI!7[Y>P"SI``&^`B8J0''F2.SE`%K];OVR_/7[>?``)
+M`K"F`/#\"_#V`;R?HOMQ]##PV0`4$`'Y@K^1_D@!_DOXJ_>[]LOUU^.&@`/HQ_`+,@
+M``;X"+,``!JS#0*``>4?``'9`!00`:"?OY$^\(``LHJR>[)LLEU^)7T`LZ0!
+M)-WZ80``?]GE'@`!WP`4$`&0,P&@_E"9`;_Q8-D^[H``LZD".`'9."@``=X\
+M*``!OYV_Z=^@7```O_"S*_\#T`!8^@4)\/_9Y'"F`?0-'UC_!,39!V:?]!L]
+MI@[T##B0"1"FGO0;,#ZW@`!SK0&@`-DH*``!OYFSG0&4`%CY!'.=`(P`F/D$
+MII[U"X(`&/D@,Y0`>[,@``;X"-$<%!`!OQGPE`+U&[4`W?IA``#;H%P``'_?
+MF+P!V2`4$`&0,P%0_P'$SO^@GF#?ML4?Q0D"Q,\!_9\%H!ESI`$EF+\%,,8`
+M\)P+F+X$MI0?_9\%6+\,H+ZUN0%UOP4^X8``D`D0H+E2J0%UN04^X8``OXJ_
+M>[]LOUU^WGP`LZ``0MWZ80``?]_E'@`!V0`4$`&0,P%0_P&@GF#?V0`4$`&_
+MD;`V`?0,&KT$DD0!"?^F2?0+$,09`?4;"_X^!X$`O02R"ON%$+V4M9,+:E$)"9`;R:H/@`
+MF*D$OZ^VE1"5^A"SL``0X)_H`Q*I`[SYI?@`\9!`'[R:I?@`/90@J2"YWT`X
+M``#=P$D``+_YLY``+YCY`9C^",>9`Z;)]`L'L\0`'2)``!`M:X!M:D"\,4!H*R8OPN)?P#_
+M_9\$M:D#F+\,V?__#_C]GP2UJ028N0FUK@>UK@:VE1BUJ07X`+*N"?^SL``U
+M,\``+\RZ?92O`I2I![N?`KR:D*:;]`L&D*H!O.KR"0&[G`22F0']^02@WSZO
+M@@"]E*#9"@'X`)BI")BO`<>>:#/D`!3'^4,PE@3T#0K:^`T``/@`&*DTQ.K_
+M,Y``$;:D`MD(#@``O*F@^`#9_`T``+:D`KRIH/@`F*L)Q[^$<_0`!O@(V0`H
+M``&_GMEV!0``/YD8K33P\P#QY/\_=I0.DO\!?)[@E/D%MO0"NY\"WQ`.``"8
+MK`B\GY!8GP$SU``*
+M%GOJ`I6_&`D!NY\$4ID!_^FD^`!XZ?]_`'R:HO@`\*3_\+3_N[H"\+:`Q[H'
+M^``SM``0/:2PQ@3T#!L*`?@`&*DT"@0SE``/,+8!\/P+"0,\GZ+X`)BY"?0P
+M_/F"LK3T,/RRI;+!\)0/]!L%^`B820C^2`'^1@&8$!7'F6B]Y)22`I"(*]D(
+M#@``/32\*2"09BH'`3Z?A0"S"0BB`+`&"/0,$+,``1NS#0>+`3YZA`"S"0H-
+M`;,-#7T!/H6%`#43`C43`1A.)[(:LBL@'GZC60"SI``*^`@^K(4`&!D"F%\%
+MWBQ,``"R6_"4_[N0`K:4`KR>D,?_C+49"93Z!=E\4@``MO0"NZ\"O*F@M1H,
+MD*H,?I9;```'#@$^GX4`F!\,F/D"MI4$]1L8`9CY`P`(MI4$]0L.`3Z;A0"8
+M&0R830FR*@P#6)L!((,@8[;5&+!A`/"S`+*.?@M:`+.I`-X`/VDSE``FF!X,
+MF!\)&.D$\)3_=?D!(..8&0E8F0%SG0"\```*/I6%`#"6#_0,+9@>"O"4_Y2?
+M!;:4`ACN!+OY`ME\4@``O/GP-?X$F!D,``T."""3/I^%`/@(/H^%`#43`C43
+M`1A>%+(:LBL@'GZC60"SH`!B&!D"&!X!\)3_NY<"E)\"V2Q,``"\^?"U'PDS
+MY``1&/X!``T@+@X*/GJ%`!C_`<3I_]XL3```NY<"MI0"O)Z0-9\!F!\)``T.
+M"C_Y\)1_(/D^GX4`O90*`:!9/JR%`+(./I^%``X(/I^%```-#@>FX/4;5/[X
+M"+VDM1X5]#`$^X4$^8*]]+*QLJ*RQK^P&+4(O42]-`CPO70^98<`LPD#JP"P
+M!@/T#!"S``$BLPT"AP$^+X8`LPD%]P"P!@7U",\`LPT'<@$^.8<`6&D!??1U
+M'P-U&0(8&1$SD`$,L@\%_SX@A@`8&1`SE`,/L@^U)P8``CYEAP"R#[4G#CX@
+MA@`8&0A8'P-8'@(-`;O9!.3S___PXP`^:X8`F!D#_SW]6)D!\),`IOGT"PJ0
+M,P$^:X8`=1,##P(``SYEAP"F/O0-VP\"``<^98<`LFJR.PP!,EU^_E@`LJ2S
+MH``M/ZD8'P@VE00FG_08$A@9$3.4`1FR#P`$/F6'`":?]`T+L@\`!3YEAP!8
+M&0.R#SXMAP`8&1`SE`,.F$D"M2D&/M.&`)A/`K4O#E@9`P\$/BV'`!@9$1@?
+M$#.4`2^82@(S]`,6_:@$LBNXJ@`@`'[Z6@`^*(<`_:@$LBNXJ@`@`'ZK6@`^
+M*(<`D$H(,_0##K(K?I9;`#XHAP"R*WY)6P!8&0,/!5"9`0`"=1D#/F6'`!@9
+M$3.4`3<8&1`SD`,.F"D.D"HX/E>'`)@I!I`J&+.4`!P)`J"I/G.'`+(/IO#U
+M&V;^H!^]I#YUAP`*`?N!^4+PM/_9"`X``)2Q`K*BO!D0O00#\`0"/M^'`+(:
+ML@L,`0W_?OY8`)BI`K.4``;X"/V3!+WDN)\`(``^PH<`IO+T"QVR_KC?`"``
+MF/D&_Y/4MI4$]!OKIO+T"P7X"+/@``>UY`:0``%8&0'PDP"F"?0-K)@I!0WP
+MVP````BRW,>9C)2?!;:4`KOY`ME\4@``O/GPF/X"V9@6``"@GKV4_>T$M?D"
+MN.X`(``^28@`O^G]G`2XF0`@`)B?"OW[!;6?"ICN!I7I!/0+#__LE+B>`"``
+ML^0`W`\!V946```@G_M!F*D)]##L^5(!`?"4#[R1\M[`20``E/`%O`X`F`\%
+MWMQ+``"VE`*\GI#'_XR_E93Y!;;T`KR?,M]\4@``Q0D$O#\PN)0`(`*RHK(+
+MD#H,?I9;`-F5%@``/Y^]E+4)!C/]``("F#P"E`K:4%/V?!-___P___=\$
+M_9T%M0D%/BR*`)@I";:5&/0+&@GP_\F4N)D`(`"8GP:U#P:UE`8^+(H`F`T%
+MS%\'#O`)#[+J.Y\"_\[DWP``\`#$F_^XX0`@`+:4%+WD_9\$W___#__]WP3]
+MG06U"04^KXD`F!D%O=3'F72FF_0,')@9!O^:]+:5!/0+"+C]`"``LAZRT;,4
+M`-ZSX``KF.D&M0D&M>0&QYD#]`MIF`D&#_?]GP2U"0:8Z0;PE0BUZ08^+(H`
+MM0P&M30"&"DGF"P(_D\!D/\8-?D("0'>"`X``#7Y$:#Y"0.U\P,U^1"R^\?,
+M:+(*ML0"O,[`?K*%`)@9!@_W_9\$M1D&F`D&\)4(M0D&F"\)E?D8]1NN`,?Y
+MA)2?!;:4`KOY`MGT#0``O/GPF/\"E?D$]!L)O>0^BXH`"?"]Y/WY!+*;N/\`
+M(``^AXH`F/D.F/P$O?3_F]2VE03T"PBXWP`@`)7)$+SIX+/T`.28/P()\.SN
+MNPV0[@']^02X^@`@`)BI!<>9=*;I]`TYF"L(Q[MH?G>'`#[@B@"8+@K9F!8`
+M`+^?V0````C]Z04)\+4N"OWY!+C_`"``F/X&M0X&M?0&^U44F*D*3P#__9\$
+M\)4!M:D*^`#T,/SY`C[CBP`_V5C/`?"4
+M#[QIE/"3`/])G6;Y]1N.`)C/`Y7Y!/0+/?_SE,0+_[B?`"``/I6+`)CY";:5
+M&*:;]!LCF/D.F/T$O?3_D^2VE03T"PBX[P`@`)79$+P9$+/T`-F8SP*5^03T
+M"UW_\Y3$#/^XGP`@`#[8BP"8^0FVE1BFG/0;0YCY#IC]!+WT_Y/DMI4$]`L(
+MN.\`(`"5V1"\&1"S]`#9/OR+`!C.!,3I_Y2?!;:4`KSYPMGT#0``O,G`,^T`
+M2/\2``$)_R8)]1L,_[(:^W4$F*D)QYF$E)\%MI0"O/GBV?0-``"\Z>`_Z?"4
+M`?0;!?@(F*T(Q]D1]`L'^`CX`)CO`XG___?_V92UJ0CP]0+%J02UKPZXF0`@
+M`K7I`YBI",>9:/0;/YBO"=F@20``\/0/MO0%O/GPF/D%Q?T$N-T`(`+'F8R4
+MG@6VE`*[Z0+9?%(``+SIX)CI`_"5`K7Y!K7M`_@`&*DTF*\("A(SE``/Q_EH
+M"@@SD`(&"@+X`/DBLJ!^GXP`,J$SI``*O:0^%8T`L@I^]((`F`L(F`P![:,?,0WZ,@P#9G!8``/"D_[RJH+RIH#^O&*D!"@$[GP+PE(`SE``4Y"__
+M_\09_[VDIOGT#`4*`?LAV8!4``"_GSXVC0"_^9B9"<>9A*:I]!L'"@'X`)C_
+M`K/T`.R]I/@`V0`$``!8G[KY@K*3"`'P\P"]1,W_`]:<#0``O/^0NX\"O)]P
+MO50^PHX`WY`1``"\3Y`_F=_,!```Q)'_O'&0MI0$O)^0M94#M6D3H)6UE0&U
+ME0*S%`!QW_@-```_^3.0`"]8.[JR^@P!#?_PLP!^_E@`LZ``&YBJ`K.D``;X
+M")AO$U@YNJ#Z\),`M?D#WP@.```_^3.0`#!8.[JR^@P!#?_PLP!^_E@`LZ``
+M')BJ`K.D``;X")AO$U@YNK7Z`O"3`+7Y`]G\#0``E!("O"D@&"D!QYD&]`MF
+M6#FZ\)0'LY0'7;,0`0;X"`\!O!^2E)H"V0P.``"\J:"\&)+?7`4``)20`[P/
+M`*`%M04!/ZDSD``N6#NZ#`$-_^>[@P&\O+!^_E@`LZ``&)BJ`K.D``;X"%@Y
+MNJ`*\),`M0D!LQ0"#5@YNO"4!_0;/#\I,Y``-U@[NK,4`@=VM0.R*O"S``P!
+M#?]^_E@`LZ``')BJ`K.D``;X")AO$U@YNK7Z`?"3`+7Y`Y!$`=^4%@``/_GP
+ME/^F2?4(FO[[@?&D_S_QM/\_N[H"\;8`(,>Z#?@`^8+9>%0``+*ES(``.F`\"M2\"
+M/H>/`)@)`J")OV^8"0*U#P*@8+*0/IR/`+("F``"LPT`:/_[@?DRV815```_
+MF3.0`&;PE/_>A%0``)*;`;W4O<0#\-+___\`?12]!#X#D`"_[[/P`"U8Z0)F
+MFO0;'?WS!+C_`"``F/D&=>$"_9($M?D&H.`^_8\`IMST"`6RW)#=`9#N"*;;
+M]`W)$,\!V815```@G_LQWP`$``#9=@4``'&F_C_T#!(_F7:4#GRID%"9`3X_
+MD``_F1"9`?"4`7:4#G7YNO@`F*D&^0*RH+:5&+.0$@BSE`%0V7A4``"_GSYK
+MD`"_^::0]`L.F/\"L_0`]CZ@D`"8#PC'^0WT&R>8#@;9__\!\/_YE(\```K]
+MGP6U"0C9____`/WI!+4.!CZ_D`"R"GVT?NB.`+(*?M9<`+.@`!'9`"@``;^9
+ML@I^VET`^P'Y`MF8#0``/YGDK/__WI04``!]I/"4_P`!E)T$O-[0/A21`!CI
+M"?"4`?0+)YCI`Z:;]!L?&.D(6.\#O`F4\),`_\F=9OGT&PN_Z5B9"7R:H)#N
+M$*;M]!O.^P'Y$G*P\+0!?O2*`'*AO;1R"G[!D`!\&J#[$?D"V9@-```_F7*L
+MWI04``!]I/"4_P`!E)T$Y\N#`;S>T#Z3D0`8Z0GPE`'T"S`8Z0A8[P.\"93P
+MDP#_N9UF^?0;'+_IF)D$MI40S)F\$)D!\)3_9LGT&`90JKR0[A"F[?0;Q?L!
+M]##X^8*T8`RPP0FRM;+7,NA]M+*@/U)^](H`"P&RH[(*?O2*`+"A"K-D``JR
+M.C[RD0`8"@'9"`X``'VT\*0/MJ0"O*F@?O2*`+PZ,'VD?C61`/"C`+RCH-F8
+M#0``/YG?G10``#U$\)3_E)X$O._@/B*2`+^9II;T&PX_^?"4`?0;!A!$`9#_
+M$)#Y`Z;^]!OF?10^JY,`O^F8F0$SA``9QYE#O?0PE@3T#04/`;20"::?]!LG
+M&.D(\)3_0?__^[G`2F^?0=";VD/LN3`,2__]Z4%```E/D$
+MO)Z0OYF8F02VE1"\J;"FM_0(";*K/NF2`+S_D-V<%```MI0#O)V0&)X!MO0$
+MW9@4```0(@&\_?#PY0%U\0$UG@'$"?_>E!0``)2:!+RNH#Y:DP"_\)@)`3.$
+M`!G'F4.]Y#"6!/0-!0X!M)`)II[T&S48^0CPE/]FR?0;*AC]"<39`?0;(9@)
+M!+:5$+RYX*;G]!@3Q=D!=?$#-?D)$"(!/DV3`+*^D/\0LNNF^O0;IU#,`7#&
+M#_0,#-^4%```/E*3`%`1`;-@`"$+`7(:?L&0`'*@24G0,^?I0`
+MQ+D!]`MELT``,9@_!;&FNP#T#1:\_?"\_O`8^0&2JKP2F40^8)0`O/WPO/[P
+M&/D!/)J0/G.4`)@_!;&FNP#T#1F\_?"\_O`8^0&2JKP0F40U^0$^>)0`O/WP
+MO/[P&/D!.YH"-?D!O:20[@&VM0&SL``(LZ0`COM!&+DT^3*RH+*RF+H$,Y0`
+M#96C$+T4/JN4`+*Z`0%^M($`LJ.8"0J8"@@-_[W$6)L!\+,`?OY8`)@.%K*M
+MINKT&QU8Z0@8[QA\DY`0_P%UZ0@U[QBS$`!\/D^5`+/@`$T8Z1A8[@@UJ1B8
+M#Q9UK@A]Y#_Y\)3](/F8"18UGAAUG@BS$``HF`D6F)D%LY0`!O@(F-\%/_GP
+ME/X@^9@/%ICY!;79!;V4M?D%6-D(&-\8/]Y\DY`0_P'PY0)UV0@UWQ@@WK,0
+M``ZRVK(K#`%^SI,`^S'T,/SY@K*Q]##\LJ*8L`9^LX(`_D^`+`&!_0,$+,``1NS#05R`CX6E@"S"0HX`;,-
+M"V0"/A*7`)@I",>9$?0+!?@(-1,"-1,!&"DGLAJR2R`9?J-9`+.D``KX"#XB
+MF`"8+PD8&0+>+$P``+(KQ_^$E/H%MO0"\)3_NZ\"NY8"W_0-``"VE`*\GI"\
+MKZ"U&0FU&@J0J@Q^25L```4.`3X1F`"8'PJ8*@F8^0*VE03U&^L!F/D#MI4$
+M]1OA`<>JA'X7C0"SK0#6`;(.``<^$9@`F!D*F"T)LDH,`EB;`2!S(%.VU1BP
+M40#PLP"R?GX+6@"SI``&^`@_7S/T`""8&0J8'PD8F03PE/]U^0%PE@#PG`N\
+MB0(^MY8`,/8?]`PFF!D*\/3_E/X%MO0"&)D$N^\"``O?]`T``+SOX#7I!#ZW
+ME@#X")@9"IB?!;/P``L_^?"4_B#YF!\*#@<_^?"4_CX,EP`8&0&8'PDSE``-
+M&/\!($\^`)<`&/\!\)3_WBQ,``"[E@*VE`*\GI`UGP&8'PD."@`+/_GPE'\@
+M^3X1F``8*328*@0SE``-E:,0O00^+Y<`LBH``7ZT@0"RHY@9"K)*O<0-_UB;
+M`?"S`'[^6`"SH`!JF!\*IJ_T"T,_^?"4`O0+.QC_&#^I-:\8F!\*\)4"(*E8
+M_PAUKPBS```BF*\%L_``"S_Y\)3^(/F8&0J8GP6UKP4_^?"5`2#Y&*D86*\(
+M$ID!>_,"-:D8=:\(LP``#+(KO<1^SI,`F!H*/ZGPE`'T&P:UJ068*0C'F6BS
+ME`%@F"D!QYGHLY0"5MF(7```/YTSU`$@O>39$!0``:">3P`!D)D$H)^XF?0!
+M`*">/OF7`#/0`"L2WP'9B%P``""?/B"8`+(./A&8``X%``NFX/4;<_VU'@:]
+MI#XBF``*`?0P!/N%!/DR/ZFRLK+!LM,SD`!"LLL-_[W$?OY8`+.@`#28H`6S
+M```MLBI^AUX`E!D#O#F2\*3_MJ0#O`J@O*F@&*E),Y0`!QBI`<2:_SYVF`"]
+MI/LQ]##\V9@-``#Y@C^9??2RL[*E\)3_E)X$V9T4```])+SIX/Y)`9"9)F"?
+MWYT4```_L3[!F`"_F;.4``\_^?"4`?0;!A`B`9#_$)#Y`Z;^]!OG/E69`#_9
+M\)3_[QLE/0>?=V4%```Q/#_E`D$O)V0OYNR6K),#0%^H5X`LZ0!8-^<
+M%```W9@4``"\`)"VE`.\GY"4#P08G@&\_?!_31`1`?#E`36>`77]`3YDF0#^
+M1`'8F`T```?_!@&01"8F$O0+%3^*W9P4``!,_P`]M`__/OF8`"`Q"@$^A9D`
+MO:3[A02SH``.F+D"M:D"/J"9`)B_`MF`5```H)_9?%0``+^?WF4:```*`;6_
+M`C_OH)L2_P$@[WZY;0#X`/0PY-ED&@``^8(_F?0P_+"A#3"Q,S.9`,D!WP`$
+M``!8^;HRN/"$_]=0&0``\),`S94#?CZ-`+20#<2-(,2.`=2>%@``D)D!\93_
+M/Y26$-D$``"`_VF5L)$.V0@``(#_:96PD0_9!0``@/]IE;"1$+Q5D+R5D+TD
+ME)$$TR1:``#9S`0``+#1"[P9$+#A"GZTN@#?``0``%CYNI@?`_"3`*;Y]1O8
+M`+,M`($`OQRSP`!,M)`*LY``1;2P#K`A`+VDO=2]Y'XTN0"SI``//SGPE0$@
+M.3ZXF@#=G!8``#\Y/]]TT!K>3AD``/"4_B`Y8.T0_P'>G!8``"#OF!P"L\``
+M*[3P"[/P`"0-\/_-E+B9`"``F)D%M+`/O:2]U,>9=+WDL)$`?C2Y`)@<`;/`
+M`%"0(`&\@)?PE`'T"T.TL!"]Y+(JL.$`O=1^-+D`LZ0`$C\Y#P&[\`3]GP4^
+M-YL`/T\_/G30&@D!$/\!NY`$8'WPE/\@3SF9`/V>!"`YD"(!D'<"D$0"D!$0
+MLRT#"/\TX#,SX`!1WUP%``"47`/9``0``+S/P%B9NIC/`?"3`*;Y]!LRO\RS
+MP``M"0K;"0``@+"1`/]KM0H!O=2]Y'XTN0"SH``2WYP6```8^0@0F0$U^0CT
+M,`3[A1SY@M1.&0``LJ6]-`@!LD??)%H``#_Y\)3_NY,'\)0!]`LM?TGPDP"F
+ME?0+([Q9\J:5]!@*DO$!/N2;`+CQ_S\`L!8$]`T+`00^\IL`O12\@V2])#XJ
+MG`!_2?"3`)"9`<2?!^20_S^S-`,/L_``"W5P`SXGG`!R"GX4D`"R"C)K?L"9
+M`)`B`:8A]`C/D#,!D$0"LST$?O_[@=DP`!`!OYGY$K*AF*H$\)0$]`LE,J#P
+MI/]^`@<`LZ0`&1@9"`H2,Y0`$@H(,P`"#`H"/G2<`#VD^Q'99!H``/0P[/DR
+M/Y^RH1#_`2"?F*D,QY-TLS0$89BO"]DP&0``/YG'\O#PE/^2F0&\D@"\`/"4
+M"02[GP+?1%@``+:4`KR?D#^9,Y0`%K(JO;1^8"0`LBJR.[W$?A,@`+P`\)0)
+M!+N?`M]$6```MI0"O)^0/Y\0_P$@G]ED&@``/YDSE`$XWS``$`&_^=Y.&0``
+MO:3PE02@^;_Y\)40H/G9`"@``;^9\93_/W7I`V#I=>D!=>D"?KEM`)@9"<4?
+M!+CR`"`"QYF$E)\%MI0"O/D"V?0-``"\"0`_"?"4`?0;!?@(D`H,LAM^25L`
+MO928'PFU&0X_";;U&,>99*:?]`L%^`B8#P*5^03T&S6U`@*R&GZS@@`8&2?^
+M3P&0_Q"RK#7Y"`D!-?D1H/D)`K7P`[+[-?D0LAI^LH4`/L:=``GP__F4N)D`
+M(`"8GPZU'PZUD@Z8'PB8'@:8'0G9__\!\/WY!(D```K]^079____`+4?"/WI
+M!+4>!O#4#_0+&K(:?EB(`)@9"H__`/_]GP3QE0`"M1D*^S44V0`H``&_G_E2
+MV8!4``"])+^1Y//_/P7_U#`9```^#)\`6!D"OQ!FE?0;0Y@+")@,`;(*Q[MH
+MQ\Q#?HR#`-F<%@``\*3_&!\'O*J@O*F@&*D!.Y\"\)2`,YT`L@"R"GZ?C`#P
+MI/]\HZ!U&@)8&@)R.W[4C@"SK0">`#X5GP"8"0C'F0WT&PVR"GYVG``^HIX`
+ML@I^#(P`F`D,QYETLY0$5Y@/"S])Q_KP\)3_DID!O)H`O`#PE`D$NY\"WT18
+M``"VE`*\GY`_GQ+_`2"?]!L)"P%^8"0`O`#PE`D$NY\"WT18``"VE`*\GY`_
+MF3"6`/0?!?@(F!`"LANR*GZ(F0"R`;,=`"'_/BJ?`+(2F!$"/@R?`!@9!C.=
+M`&C_/IR>`/M1
+M/A*@`+_III#T"PZ8[@*SY`#V/I"@`-^<%@``Q*G_O)F0O)^0#_]U[P(_F37I
+M!CZEH`#X")CO`MET5```H."@G]^<%@``Q*G_O)F0O)^0#_]U[P(_F;7M`C7I
+M!MEX5```H)X^I:``V8!4``"_GSY_H`"_^::0]`L.F/\"L_0`]CZ?H``)`37Y
+M!CZEH`#9=%0``+^>L^0`H3XVH`"R"GYVG`#[`?DBLJ*RL#+!"@%^S6$`LJTR
+MJ3.D``SX"+VD/C.A`#\.\)3_#`&[G`*4F@+9+$P``+RIH#/@`$K?+$P``,3I
+M_[N<`K:4`KR?D#^9Q!__\)0/IOGT'0HUK@$^)*$`&"D!WRQ,``#PE/^[G`*V
+ME`*\GY`8GP$UKP$UG0$^)J$`(`T_J<0?#_"4\/WY!2"O^R&8J0CT,/R]Y/F"
+MQYEH]##\E),"_D`0H!/G&C
+M`!@N+#V4M2,(-2D!("XU*0*R*K([?J-9`+.D`!>8*P@8+"RR*GZGH`"U*@D^
+MX*$`&"D"WRQ,``#PE/^[D`*VE`*\GY"U*0E8+Q=8.0%F^?0-!G4_`0X!``(^
+M9J,`6"47F"H(&"TL/92P<0`@>2!IY%O__PP#LFY^"UH`LZ0`#+(.``,^9J,`
+M/VFR#@`$-2D\\)3_E)\%MI0"N_D"V7Q2``"\^?"U+PP^9J,`L@I^S6$`3.0`"7P
+ME/^4GP6VE`*[^0+9?%(``+SY\!CY!#7I!#7Z!#Z@H@"8*0EUF@$U+3P.`P`$
+M/F:C`/@(L@X^9J,`"@1^S6$`!/WY!;4/!9A."8G_#_[]^00)\,0=
+M#_WI!/W>!;5-"1@I/(X`\`'%#`2XS``@`K:4#/V>!/WY!;4/!;4L#I(1`;4@
+M#=_@2P``#@2\^!D`!3YFHP#X"`X$/F:C`)@I#)B?`Y7Y!/0+"9@I#;6?!I@I
+M#)@O#@X%``BUGP.FX/4;`_ZU+A2]I/0P!/N%!/0P\,6I!/F"N)D`(`+T,/RR
+MH_Y(`?Y&`?Y'`;*QL,$+LM6PD0J8L`:]])"(-I!F-Y!W,#Z%IP"S"0;,`;`&
+M!O0,)+,``E&P!@+T#`RS#0&X`S[\HP"S"03U`+,-!:H#/NFD`+,)#+T"L`8,
+M]`P,LPT'E@,^'J8`LPD-@`.S#0Z(`SX`IP`8.0*R#P`"-1DL/H6G`)@Y"+(Z
+MQYEH-1D<,I!^LX(`M1H(,P`""Q@Y-#.0``T8&2P2F0,U&2S\$
+M\93P`0_P_9X%_9\$M3D),]``'I@Y"-S\#0``QYEHMI0"O)R0&)\!\/5`-9\!
+M&!D<#PZ<`/928$`@U&0$U&0(8
+M,R>R&K(+(!-^HUD`#@&SH`!V&!D"&!X!"@'PE/^[F@*4GP+9+$P``+SY\+4?
+M"3/D``T8_P$@#SY>IP`8_P'$Z?_<+$P``+N:`K:4`KRH-D^D*<`L@\^A:<`#PP`#:;P]1LG_+4?!KWDLNKT
+M,`3[A1`0Z0'?E!8``-R0$0``(/G$Z?\\P)D^7:0`WT09``!__]E@$``!OYGP
+M\@^V]`/'F:B2F2"VE!"\GY#?``"F#KR?D.R9`/"4GQ"VE`R[^0+9-``0`:"?
+M^`#Y(K*OLL+_RP2SK@`,#[(+?L<.`#[JJ0"XJ2`$`K&6@`#T#`VR"WXZ+@`^
+MZJD`N*D@"`*PEB#T#1FXJ3`&`K"6//0,(KBI.`8"L)84]`P-L@M^U[$`/NJI
+M`+(+?LED`#[JJ0#9`"```;RI$+.I/+,`L*8\]`PCLZ`D5+"F)/0,#+.M('L!
+M/J^H`+.@-&^SK3AN`3X-J0"SJ5BQ`+&F6`#T#!&SJ5"(`+.M5%0!/BJI`+.K
+M``8(`;.O!`9%`3YRJ0"R"G[P#@`^ZJD`OQZ_&;\=Q`P(\>04!/&4`1NY+P#]
+M_03]^07D"10$_?P%N9D`_>D$__X%/NBI`+\>OQFYSP#D#?___?D$B0``__WI
+M!-E`(0``_>T%_^\%H)`^Z*D`LOJR"WXY4@`^ZJD`"<#]"039``0``+60,3[H
+MJ0#9``0``+60,C[HJ0#9Z!D``+^9\)0!]1NJ`-D$(``!OYG$"O_PE/^FJ?0-
+M!;*:OQZ_';DI`$\`__WO!/V=!/V>!?^:!3[HJ0"_';\````X+DO`.0+
+M$>#]^03_#I2YF0#]W@3]V02)[A\?_````(/W^!:"?H!#[(=DH6@``OYGY@K.=`#$!V0``$`&_D+B9-!``OYGP
+ME`+T"QW=Y!```;_?V61F```.`2">V0```(#]^02@W]DT$!`!OYGPE`3T"S)^
+M2Y\`WF0`$`&_Z=\```"`_9\%H.G9)````;^?V7@:```.`2">D/\!V>!A``"@
+MG]F`&@``OYK8!``0`=E\&@``UP@`$`&_GI*A`=8,`!`!U6!;``#4````0-,`
+M``"`T@``$`$^$*L`OXN_?;]LO.J2IN'T"S^SD`\\L.8/]`T%^`B\[I"\GI"0
+MGP&VE`*\7?G?8%L``+R?D+6<`J";D.\!_P24Q/X/_9,%H"F_(#X0JP#9?!H`
+M`*">V4@9``"_F;.0``;X"+WTV000$`&@GP\!V4@9``"@GSX=JP#$"0'T&XG9
+M?!H``*">#P'9$!`0`:"?^X'>``0``-W@&0``F.D#?]^UZ@3QE0"`\/4(M>D#
+M8-_X`-E4)```\*3_MJ0!O*F@6*H!\*1_^`#>."```;_IQ)\(]!L/"0B@Z=D`
+M(P``-9\8^`#96"```;^9\)3_IJGT#0>]I/@`WM`C``"2KP&5^06VE`*\GI"_
+MGO#T'PD!NY\$_9X$\*P+\*8!^`#>``0``-W@&0``O^E_W[7J`?&5`(#P]0*@
+MZ6#?^`"SP``IW0`$``#;X!D``+_9?[_<`%H``+_.\94`&/#U`J#9D.X!8+^@
+MSI6I&+.4$3+9`",``)B?!-G___\`_ZF4IOGT&QS>``0``-W@&0``O^E_W_&5
+M`!#P]0*@Z6#?^`#9`",``)B9:\>9JK.0#Q"SD!`ELY0+1#Z#K`#=X!D``'_?
+M/>39RC4```H!\/4"()Y@W_@`W>`9``!_W]G`-0``E`+"F`/"L"_"F`?L!F*D*^3*RH;*SF*(!QYD7]`L)LJ`^
+M]*P`F!D,F*H+MI4;MJ48MJ0&_:D%?OE[`+*@Q"D(]`M1LP0`!O@(O10)$OZ1
+M#/0R$O0R$O0R$K,4`0O9*%H``*"1L@I]M'[HC@"8"0BR"O&5`""U"0A^C:P`
+MLQT!Y@"]]-DH6@``H)_T,1(^&:X`LP``%,4)!+VTN)H`(`(,`3Z9K0"8'PC9
+M`",``)B>?9@=#/'U`""U'PB4Z0/?`",``+R?D)B;@=D`)0``MN0#O.G@O^FV
+MU1NR$+;4!KW$O-F@F`D(QYD2]!L)O:0^&:X`WL@U```_Z=W)-0``/]\0F0$@
+MZ1#_`2#?F`D(Y9T`(+4-"+/``$:8"0K?____^,?>:`H!_9\$WP````']GP6U
+M"0K9\!D``+R>^-G+-0``()Z5V1R\J92U^0B8"0C'F1/T&Q*@.CX9K@"8'`I^
+MA$0`"@'[,=D`(P``]##T^8*8F`+T,/C^20&0F33^3P&@F)#_,+*3O93>`.H`
+M`*#YU____P#?````(?_GE/V?!;T4L)$+U!`&``#9L>\``-6,!@``O)YB/F*P
+M`+`6"/0-/7Q1*+Q!".0K__^R"G[HPP"SI`,JV="K``#?````(;"1`#V4_P?D
+ML@KD*____>\%,)$$?<0-(7[Z10"_,;,9")$!L!8(]`P4L!8!]0BC`;`6!O0-
+M&3YXKP"S$`EMDAD+L)82]0R+`3XZKP#:`.H``+)K?NC#`+.@!V&SI`-G_DH!
+MLCN0JC!^`.H`LQT!9`&_.;.=`5T!M.`+V="K``"PD0`]E-H`Z@``,)$$LFM]
+MQ`TA?OI%`-D`(P``WP#J``"UGP0^8K``?%&XO$&H\+,`?NC#`+.D!PKX"#Y5
+MKP"SH`,4OS_9`",``+6?`PD'/CRP`+\Y_DH!D*HPO$F8^96@.CYBL`#>``0`
+M`+_OV0`C``"8F@-)_^_]^02@[Y*I`;"6!?0,#M(`Z@``LF`^K:\`?%J8O$HH
+MY)#__[(JL@M^Z,,`LZ0'!O@(DJD$L)8!]`Q&V="K``"PD0#_)Y3>````$?^>
+MY3V4L@LPD02R*GW$#1%^^D4`LZ`"-]D`(P``F)\#M9($L_0,-WXN5P"SI`(O
+M/A^P`+.D`UO9`",``)B9`[.4#"%^+E<`LZ0""O@(/F*P`)*I!+"6`?0,"0D(
+M/CRP`-D`(P``F)D#H#D^8K``W@`$``"_[^3Y`!#T"Q79`",``)B9`Z`Y2?_O
+M__F4H.F_.:89]1L)_MD`(P``M9$"IACT"PT/`?Y)`9"9,*"?_DD!]#`(D)DP
+MOYK[A0SY$M$T%!`!OQFRP++<#0SPE`'T&S6_K]DD%!`!Q;X!O=2@GYBO`9"9
+M!*"?F*\"D)D$H)^8KP.0F02@GY"9#*"\#M>D"
+MLAM^C[``LZ0`$E@)!9`?$*`/4ID!=0D%^Q40V20@``&_F;*O6*Z#\)0!,Y``
+M"PH%<^[^`T6X^0`!`#^9"@0SD`PW&/DA,Y0$"+VD^``PE@CT#"$.`0H#O.GT
+MQ/EL]!L8LNKD^8`!]!L/Q/D#"@+T&P?X"+VD^`#?``0``)6I$+.>_@,1F/T1
+MW$0$```^J;$`F/T0W$`$``#$J0'T&R?>X!D``'_IQZ_HMO00\/40\)4!8.G9
+M__\`___9E/WY!:#/^`#X"/@`]##\^3*XJ3@&`O0P^++#L)84]`P@V0`$``"X
+MKS`&`IB1$="P70``W$0$```"`3XZL@#9`",``)B9A+B@(`@"E0\%YYE(`:;Y
+M]1@H`MD`!```F)$0Q`\?W$`$``#0H%P``#TDV0`@``&\J:"S^13&`+#V%/0,
+M$+/P"!NS_1#V`3[,L@"S^1C7`+/]'.@!/M"S`+^NOZ_DO?__N3D`_9\$CP``
+M__WO!/WI!?_MM?4+Q`$S(``2V3`F``&_G\?_D#ZCL@#9""```;^?Q_]D"0&[
+MGP2FN?4,G0&X"00!`#^9,Y0?"0D!-0D@N`\$`0`_^?"5`3[:LP"_KK^MN3D`
+M#\#PY#__O_3]G03]Z07_[[7U"V,!V20@``&_F?"4`?0;"#,I`%(!N`\$`0`_
+M^?"5"#[:LP"QMO\`]`T%^`C9)"```;^9\)0!]!L(,RD`*0&X#P0!`#_Y\)40
+M/MJS`!@)(3.4!TW>X!D``'_O6`T%Q1D!H,GP]0%@[W/4`#68"028#@&@"9@)
+M!;4)`5@)#'4)!=DH*``!OYFSE`$6F`\%E>D?\)8!MI0?_?D%M0\!N`D$`0`_
+MG<39`O0+-[\/"?#_N92FG_0;*S,@`!395"8``;^?#O[]_@0^P+,`20`!_D\!
+MD/\8H/F__]E$`!`!H)_%WP*X"00!`""?/MRS`+@/!`$`/_GPE00@^:"KN`D$
+M`0`_F3.4'V(8"2$SE`!;,R``#=E`)@`!/@*T`-DP*``!OYJ0F02_F[.D``;X
+M"%@)@P$"D`P0,!$$MI00#1"PD0#>B+$``'X[P@"SI``9V>`9``!_G_#U`6"?
+M"0,U"2$^1[0`-0$A]#`(^S4$WN`9``"_J7_O\94`@*"IQYGP_9\%8.GX`/D2
+M/ZGT,/BRH,21_[,9!-,`L!8$]`P0LQ``&[,=`_T!/L6T`+,9!1$!LQT&[P$^
+M0+8`6*H!P"SH``9Q:D$M0$$N)D`(`*U"@*U"0,^
+M>+8`6`D!QYK&Q*T!M0T&DJ\!L/8C]`PVW-@&``"\_Y"\GY"4G@2\[."8[`JS
+MP``?D-D$MI0#O`F0H)R8[@N4WP.\#_"U_@D^1;4`V0`$``"8FS*8F3&8#@'P
+MI'ZVI`.\J:`)`K#A`#"1!)`,(`T0WDVT``!^.\(`"02SK0#^`#Y^M@"8#P98
+M"@&0^02VE`.\"9"_F;;T`[P/\,>JQK4)`YCY"9@+`[*3;0``'X[P@`)!;.M`*@`/GZV`)BM!5BO`;_9
+M\/,`Q/H_MI4;IJGT#0F]E#YUM@#'_\:P]B3T##N8W@*2_P'$)"?)#7\`1C>!C6>)%C=`77]`9@/!K:D
+M!I@,!0U`D/D$MI0#O`F0OYFV]`.\#_#>3;0``+RIH+4*`PD"F/L),)$$F`\!
+ML/$`M0L$?CO"`+.@`$H)!B`)/GZV`%BJ`9@+!7Z1-@"SH``H6`H!?OE[`+.D
+M``;X",6I!+B9`"`"M0H"M0D#O92U"00^>+8`F`D%M0D""@$^@+8`O:3T,`C[
+M$=DL&0``]##T^8(_G]GP&0``O)N8LJBPD0LS]``&^`BSA``_V31;``"\FYBS
+MG0!8`=G\&0``O)OXV6@:``"4O@*\Z7`)\/WY!-DT6P``N/8`(`#?'!H``+R_
+M,#X:MP#93%L``+R;F+.=`!T!V10:``"\F_C9=!H``)2^`KSI<`GP_?D$V4Q;
+M``"X]@`@`-\B&@``O+\PO.F0LFJPD0J]!#\UO10^I+<`F*D.#O#_GL2XS0`@
+M`)C?",24"(D```+%P@3_^96PD0FRGL?_$XG___O]Z02S]``MF-D.M=X(_TF5
+MM:D.LP``"[4""3YXMP"TX`J@XC\YLM`2F0$@.3ZAMP"S$``*LMH^H;<`F-D,
+MWP````'%P02RVOV?!:!Y$E4!,U0`B+,``&"S%``?/SDSD``&^`BRBGZ'`0"8
+M"0GPE0*U"0D^"+@`I@;T&QBSA``-V?P9```^XK<`V10:``"\D;D)`K4)";]W
+MM.`+#_#_'_2X_P`@`+7W#+"&`/#\"[N?`K7I"/N%#/D2V>1A``"_D++1LP1_
+M!O@(WC!:``#9_&```)0/!+S^\+^>F/T#H)#9Y&$``+;D`\?=P_'D^`.@G:#Z
+M20?\M?L!_QF4M?P"_9X%M?D#^Q';_&```+^]L]E_FP"4W@39,%H``+SIX)CL
+M`Z;J]!LFV>1A``"_GZ"=Q\G#H+FV]`-)!_SQ]/@#_\F4_?D%M>\#^`#'S,.R
+MZS[XN`"4SP39,%H``+SY\*;Z]!L^F+\#F*D#30?\WN1A``#]_03QE/@#_9\%
+MM;D#F*\#O^F@[/W]!+:4`_&4^`/]GP6/___?_9\$M:D#^`"8^0.R^\>RU;+FM(`,O13^D0ST,A+T,A+T
+M,A*S%`$+V2A:``"@D=GP&0``O),(Q"3_WB5:``"_"?&4_P_T&TD_Z0\'N_0"
+M$)D!(.FP]@'T#"'=]&```-S@&0``O]Y_SPD!NY,$_9X%\?4`(*#98,^S%`$0
+MO?39*%H``*"?]#$2O:0^*KH`/92P@0"P,0$@Z;(*LFZR*[)\LEU^=P4`M0(!
+MM04#M08$M0@%M0<""0>\E.*PY@'T#";9/AH``#R3V`D!O)[TQ-G___F4]`L%
+M^`C_W_79/AH``#R?.0H!IAKT&Q&]]-DH6@``H)_T,1*R&O0P"/N!^1+9/AH`
+M`#R;Z,2@_P\'`0&[\`*\'_3P]/\Y_P#]_@0\G[GT,/RS``8GLP0'5-D?&@``
+M/)N8,Y``2-G\&0``LKJ\F\C9"!H``#Z7N@#9)1H``#R;F#.0`"G9%!H``+*Z
+MO)O(V1@:``"\FMB]E+(+L)$`O>1^-+D`LAH^K[H`O:3T,`3[$?0P]/E"?JUO
+M`+"F`?0-!?@(W^AA``"_^?Y!`;+RU-QA``"0F0&0$13$D`_3#&$``#XFNP!^
+M_`0`LZ``1;\OL/8/]`T%^`B_'MT,80``O/^0O)^0E)\"O/WPH/Z8'0&0F0&0
+M#@&\/9F8&0*U^0*@(,3@#[])LAN]I*8)]!NZV?`9``"_G]G<80``OYF8_T"F
+M"?0;(<3Y`?0+&]T$$!`!O]_9^&````X!()Y)__?]^02@WP\$V1`0$`&@G_M%
+M#)BO",?Y&O0;![VD^`"8J0?>____!\?_E;;T&_V>!/WY!;6O!WY`"0#X`/DB
+M"?#'K.C]N02XL0`@`+/``U^PQ@/T#`NSP``7/L6[`+/)!3@!L\`&2+V4/D>\
+M`/"D_[.@!1VSH`D-LZT$^P$^Y;L`"00^[KL`/90^[KL`$-D!WYP6``#PE/^\
+MF9"\GY`8GP$0_P$UGP$^T;T`O>0)$OZ>#/0R$O0R$O0R$K/D`0O9*%H``*">
+MF!D(C___]_V?!+49"+/D`1"]]-DH6@``H)_T,1*8&0''F4.SP`,9L,8#]0V!
+M`;/)!:(`L\T&>`$^M;P`\)0#LY`#!O@(F!P(Q\D1]0MB`8
+M'0;?____!\?)E?WO!+:4&_V>!8\```JU&0?9__\!\/_)E/V?!;49"-G___\`
+M_=D$M1T&/M&]`/"4`[.0`P;X"+T$"1+^D`ST,A+T,A+T,A*S!`$+V2A:``"@
+MD+(:?D20`+,-`?(`O?39*%H``*"?]#$2/M&]`)@?!I@9`97R&,>9([.4`2*S
+M(!`>LR`2&K,@%!:8&0;?____`/V?!+49!C[1O0"]Y`D2_IX,]#(2]#(2]#(2
+ML^0!"]DH6@``H)Z8&0B/___W_9\$M1D(L^0!$+WTV2A:``"@G_0Q$K,@$'>]
+M!`D2_I`,]#(2]#(2]#(2LP0!"]DH6@``H)"R&GY$D`"S!`$0O?39*%H``*"?
+M]#$2LR`20K(:?CL%`+,D%!*_&0_X_9\$\)4$/L&]`)@9`<>9([.0`P;X"+\9
+M#_C]GP3PE0*@&;(:"P%^G`@`/M&]`/@(^R&8KPCY`K*@Q_D:]`M,Q_D;]`M&
+MF*X-F*P'F*T*F*L)B0``,/WI!=G___\'\;3___W)!,?_E8D``/^V]!O]V03]
+M_`7]VP6UK@VUKP>UK0I^0`D`/DN^`,?Y&_0+'5@+$K(*?JY!`+\)\)0'LY0"
+M#+(*"P%^G`@`O:3[`?DR"0?$O_^RL;R?,K*B"?#'N^C_R92XD``@`+.Y!IP`
+ML+8&]`P6L[D#RP"SN047`;.]`@<"/IF^`+.Y"FD!L[D+=`&SO0?T`3X+P`"]
+ME*#IV2P9```_F3.0`!"R&K(K?ID+`#Z&P`"R&K(K?B^Z`+.M`,H!T#X:``#<
+M`"```#P"&)C*`=O@&0``V3L:``!_OCR2V`D!O)/T\>4``;N=!/#T__V:!3G_
+M`+7)`?WQ!&"^/`\I/H;``-DL&0``/YDSF0`B`9@/"L?Y6/0;/9BO0+#;(*?M.]`#XIP`"R"GYQNP"SK0`5`9@)"-\`
+M```(_9\%C___[_V?!+4)"#XMP`#9+!D``#^9,YD`EP"8#PK'^1?T"PL)`:#I
+M/BW``,?Y6/0+";(*?GX)`+\)F`\&#OC]G@3PE0*@";;U&+/T%`S]G@3PE02@
+M"9@/"(G__^^R"@L!_?D$M0\(?IP(`#XMP`"RR[(:LMRR+7[W!P`^AL``LCJR
+M*WZ1"@`^AL``V2P9```_F3.0`'28"0K'F5CT&P7X"+(*"P=^?@D`LZ0`7=DL
+M&0``/YDSD``1F`D(C___]_V?!+4)"+`V`?0-!?@(WC@:```\XO@)`;N3!/WY
+M!3SO*;,T``W9'QH``#YRP`#9)1H``+PIH#^I,Y``#1*9`2"I/H;``/@(^S&]
+ME/0PX/F"L)$0V2`0$`&]-+^8O:39\!D``+"1#[.)`/8`WSL:``"\/Y`_F0\!
+MN_D$_X^4]0O.`+20#[^2N?D`O?3]B02P\0V0*82P\0Z0+XBPD0RP\0N0*8R0
+M+Y"0)("8(""PD0JP\0D^:<$`M)`,M/`+OY&_]K20"K3P";^5O_=^404`Y0D`
+M`:!)Q!G_DID&L)8!]`P>LANR;+)=LCK^3@&0[D!^3;X`"0&PD0T^6\$`QQ#H
+MLP`$&+,`"12R&K)KLGRR/7Z;NP"S!``*OT`^:<$`OT"T\`ZS\`$1"0&PD0ZR
+M*L0)`?0;A[3P#0H!L_``%+2P$+(Z?LL#`+V4"@&PD1"T\`^0,P&0_P2P\0^S
+M/0,/__N%('^IW^`9``#QE0"`8*E_^?"50&#Y^`#91!H0`;^?^3+9L!8``-,P
+M&A`!OYS$^P?2-!H0`=$X&A`!T#P:$`$^*L(`&,X66,T*V@````;PY/_PTP#'
+MZ0+'[P&VE!VV]![]GP7]G06@.;_)\.0!H"F8R0'PE/^@&;/@``G:````!)C)
+M`IC,!I*[`?^IE:`)L\``"+.T`+'9L!8``*"<^S'Y4G+4LJ*RL[+!LN7$20_T
+M&S/$J0_T&RU)`/__N93T&R3$R0_T&QZQQO\?]`T7VK06``#;N!8``'XD@0"R
+MH+.D``SX"+VD/LG"`*"BM:,!M)`'=:0*M:4#VZP6``"UJ00TD""R##6I%K@9
+M`"`"M:D"VJ@6``!^#($`W[`6``"_^0H!LY0`#*#P?K3!``H!^U'Y8K*BLZ0`
+M5=F\%@``OYFSE``D/B3#`)@)`[.0``F8"@3YE;(,VK06``#;N!8``'X,@0#;
+MP!8``-J\%@``?B2!`+*@LZ0`U-F\%@``OY^S]``+V81<``"@G]E`&A`!OY&P
+M%@#T'G6]E#[DPP"@-MJH%@``VZP6``!^)($`LJ"SI``&^`B8#P+_%93T"P7X
+M"/\4E*:?]`L%^`BS(``-&`D6QYD#]`L?F`D#LY``"9@*!/F5L@S:M!8``-NX
+M%@``/IG#`+(,VKP6``#;P!8``'X,@0"_,3ZSPP"RD]8```!`U0````&$\/\#
+ML!8`]!Z!V;`6``"_F;.0``A^M,$`V;P6``"_F=^$7```LY``#`D!H/D^Y,,`
+MH/D)`;*:^V&]E)B>$*:N]`@6F)\1IJ_T#`Z2J0&\FY"FG_0("?@("@?X`+RN
+MDM^<&@``MI4(//F8Q)K_Q*D!,Y``#,>I!@H#]`L%"@7X`-W@&0``W-!E``!_
+MWUC.'-D`!```F)D/\?4`!/'E`(!@WW7.'/&4``'T"P<)1"#)^`#X`/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^```````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````/@`V@`@``!+L`!^OS<`V;`@``#>`"```+7I$MF^30``M>D.V;I-``"U
+MZ0_9P"```+7I$-D`(0``M>D1V10$``#?`+8!`+7I&]F>NP$`NY\"WS1<``"@
+M^0D!W?`9``"@Z=SJ8```20`!M>D:O>0_R3.0``BSX``0O]^8^2#QE0"`M?D@
+MD.X!D-T$L^0#Y/@`"?"[RP*0S`_]R039````0/W)!=DP&A`!H)R2F2R_F?0P
+M_+B[`"`"CO#_`[RIH-DT&A`!H)J2F2R_GY"9,/^^Y-Q`&A`!\/3_H)_9````
+M!@]D_>D%_DT!V3P:$`&@GCX`QP"2_P&S]`$,O\F@V3[QQ@"S]`#QO\F@V;_9
+ML)8`]!X)#V0^\<8`Y^FD`;:4!*:;]`L%^`C9````0-]`&A`!_^F5H/GT,`3X
+M`/D"LJ!^(]X`?IC>`'Y>W@!^'0"$``+7I0=EP(@``M>DQV;`B``"UZ4+9
+M\"(``+7I0[V4WV`B``"U^0.@^;7Y`;7Y`@D!W?`9``"UZ13E`
+MO>0_R3.0``BSX``0O]^8^4#QE0`!M?E`D.X!D-T$L^0#Y/@`^6+:`",``$O`
+M$WX<.`#9P1,!`-\`(P``M?DCV;$"`0"U^2397"(!`+7Y)=D"*0$`M?DFV2(T
+M`0"U^2?9`B`!`+7Y*-D"&0$`M?DIV0(=`0"U^2H)`;7Y`@D+W@`,`0"U^0C9
+M618!`+N>`K7Y&@D,W0#P``"U^0G9;@L!`+N=`K7Y&PD*W``B`0"U^0K9PB@!
+M`+N<`K7Y'`D.VP`I`0"U^0O9-2H!`+N;`K7Y'0D/V@`K`0"U^0S9R#0!`+N:
+M`K7Y'@D1T``@`0"U^0W9<"$!`+N0`K7Y'PD-T0`7`0"U^0[99AP!`+N1`K7Y
+M(`D0T@`=`0"U^0_9U1\!`+N2`K7^$;7]$K7Y(;7\$PDQM?L4M?H5M?`6M?$7
+MM?(8M?D0V00@``&_G=D"40$`W@!1`0"U^2NU_AG9DU$!`+7]A+N>`K7Y(C#6
+M)/0-!?@(Y]E(`;"6`?0-!?@(E=D8L)8(]`T%^`C9`#L!`-\0!@``M?D)V0`\
+M`0"U^0O9`$H!`+7Y#-D`3@$`M?D-V0`U`0"U^0[9`$0!`+7Y#]D`10$`6/T2
+MM?D0V0!&`0!8_!:U^1'9`$=>D)V4(\`0![G`)8\B!UZ0O9R$H!`'N;`ECS
+M(G7I#-D'3P$`>YH"6/0D=>D-V2Y("=>D0V4-&`0![DP)UZ1'9-4Y4"=>D3
+MV35)`0![E@)UZ139`#T!`+7Y%=D`/@$`M?D6V0`_`0"U^1?9`$`!`+7Y&-D`
+M00$`6/TJM?D9V0!"`0!8_"RU^1K9`$,!`%C[+K7Y&]D`2P$`6/HPM?DYP"6/(V=>D6V8L_`0![FP)8
+M\SIUZ1=8_SC9-4`!`'N:`G7I&-EL00$`>Y`"=>D9V35"`0![D0)UZ1K9L4,!
+M`'N2`G7I&]DS3`$`>Y\"=>D@_'U`("@W_@`VL`V``!+\`!^
+MOS<`WRP$``#9P#8``+6?&=^P-P``M9\)W_`W``"UGQK?T`8``+6?&P\!H)\/
+M$+6?&/@`WP`$```)`37Y>-X[&@``-?G"-?G!/90@Z37YP`D"-?F("0@UZ0$)
+M`S7YF`D0->D"^`#Y$MH05@``2X``?APX`-D05@``T,!5``"U"32U"35)`AC?
+M@%8``-$0-@``M?D#H/$)`=K`5@``-0G8"T!^'#@`"0&U"4#9)@```K4)00D(
+MM0E$B0``#/`5`;4)1HD``#BU`4*U"4H)!+4)3OL1^4+:P%4``$M``GX<.`#9
+MP%4````!M9`+M9`#M9`%M9`(M9`)?N+,`#V4WQ!8```U^08U^00U^04)"7VT
+MW,!>``#=$%\```$"TM!>```U\!$U\`$U\`XUT`0UT`4U\0\UT0$UP00UP08@
+MR37Y!R#9`P,URP@U\Q`URP(URP,URPD"20`$=2D"
+M=L#-?,"=?D"==L"2?\'
+M=>L"=?D$^T'9J!8``+WTH)_9K!8``*"?V;`6``"@G]F\%@``H)_9P!8``*"?
+MV81<``#Y,J"?T+@6``#1M!8``*`/H!_:Q!8``$LP`GX<.`#9Q!8``-+@%@``
+MH`G3]!@``*`9LBS:M!8``)`B'-NX%@``?@R!`*8C]!OK^S'=`)\!`-^$8```
+MV0"C`0"U_0+>`*$!`-T`I@$`H/FU_@.U_0'9`)T!`-X`EP$`W0"/`0"U^039
+M;&```*">M9T!W@"2`0#=`)H!`+6>`[6=`MZ<8```W0!2`0"@[7_L?YM8F@+Y
+M8EB2!%B0!MG@8```6/8"?_%8\P18]`98]0@]]""?V=J(`0![G`+?[&```&#Y
+MV0N9`0![FP+>U&```&#IV5&1`0![F@)UZ0'9JY8!`'N0`G7I`]DQG`$`>Y("
+M=>D"V0VE`0![D0+=7&```	V3^@`0![DP)UV0+9!*(!`'N4`G79`]FY4"==D$V>^F`0![E@)UV0'[8;WT]#"P^8+^0`&0`'"@#_Y)`9"9;*"?DID$
+MH)^2F02@G]D\%``!OYFPH0E+P`':0%@``/"4`3"1.]GN8```()_9H&```""?
+MV=!@``"@G]FP8```H)_9K&```&"?V6A@``!@G]GH8```8)\8_W79R&````<$
+M!@$@GWX<.`#:,%@```L0?APX`-DQ&0``/YG<15@``+W4U1`4``'$FO_;%!0`
+M`=-4%@`!TO____V$```0T4@6``$@QMZX8```O-Z0(),+/T
+M`"V@7TD`$*"YOSF@";\)_9($H`F_":`YH+2_&:`)OPG]D@2@";\)H!F@OY#)
+M`Z"?D,PXL]0(A]DP&0``/YS=$!0``0D!H-F]Y-D4%``!H)X/#[B9#`(`H)_^
+M2`'^10'^00'^1P'^0P&@WA+$`3TDUNI@``"0B&B056"0$6R0=V20,W`^:-,`
+MQ$#_E`D&E`\#O)_2"03<0%@``+S\$H#Z_/KP`\+N?`@\!H,ZVE`+<1%@``+R
+M.!D``+SMF+.0`#.4#@.4"0;<0%@``+N>`KR\Z?"_^8S`(@*\W-#<"&`1`:")OXF\[.#<````SK;4!_V<
+M!*!9OUG<``#_`,0J_XM!?@7]G`6@6;]9\95?#*!9OUF@^;_93Q_^H!F_&?V?
+M!/"5H*`9OQGQE0`"H!F_&?"5$*`9O^F@>;]YH.F_&:#9?B5J`)0.`Y0)!MU`
+M6```NYX"O)V0#@*@GKP`D)0/!-Y$6```N_D""0.V]`*\_O`U^0$^8M,`/VDS
+ME``+Q"K_?EEJ`!`B`1!$`=\N&0``/_DF*?4()?[9,1D``#^?-)`[,Y0`$[W$
+ML,$/L,$0L,$1/K#3`-EX%``!OYFPD0_9?!0``;^9L)$0V8`4``&_F;"1$1+_
+M`3W4_D8!_D@!_D`J!_MI0"H*&\
+MG)`/`3[^U`"2V06PE@'U#-$`OXGPE8"@B;.T!2R_?@\"H*^\1/"4203PY8"[
+MGP+=1%@``+:4`J!^O)V0#P,UGP$^[]8`L+8#]`T(L[T/X@&_>8Y"`A"\3D"4
+M2@3PE;V@>;^IC[[][[Q/0)1+`Z!9OU])'_Z430:[VP+]^03_/_6@7[]9WT!8
+M``"\W]"\1/#PE0&@6;]9E$X$N^\"WT18``#PE0*@6;]9MN0"O._@3__#E`P*
+M_9\$_D!"0$UV0_9)````;^9D)D!M=D)/N_6`+/=
+M!X4`L[`'!O@(OWF,0@(0O$Q`E$P$\)4@H'F_B8V^_>^\34"\1/#PE2"@B;_)
+ME$X$N^\"WT18``"@6;]9MN0"O._@3Q_^_9\$\)7@H%F_691-`Y1/!KO]`MU`
+M6```\)4!O/WPH%F_70D!H/D)!Z#-->D!V20```&_F9"9`;7Y"3[OU@"PU@/T
+M#0BSW0_#`)1)!KQ$\)1+`[R;PI1)!+N?`M]$6```MI0"O)^0#P?"5@*!YOX\)"*#)B;[][_'U
+M#8"\24"@C[_I3Q_^H%F_6?V?!/\IE:!9OUE/_\/PE0*@6;]9\)4!H%F_6?V?
+M!/&5``R@6;]9H.G9)````;^9D)D!MV409``!@G]DH&0``H)_9+!D``"">V2T9```@GMD$6@``H)_9"%H``*"?
+MV0Q:``"@G]D06@``H)_9%%H``*"?V1A:``"@G]D<6@``H)_9(%H``*"?V25:
+M``!]U""=V21:```@G=DH6@``H)_9?!H``*"?V8`:``"@G]E(&0``H)_9Z&$`
+M`*"?V=QA``"@G]GX8```()W93!D``&"?V?QA``"@G]D(80``H)_9V&$``*"?
+MV0!A``"@G]G$8```H)_9H6```""=#/[9(````:"\!M>\"D)D$#@&@GMG@&0``8)_9Y!D``*"?V5@9``"@G]E<&0``H)_9!&$`
+M`&"?V?IA``!@G]DP6P``()W9,5L``""=V?!@```@G=GL&0``()W9>!H``""=
+MV60:```@G=EE&@``()W9%!H``*"?V1@:``"@G]DB&@``()W9)1H``""=V4Q;
+M``"@G]E06P``H)_9=!H``+W4H)^]Y-GL80``/;2@G[W$L]0"#=\`0!$!/AG:
+M`+/4``W?```1`3X9V@#?`"`1`=KP&0``O.J0H)_?.!H``+S?D-H^&@``()N\
+MVI#?_!D``"";O.^0V@@:``"@G+SJD-\<&@``H)R\WY#:'QH``""3?P$D``*">D)E`II_T
+M&_G?,%H``+WDO=2@_;7]`;7]`I#N`93I`_&4^`.U^0.0_Q"SY!#HWC!:``"8
+M[S_93AD``'6=`V"==9T!=9T"V>1A``#Q]?@#H)W9_&```+7O/P]_H)_9]&``
+M`#WTH)W>IA8``-F<%@``()\UGP&0F0*FGO0;]MF(7```()_X`-X``A`!O^E/
+M__'=!`(0`=P(`A`!\94/`?V?!*#IO]F0[A#;%`(0`;WT\97_`:#9O\G:&`(0
+M`9#=&/&5/Q"@R;_I&/]T\)4'H.F_N?&5,?.@N;^I\)4'H*F_V?&5$0.@V=E@
+M`A`!OYG%G@8S\``-"?[_Z?0^#=P`Q9\'V6`"$`&@G_@`V0!:``#Y`KT$H)#9
+M`!D``*"0V009``"@D-D(&0``H)#9#!D``*"0V1`9``"@D-D@&0``H)#9'!D`
+M`*"0V1@9``"@D-F)7```()#9,%P``""0V31<``"@D'X6SP#?C%P``-D`K@$`
+MH/E__]X`X0$`V41@``"@GG^>V?FU`0![GP+?DEP``&#YV9!<```@D-DS`0(`
+M>YX"WT!@``!@^=GV7@``()#[`?D"VFAF```+3'Z_-P#?[(H!`-EH9@``M9\2
+MWU:*`0"UGP7?<8H!`+6?!M^,B@$`M9\'WR:,`0"UGPC?.HX!`+6?"M]QC@$`
+MM9\+WU>,`0"UGP3?&HT!`+6?#=];C@$`M9\.#P&@G]ED9@``/=0@G=FT9@``
+M()W9P&```+WDC\#4`:">V>1@``"@GMFD8```H)^8[Q_9J&```-HX&0``"PB@
+MG]G,8```H)[9M&```*">V5A@``"@GMGJ8```()[9-!D``"">?K\W`-I`&0``
+M"P)^OS<`VD(9```+`GZ_-P#9&"8``;^VC(9```RV=`S&0``)LWT&`\2F0$@K#R>D#[N
+MW0`2R0$@K3R?D"`)V0!8```]]""?V109``"]Y-\`O`$`H)[98&8``"">V;C@
+M`0![GP+?$F(``&#Y?J'.`/L!]##\O=3^3@&@[0\!V1`4``&@GY"9!-P$%@`!
+MH)V_R4\`_Z#IO^G]GP2@Z;_I\)4?H.F_Z:#)]#`$^`#T,/R]U/Y.`:#M#P'9
+M$!0``:"?D)D$W`@6``&@G;_)#_B@Z;_I_9\$H.F_Z?"5!:#IO^F@R?0P!/@`
+M]##\O=3^3@&@[0\!V1`4``&@GY"9!-P0%@`!H)V_R0_]H.F_Z?V?!*#IO^E/
+M?__]GP2@Z;_IWP``A`'QE/__H.F_Z?V?!:#IO^F@R?0P!/@`V<1E``#;0&(`
+M`/0P_*";VM!E``!+D`!^'#@`#0'<"!8``=D0%``!H)V_S_Y.`=G090``VT!<
+M``"@[[_O()VUFQG9````!/WY!:#OO^G?````$/V?!:#IO^F@R?0P!/@`]#(2
+M]#(1]#(0C___`-D4```!H)^2F1"@G[WTD)DDH)\/`I*9#*"?DID,WB04``&@
+MG[_I#_?]GP2@Z=D$;P``_I``^`#$J0+T"QOYD^HN$`H.^_Z>6?``'PE`'T&_6]I+VTO<1^CDH`?DG?`'YH%^_6=^`&@``O__QE/__H%FF[_0+(GYT%`#?2!D``+_YLY0!$KV4H/E/
+M#0[9!!`0`:"?O02_6?"4(/0+*=D8&A`!OYFPE@#T'P=^T4<`V4`:$`&_F;"6
+M`/0?";VD?LO"`+T$V>`9``!_F?"4`?0+"7X`.@"]!-&A8```/QDSD``;"OY^
+M*6X`L:;',O0-"SV4(!E^30T`O039T&```+^9LY``#GXR)0"SH``&O0398&8`
+M`#^9,YT`Q0"_6?&4@`'U"[H`T.!@```_";WTH$_PE`'T&SS9G&```+^=V>Q@
+M``!_F]\````1LMJP00#]U@3PLP#]WP4,$=Z^(P``?H9'`+])LY0`"S\)\)4!
+M(`F_2;.4`TQ^6W@!V9Q@``"_G=GL8```?YO9````(;+:L$$`_=8$\+,`_=D%
+M#"'>OB,``'Z&1P"_2;.0`AK?X&```#_YO03PE/T@^3YYY`"SE`(6W^`9``!_
+M^;T$\)4@8/D^>>0`LY0'!O@(O039X!D``'^9\90`!/4+M0#18&8``#\9O?2@
+M3\2?_\?Y`O0+8MD`!```F)D/\)3`,Y0`!O@(V1)B``!_F[*-L$$`V@"\`0`,
+M(?"S`-Z)3```?H9'`+])W>`9``"SE`(0?]GQE0`$8-D^+>4`?]G>8&8``#_O
+M\93_^V#9\/3Y(.\^+>4`Q/D!]!LOV1)B``!_F]H`O`$`L$$`#!'PLP"R?=Z)
+M3```?H9'`+])LY0`"S\9\)4!(!F_2;.4`PI^`+P!O01^7U``V6AF``"8F0*S
+MD``&O03=X!D``'_>Y.D`"/0+&ME88```OY_DZ?_W8-FS\``(?C9/`+T$OUGP
+ME`+T"P=^VGX`V>`9``!_F?"40/0+#7XE:0"SH``&O039-````;^9LY0`!O@(
+MTS0```'2`,J:.Z`RD``!L`8%]`TMT#@```&]%*`!?HI``*`R"0'?*!D``*`)
+MH/E^$'``V2A:``"@D?0Q$KT$V>@9``"_F?"4`?0+"0H!/@+F`-GL&0``/YGP
+ME`;U"^G\O:3T,`3[A0C>,``0`;_I#_[=)"```?V?!`_+\)4"_9\$H.F_V4_W
+M]Y#N-/V?!*#9O^G?````0/V?!:#I^`#9+AD``/0P[/F"/Y_9,!D``#^9BT$"
+M$+W4\/3_\)3_O)N0E)($LBX^AN8`O^G;0!D``+S;P)#=`<>9!/0;"K_I\)0!
+M(,F0[A"FW_0(X=G(8```/YX/#]D$!!`!H)\/`Y"9"*"?D)D(H)_PY/_$Z0'T
+M"PN/#P`//KSF`(\.``[$Z0+T&PJ)_?_]_?D$W`@$$`&@STG_#]T0!!`!H-G?
+M&`00`:#YV1P$$`&_GK+TLL;^3P'PY0&@GI#_-$F($[+5LOJ@^=,$!!`!T0P$
+M$`'0%`00`3XQYP"_.[\9OP^_;K]=OTS]FP7]GP7]G@7]G07_G.7T"PZ_KY+Y
+M`:"IL_0`V_Y)`9"9-+^9LY``"+/@``;X"-\`!!`!"0'^30&R_*#Y#F20W20/
+M9)+_`;/T`0R_R:#9/F/G`+/T`/&_R:#9O]GPE`$SD``.DNX!]!O;/L?G`+/@
+M`#H$`?Y``?Y*`?Y,`=LX&0``O=3>!&`1`=@N&0``D``HD*HLAP``_T,?_H8`
+M`""0S#`R13X_Z`#X"#Z1YP"8Z0&@";\)\)0/LY0$$M]"&0``O-^0()4^,^@`
+MH+2_Z:"IOZG]EP3QE5\,H*F_J:#I/_F_+_"4`?"5$/V?!?V3!/"5H*`IH`:_
+M";7I`;\9H,F_R?V3!/"5H*#)O\GPE1"@R;_)H!F0W0&0NP20[H"0(A#90!D`
+M`+S9\#^)DN$$\)3_IMGU"'S_/?39-!D``""?^X44^```````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````^```````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````````````+^_]##X
+M^7+T,/C^20&0F2R@G[*SL_0`!O@(V=]0`0#?`%`!`+R?0MG___\`_?D$V0``
+M`"'^0@'_^67^1P'9````$;VD__E5D"(LD']#$2/KOM`-``(P``F`HMF`LNO90P$02P
+MD0#?OI%`+.D`@J@
+M(3Z[[0#9`%`!`+4!`[4)!`D(H#D^R>T`T``C``"8"6O'F:JSE`83LBI^+^\`
+MORZU#@,^N^T`LBK;P#4``+)\?M/M`+]YLY``"`D%H"F_+M\`(P``F/EKM?X#
+MQYFJLYT)/0'?T*L``#V4L/$`,)$$LDM]Q`TALF[:`%`!`'[Z10`^N^T`V<`U
+M``"_G]G$-0``OYG0`",``+;T&)@.+;4/;I@/+K:4&/&5`(2U#FRU"6^U#VW:
+ML"0``'VTW``$``!^`#X`"0DSK0#0`)@)+0\&M0\#H"^0F1"U"2T^N^T`V@`$
+M``"_J^2Y`$#U"[$`W>`9``!_V=X`(P``&.P8#P+QE/W_H"]@V;7O`TG_O_^Y
+ME*"I,\D`B0`)&-_`-0``H/D)"CZY[0#9P#4``+^9T``C``"8#RZ8#BVVE!BU
+M"6X]E+4/;34)&+4.;-DX(``!O?2@GXD`A`#:L"0``+4);WVTW``$``!^`#X`
+M"0LSI``KW>`9``!_V=P`!```O\X/`?&4_?^U#P-@V:`O2?^__>D$H,X^N^T`
+MM0D#H"FR&K\AIJ'U&Y#\H#JRJ;*:]#`(^W4(^`#>`",``)CO:_E2#0$]E)7T
+M&-7$-0``M>V)->D9H%2RH[*RLL''\*JP!A'T#"VP!@[T&'VS``MPL`8+]`P0
+MLP`)1[,-"A$!/H#N`+,`#$RS#0T$`3YV[@"S"1:P`+`&%O0,#+,-%?``/N3N
+M`+,`%PVS#3'C`#[N[@"@O;V4H,V@63XM[P"RNGX`4`$)!K.@`7.@,#[4[@#'
+M^0GT&Q0U[1D^@.X`#P'9`",``#6?&;)*?GFK`+.D`![9`",``)B9:P\+H"_'
+MF:JSG1&0``D3/B?O`-X@(P``O?2_Z9#N!*:0]!L5V0`C``"UGP>P]@CT#1`^
+MSNX`D/\!L_0)X?@("16@.;V4/BOO`+V4H,D)#3X?[P"]E*#)"0X^'^\`WB`C
+M``"]]+_ID.X$LY0Q%MD`(P``M9\'L/8(]`T0/A?O`)#_`;/T">+X"+V4H!D)
+M#*`Y/BWO``D%H"D)`:`9^U'Y$M&@)```F!\#"0*@J;*@Q_\%]`M#V0`C``"8
+MGRW:L"0``'VTW``$``"UGVR8GRZUGVW?`````;6?;H\`A`"UGV]^`#X`,Z``
+M#`D$H`D^K^\`"0:@";\9F!X#F!$!W0`C```/P/V?!+71+K79+;*+.P`W:S,`$(
+ML[0`;K/P`'#'F?"PE@_T#&"8`@25+Q#T&R>0NP''JNB0J@%^A&X`LAM^A&X`
+MY"G__^2O__^VI!#]J06U"@2S-`,5L?8!#/"<"/"6`<::`3[\\`"S-`$A/>2)
+M`,``IOGT#04R/L;I`<2:_S[\\`"]I#[\\``*`?LQOZGY$IBO`;*@QYDH]1NP
+M`,?^0\?]Z/0+%\3I`[.9`J``L^D$FP"PU@+U#),`E?D0]!L=\?3__[/D!`R)
+M``!`/D7Q`(D```'_^96U"0&8#0'$Z0.5VQ"SE`,+L;8`!/0,7K/D!`BSM$!7
+MLY0!"[&V``3T#$O$Z0$*`?0+1;\)QYGPL)8/]`PXF`$$E1\0]!L>Q]KHD*H!
+M?H1N`.09___DK___MJ00_:D%M0H$L?8!#/"<"/"6`<::`3Z\\0"]I/L1F*\!
+M^1*RH,?YZ/4;KP"_J<>9*/4;I@#'_D.5^1#T&QWQ]/__L^0$#(D``$`^\O$`
+MB0```?_YE;4)`9@*`<3O`Y6K$+/P`PBSY`0+L;9``/0,:K/T`0^QM@`$]`T2
+M/G?R`+/T`@NQMD``]`Q0Q.D!]`M0OPG'F?"PE@+T#3^S]`$.L)82]`T1/G?R
+M`+/T`PJPE@KT#">8`025&1#T&R3'JNB0J@%^A&X`Y!G__[:D$/VI!;4*!#Y]
+M\@"]I#Y_\@`*`?L1F*\!^1*RH,?^0\3I`[.4`W3'^>CT&VV_J<>9*/0;997Y
+M$/0;'?'T__^SY`0,B0``"#ZZ\@")```!__F5M0D!F`\!E?L0L+8(]`PYOPG'
+MF?"2F0.PE@?T#"N8`00*`949$/0;(L?ZZ)"J`7Z$;@#D&?__MJ00_:D%M0H$
+M"@$^!/,`O:3[$?F"T$`N```#`M@``/``U___#__6@"T``-40(``!/A;T`-^$
+M+0``O_D$`;M#!/])E/4+V@"8#P'$/@''\D,SX``*,"8$]`T-L^0`$#`F!/0-
+M"?@(/BST`-\`(P``F/F@QY%TLQ0$#K(*?@+P`#Z<\P"S%`,.L@I^_O``/ISS
+M`+,4`0ZR"GZ^\0`^G/,`LQ0"#[(*?H'R`+.I`)``VH`E``!^4%,`F`D,MJ04
+M_:@$_9<$_:D%M0H,OVG_293T&Q&_"?"4!_0+"0H(/B[T`+\.Q^V*]`LYQ"D#
+MLY0"3[,4!$N_7\?I#\?^;+.0``VFWO0-'3XL]`#$^8`SE``OLNFPY@?T#04)
+M!Z;9]`P?D#,!D`!`W\`M``"_^;:5&Z8Y]0T%_PH!/B[T``H1^X'Y$MP`)@``
+M#0+1P"T````!VH0M``#;@"T``#Y\]`"_J9#=`?_YE+.4`2._OO_^E/0;&K_)
+M_?X%\)0']`L/LY`#"@H3/HOT`*"_D,Q`OQF\#?2VE1NFV?0-R`H!^Q%^QE0`
+M^`#>`",``)CII/F",I:SH``OQ&G_W_P-``"4E`*4DP*\3T#9"`X``-&4%```
+MO#DPO20]A-<`(P``/C_V`-F`+0``OY_$:?_10"X``)24`I23`I7R`MD(#@``
+MW_P-``"\.3"\3T!%_^]]A#UT/K+U`,0I`?4+J`"8'PG'^0ST"PG_]92U&0F8
+M&0$S8```+WT\*3_MJ0#F`D%O)J0O)^0-9=)D/\!
+ML_0(\9@9"?V5!+49";8E`9`10+,M`$__/J/T`%@9`@__9I_T&W>_%9A9`3-@
+M`!>8>:(SD``*LCH^^/4`LDH^^/4`QYE#,)8#]`T,VO@-```^^/4`VOP-``!8
+M&P.]Q`W_\+,`?OY8`+*@LZ``,9BI!7WT=:\)LY``);):?H=>`+WT\*3_MJ0#
+MF`D%O)J0O)^0-9A)D/\!L_0(\9`B`9`1$-^8#0``/_GPE/^F*?4(=0\39`?4+M@#?E!0`
+M`#WD/L'V`+_YD/\0IIOT"PL0[@$FX/0(\;-```XS%``*,-8$]`P2LSD`A``S
+M%``*,-8$]`QX\.3_W904``"4Z02\G9"@F[^_O.Z0W9P4``"VE`/'__"\G9`@
+MGS,0`@BS4``7$O\#O.Z0W9P4``"VE`.\G9`@G]^<%```O.Z0E)T#O-_0&-\!
+ME.D$WI@4``"\GI!@EW6<`?#T`?0+"C7<`3Y;]P`0``$^6_<`$"(!MJ4!D+M`
+MLZT`-/_^20':0#@``)"9)[W$()*])+^ILYD`S@"8J0'?0#@``)3+!IBN"+R_
+ML,>?0YB]#<3Y`?4+KP#'Z6@F&?4;I@#$V?_PG`OPE@&F6?4;EP"S0``.,Q0`
+M"C#V!/0,$K,Y`(4`,Q0`"C#V!/0,>9B_"24G`,^&OH`Q+D!]0N(`)@]!;S\!CY23.4`!88_P$S]``&^`B\
+MW)"\GI`UGTFS0``QF#\%L::[`/0-%KS\\+S^\!CY29*JO!*91#[\^0"\_/"\
+M_O`8^4D\FI`^#_H`F#\%L::[`/0-&;S\\+S^\!CY29*JO!"91#7Y23X4^@"\
+M_/"\_O`8^4D[F@(U^4F]I)#N`;:U`;.P``FSK0!K__M!V8`M``#?`",``/0P
+MZ/F"OY"8^:2PX0G?_`T``+"A##"1-_"4_[*VE)X"E)@"O._@V0@.``"PP0NP
+MT0J5!0*PX0Z\B8#4`"8```<"/A3\`,19`?4+E`&TX`R83P&_ZJ5^^7L`LJ&SI``&^`B8&0FR"KW$#?_'F824GP6VE`*[^0+9]`T`
+M`+SY\%C[`?"S`'[^6`"RH+.@`$98J0ESE``*6*X(=:X)WP`C``"8^:*8&@0S
+ME``+E:(0/N+[`+(:?K2!`+(;LJ*]Q+(*?D?Y`%@)"7N2`G4)"3[Q^P#X")@9
+M"?&5`!"U&0FS-`$0O>39*%H``*">]#$2ME4!D'"`X``/"4_Y2:`K:4`KRKH+R>D##Q7["A'+"1&[WT"0<]I+#!
+M#;#1#--`+@``L/$2L)$3,*%G/MT!`;20%O"4`?4+.P6TL`Z8/P&_NT$O?39*%H``*"?]#$2/MH!
+M`;\Y-*!?MI40,)%4,Z`"%MD`(P``F)FB,Y0`"KVT/B[]`#2P5!*[`S"Q5`L!
+MLCI^R($`-.!?,^``3[3P'S_Y$)D!(/DQED8`]!T.M*`/"0>@J3YM`0&TL`W?
+M`",``)C_HK^YO)J0H+DS\``3M.`;#P&P\1*PX1@^ROT`M)`P!$+D!VI@-```@
+MJ3XN`@%0R0%@&7\;Y+G__Z:4]1XS_SX&`0&TH!BR.[W4?J%>`+.M`?T!LCI^
+MM($`S:B\S*2\LX0`"TB\`#X'_P"01`'^20&0F79_GY)+`;V4?61V]0.PL0ER
+M_G#Q*?#C`+#A"C[W_P!T`#NTH!BTP`JR._`#`+Q0`+(-?BB8`/`$!Y`)`0\!
+MTI04``"[^02RH0D!L/$0NY`$O02PD1H^R?\`6"D""O]FFO0;5Q@I"?"4`?0+
+M3A@I"%@O`[3@"@L!O+F4\/,`_^F=II_T&S6_*9B9"L>?Z+20&OV?!/0+)+20
+M$/V?!/0;#K(Z?K2!`+.NO``,D!&\/L/_`,VIO+P9$)```9`B$-^8#0``/_GP
+ME/^F"?0(D+20":99]!L*O!B@/NK_`)`:O+&FO`#U#/(`4&8!"0'D9?__IE3U
+M""[_LYD`Y`#^20&8/P&0F79_F9@]"L2:!\?Y0[.4`2N/_P#__]_TNY0$DID!
+MNYH$MI0(\93___V?!4\`__V?!+4Y"CZ*``$.`;SJE+:4"/&4__^/_P#__]_T
+M_Y_5D$D"M3T*N^D$D*D!DNX!O.F4L9;_`/0-"K.@``?PE0'$G_])`/__V93]
+M^06U/PK:F`T``#^L-)!4VYP4``#:E!0``,3._[SN\+;T`[S[\!C]`2#YE.D$
+MO)J0\-4!-?T!=/`IH).VY`3;F!0```G_O.O@=>\!8.D0S`':F`T``""L/BX"
+M`0LCL+$3_D\!D/]V?_E0F0%@^?Y,`;3@$9#,=G_)\),`II[U'MO]M)`3/F@!
+M`=D`(P``-*!4F)FAY)W__S.@`#/,WGV4[P*4Z0>[GP*\GI"FG?0+!I#N`32P
+M5`D!NYL$INGT#5L)';3@#Z#I/FT!`9@Y!(_226NVE1#_GYP/<+OY`J;]]!@Y
+M"1VT\`^@^;-]`;H`O?39*%H``*"?]#$2/B<"`3207S.4`1>8.0''F>BSE`(-
+M-*!G$*H!,*%GLW0!$+WTV2A:``"@G_0Q$K2P'[3@"S^_/^GP\@?PD@>\^?"Q
+M]D8`]!T.M/`/"0>@^3XG`@&TD!:VE0&PD1:0,T"TH!:SK0"P^C2P9S.P`#39
+MB%P``#^>,^0`'-D0%``!H)I/``&0F02@GP\!N)GT`0"@GS3P9]F(7```//[P
+M()^TX`\)`:#I/BD"`;V4LIK[A50T\%\S^0#<_CZ"`0'$J3_Y$I20!MF`)0``
+MLJ&\"0#'J<;T&P7X"+(:?HWT`+\)QYF*]`L0F`D-C___S_V?!+4)#=X`(P``
+MF.FDC_\`__^?]/&4`/^XF0`!`/&4___]GP6UZ:28"0''F2.SE`(0F`H,"P''
+MJG1^'E,`2PD0RV]`3^20'=<`0``)"96+S]\*">O<22F02P\0V@GK#!
+M#CY2"P&S&0GB`[`6"?0,*;,9!3$!L!8%]`P0LQ`!7+,=`R@(/@T$`;,9!ZD!
+MLQT(&@@^NP8!LQD,306P%@ST#!&S&0H2!+,="P$(/F<(`;,9#\X&LQD0Z0:S
+M'0WN!]"4%````1"]1+UTUBA:``#8`",``#X#"@'9`",``)B9H[:5&["1#I*9
+M`K"6`?0-";(:/NH#`=G`+0``OY[9Q"T``+^?E>D;]`L/E?D8]`L/Q^D:]!L)
+M"1$^)0@!?@;S`+*@LZ`!"J!:/F8+`=Z@)```F.D#QY$)]`LBM/`.L_0#%-D`
+M(P``LJRUFH^R\3Y2"P$)$Z!9/F@+`=J4%```2P`"?K\W`-F8#0``L@P@D0$'
+M/E(+`=H`)0$`V\`H`0!^H%@`LZD`-0>SK0$P!]X`!```O^^R'$G_[P$%_?D$
+MH.\^4@L!VJ`D``"8J0,`_,>9"?0;"MF`+0``OY"R"GZ8)P&SJ0#I!@\!V0`C
+M``"R"K6?CWX?)@':`"4!`-O`*`$`?D!8`+.@`0;X"-V@)```F-D#QYD)]!L)
+M#`4^U`8!W``C``"8SZ.8SJ#9____!PT!_?D$_>D$V0```!"@7?WY!;+:V0``
+M``BUSZ/]Z06USJ`^:`L!O?3^20&0F5"@GY*9"*"?DID$_D0!H)^01$S^0P&@
+M3Y`S0/Y"`:`_D"(\H"]^,/0`H%JSK0%H!K*L_D`!_D$!D`!?D!%>L@JR&W[L
+M@0"TX`ZSY`,:L%$`LDJR*[(\L@VR'GXE^@"SJ0`U!OY)`9"97K"1`)*9"K"1
+M`9"9!/Y"`?Y!`9`B4)`11/Y``?Y.`9``2+"1`K):LBNR'+(-D.Y??BO\`+.I
+M`/<%_D\!D/]`OPV__K\<_DD!VP`$``"0F3R8OQJ_F;R?D+R>D+N=`KN<`O0?
+M"0D(/B4(`9B_&;\N_DD!D)E,OYF\GY"[G@+U'FL"O00)$OZ0#/0R$O0R$O0R
+M$K,$`0O9*%H``*"0_DD!D)E4OYFSE``0_DD!D)E8OYFSD``Q"@%^D_0`_DD!
+MD)E4OYN0F02_G+):?E'V`+.D`!2S#0%:!=DH6@``H)H^=PD!LP0!$+WTV2A:
+M``"@G_0Q$K3P#?Y)`9"90-X`!```O_V_GY"9"+^;DID,OYRTD`V[^P*\_="T
+MH`R@G9CM&OY)`9"91+^;O/WPM>\:OZF[RP*8X!F8[1B\R9"@J?Y)`9"93+^?
+MD)D$F.L:OYK9@"T``+^9O,O`N_H"N]\"MI4"O/#PM>P:M>\9M>T8WP`C```,
+M![7YB@$("0*U^8L^4@L!V8`M``"_GPX!V0`C``"UGH^V]0+T&PNR'`$)/E(+
+M`;(<`0,^4@L!V8`M``"_F;VTE9P"/OL&`9+)`9"[`?W)!+/$`/?9A"T``-J@
+M)```OY^8J0/=`",``)C>I+;U`K:5$O&4P!_PE0*UW(VUWXJUV8N/_P#_Q^GH
+M#`F[FP+][P2VE`@!"O&4___]G@6UV:0^4@L!V@`C``"8K:3'V1CU&^\#V<`M
+M``"_DMD````!_]D%M:"DQRD:]0O6`YBMH)BNH=G$+0``OY_9````!/_9M=D`
+M``#_M:N@_?D$V?___P#]Z03]_@6UKZ''N72SG0.A`]G(+0``OYZ8K*+?_`T`
+M`-G____]_[F4Q`W_MM0"O-_0WP````+_+_3]^06)```#_>D$B?___+6OH/W)
+M!/WL!;6NHAC9`;(<`0OPE4`UV0$^4@L!\)0!F!"+]`M,L@KP!#^U$(U^.@(!
+MM@0&V8`E``"\"0"SI``,"0>@63YF"P&8"0'PE`CT"R"8*8J8+XNU((X,"[:5
+M`9#_`;4IBK4OBP$,/E(+`9@9BI@?B[:5`9#_`;49BK4?BSYL"`'1`",``)@9
+MBM(`(P``LY0`BPP+/C(*`=D`(P``F)J+4JH!?OE[`+*@LZ0`!O@(V0`C``"8
+MF8O:F`T``#^OW904``#PE#^]))2>!O#T_]F`+0``O.G@/MX(`;_9D-T0INGT
+M&Q24*03:E!0``+R:D*"0/N,(`9`B`:8O]`C@W9@-```_V?"4_Z8I]!L%^`C9
+M`",``-K,-0``M9"."UQ^OS<`Q0D$N)D`(`+?##8``*#YV>0U```/`;T$H)\)
+M$OZ0#/0R$O0R$O0R$J8/]!L*V2A:``"@D)0I!-Z8%```O)Z06)T!V0`C``"8
+MFH[;S#4``/#3`+)C`+.@`"._6;.0`1NS#0']`;WTV2A:``"@G_0Q$K(*
+M/F@+`0$+#`RS#0'.`;WTV2A:``"@G_0Q$@P,/E(+`;)S#Q+^\PST,A+T,A+T
+M,A*S-`$&H&-8#P()_V;Y]`L\6`L#\/(/Y+G__Z;Y]`LM&`D)\)0"]!LDOP+P
+MLP"R*GX08P"SI``-M8*.`0\^]`D!&`D)\)4"-0D)LS0!":!G]#$2D$0!D``0
+MVI@-```_J?"4_Z9)]`B,#`T^4@L!V8!4``"_FMD`(P``F)N.?E]>`+(9Z+.4`2^8WZ.8WJ#9____!_WY!/WI!-D````0
+M_?D%V0````BUWZ/]Z06UWJ`^P0H!F-FCW____P?>P"4``+W$_9\$WP```!C]
+MGP6]]+79H[_ID.Y`\)0']`L%LOR0_P&S]!_PW0`C``"8WJ"0R0'?____![:4
+M&_WO!/V>!;79H-V@)```F-D#E9\8L/8D]`PTV0`C``"8GJ"8G:*8G*&2_P&V
+MY1"\_Y"VU1:\GY#?V`8``+:4!+R?D'6>$W6=$'6<$7XP5`"]!`D2_I`,]#(2
+M]#(2]#(2LP0!"]DH6@``H)"]I'Z3]`"S!`$0O?39*%H``*"?]#$2"0&@6;*:
+M/F@+`;(FD/0;',3Y'[P9Q,3Y?Y6?!;.0
+M``V\KYC_R96\J?FFZ_0-T?Y)`;WTD)D,#?^_GI"9!*;M]`LC"P&RO;/T`PBS
+ML!]!O-N4_9X$]`L9D+L!L[0@[#ZY#`&0_P&S]`33/KD,`90O`50)!]Y4)```
+M\92`![S^\/V;!;*Z=?D!/KL,`;VD^R40V<0M``"_F8Y!`A#?P"T``+__QYGP
+MO)Z0MI0$OYG'_W3'GFJSY`$3DOD!O:2PE@'T#!RRZO@`L^0"#+#V`O"L"_@`
+MO:2F_O0,!0H!^`#9A"T``+^9\)0#LYT#J`'9@"T``+^9LYT`G`'9`",``)B9
+M:\>9"?0;:MG`+0``OY\.#XG__P\,!?_YM++M/E8-`;;D!/W>!3/```T2S`'_
+MZY3T&_"YV0#_N93U&U@!V<0M``"_F8Y!`A#'F?"\GI"VE`2_F;.P`!!^O@P!
+MLZ0`%#Z]#@''_W3'F6JF^?4;)@'9P"T``+^=E=D;LYT!&`'9Q"T``+^?V0`C
+M``"8G(3'__#U"P$!ECU&\@`V<@M``"_G^?)2`&2F0&V]1:F^?4,
+ML0#9S"T``#^9,YT`I@#9!"X``+^?Q_E#LYT$EP#'^>CU&X\`L^0$$97Y$+.?
+M``*$`#YB#@&SX`,(L^0!#I7Y$+&60`#T#&NSY`(-E?D0L)8(]`Q>E?D0]!M`
+ML^`"'[#F`O0-)+/@`R&SY`0=Y/G__]\````"/IL.`>3Y__^/```(/IL.`>3Y
+M__^/``!`_9\%WP0N``"@^=D`+@``OY_'^?"PE@_T#`O'^8KPK`OX`+VD^`#?
+M`"X``/DRQ*,_DCD!MI0&O)\`W\`E```,%+R?$+(+LJ*R&GY4-P"_'Y@>`0GX
+MF`H*_?D$O93P]0&U&06@'\?L0\3+`?0;#-T````!/A8/`=T````#F!\!O92U
+M&0^U&0FU&0['^>B0F0&VE!O'_R&U&0>V]!*)```@_]F5_9\%W@`C``"U&0:8
+MZ:28[Z+$G?^4V0CDG@`/,_``"/'E`!"SL``GV0```"#_Z?6SU``OL,8$]`TH
+MV?___P__^93?````,#Z8#P&R[[/4`!*PQ@3T#0O9````$/WY!;4?"+.P`!C9
+M`",``)B9HC.0``SDK___/K@/`;WTB0``"/_YE;49"MD`(P``F)FB\)3_]!L)
+MO<0^Z@\!MI0!WU0D``"\GY!8F0'PE'^4G`C9`",``-\P&0``F)ZA/_"8G:/'
+M[O#$"_^FZ_0('-DN&0``/YG$G_^\^Y"FZ?08"KSKDCXW$`'9,1D``-\O&0``
+M/YD___"4__#T_[SIDJ:?]`@%^`C?``#_`/#4?__-U;:4$-P`(P``_9\$E2X&
+M_9T%MN08_9X%M1D+F,V@F,^DB?__#PX$_]FD\/3_]`L^Q]YTLZ0`#+/T`2,^
+ML1`!L_0!&YC)HC.4`!2SX`,AL^`!';/D`A<^LQ`!DND!L)8!]`T+#@$^LQ`!
+M#@/9`````O_9E)3O%/WZ!?WY!=D````$_]F4E#X;_?D%V0`C``#]_@6U'PR8
+MG:+$W/_T&PF]Y#Y-$0&8F:''GO"FZ_0(']DN&0``/Y_$"?_P]/^\^9"FZ?08
+M"KOK`CXJ$0'9,1D``-\O&0``/YD___"4__#T_[OI`J;O]`@%^`C9E%P``#R>
+MF(\```/DW@#__>P%MI00_9\$_>D%C___/XD``,#_[_3_V93]^06U'PW[,?E"
+MV\`M```,0-J`)0``?E0W`-F@)```F)H#T@`$``#0P"0``-/0)```MJ42\:3`
+M'_"E`7[!#@'=`",``%C;^)@N"]S@&0``V<`E``!U"P%_S[4I#ME`(0``F-&R
+MF-J]V\`E``#PY1"UFR:U+@N]E+4Y`;\D\/40M=FS8,\@":`Y=0D#=0D"B0``
+MP+4Y`OVI!=D``)``Q!L!M=FZ\!0/#_#9P`0``/V?!/V1!;7:O;79L@D%-0D!
+MB0@`P+4)`N6Y0`BU"0.)`!`!N;P`_;D%V>`D``"U.P.UG`,)_?U)!*`D^T'Y
+M`L>NQK+`L.8D]`Q)F+D$F+P!C_\`_Y+N`?V?!)B_`O&5``&UN03'S?"\[I"\
+MGI#>V`8``+:4!+R>D#6=)%B[`;;U%G6<$76?$'6;$[(+?I$V`/L!^2+;P"T`
+M``Q`VH`E``!^5#<`V:`D``"8F0/=`",``-P$80``QYL)E9(8L[``'IC9H]__
+M__\'8,+]GP20_P']GP6UV:,^!!,!F-FC?\[?____!_V?!-\````0_9\%M=FC
+M\.3_IN+T&P5@R]$`(P``F!ZCF!E\F!VD3P#__>\$\)3__9X%E"\0M1FCV?__
+M`/_]V03]_064(`:U'Z3Q!,`?\`4!L@I^P0X!VX`E``#O+[(F!V@\/0?"0&[GP3]G`6\N>G'W72SU`-(F!FAWS`9
+M```__\>>\/#T_Z;O]`@=V2X9```_F?"4_[R?D*;I]!@+^`B]Y#ZL$P$.`=D`
+M(P``F)FBWY1<``#'F3`\^>G[(=D`(P``]##\O?3Y@K*C_D8!LI*8D(F09B35
+MT"T``(A`0@_4Q#4``->@)```/D86`;,)`VP!L`8#]`P0LP`!(K,-`D0"/A45
+M`;,)!=P!L`8%]0B6`;,-!B\"/A06`7X+#0&SI``."1&R"J`Y/E86`;]*F"]4
+MO`J4_9\$]`L8?H@#`)@O5+])O`F4N9D`_9\$M2E4V<0M``"_F]G`+0``F'H#
+MOYR_3MG(+0``OYW'J@G'N_#'S'3PU/]^B@(`B?__`+*@IJGT&PD)!#ZW%`&_
+M64\`_\2N_]U`.```_9\$_>D%O92@7K_1D)D!D-U`LQ``$K.41O0)!Z`Y"@$^
+M5A8!OTJVI`;QI,`?\*4!?A$V`)AY`\>9"?0+#+4A?`\!/E<5`;]*L@M^`@P!
+MM2I\LZ0`$]G$-0``OYI^B`,`/K44`7YC$0'>)````;_I#P$``K4I!3Y&%@';
+M``0``+^\Q,D"]!L8F"H%?BEN`+(/IJCU#1D!``,^1A8!W>`9``!_WY@NM@G]
+M_\F4\?3]_Z"Y8-^VY1BSY`$ML@\`!CY&%@&]E-_)-0``WL@U```@^:!I(.G:
+MP"4``+)K?L2L`+.D``JR#SZT%0'?)````;_YOV^U*06S\``/OUH+`?"D_W[+
+M`P"R#P`$/D86`=[)-0``/^DSE``,#P0`!3Y&%@&8*@5^*6X`#P2FJ/4-@0#X
+M"-\D(``!O_G>)"```0\$``7QE0`0H.D^1A8!T,0U``"_"ME`(0``O12UD29^
+MB`,`OPD/!`H!H#^VE`'?5"0``+R?D'61`3Y6%@&]]-E`(0``M9\F?IH2`=T`
+M(P``V<0U``"8WE2_F0\!H#^R^KSYE/V>!;795#Y6%@&R#Z;P]1NI_=D`(P``
+MO:2UGXG[A03X````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````````````/@`]#"D
+M"USY`C*@_DH!D*H$?K\W`-F@20``\`3_E`H%O*F@F*\%Q_D1LY0!3,?Y$O0+
+M*,?YC)2?!;:4`KOY`ME\4@``O/GPF/D#M:D&Q:D$N)D`(`*U^0._JPGP_D\!
+MD/\$_;D$"0&R_+B[`"``M?D5?K*#`/L%7)C9"IBO"/0P^/F"6)D!LN>RTK*A
+MY)3__[*VLLC'_V@T4#"8J0&8K@DS\``&^`@U+QS'F4/P]/\PE@/T#`^V]`+9
+M_`T``#[)%P&V]`+9^`T``+SY\!@9)[4O"#4I+!@?+\?IA/"0'#4O/=_T#0``
+MO)^0M2D*F!D,MI4;-2D^,U0`"KT$/AH8`<19_Y20!=F@20``O`D`F`D%CP``
+M`OV?!;4)!9@9",>9$?0+$)@)!8\```3]GP6U"048+"S^0P&R2I`S*+)KLCU^
+M=((`LZ`!#*!ZO:0^_Q@!OST)_Z;9]`LUM2H4=2T7LFRR&K(K?C6A`)@9",>9
+M$?0+'+(:O;1^6(@`F!D*C_\`__V?!/&5``*U&0HS4`!OF`D%QYD2]`MEL@JR
+M&W[?6P`8+"RRB_Y``;)*D``DL@U^=((`V0`H``&_#K^?V78%```_F?'T_S_P
+ME/^VE`Z\GZ"FKO0-&!@I++RDX@\!N_D$DO\!_^^4/O$8`;RDDKB9_W\`"@&P
+ME@+T#06]I`D!H'G[A0CY@MD`(P``]##\LJ:RDYB1B;U4O72]Y-04)0``V"A:
+M```^41P!LQD#70&P%@/T#`^S$`$CLQ0"&3[Y&0&S&06E`K`6!?4(+P*S&0;Q
+M`K(>/E$<`=F$+0``OY[$[0'T"R/9R"T``+^?F#F$MO46YYE(`:;Y]`@-"1&R
+M&J!I/F$<`<3I`O0+:9@YL/"4![.0`0ZSD`,*"1,^YAD!F#F@W@0N``"_[\>9
+M=+;U$+.4!`ZS^P`"G0(^Y!D!LY`#%[.4`1RS^0B+`K/Y$(8"L_D@@0*S^4!\
+M`C[D&0&SG0)S`K/Y"&X""1&@:0H!/F$<`0X!L]D`I``^11P!V<@M``"_GY@[
+MH9@^HMG$+0``OYV8/&N)``#`_?D$B?__/^35___]Z02)``#___[E_[F4M3ZB
+M_UF5M3FAY+?__Y7)&+"6)/0,()*9`;;E%KR9\+SY\-G8!@``MO0$O/GP=?X0
+M=?41F#FD,Y0`,*9U]`LJF#^@"0$.`B!)MO4;V14E```!`R"?/E$<`=X5)0``
+M/T\_Z2;Y]`T+LAX!!CY1'`'$^?^4D`;9@"4``+P)`)@)`;\.QYD#,YD`N@#$
+MZ0P"RHK.D``;X"-K,-0``"UQ^
+MOS<`Q2D$N)D`(`+>##8``*#IF`D)O03$GP\)$K4_B_Z0#/0R$O0R$O0R$K,$
+M`0:@@+(J,/$`LENR?-W,-0``LFY^>!@"4``,0)_[:4
+M!KR>D)B:",>J:'X"!P`.!+.I`*H`O00)$OZ0#/0R$O0R$O0R$K,$`0:@@)@Z
+MBWX"%P&S!`$+O92@B?0Q$C])LAX!`Q"9`2!)/E$<`9@YL=X$+@``O^^8/FOQ
+ME/__MO40E/`0_PF5M3FQE>H8L*8D]`PB=J0&\:3`'_"E`7[Y>P"SH``1F*D!
+M\93___\)E;6I`=^$+0``O_D.!?"4`?0;$SZ2&@$)`:!ILIH^81P!#@$!`CY1
+M'`$.`0$%IN'U&]3\V0`C``"]I+6>B?0P!/N!^```````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`/@`^8+9`",``+*FLI68DXF])+T4O438R34```?D+5?BO0+#IA9H+:5
+M&Z;Y]`T)"1,^VAT!O/.2TL`E``"4D0:\$A"8&0R8&@NVE1NVI1BVI`;]J05^
+M^7L`LJ"SH``.LAJR"PQ`?E0W`+\?M5".Q/H'DJD#L)8!]`T5LZ0!$L?YBO0;
+M"PD3H&D^TQ\!F$D"\?0`?+:5$/0+')7Y"O4+#``"`0,"/L,?`0D%H&D*`3[3
+M'P&5^0KT&_._2=W`-0``LG*@U[49`IA/`0,$M1\#/L,?`0D!TL@U```@B2`I
+MW!9@?!Y@="+49!9A"`4G_X/W*!/"T!_W+!?W)!(G__^"VY1NV]1NV
+MY`BV]!#][`7'W1O]Z02VU!C][P79_____OWI!/WM!;42![5>B[(:LC)^_GD`
+M`P,^PQ\!F%F*/X^[EP*4D0;9P"4``+P9$)@9!C/]`.0`W![4:"`,$/L,?`9@?!Y@>!I@=!=G`-0``OYR)``#^_?D$V?__?_^U'P?]
+MZ039````_;4>!OW9!+4=!;/$`1>_'\3Y![.0`0X)^/_YE/"5`Z`9V0`C``"8
+MFHZSH``,LAL,0'Y4-P#9P#4``+^9/MH=`;(R/L,?`0(#IB/U&US]V0`C``"]
+MI+62B?N!^```````````````````````````````````````````````````
+M`````/@`^4+9`",``+*DLI.8D(F]]-$`!```0O_O/EXA`;,``ABS``0[LPT!
+M,`&U,(^R#P`"/EXA`=H`)0$`V\`H`0!^H%@`LZD`&`&SK0$3`;\9L@\`!/V2
+M!*`9/EXA`0K_?I@G`;.I`/,`"OQ^'R8!#P'9`",``-H`)0$`M9^/V\`H`0!^
+M0%@`LZ`!!O@(T``C``"8#;N8"KR8#J"8#Z.VU1B4V0:VI1O_FJ79````"-'_
+M__\'_>$$_?$$_>D%_?D%V01A``!@G4D`__WY!+4.H+4/HW[Y>P"SH``UF*T+
+MF*\%OZX)@/W9!/WQ!`GX_>D$\.4!LJNUKP6UK0N@K@Q`VL`E``!^5#<`/BTA
+M`9@/NY@-L)@.M0F`_?D$"?C]X03]V02U#[OPU0&U#K6U#;#9Q#4``+^>V0`C
+M```/`;6?B=E4)```MN0!H$^\Z>"R^GV4=>D!/FXA`;(//EXA`0\"IO#U&[[^
+MV0`C``"]I+6?B?M!^```````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````^`"2J@'=5"0``)6N!=G0(P``/]^VY`*\
+MZ>"_[/"D'PD!$O\!NYH$(-^YF0#]G`2@Z?@`L*8D]`PDDJ\!O/^0O)^0W]@&
+M``"]Y+:4!+R?D`__M9X+M9X*=9\0^`#Y@MD`(P``LJ2RD9B0B;W4T\0U``#2
+MP"0``-95)```U?___P?8__\`_]<````(/@XD`;,)!.,`L`8$]`P0LP`!&[,-
+M`F:L`LZ0`#+(*"0L^_B,!OSZ8'U2\
+M#I3]GP3U"SD!F!F@H"F8'Z'9S`8``+4O`;SN\+S^\+\NMO0$O/GP6/D!_>4$
+MF"T!F!RCQYF+MI0;_9X%M1F@/_G]V`3?``#_`+;%&[:4$/V?!/V=!;49H;/)
+M`.8`DLD!L)8"]0S;`+40C[(-``(^#B0!"O]^F"4$_9<%M1^/M1ZUM1FC``0^#B0!OSI^B`,`OSW95"0``)3?
+M`;SY\%CY`7.0`!@_;GV4=?D!Q.G_IIWT&P@2Z0$@:;\O#02U'Z"8*0&U&:$^
+M#"0!OSI^,R(!OSI^`B(!L@T`!CX.)`'=`",``)C?H]G$-0``F-Q4OY[9____
+M!_WY!+7?HPH!O*[T__R4]`L2N?D`H$K]G`2UV50^'B0!2<$`H$D^'B0!L@T^
+M#B0!#0$`!:;0]1M^_MD`(P``O:2UG8G[@0``````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````^`"8J0R8J@OY$K:5&[:E&+:D!OVI
+M!7[Y>P"RH+.D``;X"-K,-0``"UQ^OS<`Q0D$N)D`(`+?##8``*#YV>0U```!
+M`;(*H)';S#4``'Y9E0"8"0GPE`_T"R.\D:+9P$D``+:D!;RIH-D@-@``L@N@
+MD=S,-0``?K*#``H!^Q&8KP'Y(K*@LK'$^0CT"R>8J0@+`<>9:#.0`A"8J0WP
+ME/_PO`OPM@&R"G[(@0"@&C[#)0''^2.SE`(0F*H,"__'JG1^'E,`V20```&_
+MGY@."Y@-#-G\80``D/\!E>(8E=$;H)^R*K(;?OZX`+.@``A^6K@`LBJR&W[^
+MN`"SH``&^`B8"0R8"@NVE1NVI1AVI`;]J05^$38`OPD/^/V?!*`)^R'9`",`
+M`)B?H)B9I/0P]/F"MJ4!,IBVE`2V]1ODDO`/_D;R?D+59
+M'#[E)@&_+[]YO)^0H"F861B87QF2F0&0_P&U61BU7QF0,P&0$4"TD`FF.?4(
+M8/_[A0S?`",``)CYH/0P_/ERE:4!E90;O93^3@&R]Y#N(-#`)0``H.FRY@G_
+MO12U^8J])`,!/G$G`;PQE/V5!/0+)[\)\)0']`L?L@JR:W[$K`"SH``4F`D!
+M`@'PE`CT"PBU`+.@``H/`SZ?*`&0(@&0`$"F)/0(LCZW*`$_>3.0
+M`$D/`P$(/I\H`3]Y,Y``.Y@Z!7XI;@"FJ/0-&/@(WR0@``&_^0K_\94`$*#Y
+M/K4H`;(?IO'U&Q?_V0`C``"]I+6?CSZU*`$*`?N!"?^U.8H^:"@!^`#X````
+M````````````````````````````````````````````````````````````
+M`````````````````/@`^2+0`",``)@.:[*AF`F@Q^^0]0O!`+:5&Z:?]0BX
+M`)+Y`97J&)22!K"F)/4,EP!VI`;QI,`?_:\%?OE[`+*LLZD`@P"_J?"4![.=
+M`HH`F`EKQYD)]!L1F*D%W____P?]GP2UJ06_SYC.!IC-!0GX_?D$V?__?__P
+M]0/]Z02@S]G____]MD!O\_9`",``)B=CMD````;M>D""?#]^02@[YC)`YC?`L>9`<3^`;.0``?P
+MY@&_R0_P_9\$_^F5M=D"F,P!M=P#^`#9`",``)B=CIB>:P_PW+`D``"8V0+:
+MP"0``)BK`\?ND/V?!*#)V<0U``"_F9C?`[;D$+:4&/&5`("USP'_GN79____
+M?[7.`_^Y]+6O`[_9QYF*]`L.O92UR0&@R3Z_*P&8V0+_^9;PE`'T"PS9````
+M&SX;+`''N:JSF0:W`+"6!O0,#K"6`?4(V@`^[BL!LY`'0;.=",X`/JD$Q[X$M<\!F-\%MT#^`!^`BL!"@'X`-D`(P``F)N.F)IK^1)/
+M_]^8N0B_OOV?!+6Y",3A![,4`1`)^`$#_^F4\)4#H+F_N<>9BO0+$)BY#8__
+M__[]GP2UN0V8N0C?___O\T#!`/V?!+6Y"-D`(P``F)F,\)0$]`LBV<`E``#'
+MJI```0Q`NZ`"MJ0&O*F@?E0W`+,0`P8`$[(*^Q'9`",``)B?:_DBF)F@Q_J0
+M]0OO`+:5&Z::]0CF`-F`)0``E*`&O`D`F`D,F`H+F`(!MI4;MJ48=J0&_:D%
+M?OE[`+*ALZ``#K(*LAL,0'Y4-P"_"<2:![.M`:D`LQ``:+WT"1+^GPST,A+T
+M,A+T,A*S]`$+V2A:``"@GY@9"/&5`""U&0BS]`$0O?39*%H``*"?]#$2Q1D$
+MN)D`(`+?`",``+7YC+7QCKV4M?F-Q"D(]`L)"10^B2X!"0VU^8D*`3[0+@'=
+M`",``)C>?9@/#-P`)0``M=".E.D#O)R0OYFV]1NVY`.V]`:\[>"\^?"UWXR8
+M[H$)"K79B;7>C3[0+@$*$_LA^5+9`",``/0P^+*4F)")O?31``0``(/_?__5
+MP"0``-+@&0``/ODO`;,)((4`L`8@]`P0LP`>&[,-']@`/D,O`;,)(8H`LPTB
+MR@`^J"\!?RF_'YA*BO"5`O'U`(!@*:`??I-\`+(/LZD`P0``'S[Y+P&_&9A/
+MC@KPW,`D``#]DP2@&;V4F/X"L)$`"0(PD028^P/_ZJ0-$-ZRJP``?CO"`+(/
+MLZD`A0``(#[Y+P&_'^3Y`(!SE``*L@\^^2\!__.4L@^@&0`A/ODO`7Y3*P&R
+M#P`B/ODO`=JP)```?;3<``0``'X`/@`SI``_F%D#L)8`]!\M?NPL`=JP)```
+M?;3<``0``'X`/@`SH``6/O9
+M$_0;%)@)"K(>M2".`0W]F`4^]#(!"0&8*HP@22!IF"N-F`P*?H1$`+(>`0L^
+M-S,!/TDSG0"!`I@JC)@KC;V4L)$`"0*R/#"1!`U`WK*K``!^.\(`LZD`7P*R
+M'@$,/C/C9&_WO!+:4&/V>!;4IB^3?
+M__^)_?\`IOGT#0V)``#__]F4M0D*/=0)`2!)(&D@69@/"C/0`!_9____^/_Y
+ME-\````!_9\%M0D*/90@63X1,@'9____^/_YE-\````#_9\%M0D*F`T(Q]D3
+M]`L=Q]]HV?`9``"\G^B5WQP)`;N?!+7I"#XZ,@&R"G[^>0#9)````;^9LAX!
+M#K4I!3XW,P$_:9@@CC.4`!$_23.4``L_63.9`-``OPGPE`>SF0+&`)@J!7XI
+M;@`.#HE`0@^FJ?4-O`#X"-XD(``!O^G?)"```0X.`0_QE0`0H/D^-S,!F"^-
+MF`X-F`P*F`T(OPN)__\_MO06_>D$_=<$V?__?_C]_@7]R02U#PVU#0BU#`K'
+MN8KT"RZ8*8NR'H\``/\!`L>9&+:4&_V=!;4)")@IBO_/]/&4___]GP6U"0H^
+M-S,!Q+D'LY`!#+(>`0(^-S,!V?IA``!_F;(>`1[PDP"U*8H^-S,!V0`C```*
+M`;61B3Y',P$.#@$//CB?0P"/N!^7+9`",`
+M`+WTLI>8D(F8D8[6@%0``-7Z80``!!*]--(H6@``/A`T`;,`%D^S`!=?LPT4
+M@@"R,/Y`#/0R$O0R$O0R$K,$`0:@(+(:?;1^Z(X`LAI^C:P`LZ0`$[,$`0F@
+M*O0Q$@\4/M$S`;,$`5:@(_0Q$CX,-`&_:K(;?E]>`+(/LZ0`0P`7/A`T`;\9
+M\)0'LY`!$M\`(P``"0*U^8D^!C0!?UFR#P`>\),`M7F*/A`T`=D`(P``M9")
+M"@$^(#0!#Q0`%J;P]1MB_]D`(P``O:2UGXG[L)8$
+M]`Q4/HTT`7[/+0&@*K.@`32R"C[&-`&U$(E^#C`!/I0T`;40B7Y,,P$^E#0!
+MM1")?M(N`;.@``JR"CZA-`&8&HF8$(D^MC0!?DHM`:`J"@$^QC0!L@JFH/4;
+M?O_9`",``+6:B;VD^R'X````````````````````````````````````````
+M`````````````````````````````````-K`-0``?AHX`0D.LZ``$-D`(P``
+M#P6UGP,)![*:^`#9`",``/D"F)]K/=394!H``-Y<&@``()V0F0&FGO0;^H"
+MY)____4+L@`]E#SI^3Y1-@'9``0``)B:(1B0B8L`4P=^0VX`W5,:``#>0"0`
+M`=R@)``!O^D/4,>9:K.4`0J]]#[E-0$S```&LJ\@WY#N$)#=`:;L]!O?/E$V
+M`=D`!```F)\E&)"9BXBG$;S_D+R?D)2:!+NI`KRJH'Y#;@#=4QH``-Y`)``!
+MW*`D``&_Z0]:QYEJLY0#"KWT/CXV`3,```:RKR#?D.X0D-T!INST&]\^438!
+M^`C[`2:K]!LXL\``-[+.#P&]E+:4!+;E!/"5#S+[L^``"Y#_`;/T!>[]G02F
+MG/0;$,2Y_[:4`KO9!3Z/-@&]U++:^`"_KIBI`?F"C___#[*B_^]DMI48L)8/
+M]`T%^`@]]-E0&@``Q^09()\,_P\!#5H^TS8!LT``"B#M/M`V`2#LD/\!F"D!
+MVU`:``"\^^"VE1BF^?0-X=!`.````UJ(B*<1LK77P$D``+\)LYD`B`"8"0'P
+ME`CT"WV8*@$8"2[<,1D``)@-##_+C___#[:E$+)L/)NP_=\$?E,V`;*ALZ``
+M59@)#,>9=+"6`?0(1K"6`O0-"[.4`ST^@C!?L!V0`C``#T,/B]Y/F"LJ3T,/BRD_Y&`?Y'`9B1B;TDU0`$``"(
+M_W__D&8PD'9`3Z3.0&8.FO'J7"2F0&PE@/T#0T)!;(:H$D^(3H!
+ME:(8]`L+LAX!`SX1.@%^'S4!"@P^W3D!LBI^>:L`LZD`#@'$*0&R*K4Y?;)K
+MLGQ^838`LZ``+I@Y?=T`(P``#@,!!I2?`[S]\-T`)0``MI0#O)V0OVV@G;]Y
+MM?F!/A$Z`9A9,9A;,K"A`,0J_K:D`[RIH`D"H&K>LJL``#"1!-P`)0``#1!^
+M.\(`#@.SJ0#M``D%#@.U.0,^$3H!OU\.!>3Y`(!SF0#5`/_XE`X%H%D!!CX1
+M.@&8/WV]E+"1``D"W0`C```PD03>`"4``)3Y`[;T`[R=D+S^\)B;@;_ZWK*K
+M``#<@"4```U`?CO"`+(>LZD`B0`!!SX1.@&_7^3Y`(!SD`!V__B4LAZ@60$$
+MV8`E``"U.8X^$3H!F#".OP_'^1KT"PK'^72SD`,."04*`:!)/B$Z`;(*?I,V
+M`9@*`;:E&)"J`7ZT-P&R'@$"/A$Z`=U@&@``F#F*O]^F^?0;&MG@&0``?Y\.
+M`:!.LNKQ]/W_8)\^(3H!LAZFX?4;./[9`",``+VDM9Z)]#`(^X4(^```````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````-P`!```VK`D``!]M'X`
+M/@#<`",``#.D`"68R2W>X!D``'_O#0:0F1"US0.UR2WQ]/W_LME@[SX_.P$)
+M";7)`[*:^`#X````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````#:L"0``'VTW``$``!^`#X`"0LSI``LW0`$``"_
+MV=S@&0``?\Y/_[_]GP2@V=D`(P``\>3]_P\!8,ZUGP,)![*:^`#X````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````]##X^3+1`",``)@9:_0P^/Y"`?Y#`960&,0)`9`B')`S&+(KLCRU&7VR
+M"GYA-@"SH``LF!E]OR(/%]T`)0``M1\#E)\#MI0#O)V0H)*_,[SQ\`X'M?.!
+M/I8]`=D`!```F)LRF)DQL*$`Q`K^MJ0#O*F@"0*@*MZRJP``,)$$W``E```-
+M$'X[P@`.%;.@``L)%@X'M1D#LNKT,`C[-0CX````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````-L`!```O[P*%N3)
+M`(!SD`!NWN`9``!_Z=\`(P``F/UKF/]]\93]_V#IW@`C``")_W___\F4D/]`
+MH+FV]`.\_I#>!",``+;5&+S^\+^"[6<"@\7V0`C```*![6?`_@`^```````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````#>`",``)CO?0D8W0`E``"UZ0.4^0.\G9"_
+MFK;T`_0P^+S^\)C[@;.D`#*SM``NF.EKQYFJLY0*$`D,M>NCM>D#/H(_`?@(
+M"04/$[7I`]G`-0``H)\^@C\!O92PD0`)`MR`)0``,)$$#4#>LJL``'X[P@`)
+M%[.@`!`/&-D`(P``M9\#"0>RFO0P"/@`^```````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````W``$``"_S0H8Y-D`@'.0`";>X!D``'_OB?]____9E`H'\?3]_Z#)
+M8._9`",```\9M9\#^`#X````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````````/D"T``C``"8
+M":#T,/BVE1NU"9#T&PD)&SY@00&8"7W>`",``-S`)0``3<`'E)\#MI0#O/[P
+MW@`E``"\GI"_FKV4L)$`"0(PD028^X&0JD#>LJL``'X[P@`)&;.@``L)&K4)
+M`PD'LIKT,`C[`?@`````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````#<``0``+_-"AKDV0"`&[#V$/0,%;#V#?08
+M3;/P"Q2S]`P,/H=#`;/P$2D*`?@`Q]D)]`L0L.8`\)P+\)8!/H)#`;#F`O"<
+M"/"6`<::`?@`DND"/?2PE@'T#04/`<;Y`<2:__@`DND!/?2PE@+T#04/`<;Y
+M`<2:__@`^```````````````````````````````````````````````````
+M`````````````````````````````````````````````````````-F@)```
+MF)L!OYJ]E/0P^+"1``D"W(`M```PD00-0-ZRJP``?CO"``D/LZ``$-D`(P``
+M#Q"UGP,)![*:]#`(^`#X````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````#<``0``+_-"A#DV0"`X!D``'_OB?]____9
+ME`H'\?3]_Z#)8._9`",```\,M9\#^`#X````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`/DBT0`C``"8'P?>:",``+*BE/D"O)Z0MO0"OYO91",``+SY\+_Z?NC#`+.D
+M!PSX"+*N/L1*`0X'LZT#C`"8&0?>C",``-K`-0``MI0"O)Z0OYGYE9@?!]YH
+M(P``LJ"4^0*\GI"V]`*_F]E$(P``O/GPO_I^I5<`LP0`#@D!#@R@*3[$2@'?
+MP#4``+_YLY[B`!0)!K49`[*>"0&@^3[$2@&SD`$=LY[!``D)`:#Y#P79`",`
+M`++^M9\#/L1*`0D<#@>U&0.RZOLA^```````````````````````````````
+M``````````````````````````````````````````#9`",``)B=:_E"F)^0
+M]##XF)F@Q]ZJ,^`*$I63&Z8_]!@CLO,^0DL!E=D8O)GPO/GPVV8`M``"_G]F$+0``OYD])/_Y
+M%3[12P$0(@'$&0'T&S+9P"4``)2@!KP)`)@)#)@*"[:5&[:E&+:D!OVI!7[Y
+M>P"RJ[.@``RR"@Q`?E0W`+85`<0J_Z:C]`C`D#D!W(`E``!4G0:]Y-L`(P``
+ME$\#E$D#O/OPVP`E``"\FY"_FKV4L)$`"0$PD028^X&\ZJ#>LJL``'X[P@`)
+M'+.@`!#9`",```\=M9\#"0>RFO0P"/M!^```````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````-P`!```O\T*'>39`(!SD``OWN`9``!_[XG_?___V92@R?'T_?_9P#4`
+M`&#O#P$*!Z"?#P79`",``+6?`_@`^```````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````````#>@%P``-F@)```
+MO^^8G0/Y(MDP&0``/YR0_P&@[[*BQ,__E=H8IJ_T"!79+AD``#^9Q)[_O.^0
+MIJGT""'9`",```\%M9\#V<`U``"@G[WTV<0U``"@GSZA3@'9`"@``;^=O*^2
+MII[T"`7X"(E!`A"\J:"4J02_GXF__>^\J:#$^0$SE``J#P39P#4``*"?O?39
+MQ#4``*"?#P79`",``+6?`PD!#P>@*3X#3P''\6HS$`0&^`@\K`*0W0&]I';4
+M!-N@)```,@Q^3@(`#PVSH``S#P'9P#4``*"?O?39Q#4``*"?#P79`",``+6?
+M`P\',Q0$$<0*_PL$O<1^$R``#P<)`:`ILOK[(?@`````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````D!^0*@J;*@?EY0`;.D``@)":`)OPG0`",``)2O&/'U`(2VE!BU
+M"6Z8"2VU#V_:L"0``'VTM0ELF`DNW``$``"U"6U^`#X`,Z``"KVD/EQ0`9@)
+M+0H!D)D0M0DM^P'96"```?D"OY_95"0``#^9)I_T&&O>T",``+W$/M%0`;S=
+MT)#Z`?_;E+*O]!LZWE0D```_Z=!5)```/P__O=40F0$@Z93)`M[0(P``O)Z0
+MH)WP]/^4R06\J:"FK_0-(R`*/MU0`;.D(+N0S`&0[@2SP"`.O^N]]`T!/H%0
+M`;VD^P'X``````````````````````````````````````````#X`/D"T``C
+M``"8#RV]E)B9$MJP)```M0]LF`\NM0]ME9\8MI40Q)X/QYEDE)P#O)F0O)R0
+M/.G@V0````'$_0_PY/_'_V3]Z064^P.)`,``O/_PO/OP/-_0\-3_MM0(_>T%
+MM0EOM0YN?;3<``0``'X`/@`SH``*O:0^D5$!F`DM3N(`W\`U```*`9"9$*#^
+MM0DM^P'X`/@`````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````^`#991H``#^9,Y0`,MED&@``/YDS
+ME``GWR4:```_^3.4`!P8^0$SE``5&/D",)8`\)P+\)8!QIH!^`"]I/@`V3`9
+M```_F9"M`<2?_Z;?]`@DV2X9```_F<2>_[SOD*;9]!@2O*^2D)D!II[T""@^
+MD5(!V3$9``#?+QD``#^9/__PE/_P]/^\J9*0F0&FG_0(!?@(C$("$-\$:!$!
+MO*R@E)L$E*X$O+_`O\V_[XF^_>^\J:")```!_]F4]`MF21_^__F4\95@`Z#I
+MB0``___9E*#)E*D#WPQH$0&4K@:[Z0+90%@``+R_L+SIX+^_F.D,W"0D``&4
+MK02\W-"VE!S<____#_W\!/WY!:"_O]^8Z0S]_`2VE!S]^06@W[V4M>D+^`"4
+MJ0.4KP:[^0+90%@``+SY\)C\!/D"Q,F`,Y``&^3)``'U"\L`27_^"@'_R92U
+M^00^$%0!V3`9```_F9"M`<2?_Z;?]`@DV2X9```_F<2>_[SOD*;9]!@2O*^2
+MD)D!II[T""@^J%,!V3$9``#?+QD``#^9/__PE/_P]/^\J9*0F0&FG_0(!?@(
+ME*D&E*X#O)X"V4!8``#%SX"\"0!)__[]^02RJ[4/!`H)W)"-`0!^RTX`LZ0!
+M)-Y88```W>`9``"_Z7_?O:3QE0`"\?4`"*#I8-\^$%0!LZ0"%I@)!$]__PH!
+M_9\$M0D$/A!4`;VD^P'T,/3Y@K*@LK@RPC/$!`W9,!D``#XO5`'9,1D``#^9
+MC;_][_"4_[P)<(E!`A"2=`&\>7"4?`2_P[#!";Q]<,<^T;#A"C,D!!K?!&`1
+M`90)![R?D)"?!+^1O_4^DE0!E`T$,R0#$-D$:!$!O-G0/HM4`=P$3%@``+N?`KR>
+MD!B?`S/T!!64"0?<"&`1`;R"&@1`;S>T#[L5`'9
+M"'`1`;S9T+_9M-`+,/8`\,P+\,8!QYX,IM[P;`OP9@&S8``(L^`!8=G__P#.
+MCP```?\9E/^?]3,D!!"4"0?=!&`1`3XX50$S)`,3E`D$W01H$0&\G9`^:%4!
+M$BD!E`T$,)8!]`P1V01P$0&\V="@WSYJ50'9!&@1`;S9T*#?N-D`"`"@GXD`
+M``'_&93T&SZS9`!:B0``0/\9E/0;-)1)`Y1/!MU`6```N_D"O/WPF/D$\)0$
+M]!L:L\D`,PF)```(_QF4]!L+/L]>`;-D`!^420.43P:[^0+90%@``+SY\)C_
+M!,3Y!/4+I@.43P.420:SY`$YNY\"W$!8``"\G)"8F03PE`3T"P7X"+Q$\)1)
+M!-U$6```NY\"MI0"O)V0#P,UGP$)`S[17@&[GP+>0%@``+R>D)B9!/&4`!#T
+M"PNR"@L!?F`D`)1/`Y1)!KN?`M]`6```O)^0F)X$O?2UGPFUGPI/\^_][P1/
+M?_7][P2UG@0S)`0MB<`B`KP)`)0)!XQ`W?V_GKP,`-T$8!$!E`D'O)V0OY^0
+MF02_F3[15@&4#00S)`,JCH`6$;P.`)0)!-\$:!$!OYZ\W]"_V9#?!(R`Z>Z_
+M^;P,`#[15@&.`!<1O`X`E`D$WP1P$0&_GKS?T+_9D-\$O_F,`.GNO`P`Q)T/
+M,R`$"KWT/N%6`<>?#+/4``PS)`1ZL_0`=I+9`;"6`O0-;+/0#VDS)`0BL]`(
+M8;/0!V.SU``,L_``6SXN5P&SU`8*LMX^ST`9'
+MY.D``O0;";WD/G-7`0X'L]`*-@X.L]`+,#,D!`RSU`0,/FM7`;/0!QCX"`X-
+M/G-7`0X(/G-7`0X%/G-7`0X!/G-7`0X"E$\#E$D&W4!8``"[GP*\G9"@GK3@
+M"[/@`0BS9`$+B0```OTY!<<9%K:4%H_L_[__/_3]^05)'\+]^03$7@^VY`7_
+M_E6T\`G9__\`SO\9E*#UCP``0OV?!8\``/__G^0S)`06Y>-_#+(*BT%^!7XE
+M:@`^8E@!E$D&E$\#O)\2V4!8``"\&1"8&03%XX#PE$#T"R@]M+)*?I2%@`
+M`+N4`K:4`[R>D+^1LQ0!.MRL8```V^A@``!_SG^ZW6A@``!_WY!)`;P9E/"3
+M`'F9`/^?]/^>Y/V:!&#?8,Y@N;VD?KEM`#,D!!.4"0??!&`1`;R?D#[^6`$S
+M)`,3E`D$W`1H$0&\G)`^_E@!$BD!E`T$,)8!]`P1W@1P$0&\WM"@TSX`60'?
+M!&@1`;S?T*#3N-D`"`"@D]DX`!`!CP``?Z"?M)`*LY0`$L=9T?0+"S)Z,@M^
+MA30`"0>@B=D`6```/YDSF0">!3,M!)D%V>@9``"_F?"4`?4;B@4*#KVTO<1^
+MRTX`LZT!?`7>6&```-W@&0``O^E_W_&5`$#Q]0`(H.E@WS[)7@&SR0"F`<<9
+M$S.9`)X!L@K$*_]^1B,`?@)2`;.D`![$*_^R"CW$?A(C`+(*Q"O_#`%^$B,`
+M/L]>`=PD)``!E$D$W2PD``&\G+"\G9"_O+^9E`T$Q)\#,R0##=X,:!$!/M=9
+M`=X,V?__`,[_
+M&93%GP0S)`0?E`D'W`1@$0&-P"("O)R0O`T`H)^4#P<^:EH!,R0#))0)!-X$
+M:!$!O)Z0H)^/@!81O`\`E`\$25`"H/D^[EH!$BP!E`T$,,8!]`P1V01P$0&\
+MV="@WS[87@'>!&@1`;S>T*#?N-D`"`"@GS[87@&4[P1)4`*@^3["6@&/@!81
+MO`\`3U`"E`D$H)^4Z02@GS,D`2S9)````91/`[^>W$!8``"420:[GP*\G)"8
+MGP20[@&UG@WQ]0`(M9\$O[Z\1-`/^)1)!/WO!+N=`J"^MI0"W418``"\G9`/
+M"36?`0D)/M%>`3`F!,16#^3Y``+T"T])__W_^>243P.420:[GP+?0%@``+R?
+MD+6>!#,D!`;X")1)`]Q(6```NY0"MI0#O)R0OYFSD`$&^`C$Z0'T"P7X"(D`
+M`$#].04^?UL!C___O\<9%O\_]+:4%O^?-91)`Y1/!MU`6```N_D"O/WPF/X$
+MY.D($/4+Y`!)]^__Z92U^02]E+7Y"K-D`&TS(`0&^`C9__]`SO^1]#,D!!.4
+M"0?>!&`1`;R>D#X*7`$S)`,3E`D$W`1H$0&\G)`^"EP!$BD!E`T$,)8!]`P1
+MW@1P$0&\WM"@WSX,7`'9!&@1`;S9T*#?N-D`"`"@G[)*?IXF`#[/7@&2:0&P
+ME@'T#%?#+/4``PS)`1\L_0`>)+9`;"6`O0-;K/0#VLS)`0?L]`(8[/9
+M!Z,!L]0`#;/Y`)H!/GY=`;/9!H4!L]D%D@$S(`,*,"8"]`P(L]D&@P'DR0`"
+M]!L)O<0^_EX!#`>SV0IQ`0P.L]D+:@$S)`0,L]0$#3[P7@&SV0=+`?@(#`T^
+M_EX!#`B420:43P.\G_+90%@``+SY\)C]!-G__T+.H/S_D<3$V0'T"Q:S9`\3
+M"?[_V92U^02)__^__>D$M-`)H-XS)`03E`D'WP1@$0&\GY`^/UX!,R0#$Y0)
+M!-T$:!$!O)V0/C]>`1(I`90-!#"6`?0,$=\$WEA@``#=X!D``+_I
+M?]_QE0!`\?4`"*#I8-^420:43P/=0%@``+R?HKRMH+^ILY0&%+-D!1`)`Z")
+M"0*@J3[)7@$)!Z")OXH^U5X!"0>@B;*:^X4,CP`7$;P/X##&`?4,S/L^HEH!
+MLMP^_EX!#`$^_EX!#`4^_EX!#`()_?WI!#ZT70'T,/#Y@K"Q";*B,\0$#=DP
+M&0``/B-?`=DQ&0``/YF-O_WO\)3_O"E0B4$"$))0`;Q94)18!+^$O%U0QT[1
+ML.$,,\0$+I0I!]T$8!$!O)UPOW'?"&`1`;R?8+]CE1X1L.$*LNGPE`'U&Y,!
+M/HMC`90N!#/$`Q#?!&@1`;SOX#Z07P'9!'`1`;SIX)#I!+_CE`\#OY'=3%@`
+M`)0)!KN?`KR=D!B9`S.4!!64*0?="&`1`;R=D+^?/MU?`90N!#.4`Q#?"&@1
+M`;SOX#[;7P'9"'`1`;SIX+_OB0```?\YE/4+?`3'_`RSS0%U!-DD```!W4A8
+M``"_GY0.`[S@DK:4`[R=D+^=D/\!E`D&NYX"WD!8``"\GI"UGPF@G+/4`1S>
+MK&```'_OD`D!O-F4LMK]^05@[WZY;0!.#_Z)`0`"_TF5_9X$Q!\/MO0%_?D%
+M2?_#QQYP_?D$E.D*__G5L^``!O@(E`\#E`D&NY\"WTQ8``"\GY`8F0,SD``&
+M^`B@C=G__P#.C^^,0_\YE/^?];/D!!"4*0?>!&`1`3ZN8`&SY`,3E"D$W@1H
+M$0&\GI`^WF`!DND!E"X$L)8!]`P1V01P$0&\Z>"@[S[@8`'9!&@1`;SIX*#O
+MN.D`"`"@G\?9T?0+$K30#+/4``PR6C(K?H4T`+3@"0D'H.D^9V0!C\`B`KPO
+M()0I![^=L)$+OWF_:8Y`W?V\+B#$GP_'G@RS]``)L^T`FP"2^0&PE@+U#9``
+ML_D/C`"S^0B'`+/Y![@`L_0`#;/I`*\`/GUA`;/Y!I,`L_0%*8\```/9__\`
+MSO\9E/V?!;3P#*!YB0```O])E:")L_0`*3Z680'DV0`"]`MAL_`*7K/P"UJS
+M\`1I^`@^]6$!,EHR*WZ%-`"4"0.4#P:[^0+90%@``+SY\)CY!$Y___V>!+7Y
+M!#Y"9`&R"GXB4P&SI``-M.`)O^D^9V0!LBI+$0Y^)6H`Q4\"/OYA`;(JBT%^
+M!7XE:@`)_?])]#[^80&T\`F_^3YG9`$)_O_YE,<_#+3@"OV?!4__P[^,_9\$
+MQS]PMO0*_9\%C____?V?!$\?_O#D`;;D$?V>!?V?!(___[_$/0_'S`FVU`7]
+MG07]GP3''Q:V]!;_GS6SP``:E`D$W20D``&\G9"_GX[___[]_@2@G]XH)``!
+ME`P$O,[0O]^)``#_WO__`,[_'N3]^02@W[3P"[_]OWF_;XD``$/_Z17'_@SP
+M]`_T&P>SY`!.DOD!L)8"]`U$L_`/0;/P"#VS^0>R`+/T``VSZ0"I`#[18@&S
+M^0:@`+/Y!9L`Y-D``O4+D@"S^0J.`+/Y"XD`L_D$A`#X"#YG8P'9)"0``;S)
+MT+_>E`\#E`D&NY\"WT!8``"\GY`/"*"?V>____[].00SX``'\!4"O]G'F>CT
+M"P;P%039`%@``#^9,Y``.=GH&0``OYGPE`'T&RL*#KVTO<1^RTX`LZ0!'MY8
+M8```W>`9``"_Z7_?\94`0/'U``B@Z6#?H(.@<<949$?"49<0]#\D%2?S#_>D$H(ZST`80L]`*([/4!5P^(V0!E`\#E`D&NY\"WT!8
+M``"\GY"@G3XC9`&4#P.4"0;=0%@``+N?`@\'O)V0H)_$Z0'T"PJ)```"_>D%
+MM/`,21S"_^F4_YSEH(ZS\``-M-`)O]D^9V0!Q^G1]`L2M.`,L^0`##):,BM^
+MA30`M/`)"0>@^;*:^X40]##H^8*PL0FRH3+%,\0$#=DP&0``/HID`=DQ&0``
+M/YF4$P3>"&@1`;P^$)09!]X$8!$!OYV\'Q"4&0>\
+MGI"0GP2_F+__/AQE`3-4`S*/@!81V01H$0&-@.GNO!\0O#DPE!D$O!T0OYV_
+M.+]_WOR7[OZ\/C"P\0P^4&4!B0`7$=T$Z_>;P>$-_\E^[^O#\P/A%F`8D`%Q'=!'`1`;P9
+M$+P],)09!+^=OS^.`.GND#,$O!X0OSG?^(_N_KP_,,2?#S-0!`J]Y#XA9@''
+MG@RS]``0`@@S7037`+/M`"`(DOD!L)8"]0V#`+/P#W\S5`0EL_D("0BS^0<&
+M`;/T``VSZ0#]`#Z)9@&S]`8*LO(^[F8!L_0%#3-=!-X'/NQF`3-4`PRS]`84
+M/D9N`3!6`O0,"0("L_`&-^39``+T&PF])#Z\9@$"![/P"B0"#K/P"QXS5`0,
+ML_0$##Y.9P&S\`=.^`@"#3Z\9@$""#-4!$*S(`@4LR`&*K,@`B:S(``B/DYG
+M`32@-_"D_WXB4P&SJ0`_![(:2Q$./O1F`0("LAJ+07X%?B5J`#X\:`$"`3-=
+M`#P!E$\&E$D#WD!8``"\^0*\#@"8#P20!@PU90/$^03U&QP!Q/D"]!L:Q?D"
+MM0D$V20```&_F9"9`;4)!SXP:P&8"@=^*6X`L*8"]`P,M)`)OYH^(FX!F`D$
+M#_W]GP2U"02S)`@TM)`.\)0/LY0&*K30#-D$:!$!O#G@Q]]P-6\#O^DR]8\`
+M`/_]GP2@Z;]YH'D^/&@!C8`6$=X$:!$!O!T0O#Z@E!X$O^V_J;]YCX#I[KP?
+M$,2?#[#V`_0-.;/P#S:2^04"`K"6`?0-")``#__?D$H,^_Z;!Q##+5`@B@Z3X\:`'X
+M"+3@"I1/`Y1)!KN?`K_MWT!8``"\GY"@DC-4!$>5C!/$R0'U"\<%WC@9``"\
+MX9BSD``FV4`9```\D?B]E+SI&3/T``N)```"_=D%/?390!D``#R?&8D```C]
+MV04^)6X!QXD5MI05_]GULR0("_#U`CZT:`$)_?WY!)1)!I1+`[R;PME`6```
+MO,G`&,X/QXD2MI02__G5,^0$)@_^_]_TM-`,Q]D,_?D%B?___?WY!,>)$;:4
+M$?_Y93X!:@$SZ0":`+RTDMY(6```MI0#O)Z0OYK%WP&)___]__EDLZT!ZP"8
+MP`3D"0`$]0O?`-]H8```WNA@``!_^W_MD$D!O*F4_YNU\),`>9D`_9T$8.E)
+M__O_"91@^[7)!/"S``H-W-.+`0!^RTX`W5A@``"SI`$=O]G>X!D``'_O\94`
+M(*#9\?4`"&#O/@%J`;_93__?_9\$H-D^`6H!WPAP$0&\/S"_.=[XC^[^O#XP
+MQYX,]`L4V20```&_F9"9`;7)"3Z]:0&US@G?2%@``)1)`[N4`K:4`[R?D+^<
+M#_Z)```"_]_T_^F5_Y]EL\0!(MFL8```?YZ03P&\S_3P\P!Y_P#]_@2]I&"?
+M?KEM`)1/`Y1)!MU`6```NY\"O)V0F)X$">__:<3$Z03T"RZ2*0&PE@'T#07X
+M")1)`Y1/!KOY`ME`6```O/GP"?O_Z92U^02)```B_VE`*\G9`UGP&TX`D)!Z#I/H%L`;/I
+M`,D!E8\5Q/D!,Y``?XD```C_B93T&W0S5`1QWPA@$0&)``!@E!X'O._@CP``
+M(Z#IV?__`,[_B93]GP62[@2@Z8G`(@*\&1!)'_Z4'P?_V92-0-W]\)6PO!T0
+MH/FR&HM!?@5^)6H`O$3PE$D$WD18``"[GP(/!K:4`KR>D#6?`;3P";_Z/B)N
+M`96+$_^_E?"4`?0;,#-4!"+9R&```#^9\)3_NY$'\)0!]1L?`<>I!/0;$CYX
+M;`&TD`SPE`^SG04+`91)!I1/`[R?PME,6```O,G`21_^CP``(!C.`O^O]?WY
+M!+20#/"4#[:4!?V?!4_NP_^?U#/@`!")```"_=D%/90UR0+$N0'T"T3>.!D`
+M`+SA^(D```C]V06S\``RV4`9```\D?B]E+SI&3/P``^)```"_=D%/O)K`=G_
+M_P'__=D$/?390!D``#R?&;3@"K3P#(D``""@[?WY!3-4!!64&0?="&`1`;R=
+MD*"?/C]L`3-4`PJ@?SX_;`'="'`1`1)9`;P]X#"6`?0-!:!_H.^\1/"4203>
+M1%@``+N?`@\#MI0"O)Z0-9\!M-`)O$_TE$D&NY\"WT!8``"\GY`/`J"?"0.@
+MV3Z!;`&TX`F_ZCXB;@&T\`F_^9*9!;"6`?4-D0&TD`I,O0"_DC-4!#KD*0`"
+M]`L9E$D$W20D``&\G9"_GX[___[]_@2@G]XH)``!E$D$O)Z0OY^.``#_3'\,
+M_?X$H)_?3%@``)1-`Y1)!KN=`KR?D!B>`X\``/^)```O_XF5_9\$_\D%,^0`
+M*+S4DMU(6```MI0#O)V0OYFPE@'T#1&SD`,.-*`W\*3_?D$A`+3@"\?IT?0;
+M%<U3Z;:`$"`C[^9@$""#[49@&]]/0PK/F"_DD!D)EPH)^2
+MF0R@GY*9!*"?LJ,RL3.T!`W9,!D``#Z!;@'9,1D``#^9/).0,)%.-)!.$ID!
+M,)%/,Q0$#;W$L,$4/N]N`3203]Y,6```\)3_E)\&MI0#N_D"O/[P&/\#,_0$
+M$Y0Y!]\(8!$!O)^0/N=N`90Y!#/T`Q#<"&@1`;R"'`1`;R>D+^9
+MQYD,L)$4-%!/C+[][X]"`A#>1%@``/!4_[Q?4)19!+Q<4+"1"[3`"[Q5\)19
+M!+N?`K_/MI0"O)Z0&)D!_D\!D/]T\)3_H/GU&WD&^`@^J74!&$T!Q-[_L.$2
+MH/XS%`0IOX_^20&0F62TP`R@G[20%;^?_DD!D)E@H)^_SY"9$*"?/JAO`?Y,
+M`?Y.`?Y/`9#,<)#N9)#_8#,4`Q:_>:#IM.`6O^F@^;3P#3ZD;P&_::#IM.`7
+MO^F@^;3P#K_YH,FTD`N_G_Y)`9"9:*"?,]`'>S#6!_0,(3/0`U@PU@/T#`PS
+MW0&N!3XD=0$PU@7U"*(%/@-P`3/0"V74!_D`!LCJ0`'0R'+(+?A)4`3XG<`$S%`0&^`C^20&0F62_
+MF<>9$#.0`"JTP!2SQ`$CW>Y@```)"#5)`3_?#@C^20&0F702_P&@GB#?/A5Q
+M`;3@";_J?BEN`+&FT$F"\$W>Y@```)"#5)`3_>\/4$M2\$#P@2[@$@
+MWCY-<0$S%`0&^`C^3@&0[F2_Z<>9$#.0`%^T\!2S]`%8O^G?__\`SMW@&0``
+MW.Y@``#]GP2@Z;_OB0```_WY!:#OO^F@>;_IH&G9)````;^>"0XU20$_SW_9
+MD.X!M2X)$O\!\)4@(,]@V3#V`/4?800^=W4!M)`)OYI^*6X`L:9P%_4-3`28
+M+P3=[F````D%-4D!/][P]02U+P0/!1+N`2#>_DD!D)ETH)\PY@#U'R$$/G=U
+M`9@J";.D``;X"+20"MQ(6```NY4"MI0#O)R0OYFSE`$0F"D$\90`!/0;!?@(
+M?BEN`+&F9`#T#1$TH$_PI/]^%R(`/GEU`=_@&0``?_GPE2!@^3YY=0&8+P0)
+MW__YU+4M!#,4!!R_C[3@%?Y)`9"99*"?O^^2F02@GSX)<@'^3@'^3P&0[F20
+M_V`S%`,6OWFTP!:@Z;_)M.`/H/D^#'(!OVFTP!>@Z;_)H/FTX!"_Z<23YB<@$2&0$PE@'T#0>_Z:!YO^F@:0D+L\`!%)+)`K"6
+M`?0-"+/-!.``"0FT\!&TX`N@*?Y-`;_YO^^_+I#=;*#?#_C]GP3_R06SY`L5
+MO]E/'_[]GP3PE4"@V3X_
+MO]F/```"Q^[1_9\%H-F_W[#F`/"<"S*<"?[]^02@W[_93__#_9\$H-D^R'0!
+M_DD!D)EHOY]._\,]Q/W^!*"?_DT!D-UHO]Y/'_Z4N07QE.`!_>\$_9X%H-D)
+M`;_?H"FTD`N@GPD'-4D!#P?^20&0F72@GS/``'TTH$XR.WZ%-``^>74!,Q`$
+M;+^9LY0%9@D'-4D!"0&@*3YI=0$S%`01M,`5O\G^20&0F6"_F;3@#/Y)`9"9
+M<+_OH)^_F?&4``+T"S'^3@&0[FB_Z0\"H"^T\`OQE0`"H.F_Z:#Y"0;3`%J#IO\D^TG8!OVF@Z;3@%[_I
+MH/F_^<>2%?Y.`9#N9+_IC___O_V?!*#IO^G?``",`/V?!/0;"#,I`&$!M/`+
+M_DT!D-UH_DX!O_F0[F2@V;_4,Q0$%+_OO^G9``"``/_Y!#Z>=P&_Z;_OO^^.
+M```$_YX$_?X$]`MIO]D/_?V?!*#9_DD!O]Z0F6"_F4\?_OWO!/"4#[:4!?V>
+M!:#9,Q0!0K3`%K_)\)0/LY0%-K3@%[_I\)0/]!LJE%D#WTA8``"[E0*VE`.\
+MGY"_F;"6`?0-$;.0`PXTH$_PI/]^02$`E%D$O%7PW$18``"[GP*VE`*\G)`8
+MF0'$G?^2V06PE@'T#3BST`@6_DD!D)EDOYF/```(_9\$_0D%_DD!D)EDOYDS
+M(``7_DD!CP``()"98+3@%:"?OYF@Z?Y/`9#_:+_Y_PF5H/FS``!5O_FT\`N@
+M^3,4!!+^20&0F62_F:")/DEX`3,4`Q+^20&0F62_F:!Y/DEX`?Y.`1(9`9#N
+M9#"6`?0-![_IH'F_Z:!IQTG1]!L,-*!.,CM^A30`^X54O?3T,+SY@OY)`9"9
+M7*"?DID$H)^2F02@GY*9!*"?WV`"$`&_^;"1#O"4`;"1"?0+$+3`#@G^_X!D``-DR&0``?^\_F;W4_D8!\?3?__Y(`6#O,)$V/>2PT0R]-##A
+M-Y!F6)"(7#ZVAP'9,!D``#3`-C^?)L_T"#/9+AD``#^9Q/[_,L_P]/_PE/^\
+MGI"F^?0?&=DD$!`!OYD-!+S^,C#1-["1&#[+>@'>,1D``#20-C_O)I_U"+0!
+MV2\9```TX#8_F<3]__#D__"4_[R=D*;I]1^8`<1<_[S,\)3)!+N?`M]$6```
+MMI0"O)^0O.TR&)L!E,\#E,D&W4Q8``"[GP*\G9`8F0,PD3<2N04PE@'T#`@]
+MY##A-S.T#324SP.4R0:[GP+?0%@``+R?D)B:"[.I`!P.?BEN`+&FR`#U#0\.
+MQ%K_?C]2`3ZMAP$TD#Y@```_F3.=`,4`W:!@```_V3.9`)L-/LMZ`320-Q*9`3"6`?0,=)0_
+M!-X$:!$!O/[0O]F0[@2\_O`.`:!IO_F[XP2PD16_::#9M)`5H/G9+!`0`;^9
+ML)$8M)`8_>D$]!MLV>Y@```_F3.4`&+?H&```#_Y,Y0`5Y3)!I3/`]Q`6```
+MNY\"O)R0F)D$\90`"/4+'0T^RWH!V2P0$`&_GPD!NY,$L/$8M/`8_9\$]!L>
+MV>Y@```_F3.4`!3=H&```#_9,Y0`"3.]#N<,WJ!@```_Z3"6`/0>$-GN8```
+M/YDPE@#T'P7X",12_Y0I`Y0O!KOY`ME`6```O/GP&/D,,Y``&MDD(``!OYGP
+ME`'T&PPTH#8R.WZ%-``TP#!?@(E"D&E"\#W$Q8``"\GQ*\'!`8&0'PE`+U"X$`W20D
+M``&4(`2\#0"_"=[Y@```_F3.4`#N\(I"4+P3>1%@`
+M`+OY`K;T`KS^\!CY`3.0#B"4*0.4+P:[^0+90%@``+SY\)CY!/&4``CU"^4*
+MW#`9```TT#8_SR;?]`@IV2X9```_F?#T_S+>\.3_\)3_O)^0INGT'P_9ZF``
+M`#^9,YT`L0HTX#\
+M[>"_Z9#N!-_XG^[^H&F_Z;SOX+"1%;]IQYD>,Y``>CZ??0$TD#>4/@0SE`,C
+MC(`6$=T$:!$!O#PPO.W@E#D$D.\$OYF,@.GN/HU]`8T`%Q&\/3"4.02_F=\$
+MO"*0E"\$WD18``"[^0()`[;T`KS^\#7Y`0\!L/$,/JV'`=D48!$!O.G@
+MO^^4*03<*"0``;R^P
+MD1FTD!F\+R"PD0LSQ`0D#X)
+M@`$S1`,7OV^4.03"@Z3Y`@`&_:=\$:!$!O._@N.\`"`"@Z;]IH/F4*0.4+P:[^0+90%@``+SY
+M\)CY!/&4`!#T"PNR.@L!?F`D`)0I!I0O`]Q`6```NY\"O)R0/M:!`;]OV0``
+M`,Z4/@?=!&`1`?WY!*!OOVF\[>"0[P2-P"("\)40H&F_:;P],)0]!Z#IB0``
+M(*#YOXE/__V.0-W]O#XP_9\$H(F_B4\?_OV?!/"5@*")OXGPE1"@B;^)H-D)
+M"C7)`3ZZB`&4.0??"&`1`;R?D+^9L)$5/K^"`=DQ&0``-,`V/Y\FS_4(NP?9
+M+QD``#^9\/3_,L[PY/_PE/^\GY"FZ?4?H`>4,03="&@1`=X(S]
+M_W^4+`.4+@;]^02P\1FTT!FTD!6[[`+<0%@``+SLX)CN!/"4#T\?_K:4!?W?
+M!/V=!;"1&?'D`!#T"PNR.@L!?F`D`)0N`Y0I!KN>`MY`6```O)Z0O=2@G;6=
+M!+PBD)0O!+OY`ME$6```MO0"O/GP"0$U^0$S1`0;C,`B`HU`W?V\/#"4.0>\
+M/3"_F3[=@P$S1`,;CH`6$8^`Z>Z\/C"4.02\/S"_F3[=@P&)`!<1O#DPE#D$
+MOYF,`.GNO#PPW3`9```TX#8_WZ"))N_U"*8`V2X9```_F?#T__#D__"4_[R?
+MD*;I]1^-`#-$!!.4.0??"&`1`;R?D#XJA`$S1`,7E#D$W`AH$0&\G)"/```@
+M/F.$`1))`90^!#"6`?0,%=T(^\/#"4/@?]^02@C[^)
+MO#TPH.D^QH0!V01H$0&4/P2\^>"_Z8W__^_A0$S1`05E#D'W@1@$0&_;[R>
+MD#[XA`$S1`,7OV^4.03"@Z3XOA0&_:=\$:!$!O._@N.\`"`"@Z;]IH/FTD!F/```0M,`*_9\%
+ML)$9M)`9#_?]GP2PD1FTD!E/'_[]GP3PE8"PD1FTD!F@R;,-`$\"M)`9QYG1
+M]0M$`C2@-C([?H4T`#ZMAP'X"#ZMAP&4*0.4+P;=0%@``+OY`KS]\+_YLY0`
+M';20%8\``$#]GP3T&P^_:8\```+]GP3T"Q*_B?&4``+U&U,!,^D-3P$TX#4/@0SE`,0W`1H$0&\[.`^]84!W01P
+M$0&\[>"_Z:!IOVDTX#>/___O_9\$H&DSY`05E#D'W`1@$0&_;[R!&@1`;R>D*"?/FJ&`320-Y0^!!*9`3"6`?0,$[]IWP1P
+M$0&\[^"@Z3YJA@&_:=P$:!$!O.S@N.\`"`"@Z;]IH/F)```@L)$5M.`5E#D'
+MW0A@$0&\G9"4+P.@GI0I!MY`6```NY\"O)Z0F)D$\90`$/0+"[(Z"P%^8"0`
+MO"+PE"D$NY\"WT18``"VE`*\GY`8G@&4+P.4*0;<0%@``+N?`KWTO)R0M9\$
+M$NX+,.8!]0S6`-_N8```/_D2F0$@^?0?!?@(O"+PE"D$W418``"[GP(/![:4
+M`KR=D#6?`3ZMAP$TX#R.GY2;@$.`;#A##3P-A#_
+M`3#Q-MPS&0``-%`V/\D250$F6?4(!_%^D!\`V3(9```_GMDQ&0``/Y^]Q-DS
+M&0``$NX!\/3_/Y"2^@&]M#XGB`$8F0$2F0LPE@'T#`VFVO0?!?@(D,P!E-D&
+ME-\#W4!8``"[GP*\G9`8F0P0[@$SE`$'D+L!Q.W_O-WPE-D$NY\"WT18``"V
+ME`*\GY`FX/0(L]GN8```/YG$S__PD@>F^?0+!?@(V:!@```_F<2___"2!Z;Y
+M]`L%^`BTD`FSD``0WV`"$`&_^?"5`:#YM*`,^X5$L)$4M)`4QYD4,YD`%_8^
+MH'X!E#D$W0AP$0&\G9"_F;"1%33`-MDP&0``/Y\FS_4(0?@^BW\!E"D$O"+P
+MWD18``"[GP*VE`*\GI`8F0$SG0JI_#ZMAP'X````````````````````````
+M`````````````````````````/@`V6AF``"_G[/P!`;X"-GH$``!OYH^:8D!
+ML_`$#+/T!DD^-(D!V6AF``"8F0.SD``&^96]Y-GH$``!H)[=Y!```9"9!*">
+MO]_9````@`P!LLK]^02@W]GP$``!H)[9:&8``*"<^`#X"+/T`+&]I/@`^1+1
+MZ!```;\>E>`8L`8/]`PDD`\#V6AF``"\GYBSD``6VO___P#_ZJ3YE;,$`QD^
+MQ8D!^`@/`=EH9@``O:2@GSX4B@&S``40LP`'#+,`"`BS!`LGO?39Z!```:"?
+MD)D$WN00``&@FK_IWP```"#]GP6@Z3X)B@'=Y!```;_9WP```("]Y/V?!*#9
+MH![9[!```:">D)D$H)X/`=EH9@``LOJ@G_L1V6AF``"8F0*SD``(?L1-`-YD
+M9@``/^DSD``GV?`0``&_GSV4(.GP]/_T&P?X"/@`L_0!"GX"B0'X`'YQB0'X
+M`/@(B8`@!::I]`T%^`C9J&```*":V@```(#X`/@(B8`@!::I]`T%^`C9J&``
+M`*":V@```(#X`(G`U`&FJ?0+!?@(V:1@``"_F;.>X"XVO>3?`&`1`=PN&0``
+MC>___3[*B@&_^9#N`?V=!*#YF/D"M?D"D/^`/\GPE/^FZ?0(YMFD8```H)I/
+MF#K9/``0`=H```"`H)_X`/E2VTA8```,`=4P&0``U````$`#[](Q&0``T2\9
+M``#0+AD``+RLE?"4`?0+5+^YLY0!3S]9Q)__IL_T"!P_";S/XL2=_[S?D*;)
+M]!@,INWT"!L^5(L!/RD_'_"4__#T_[S)XJ;O]`@%^`B)@!81O.G@E.\$O_G]
+ME`7]DP2@^9#,`9"[.+/$":"]I/M1O93?P&```*#YMJ48LZZ!`$N/P-0!V:1@
+M``"@GT^8.MD\`!`!O>2@G]PN&0``WP!@$0&-[__]/L6+`;_YD.X!_9T$H/F8
+M^0*U^0*0_X`_R?"4_Z;I]`CFO:3X`+VD^`"5J1BSGH``1N>JP0+T&P7X"-]%
+M6```#0X^"8P!Q*D!]`L-O^D@_?&5``2@Z;:E`9#_.)#^"[.D`.??X!D``'_Y
+M\)4@8/D^(HP!^`B]I/@`LZK@+@?X"'[J'@"SI`4+V@```('X`$_@+MFD8```
+MH)_:````@$],'=D\`!`!H)_X`'Z0'P"]I/@`E:D8LYJ```?X"-G___\`_:D$
+MB<#4`::I]`L%^`C=X!D``'_?V\?4`"-FD8```8-^@F@H!^`#9
+MY&```+WTH)_9____`/E2_ZGTV:1@``"@G[:E&+.N@`!A@``!@G]H```"`^S'9____`/VI!-E`6```E*X&MJ0#N^H"O.G@V3`9
+M```_G=DN&0``/YF8[P3PU/^2W`'PE/_Q]0`!O)VPE,D&M>\$DKT!E,\#O)_R
+MV5!8``"\^?`^&HX!O_F0_SCDG@`!\)2`,Y``)K/D`"+>6&```-W@&0``O^E_
+MW_&5``+Q]0`(H.E@WSX?C@&0S`&FS?0(R9*Y`:;)]`@2V5A@``"_GT[__?W^
+M!*"?O:3X`-GJ8```/YDSD``&^`A^-6L`#P'9ZF```-H```"`()_X`+V4&)ET
+M,Y``"KVD?KEM`-H```"`^`#9ZF```#^9,Y0`!O@(VI@```@
+MGS/@``_9$&(``#^9,Y``"'[?:P#:````@/@`^```````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````/DRV3`9```_GI2O`Y2I!K*@NY\"
+M\.3_WTQ8``"0H@&\GY`8DP.F+O0('-DN&0``/YG$G_^\_I"F*?08"KRNDCY:
+MCP'9,1D``-\O&0``/YD___"4__#T_[P)DI"1`:8?]`@%^`B4"0:4#P.\G_+9
+M0%@``+SY\)CY!/"40/0+);_YLY0((,0[_SW$LAI^$B,`L@H]M'Z7(P"R&L0[
+M_WY&(P"4#P/>2%@``+SPDK:4`[R>D+^=L]``"+/4`WF4#P.4"0:[GP+?0%@`
+M`+R?D)B:";.D``;X"'XI;@"QIF0`]`T-L@I^%R(`/D^1`90/`Y0.!KOO`M]`
+M6```O._@O`#PE`D$NY\"WT18``"VE`*\GY`/#C6?`3V4W.`9``"0[0PUV0-_
+MR0\$H._PE2!@R3Y/D0&SW0&U`-Y`6```E`D&NY\"O)Z0F)X$#P2@GY"9##WT
+M-9\#\>0`!/0;9MGH8```?YN\TO0*#-S7BP$`_;\%8)OPLP!^RTX`W5A@``"S
+MI`$=O]G>X!D``'_O\94`$*#9\?4`"&#O/J*0`;_93__O_9\$H-F\`/"4"02[
+MGP+?1%@``+:4`KR?D`\'/MZ0`=W@&0``?]Z\`/"4"02[GP+PY2"VE`)@W@\.
+MWD18``"\GI`UGP$^3Y$!L@I^02$`O`"0E`\$N_D"V418``"V]`*\^?`8^0$S
+MD`L0W^Y@```_^1"9`2#YV>Y@```_F3"6`/02`=D(9Z/0+#<2:_WY(
+MJP#$J?_$FG^S)`,;CY`6$;P/`)0)!*":B7#I[KP)`#ZODP&-$!<1C_#H[KP-
+M`)0)!+P/`*":E!D#W4A8``"[D0*VE`.\G9"_F;.9`*P"LR0$%=\$8!$!E`D'
+MO)^0OY\^^9,!E`\$LR0#$-D$:!$!O/GP/O>3`=T$!+,D!!^4"0??!&`1`;R?D*">B<`B`KP)`)0/!SX^E`&S)`,FCX`6$90)
+M!-T$:!$!O`\`O)V0E`\$H)Z_^4E0`J#Y/I"4`9(K`90/!+"V`?0,$=D$!KOI`KSMX)CO!+P1T)09!+N=`O#U(+7O!-]$6```MI0"O)^0
+M#PDUGP$^J98!L\T/D@&4'P.4&0;=0%@``+N?`KR=D)B?!/#U`;6?!+,D!!7?
+M!&`1`90)![R?D+^?/FB5`90/!+,D`Q#9!&@1`;SY\#YFE0'=!'`1`;S]\+__
+MV?__`,[_^93EG@"`LR0$$Y0)!]\$8!$!O)^0/MB5`;,D`RB4"02-@!81WP1H
+M$0&\GY"\#0"@GHV`Z>Z4"02\#0"_F3[ME0&2*0&4#P2PE@'T#!'9!'`1`;SY
+M\*#^/MJ5`=T$:!$!O/WPH/ZX^0`(`*">CP`7$;P/`)0)!+^9C0#I[KP-`.6?
+M\`&S)`02B<`B`KP)`)0)!SXTE@&S)`,2C8`6$;P-`)0)!#XTE@&-`!<1DBD!
+MO`W@L)8!]`T/B8`6$;P)`)0)!*"?E.D$H)\^J98!OTE/'_Z4'@3'W=']GP2/
+M``!`_9\%WR0D``&@2;SOX+_I#_C]GP3PE0&@Z;/=`+7\/O:2`;])3Q_^_9\$
+M\)5`H$F_.0_X_9\$\)4!H#D^J98!B0`7$;P)`)0.!+_IC0#I[KP-`+"V`?4,
+MWOT^>)0!^T'X````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````^4+9,!D``(U"`A`_GK*BO"T@E"0$OT.4KP/=0%@``)2I!O#D_[N?`H^^
+M_>^\G9"\+R"8G`60+0&FWO0('-DN&0``/YG$G_^\_I"FV?08"KPNDCYMEP'9
+M,1D``-\O&0``/YD___"4__#T_[PIDI"0`:8/]`@%^`C'SPGU"Y,`QSD)]1N,
+M`-D$:!$!E`\$O/G@O^F,___OW01P$0&\_?#PE8#]G`2@Z;_YC8`6$;P-`)0+
+M!/"5@/V#P.4*02\(L#>1%@``+N<
+M`K:4`KR>D#6?`;PO])0I!KN?`M]`6```O)^0#P*@GTD?_O\YE/&5H`*@23X)
+MF0''.0GU"_D`L_T`]0"4*0:4+P.\GQ+90%@``+P9$)@9!!@;#_"40/0+(?"T
+M_SW$L@I^$B,`LBH]M'Z7(P"8&00/O_V?!+49!(V`%A&\#0"4#@2_Z4\?_)``
+M@)0-!/V?!/"5D*#IH-G9!&@1`8X`Z>Z\#@"4#02\V?"_^=X$
+MT/V]`@@+,D!":4"0>/P"("W01@$0&\G9"\
+M#P"@GH]`W?V4"0>\#P`^'9P!LR0#(Y0)!(V`%A'?!&@1`;R?D+P-`*">C8#I
+M[I0)!#X:G`&2*0&4#P2PE@'T#!'9!'`1`;SY\*#^/@R<`=T$:!$!O/WPH/ZX
+M^0`(`*">/@R<`8G`(@*\"0"4"0<^JYL!LR0#$HV`%A&\#0"4"00^JYL!C0`7
+M$9(I`;P-X+"6`?0-#XF`%A&\"0"4"02@GY3I!*"?O!&0E!\$W418``"[^0()
+M"+;T`KS]\#7Y`3[UFP&R&GY!(0#=[F```#_?O!'@E!D$NYX"$/\!(-_?1%@`
+M`+:4`KR?D`\+-9\!E!\#E!D&W4!8``"[GP*\G9`/#Z"?^R&/`!<1C0#I[KP/
+M`)0)!+P-`+^?21_^__F4Q9_PLRT$4O\^;)L!^```````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````V3`9``#Y(C^=B4("$+*AO!D0E!D$OYN4K@.)OOWOE*\&O!D0
+MN_X"V4!8``#PU/^\^?"0'@&8_`6F[?0('-DN&0``/YG$G_^\_9"FZ?08"KP=
+MDCYMG0'9,1D``-\O&0``/YD___"4__#T_[P9DI"0`:8/]`@%^`B4&0.4'P:\
+M^2*]E-]`6```O"\@M2D*Q\EELY0#7K(*O;1^8"0`E`D'WPA@$0&\GY"_F?"4
+M#_0;#;(:?IXF`#Z:G@&R"@L$O<1^$R``F"X$O!'PE!D$NY\"#^_PY0C][P3?
+M1%@``+:4`K4N!+R?D`\'-9\!/IJ>`;.=!94`Q[D!]1ND`+\ILY0(!O@(WP1@
+M$0&4#@>\[^"\$?"4&02[GP+?1%@``+:4`KR?D`\#-9\!O^F/P"("O`\`WP``
+M`,[]GP3QE7\,E`T'H.F)0-W]O]^\"0"4&0.R"I00!KL)`ME`6```O`D`"0*@
+M"4D?_OWY!/#UL(M!?@6@WWXE:@"8"01/?__]GP2U"00^FIX!LY0`%PL$L@J]
+MQ'X3(`"R"DL1#GXE:@#[(?@`````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````")0@(0^3*RH;P9$-DP&0``E!,$
+M/YF_.X^^_>^\'Q#$G_^0'0&FW_0()-DN&0``/YG$GO^\[Y"FV?08$KP?DI"0
+M`:8.]`@H/FF?`=DQ&0``WR\9```_F3__\)3_\/3_O!F2D)`!I@_T"`7X"-D(
+M8!$!E`X'O.D@ORG'O`3T&P7X")0?`Y09!KR?TM]`6```O-_0F-\$O92UV0I)
+M]^_]^02UWP2_*:`IL\0`"L2Y`379#MD$8!$!O.G@O^F/P"("O`\`WP```,Z4
+M#0?]GP3PE2&@Z;_?B4#=_;P)`$D?_OWY!/#UL+(*H-^+07X%?B5J`+V4WR0D
+M``&R"I00!+P/`*`)V=S;__Z]M+P)`'Y@)`"\$9"["0()!M]$6```M@0"O`\`
+M-0D!ORF_.90?`Y09!KN?`M]`6```O)^0#P2@G_LQ^```````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````````````````/DB
+MV3`9```_F;*BD*T!Q)__IM_T""39+AD``#^9Q)[_O.^0IMGT&!*\KY*0F@&F
+MKO08)CY8H0'9,1D``-\O&0``/YD___"4__#T_[PIDI":`::O]`@%^`B4K@?<
+M"&`1`;SLD+^?OY^-P"("O*V@E*T'H)^_V8]`W?V\KZ!/'_Z2S`3]GP2\[.#Q
+ME3`!H-F_[]D```#.W-S;__Z]%/WY!-DD)``!\/4AH.^4(`2]M+P)`*`!O`P`
+M?F`D`+PBD)0O`[L)`I0I!KN?`M]`6```W418``"\GY`/!=S@&0``M@0"O`T`
+MF)T$-0\!D)\,-?$!?\ZUD0I/]^_]WP3PY2"UG01@SOLA^```````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````^3+9,!D``(U"`A`_GK*AO!T0E!,$OS*4KP/=0%@`
+M`)2I!O#D_[N?`H^^_>^\G9"\'Q"8G`60'0&FWO0('-DN&0``/YG$G_^\_I"F
+MV?08"KP>DCYMHP'9,1D``-\O&0``/YD___"4__#T_[P9DI":`::O]`@%^`C'
+MP`GU"Y\`QRD)]1N8`)2N!]\$8!$!O._@O^F/___OC<`B`KRMH/V?!*#IO^F/
+M0-W]E*T'O*^@WP```,[]GP3QE7\,H.F_WPGO0!_^BT%^!?'U``+]^02@W[_9
+M_9`$\)6PH-E^)6H`O!'PE!D$W418``"[GP(/`[:4`KR=D#6?`;P?])09!KN?
+M`M]`6```_R`$O)^0\06@`@\"H#"@GSX+I0''*0GU"^\`LPT`ZP")P"("C4#=
+M_;RIH-\$8!$!E*L'O*V@O[R4K@>\[^"_Z8\0<^^4'03]GP2@Z4D?_/W)!-DD
+M)``!\,60O-G@H+R_[[P1D+O9`HG___[]^00)`:#OMM0"WT18``"\W]`UV0&4
+M&0.4'@:[Z0+90%@``$__P[SIX(D,//__*93PE8#]GP2@.9CI!*#@\90`$/0+
+M"0L!?F`D`+P1\)09!-U$6```NY\"MI0"O)V0&)X!E!\#E!D&NY\"WT!8``"\
+MGY"]]+6?!!+N"S#F`?0,#]_N8```/_D2F0$@^=GN8```/YDPE@#T'P7X"/LQ
+M^```````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````^0+9,!D``#^9LJ"0K0'$G_^FW_0()-DN&0``
+M/YG$GO^\[Y"FV?08$KRODI":`::N]`@H/E:F`=DQ&0``WR\9```_F3__\)3_
+M\/3_O`F2D)H!IJ_T"`7X"-D$8!$!E*X'O.G@O^F/P"("O*^@WP```,Z4K`?]
+MGP3PE1"@Z;_/21_^E`T#E`X&_?D$N^T"\/60V4!8``"@S[SIX)CN!+P`\)0)
+M!+N?`M]$6```MI0"O)^0#P@UGP'QY``0B4#=_;RIH+/@``H+`7Y@)`"4#P.4
+M"0:[GP+?0%@``+R?D)B>!+WTM9\*3_?O_>\$M9X$^P'X````````````````
+M`````+^O^2*8K@&RH)BB",3Y![.0`0FSG0.&`0GX__F4\)4!H`G$Z0CU&W0!
+MQ_F*]`L9V<`V``"8FP&R"K:U$'[&0@"SJ0%9`9@/"-D```H(__F4]`L1B0``
+M$/_YE;4)"#Z9J`&R"G[A>`"8"0C?P#8``)61',><:+7Q'[7\';,4`0\)!K7Y
+M'@D"/I&G`0D'M?D>"0&U^2#'*1+T"RW'*1,*#O4;_`"S%`$-WR4:```^M:'!H``-T?&@``/.R8/-SXTP#8``/WY!/Y%`=D````1LN/_^66_X+T4!`'8+!D``-``0``)CO"PD!M3DXY/D`@'.9`'X"B?]____YE-K0-@``M>D+?F:T`+.I
+M`&8"/DVJ`9@Q!K,9`&`"F!D(QYD-]1M5`K\?F!(!Q/D'LY0#)5@Z"0GX__F4
+M\)4!H!E^^7L`LZ``%;(:O;1^G`@`/LNJ`;.=`20"Q"\(]`L+`00`"S[NK`'2
+MB5P``#\IH%_'F0'T&RBTL`JP40#:`*`@$``'Z&1P"_6;.4``L_
+M*?"5`B`IOUFSE`,2LAH!!'X`IP&RH#[NK`$!!+.=!\L!^`@!!#[NK`&8/QV8
+M/B#9\!D``+(!O)^8``VUG@@^[JP!F#D'`0C'F0+U&S(`"0?0Q$@$+/NRL`0$-/NRL`0$'``8^[JP!`0,^[JP!`00`!:80]1M9_-G`
+M-@``H)&S%`%XV8E<```_F?"4`?0+:M\`IP$`V?___P"R^MN=J`$`N[\"_?D$
+M_D`!W0```"&0`"S__=6P`0`,(=X"`0``?H9'`+\`LP0'"O@(/F6M`;,$`A;?
+MX!D``'_YLA3PE1!@^3YSK0&S```&^`C?B5P``#_Y\)3^(/FR2O0P!/N%"/@`
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````````````````#X`+WT
+M]##XO>3Y>40``+`1`#"1!+(L#4!^.\(`#@2SJ0#8`+\YM1((#@0`
+M!;49!;])M1D&/MVO`1@9$#.9`*<`/92R#C49$``(/MVO`9@:"+WTF*D)M1D'
+MF*D(F*X*M:\)M:\._9<$M:\/M:D(Q^D7]`L@F*D&MI48DID(L)8"]`T1OUE_
+M;_"5`O#U`J!98&_'Z5CT"PD+`GY^"0"_.0X(QYD"]!M1#@@`!C[=KP&8&068
+M&P:8'`@*\/^:I`D!WGE$``"P$0`PD00-0'X[P@`.!K.@`"4`!S[=KP$8&1`S
+ME``*L@X^W:\!F!D'L@Z@.3V4-1D0``.FX/4;5_ZU'@.]I#[NKP$*`?0P"/MU
+M")BI!OD2LJ&5D!CT"PK$"8`SD``&^`B8&0K'F5CT"PNR&KVT?GX)`+,)$:``
+ML`81]`PEL`8*]`P7L`8(]1BG`+,``3RS#0*"`#[6L`&S!!!Y/FFP`;,`%%*P
+M!A3T#!"S"1*$`+,$$V(^N[`!L`86]`Q7/KNP`;VD/MBP`;\9QYF*]`MBF!\-
+MQ_DTL)8!]`U6B?__S[(*__F4CP``(/V?!;49#3[8L`&8'PV_'@GX_>D$B?__
+MS_#E!/WY!+4?#:`>"@(^V+`!^`B8'PV_'@GX_>D$B?__S_#E`OWY!+4?#3ZQ
+ML`$*`?L1OZGY`K*]]##\LL#'F8KT&QV8J0>8KPC>____!_V>!,?_E;;T&_WY
+M!;6O!YBI")BN!M___P'P_9\$CP``#/V?!=____\`M:D(_>\$M:X&E9P.!H``)@9`3SL^+W4M1P$
+M/.W)_[F6\/3_M1T#M1D!=1\$#18^L;4!LNRPQ@+T#<+9`"```+6`[/D`!N8&03?
+M-%L``+SYF+.0`".R#0`?/KFU`9@9!-],6P``O/F8LY``#+(-`"`^N;4!F!P'
+MF!\(O92U%!RU'!6U'Q:U&0FSY``EF!D$WQP:``#N`O^?Q;4<"[/@`!4)\/^I
+ME+B9`"``M9P,/D&T`9@;"@T,?M@'`)@?`U@>!-DT7```OYN0_P%VY0&U'P-U
+M'@2R7;`Q`-H`M@$`#"'>B4P``'Z&1P"_.0T;LYT`/@'?,%P``#_Y#1L`%_"4
+M_2#Y/KFU`;\YLYD"*0&SG0"U_@(^1K4!^`BR#0`=/KFU`=HX(```O;1^`JX!LZ``8)@9`U@?!+(-`!Z0
+MF0%V]0&U&0-U'P0^N;4!V3@@``"8GP%)``'H&Z__Z!?M1X0OU^U'Q&SY``+OUFSF0`!!,?I`O0+(!@?)`GP_^F4N)0`
+M(`"U%!0S_0'*`[(N#0(^>;L!"0&R+C49/0T"/MRW`1@9)#.4``RR+@T#/N6X
+M`9@9$)@<$9@4%+49$K4<$YA/#IA.#[44%:!OH%ZU'A&U'Q#'^0+T&PVR+@T#
+M``0^>[L!"?"R+O_YE`T#N)D`(`"U&10^>;L!&!D]F!P",Y0`$Y@9%::<]!L*
+MF!,#/A*X`;+#OVF_6PKPL!$`_YJD"0*R/#"1!`U`WG)$``!^.\(`LZ0`#+(N
+M#00^>[L!OVRU$Q0-!``%M1P0OUZU'A&R+CY[NP$8&3PSE``,LBX-!3Y[NP$8
+M&3T]]#4?/#.9``L#F!D4-1\]F!\0#/>8F0[]G`2FG_4+\P*R+@T%/E6[`9@9
+M$)@;$9@<%`KP_YJD"0&P$0`PD00-0-YR1```?CO"`+.I`)`"L@VR+@`'/GN[
+M`1@9/#.9`'X"F!\2/90U&3RS]``,LBX-!SY+NP$8&3XSE`$.LBX-!P`@/GN[
+M`9@>%9@?$I@9$PT'M1X4M1\0M1D1LBX^5;L!&!DDOQ\2F0$U&22S\``[F!H4
+MF!L0F!P1LHWY];.@`Q"SH`02LZ0"(CZ4NP$`(#Z6NP$8'R0)"+VDM1D.$/\!
+M-1\D/HZ[`;(N#0@`"CY[NP&8%!2820:VE1CT"PR820:PE@#T'P\8&20SF0``
+M`CY1NP&830Z83P^8'A`,]Z!MH%__W)2FGO0;'Y@9$:;Y]!L7F!D'F!X(O?2R
+M#:"?H.^R+CXUN@&8'`>_R::>]!L6F!X(F!\1O^FFG_0;":#-OU^@[Y@9$K.9
+M`)P!QYD"]`LPF!D4F)\.Q_D"]`LDF!T5F-X.Q^D"]0M\`[L!WO`9$`&_Z?"4
+M`O0;"[(N#0L^>[L!LBX-"P`4/GN[`9@9`9@4%+.9`!H!F!L0F!P1F!T5LDKY
+ME;.@`AZSJ0,$`;.D`528'A#'Z0+U&_4`F!<1/GRZ`9@9$,>9`O0;"[(N#10^
+MJKH!F$H+LFNR7+:E&'YA-@"SI``&^`B820R_;[]7#12VE1NVE`:\G^"@;@`1
+M/GN[`?@(/EN[`9@<%`D!L!$`,)$$LBJR>PU`WG)$``!^.\(`LZ``;[(-LBX`
+M$CY[NP$8&3PSD`!>F!D0/?0U'SS'F0+T"QF820R82@NVE1NVI1AVI`;]J05^
+M$38`L@VR+CY?NP&8&1*SD``3F!\5F!P3M1D0M1\4M1P1&!DD,Y``0Y@9$K.4
+M`""R+@T,/DN[`?@(LBZR#3Y[NP&R+@T>``(^>[L!L@VR+@`#/GN[`;(N#10`
+M##Y[NP&R+@T*/GN[`;(-LBX^Y;@!LBX-!0`(LN*FT/4;K_JU'0Z]I#Z.NP$*
+M`?0P"/N%"``#LBX-"#Y[NP'X````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````-[@&0``?^_T,.S9T&4``/F"\?3_
+M^_0P^#^2/;1@[SZPVP$S*2+K'#`F(O4,_@`S*1&A#3`F$?0,>#,I"$D&,"8(
+M]`PX,RD$_P(P)@3T#!@S*0)6`C`F`O4,O`(S+0%1'SYBO@$S*09A!-'090``
+M,"8&]0S/!#ZNOP$S*0S]"#`F#/0,$S,I"F\',"8*]0SQ!SX-PP$S*0[]"C`F
+M#O4(@0HS*0_+"S,M$`H4,"89]`PX,RD5#1,P)A7T#!@S*1,@
+M$M'090``,"83]0R\$CY#R@$S*1<'%-'090``,"87]0QY%#ZGT`$S*1TK&#`F
+M'?0,&#,I&Y<5T=!E```P)AOU#`D6/E?2`3,I'Q,9,"8?]0C2&#,I('@9,RTA
+MC1X^%]@!,RDS#0XP)C/U#+$`,RDJ?08P)BKT#%HS*28V`S`F)O0,*3,I)&P=
+M_DH!_DT!T=!E``"0JCR0W330Q&4``#`F)/4,O0(^8=H!,RDH803^2@'^30'1
+MT&4``)"J/)#=--#$90``,"8H]0S)!3YXP0$S*2Z3"C`F+O0,*3,I+!<)_DH!
+M_DT!T=!E``"0JCR0W330Q&4``#`F+/4,#PH^7L8!,RDPQPLP)C#U"$\+,RDQ
+MJ`PS+3+4'3[IR@$S*3SM%3`F//0,/3,I-SX/,"8W]`P8,RDU>P[1T&4``#`F
+M-?4,WPX^ILL!,RDY&Q`P)CGU"(``0``)CO#\3Y`_0+%#(K20/_`@+_^92UZ0\^L-L!W6!F``#4`!"#?8,X^O=L!V5`@``&_F?Y.`9#N/*#IV50@
+M``&_G_Y)`9"9.*"?O^GPE#_T"P7X"/Y)`9"9/+^:DID$OYN]E``"L)$`,`$$
+MW.!E```-$-XOQ```?CO"`+.@``PR"P(#/K#;`=_@&0``?_DR"_&5``1@^3ZP
+MVP'?T&4``%CY''"6`/0>%M_@&0``?_D+`_&5``1@^3ZPVP'QE/]_"P-U^1P"
+M!#ZPVP'9T&4``)B>!)B=!?Y/`?Y)`9#_/)"9.*#^H)V_^?"4/_0+!?@(_DD!
+MD)D\OYJ2F02_F[V4L)$`"0+<\&4``#"1!`T0WB_$``!^.\(`LZ``#`L$`@4^
+ML-L!W^`9``!_^0L$\94`!&#Y/K#;`5@9''"6`/0>%M_@&0``?_D+!?&5``1@
+M^3ZPVP&8'@B8'PGQE/]_=1DD/
+M`B4^L-L!F!D&F!L'OPP/\*"I"0B@V;_9WB_$``"0F0_]GP2@V;^JO]V]E+"1
+M``D",)$$?CO"`+.@``P+)0(F/K#;`=_@&0``?_D+)?&5``1@^3ZPVP'?T&4`
+M`%C]'-G$90``OYYPU@#T'A;?X!D``'_Y,BOQE0`$8/D^L-L!Y-G_?W7Y'+_O
+MV0`F``$+"++JH)^8[P&0F02@GW[#VP$R*P(G/K#;`=S$90``V0`F``&_S[^9
+MW=!E``#^2@&0JCR@^=D$)@`!OYG^3@&0[C2U^0&8V0:8VP>_S*"I"0B@Z;_O
+MO92PD0`)`S"1!)#_#PGP_?D$H.^_JK_MWB_$``!^.\(`LZ``#`L&`@<^L-L!
+MW^`9``!_^0L&\94`!&#Y/K#;`5@?''#V`/0>%M_@&0``?_D+!_&5``1@^3ZP
+MVP'9Q&4``+^:Y/G_?PL(=1D_
+M#+R?D*"IH-._V0_PWB_$``"0F0_]GP2@V;^JO]V]E+"1``D",)$$?CO"`+.@
+M``PR,@LG/K#;`=_@&0``?_D+)_&5``1@^3ZPVP'?T&4``%CY''"6`/0>%M_@
+M&0``?_D+*/&5``1@^3ZPVP'0Q&4``+\*\93_?PLH=?D+\0``#"1!'X[P@"S
+MH``,"P@""3ZPVP'?X!D``'_Y"PCQE0`$8/D^L-L!T-!E``!8#QQP]@#T'A;?
+MX!D``'_Y"PGQE0`$8/D^L-L!V<1E``"_FN3Y_W\+*'4)''[#VP'9)````;^9
+M"PD""I"9`;4)(3ZPVP$)0)@?!J"IOZF8&P>_#-XOQ```O)^0H*E)(`&@V;_9
+M#_"0F0_]GP2@V;^JO]V]E+"1``D",)$$?CO"`+.@``P+*0(J/K#;`=_@&0``
+M?_D+*?&5``1@^3ZPVP'>T&4``%CO''#V`/0>%M_@&0``?_DR*_&5``1@^3ZP
+MVP'9Q&4``+^:2R`!Y/G_?W7I''[#VP%^@=X!,BL"*SZPVP'9T&4``)B:(7XI
+M;@"QI@\G]`QHV3$9```_GMDO&0``/YD]U,3O__"4_[R?L#XVQ`&_^;_/$.X!
+M\)0/]`LKQ/D/]`LEQ-G_E)\$V0AH$0$0W0&\^?#$Z?^X_``(`*:;]![2/FO$
+M`=_@&0``?_D+"O&5``1@^3ZPVP&]]-G090``"PJUGR$""SZPVP'9,1D``#VT
+MLI@_FM%"0``;R>D+^?OQF\GUF_;[\9/)\YCI`6$<2Y_S]]O)GPO/GPO)Z0/XZ4
+M]`.4E@3PU/^\_Y#PY/^0_P'$K/^0E0&\WM`0NP&4\P,0J@'0Q&4``*;-]!Z.
+M"4#?T&4``/Y-`9C\!I#=/*#9O]G^3@&0[C28^P>\G)"@V4D@`:#IO^F_#`_P
+MD)D/_9\$H.F_VK_MO92PD0`)`]XOQ```,)$$?CO"`+.@``P+"P(,/K#;`=_@
+M&0``?_D+"_&5``1@^3ZPVP'>T&4``%CO''#V`/0>%M_@&0``?_DR*_&5``1@
+M^3ZPVP'9Q&4``+^:Y/G_?TL@`77I''[#VP'9,1D``#^^)?N_KS^\,2=#[/4
+M!PP-!0D!/OC%`;V4W@AP$0&\_O"__\3^#[/@!PRSD``*L^0&!@X%L]``"+/D
+M``@-!;+>E"D"Q_]PN_D$$,P!_:\%$!$!O-GTO.F4_0\%_;D%Q,G_II/T'HW9
+M>!0``:"0D)D$H)L"#9"9!`L,H)H^L-L!26`!F!\&H*F_J9@;![\,WB_$``"\
+MGY"@J0D+\0``+R?D*"I27P!H-F_V0_PD)D/_9\$H-F_JK_=O92PD0`)`C"1!'X[
+MP@"SH``,"RT"+CZPVP'?X!D``'_Y"RWQE0`$8/D^L-L!W]!E``!8^1QPE@#T
+M'A;?X!D``'_Y,BOQE0`$8/D^L-L!\93_?W7Y''X"W0'9Q&4``+^:2WP!?L/;
+M`3(K`B\^L-L!?E[=`4F``=_090``_DT!F/P&D-T\H-F_V?Y.`9#N-)C[![R<
+MD*#927P!H.F_Z=_$90``O_P/\)"9#_V?!*#IO]J_[;V4L)$`"0/>+\0``#"1
+M!'X[P@"SH``,,BL"$#ZPVP'?X!D``'_Y,BOQE0`$8/D^L-L!WM!E``!8[QQP
+M]@#T'A;?X!D``'_Y,BOQE0`$8/D^L-L!V<1E``"_FN3Y_W]+?`%UZ1Q^P]L!
+M,BL"$3ZPVP%)``/?T&4``/Y-`9C\!I#=/*#9O]G^3@$`,)#N-+R+\0``#"1!'X[P@"S
+MH``,,@(++SZPVP'?X!D``'_Y"R_QE0`$8/D^L-L!WM!E``!8[QQP]@#T'A;?
+MX!D``'_Y"S#QE0`$8/D^L-L!V<1E``"_F@LPY/G_?W7I''[#VP%^OMP!`C$+
+M,#ZPVP%^=MP!20`#W]!E``#^30&8_`:0W3R@V;_9_DX!D.XTF/L'O)R0H-D)
+M,*#IO^G?Q&4``+_\#_"0F0_]GP2@Z;_:O^V]E+"1``D#WB_$```PD01^.\(`
+MLZ``##(K`A(^L-L!W^`9``!_^3(K\94`!&#Y/K#;`5@?''#V`/0>%M_@&0``
+M?_D+$O&5``1@^3ZPVP'9Q&4``+^:Y/G_?PLP=1D%M_@&0``?_DR*_&5``1@
+M^3ZPVP'0Q&4``+\*\93_?TN``W7Y''[#VP&_"]H0#@``3(`#?E0W`#(K`C,^
+ML-L!28`#W]!E``#^30&8_`J0W3R@V;_9_DX!D.XTF/L+O)R0H-E)X`*@Z;_I
+MW\1E``"__`_PD)D/_9\$H.F_VK_MO92PD0`)`MXOQ```,)$$?CO"`+.@``PR
+M*P(T/K#;`=_@&0``?_DR*_&5``1@^3ZPVP%8&1QPE@#T'A;?X!D``'_Y"S3Q
+ME0`$8/D^L-L!T,1E``"_"O&4_W]+X`)U&1Q^P]L!OPO:+$P``$R0`'Y4-P"_
+M"]J84@``3-P!D+O`?E0W`+\+VN!+```,0+B[G`(`?E0W`+\+VI`1```,`[B[
+MW`(`?E0W`-F0$0``/Y\)_R;Y]`L/WY06```_^1"9`2#YV9`1```8GP$)_R;Y
+M]`L/WY06```_^1"9`2#YV9`1```8GP()_R;Y]`L/WY06```_^1"9`2#Y"S0"
+M-3ZPVP%)8`;?T&4``/Y-`9C\"I#=/*#9O]G^3@&0[C28^PN\G)"@V4D@`J#I
+MO^G?Q&4``+_\#_"0F0_]GP2@Z;_:O^V]E+"1``D"WB_$```PD01^.\(`LZ``
+M#`LU`C8^L-L!W^`9``!_^0LU\94`!&#Y/K#;`5@9''"6`/0>%M_@&0``?_D+
+M-O&5``1@^3ZPVP'0Q&4``+\*\93_?TL@`G49''[#VP&_"]K`20``3"`"`C=^
+M5#<`"S8^L-L!28`(W]!E``#^30&8_`J0W3R@V;_9_DX!D.XTF/L+O)R0H-E)
+M[@*@Z;_IW\1E``"__`_PD)D/_9\$H.F_VK_MO92PD0`)`MXOQ```,)$$?CO"
+M`+.@``PR*P(X/K#;`=_@&0``?_DR*_&5``1@^3ZPVP'?T&4``%CY''"6`/0>
+M%M_@&0``?_D+./&5``1@^3ZPVP'0Q&4``+\*\93_?TON`G7Y''[#VP&_"]KX
+M#0``#`0".7Y4-P"_"]K\#0``#`R0NP1^5#<`OPO:"`X```P$D+L0?E0W`+\+
+MV@P.```,!)"[%'Y4-P"_"]KL3```3-4"D+L8?E0W``LX/K#;`4EP"]_090``
+M_DT!F/P*D-T\H-F_V?Y.`9#N-)C["[R+\0``#"1!'X[P@"SH``,"SD".CZPVP'?X!D`
+M`'_Y"SGQE0`$8/D^L-L!W]!E``!8^1QPE@#T'A;?X!D``'_Y,BOQE0`$8/D^
+ML-L!T,1E``"_"O&4_W]+U0)U^1Q^P]L!OPO:P4\``$S5`GY4-P`R*P([/K#;
+M`=#$90``OPI,@`/;$`X``'Y4-P"]U+W$OPZ4WP*4V06[GP(\Z?B0W0&\Z>#P
+M]`'T"PFU[`.U[`*SU"#@W]!E``"]!)C]"OY*`9"J/*"@OZG^3@&0[C28^PN\
+MG9"@J4F``Z#IO^G?Q&4``+_\#_"0F0_]GP2@Z;^JO^T)`[`!`#"1!-XOQ```
+M?CO"`+.@``P+$P(4/K#;`=_@&0``?_D+$_&5``1@^3ZPVP%8'QQP]@#T'A;?
+MX!D``'_Y"Q3QE0`$8/D^L-L!V<1E``"_FN3Y_W]+@`-U&1Q^P]L!`A4+%#ZP
+MVP'0Q&4``+\*VRQ,``!,D`!^5#<`OPK;F%(``$S<`9"JP'Y4-P"_"MO@2P``
+M#$"XJIP"`'Y4-P"_"@P#VY`1``"XJMP"`'Y4-P"]U+W$OPZ4WP*4V06[GP*\
+MZ>`8Z<"0W0'PE`'T"PFU[#.U[#*SU!'@28`#W]!E``#^30&8_`J0W3R@V;_9
+M_DX!D.XTF/L+O)R0H-E)X`*@Z;_IW\1E``"__`_PD)D/_9\$H.F_VK_MO92P
+MD0`)`]XOQ```,)$$?CO"`+.@``P+%0(6/K#;`=_@&0``?_D+%?&5``1@^3ZP
+MVP%8'QQP]@#T'A;?X!D``'_Y"Q;QE0`$8/D^L-L!V<1E``"_FN3Y_W]+X`)U
+M&1Q^P]L!`A<+%CZPVP'0Q&4``+\*V\!)``!,(`)^5#<`26`&W]!E``#^30&8
+M_`J0W3R@V;_9_DX!D.XTF/L+O)R0H-E)(`*@Z;_IOPP/\)"9#_V?!*#IO]J_
+M[;V4L)$`"0/>+\0``#"1!'X[P@"SH``,"Q<"&#ZPVP'?X!D``'_Y"Q?QE0`$
+M8/D^L-L!6!\<+\0``#"1!'X[
+MP@"SH``,"QL"'#ZPVP'?X!D``'_Y"QOQE0`$8/D^L-L!6!D<<)8`]!X6W^`9
+M``!_^0L<\94`!&#Y/K#;`=#$90``OPKQE/]_2]4"=1D%M_@&0``?_DR*_&5``1@^3ZPVP'9Q&4``+^:Y/G_?TN.
+M`'4)''[#VP$R*SV4`CTU"4$^L-L!T,1E``"_"1@?01B9C";Y]`@+"ST"0#ZP
+MVP$+,-H@9@``?APX`+\.&!E!WT!<``#<``0``+4?&?"4_YC/#[R9D+SIX'_N
+MO=3Q]0"`V3P$```+/74>*34=4+7/#[4=%K49%0(^/K#;`=X`!```F.\/Y/D`
+M@'.0`".)_W____F4VB!F``"UZ0]^9K0`LZ``#`L^`C\^L-L!W^`9``!_^0L^
+M\94`!&#Y/K#;`9@=%K/4``;X")C9")C>`4__W_^?]+7?",?N`_0+%XG___W_
+M^92RVK79"'X,C``^`]4!V?__`?"UW@__^92UW@FUW@JUW@ZUV0C?T&4``!CY
+M03(K`CT0F0$U^4$^L-L!V=!E``"8D2#>0#@``-/$90``O524$@8$`[PN(#[.
+MU0&_*;.9`(T`OSW?0#@``)00!KP/`!C?C)@)"Y@.#/Y+`?#T_[S_\+:5&+S?
+MT':4!K;E&_V>!6#9OS_^3`&0NS"0S"P8^8P0F0$U^8R8"@NVI1A^838`LZ0`
+M!O@(F`H,M)`,M+`+L%$`MJ4;,$$$MJ0&L@R\J:`-0+"A#-XOQ```?CO"`+.@
+M``H-'C[8U0'X")`1`9`B0+$610#U#6?_#1_9T&4``#+2M9$@"QT^L-L!WM!E
+M``!8Z1QPE@#T'A;?X!D``'_Y"Q[QE0`$8/D^L-L!F.\@\93_?PL>=>DT&4``%CO''#V`/0>
+M%M_@&0``?_DR*_&5``1@^3ZPVP'9Q&4``+^:Y/G_?TN.`'7I''[#VP$R*P(A
+M/K#;`4G``]_090``_DT!F/P&D-T\H-F_V?Y.`9#N-)C[![R%M_@&0``
+M?_D+0?&5``1@^3ZPVP'0Q&4``+\*\93_?PM$=?DO?39$!0``:"?3P`!D)D$H)\/`;B9]`$`H)_9Q&4``+^;VIP$
+M```,)`)"?E0W``M!/K#;`=#$90``OPK;G`0```PD?E0W`+\/V0`$``"8F1K<
+MT&4``/Y*`9"J/+7Y"=G880``OP^_F?Y-`9#=--XOQ```M?D*V0!A``"_#[^9
+MM?D+V01:``"_#[^9M?D,V0A:``"_#[^9M?D-V0Q:``"_#[^9M?D.V1!:``"_
+M#[^9M?D/V3!;``"_#S^9-?E`V3%;``"_#S^9-?E!V8A<``"_#S^9-?E"2<`#
+MF,\&H*F_J;R?D*"I"42@V;_?F,L'O92_#+"1`)#_#PGP_?D$H-^_JK_="0,P
+MD01^.\(`LZ``##(K`B(^L-L!W^`9``!_^3(K\94`!&#Y/K#;`=[090``6.\<
+MT&4``/Y/`9CM!I#_/*#YO_F8ZP?^3@&0[C2\G9"@^0D0
+MH.G9Q&4``+_ZOYR_[;V4L)$`"0+>+\0``#"1!'X[P@"SH``,"T("0SZPVP'?
+MX!D``'_Y"T+QE0`$8/D^L-L!W=!E``!8WQQP]@#T'A;?X!D``'_Y,BOQE0`$
+M8/D^L-L!V<1E``"_GN3Y_W^8WP]UV1R_Z:;Y]!L,/90UV3L^!]H!WB0@``&_
+MZ0\!-=\[#_?]GP3QE0`$H.G9``0``)B=#\39"/0;!?@(WB0@``&_Z4_W_=P\
+M%``!"T/]GP2@Z;_)Q=Z`#0$RTK"1"[3P"PGU_>D$"?[]^02P\0NT\`O9``0`
+M`+6>#]D08@``()V@SSZPVP&_"9@>#Z">21`$F!\&H*F_J9@;![\,WB_$``"\
+MGY"@J0D0H-F_JK_=O92PD0`)`S"1!'X[P@"SH``,"R,")#ZPVP'?X!D``'_Y
+M"R/QE0`$8/D^L-L!W=!E``!8WAQPY@#T'A;?X!D``'_Y"R3QE0`$8/D^L-L!
+MV0`$``"8GP_DZ?]_==D0``;6Y#SZ1VP'$R0CT"QO=)"```;_>Q``0``)CO#TGS_@M$`@']^02U[P\^L-L!^`@R*R:R]1MPX-G0
+M90``()OT,`C[A13Y,K*MLJ&RL)6Z`CTTV]!E``"RK`(!/@+<`;_9&+]`F+X/
+M-;-`D-T$\/3_O/[PO/GPM;\/DLP!II_T#08ULD"SQ`#;E*D"O!F@Q`D"]`LO
+MW=!E``!_J1C?0)C>#S7<0/"3`/#T_[S^\+R?\+7?#Z:?]`T("0$UV4"0J@+$
+M"0'T"S/>T&4``)CO#QCI0#W4\)3_O)^0M>D//Z_P]/^\^?"U[P\_J?"4_Z:?
+M]`T%#0$U[4#[,=D`!```WL1E``"8G1R_[[7]`9B=';7]`AB=>37]#+_OF)T@
+MM?T%F)TAM?T&&)V)-?T')C^`K6>'1C^##6>>9C^!;6>()C^!K6>(1C^'#6>B9C^";6>
+M))C^"K6>)1C_+#6?F?@`^0+0Q&4``+\+VM`C``!,@`"0NQA^5#<`OP_95"0`
+M`-I6)```#$@8_IB0^YH@GAC_F=E5)```()]^5#<`OPO:>`4``$R4`)"[Z'Y4
+M-P"_#]D`(P``F/\YM9]4^P'Y$M#$90``T0`C``"_"9@?+-O0(P``3(``H)^_
+M"9@?+;6?`;\)F!\NM9\"OPF8'R^UGP._"9@?,+6?!+\)F!\SM9\%OPJ0JAA^
+M5#<`OP_95"0``#^9VU8D```,2#7YF-E5)```OP\_F37YF;\*D*J:?E0W`+\*
+MVW@%``!,E`"0JNA^5#<`OPF8$52UD3G[$=G$90``OY_9H%P``+_^M9X!F/X!
+MH)Y8_@1UG@18_@5UG@68_@.UG@28_@2UG@58_@IUG@Q8_@MUG@V8_P:UGP?X
+M`-[$90``WZ!<``"_Z9C]`:"=O_V_Z;6=`5C]!+_I=9T$6/T%O^EUG068_02_
+MZ;6=`YC]!;_IM9T$6/T,O^EUG0J_Z5C]#76="[_IF/\'M9\&^`#T,/C9,1D`
+M`/F"/Y0]9#)',$$G$G^\'!"\/C#'2!3T&PFR6CY9WP%)__W_6:2/`!<1O!\0E!L$O[R)`.GN
+MY*T``KP9$)7?"$$[O_?_.E/_9E90?!*"YO_F,@.GN
+MO!P0_9X$_]F5H/F4/P.4.0;>3%@``+N?`KR>D!B?`S/T!!64&0?<"&`1`;R<
+MD+^9/O/?`3/T`Q?>"&@1`=SXE^[^O"X@ORD^\-\!W@AP$0&\+B"_*=SXC^[^
+MO"P@QYP,QTT1"?[_J93_R>6SU`$+B0```OWI!3/T!!64&0??"&`1`;R?D+^0
+M/CO@`3/T`Q#9"&@1`;PI(#XYX`'?"'`1`;PO(+\@Q`\/21_^MO0%_^F4__D%
+ML]``#K/$``I)_
+M!:!)QUG1]`L/-)`G,FL\::!^A30`$&8!$',1D``#_)/^_$<_^0
+M.@'PE/_P]/^\GY"FJ?4>ZOW[A0CX````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``#X`-G`50``&)\U&)LT6)X;6)H<6)P=F)T#,_D(@0$P]@CT#"DS^0/\`##V
+M`_0,$#/P`$0S_0&Y`3[)X0$S^05)`0H7,_T&J0'X`#/Y"XP!,/8+]`P1,_D)
+M5P$S_0J2`3[$X@$*)C/Y,(D!"B@S_3&``?@`<^0`4'/$`DS$N1_$K@\SE``,
+M\$D-\0M=D!M=H"Q,D!_9X%M=D#"@'9P%4`
+M`#6D%B?__`?]9E/V?!?Y-`;;$$)#='+79`HD```']R03][`6UU`&RVK7>`W[P
+MX@'[91#T,/#Y8C1@,+*ALK3^0`&RQ9``'#+2,N.R"@L0?APX`#-@``J@`3XQ
+MY`&X&0`@`J`)-,`TE#D%\)0@E"X$\.00\>4`#/WI!91I!O"40(\``(#]Z06)
+M__\!_UF4_9\%_DT!ML00D-T',)`Z,`8!Q/D@]`L+Y.G?_SZEY0'D^0`!]0M+`>3I__YU&0X^G^8!
+M6!\.Y/[__^3I`!#T"Q#D^?_O#P=U&0X^E.4!Y.D``?0+$.3Y__X/!G49#CZ4
+MY0%R#U@=#N3>___$Z2#T"Q+DV=__=1D.<@P/"#[?Y@'DZ0`(]`L:6!\$Y-G_
+M]W(,=1D.\?4`0'4?!#[DY0'DZ0`!]!L)<@P^W^8!Y-G__G(,=1D.#P8^W^8!
+MORF8'G`-]W(,_9T$H"F_/PGX_>D$M1YP_?T$"0&@/[49#`\)/M_F`9@?<+\N
+M"?@,!_WY!/#U`K4?<`D#\.4(M1D,H"X/"3[?Y@':E%<```LL?APX`)@9<;44
+M=K45>G(,\)4&#P&U&7$^W^8!F!]QF!HWF!LXV=Q5``"PD0`)Q_WY!`D!\/40
+MM1]QD*I`,)$$W(!7```-0-Z>P0``?CO"`+.@`!5R#`\*/M_F`5@9#G"6`/0>
+M"W(,<@\^W^8!F!EQF!X,#\?]GP3PE3"U&7&SY`(.6!D$\94`$'49!%@9#E@?
+M&`P*\93_?W49#C[?Y@'X"'(/<@QR\&8,]1O]_>0/___9P%4``/0P"+6?"_M1
+M^5+9P%4``/0P^+*16)`2?<32$(`1`=-0)@`!A```#(4```@^(.D!#>3O___D^0`$]`L@F!]@Y.G_^W49#0GX<@S]^00)`O#U`;4?8#Y(
+MZ`'$^2#T"PODZ=__/N3G`>3Y``'U"TL!Y.G__G49#3[>Z`%8'PWD_O__Y.D`
+M$/0+$.3Y_^\/!W49#3[3YP'DZ0`!]`L0Y/G__@\&=1D-/M/G`7(/6!T-Y-[_
+M_\3I(/0+$N39W_]U&0UR#`\(/A[I`>3I``CT"QI8'P3DV?_W<@QU&0WQ]0`@
+M=1\$/B/H`>3I``'T&PER##X>Z0'DV?_^<@QU&0T/!CX>Z0&_*9@>8`W[<@S]
+MG02@*;\_"?C]Z02U'F#]_00)`:`_M1D*#PD^'ND!F!]@ORX)^`P'_?D$\/4"
+MM1]@"0/PY02U&0J@+@\)/A[I`=I45P``"RQ^'#@`F!EAM11FM15J<@SPE08/
+M`;4983X>Z0&8'V&8&C>8&SC9VE4``+"1``G'_?D$"0'P]3"U'V&0JH`PD03<
+M0%<```U`WI[!``!^.\(`LZ``%7(,#PH^'ND!6!D-<)8`]!X+<@QR#SX>Z0&8
+M&6&8'@H/Q_V?!/"5$+498;/D`@Y8&03QE0`(=1D$6!D-6!\4#`KQE/]_=1D-
+M/A[I`?@(<@]R#'+P9@SU&_W]Y`___]G`50``]#`(M9\)^U'9P%4``/0PV'W4
+M^8*RDO0P^%B0$-@H@!$!/O3S`7,)%T($<`87]0R$`',)#H8"<`8.]`Q#T!3I``$-
+M`?4+2@GD^?_^=2D,/I[J`5@N#.3O___$^4#T"PODZ;__/@3K`<3Y`O0+$N3I
+M_?\`"W4I#`T"/O3S`<3Y(/0+$.3IW_\`"'4I##[=Z@'D^0`!#0+U"_@(Y.G_
+M_G4I#``&/MWJ`5@N#.3O___$^0+T"R68+D#=$(`1`;_?"?C]Z00)_OWY!*#?
+M\.4!``*U+D`^3.L!Y/D``?0+$N3I__X`!G4I#`T#/O3S`<3Y(`T#]0N=".3I
+MW_\`"'4I##Y,ZP'=$(`1`9@N0+_?"?@``?WI!`G^_?D$H-^U+D`-!C[T\P':
+MU%8```LL?APX`)@O08D```RU*4:)```X\/4&M2E*M2]!"00``;4I3@T(/O3S
+M`7X"X0$-"W*@/O3S`0H!?H/D`5@I(@`.#0P^?_,!/:1^@^0!6"DB``X-#3Y_
+M\P%8+PS$^03U"^`'Y/G[_P`"=2D,#0X^]/,!&"DT6"\<"@'PE!\SD``G,Y`"
+M"KVD/C'L`=K`5@``Q/D/MI0&O)J0OYGPE`>PE@+PK`L.`3W4,.$`,.$$O;0,
+M`GX`Y`%8*2(`$`T//G_S`5@O#,3Y!/4+>`?D^?O_``UU*0P-$#[T\P$8*318
+M+AS$GQ\S^0"`!S/T`0KX"#[R\P$-$3/]`G,'Q.\/,_0`%=X0@!$!`!*_[PT1
+M"?X^M^P!,_T!4@__``QU*0P-%C[T\P%8*1M8)1U5GPAS\`)8$%@``#_I\)3_9I7T#05R6>2<
+M__\]E`X!,)$`/=0PX03:$%@``+VT?@#D`5@I(@`8#1<^?_,!,YT`Z07?P%X`
+M`+#Q$-_@7@``VO!>``#9T%X``-Y08```L)$1L.$3L/$4W>!>```_K]S`7@``
+M/YD_[C_=/\RPH1+:$%\``#^K\)3_\/3_L)$,\.3_\-3_\,3_L/$-L.$.L-$/
+ML,$+Q+G_9I7PG`@RD#.0``O$L?\^=NX!Y%'__SV4,`8`\.P+`P$PD0`P,03:
+M$%\``+VTLAPR#7X`Y`$S"0`4`C(W/42]-#UD_DD!D)DLO).0OY_^2@%[40*0
+MJD#D4?__O*.@IO'PG`B0,P0RD#.0``:R\3-$!`8]!#!A`#!Q!+^J,`8`\.P+
+M$$0!O;2R'#(-?GWC`3,)`+L!,T0%KSZI\`'$GO^SX`%JL.8!]!P+L^``&CX:
+M[P&SZ0*>`+/I`]T`#1<`*3[T\P&8*8B8+X"8*X'>V%4``/"4_\3]#WS9T`D"
+ML.$`4-T/"O#QU/#___JD,)$$W#!?``#>GL$``'X[P@"SJ0"'!'(-`!D^]/,!
+MF"F(F"^"F"N#VMA5``#'F>C$_0]0W0]\V=`)`K"A`/'4\/\*\#"1!/_ZI-PP
+M7P``WI[!``!^.\(`LZD`001R#0`:/O3S`9@IB)@OA)@KA3#A!,>9\-[850``
+MQ/T/L.$`4-T/"O!\V=#_^J3QU/#_W#!?``#>GL$``'X[P@"SJ0#]`W(-`!L^
+M]/,!F"F(F"^&F"N'VMA5``"VE1C$_0]\V=`)`K"A`%#=#PKP\=3P___ZI#"1
+M!-PP7P``WI[!``!^.\(`LZD`MP,-%P`,!6"DB#1<`&#Y_\P%8+PP-&,3Y!/4+.`/D^?O_``UU*0P-&#[T\P%8
+M*0QPE@#U'_<"F"F(F"^`6"$=Q)#_Q/L/]`L3V3!?``"R#+RYL+*:?E0W`.0<
+M__^FP/0-!;(,/90.`3"1`#W4,.$$VC!?``"]M'X`Y`%8*0Q8+R(`&`T9/D7R
+M`5@I#`T:<)8`]1_!`I@IB)@O@E@A'<>0Z,3[#_0+$=HP7P``L@R\NK!^5#<`
+ML@SD&?__I@GT#0?D'/__/90.`3"1`#W4,.$$VC!?``"]M'X`Y`%8*0Q8+R(`
+M&`T:/D7R`5@I#'"6`/4?.P*8*8B8+X18(1W'D/#$^P_T"Q/>,%\``+(,O+ZP
+MLNI^5#<`L@SD&?__I@GT#0?D'/__/90.`3"1`#W4,.$$VC!?``"]M'X`Y`%8
+M*0Q8+R(`&`T;/D7R`5@I#`T<<)8`]1\!`I@IB)@OAE@A'960&,3[#_0+$]\P
+M7P``L@R\O["R^GY4-P#D'/__IL#T#06R##V4#@$PD0`]U##A!-HP7P``O;1^
+M`.0!6"D,6"\B`!@-'/&4_W^V]!!U*0R@CS[T\P&8*0,.`3W4,.$`L)8%\*P+
+M,.$$O;0,`7X`Y`%8*2(`'@T=/G_S`5@O#`T>Q/D$]0MQ`>3Y^_\`#74I#`T>
+M/O3S`9@O`Q@I-K/T!!PSF0`R`3.=`3,!6"D$`"`-'_"5"#[,\@&S_044`3.4
+M`!98*00`(0T?\94``G4I!#[T\P$SG0$%`3[2\P%8+PS$^0CU"^H`Y/GW_P`,
+M=2D,#2`^]/,!6"\,#2'$^8`SF0#W`.3Y?_\`#'4I#`TA/O3S`5@I''.0``P`
+M*0TB/O3S`0X!/=0PX0`PX02]I+VT#`%^`.0!6"DB`",-(CY_\P%8+PP-(\3Y
+M!/4+K0#D^?O_``UU*0P-(S[T\P$`*0TD/O3S`3V4#@$PD00]U##A`+VDO;0,
+M!GX`Y`%8*2(`)PTFMI00H(D^]/,!6"\,Q/D$]`L^Y/G[_P`,=2D,#2<^]/,!
+M``P-*#[T\P'=$(`1`;_?F"Y`"?@``_#U`:#?_>D$#2GPY0*U+D`^]/,!^`AR
+M#3[T\P$`##[:\P$`*0T?/O3S`0`I#1<^]/,!`"D-$S[T\P$`*0T19@WU&U[U
+MY`___]G`50``]#`(M9\(^X4HW\!5``#T,,#9P#8``/F"?>3T,/BR\?Y'`<68
+M!%CP!H4```R&```(D'3Y
+M``'T"Q+DV?_^``%U&00.`CZ#^0'$^8`SD``1Y-E__P`0=1D$/D/U`>3Y``0.
+M`O4+(`3DV?_[`!%U&00^0_4!6!\$Y/[__\3I`O0+-K\M6!X,6!D;\?3]_W4?
+M!-____^`\.40_=\$MI08WP```']U'@S]GP0`!/V=!:`I/L3U`<3I@#.0`!/D
+M^7__`!!U&00.`SZ#^0'DZ0`$#@/U"[,#Y/G_^P`1=1D$/L3U`5@#%@9&^3/_?]U'P3?____@/#E$/W?!+:4&-\```!_=1X,_9\$
+M_9T%H"D^@?D!Q/D$]`LEOR]8'@SDR?O_``-U&03PY1#9____@'4>#/WY!*`O
+M/E;V`<3Y"/0+$N3)]_\`"G49!`X$/H/Y`<3Y@#.0`!'DR7__`!!U&00^5O8!
+MY/D`!/4+#0/DR?_[`!%U&00^5O8!6!T$Y-___\3Y@#.0`!'DV7__`!!U&00^
+ML/8!Y/D``O0+$N39__T`#749!`X%/H/Y`>3Y``0.!?4+QP+DV?_[`!%U&00^
+ML/8!F!HWF!LXVP0``,)$$W,!7```-0'X[P@!R#K.I`)$"
+M``<^@_D!6!D$<)8`]1]^`O&4_W\`"'49!`X'/H/Y`9@:-Y@;.-G(50``L)$`
+M"0+>GL$``#"1!)"J0-Q`5P``38``?CO"`'(.LZD`1`(`"0X(/H/Y`5@9!'"6
+M`/4?+P*U%6:R>MM`5P``#$"U%FJU%7:U%GI^5#<`VD!7``#;@%<```Q`?E0W
+M`-J`5P``LGL,0'Y4-P"8&6&8'W%8'00.QP`!_9X$_?X$\)40\/4P\=3_?[49
+M8;4?<74=!`X)/H/Y`5@9#0`+#@KQE0`$/GCX`5@>!.3I``CU"[,!6!\.Y.G_
+M]P`,=1D$\?4`!`X+=1\./H/Y`5@9!`X,\90`$/4+CP$)#]X8@!$!H$F_Z0_P
+M_9\$\)4-H.F_3K/D#?[9%(`1`;WTH)^@3K\I\)4!H"F_*?"4`?0+^U@9"%@>
+M#+\_6!T$ORSPE0+PY0AU&0C9____@/#U`74>#/WY!/'4_^_9````?W4=!/W)
+M!``%_?P%#@R@/SZ#^0%8&0T`#@X-\94`"'49#3Z#^0%8'00.#N39`"#U"_L`
+M6!\.Y-G_WP`/=1D$\?4`"`X.=1\./H/Y`5@#?#5(*`Y=1\,=1T.``(.$#Z#^0&_*=_^__^`WA"`$0']GP2@*;_I#_#]
+MGP2@Z;\\Q,D!]`L&\,406!X-6!\,6!T.V?[__X#QY0`!_\F4\?4``74>#?'5
+M``&@.74?#'4=#@`!#A$^@_D!^`AR#F8.]1O$^N0/___9P%4``/0P"+6?`_N%
+M0-G`50``F)D!]##\^0*SD`!$T*!>```+$+(*?APX`-FP70``6)N#V0````&U
+M"0*)`(@`_DP!L@JU"0.0S`1^`#X`,Z0`$-]4)@`!O_GPE0&@^?L%!-G`50``
+M]##X?Y[Y@MDP&0``/YG$G_]F[_0()=DN&0``/YGD[/__Q)W_O-^0ILGT'P^\
+MSZ*FK?0>*#Y+^@'9,1D``#^?V2\9```_F?#C`/#T_[SOHO"4_Z:I]!X%^`C>
+MP%4``%CI`=\$8!$!C0```K+B\),`MI0'O)^0D)\$OY&_^=]8)@`!O_.RU\24
+M#UC@"K*FQYX,QS71QYEP,.$DMI0*E$@%_YW5??2PT0H^E@`"R!3X^_P%S"0DA!7,-"J0%/F```KWDWP1@$0$^B/\!6"D(\)0!
+M]0N,!;WDWP1@$0$^+OL!6"D!\),`INGT"P^_^=W__P"._9T$H/F0[@&0_X#=
+M+AD``#_9\)3_INGT"-?<5"8``;_-W\!5``!__M____\`_=\$3Q_^MN08_>T%
+MM-`*Q3D#H,[]GP1/_\/]F`7]GP3_G3796"8``:"3LU0`"'Z;^0%8*00``P\"
+M\)4!=2D$/I8``E@N".3O___$^0'U"^(!QQX1,^``833P)#/P`%I8*0&."0`+
+MW01@$0'?````SO"3`/\?]+:4![R=D/_^%;)JH)%+$0Y^)6H`6"\$6"X,6"D!
+M\/5`\.4!=2\$\),`=2X,3Z`"CD("$+R>D+:4!*"?/G;]`94=%I49%_V=!?"4
+M`?0+>;-$!'98*0'?__\`SO\?]-X``,``__X5WP1@$0'PDP"VE`>\GY"/__^_
+MH)%)'?[_.93PE8#]GP2/``!`_9\%W___?__]GP3?``"``/^?-=E8)@`!H).S
+M5``(?IOY`5@I!%@O#``%\94``?#U0'4I!'4O##YV_0&5&165'Q/]GP7PE`'T
+M"PD`"3YV_0$SX``.LT0%"@`(/G;]`<!&`1`;R>D(\``$"@D4D?_O\YE/^?-=E8)@`!H).S5``(?IOY`5@I
+M"`\#/I?^`<3Y`O4+#`/DZ?W_``1U*0@/`SZ6``)8+@CD[___Q/D!]0L#`949
+M%94?$_V?!?"4`?0+"0`)/I+^`<<9$3.0``ZS1`4*``@^DOX!QQ\0,_``.+-$
+M`S18*0'?__\`SO\?](X```'PDP#__A6VE`??!&`1`;R?D(]@`$"@D4D?_O\Y
+ME#Z`_@''&18SD`!%LT0/05@O`8X``$#9__\`SO\9E/#S`/^>%93Y!]X$8!$!
+MO)Z0C<`B`J"1O/WPMO0'O_E.'_[PE1#]G@2@^3Z2_@&S\`!<0`0E@I`=__
+M_P#._Q_TC@``0?"3`/_^%;:4!]\$8!$!O)^0CP``0*"121_^_SF4_Y\UV5@F
+M``&@D[-4``A^F_D!6"D(#P3QE/[_=2D(/I8``L3Y!/4+Z0'DZ?O_``-U*0@/
+M!#Z6``+_%Y3U"]D!LTT%U0&-```(_QV4]1O)`0`(D/_?%0`*H)$^-?\!_Q>4]`L3LT0%$(\```C_'Y3T&P4`"%@I"`\&
+M/I?^`5@N",3I`?4+2@&5&165'Q/]GP7PE`'T"PD`"3YI_P'_%Y3T"PFS1`4&
+M``CDZ?[_#P=U*0@^E@`"O_G=````0)#N`?V=!:#YD/^`W2X9```_V?"4_Z;I
+M]`CB"_^R:GXC:@"R:HM!?@5^)6H`WE0F``&_Z=____\`_9\$H.F/H``"V5@F
+M``&@G[-4``A^F_D!6"D$6"\,6"X-6"T.\94`!/'U``%U*01U+PQ]E/'E``'Q
+MU0`!=2X-=2T.=2D!8"D``@\(/I8``E@I`=\$8!$!W0"`$0'>__\`SO"3`+:4
+M![R?D/\>Y(\!`&K_[Q6@D;_96"X$WP```(``!OV?!4\?_J#9"?W_.93PE1#]
+MGP3PY8#%DZ!U+@396"8``0\)H),^E@`"3Q_^">__.93PE0+]GP2/```@_Y\U
+MV5@F``&@D[-4``A^F_D!``,/"CZ6``+X"'(//I8``@\%9@_U&P?ZY`___]G`
+M50``M9\%^X4(^2(!"@+_T,!5```^)P$"6`D$V1P8$`&@G[B9_`$`OYGDZ_\!L)8`]!X%^`@/_]D8&A`!H)^2F0B_
+MF96?&.>9:`&\G_"0F0&4_0B4G@B\FY"[GP*VE`@^C`@"^ND$N.X``0"XF0`!
+M`*;M]`CQ^`>]Y-E4`0`!H)[?````(-D4&A`!H)^XF0P"`J">D)D$H)Z0F02@
+MGI"9#*">CP``$)*9&*"?#Q.0F3R@GT\`$9"9!*"?N)G``0"_GI"9!+^=DID(
+MOY_9=!T``*">V7@=``"@G=E\'0``H)^QYO\`]`P%^`A)`/"X[P`!`OWY!-E(
+M&!`!H)^RZ=X`__\/O)Z0NY\"WTP8$`&@_8\```;ZGP7X`[WTF/D-F/X,O_V8
+M_P[PE?^[G@*\GY"FG?0(!?@(O?28^0.__Y2^"+R?D*;I]!@%^`B]E)B9#=]T
+M'0``O_U/`/^0F?_]GP3?"!@0`;:5!/&4_S^4GA"@_M\```!`MI0$_9\%WS`:
+M$`&@^=DT&A`!H)V2F2R_GY"9,`YDW4`:$`&@G]\````'D)D$H)_^3P&0_P0^
+MV`D"DNX!L^0!#+_9H/D^R0D"L^0`\;_9H/F_^;"6`/0>"0YD/LD)`ME`&A`!
+MWP```$"@GYCI#KWD/@L*`OKN!+CN``$`INGT"/;X![V4F)\-F)T,20#_D/__
+M_?D$/C0*`OK>!+C=``$`N.X``0"FW_0(\?@'V5@!``&VY0BRO+R^\@H!H)_9
+M)!D``&">/ET*`K;%`1"J`;/$`/J8S@Z8R1%/`/CG[N@!N)G_!P#]GP2VE`C]
+MG@7?4`$``:#YF,D/3P#_D)G__Y^TE;D$Y)#_/]D(&!`!E`\0H)^8S1"8SA$)
+M`=\F&0``NYH$4ID!8/F[[0*)`$`!INGT#07X"+/D``JROCX_"P+9````!/\)
+ME=\,&!`!N+T`0`"@^979!/&4_S^0_P2@^=D4&A`!WP```$'>&!H0`:"?21`G
+MO^^P]@#T'@V2F0'T&_4^%PL"LY0`!O@(W@```$#9&!H0`?W^!:"?D)D(H)[?
+M^/CX^)"9"*"?D-Z`DID$H)_9`!@0`;^?"<"0[C_]Z03P]`^V]`^5[02\_L+Q
+MU/\_WP08$`&5R03QE/\_MI00_9T%H/D.`[WTV2`8$`$8_4R@GI"9"*"?D)D$
+MH)^2F0B@G#/0`&])``'?[[ZMWJ"?D)D$LYX``OM)`/^]U/_)](X``08^Q`L"
+MN-D`(`#ZG@:XW0`!`/@#IM_T".^RSXX``0(^W@L"N-D`(`#ZG@:0W1"FW_0(
+M\[+/3@`!/O<+`KC9`"``^IX&D-T$IM_T"//X`WX)#`)^&T$`^P4$V8`=``"]
+M]*"?V80=``"@G]F8'0``H)_9C!T``*"?V9`=``"@G]F4'0``H)_9`6(``""?
+MV0)B```@G]D`8@``()_9G!T``-J<&@``2T`!H)]^OS<`VMP;``!+F`%^OS<`
+M^`#X^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX
+0^/CX^/CX^/CX^/CX^/CX^```
+`
+end

From 46a30e2e108c3996f8c1ef41888011c2a5cedaf7 Mon Sep 17 00:00:00 2001
From: Xin LI 
Date: Mon, 7 Nov 2016 07:26:06 +0000
Subject: [PATCH 072/127] Vendor import of file 5.29.

---
 ChangeLog                   |  29 +++
 TODO                        |  20 +-
 config.guess                | 376 ++++++++++++++----------------------
 config.sub                  | 137 ++++++++-----
 configure                   |  20 +-
 configure.ac                |   2 +-
 doc/file.man                |  13 +-
 doc/magic.man               |  17 +-
 ltmain.sh                   |   3 +-
 magic/Magdir/algol68        |  19 ++
 magic/Magdir/animation      |  10 +-
 magic/Magdir/apple          | 172 +++++++++++++----
 magic/Magdir/application    |   7 +
 magic/Magdir/apt            |  52 +++++
 magic/Magdir/bioinformatics |  60 +++---
 magic/Magdir/c-lang         |   7 +-
 magic/Magdir/claris         |   5 +-
 magic/Magdir/commands       |   6 +-
 magic/Magdir/compress       |  52 ++++-
 magic/Magdir/cups           |   4 +-
 magic/Magdir/editors        |  27 ++-
 magic/Magdir/filesystems    |   5 +-
 magic/Magdir/fonts          |  59 +++++-
 magic/Magdir/gcc            |   6 +-
 magic/Magdir/gnu            |   9 +-
 magic/Magdir/images         |  32 +--
 magic/Magdir/jpeg           |   9 +-
 magic/Magdir/msdos          | 230 +++++++++++++++++-----
 magic/Magdir/pgp            |  59 +++++-
 magic/Magdir/psl            |  14 ++
 magic/Magdir/python         |   5 +-
 magic/Magdir/ruby           |   6 +-
 magic/Magdir/sgml           |   4 +-
 magic/Magdir/sql            |  71 +++++--
 magic/Makefile.am           |   6 +-
 magic/Makefile.in           |   6 +-
 python/magic.py             |   6 +-
 src/apprentice.c            |  37 ++--
 src/ascmagic.c              |   8 +-
 src/cdf.c                   |  32 ++-
 src/cdf.h                   |   6 +-
 src/compress.c              |  14 +-
 src/der.c                   |  14 +-
 src/file.c                  |   6 +-
 src/file.h                  |  10 +-
 src/funcs.c                 |   5 +-
 src/magic.c                 |   4 +-
 src/readcdf.c               | 185 ++++++++++++------
 src/readelf.c               |  22 ++-
 src/softmagic.c             | 353 ++++++++-------------------------
 50 files changed, 1378 insertions(+), 883 deletions(-)
 create mode 100644 magic/Magdir/algol68
 create mode 100644 magic/Magdir/application
 create mode 100644 magic/Magdir/apt
 create mode 100644 magic/Magdir/psl

diff --git a/ChangeLog b/ChangeLog
index 345b32efdc39..2b6606d2979b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2016-10-25  10:40  Christos Zoulas 
+	
+	* release 5.28
+
+2016-10-24  11:20  Christos Zoulas 
+
+	* der getlength overflow (Jonas Wagner)
+	* multiple magic file load failure (Christoph Biedl)
+
+2016-10-17  11:26  Christos Zoulas 
+
+	* CDF parsing improvements (Guy Helmer)
+
+2016-07-20   7:26  Christos Zoulas 
+
+	* Add support for signed indirect offsets
+
+2016-07-18   7:41  Christos Zoulas 
+
+	* cat /dev/null | file - should print empty (Christoph Biedl)
+
+2016-07-05  15:20  Christos Zoulas 
+
+	* Bump string size from 64 to 96.
+
+2016-06-13  20:20  Christos Zoulas 
+
+	* PR/556: Fix separators on annotations.
+
 2016-06-13  19:40  Christos Zoulas 
 
 	* release 5.28
diff --git a/TODO b/TODO
index 5c2ed49e02f1..78890cfa5ab3 100644
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@ file, not here. More speculative material can live here.
 listed in the BUGS section of the man page had been fixed!)
 
 ---
-
 It would be nice to simplify file considerably. For example,
 reimplement the apprentice and non-pattern magic methods in Python,
 and compile the magic patterns to a giant regex (or something similar;
@@ -15,8 +14,23 @@ small amount of C is needed (because fast execution is typically only
 required for soft magic, not the more detailed information given by
 hard-wired routines). In this regard, note that hplip, which is
 BSD-licensed, has a magic reimplementation in Python.
-
+---
 Read the kerberos magic entry for more ideas.
-
+---
 Write a string merger to make magic entry sizes dynamic.
 Strings will be converted to offsets from the string table.
+---
+Programming language support, we can introduce the concept of a group
+of rules where n rules need to match before the rule is positive. This
+could require structural changes to the matching code :-(
+
+0	group	2	# require 2 matches
+# rule 1
+>0	....
+...
+# rule 2
+>0	....
+...
+
+christos
+
diff --git a/config.guess b/config.guess
index d622a44e551f..f7eb141e75a9 100755
--- a/config.guess
+++ b/config.guess
@@ -1,14 +1,12 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-#   2011, 2012 Free Software Foundation, Inc.
+#   Copyright 1992-2015 Free Software Foundation, Inc.
 
-timestamp='2012-02-10'
+timestamp='2015-03-04'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful, but
@@ -22,19 +20,17 @@ timestamp='2012-02-10'
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner.  Please send patches (context
-# diff format) to  and include a ChangeLog
-# entry.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 #
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
 # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to .
+
 
 me=`echo "$0" | sed -e 's,.*/,,'`
 
@@ -54,9 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -138,6 +132,27 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include 
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@@ -153,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# Note: NetBSD doesn't particularly care about the vendor
 	# portion of the name.  We always set it to "unknown".
 	sysctl="sysctl -n hw.machine_arch"
-	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
-	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    /sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || \
+	    echo unknown)`
 	case "${UNAME_MACHINE_ARCH}" in
 	    armeb) machine=armeb-unknown ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
 	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine=${arch}${endian}-unknown
+		;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
 	# to ELF recently, or will in the future.
 	case "${UNAME_MACHINE_ARCH}" in
-	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
 		eval $set_cc_for_build
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
 			| grep -q __ELF__
@@ -182,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		os=netbsd
 		;;
 	esac
+	# Determine ABI tags.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+		;;
+	esac
 	# The OS release
 	# Debian GNU/NetBSD machines have a different userland, and
 	# thus, need a distinct triplet. However, they do not need
@@ -198,7 +227,11 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 	# contains redundant information, the shorter form:
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-	echo "${machine}-${os}${release}"
+	echo "${machine}-${os}${release}${abi}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
 	exit ;;
     *:OpenBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
@@ -302,7 +335,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit ;;
-    arm:riscos:*:*|arm:RISCOS:*:*)
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
 	echo arm-unknown-riscos
 	exit ;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -560,8 +593,9 @@ EOF
 	else
 		IBM_ARCH=powerpc
 	fi
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
 	else
 		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
 	fi
@@ -801,10 +835,13 @@ EOF
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
-    i*:MSYS*:*)
+    *:MSYS*:*)
 	echo ${UNAME_MACHINE}-pc-msys
 	exit ;;
     i*:windows32*:*)
@@ -852,21 +889,21 @@ EOF
 	exit ;;
     *:GNU:*:*)
 	# the GNU system
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit ;;
     *:GNU/*:*:*)
 	# other systems with GNU libc and userland
-	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
 	exit ;;
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit ;;
     aarch64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     aarch64_be:Linux:*:*)
 	UNAME_MACHINE=aarch64_be
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     alpha:Linux:*:*)
 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -879,59 +916,57 @@ EOF
 	  EV68*) UNAME_MACHINE=alphaev68 ;;
 	esac
 	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
-	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     arm*:Linux:*:*)
 	eval $set_cc_for_build
 	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
 	    | grep -q __ARM_EABI__
 	then
-	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	else
 	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
 		| grep -q __ARM_PCS_VFP
 	    then
-		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
 	    else
-		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
 	    fi
 	fi
 	exit ;;
     avr32*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     cris:Linux:*:*)
-	echo ${UNAME_MACHINE}-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
     crisv32:Linux:*:*)
-	echo ${UNAME_MACHINE}-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    e2k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     frv:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     hexagon:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     i*86:Linux:*:*)
-	LIBC=gnu
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#ifdef __dietlibc__
-	LIBC=dietlibc
-	#endif
-EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
-	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
 	exit ;;
     ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     mips:Linux:*:* | mips64:Linux:*:*)
 	eval $set_cc_for_build
@@ -950,54 +985,63 @@ EOF
 	#endif
 EOF
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
 	;;
-    or32:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     padre:Linux:*:*)
-	echo sparc-unknown-linux-gnu
+	echo sparc-unknown-linux-${LIBC}
 	exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-gnu
+	echo hppa64-unknown-linux-${LIBC}
 	exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
-	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
-	  *)    echo hppa-unknown-linux-gnu ;;
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
 	esac
 	exit ;;
     ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-gnu
+	echo powerpc64-unknown-linux-${LIBC}
 	exit ;;
     ppc:Linux:*:*)
-	echo powerpc-unknown-linux-gnu
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
 	exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-	echo ${UNAME_MACHINE}-ibm-linux
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
 	exit ;;
     sh64*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sh*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     tile*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     vax:Linux:*:*)
-	echo ${UNAME_MACHINE}-dec-linux-gnu
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
 	exit ;;
     x86_64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     xtensa*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1201,6 +1245,9 @@ EOF
     BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
 	echo i586-pc-haiku
 	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
     SX-4:SUPER-UX:*:*)
 	echo sx4-nec-superux${UNAME_RELEASE}
 	exit ;;
@@ -1227,19 +1274,31 @@ EOF
 	exit ;;
     *:Darwin:*:*)
 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	case $UNAME_PROCESSOR in
-	    i386)
-		eval $set_cc_for_build
-		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-		      grep IS_64BIT_ARCH >/dev/null
-		  then
-		      UNAME_PROCESSOR="x86_64"
-		  fi
-		fi ;;
-	    unknown) UNAME_PROCESSOR=powerpc ;;
-	esac
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1256,7 +1315,7 @@ EOF
     NEO-?:NONSTOP_KERNEL:*:*)
 	echo neo-tandem-nsk${UNAME_RELEASE}
 	exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
+    NSE-*:NONSTOP_KERNEL:*:*)
 	echo nse-tandem-nsk${UNAME_RELEASE}
 	exit ;;
     NSR-?:NONSTOP_KERNEL:*:*)
@@ -1330,157 +1389,6 @@ EOF
 	exit ;;
 esac
 
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <
-# include 
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include 
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-	"4"
-#else
-	""
-#endif
-	); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-#  include 
-#  if defined (BSD)
-#   if BSD == 43
-      printf ("vax-dec-bsd4.3\n"); exit (0);
-#   else
-#    if BSD == 199006
-      printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#    else
-      printf ("vax-dec-bsd\n"); exit (0);
-#    endif
-#   endif
-#  else
-    printf ("vax-dec-bsd\n"); exit (0);
-#  endif
-# else
-    printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
-	{ echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
-	exit ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit ;;
-    c34*)
-	echo c34-convex-bsd
-	exit ;;
-    c38*)
-	echo c38-convex-bsd
-	exit ;;
-    c4*)
-	echo c4-convex-bsd
-	exit ;;
-    esac
-fi
-
 cat >&2 <.
@@ -26,11 +20,12 @@ timestamp='2012-04-18'
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 
 
-# Please send patches to .  Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches to .
 #
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
@@ -73,9 +68,7 @@ Report bugs and patches to ."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -123,8 +116,8 @@ esac
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
-  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
-  knetbsd*-gnu* | netbsd*-gnu* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
   kopensolaris*-gnu* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
@@ -156,7 +149,7 @@ case $os in
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray | -microblaze)
+	-apple | -axis | -knuth | -cray | -microblaze*)
 		os=
 		basic_machine=$1
 		;;
@@ -259,21 +252,24 @@ case $basic_machine in
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
-        | be32 | be64 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| be32 | be64 \
 	| bfin \
-	| c4x | clipper \
+	| c4x | c8051 | clipper \
 	| d10v | d30v | dlx | dsp16xx \
-	| epiphany \
-	| fido | fr30 | frv \
+	| e2k | epiphany \
+	| fido | fr30 | frv | ft32 \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| hexagon \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
+	| k1om \
 	| le32 | le64 \
 	| lm32 \
 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | mcore | mep | metag \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
@@ -287,23 +283,26 @@ case $basic_machine in
 	| mips64vr5900 | mips64vr5900el \
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
 	| mipsisa64 | mipsisa64el \
 	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
 	| moxie \
 	| mt \
 	| msp430 \
 	| nds32 | nds32le | nds32be \
-	| nios | nios2 \
+	| nios | nios2 | nios2eb | nios2el \
 	| ns16k | ns32k \
-	| open8 \
-	| or32 \
+	| open8 | or1k | or1knd | or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
+	| riscv32 | riscv64 \
 	| rl78 | rx \
 	| score \
 	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
@@ -314,6 +313,7 @@ case $basic_machine in
 	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
 	| ubicom32 \
 	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
 	| we32k \
 	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
@@ -328,7 +328,10 @@ case $basic_machine in
 	c6x)
 		basic_machine=tic6x-unknown
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
 		basic_machine=$basic_machine-unknown
 		os=-none
 		;;
@@ -370,26 +373,28 @@ case $basic_machine in
 	| aarch64-* | aarch64_be-* \
 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
 	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
 	| c[123]* | c30-* | [cjt]90-* | c4x-* \
-	| clipper-* | craynv-* | cydra-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
-	| elxsi-* \
+	| e2k-* | elxsi-* \
 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| hexagon-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
+	| k1om-* \
 	| le32-* | le64-* \
 	| lm32-* \
 	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
@@ -403,18 +408,22 @@ case $basic_machine in
 	| mips64vr5900-* | mips64vr5900el-* \
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
 	| mipsisa64-* | mipsisa64el-* \
 	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
 	| mipstx39-* | mipstx39el-* \
 	| mmix-* \
 	| mt-* \
 	| msp430-* \
 	| nds32-* | nds32le-* | nds32be-* \
-	| nios-* | nios2-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
 	| open8-* \
+	| or1k*-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
@@ -432,6 +441,7 @@ case $basic_machine in
 	| ubicom32-* \
 	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
 	| vax-* \
+	| visium-* \
 	| we32k-* \
 	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
@@ -508,6 +518,9 @@ case $basic_machine in
 		basic_machine=i386-pc
 		os=-aros
 		;;
+        asmjs)
+		basic_machine=asmjs-unknown
+		;;
 	aux)
 		basic_machine=m68k-apple
 		os=-aux
@@ -769,6 +782,9 @@ case $basic_machine in
 		basic_machine=m68k-isi
 		os=-sysv
 		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+		;;
 	m68knommu)
 		basic_machine=m68k-unknown
 		os=-linux
@@ -788,11 +804,15 @@ case $basic_machine in
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
-	microblaze)
+	microblaze*)
 		basic_machine=microblaze-xilinx
 		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	mingw32)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-mingw32
 		;;
 	mingw32ce)
@@ -820,6 +840,10 @@ case $basic_machine in
 		basic_machine=powerpc-unknown
 		os=-morphos
 		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
 	msdos)
 		basic_machine=i386-pc
 		os=-msdos
@@ -828,7 +852,7 @@ case $basic_machine in
 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 		;;
 	msys)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-msys
 		;;
 	mvs)
@@ -1019,7 +1043,11 @@ case $basic_machine in
 		basic_machine=i586-unknown
 		os=-pw32
 		;;
-	rdos)
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
 		basic_machine=i386-pc
 		os=-rdos
 		;;
@@ -1346,29 +1374,29 @@ case $os in
 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
-	      | -sym* | -kopensolaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* | -aros* \
+	      | -aos* | -aros* | -cloudabi* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* | -cegcc* \
 	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-android* \
-	      | -linux-newlib* | -linux-uclibc* \
-	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1492,9 +1520,6 @@ case $os in
 	-aros*)
 		os=-aros
 		;;
-	-kaos*)
-		os=-kaos
-		;;
 	-zvmoe)
 		os=-zvmoe
 		;;
@@ -1543,6 +1568,12 @@ case $basic_machine in
 	c4x-* | tic4x-*)
 		os=-coff
 		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
 	tic54x-*)
 		os=-coff
 		;;
diff --git a/configure b/configure
index b6dc19f5e647..47f7cbfb8587 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for file 5.28.
+# Generated by GNU Autoconf 2.69 for file 5.29.
 #
 # Report bugs to .
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='file'
 PACKAGE_TARNAME='file'
-PACKAGE_VERSION='5.28'
-PACKAGE_STRING='file 5.28'
+PACKAGE_VERSION='5.29'
+PACKAGE_STRING='file 5.29'
 PACKAGE_BUGREPORT='christos@astron.com'
 PACKAGE_URL=''
 
@@ -1328,7 +1328,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures file 5.28 to adapt to many kinds of systems.
+\`configure' configures file 5.29 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1398,7 +1398,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of file 5.28:";;
+     short | recursive ) echo "Configuration of file 5.29:";;
    esac
   cat <<\_ACEOF
 
@@ -1509,7 +1509,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-file configure 5.28
+file configure 5.29
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2165,7 +2165,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by file $as_me 5.28, which was
+It was created by file $as_me 5.29, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3031,7 +3031,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='file'
- VERSION='5.28'
+ VERSION='5.29'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -15075,7 +15075,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by file $as_me 5.28, which was
+This file was extended by file $as_me 5.29, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -15141,7 +15141,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-file config.status 5.28
+file config.status 5.29
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 9c38b694ed50..da2fbbf5fbfa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT([file],[5.28],[christos@astron.com])
+AC_INIT([file],[5.29],[christos@astron.com])
 AM_INIT_AUTOMAKE([subdir-objects foreign])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
diff --git a/doc/file.man b/doc/file.man
index abaf2c671ffe..94174c452349 100644
--- a/doc/file.man
+++ b/doc/file.man
@@ -1,5 +1,5 @@
-.\" $File: file.man,v 1.121 2016/06/07 22:09:20 rrt Exp $
-.Dd March 13, 2016
+.\" $File: file.man,v 1.124 2016/10/19 20:52:45 christos Exp $
+.Dd October 19, 2016
 .Dt FILE __CSECTION__
 .Os
 .Sh NAME
@@ -8,7 +8,7 @@
 .Sh SYNOPSIS
 .Nm
 .Bk -words
-.Op Fl bcEhiklLNnprsvzZ0
+.Op Fl bcdEhiklLNnprsvzZ0
 .Op Fl Fl apple
 .Op Fl Fl extension
 .Op Fl Fl mime-encoding
@@ -181,6 +181,8 @@ Cause a checking printout of the parsed form of the magic file.
 This is usually used in conjunction with the
 .Fl m
 flag to debug a new magic file before installing it.
+.It Fl d
+Prints internal debugging information to stderr.
 .It Fl E
 On filesystem errors (file not found etc), instead of handling the error
 as regular output as POSIX mandates and keep going, issue an error message
@@ -208,7 +210,8 @@ Prints details of Compound Document Files.
 .It compress
 Checks for, and looks inside, compressed files.
 .It elf
-Prints ELF file details.
+Prints ELF file details, provided soft magic tests are enabled and the
+elf magic is found.
 .It soft
 Consults magic files.
 .It tar
@@ -312,7 +315,7 @@ attempt to preserve the access time of files analyzed, to pretend that
 never read them.
 .It Fl P , Fl Fl parameter Ar name=value
 Set various parameter limits.
-.Bl -column "elf_phnum" "Default" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" -offset indent
+.Bl -column "elf_phnum" "Default" "XXXXXXXXXXXXXXXXXXXXXXXXXXX" -offset indent
 .It Sy "Name" Ta Sy "Default" Ta Sy "Explanation"
 .It Li indir Ta 15 Ta recursion limit for indirect magic
 .It Li name Ta 30 Ta use count limit for name/use magic
diff --git a/doc/magic.man b/doc/magic.man
index f3b63b461808..bc374040dc2f 100644
--- a/doc/magic.man
+++ b/doc/magic.man
@@ -1,5 +1,5 @@
-.\" $File: magic.man,v 1.86 2015/09/08 13:48:44 christos Exp $
-.Dd January 1, 2015
+.\" $File: magic.man,v 1.88 2016/07/27 09:42:49 rrt Exp $
+.Dd July 20, 2016
 .Dt MAGIC __FSECTION__
 .Os
 .\" install as magic.4 on USG, magic.5 on V7, Berkeley and Linux systems.
@@ -535,13 +535,18 @@ the file.
 The value at that offset is read, and is used again as an offset
 in the file.
 Indirect offsets are of the form:
-.Em (( x [.[bislBISL]][+\-][ y ]) .
+.Em (( x [[.,][bislBISL]][+\-][ y ]) .
 The value of
 .Em x
 is used as an offset in the file.
 A byte, id3 length, short or long is read at that offset depending on the
 .Em [bislBISLm]
 type specifier.
+The value is treated as signed if
+.Dq ,
+is specified or unsigned if
+.Dq .
+is specified.
 The capitalized types interpret the number as a big endian
 value, whereas the small letter versions interpret the number as a little
 endian value;
@@ -564,9 +569,9 @@ That way variable length structures can be examined:
 \*[Gt]\*[Gt](0x3c.l)  string  LX\e0\e0  LX executable (OS/2)
 .Ed
 .Pp
-This strategy of examining has a drawback: You must make sure that
-you eventually print something, or users may get empty output (like, when
-there is neither PE\e0\e0 nor LE\e0\e0 in the above example)
+This strategy of examining has a drawback: you must make sure that you
+eventually print something, or users may get empty output (such as when
+there is neither PE\e0\e0 nor LE\e0\e0 in the above example).
 .Pp
 If this indirect offset cannot be used directly, simple calculations are
 possible: appending
diff --git a/ltmain.sh b/ltmain.sh
index f07ffc8b3c18..fcc4d744b45e 100755
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -9432,7 +9432,8 @@ dlpreopen='$dlprefiles'
 
 # Directory that this library needs to be installed in:
 libdir='$install_libdir'"
-	  if test "$installed" = no && test "$need_relink" = yes; then
+	  if test "$installed" = no && test "$need_relink" = yes && \
+	     test -n "$relink_command"; then
 	    $ECHO >> $output "\
 relink_command=\"$relink_command\""
 	  fi
diff --git a/magic/Magdir/algol68 b/magic/Magdir/algol68
new file mode 100644
index 000000000000..a9aad46e1fc3
--- /dev/null
+++ b/magic/Magdir/algol68
@@ -0,0 +1,19 @@
+
+#------------------------------------------------------------------------------
+# $File: algol68,v 1.2 2016/10/17 14:17:48 christos Exp $
+# algol68:  file(1) magic for Algol 68 source
+#
+0	search/8192	(input,			Algol 68 source text
+!:mime	text/x-Algol68
+0	regex		\^PROC			Algol 68 source text
+!:mime	text/x-Algol68
+0	regex           MODE[\t\ ]		Algol 68 source text
+!:mime	text/x-Algol68
+0	regex          	REF[\t\ ]		Algol 68 source text
+!:mime	text/x-Algol68
+0	regex          	FLEX[\t\ ]\*\\[		Algol 68 source text
+!:mime	text/x-Algol68
+#0	regex          	[\t\ ]OD		Algol 68 source text
+#!:mime	text/x-Algol68
+#0	regex          	[\t\ ]FI		Algol 68 source text
+#!:mime	text/x-Algol68
diff --git a/magic/Magdir/animation b/magic/Magdir/animation
index 51eeea2db783..faa839e8783b 100644
--- a/magic/Magdir/animation
+++ b/magic/Magdir/animation
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: animation,v 1.57 2015/11/29 22:11:07 christos Exp $
+# $File: animation,v 1.58 2016/07/03 14:13:11 christos Exp $
 # animation:  file(1) magic for animation/movie formats
 #
 # animation formats
@@ -1008,3 +1008,11 @@
 >4	lelong	x	%d x
 >8	lelong	x	%d,
 >12	lelong	x	%d frames
+
+# Material Exchange Format
+# More information:
+# https://en.wikipedia.org/wiki/Material_Exchange_Format
+# http://www.freemxf.org/
+0	string	\x06\x0e\x2b\x34\x02\x05\x01\x01\x0d\x01\x02\x01\x01\x02	Material exchange container format
+!:ext	mxf
+!:mime	application/mxf
diff --git a/magic/Magdir/apple b/magic/Magdir/apple
index 5db4feeee52b..ce03298f95f2 100644
--- a/magic/Magdir/apple
+++ b/magic/Magdir/apple
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: apple,v 1.32 2015/12/04 20:40:10 christos Exp $
+# $File: apple,v 1.35 2016/08/17 09:45:13 christos Exp $
 # apple:  file(1) magic for Apple file formats
 #
 0	search/1/t	FiLeStArTfIlEsTaRt	binscii (apple ][) text
@@ -285,49 +285,118 @@
 # .vdi
 4	string innotek\ VirtualBox\ Disk\ Image %s
 
-# Apple disk partition stuff, strengthen the magic using byte 4
+# Apple disk partition stuff
+# URL: https://en.wikipedia.org/wiki/Apple_Partition_Map
+# Reference: https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/bootblock.h
+# Update: Joerg Jenderek 
+# "ER" is APPLE_DRVR_MAP_MAGIC signature
 0	beshort	0x4552
->4	byte	0			Apple Driver Map
+# display Apple Driver Map (strength=50) after Syslinux bootloader (71)
+#!:strength +0
+# strengthen the magic by looking for used blocksizes 512 2048
+>2	ubeshort&0xf1FF		0	Apple Driver Map
+# last 6 bytes for padding found are 0 or end with 55AAh marker for MBR hybrid
+#>>504	ubequad&0x0000FFffFFff0000	0
+!:mime	application/x-apple-diskimage
+!:apple	????devr
+# https://en.wikipedia.org/wiki/Apple_Disk_Image
+!:ext	dmg/iso
+# sbBlkSize for driver descriptor map 512 2048
 >>2	beshort	x			\b, blocksize %d
->>4	belong	x			\b, blockcount %d
->>10	beshort	x			\b, devtype %d
->>12	beshort	x			\b, devid %d
->>20	beshort x			\b, descriptors %d
-# Assume 	8 partitions each at a multiple of the sector size.
-# We could glean this from the partition descriptors, but they are empty!?!?
->>(2.S*1)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*2)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*3)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*4)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*5)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*6)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*7)	indirect	x	\b, contains[@0x%x]: 
->>(2.S*8)	indirect	x	\b, contains[@0x%x]: 
+# sbBlkCount sometimes garbish like
+# 0xb0200000 for unzlibed install_flash_player_19.0.0.245_osx.dmg
+# 0xf2720100 for bunziped Firefox 48.0-2.dmg
+# 0xeb02ffff for super_grub2_disk_hybrid_2.02s3.iso
+# 0x00009090 by syslinux-6.03/utils/isohybrid.c
+>>4	ubelong	x			\b, blockcount %u
+# following device/driver information not very useful
+# device type 0 1 (37008 garbage for super_grub2_disk_hybrid_2.02s3.iso)
+>>8	ubeshort	x		\b, devtype %u
+# device id 0 1 (37008 garbage for super_grub2_disk_hybrid_2.02s3.iso)
+>>10	ubeshort	x		\b, devid %u
+# driver data 0 (2425393296 garbage for super_grub2_disk_hybrid_2.02s3.iso)
+>>12	ubelong		>0		
+>>>12	ubelong		x		\b, driver data %u
+# number of driver descriptors sbDrvrCount <= 61
+# (37008 garbage for super_grub2_disk_hybrid_2.02s3.iso)
+>>16	ubeshort	x		\b, driver count %u
+# 61 * apple_drvr_descriptor[8]. information not very useful or same as in partition map
+# >>18	use		apple-driver-map
+# >>26	use		apple-driver-map
+# # ...
+# >>500	use		apple-driver-map
+# number of partitions is always same in every partition (map block count)
+#>>0x0204	ubelong		x	\b, %u partitions
+>>0x0204	ubelong		>0	\b, contains[@0x200]: 
+>>>0x0200	use		apple-apm
+>>0x0204	ubelong		>1	\b, contains[@0x400]: 
+>>>0x0400	use		apple-apm
+>>0x0204	ubelong		>2	\b, contains[@0x600]: 
+>>>0x0600	use		apple-apm
+>>0x0204	ubelong		>3	\b, contains[@0x800]: 
+>>>0x0800	use		apple-apm
+>>0x0204	ubelong		>4	\b, contains[@0xA00]: 
+>>>0x0A00	use		apple-apm
+>>0x0204	ubelong		>5	\b, contains[@0xC00]: 
+>>>0x0C00	use		apple-apm
+>>0x0204	ubelong		>6	\b, contains[@0xE00]: 
+>>>0x0E00	use		apple-apm
+>>0x0204	ubelong		>7	\b, contains[@0x1000]: 
+>>>0x1000	use		apple-apm
+#	display apple driver descriptor map (start-block, # blocks in sbBlkSize sizes, type)
+0	name				apple-driver-map
+>0	ubequad		!0		
+# descBlock first block of driver 
+>>0	ubelong	x			\b, driver start block %u
+# descSize driver size in blocks
+>>4	ubeshort	x		\b, size %u
+# descType driver system type 1 701h F8FFh FFFFh
+>>6	ubeshort	x		\b, type 0x%x
 
-# Yes, the 3rd and 4th bytes are reserved, but we use them to make the
+# URL: https://en.wikipedia.org/wiki/Apple_Partition_Map
+# Reference: http://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h
+# Update: Joerg Jenderek 
+# Yes, the 3rd and 4th bytes pmSigPad are reserved, but we use them to make the
 # magic stronger.
-0	belong	0x504d0000		Apple Partition Map
->4	belong	x			\b, map block count %d
->8	belong	x			\b, start block %d
->12	belong	x			\b, block count %d
->16	string >0			\b, name %s
->48	string >0			\b, type %s
->124	string >0			\b, processor %s
->140	string >0			\b, boot arguments %s
->92	belong	& 1			\b, valid
->92	belong	& 2			\b, allocated
->92	belong	& 4			\b, in use
->92	belong	& 8			\b, has boot info
->92	belong	& 16			\b, readable
->92	belong	& 32			\b, writable
->92	belong	& 64			\b, pic boot code
->92	belong	& 128			\b, chain compatible driver
->92	belong	& 256			\b, real driver
->92	belong	& 512			\b, chain driver
->92	belong	& 1024			\b, mount at startup
->92	belong	& 2048			\b, is the startup partition
+# for apple partition map stored as a single file
+0	belong	0x504d0000		
+# to display Apple Partition Map (strength=70) after Syslinux bootloader (71)
+#!:strength +0
+>0	use		apple-apm
+# magic/Magdir/apple14.test, 365: Warning: Current entry does not yet have a description for adding a EXTENSION type
+# file: could not find any valid magic files!
+#!:ext	bin
+#	display apple partition map. Normally called after Apple driver map
+0	name				apple-apm
+>0	belong	0x504d0000		Apple Partition Map
+# number of partitions
+>>4	ubelong	x			\b, map block count %u
+# logical block (512 bytes) start of partition
+>>8	ubelong	x			\b, start block %u
+>>12	ubelong	x			\b, block count %u
+>>16	string >0			\b, name %s
+>>48	string >0			\b, type %s
+# processor type dpme_process_id[16] e.g. "68000" "68020"
+>>120	string >0			\b, processor %s
+# A/UX boot arguments BootArgs[128]
+>>136	string >0			\b, boot arguments %s
+# status of partition dpme_flags
+>>88	belong	& 1			\b, valid
+>>88	belong	& 2			\b, allocated
+>>88	belong	& 4			\b, in use
+>>88	belong	& 8			\b, has boot info
+>>88	belong	& 16			\b, readable
+>>88	belong	& 32			\b, writable
+>>88	belong	& 64			\b, pic boot code
+>>88	belong	& 128			\b, chain compatible driver
+>>88	belong	& 256			\b, real driver
+>>88	belong	& 512			\b, chain driver
+# mount automatically at startup APPLE_PS_AUTO_MOUNT
+>>88	ubelong	&0x40000000		\b, mount at startup
+# is the startup partition APPLE_PS_STARTUP
+>>88	ubelong	&0x80000000		\b, is the startup partition
 
-#http://wiki.mozilla.org/DS_Store_File_Format`
+#http://wiki.mozilla.org/DS_Store_File_Format
 #http://en.wikipedia.org/wiki/.DS_Store
 0	string	\0\0\0\1Bud1\0		Apple Desktop Services Store
 
@@ -337,5 +406,28 @@
 # extensions rsr/rsrc
 0	string  \000\000\001\000
 >4	leshort 0
->>16    lelong  0			Apple HFS/HFS+ resource fork
+>>16	lelong  0			Apple HFS/HFS+ resource fork
 
+#https://en.wikipedia.org/wiki/AppleScript
+0	string	FasdUAS			AppleScript compiled
+
+# AppleWorks/ClarisWorks
+# https://github.com/joshenders/appleworks_format
+# http://fileformats.archiveteam.org/wiki/AppleWorks
+0	name			appleworks
+>0	belong&0x00ffffff	0x07e100	AppleWorks CWK Document
+>0	belong&0x00ffffff	0x008803	ClarisWorks CWK Document
+>0	default			x	
+>>0	belong			x		AppleWorks/ClarisWorks CWK Document
+>0	byte			x		\b, version %d
+>30	beshort			x		\b, %d
+>32	beshort			x		\bx%d
+!:ext cwk
+
+4	string	BOBO
+>0	byte	>4
+>>12	belong	0
+>>>26	belong	0
+>>>>0	use	appleworks
+>0	belong	0x0481ad00
+>>0	use 	appleworks
diff --git a/magic/Magdir/application b/magic/Magdir/application
new file mode 100644
index 000000000000..f316608081c2
--- /dev/null
+++ b/magic/Magdir/application
@@ -0,0 +1,7 @@
+
+#------------------------------------------------------------------------------
+# $File: application,v 1.1 2016/10/17 12:13:01 christos Exp $
+# application:  file(1) magic for applications on small devices
+#
+# Pebble Application
+0	string	PBLAPP\000\000	Pebble application
diff --git a/magic/Magdir/apt b/magic/Magdir/apt
new file mode 100644
index 000000000000..2d9f15901b2e
--- /dev/null
+++ b/magic/Magdir/apt
@@ -0,0 +1,52 @@
+
+#------------------------------------------------------------------------------
+# $File: apt,v 1.1 2016/10/17 19:51:57 christos Exp $
+# apt: file(1) magic for APT Cache files
+# 
+# 
+
+# before version 10 ("old format"), data was in arch-specific long/short
+
+# old format 64 bit
+0   	name		apt-cache-64bit-be
+>12	beshort		1		\b, dirty
+>40 	bequad		x		\b, %llu packages
+>48 	bequad		x		\b, %llu versions
+
+# old format 32 bit
+0   	name    	apt-cache-32bit-be
+>8  	beshort 	1		\b, dirty
+>40 	belong  	x		\b, %u packages
+>44 	belong  	x		\b, %u versions
+
+# new format
+0	name		apt-cache-be
+>6	byte    	1		\b, dirty
+>24	belong  	x		\b, %u packages
+>28	belong		x		\b, %u versions
+
+0	bequad		0x98FE76DC
+>8	ubeshort	<10		APT cache data, version %u
+>>10	beshort	    	x	  	\b.%u, 64 bit big-endian
+>>0	use		apt-cache-64bit-be
+
+0	lequad	    	0x98FE76DC
+>8	uleshort    	<10		APT cache data, version %u
+>>10	leshort		x		\b.%u, 64 bit little-endian
+>>0	use		\^apt-cache-64bit-be
+
+0	belong	    	0x98FE76DC
+>4	ubeshort    	<10	 	APT cache data, version %u
+>>6	ubeshort    	x		\b.%u, 32 bit big-endian
+>>0	use  		apt-cache-32bit-be
+>4	ubyte	    	>9		APT cache data, version %u
+>>5	ubyte	    	x		\b.%u, big-endian
+>>0	use 		apt-cache-be
+
+0	lelong	    	0x98FE76DC
+>4	uleshort    	<10		APT cache data, version %u
+>>6	uleshort   	x		\b.%u, 32 bit little-endian
+>>0	use 		\^apt-cache-32bit-be
+>4	ubyte	    	>9		APT cache data, version %u
+>>5	ubyte	    	x		\b.%u, little-endian
+>>0	use		\^apt-cache-be
diff --git a/magic/Magdir/bioinformatics b/magic/Magdir/bioinformatics
index 7de08a1e0088..0c761ed351fe 100644
--- a/magic/Magdir/bioinformatics
+++ b/magic/Magdir/bioinformatics
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: bioinformatics,v 1.2 2016/02/14 15:53:53 christos Exp $
+# $File: bioinformatics,v 1.4 2016/06/20 16:13:46 christos Exp $
 # bioinfomatics:  file(1) magic for Bioinfomatics file formats
 
 ###############################################################################
@@ -16,32 +16,32 @@
 
 
 ###############################################################################
-# Tabix index file 
+# Tabix index file
 # used by SAMtools bgzip/tabix (http://samtools.sourceforge.net/tabix.shtml)
 ###############################################################################
 0	string	TBI\1		SAMtools TBI (Tabix index format)
 >0x04	lelong	=1		\b, with %d reference sequence
 >0x04	lelong	>1		\b, with %d reference sequences
 >0x08	lelong	&0x10000	\b, using half-closed-half-open coordinates (BED style)
->0x08	lelong	^0x10000	
+>0x08	lelong	^0x10000
 >>0x08	lelong	=0		\b, using closed and one based coordinates (GFF style)
 >>0x08	lelong	=1		\b, using SAM format
 >>0x08	lelong	=2		\b, using VCF format
 >0x0c	lelong	x		\b, sequence name column: %d
 >0x10	lelong	x		\b, region start column: %d
->0x08	lelong	=0		
+>0x08	lelong	=0
 >>0x14	lelong	x		\b, region end column: %d
 >0x18	byte	x		\b, comment character: %c
 >0x1c	lelong	x		\b, skip line count: %d
 
 
 ###############################################################################
-# BAM (Binary Sequence Alignment/Map format) 
-# used by SAMtools (http://samtools.sourceforge.net/SAM1.pdf) 
+# BAM (Binary Sequence Alignment/Map format)
+# used by SAMtools (http://samtools.sourceforge.net/SAM1.pdf)
 # data is normally present only within compressed BGZF blocks (CDATA), so use file -z to examine it
 ###############################################################################
 0	string	BAM\1	SAMtools BAM (Binary Sequence Alignment/Map)
->0x04	lelong	>0	
+>0x04	lelong	>0
 >>&0x00 regex	=^[@]HD\t.*VN:		\b, with SAM header
 >>>&0	regex	=[0-9.]+		\b version %s
 >>&(0x04)	lelong	>0	\b, with %d reference sequences
@@ -49,14 +49,14 @@
 
 ###############################################################################
 # BAI (BAM indexing format)
-# used by SAMtools (http://samtools.sourceforge.net/SAM1.pdf) 
+# used by SAMtools (http://samtools.sourceforge.net/SAM1.pdf)
 ###############################################################################
 0		string	BAI\1	SAMtools BAI (BAM indexing format)
 >0x04		lelong	>0	\b, with %d reference sequences
 
 
 ###############################################################################
-# CRAM (Binary Sequence Alignment/Map format) 
+# CRAM (Binary Sequence Alignment/Map format)
 ###############################################################################
 0	string	CRAM	CRAM
 >0x04	byte	>-1	version %d.
@@ -69,13 +69,13 @@
 # used by SAMtools & VCFtools (http://vcftools.sourceforge.net/bcf.pdf)
 # data is normally present only within compressed BGZF blocks (CDATA), so use file -z to examine it
 ###############################################################################
-0		string	   BCF\4    
+0		string	   BCF\4
 # length of seqnm data in bytes is positive
->&0x00		lelong	  >0	
+>&0x00		lelong	  >0
 # length of smpl data in bytes is positive
 >>&(&-0x04)	lelong	  >0			SAMtools BCF (Binary Call Format)
 # length of meta in bytes
->>>&(&-0x04)	lelong	  >0	
+>>>&(&-0x04)	lelong	  >0
 # have meta text string
 >>>>&0x00	search	  ##samtoolsVersion=
 >>>>>&0x00	string	  x			\b, generated by SAMtools version %s
@@ -88,7 +88,7 @@
 ###############################################################################
 0		string	   BCF\2\1    Binary Call Format (BCF) version 2.1
 # length of header text
->&0x00		lelong	  >0	
+>&0x00		lelong	  >0
 # have header string
 >>&0x00 search	  ##samtoolsVersion=
 >>>&0x00	string	  x			\b, generated by SAMtools version %s
@@ -101,7 +101,7 @@
 ###############################################################################
 0		string	   BCF\2\2    Binary Call Format (BCF) version 2.2
 # length of header text
->&0x00		lelong	  >0	
+>&0x00		lelong	  >0
 # have header string
 >>&0x00 search	  ##samtoolsVersion=
 >>>&0x00	string	  x			\b, generated by SAMtools version %s
@@ -119,11 +119,11 @@
 ###############################################################################
 # XXX Broken?
 # @
-#0	regex	=^@[A-Za-z0-9_.:-]+\?\n	
+#0	regex	=^@[A-Za-z0-9_.:-]+\?\n
 # 
 #>&1	regex	=^[A-Za-z\n.~]++
 # +[]
-#>>&1	regex	=^[A-Za-z0-9_.:-]*\?\n	
+#>>&1	regex	=^[A-Za-z0-9_.:-]*\?\n
 # 
 #>>>&1	regex	=^[!-~\n]+\n		FASTQ
 
@@ -132,7 +132,7 @@
 # used by FASTA (http://fasta.bioch.virginia.edu/fasta_www2/fasta_guide.pdf)
 ###############################################################################
 #0	byte	0x3e
-# q>0	regex	=^[>][!-~\t\ ]+$	
+# q>0	regex	=^[>][!-~\t\ ]+$
 # Amino Acid codes: [A-IK-Z*-]+
 #>>1	regex	!=[!-'Jj;:=?@^`|~\\]		FASTA
 # IUPAC codes/gaps: [ACGTURYKMSWBDHVNX-]+
@@ -141,37 +141,37 @@
 #>>>1	regex	=^[EFIJLOPQZefijlopqz]+$	\b, with Amino Acid codes
 
 ###############################################################################
-# SAM (Sequence Alignment/Map format) 
-# used by SAMtools (http://samtools.sourceforge.net/SAM1.pdf) 
+# SAM (Sequence Alignment/Map format)
+# used by SAMtools (http://samtools.sourceforge.net/SAM1.pdf)
 ###############################################################################
 # Short-cut version to recognise SAM files with (optional) header at beginning
 ###############################################################################
-0      string	   @HD\t	
+0      string	   @HD\t
 >4     search	   VN:		Sequence Alignment/Map (SAM), with header
 >>&0   regex	   [0-9.]+	\b version %s
 ###############################################################################
 # Longer version to recognise SAM alignment lines using (many) regexes
 ###############################################################################
 # SAM Alignment QNAME
-0		regex	=^[!-?A-~]{1,255}(\t[^\t]+){11}		
+0		regex	=^[!-?A-~]{1,255}(\t[^\t]+){11}
 # SAM Alignment FLAG
->0		regex	=^([^\t]+\t){1}[0-9]{1,5}\t		
+>0		regex	=^([^\t]+\t){1}[0-9]{1,5}\t
 # SAM Alignment RNAME
->>0		regex	=^([^\t]+\t){2}\\*|[^*=]*\t		
+>>0		regex	=^([^\t]+\t){2}\\*|[^*=]*\t
 # SAM Alignment POS
->>>0		regex	=^([^\t]+\t){3}[0-9]{1,9}\t		
+>>>0		regex	=^([^\t]+\t){3}[0-9]{1,9}\t
 # SAM Alignment MAPQ
->>>>0		regex	=^([^\t]+\t){4}[0-9]{1,3}\t		
+>>>>0		regex	=^([^\t]+\t){4}[0-9]{1,3}\t
 # SAM Alignment CIGAR
->>>>>0		regex	=\t\\*|([0-9]+[MIDNSHPX=])+)\t		
+>>>>>0		regex	=\t(\\*|([0-9]+[MIDNSHPX=])+)\t
 # SAM Alignment RNEXT
->>>>>>0		regex	=\t(\\*|=|[!-()+->?-~][!-~]*)\t		
+>>>>>>0		regex	=\t(\\*|=|[!-()+->?-~][!-~]*)\t
 # SAM Alignment PNEXT
->>>>>>>0	regex	=^([^\t]+\t){7}[0-9]{1,9}\t		
+>>>>>>>0	regex	=^([^\t]+\t){7}[0-9]{1,9}\t
 # SAM Alignment TLEN
->>>>>>>>0	regex	=\t[+-]{0,1}[0-9]{1,9}\t.*\t		
+>>>>>>>>0	regex	=\t[+-]{0,1}[0-9]{1,9}\t.*\t
 # SAM Alignment SEQ
->>>>>>>>>0	regex	=^([^\t]+\t){9}(\\*|[A-Za-z=.]+)\t	
+>>>>>>>>>0	regex	=^([^\t]+\t){9}(\\*|[A-Za-z=.]+)\t
 # SAM Alignment QUAL
 >>>>>>>>>>0	regex	=^([^\t]+\t){10}[!-~]+	Sequence Alignment/Map (SAM)
 >>>>>>>>>>>0	regex	=^[@]HD\t.*VN:		\b, with header
diff --git a/magic/Magdir/c-lang b/magic/Magdir/c-lang
index b930bccb966b..bb594b069fc7 100644
--- a/magic/Magdir/c-lang
+++ b/magic/Magdir/c-lang
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: c-lang,v 1.23 2016/05/21 14:28:27 christos Exp $
+# $File: c-lang,v 1.24 2016/07/01 23:31:13 christos Exp $
 # c-lang:  file(1) magic for C and related languages programs
 #
 # The strength is to beat standard HTML
@@ -48,6 +48,11 @@
 !:strength + 30
 !:mime	text/x-c++
 
+# Objective-C
+0	regex	\^#import	Objective-C source text
+!:strength +25
+!:mime	text/x-objective-c
+
 # From: Mikhail Teterin  
 0	string		cscope		cscope reference data
 >7	string		x		version %.2s
diff --git a/magic/Magdir/claris b/magic/Magdir/claris
index 0f7b591b77f3..6a1b68fb2275 100644
--- a/magic/Magdir/claris
+++ b/magic/Magdir/claris
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: claris,v 1.7 2014/06/03 19:17:27 christos Exp $
+# $File: claris,v 1.8 2016/07/18 19:23:38 christos Exp $
 # claris:  file(1) magic for claris
 # "H. Nanosecond" 
 # Claris Works a word processor, etc.
@@ -18,7 +18,8 @@
 
 # Claris works files
 # .cwk
-0	string	\002\000\210\003\102\117\102\117\000\001\206 Claris works document
+# Moved to Apple AppleWorks document
+#0	string	\002\000\210\003\102\117\102\117\000\001\206 Claris works document
 # .plt
 0	string	\020\341\000\000\010\010	Claris Works palette files .plt
 
diff --git a/magic/Magdir/commands b/magic/Magdir/commands
index 8dad8fee52f3..48d706358c0e 100644
--- a/magic/Magdir/commands
+++ b/magic/Magdir/commands
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: commands,v 1.54 2016/04/19 13:40:02 christos Exp $
+# $File: commands,v 1.56 2016/07/14 19:01:12 christos Exp $
 # commands:  file(1) magic for various shells and interpreters
 #
 #0	string/w	:			shell archive or script for antique kernel text
@@ -112,3 +112,7 @@
 # URL:  http://packages.debian.org/pdmenu
 # From: Edward Betts 
 0	string		#!/usr/bin/pdmenu	Pdmenu configuration file text
+
+# From Danny Weldon
+0	string	\x0b\x13\x08\x00
+>0x04   uleshort	<4      ksh byte-code version %d
diff --git a/magic/Magdir/compress b/magic/Magdir/compress
index 910545a788c4..3297d5dc6b9b 100644
--- a/magic/Magdir/compress
+++ b/magic/Magdir/compress
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: compress,v 1.65 2015/12/04 20:48:03 christos Exp $
+# $File: compress,v 1.66 2016/09/16 12:12:05 christos Exp $
 # compress:  file(1) magic for pure-compression formats (no archives)
 #
 # compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, etc.
@@ -220,6 +220,56 @@
 0	lelong		0x184c2102	LZ4 compressed data (v0.1-v0.9)
 !:mime	application/x-lz4
 
+# Zstandard/LZ4 skippable frames
+# https://github.com/facebook/zstd/blob/dev/zstd_compression_format.md
+0         lelong&0xFFFFFFF0  0x184D2A50
+>(4.l+8)  indirect
+
+# Zstandard Dictionary ID subroutine
+0     name        zstd-dictionary-id
+# Single Segment = True
+>0    byte        &0x20   \b, Dictionary ID:
+>>0   byte&0x03   0       None
+>>0   byte&0x03   1
+>>>1  byte        x       %u
+>>0   byte&0x03   2
+>>>1  leshort     x       %u
+>>0   byte&0x03   3
+>>>1  lelong      x       %u
+# Single Segment = False
+>0    byte        ^0x20   \b, Dictionary ID:
+>>0   byte&0x03   0       None
+>>0   byte&0x03   1
+>>>2  byte        x       %u
+>>0   byte&0x03   2
+>>>2  leshort     x       %u
+>>0   byte&0x03   3
+>>>2  lelong      x       %u
+
+# Zstandard compressed data
+# https://github.com/facebook/zstd/blob/dev/zstd_compression_format.md
+0     lelong       0xFD2FB522  Zstandard compressed data (v0.2)
+!:mime  application/x-zstd
+0     lelong       0xFD2FB523  Zstandard compressed data (v0.3)
+!:mime  application/x-zstd
+0     lelong       0xFD2FB524  Zstandard compressed data (v0.4)
+!:mime  application/x-zstd
+0     lelong       0xFD2FB525  Zstandard compressed data (v0.5)
+!:mime  application/x-zstd
+0     lelong       0xFD2FB526  Zstandard compressed data (v0.6)
+!:mime  application/x-zstd
+0     lelong       0xFD2FB527  Zstandard compressed data (v0.7)
+!:mime  application/x-zstd
+>4    use          zstd-dictionary-id
+0     lelong       0xFD2FB528  Zstandard compressed data (v0.8+)
+!:mime  application/x-zstd
+>4    use          zstd-dictionary-id
+
+# https://github.com/facebook/zstd/blob/dev/zstd_compression_format.md
+0  lelong    0xEC30A437  Zstandard dictionary
+!:mime  application/x-zstd-dictionary
+>4 lelong    x           (ID %u)
+
 # AFX compressed files (Wolfram Kleff)
 2	string		-afx-		AFX compressed file data
 
diff --git a/magic/Magdir/cups b/magic/Magdir/cups
index 005a134586e8..4d0056bb4b57 100644
--- a/magic/Magdir/cups
+++ b/magic/Magdir/cups
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: cups,v 1.3 2014/05/28 19:50:41 christos Exp $
+# $File: cups,v 1.4 2016/10/17 18:51:02 christos Exp $
 # Cups: file(1) magic for the cups raster file format
 # From: Laurent Martelli 
 # http://www.cups.org/documentation.php/spec-raster.html
@@ -44,7 +44,7 @@
 >3	string		2		Cups Raster version 2, Big Endian
 >3	string		3		Cups Raster version 3, Big Endian
 !:mime	application/vnd.cups-raster
->0	use		^cups-le
+>0	use		\^cups-le
 
 
 # Cups Raster image format, Little Endian
diff --git a/magic/Magdir/editors b/magic/Magdir/editors
index 4c5b8a669957..fa6cbc64c095 100644
--- a/magic/Magdir/editors
+++ b/magic/Magdir/editors
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: editors,v 1.8 2009/09/19 16:28:09 christos Exp $
+# $File: editors,v 1.10 2016/07/18 17:44:49 christos Exp $
 # T602 editor documents 
 # by David Necas 
 0	string	@CT\ 	T602 document data,
@@ -12,7 +12,28 @@
 # Vi IMproved Encrypted file 
 # by David Necas 
 0	string	VimCrypt~	Vim encrypted file data
+
+0	name	vimnanoswap
+>67	byte	0
+>>107	byte	0
+#>>>2	string	x	%s swap file
+>>>24	ulelong	x	\b, pid %d
+>>>28	string	>\0	\b, user %s
+>>>68	string	>\0	\b, host %s
+>>>108	string	>\0	\b, file %s
+>>>1007	byte	0x55	\b, modified
+
 # Vi IMproved Swap file
 # by Sven Wegener 
-0	string	b0VIM\ 		Vim swap file
->&0	string	>\0		\b, version %s
+0	string  b0VIM\ 		Vim swap file
+>&0	string  >\0		\b, version %s
+>0	use	vimnanoswap
+
+
+# Lock/swap file for several editors, at least
+# Vi IMproved and nano
+0	string	b0nano		Nano swap file
+>0	use	vimnanoswap
+
+# kate (K Advanced Text Editor)
+0	string	\x00\x00\x00\x12Kate\ Swap\ File\ 2.0\x00	Kate swap file
diff --git a/magic/Magdir/filesystems b/magic/Magdir/filesystems
index e9508739834d..b7c6e5b32fa7 100644
--- a/magic/Magdir/filesystems
+++ b/magic/Magdir/filesystems
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: filesystems,v 1.113 2016/02/14 14:38:24 christos Exp $
+# $File: filesystems,v 1.114 2016/09/05 08:34:25 christos Exp $
 # filesystems:  file(1) magic for different filesystems
 #
 0	name	partid  
@@ -539,8 +539,6 @@
 >>>514		string		!HdrS			
 # not BeOS
 >>>>422		string		!Be\ Boot\ Loader	
->>>>>32769	string    CD001
->>>>>>0	use cdrom
 # jump over BPB instruction implies DOS bootsector or AdvanceMAME mbr 
 >>>>>0		ubelong&0xFD000000	=0xE9000000	
 # AdvanceMAME mbr
@@ -1929,6 +1927,7 @@
 >>38917	string    3         (version 2.0)
 >>38917	byte     >0x33      (unknown version, ID 0x%X)
 >>38917	byte     <0x31      (unknown version, ID 0x%X)
+# The next line is not necessary because the MBR staff is done looking for boot signature
 >0x1FE	leshort  0xAA55     (DOS/MBR boot sector)
 # "application id" which appears to be used as a volume label
 >32808	string/T  >\0       '%s'
diff --git a/magic/Magdir/fonts b/magic/Magdir/fonts
index 41899fb0257b..be489cba01e0 100644
--- a/magic/Magdir/fonts
+++ b/magic/Magdir/fonts
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: fonts,v 1.30 2016/03/22 22:27:47 christos Exp $
+# $File: fonts,v 1.33 2016/09/14 01:26:26 christos Exp $
 # fonts:  file(1) magic for font data
 #
 0	search/1	FONT		ASCII vfont text
@@ -15,6 +15,56 @@
 6	string		%!FontType1	PostScript Type 1 font program data
 0	string		%!PS-Adobe-3.0\ Resource-Font	PostScript Type 1 font text
 
+# Summary:	PostScript Type 1 Printer Font Metrics
+# URL:		https://en.wikipedia.org/wiki/PostScript_fonts
+# Reference:	http://partners.adobe.com/public/developer/en/font/5178.PFM.pdf
+# Modified by:	Joerg Jenderek
+# Note:		moved from ./msdos magic 
+# dfVersion 256=0100h 
+0		uleshort	0x0100		
+# GRR: line above is too general as it catches also TrueType font,
+# raw G3 data FAX, WhatsApp encrypted and Panorama database
+# dfType 129=0081h
+>66		uleshort	0x0081		
+# dfVertRes 300=012Ch not needed as additional test
+#>>70		uleshort	0x012c		
+# dfHorizRes 300=012Ch
+#>>>72		uleshort	0x012c		
+# dfDriverInfo points to postscript information section
+>>(101.l)	string/c	Postscript	Printer Font Metrics
+# above labeled "PFM data" by ./msdos (version 5.28) or "Adobe Printer Font Metrics" by TrID
+!:mime	application/x-font-pfm
+# AppleShare Print Server
+#!:apple	ASPS????
+!:ext	pfm
+# dfCopyright 60 byte null padded Copyright string. uncomment it to get old looking
+#>>>6		string		>\060		- %-.60s
+# dfDriverInfo
+>>>139		ulelong		>0		
+# often abbreviated and same as filename
+>>>>(139.l)	string		x		%s
+# dfSize
+>>>2		ulelong		x		\b, %d bytes
+# dfFace 210=D2h 9Eh
+>>>105		ulelong		>0		
+# Windows font name
+>>>>(105.l)	string		x		\b, %s
+# dfItalic
+>>>80		ubyte		1		italic
+# dfUnderline
+>>>81		ubyte		1		underline
+# dfStrikeOut
+>>>82		ubyte		1		strikeout
+# dfWeight 400=0x0190 300=0x012c 500=0x01f4 600=0x0258 700=0x02bc
+>>>83		uleshort	>699		bold
+# dfPitchAndFamily 16 17 48 49 64 65
+>>>90		ubyte		16		serif
+>>>90		ubyte		17		serif proportional
+#>>>90		ubyte		48		other
+>>>90		ubyte		49		proportional
+>>>90		ubyte		64		script
+>>>90		ubyte		65		script proportional
+
 # X11 font files in SNF (Server Natural Format) format
 # updated by Joerg Jenderek at Feb 2013
 # http://computer-programming-forum.com/51-perl/8f22fb96d2e34bab.htm
@@ -110,7 +160,12 @@
 >14	string		x		version %s
 
 # EOT
-34	string		LP		Embedded OpenType (EOT)
+0x40	string		\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
+>0x22	string		LP		Embedded OpenType (EOT)
+# workaround until there's lepstring16
+# >>0x52	lepstring16/h	>\0		\b, %s family
+>>0x52	short	!0
+>>>0x54	lestring16	x		\b, %s family
 !:mime application/vnd.ms-fontobject
 
 # Web Open Font Format (.woff)
diff --git a/magic/Magdir/gcc b/magic/Magdir/gcc
index 893d0d91e692..ae98dc7dbc1f 100644
--- a/magic/Magdir/gcc
+++ b/magic/Magdir/gcc
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: gcc,v 1.4 2009/09/19 16:28:09 christos Exp $
+# $File: gcc,v 1.5 2016/07/01 23:31:13 christos Exp $
 # gcc:  file(1) magic for GCC special files
 #
 0	string		gpch		GCC precompiled header
@@ -12,6 +12,6 @@
 
 # 67 = 'C', 111 = 'o', 43 = '+', 79 = 'O'
 >4	byte		67			for C
->4	byte		111			for Objective C
+>4	byte		111			for Objective-C
 >4	byte		43			for C++
->4	byte		79			for Objective C++
+>4	byte		79			for Objective-C++
diff --git a/magic/Magdir/gnu b/magic/Magdir/gnu
index c94cefc5c3ff..24609c16459c 100644
--- a/magic/Magdir/gnu
+++ b/magic/Magdir/gnu
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: gnu,v 1.16 2015/04/19 22:59:25 christos Exp $
+# $File: gnu,v 1.17 2016/07/16 22:17:04 christos Exp $
 # gnu:  file(1) magic for various GNU tools
 #
 # GNU nlsutils message catalog file format
@@ -34,8 +34,11 @@
 
 # This magic is not particularly good, as the keyrings don't have true
 # magic. Nevertheless, it covers many keyrings.
-0       beshort         0x9901                  GPG key public ring
-!:mime	application/x-gnupg-keyring
+0	ubeshort-0x9901	<2
+>3	byte		4
+>>4	bedate		x		GPG key public ring, created %s
+!:mime application/x-gnupg-keyring
+
 
 # Symmetric encryption
 0	leshort		0x0d8c
diff --git a/magic/Magdir/images b/magic/Magdir/images
index d084da781256..3e9cd81f3198 100644
--- a/magic/Magdir/images
+++ b/magic/Magdir/images
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: images,v 1.116 2016/03/23 15:29:20 christos Exp $
+# $File: images,v 1.117 2016/07/05 19:12:21 christos Exp $
 # images:  file(1) magic for image formats (see also "iff", and "c-lang" for
 # XPM bitmaps)
 #
@@ -171,38 +171,44 @@
 >>>&0	regex		=[0-9]{1,50}			\b %s
 
 0	search/1	P1		
->0	use		netpbm
->>0	string		x	\b, bitmap
+>0	regex/4		P1\\s
+>>0	use		netpbm
+>>>0	string		x	\b, bitmap
 !:strength + 45
 !:mime	image/x-portable-bitmap
 
 0	search/1	P2		
->0	use		netpbm
->>0	string		x	\b, greymap
+>0	regex/4		P2\\s
+>>0	use		netpbm
+>>>0	string		x	\b, greymap
 !:strength + 45
 !:mime	image/x-portable-greymap
 
 0	search/1	P3
->0	use		netpbm
->>0	string		x	\b, pixmap
+>0	regex/4		P3\\s
+>>0	use		netpbm
+>>>0	string		x	\b, pixmap
 !:strength + 45
 !:mime	image/x-portable-pixmap
 
 0	string		P4		
->0	use		netpbm
->>0	string		x	\b, rawbits, bitmap
+>0	regex/4		P4\\s
+>>0	use		netpbm
+>>>0	string		x	\b, rawbits, bitmap
 !:strength + 45
 !:mime	image/x-portable-bitmap
 
 0	string		P5		
->0	use		netpbm
->>0	string		x	\b, rawbits, greymap
+>0	regex/4		P5\\s
+>>0	use		netpbm
+>>>0	string		x	\b, rawbits, greymap
 !:strength + 45
 !:mime	image/x-portable-greymap
 
 0	string		P6		
->0	use		netpbm
->>0	string		x	\b, rawbits, pixmap
+>0	regex/4		P6\\s
+>>0	use		netpbm
+>>>0	string		x	\b, rawbits, pixmap
 !:strength + 45
 !:mime	image/x-portable-pixmap
 
diff --git a/magic/Magdir/jpeg b/magic/Magdir/jpeg
index b20b19fc2f24..2b49c21c6053 100644
--- a/magic/Magdir/jpeg
+++ b/magic/Magdir/jpeg
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: jpeg,v 1.29 2015/04/10 15:36:02 christos Exp $
+# $File: jpeg,v 1.30 2016/07/04 15:18:23 christos Exp $
 # JPEG images
 # SunOS 5.5.1 had
 #
@@ -117,3 +117,10 @@
 # From: Mathieu Malaterre 
 0	belong		0xff4fff51						JPEG 2000 codestream
 45	beshort		0xff52
+
+# JPEG extended range
+0	string		\x49\x49\xbc
+>3	byte		1
+>>4	lelong%2	0	JPEG-XR
+!:mime	image/jxr
+!:ext	jxr
diff --git a/magic/Magdir/msdos b/magic/Magdir/msdos
index f4b35ca896e9..55ea3e83c3a7 100644
--- a/magic/Magdir/msdos
+++ b/magic/Magdir/msdos
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: msdos,v 1.106 2016/06/11 00:52:14 christos Exp $
+# $File: msdos,v 1.111 2016/09/14 01:26:26 christos Exp $
 # msdos:  file(1) magic for MS-DOS files
 #
 
@@ -328,15 +328,6 @@
 0	string	\xffKEYB\ \ \ \0\0\0\0	
 >12	string	\0\0\0\0`\004\360	MS-DOS KEYBoard Layout file
 
-# .COM formats (Daniel Quinlan, quinlan@yggdrasil.com)
-# Uncommenting only the first two lines will cover about 2/3 of COM files,
-# but it isn't feasible to match all COM files since there must be at least
-# two dozen different one-byte "magics".
-# test too generic ?
-0	byte		0xe9		DOS executable (COM)
->0x1FE leshort		0xAA55		\b, boot code
->6	string		SFX\ of\ LHarc	(%s)
-
 # DOS device driver updated by Joerg Jenderek at May 2011
 # http://maben.homeip.net/static/S100/IBM/software/DOS/DOS%20techref/CHAPTER.009
 0	ulequad&0x07a0ffffffff		0xffffffff		DOS executable (
@@ -439,12 +430,37 @@
 # byte 0xeb conflicts with "sequent" magic leshort 0xn2eb
 0	ubeshort&0xeb8d	>0xeb00		
 # DR-DOS STACKER.COM SCREATE.SYS missed
->0	byte		0xeb
->>0x1FE leshort		0xAA55		DOS executable (COM), boot code
->>85	string		UPX		DOS executable (COM), UPX compressed
->>4	string		\ $ARX		DOS executable (COM), ARX self-extracting archive
->>4	string		\ $LHarc	DOS executable (COM), LHarc self-extracting archive
->>0x20e string		SFX\ by\ LARC	DOS executable (COM), LARC self-extracting archive
+
+0       name    msdos-com
+>0  byte        x               DOS executable (COM)
+>6	string		SFX\ of\ LHarc	\b, %s
+>0x1FE leshort	0xAA55		    \b, boot code
+>85	string		UPX		        \b, UPX compressed
+>4	string		\ $ARX		    \b, ARX self-extracting archive
+>4	string		\ $LHarc	    \b, LHarc self-extracting archive
+>0x20e string	SFX\ by\ LARC	\b, LARC self-extracting archive
+
+# JMP 8bit
+0	        byte	0xeb
+# allow forward jumps only
+>1          byte    >-1
+# that offset must be accessible
+>>(1.b+2)   byte    x
+>>>0        use msdos-com
+
+# JMP 16bit
+0           byte    0xe9
+# forward jumps
+>1          short   >-1
+# that offset must be accessible
+>>(1.s+3)   byte    x
+>>>0        use msdos-com
+# negative offset, must not lead into PSP
+>1          short   <-259
+# that offset must be accessible
+>>(1,s+65539)   byte    x
+>>>0        use msdos-com
+
 # updated by Joerg Jenderek at Oct 2008,2015
 # following line is too general
 0	ubyte		0xb8		
@@ -578,17 +594,158 @@
 0	string/b	\x09\x04\x06\x00\x00\x00\x10\x00	Microsoft Excel Worksheet
 !:mime	application/vnd.ms-excel
 #
-0	belong	0x00001a00	Lotus 1-2-3
-!:mime	application/x-123
->4	belong	0x00100400	wk3 document data
->4	belong	0x02100400	wk4 document data
->4	belong	0x07800100	fm3 or fmb document data
->4	belong	0x07800000	fm3 or fmb document data
+# Update: Joerg Jenderek
+# URL: https://en.wikipedia.org/wiki/Lotus_1-2-3
+# Reference: http://www.aboutvb.de/bas/formate/pdf/wk3.pdf
+# Note: newer Lotus versions >2 use longer BOF record
+# record type (BeginningOfFile=0000h) + length (001Ah)
+0	belong	0x00001a00	
+# reserved should be 0h but 8c0dh for TUTMAC.WK3, 5h for SAMPADNS.WK3, 1h for a_readme.wk3, 1eh for K&G86.WK3
+#>18	uleshort&0x73E0	0	
+# Lotus Multi Byte Character Set (LMBCS=1-31)
+>20	ubyte		>0	
+>>20	ubyte		<32	Lotus 1-2-3
+#!:mime	application/x-123
+!:mime	application/vnd.lotus-1-2-3
+!:apple	????L123
+# (version 5.26) labeled the entry as "Lotus 1-2-3 wk3 document data"
+>>>4	uleshort	0x1000	WorKsheet, version 3
+!:ext	wk3
+# (version 5.26) labeled the entry as "Lotus 1-2-3 wk4 document data"
+>>>4	uleshort	0x1002	WorKsheet, version 4
+# also worksheet template 4 (.wt4)
+!:ext	wk4/wt4
+# no example or documentation for wk5
+#>>4	uleshort	0x????	WorKsheet, version 4
+#!:ext	wk5
+# only MacrotoScript.123 example
+>>>4	uleshort	0x1003	WorKsheet, version 97
+# also worksheet template Smartmaster (.12M)?
+!:ext	123
+# only Set_Y2K.123 example
+>>>4	uleshort	0x1005	WorKsheet, version 9.8 Millennium
+!:ext	123
+# no example for this version
+>>>4	uleshort	0x8001	FoRMatting data
+!:ext	frm
+# (version 5.26) labeled the entry as "Lotus 1-2-3 fm3 or fmb document data"
+# TrID labeles the entry as "Formatting Data for Lotus 1-2-3 worksheet"
+>>>4	uleshort	0x8007	ForMatting data, version 3
+!:ext	fm3
+>>>4	default		x	unknown
+# file revision sub code 0004h for worksheets
+>>>>6	uleshort	=0x0004	worksheet
+!:ext	wXX
+>>>>6	uleshort	!0x0004	formatting data
+!:ext	fXX
+# main revision number
+>>>>4	uleshort	x	\b, revision 0x%x
+>>>6	uleshort	=0x0004	\b, cell range 
+# active cellcoord range (start row, page,column ; end row, page, column)
+# start values normally 0~1st sheet A1
+>>>>8	ulelong		!0	
+>>>>>10	ubyte		>0	\b%d*
+>>>>>8	uleshort	x	\b%d,
+>>>>>11	ubyte		x	\b%d-
+# end page mostly 0
+>>>>14	ubyte		>0	\b%d*
+# end raw, column normally not 0
+>>>>12	uleshort	x	\b%d,
+>>>>15	ubyte		x	\b%d
+# Lotus Multi Byte Character Set (1~cp850,2~cp851,...,16~japan,...,31~??)
+>>>>20	ubyte		>1	\b, character set 0x%x
+# flags
+>>>>21	ubyte		x	\b, flags 0x%x
+>>>6	uleshort	!0x0004	
+# record type (FONTNAME=00AEh)
+>>>>30	search/29	\0\xAE	
+# variable length m (2) + entries (1) + ?? (1) + LCMBS string (n)
+>>>>>&4	string		>\0	\b, 1st font "%s"
 #
-0	belong	0x00000200	Lotus 1-2-3
-!:mime	application/x-123
->4	belong	0x06040600	wk1 document data
->4	belong	0x06800200	fmt document data
+# Update: Joerg Jenderek
+# URL: http://fileformats.archiveteam.org/wiki/Lotus_1-2-3
+# Reference: http://www.schnarff.com/file-formats/lotus-1-2-3/WSFF2.TXT
+# Note: Used by both old Lotus 1-2-3 and Lotus Symphony (DOS) til version 2.x
+# record type (BeginningOfFile=0000h) + length (0002h)
+0	belong	0x00000200	
+# GRR: line above is too general as it catches also MS Windows CURsor
+# to display MS Windows cursor (strength=70) before Lotus 1-2-3 (strength=70-1)
+!:strength -1
+# skip Windows cursors with image height <256 and keep Lotus with low opcode 0001-0083h
+>7	ubyte		0	
+# skip Windows cursors with image width 256 and keep Lotus with positiv opcode
+>>6	ubyte		>0	Lotus
+# !:mime	application/x-123
+!:mime	application/vnd.lotus-1-2-3
+!:apple	????L123
+# revision number (0404h = 123 1A, 0405h = Lotus Symphony , 0406h = 123 2.x wk1 , 8006h = fmt , ...)
+# undocumented; (version 5.26) labeled the configurations as "Lotus 1-2-3"
+>>>4	uleshort	0x0007	1-2-3 CoNFiguration, version 2.x (PGRAPH.CNF)
+!:ext	cnf
+>>>4	uleshort	0x0C05	1-2-3 CoNFiguration, version 2.4J
+!:ext	cnf
+>>>4	uleshort	0x0801	1-2-3 CoNFiguration, version 1-2.1
+!:ext	cnf
+>>>4	uleshort	0x0802	Symphony CoNFiguration
+!:ext	cnf
+>>>4	uleshort	0x0804	1-2-3 CoNFiguration, version 2.2
+!:ext	cnf
+>>>4	uleshort	0x080A	1-2-3 CoNFiguration, version 2.3-2.4
+!:ext	cnf
+>>>4	uleshort	0x1402	1-2-3 CoNFiguration, version 3.x
+!:ext	cnf
+>>>4	uleshort	0x1450	1-2-3 CoNFiguration, version 4.x
+!:ext	cnf
+# (version 5.26) labeled the entry as "Lotus 123"
+# TrID labeles the entry as "Lotus 123 Worksheet (generic)"
+>>>4	uleshort	0x0404	1-2-3 WorKSheet, version 1
+# extension "wks" also for Microsoft Works document
+!:ext	wks
+# (version 5.26) labeled the entry as "Lotus 123"
+# TrID labeles the entry as "Lotus 123 Worksheet (generic)"
+>>>4	uleshort	0x0405	Symphony WoRksheet, version 1.0
+!:ext	wrk/wr1
+# (version 5.26) labeled the entry as "Lotus 1-2-3 wk1 document data"
+# TrID labeles the entry as "Lotus 123 Worksheet (V2)"
+>>>4	uleshort	0x0406	1-2-3/Symphony worksheet, version 2
+# Symphony (.wr1)
+!:ext	wk1/wr1
+# no example for this japan version
+>>>4	uleshort	0x0600	1-2-3 WorKsheet, version 1.xJ
+!:ext	wj1
+# no example or documentation for wk2
+#>>>4	uleshort	0x????	1-2-3 WorKsheet, version 2
+#!:ext	wk2
+# undocumented japan version
+>>>4	uleshort	0x0602	1-2-3 worksheet, version 2.4J
+!:ext	wj3
+# (version 5.26) labeled the entry as "Lotus 1-2-3 fmt document data"
+>>>4	uleshort	0x8006	1-2-3 ForMaTting data, version 2.x
+# japan version 2.4J (fj3)
+!:ext	fmt/fj3
+# no example for this version
+>>>4	uleshort	0x8007	1-2-3 FoRMatting data, version 2.0
+!:ext	frm
+# (version 5.26) labeled the entry as "Lotus 1-2-3"
+>>>4	default		x	unknown worksheet or configuration
+!:ext	cnf
+>>>>4	uleshort	x	\b, revision 0x%x
+# 2nd record for most worksheets describes cells range
+>>>6		use	lotus-cells
+# 3nd record for most japan worksheets describes cells range
+>>>(8.s+10)	use	lotus-cells
+#	check and then display Lotus worksheet cells range
+0	name		lotus-cells
+# look for type (RANGE=0006h) + length (0008h) at record begin
+>0	ubelong	0x06000800	\b, cell range 
+# cell range (start column, row, end column, row) start values normally 0,0~A1 cell
+>>4	ulong		!0	
+>>>4	uleshort	x	\b%d,
+>>>6	uleshort	x	\b%d-
+# end of cell range
+>>8	uleshort	x	\b%d,
+>>10	uleshort	x	\b%d
+# EndOfLotus123
 0	string/b		WordPro\0	Lotus WordPro
 !:mime	application/vnd.lotus-wordpro
 0	string/b		WordPro\r\373	Lotus WordPro
@@ -738,24 +895,6 @@
 0	lelong		0x00000005
 >12	lelong		0x00000320	Windows Recycle Bin INFO2 file (Win2k - WinXP)
 
-
-##### put in Either Magic/font or Magic/news
-# Acroread or something	 files wrongly identified as G3	 .pfm
-# these have the form \000 \001 any? \002 \000 \000
-# or \000 \001 any? \022 \000 \000
-0	belong&0xffff00ff	0x00010012	PFM data
->4	string			\000\000
->6	string			>\060		- %s
-
-0	belong&0xffff00ff	0x00010002	PFM data
->4	string			\000\000
->6	string			>\060		- %s
-#0	string	\000\001 pfm?
-#>3	string	\022\000\000Copyright\	yes
-#>3	string	\002\000\000Copyright\	yes
-#>3	string	>\0	oops, not a font file. Cancel that.
-#it clashes with ttf files so put it lower down.
-
 # From Doug Lee via a FreeBSD pr
 9	string		GERBILDOC	First Choice document
 9	string		GERBILDB	First Choice database
@@ -940,7 +1079,8 @@
 # Type: Microsoft Document Imaging Format (.mdi)
 # URL:	http://en.wikipedia.org/wiki/Microsoft_Document_Imaging_Format
 # From: Daniele Sempione 
-0	short	0x5045			Microsoft Document Imaging Format
+# Too weak (EP)
+#0	short	0x5045			Microsoft Document Imaging Format
 
 # MS eBook format (.lit)
 0	string/b	ITOLITLS		Microsoft Reader eBook Data
diff --git a/magic/Magdir/pgp b/magic/Magdir/pgp
index 95a676600dd2..6e685fcfc979 100644
--- a/magic/Magdir/pgp
+++ b/magic/Magdir/pgp
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: pgp,v 1.11 2014/11/11 21:32:38 christos Exp $
+# $File: pgp,v 1.12 2016/10/07 20:22:12 christos Exp $
 # pgp:  file(1) magic for Pretty Good Privacy
 # see http://lists.gnupg.org/pipermail/gnupg-devel/1999-September/016052.html
 #
@@ -194,6 +194,23 @@
 >0	byte	0x0a			SHA512
 >0	byte	0x0b			SHA224
 
+# display public key algorithms as human readable text
+0	name	key_algo
+>0	byte	0x01			RSA (Encrypt or Sign)
+# keep old look of version 5.28 without parentheses
+>0	byte	0x02			RSA Encrypt-Only
+>0	byte	0x03			RSA (Sign-Only)
+>0	byte	16			ElGamal (Encrypt-Only)
+>0	byte	17			DSA
+>0	byte	18			Elliptic Curve
+>0	byte	19			ECDSA
+>0	byte	20			ElGamal (Encrypt or Sign)
+>0	byte	21			Diffie-Hellman
+>0	default	x			
+>>0	ubyte	<22			unknown (pub %d)
+# this should never happen
+>>0	ubyte	>21			invalid (%d)
+
 # pgp symmetric encrypted data
 
 0	byte	0x8c			PGP symmetric key encrypted data -
@@ -465,5 +482,41 @@
 >1	use	pgpkey
 0	byte	0x97			PGP	Secret Sub-key -
 >1	use	pgpkey
-0	byte	0x9d			PGP	Secret Sub-key -
->1	use	pgpkey
+0	byte	0x9d			
+# Update: Joerg Jenderek
+# secret subkey packet (tag 7) with same structure as secret key packet (tag 5)
+# skip Fetus.Sys16 CALIBUS.MAIN OrbFix.Sys16.Ex by looking for positive len
+>1	ubeshort	>0		
+#>1	ubeshort	x		\b, body length 0x%x
+# next packet type often 88h,89h~(tag 2)~Signature Packet
+#>>(1.S+3)	ubyte	x		\b, next packet type 0x%x
+# skip Dragon.SHR DEMO.INIT by looking for positive version
+>>3	ubyte		>0	
+# skip BUISSON.13 GUITAR1 by looking for low version number
+>>>3	ubyte		<5		PGP Secret Sub-key
+# sub-key are normally part of secret key. So it does not occur as standalone file
+#!:ext	bin
+# version 2,3~old 4~new . Comment following line for version 5.28 look
+>>>>3	ubyte		x		(v%d)
+>>>>3	ubyte		x		-
+# old versions 2 or 3 but no real example found
+>>>>3	ubyte		<4		
+# 2 byte for key bits in version 5.28 look
+>>>>>11		ubeshort	x	%db
+>>>>>4		beldate		x	created on %s -
+# old versions use 2 additional bytes after time stamp
+#>>>>>8		ubeshort	x	0x%x
+# display key algorithm 1~RSA Encrypt|Sign - 21~Diffie-Hellman
+>>>>>10	  	use		key_algo
+>>>>>(11.S/8)	ubequad		x	
+# look after first key
+>>>>>>&5	use		keyend
+# new version
+>>>>3	ubyte		>3		
+>>>>>9		ubeshort	x	%db
+>>>>>4		beldate		x	created on %s -
+# display key algorithm
+>>>>>8		use		key_algo
+>>>>>(9.S/8)	ubequad		x	
+# look after first key for something like s2k
+>>>>>>&3	use		keyend
diff --git a/magic/Magdir/psl b/magic/Magdir/psl
new file mode 100644
index 000000000000..1f88df106e5a
--- /dev/null
+++ b/magic/Magdir/psl
@@ -0,0 +1,14 @@
+
+#------------------------------------------------------------------------------
+# $File: psl,v 1.2 2016/07/14 17:34:27 christos Exp $
+# psl:  file(1) magic for Public Suffix List representations
+# From: Daniel Kahn Gillmor 
+# URL: https://publicsuffix.org
+# see also: http://thread.gmane.org/gmane.network.dns.libpsl.bugs/162/focus=166
+
+0	search/512	\n\n//\ ===BEGIN\ ICANN\ DOMAINS===\n\n Public Suffix List data
+
+0	string	.DAFSA@PSL_
+>15	string	\n	Public Suffix List data (optimized)
+>>11	byte	>0x2f
+>>>11	byte	<0x3a   (Version %c)
diff --git a/magic/Magdir/python b/magic/Magdir/python
index 06da176937e6..29dcc15a8519 100644
--- a/magic/Magdir/python
+++ b/magic/Magdir/python
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: python,v 1.28 2015/09/16 22:19:54 christos Exp $
+# $File: python,v 1.29 2016/07/27 09:42:16 rrt Exp $
 # python:  file(1) magic for python
 #
 # Outlook puts """ too for urgent messages
@@ -9,7 +9,7 @@
 0	string/t	"""	Python script text executable
 # MAGIC as specified in Python/import.c (1.5 to 2.7a0 and 3.1a0, assuming
 # that Py_UnicodeFlag is off for Python 2)
-# 20121  ( YEAR - 1995 ) + MONTH  + DAY (little endian followed by "\r\n"
+# two bytes of magic followed by "\r\n" in little endian order
 0	belong		0x994e0d0a	python 1.5/1.6 byte-compiled
 0	belong		0x87c60d0a	python 2.0 byte-compiled
 0	belong		0x2aeb0d0a	python 2.1 byte-compiled
@@ -24,6 +24,7 @@
 0	belong		0x6c0c0d0a	python 3.2 byte-compiled
 0	belong		0x9e0c0d0a	python 3.3 byte-compiled
 0	belong		0xee0c0d0a	python 3.4 byte-compiled
+0	belong		0x160d0d0a	python 3.5 byte-compiled
 
 0	search/1/w	#!\ /usr/bin/python	Python script text executable
 !:strength + 15
diff --git a/magic/Magdir/ruby b/magic/Magdir/ruby
index 26630f3a8202..cc3abd0408ae 100644
--- a/magic/Magdir/ruby
+++ b/magic/Magdir/ruby
@@ -1,18 +1,22 @@
 
 #------------------------------------------------------------------------------
-# $File: ruby,v 1.5 2010/07/21 16:47:17 christos Exp $
+# $File: ruby,v 1.6 2016/07/27 09:46:29 rrt Exp $
 # ruby:  file(1) magic for Ruby scripting language
 # URL:  http://www.ruby-lang.org/
 # From: Reuben Thomas 
 
 # Ruby scripts
 0	search/1/w	#!\ /usr/bin/ruby	Ruby script text executable
+!:strength + 15
 !:mime text/x-ruby
 0	search/1/w	#!\ /usr/local/bin/ruby	Ruby script text executable
+!:strength + 15
 !:mime text/x-ruby
 0	search/1	#!/usr/bin/env\ ruby	Ruby script text executable
+!:strength + 15
 !:mime text/x-ruby
 0	search/1	#!\ /usr/bin/env\ ruby	Ruby script text executable
+!:strength + 15
 !:mime text/x-ruby
 
 # What looks like ruby, but does not have a shebang
diff --git a/magic/Magdir/sgml b/magic/Magdir/sgml
index 28cbf87f21b7..e3dcc26c89b7 100644
--- a/magic/Magdir/sgml
+++ b/magic/Magdir/sgml
@@ -1,4 +1,4 @@
-#------------------------------------------------------------------------------ # $File: sgml,v 1.33 2015/11/29 22:14:49 christos Exp $
+#------------------------------------------------------------------------------ # $File: sgml,v 1.34 2016/09/11 13:56:42 christos Exp $
 # Type:	SVG Vectorial Graphics
 # From:	Noel Torres 
 0	string		\>19	search/4096	\
@@ -10,25 +10,67 @@
 #
 0	beshort			0xfe01		MySQL table definition file
 >2	byte			x		Version %d
-0	belong&0xffffff00	0xfefe0700	MySQL MyISAM index file
->3	byte			x		Version %d
-0	belong&0xffffff00	0xfefe0800	MySQL MyISAM compressed data file
->3	byte			x		Version %d
-0	belong&0xffffff00	0xfefe0900	MySQL Maria index file
->3	byte			x		Version %d
-0	belong&0xffffff00	0xfefe0A00	MySQL Maria compressed data file
->3	byte			x		Version %d
+>3	byte			0		\b, type UNKNOWN
+>3	byte			1		\b, type DIAM_ISAM
+>3	byte			2		\b, type HASH
+>3	byte			3		\b, type MISAM
+>3	byte			4		\b, type PISAM
+>3	byte			5		\b, type RMS_ISAM
+>3	byte			6		\b, type HEAP
+>3	byte			7		\b, type ISAM
+>3	byte			8		\b, type MRG_ISAM
+>3	byte			9		\b, type MYISAM
+>3	byte			10		\b, type MRG_MYISAM
+>3	byte			11		\b, type BERKELEY_DB
+>3	byte			12		\b, type INNODB
+>3	byte			13		\b, type GEMINI
+>3	byte			14		\b, type NDBCLUSTER
+>3	byte			15		\b, type EXAMPLE_DB
+>3	byte			16		\b, type CSV_DB
+>3	byte			17		\b, type FEDERATED_DB
+>3	byte			18		\b, type BLACKHOLE_DB
+>3	byte			19		\b, type PARTITION_DB
+>3	byte			20		\b, type BINLOG
+>3	byte			21		\b, type SOLID
+>3	byte			22		\b, type PBXT
+>3	byte			23		\b, type TABLE_FUNCTION
+>3	byte			24		\b, type MEMCACHE
+>3	byte			25		\b, type FALCON
+>3	byte			26		\b, type MARIA
+>3	byte			27		\b, type PERFORMANCE_SCHEMA
+>3	byte			127		\b, type DEFAULT
+>0x0033	ulong			x		\b, MySQL version %d
 0	belong&0xffffff00	0xfefe0500	MySQL ISAM index file
 >3	byte			x		Version %d
 0	belong&0xffffff00	0xfefe0600	MySQL ISAM compressed data file
 >3	byte			x		Version %d
-0	string			\376bin		MySQL replication log
-0	belong&0xffffff00	0xfefe0b00
->4	string			MARIALOG	MySQL Maria transaction log file
->>3	byte			x		Version %d
+0	belong&0xffffff00	0xfefe0700	MySQL MyISAM index file
+>3	byte			x		Version %d
+>14	beshort			x		\b, %d key parts
+>16	beshort			x		\b, %d unique key parts
+>18	byte			x		\b, %d keys
+>28	bequad			x		\b, %lld records
+>36	bequad			x		\b, %lld deleted records
+0	belong&0xffffff00	0xfefe0800	MySQL MyISAM compressed data file
+>3	byte			x		Version %d
+0	belong&0xffffff00	0xfefe0900	MySQL Maria index file
+>3	byte			x		Version %d
+0	belong&0xffffff00	0xfefe0a00	MySQL Maria compressed data file
+>3	byte			x		Version %d
 0	belong&0xffffff00	0xfefe0c00
 >4	string			MACF		MySQL Maria control file
 >>3	byte			x		Version %d
+0	string			\376bin	MySQL replication log,
+>9	long			x		server id %d
+>8	byte			1
+>>13	long			69		\b, MySQL V3.2.3
+>>>19	string			x		\b, server version %s
+>>13	long			75		\b, MySQL V4.0.2-V4.1
+>>>25	string			x		\b, server version %s
+>8	byte			15		MySQL V5+,
+>>25	string			x		server version %s
+>4	string			MARIALOG	MySQL Maria transaction log file
+>>3	byte			x		Version %d
 
 #------------------------------------------------------------------------------
 # iRiver H Series database file 
@@ -94,3 +136,6 @@
 >126	string		SQLite\ format\ 3	
 #!:mime	application/x-panasonic-sqlite3
 >>&-15	indirect	x			\b; contains 
+
+# H2 Database from http://www.h2database.com/
+0	string		--\ H2\ 0.5/B\ --\ \n	H2 Database file
diff --git a/magic/Makefile.am b/magic/Makefile.am
index ab8b075fd5ed..19701ecd179b 100644
--- a/magic/Makefile.am
+++ b/magic/Makefile.am
@@ -1,5 +1,5 @@
 #
-# $File: Makefile.am,v 1.116 2016/06/13 19:09:31 christos Exp $
+# $File: Makefile.am,v 1.120 2016/10/17 19:52:29 christos Exp $
 #
 MAGIC_FRAGMENT_BASE = Magdir
 MAGIC_DIR = $(top_srcdir)/magic
@@ -13,6 +13,7 @@ $(MAGIC_DIR)/Localstuff \
 $(MAGIC_FRAGMENT_DIR)/acorn \
 $(MAGIC_FRAGMENT_DIR)/adi \
 $(MAGIC_FRAGMENT_DIR)/adventure \
+$(MAGIC_FRAGMENT_DIR)/algol68 \
 $(MAGIC_FRAGMENT_DIR)/allegro \
 $(MAGIC_FRAGMENT_DIR)/alliant \
 $(MAGIC_FRAGMENT_DIR)/amanda \
@@ -22,7 +23,9 @@ $(MAGIC_FRAGMENT_DIR)/animation \
 $(MAGIC_FRAGMENT_DIR)/aout \
 $(MAGIC_FRAGMENT_DIR)/apl \
 $(MAGIC_FRAGMENT_DIR)/apple \
+$(MAGIC_FRAGMENT_DIR)/application \
 $(MAGIC_FRAGMENT_DIR)/applix \
+$(MAGIC_FRAGMENT_DIR)/apt \
 $(MAGIC_FRAGMENT_DIR)/archive \
 $(MAGIC_FRAGMENT_DIR)/assembler \
 $(MAGIC_FRAGMENT_DIR)/asterix \
@@ -207,6 +210,7 @@ $(MAGIC_FRAGMENT_DIR)/polyml \
 $(MAGIC_FRAGMENT_DIR)/printer \
 $(MAGIC_FRAGMENT_DIR)/project \
 $(MAGIC_FRAGMENT_DIR)/psdbms \
+$(MAGIC_FRAGMENT_DIR)/psl \
 $(MAGIC_FRAGMENT_DIR)/pulsar \
 $(MAGIC_FRAGMENT_DIR)/pwsafe \
 $(MAGIC_FRAGMENT_DIR)/pyramid \
diff --git a/magic/Makefile.in b/magic/Makefile.in
index 531091a4c235..0de849d603bd 100644
--- a/magic/Makefile.in
+++ b/magic/Makefile.in
@@ -273,7 +273,7 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 
 #
-# $File: Makefile.am,v 1.116 2016/06/13 19:09:31 christos Exp $
+# $File: Makefile.am,v 1.120 2016/10/17 19:52:29 christos Exp $
 #
 MAGIC_FRAGMENT_BASE = Magdir
 MAGIC_DIR = $(top_srcdir)/magic
@@ -285,6 +285,7 @@ $(MAGIC_DIR)/Localstuff \
 $(MAGIC_FRAGMENT_DIR)/acorn \
 $(MAGIC_FRAGMENT_DIR)/adi \
 $(MAGIC_FRAGMENT_DIR)/adventure \
+$(MAGIC_FRAGMENT_DIR)/algol68 \
 $(MAGIC_FRAGMENT_DIR)/allegro \
 $(MAGIC_FRAGMENT_DIR)/alliant \
 $(MAGIC_FRAGMENT_DIR)/amanda \
@@ -294,7 +295,9 @@ $(MAGIC_FRAGMENT_DIR)/animation \
 $(MAGIC_FRAGMENT_DIR)/aout \
 $(MAGIC_FRAGMENT_DIR)/apl \
 $(MAGIC_FRAGMENT_DIR)/apple \
+$(MAGIC_FRAGMENT_DIR)/application \
 $(MAGIC_FRAGMENT_DIR)/applix \
+$(MAGIC_FRAGMENT_DIR)/apt \
 $(MAGIC_FRAGMENT_DIR)/archive \
 $(MAGIC_FRAGMENT_DIR)/assembler \
 $(MAGIC_FRAGMENT_DIR)/asterix \
@@ -479,6 +482,7 @@ $(MAGIC_FRAGMENT_DIR)/polyml \
 $(MAGIC_FRAGMENT_DIR)/printer \
 $(MAGIC_FRAGMENT_DIR)/project \
 $(MAGIC_FRAGMENT_DIR)/psdbms \
+$(MAGIC_FRAGMENT_DIR)/psl \
 $(MAGIC_FRAGMENT_DIR)/pulsar \
 $(MAGIC_FRAGMENT_DIR)/pwsafe \
 $(MAGIC_FRAGMENT_DIR)/pyramid \
diff --git a/python/magic.py b/python/magic.py
index c48f7d5a3012..b0f7a1765e8f 100644
--- a/python/magic.py
+++ b/python/magic.py
@@ -134,7 +134,7 @@ def file(self, filename):
         if isinstance(r, str):
             return r
         else:
-            return str(r).encode('utf-8')
+            return str(r, 'utf-8')
 
     def descriptor(self, fd):
         """
@@ -152,7 +152,7 @@ def buffer(self, buf):
         if isinstance(r, str):
             return r
         else:
-            return str(r).encode('utf-8')
+            return str(r, 'utf-8')
 
     def error(self):
         """
@@ -163,7 +163,7 @@ def error(self):
         if isinstance(e, str):
             return e
         else:
-            return str(e).encode('utf-8')
+            return str(e, 'utf-8')
 
     def setflags(self, flags):
         """
diff --git a/src/apprentice.c b/src/apprentice.c
index e395854d0478..f2622c081284 100644
--- a/src/apprentice.c
+++ b/src/apprentice.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.249 2016/05/17 21:43:07 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.255 2016/10/24 18:02:17 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -408,11 +408,11 @@ add_mlist(struct mlist *mlp, struct magic_map *map, size_t idx)
 {
 	struct mlist *ml;
 
-	mlp->map = idx == 0 ? map : NULL;
+	mlp->map = NULL;
 	if ((ml = CAST(struct mlist *, malloc(sizeof(*ml)))) == NULL)
 		return -1;
 
-	ml->map = NULL;
+	ml->map = idx == 0 ? map : NULL;
 	ml->magic = map->magic[idx];
 	ml->nmagic = map->nmagic[idx];
 
@@ -451,6 +451,8 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
 
 #ifndef COMPILE_ONLY
 	map = apprentice_map(ms, fn);
+	if (map == (struct magic_map *)-1)
+		return -1;
 	if (map == NULL) {
 		if (ms->flags & MAGIC_CHECK)
 			file_magwarn(ms, "using regular magic file `%s'", fn);
@@ -462,7 +464,7 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
 	for (i = 0; i < MAGIC_SETS; i++) {
 		if (add_mlist(ms->mlist[i], map, i) == -1) {
 			file_oomem(ms, sizeof(*ml));
-			goto fail;
+			return -1;
 		}
 	}
 
@@ -476,12 +478,6 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
 		}
 	}
 	return 0;
-fail:
-	for (i = 0; i < MAGIC_SETS; i++) {
-		mlist_free(ms->mlist[i]);
-		ms->mlist[i] = NULL;
-	}
-	return -1;
 #else
 	return 0;
 #endif /* COMPILE_ONLY */
@@ -554,7 +550,7 @@ apprentice_unmap(struct magic_map *map)
 	case MAP_TYPE_MALLOC:
 		for (i = 0; i < MAGIC_SETS; i++) {
 			if ((char *)map->magic[i] >= (char *)map->p &&
-			    (char *)map->magic[i] < (char *)map->p + map->len)
+			    (char *)map->magic[i] <= (char *)map->p + map->len)
 				continue;
 			free(map->magic[i]);
 		}
@@ -594,7 +590,7 @@ mlist_free(struct mlist *mlist)
 	ml = mlist->next;
 	for (ml = mlist->next; (next = ml->next) != NULL; ml = next) {
 		if (ml->map)
-			apprentice_unmap(ml->map);
+			apprentice_unmap(CAST(struct magic_map *, ml->map));
 		free(ml);
 		if (ml == mlist)
 			break;
@@ -1879,10 +1875,13 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
 	if (m->flag & INDIR) {
 		m->in_type = FILE_LONG;
 		m->in_offset = 0;
+		m->in_op = 0;
 		/*
-		 * read [.lbs][+-]nnnnn)
+		 * read [.,lbs][+-]nnnnn)
 		 */
-		if (*l == '.') {
+		if (*l == '.' || *l == ',') {
+			if (*l == ',')
+				m->in_op |= FILE_OPSIGNED;
 			l++;
 			switch (*l) {
 			case 'l':
@@ -1934,7 +1933,6 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
 			l++;
 		}
 
-		m->in_op = 0;
 		if (*l == '~') {
 			m->in_op |= FILE_OPINVERSE;
 			l++;
@@ -2930,6 +2928,7 @@ apprentice_map(struct magic_set *ms, const char *fn)
 	struct stat st;
 	char *dbname = NULL;
 	struct magic_map *map;
+	struct magic_map *rv = NULL;
 
 	fd = -1;
 	if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
@@ -2978,8 +2977,10 @@ apprentice_map(struct magic_set *ms, const char *fn)
 	(void)close(fd);
 	fd = -1;
 
-	if (check_buffer(ms, map, dbname) != 0)
+	if (check_buffer(ms, map, dbname) != 0) {
+		rv = (struct magic_map *)-1;
 		goto error;
+	}
 #ifdef QUICK
 	if (mprotect(map->p, (size_t)st.st_size, PROT_READ) == -1) {
 		file_error(ms, errno, "cannot mprotect `%s'", dbname);
@@ -2995,7 +2996,7 @@ apprentice_map(struct magic_set *ms, const char *fn)
 		(void)close(fd);
 	apprentice_unmap(map);
 	free(dbname);
-	return NULL;
+	return rv;
 }
 
 private int
@@ -3151,7 +3152,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip)
 		return NULL;
 
 	/* Compatibility with old code that looked in .mime */
-	if (strstr(p, ".mime") != NULL)
+	if (strstr(fn, ".mime") != NULL)
 		ms->flags &= MAGIC_MIME_TYPE;
 	return buf;
 }
diff --git a/src/ascmagic.c b/src/ascmagic.c
index baa95aba2df5..85a973e4fe2e 100644
--- a/src/ascmagic.c
+++ b/src/ascmagic.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: ascmagic.c,v 1.95 2016/05/03 16:10:37 christos Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.97 2016/06/27 20:56:25 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -144,8 +144,10 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
 		    (size_t)(utf8_end - utf8_buf), NULL, NULL,
 		    TEXTTEST, text)) == 0)
 			rv = -1;
-		if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)))
-			return rv == -1 ? 0 : 1;
+		if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) {
+			rv = rv == -1 ? 0 : 1;
+			goto done;
+		}
 	}
 	if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)))
 		return 0;
diff --git a/src/cdf.c b/src/cdf.c
index 4ec65b4510d5..d38e793612fc 100644
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.82 2016/06/01 22:25:25 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.85 2016/10/24 18:02:17 christos Exp $")
 #endif
 
 #include 
@@ -266,7 +266,7 @@ cdf_unpack_dir(cdf_directory_t *d, char *buf)
 	CDF_UNPACK(d->d_unused0);
 }
 
-static int
+int
 cdf_zero_stream(cdf_stream_t *scn)
 {
 	scn->sst_len = 0;
@@ -731,22 +731,25 @@ cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
 			break;
 
 	/* If the it is not there, just fake it; some docs don't have it */
-	if (i == dir->dir_len)
+	if (i == dir->dir_len) {
+		DPRINTF(("Cannot find root storage dir\n"));
 		goto out;
+	}
 	d = &dir->dir_tab[i];
 	*root = d;
 
 	/* If the it is not there, just fake it; some docs don't have it */
-	if (d->d_stream_first_sector < 0)
+	if (d->d_stream_first_sector < 0) {
+		DPRINTF(("No first secror in dir\n"));
 		goto out;
+	}
 
 	return cdf_read_long_sector_chain(info, h, sat,
 	    d->d_stream_first_sector, d->d_size, scn);
 out:
 	scn->sst_tab = NULL;
 	(void)cdf_zero_stream(scn);
-	errno = EFTYPE;
-	return -1;
+	return 0;
 }
 
 static int
@@ -758,6 +761,15 @@ cdf_namecmp(const char *d, const uint16_t *s, size_t l)
 	return 0;
 }
 
+int
+cdf_read_doc_summary_info(const cdf_info_t *info, const cdf_header_t *h,
+    const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
+    const cdf_dir_t *dir, cdf_stream_t *scn)
+{
+	return cdf_read_user_stream(info, h, sat, ssat, sst, dir,
+	    "\05DocumentSummaryInformation", scn);
+}
+
 int
 cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h,
     const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
@@ -1098,7 +1110,7 @@ cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst,
 			cep->ce_namlen = rlen;
 
 		np = CAST(const uint16_t *, CAST(const void *, (b + 16)));
-		if (CAST(const char *, np + cep->ce_namlen) > eb) {
+		if (RCAST(const char *, np + cep->ce_namlen) > eb) {
 			cep->ce_namlen = 0;
 			break;
 		}
@@ -1275,7 +1287,7 @@ cdf_dump(const void *v, size_t len)
 }
 
 void
-cdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst)
+cdf_dump_stream(const cdf_stream_t *sst)
 {
 	size_t ss = sst->sst_ss;
 	cdf_dump(sst->sst_tab, ss * sst->sst_len);
@@ -1331,7 +1343,7 @@ cdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h,
 				    name, d->d_stream_first_sector, d->d_size);
 				break;
 			}
-			cdf_dump_stream(h, &scn);
+			cdf_dump_stream(&scn);
 			free(scn.sst_tab);
 			break;
 		default:
@@ -1507,7 +1519,7 @@ main(int argc, char *argv[])
 		    == -1)
 			err(1, "Cannot read short stream");
 #ifdef CDF_DEBUG
-		cdf_dump_stream(&h, &sst);
+		cdf_dump_stream(&sst);
 #endif
 
 #ifdef CDF_DEBUG
diff --git a/src/cdf.h b/src/cdf.h
index 853a71996b63..0b345ab49615 100644
--- a/src/cdf.h
+++ b/src/cdf.h
@@ -316,6 +316,10 @@ int cdf_read_user_stream(const cdf_info_t *, const cdf_header_t *,
     const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
     const cdf_dir_t *, const char *, cdf_stream_t *);
 int cdf_find_stream(const cdf_dir_t *, const char *, int);
+int cdf_zero_stream(cdf_stream_t *);
+int cdf_read_doc_summary_info(const cdf_info_t *, const cdf_header_t *,
+    const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
+    const cdf_dir_t *, cdf_stream_t *);
 int cdf_read_summary_info(const cdf_info_t *, const cdf_header_t *,
     const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
     const cdf_dir_t *, cdf_stream_t *);
@@ -336,7 +340,7 @@ char *cdf_u16tos8(char *, size_t, const uint16_t *);
 void cdf_dump_header(const cdf_header_t *);
 void cdf_dump_sat(const char *, const cdf_sat_t *, size_t);
 void cdf_dump(const void *, size_t);
-void cdf_dump_stream(const cdf_header_t *, const cdf_stream_t *);
+void cdf_dump_stream(const cdf_stream_t *);
 void cdf_dump_dir(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *,
     const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *);
 void cdf_dump_property_info(const cdf_property_info_t *, size_t);
diff --git a/src/compress.c b/src/compress.c
index 1988fe78fdc7..95f095529da5 100644
--- a/src/compress.c
+++ b/src/compress.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.97 2016/05/13 23:02:28 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.100 2016/10/24 18:02:17 christos Exp $")
 #endif
 
 #include "magic.h"
@@ -132,6 +132,9 @@ static const char *lrzip_args[] = {
 static const char *lz4_args[] = {
 	"lz4", "-cd", NULL
 };
+static const char *zstd_args[] = {
+	"zstd", "-cd", NULL
+};
 
 private const struct {
 	const void *magic;
@@ -154,8 +157,9 @@ private const struct {
  	{ "\3757zXZ\0",	6, xz_args },		/* XZ Utils */
  	{ "LRZI",	4, lrzip_args },	/* LRZIP */
  	{ "\004\"M\030",4, lz4_args },		/* LZ4 */
+ 	{ "\x28\xB5\x2F\xFD", 4, zstd_args },	/* zstd */
 #ifdef ZLIBSUPPORT
-	{ zlibcmp,	0, zlib_args },		/* zlib */
+	{ RCAST(const void *, zlibcmp),	0, zlib_args },		/* zlib */
 #endif
 };
 
@@ -204,7 +208,7 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
 			continue;
 #ifdef ZLIBSUPPORT
 		if (compr[i].maglen == 0)
-			zm = (CAST(int (*)(const unsigned char *),
+			zm = (RCAST(int (*)(const unsigned char *),
 			    CCAST(void *, compr[i].magic)))(buf);
 		else
 #endif
@@ -362,7 +366,7 @@ sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__)))
 			return rn - n;
 		default:
 			n -= rv;
-			buf = ((char *)buf) + rv;
+			buf = CAST(char *, CCAST(void *, buf)) + rv;
 			break;
 		}
 	while (n > 0);
@@ -517,7 +521,7 @@ uncompresszlib(const unsigned char *old, unsigned char **newch,
 
 	return OKDATA;
 err:
-	strlcpy((char *)*newch, z.msg, bytes_max);
+	strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max);
 	*n = strlen((char *)*newch);
 	return ERRDATA;
 }
diff --git a/src/der.c b/src/der.c
index f36606b9d82e..8ae638fb9897 100644
--- a/src/der.c
+++ b/src/der.c
@@ -35,13 +35,11 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: der.c,v 1.7 2016/06/01 22:01:15 christos Exp $")
+FILE_RCSID("@(#)$File: der.c,v 1.10 2016/10/24 18:02:17 christos Exp $")
 #endif
 #endif
 
 #include 
-#include 
-#include 
 
 #include 
 #include 
@@ -53,6 +51,8 @@ FILE_RCSID("@(#)$File: der.c,v 1.7 2016/06/01 22:01:15 christos Exp $")
 #include "magic.h"
 #include "der.h"
 #else
+#include 
+#include 
 #include 
 #endif
 
@@ -181,6 +181,8 @@ getlength(const uint8_t *c, size_t *p, size_t l)
 
 	for (i = 0; i < digits; i++)
 		len = (len << 8) | c[(*p)++];
+	if (*p + len >= l)
+		return DER_BAD;
         return len;
 }
 
@@ -198,7 +200,7 @@ der_tag(char *buf, size_t len, uint32_t tag)
 static int
 der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len)
 {
-	const uint8_t *d = q;
+	const uint8_t *d = CAST(const uint8_t *, q);
 	switch (tag) {
 	case DER_TAG_PRINTABLE_STRING:
 	case DER_TAG_UTF8_STRING:
@@ -220,7 +222,7 @@ der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len)
 int32_t
 der_offs(struct magic_set *ms, struct magic *m, size_t nbytes)
 {
-	const uint8_t *b = CAST(const void *, ms->search.s);
+	const uint8_t *b = RCAST(const uint8_t *, ms->search.s);
 	size_t offs = 0, len = ms->search.s_len ? ms->search.s_len : nbytes;
 
 	if (gettag(b, &offs, len) == DER_BAD)
@@ -251,7 +253,7 @@ der_offs(struct magic_set *ms, struct magic *m, size_t nbytes)
 int
 der_cmp(struct magic_set *ms, struct magic *m)
 {
-	const uint8_t *b = CAST(const void *, ms->search.s);
+	const uint8_t *b = RCAST(const uint8_t *, ms->search.s);
 	const char *s = m->value.s;
 	size_t offs = 0, len = ms->search.s_len;
 	uint32_t tag, tlen;
diff --git a/src/file.c b/src/file.c
index 9a8606d5418f..fad3160d15fe 100644
--- a/src/file.c
+++ b/src/file.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: file.c,v 1.171 2016/05/17 15:52:45 christos Exp $")
+FILE_RCSID("@(#)$File: file.c,v 1.172 2016/10/24 15:21:07 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -431,6 +431,8 @@ private struct magic_set *
 load(const char *magicfile, int flags)
 {
 	struct magic_set *magic = magic_open(flags);
+	const char *e;
+
 	if (magic == NULL) {
 		(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
 		return NULL;
@@ -441,6 +443,8 @@ load(const char *magicfile, int flags)
 		magic_close(magic);
 		return NULL;
 	}
+	if ((e = magic_error(magic)) != NULL)
+		(void)fprintf(stderr, "%s: Warning: %s\n", progname, e);
 	return magic;
 }
 
diff --git a/src/file.h b/src/file.h
index f22fcd941666..180efd3525ce 100644
--- a/src/file.h
+++ b/src/file.h
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.178 2016/03/31 17:51:12 christos Exp $
+ * @(#)$File: file.h,v 1.180 2016/07/20 11:27:08 christos Exp $
  */
 
 #ifndef __file_h__
@@ -134,11 +134,11 @@
 				   or directory */
 #define MAXDESC	64		/* max len of text description/MIME type */
 #define MAXMIME	80		/* max len of text MIME type */
-#define MAXstring 64		/* max len of "string" types */
+#define MAXstring 96		/* max len of "string" types */
 
 #define MAGICNO		0xF11E041C
-#define VERSIONNO	13
-#define FILE_MAGICSIZE	312
+#define VERSIONNO	14
+#define FILE_MAGICSIZE	344
 
 #define	FILE_LOAD	0
 #define FILE_CHECK	1
@@ -275,7 +275,7 @@ struct magic {
 #define				FILE_OPS_MASK	0x07 /* mask for above ops */
 #define				FILE_UNUSED_1	0x08
 #define				FILE_UNUSED_2	0x10
-#define				FILE_UNUSED_3	0x20
+#define				FILE_OPSIGNED	0x20
 #define				FILE_OPINVERSE	0x40
 #define				FILE_OPINDIRECT	0x80
 
diff --git a/src/funcs.c b/src/funcs.c
index df8dbae67f75..c8918a45963a 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.89 2016/03/21 15:56:53 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.90 2016/10/19 20:51:17 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -250,7 +250,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
 	}
 
 	/* try soft magic tests */
-	if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
+	if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) {
 		m = file_softmagic(ms, ubuf, nb, NULL, NULL, BINTEST,
 		    looks_text);
 		if ((ms->flags & MAGIC_DEBUG) != 0)
@@ -277,6 +277,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
 			if (checkdone(ms, &rv))
 				goto done;
 		}
+	}
 
 	/* try text properties */
 	if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) {
diff --git a/src/magic.c b/src/magic.c
index a256c42f944c..b61ad29d7a5d 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -33,7 +33,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: magic.c,v 1.99 2016/05/03 16:09:38 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.100 2016/07/18 11:43:05 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -492,7 +492,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
 			if (r < PIPE_BUF) break;
 		}
 
-		if (nbytes == 0) {
+		if (nbytes == 0 && inname) {
 			/* We can not read it, but we were able to stat it. */
 			if (unreadable_info(ms, sb.st_mode, inname) == -1)
 				goto done;
diff --git a/src/readcdf.c b/src/readcdf.c
index db8d3d39d232..20e631d6db6f 100644
--- a/src/readcdf.c
+++ b/src/readcdf.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2008 Christos Zoulas
+ * Copyright (c) 2008, 2016 Christos Zoulas
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.57 2016/05/03 16:08:49 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.63 2016/10/18 22:25:42 christos Exp $")
 #endif
 
 #include 
@@ -373,13 +373,61 @@ cdf_file_catalog_info(struct magic_set *ms, const cdf_info_t *info,
 	    dir, "Catalog", scn)) == -1)
 		return i;
 #ifdef CDF_DEBUG
-	cdf_dump_catalog(&h, scn);
+	cdf_dump_catalog(h, scn);
 #endif
 	if ((i = cdf_file_catalog(ms, h, scn)) == -1)
 		return -1;
 	return i;
 }
 
+private int
+cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info,
+    const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat,
+    const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn,
+    const cdf_directory_t *root_storage, const char **expn)
+{
+	int i;
+	const char *str = NULL;
+	cdf_directory_t *d;
+	char name[__arraycount(d->d_name)];
+	size_t j, k;
+
+#ifdef CDF_DEBUG
+        cdf_dump_summary_info(h, scn);
+#endif
+        if ((i = cdf_file_summary_info(ms, h, scn, root_storage)) < 0) {
+            *expn = "Can't expand summary_info";
+	    return i;
+	}
+	if (i == 1)
+		return i;
+	for (j = 0; str == NULL && j < dir->dir_len; j++) {
+		d = &dir->dir_tab[j];
+		for (k = 0; k < sizeof(name); k++)
+			name[k] = (char)cdf_tole2(d->d_name[k]);
+		str = cdf_app_to_mime(name,
+				      NOTMIME(ms) ? name2desc : name2mime);
+	}
+	if (NOTMIME(ms)) {
+		if (str != NULL) {
+			if (file_printf(ms, "%s", str) == -1)
+				return -1;
+			i = 1;
+		}
+	} else {
+		if (str == NULL)
+			str = "vnd.ms-office";
+		if (file_printf(ms, "application/%s", str) == -1)
+			return -1;
+		i = 1;
+	}
+	if (i <= 0) {
+		i = cdf_file_catalog_info(ms, info, h, sat, ssat, sst,
+					  dir, scn);
+	}
+	return i;
+}
+
 private struct sinfo {
 	const char *name;
 	const char *mime;
@@ -388,10 +436,13 @@ private struct sinfo {
 } sectioninfo[] = {
 	{ "Encrypted", "encrypted", 
 		{
-			"EncryptedPackage", NULL, NULL, NULL, NULL,
+			"EncryptedPackage", "EncryptedSummary",
+			NULL, NULL, NULL,
 		},
 		{
-			CDF_DIR_TYPE_USER_STREAM, 0, 0, 0, 0,
+			CDF_DIR_TYPE_USER_STREAM,
+			CDF_DIR_TYPE_USER_STREAM,
+			0, 0, 0,
 
 		},
 	},
@@ -412,6 +463,46 @@ private struct sinfo {
 			0, 0, 0, 0
 		},
 	},
+	{ "Microsoft Excel", "vnd.ms-excel",
+		{
+			"Book", "Workbook", NULL, NULL, NULL,
+		},
+		{
+			CDF_DIR_TYPE_USER_STREAM,
+			CDF_DIR_TYPE_USER_STREAM,
+			0, 0, 0,
+		},
+	},
+	{ "Microsoft Word", "msword",
+		{
+			"WordDocument", NULL, NULL, NULL, NULL,
+		},
+		{
+			CDF_DIR_TYPE_USER_STREAM,
+			0, 0, 0, 0,
+		},
+	},
+	{ "Microsoft PowerPoint", "vnd.ms-powerpoint",
+		{
+			"PowerPoint", NULL, NULL, NULL, NULL,
+		},
+		{
+			CDF_DIR_TYPE_USER_STREAM,
+			0, 0, 0, 0,
+		},
+	},
+	{ "Microsoft Outlook Message", "vnd.ms-outlook",
+		{
+			"__properties_version1.0",
+			"__recip_version1.0_#00000000",
+			NULL, NULL, NULL,
+		},
+		{
+			CDF_DIR_TYPE_USER_STREAM,
+			CDF_DIR_TYPE_USER_STORAGE,
+			0, 0, 0,
+		},
+	},
 };
 
 private int
@@ -423,22 +514,19 @@ cdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir)
 		const struct sinfo *si = §ioninfo[sd];
 		for (j = 0; si->sections[j]; j++) {
 			if (cdf_find_stream(dir, si->sections[j], si->types[j])
-			    <= 0) {
-#ifdef CDF_DEBUG
-				fprintf(stderr, "Can't read %s\n",
-				    si->sections[j]);
-#endif
+			    > 0)
 				break;
-			}
+#ifdef CDF_DEBUG
+			fprintf(stderr, "Can't read %s\n", si->sections[j]);
+#endif
 		}
-		if (si->sections[j] != NULL)
+		if (si->sections[j] == NULL)
 			continue;
 		if (NOTMIME(ms)) {
 			if (file_printf(ms, "CDFV2 %s", si->name) == -1)
 				return -1;
 		} else {
-			if (file_printf(ms, "application/CDFV2-%s",
-			    si->mime) == -1)
+			if (file_printf(ms, "application/%s", si->mime) == -1)
 				return -1;
 		}
 		return 1;
@@ -459,6 +547,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
         const char *expn = "";
         const cdf_directory_t *root_storage;
 
+        scn.sst_tab = NULL;
         info.i_fd = fd;
         info.i_buf = buf;
         info.i_len = nbytes;
@@ -528,10 +617,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
 		    i = 1;
 		    goto out5;
 		} else {
-		    free(scn.sst_tab);
-		    scn.sst_tab = NULL;
-		    scn.sst_len = 0;
-		    scn.sst_dirlen = 0;
+		    cdf_zero_stream(&scn);
 		}
 	}
 
@@ -539,56 +625,31 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
             &scn)) == -1) {
                 if (errno != ESRCH) {
                         expn = "Cannot read summary info";
-			goto out4;
 		}
-		i = cdf_file_catalog_info(ms, &info, &h, &sat, &ssat, &sst,
-		    &dir, &scn);
-		if (i > 0)
-			goto out4;
-		i = cdf_file_dir_info(ms, &dir);
-		if (i < 0)
-                        expn = "Cannot read section info";
-		goto out4;
+	} else {
+		i = cdf_check_summary_info(ms, &info, &h,
+		    &sat, &ssat, &sst, &dir, &scn, root_storage, &expn);
+		cdf_zero_stream(&scn);
 	}
-
-
-#ifdef CDF_DEBUG
-        cdf_dump_summary_info(&h, &scn);
-#endif
-        if ((i = cdf_file_summary_info(ms, &h, &scn, root_storage)) < 0)
-            expn = "Can't expand summary_info";
-
-	if (i == 0) {
-		const char *str = NULL;
-		cdf_directory_t *d;
-		char name[__arraycount(d->d_name)];
-		size_t j, k;
-
-		for (j = 0; str == NULL && j < dir.dir_len; j++) {
-			d = &dir.dir_tab[j];
-			for (k = 0; k < sizeof(name); k++)
-				name[k] = (char)cdf_tole2(d->d_name[k]);
-			str = cdf_app_to_mime(name,
-			    NOTMIME(ms) ? name2desc : name2mime);
-		}
-		if (NOTMIME(ms)) {
-			if (str != NULL) {
-				if (file_printf(ms, "%s", str) == -1)
-					return -1;
-				i = 1;
+	if (i <= 0) {
+		if ((i = cdf_read_doc_summary_info(&info, &h, &sat, &ssat,
+		    &sst, &dir, &scn)) == -1) {
+			if (errno != ESRCH) {
+				expn = "Cannot read summary info";
 			}
 		} else {
-			if (str == NULL)
-				str = "vnd.ms-office";
-			if (file_printf(ms, "application/%s", str) == -1)
-				return -1;
-			i = 1;
+			i = cdf_check_summary_info(ms, &info, &h, &sat, &ssat,
+			    &sst, &dir, &scn, root_storage, &expn);
 		}
 	}
+	if (i <= 0) {
+		i = cdf_file_dir_info(ms, &dir);
+		if (i < 0)
+			expn = "Cannot read section info";
+	}
 out5:
-        free(scn.sst_tab);
-out4:
-        free(sst.sst_tab);
+	cdf_zero_stream(&scn);
+	cdf_zero_stream(&sst);
 out3:
         free(dir.dir_tab);
 out2:
@@ -605,7 +666,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
 		    if (file_printf(ms, ", %s", expn) == -1)
 			return -1;
 	    } else {
-		if (file_printf(ms, "application/CDFV2-unknown") == -1)
+		if (file_printf(ms, "application/CDFV2") == -1)
 		    return -1;
 	    }
 	    i = 1;
diff --git a/src/readelf.c b/src/readelf.c
index 39598f7a5c7f..90dae392f699 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.127 2015/11/18 12:29:29 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.128 2016/10/04 21:43:10 christos Exp $")
 #endif
 
 #ifdef BUILTIN_ELF
@@ -509,12 +509,26 @@ do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
     size_t noff, size_t doff, int *flags)
 {
 	if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
-	    type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) {
+	    type == NT_GNU_BUILD_ID && (descsz >= 4 || descsz <= 20)) {
 		uint8_t desc[20];
+		const char *btype;
 		uint32_t i;
 		*flags |= FLAGS_DID_BUILD_ID;
-		if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" :
-		    "sha1") == -1)
+		switch (descsz) {
+		case 8:
+		    btype = "xxHash";
+		    break;
+		case 16:
+		    btype = "md5/uuid";
+		    break;
+		case 20:
+		    btype = "sha1";
+		    break;
+		default:
+		    btype = "unknown";
+		    break;
+		}
+		if (file_printf(ms, ", BuildID[%s]=", btype) == -1)
 			return 1;
 		(void)memcpy(desc, &nbuf[doff], descsz);
 		for (i = 0; i < descsz; i++)
diff --git a/src/softmagic.c b/src/softmagic.c
index 644c9d98d4aa..0e9d433ddd99 100644
--- a/src/softmagic.c
+++ b/src/softmagic.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.234 2016/06/13 12:02:06 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.238 2016/10/24 18:02:17 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -57,13 +57,13 @@ private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
     const unsigned char *, uint32_t, size_t, struct magic *);
 private int mconvert(struct magic_set *, struct magic *, int);
 private int print_sep(struct magic_set *, int);
-private int handle_annotation(struct magic_set *, struct magic *);
+private int handle_annotation(struct magic_set *, struct magic *, int);
 private int cvt_8(union VALUETYPE *, const struct magic *);
 private int cvt_16(union VALUETYPE *, const struct magic *);
 private int cvt_32(union VALUETYPE *, const struct magic *);
 private int cvt_64(union VALUETYPE *, const struct magic *);
 
-#define OFFSET_OOB(n, o, i)	((n) < (o) || (i) > ((n) - (o)))
+#define OFFSET_OOB(n, o, i)	((n) < (uint32_t)(o) || (i) > ((n) - (o)))
 #define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \
     ((uint64_t)(p)->hq[2]<<40)|((uint64_t)(p)->hq[3]<<32)| \
     ((uint64_t)(p)->hq[4]<<24)|((uint64_t)(p)->hq[5]<<16)| \
@@ -80,6 +80,7 @@ private int cvt_64(union VALUETYPE *, const struct magic *);
      ((uint32_t)(p)->hl[3]<<8)|((uint32_t)(p)->hl[2]))
 #define BE16(p) (((uint16_t)(p)->hs[0]<<8)|((uint16_t)(p)->hs[1]))
 #define LE16(p) (((uint16_t)(p)->hs[1]<<8)|((uint16_t)(p)->hs[0]))
+#define SEXT(s,v,p) ((s)?(intmax_t)(int##v##_t)(p):(intmax_t)(uint##v##_t)(p))
 
 /*
  * softmagic - lookup one file in parsed, in-memory copy of database
@@ -230,7 +231,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
 			goto flush;
 		}
 
-		if ((e = handle_annotation(ms, m)) != 0) {
+		if ((e = handle_annotation(ms, m, firstline)) != 0) {
 			*need_separator = 1;
 			*printed_something = 1;
 			*returnval = 1;
@@ -328,7 +329,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
 				} else
 					ms->c.li[cont_level].got_match = 1;
 
-				if ((e = handle_annotation(ms, m)) != 0) {
+				if ((e = handle_annotation(ms, m, firstline)) != 0) {
 					*need_separator = 1;
 					*printed_something = 1;
 					*returnval = 1;
@@ -1226,7 +1227,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
 				 memchr(c, '\r', CAST(size_t, (end - c))))));
 			     lines--, b++) {
 				last = b;
-				if (b[0] == '\r' && b[1] == '\n')
+				if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
 					b++;
 			}
 			if (lines)
@@ -1294,6 +1295,45 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
 	return 0;
 }
 
+private uint32_t
+do_ops(struct magic *m, intmax_t lhs, intmax_t off)
+{
+	intmax_t offset;
+	if (off) {
+		switch (m->in_op & FILE_OPS_MASK) {
+		case FILE_OPAND:
+			offset = lhs & off;
+			break;
+		case FILE_OPOR:
+			offset = lhs | off;
+			break;
+		case FILE_OPXOR:
+			offset = lhs ^ off;
+			break;
+		case FILE_OPADD:
+			offset = lhs + off;
+			break;
+		case FILE_OPMINUS:
+			offset = lhs - off;
+			break;
+		case FILE_OPMULTIPLY:
+			offset = lhs * off;
+			break;
+		case FILE_OPDIVIDE:
+			offset = lhs / off;
+			break;
+		case FILE_OPMODULO:
+			offset = lhs % off;
+			break;
+		}
+	} else
+		offset = lhs;
+	if (m->in_op & FILE_OPINVERSE)
+		offset = ~offset;
+
+	return (uint32_t)offset;
+}
+
 private int
 mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
     size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
@@ -1301,7 +1341,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
     int *printed_something, int *need_separator, int *returnval)
 {
 	uint32_t offset = ms->offset;
-	uint32_t lhs;
+	intmax_t lhs;
 	file_pushbuf_t *pb;
 	int rv, oneed_separator, in_type;
 	char *rbuf;
@@ -1337,7 +1377,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
 	}
 
 	if (m->flag & INDIR) {
-		int off = m->in_offset;
+		intmax_t off = m->in_offset;
+		const int sgn = m->in_op & FILE_OPSIGNED;
 		if (m->in_op & FILE_OPINDIRECT) {
 			const union VALUETYPE *q = CAST(const union VALUETYPE *,
 			    ((const void *)(s + offset + off)));
@@ -1345,178 +1386,55 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
 				return 0;
 			switch (cvt_flip(m->in_type, flip)) {
 			case FILE_BYTE:
-				off = q->b;
+				off = SEXT(sgn,8,q->b);
 				break;
 			case FILE_SHORT:
-				off = q->h;
+				off = SEXT(sgn,16,q->h);
 				break;
 			case FILE_BESHORT:
-				off = (short)BE16(q);
+				off = SEXT(sgn,16,BE16(q));
 				break;
 			case FILE_LESHORT:
-				off = (short)LE16(q);
+				off = SEXT(sgn,16,LE16(q));
 				break;
 			case FILE_LONG:
-				off = q->l;
+				off = SEXT(sgn,32,q->l);
 				break;
 			case FILE_BELONG:
 			case FILE_BEID3:
-				off = (int32_t)BE32(q);
+				off = SEXT(sgn,32,BE32(q));
 				break;
 			case FILE_LEID3:
 			case FILE_LELONG:
-				off = (int32_t)LE32(q);
+				off = SEXT(sgn,32,LE32(q));
 				break;
 			case FILE_MELONG:
-				off = (int32_t)ME32(q);
+				off = SEXT(sgn,32,ME32(q));
 				break;
 			}
 			if ((ms->flags & MAGIC_DEBUG) != 0)
-				fprintf(stderr, "indirect offs=%u\n", off);
+				fprintf(stderr, "indirect offs=%jd\n", off);
 		}
 		switch (in_type = cvt_flip(m->in_type, flip)) {
 		case FILE_BYTE:
 			if (OFFSET_OOB(nbytes, offset, 1))
 				return 0;
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = p->b & off;
-					break;
-				case FILE_OPOR:
-					offset = p->b | off;
-					break;
-				case FILE_OPXOR:
-					offset = p->b ^ off;
-					break;
-				case FILE_OPADD:
-					offset = p->b + off;
-					break;
-				case FILE_OPMINUS:
-					offset = p->b - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = p->b * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = p->b / off;
-					break;
-				case FILE_OPMODULO:
-					offset = p->b % off;
-					break;
-				}
-			} else
-				offset = p->b;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+			offset = do_ops(m, SEXT(sgn,8,p->b), off);
 			break;
 		case FILE_BESHORT:
 			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
-			lhs = (p->hs[0] << 8) | p->hs[1];
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = lhs & off;
-					break;
-				case FILE_OPOR:
-					offset = lhs | off;
-					break;
-				case FILE_OPXOR:
-					offset = lhs ^ off;
-					break;
-				case FILE_OPADD:
-					offset = lhs + off;
-					break;
-				case FILE_OPMINUS:
-					offset = lhs - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = lhs * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = lhs / off;
-					break;
-				case FILE_OPMODULO:
-					offset = lhs % off;
-					break;
-				}
-			} else
-				offset = lhs;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+			offset = do_ops(m, SEXT(sgn,16,BE16(p)), off);
 			break;
 		case FILE_LESHORT:
 			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
-			lhs = (p->hs[1] << 8) | p->hs[0];
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = lhs & off;
-					break;
-				case FILE_OPOR:
-					offset = lhs | off;
-					break;
-				case FILE_OPXOR:
-					offset = lhs ^ off;
-					break;
-				case FILE_OPADD:
-					offset = lhs + off;
-					break;
-				case FILE_OPMINUS:
-					offset = lhs - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = lhs * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = lhs / off;
-					break;
-				case FILE_OPMODULO:
-					offset = lhs % off;
-					break;
-				}
-			} else
-				offset = lhs;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+			offset = do_ops(m, SEXT(sgn,16,LE16(p)), off);
 			break;
 		case FILE_SHORT:
 			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = p->h & off;
-					break;
-				case FILE_OPOR:
-					offset = p->h | off;
-					break;
-				case FILE_OPXOR:
-					offset = p->h ^ off;
-					break;
-				case FILE_OPADD:
-					offset = p->h + off;
-					break;
-				case FILE_OPMINUS:
-					offset = p->h - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = p->h * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = p->h / off;
-					break;
-				case FILE_OPMODULO:
-					offset = p->h % off;
-					break;
-				}
-			}
-			else
-				offset = p->h;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+			offset = do_ops(m, SEXT(sgn,16,p->h), off);
 			break;
 		case FILE_BELONG:
 		case FILE_BEID3:
@@ -1524,38 +1442,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
 				return 0;
 			lhs = BE32(p);
 			if (in_type == FILE_BEID3)
-				lhs = cvt_id3(ms, lhs);
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = lhs & off;
-					break;
-				case FILE_OPOR:
-					offset = lhs | off;
-					break;
-				case FILE_OPXOR:
-					offset = lhs ^ off;
-					break;
-				case FILE_OPADD:
-					offset = lhs + off;
-					break;
-				case FILE_OPMINUS:
-					offset = lhs - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = lhs * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = lhs / off;
-					break;
-				case FILE_OPMODULO:
-					offset = lhs % off;
-					break;
-				}
-			} else
-				offset = lhs;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+				lhs = cvt_id3(ms, (uint32_t)lhs);
+			offset = do_ops(m, SEXT(sgn,32,lhs), off);
 			break;
 		case FILE_LELONG:
 		case FILE_LEID3:
@@ -1563,109 +1451,18 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
 				return 0;
 			lhs = LE32(p);
 			if (in_type == FILE_LEID3)
-				lhs = cvt_id3(ms, lhs);
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = lhs & off;
-					break;
-				case FILE_OPOR:
-					offset = lhs | off;
-					break;
-				case FILE_OPXOR:
-					offset = lhs ^ off;
-					break;
-				case FILE_OPADD:
-					offset = lhs + off;
-					break;
-				case FILE_OPMINUS:
-					offset = lhs - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = lhs * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = lhs / off;
-					break;
-				case FILE_OPMODULO:
-					offset = lhs % off;
-					break;
-				}
-			} else
-				offset = lhs;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+				lhs = cvt_id3(ms, (uint32_t)lhs);
+			offset = do_ops(m, SEXT(sgn,32,lhs), off);
 			break;
 		case FILE_MELONG:
 			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
-			lhs = ME32(p);
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = lhs & off;
-					break;
-				case FILE_OPOR:
-					offset = lhs | off;
-					break;
-				case FILE_OPXOR:
-					offset = lhs ^ off;
-					break;
-				case FILE_OPADD:
-					offset = lhs + off;
-					break;
-				case FILE_OPMINUS:
-					offset = lhs - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = lhs * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = lhs / off;
-					break;
-				case FILE_OPMODULO:
-					offset = lhs % off;
-					break;
-				}
-			} else
-				offset = lhs;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+			offset = do_ops(m, SEXT(sgn,32,ME32(p)), off);
 			break;
 		case FILE_LONG:
 			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
-			if (off) {
-				switch (m->in_op & FILE_OPS_MASK) {
-				case FILE_OPAND:
-					offset = p->l & off;
-					break;
-				case FILE_OPOR:
-					offset = p->l | off;
-					break;
-				case FILE_OPXOR:
-					offset = p->l ^ off;
-					break;
-				case FILE_OPADD:
-					offset = p->l + off;
-					break;
-				case FILE_OPMINUS:
-					offset = p->l - off;
-					break;
-				case FILE_OPMULTIPLY:
-					offset = p->l * off;
-					break;
-				case FILE_OPDIVIDE:
-					offset = p->l / off;
-					break;
-				case FILE_OPMODULO:
-					offset = p->l % off;
-					break;
-				}
-			} else
-				offset = p->l;
-			if (m->in_op & FILE_OPINVERSE)
-				offset = ~offset;
+			offset = do_ops(m, SEXT(sgn,32,p->l), off);
 			break;
 		default:
 			break;
@@ -2078,7 +1875,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
 			size_t slen = ms->search.s_len;
 			char *copy;
 			if (slen != 0) {
-			    copy = malloc(slen);
+			    copy = CAST(char *, malloc(slen));
 			    if (copy == NULL)  {
 				file_regfree(&rx);
 				file_error(ms, errno,
@@ -2231,19 +2028,25 @@ magiccheck(struct magic_set *ms, struct magic *m)
 }
 
 private int
-handle_annotation(struct magic_set *ms, struct magic *m)
+handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
 {
 	if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
+		if (!firstline && file_printf(ms, "\n- ") == -1)
+			return -1;
 		if (file_printf(ms, "%.8s", m->apple) == -1)
 			return -1;
 		return 1;
 	}
 	if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) {
+		if (!firstline && file_printf(ms, "\n- ") == -1)
+			return -1;
 		if (file_printf(ms, "%s", m->ext) == -1)
 			return -1;
 		return 1;
 	}
 	if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
+		if (!firstline && file_printf(ms, "\n- ") == -1)
+			return -1;
 		if (file_printf(ms, "%s", m->mimetype) == -1)
 			return -1;
 		return 1;
@@ -2254,8 +2057,8 @@ handle_annotation(struct magic_set *ms, struct magic *m)
 private int
 print_sep(struct magic_set *ms, int firstline)
 {
-	if (ms->flags & MAGIC_NODESC)
-		return 0;
+//	if (ms->flags & MAGIC_NODESC)
+//		return 0;
 	if (firstline)
 		return 0;
 	/*

From cb1b0068a124bb7f4f8c41d99e15cf2929f196fc Mon Sep 17 00:00:00 2001
From: Andrew Turner 
Date: Mon, 7 Nov 2016 10:26:44 +0000
Subject: [PATCH 073/127] Start to deorbit the kernel configs in GENERIC by
 marking them with NO_UNIVERSE. This stops them from being built with the
 universe, tinderbox, and related targets.

Sponsored by:	ABT Systems Ltd
---
 sys/arm/conf/ALLWINNER | 2 ++
 sys/arm/conf/RPI2      | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/sys/arm/conf/ALLWINNER b/sys/arm/conf/ALLWINNER
index 11cb3b516f28..f979a3b79af2 100644
--- a/sys/arm/conf/ALLWINNER
+++ b/sys/arm/conf/ALLWINNER
@@ -18,6 +18,8 @@
 # in NOTES.
 #
 # $FreeBSD$
+#
+#NO_UNIVERSE
 
 ident		ALLWINNER
 
diff --git a/sys/arm/conf/RPI2 b/sys/arm/conf/RPI2
index e700399e2752..0c92e17859a6 100644
--- a/sys/arm/conf/RPI2
+++ b/sys/arm/conf/RPI2
@@ -17,6 +17,8 @@
 # in NOTES.
 #
 # $FreeBSD$
+#
+#NO_UNIVERSE
 
 ident		RPI2
 

From 921081191d1a2bd40b16e8d5f9aad58fb2d46336 Mon Sep 17 00:00:00 2001
From: Stanislav Galabov 
Date: Mon, 7 Nov 2016 10:54:56 +0000
Subject: [PATCH 074/127] Only include sys/boot.h if LINUX_BOOT_ABI is defined

Only include sys/boot.h if LINUX_BOOT_ABI is defined in
sys/arm/arm/machdep.c

Not doing this prevents kernels that do not define LINUX_BOOT_ABI from
being build with gcc (at least 4.2.1).

Reviewed by:	mmel
Sponsored by:	Smartcom - Bulgaria AD
Differential Revision:	https://reviews.freebsd.org/D8459
---
 sys/arm/arm/machdep.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 2958b27e2718..34357cde0d51 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -76,7 +76,9 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#if defined(LINUX_BOOT_ABI)
 #include 
+#endif
 #include 
 #include 
 #include 

From 9bd4f0a2c6b34052df6bd7002b26342960e9bc75 Mon Sep 17 00:00:00 2001
From: Konstantin Belousov 
Date: Mon, 7 Nov 2016 10:55:56 +0000
Subject: [PATCH 075/127] vn_fullpath1() checked VV_ROOT and then unreferenced
 vp->v_mount->mnt_vnodecovered unlocked.  This allowed unmount to race. Lock
 vnode after we noticed the VV_ROOT flag.  See comments for explanation why
 unlocked check for the flag is considered safe.

Reported and tested by:	avg
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
---
 sys/kern/vfs_cache.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 6101f186f938..bcfa50012190 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -2245,17 +2245,35 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
 		slash_prefixed = 1;
 	}
 	while (vp != rdir && vp != rootvnode) {
-		if (vp->v_vflag & VV_ROOT) {
-			if (vp->v_iflag & VI_DOOMED) {	/* forced unmount */
-				vrele(vp);
+		/*
+		 * The vp vnode must be already fully constructed,
+		 * since it is either found in namecache or obtained
+		 * from VOP_VPTOCNP().  We may test for VV_ROOT safely
+		 * without obtaining the vnode lock.
+		 */
+		if ((vp->v_vflag & VV_ROOT) != 0) {
+			vn_lock(vp, LK_RETRY | LK_SHARED);
+
+			/*
+			 * With the vnode locked, check for races with
+			 * unmount, forced or not.  Note that we
+			 * already verified that vp is not equal to
+			 * the root vnode, which means that
+			 * mnt_vnodecovered can be NULL only for the
+			 * case of unmount.
+			 */
+			if ((vp->v_iflag & VI_DOOMED) != 0 ||
+			    (vp1 = vp->v_mount->mnt_vnodecovered) == NULL ||
+			    vp1->v_mountedhere != vp->v_mount) {
+				vput(vp);
 				error = ENOENT;
 				SDT_PROBE3(vfs, namecache, fullpath, return,
 				    error, vp, NULL);
 				break;
 			}
-			vp1 = vp->v_mount->mnt_vnodecovered;
+
 			vref(vp1);
-			vrele(vp);
+			vput(vp);
 			vp = vp1;
 			continue;
 		}

From fe0660840467f57335fe1353b6c16ef0e1aaa731 Mon Sep 17 00:00:00 2001
From: Andrew Turner 
Date: Mon, 7 Nov 2016 11:01:09 +0000
Subject: [PATCH 076/127] Include machine/armreg.h after machine/asm.h to
 ensure __ARM_ARCH is defined.

MFC after:	1 week
Sponsored by:	ABT Systems Ltd
---
 sys/arm/arm/cpufunc_asm_sheeva.S    | 2 +-
 sys/arm/arm/cpufunc_asm_xscale.S    | 3 ++-
 sys/arm/arm/cpufunc_asm_xscale_c3.S | 3 ++-
 sys/arm/arm/fiq_subr.S              | 3 ++-
 sys/arm/arm/setstack.s              | 3 ++-
 5 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/sys/arm/arm/cpufunc_asm_sheeva.S b/sys/arm/arm/cpufunc_asm_sheeva.S
index dfcc8c96482a..c73c9088d3e5 100644
--- a/sys/arm/arm/cpufunc_asm_sheeva.S
+++ b/sys/arm/arm/cpufunc_asm_sheeva.S
@@ -29,10 +29,10 @@
  * SUCH DAMAGE.
  */
 
-#include 
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 
 .Lsheeva_cache_line_size:
diff --git a/sys/arm/arm/cpufunc_asm_xscale.S b/sys/arm/arm/cpufunc_asm_xscale.S
index d8d48b780c44..08e6f169c3cd 100644
--- a/sys/arm/arm/cpufunc_asm_xscale.S
+++ b/sys/arm/arm/cpufunc_asm_xscale.S
@@ -71,10 +71,11 @@
  *
  * XScale assembly functions for CPU / MMU / TLB specific operations
  */
-#include 
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
+
 /*
  * Size of the XScale core D-cache.
  */
diff --git a/sys/arm/arm/cpufunc_asm_xscale_c3.S b/sys/arm/arm/cpufunc_asm_xscale_c3.S
index a8344a611f53..012c4a9dfbbd 100644
--- a/sys/arm/arm/cpufunc_asm_xscale_c3.S
+++ b/sys/arm/arm/cpufunc_asm_xscale_c3.S
@@ -73,10 +73,11 @@
  * XScale core 3 assembly functions for CPU / MMU / TLB specific operations
  */
 
-#include 
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
+
 /*
  * Size of the XScale core D-cache.
  */
diff --git a/sys/arm/arm/fiq_subr.S b/sys/arm/arm/fiq_subr.S
index acb376872f24..f6300b1f442a 100644
--- a/sys/arm/arm/fiq_subr.S
+++ b/sys/arm/arm/fiq_subr.S
@@ -37,10 +37,11 @@
  */
 
 
-#include 
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
+
 /*
  * MODE_CHANGE_NOP should be inserted between a mode change and a
  * banked register (R8--R15) access.
diff --git a/sys/arm/arm/setstack.s b/sys/arm/arm/setstack.s
index 72a9905aa37a..f66b93225649 100644
--- a/sys/arm/arm/setstack.s
+++ b/sys/arm/arm/setstack.s
@@ -48,10 +48,11 @@
  *
  */
 
-#include 
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
+
 /* To set the stack pointer for a particular mode we must switch
  * to that mode update the banked r13 and then switch back.
  * This routine provides an easy way of doing this for any mode

From 97ac39086142ed8cacf7e5b67a2c4b71549f9ce1 Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Mon, 7 Nov 2016 11:15:40 +0000
Subject: [PATCH 077/127] When a firmware command times out do not free the
 command structure to avoid use after free.

Sponsored by:	Mellanox Technologies
MFC after:	1 week
---
 sys/dev/mlx5/mlx5_core/mlx5_cmd.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sys/dev/mlx5/mlx5_core/mlx5_cmd.c b/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
index 2551d3e8312f..6d6e036e86bf 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
@@ -1245,8 +1245,11 @@ static int cmd_exec_helper(struct mlx5_core_dev *dev, void *in, int in_size, voi
 
 	err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context,
 			      pages_queue, &status);
-	if (err)
+	if (err) {
+		if (err == -ETIMEDOUT)
+			return err;
 		goto out_out;
+	}
 
 	mlx5_core_dbg(dev, "err %d, status %d\n", err, status);
 	if (status) {

From 91951e3978275a59ae22593ee7481791d88a775d Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Mon, 7 Nov 2016 11:20:13 +0000
Subject: [PATCH 078/127] Ensure the firmware is notified of any host memory
 allocation failures. Else firmware commands may time out waiting for host
 memory.

Sponsored by:	Mellanox Technologies
MFC after:	1 week
---
 sys/dev/mlx5/mlx5_core/mlx5_pagealloc.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/sys/dev/mlx5/mlx5_core/mlx5_pagealloc.c b/sys/dev/mlx5/mlx5_core/mlx5_pagealloc.c
index 91904d70ee74..85ff815720c3 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_pagealloc.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_pagealloc.c
@@ -246,13 +246,14 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
 	int inlen;
 	u64 addr;
 	int err;
-	int i;
+	int i = 0;
 
 	inlen = sizeof(*in) + npages * sizeof(in->pas[0]);
 	in = mlx5_vzalloc(inlen);
 	if (!in) {
 		mlx5_core_warn(dev, "vzalloc failed %d\n", inlen);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out_alloc;
 	}
 	memset(&out, 0, sizeof(out));
 
@@ -263,7 +264,7 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
 			if (err == -ENOMEM)
 				err = alloc_system_page(dev, func_id);
 			if (err)
-				goto out_4k;
+				goto out_alloc;
 
 			goto retry;
 		}
@@ -301,12 +302,11 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
 		memset(&out, 0, sizeof(out));
 		nin->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
 		nin->hdr.opmod = cpu_to_be16(MLX5_PAGES_CANT_GIVE);
+		nin->func_id = cpu_to_be16(func_id);
 		if (mlx5_cmd_exec(dev, nin, sizeof(*nin), &out, sizeof(out)))
 			mlx5_core_warn(dev, "page notify failed\n");
 		kfree(nin);
 	}
-
-out_4k:
 	for (i--; i >= 0; i--)
 		free_4k(dev, be64_to_cpu(in->pas[i]));
 out_free:

From adea303c2a28490e3dfa94ff4a41af779833cfb2 Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Mon, 7 Nov 2016 11:22:50 +0000
Subject: [PATCH 079/127] Correct checksum fields in the "mlx5_mini_cqe8"
 structure. The fields in question are currently not used.

Sponsored by:	Mellanox Technologies
MFC after:	1 week
---
 sys/dev/mlx5/device.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sys/dev/mlx5/device.h b/sys/dev/mlx5/device.h
index 60c8e504d09a..4dec59873244 100644
--- a/sys/dev/mlx5/device.h
+++ b/sys/dev/mlx5/device.h
@@ -1348,15 +1348,16 @@ struct mlx5_ifc_mcia_reg_bits {
 
 struct mlx5_mini_cqe8 {
 	union {
-		u32 rx_hash_result;
-		u32 checksum;
+		__be32 rx_hash_result;
+		__be16 checksum;
+		__be16 rsvd;
 		struct {
-			u16 wqe_counter;
+			__be16 wqe_counter;
 			u8  s_wqe_opcode;
 			u8  reserved;
 		} s_wqe_info;
 	};
-	u32 byte_cnt;
+	__be32 byte_cnt;
 };
 
 enum {

From 627ef61aab91ca9687000b9fa71ae2f09eab050b Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Mon, 7 Nov 2016 11:26:25 +0000
Subject: [PATCH 080/127] Query flow table capabilities according to the
 correct capability bit for infiniband.

Sponsored by:	Mellanox Technologies
MFC after:	1 week
---
 sys/dev/mlx5/mlx5_core/mlx5_fw.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/sys/dev/mlx5/mlx5_core/mlx5_fw.c b/sys/dev/mlx5/mlx5_core/mlx5_fw.c
index c9060c8210e4..625e3ed39122 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_fw.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_fw.c
@@ -167,7 +167,11 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev)
 			return err;
 	}
 
-	if (MLX5_CAP_GEN(dev, nic_flow_table)) {
+	if ((MLX5_CAP_GEN(dev, port_type) ==
+	    MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET &&
+	    MLX5_CAP_GEN(dev, nic_flow_table)) ||
+	    (MLX5_CAP_GEN(dev, port_type) == MLX5_CMD_HCA_CAP_PORT_TYPE_IB &&
+	    MLX5_CAP_GEN(dev, ipoib_enhanced_offloads))) {
 		err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE,
 					 HCA_CAP_OPMOD_GET_CUR);
 		if (err)

From cb0224435556eeb120bc250a5621420a7f93fb53 Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Mon, 7 Nov 2016 11:28:50 +0000
Subject: [PATCH 081/127] Add more firmware related structures and update
 existing ones in the MLX5 core module. Update the set and query diagnostics
 counter API.

Sponsored by:	Mellanox Technologies
MFC after:	1 week
---
 sys/dev/mlx5/device.h              |   2 +
 sys/dev/mlx5/driver.h              |   9 +-
 sys/dev/mlx5/mlx5_core/mlx5_port.c |  22 +-
 sys/dev/mlx5/mlx5_ifc.h            | 463 +++++++++++++++++++++++++++--
 sys/dev/mlx5/qp.h                  |  14 +-
 5 files changed, 467 insertions(+), 43 deletions(-)

diff --git a/sys/dev/mlx5/device.h b/sys/dev/mlx5/device.h
index 4dec59873244..de1d7f9010cb 100644
--- a/sys/dev/mlx5/device.h
+++ b/sys/dev/mlx5/device.h
@@ -1271,9 +1271,11 @@ enum {
 	MLX5_RFC_2819_COUNTERS_GROUP	      = 0x2,
 	MLX5_RFC_3635_COUNTERS_GROUP	      = 0x3,
 	MLX5_ETHERNET_EXTENDED_COUNTERS_GROUP = 0x5,
+	MLX5_ETHERNET_DISCARD_COUNTERS_GROUP  = 0x6,
 	MLX5_PER_PRIORITY_COUNTERS_GROUP      = 0x10,
 	MLX5_PER_TRAFFIC_CLASS_COUNTERS_GROUP = 0x11,
 	MLX5_PHYSICAL_LAYER_COUNTERS_GROUP    = 0x12,
+	MLX5_INFINIBAND_PORT_COUNTERS_GROUP = 0x20,
 };
 
 enum {
diff --git a/sys/dev/mlx5/driver.h b/sys/dev/mlx5/driver.h
index f421636ae530..5a6c2874dc3f 100644
--- a/sys/dev/mlx5/driver.h
+++ b/sys/dev/mlx5/driver.h
@@ -120,6 +120,7 @@ enum {
 	MLX5_REG_QETCR		 = 0x4005,
 	MLX5_REG_QPDP		 = 0x4007,
 	MLX5_REG_QTCT		 = 0x400A,
+	MLX5_REG_QHLL		 = 0x4016,
 	MLX5_REG_DCBX_PARAM	 = 0x4020,
 	MLX5_REG_DCBX_APP	 = 0x4021,
 	MLX5_REG_PCAP		 = 0x5001,
@@ -954,9 +955,11 @@ int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
 				 void *in, int in_size);
 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
 				    void *out, int out_size);
-int mlx5_set_diagnostics(struct mlx5_core_dev *mdev, void *in, int in_size);
-int mlx5_query_diagnostics(struct mlx5_core_dev *mdev, u8 num_of_samples,
-			   u16 sample_index, void *out, int out_size);
+int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
+			       int in_size);
+int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
+				   u8 num_of_samples, u16 sample_index,
+				   void *out, int out_size);
 static inline u32 mlx5_mkey_to_idx(u32 mkey)
 {
 	return mkey >> 8;
diff --git a/sys/dev/mlx5/mlx5_core/mlx5_port.c b/sys/dev/mlx5/mlx5_core/mlx5_port.c
index 6ea910d43453..bf23c630eeaf 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_port.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_port.c
@@ -831,28 +831,32 @@ int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
 					  out, out_size);
 }
 
-int mlx5_set_diagnostics(struct mlx5_core_dev *mdev, void *in, int in_size)
+int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
+			       int in_size)
 {
-	u32 out[MLX5_ST_SZ_DW(set_diagnostics_out)];
+	u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)];
 
 	memset(out, 0, sizeof(out));
 
-	MLX5_SET(set_diagnostics_in, in, opcode, MLX5_CMD_OP_SET_DIAGNOSTICS);
+	MLX5_SET(set_diagnostic_params_in, in, opcode,
+		 MLX5_CMD_OP_SET_DIAGNOSTICS);
 
 	return mlx5_cmd_exec_check_status(mdev, in, in_size, out, sizeof(out));
 }
 
-int mlx5_query_diagnostics(struct mlx5_core_dev *mdev, u8 num_of_samples,
-			   u16 sample_index, void *out, int out_size)
+int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
+				   u8 num_of_samples, u16 sample_index,
+				   void *out, int out_size)
 {
-	u32 in[MLX5_ST_SZ_DW(query_diagnostics_in)];
+	u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)];
 
 	memset(in, 0, sizeof(in));
 
-	MLX5_SET(query_diagnostics_in, in, opcode,
+	MLX5_SET(query_diagnostic_counters_in, in, opcode,
 		 MLX5_CMD_OP_QUERY_DIAGNOSTICS);
-	MLX5_SET(query_diagnostics_in, in, num_of_samples, num_of_samples);
-	MLX5_SET(query_diagnostics_in, in, sample_index, sample_index);
+	MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
+		 num_of_samples);
+	MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
 
 	return mlx5_cmd_exec_check_status(mdev, in, sizeof(in), out, out_size);
 }
diff --git a/sys/dev/mlx5/mlx5_ifc.h b/sys/dev/mlx5/mlx5_ifc.h
index e3e6c86d1486..cde74d8e0a91 100644
--- a/sys/dev/mlx5/mlx5_ifc.h
+++ b/sys/dev/mlx5/mlx5_ifc.h
@@ -149,6 +149,12 @@ enum {
 	MLX5_CMD_OP_QUERY_Q_COUNTER               = 0x773,
 	MLX5_CMD_OP_SET_RATE_LIMIT                = 0x780,
 	MLX5_CMD_OP_QUERY_RATE_LIMIT              = 0x781,
+	MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT     = 0x782,
+	MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT    = 0x783,
+	MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT      = 0x784,
+	MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT     = 0x785,
+	MLX5_CMD_OP_CREATE_QOS_PARA_VPORT         = 0x786,
+	MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT        = 0x787,
 	MLX5_CMD_OP_ALLOC_PD                      = 0x800,
 	MLX5_CMD_OP_DEALLOC_PD                    = 0x801,
 	MLX5_CMD_OP_ALLOC_UAR                     = 0x802,
@@ -299,6 +305,59 @@ struct mlx5_ifc_flow_table_fields_supported_bits {
 	u8         reserved_7[0x20];
 };
 
+struct mlx5_ifc_eth_discard_cntrs_grp_bits {
+	u8         ingress_general_high[0x20];
+
+	u8         ingress_general_low[0x20];
+
+	u8         ingress_policy_engine_high[0x20];
+
+	u8         ingress_policy_engine_low[0x20];
+
+	u8         ingress_vlan_membership_high[0x20];
+
+	u8         ingress_vlan_membership_low[0x20];
+
+	u8         ingress_tag_frame_type_high[0x20];
+
+	u8         ingress_tag_frame_type_low[0x20];
+
+	u8         egress_vlan_membership_high[0x20];
+
+	u8         egress_vlan_membership_low[0x20];
+
+	u8         loopback_filter_high[0x20];
+
+	u8         loopback_filter_low[0x20];
+
+	u8         egress_general_high[0x20];
+
+	u8         egress_general_low[0x20];
+
+	u8         reserved_at_1c0[0x40];
+
+	u8         egress_hoq_high[0x20];
+
+	u8         egress_hoq_low[0x20];
+
+	u8         port_isolation_high[0x20];
+
+	u8         port_isolation_low[0x20];
+
+	u8         egress_policy_engine_high[0x20];
+
+	u8         egress_policy_engine_low[0x20];
+
+	u8         ingress_tx_link_down_high[0x20];
+
+	u8         ingress_tx_link_down_low[0x20];
+
+	u8         egress_stp_filter_high[0x20];
+
+	u8         egress_stp_filter_low[0x20];
+
+	u8         reserved_at_340[0x480];
+};
 struct mlx5_ifc_flow_table_prop_layout_bits {
 	u8         ft_support[0x1];
 	u8         flow_tag[0x1];
@@ -421,7 +480,9 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8         vxlan_vni[0x18];
 	u8         reserved_3[0x8];
 
-	u8         reserved_4[0x20];
+	u8         geneve_vni[0x18];
+	u8         reserved4[0x7];
+	u8         geneve_oam[0x1];
 
 	u8         reserved_5[0xc];
 	u8         outer_ipv6_flow_label[0x14];
@@ -429,7 +490,9 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8         reserved_6[0xc];
 	u8         inner_ipv6_flow_label[0x14];
 
-	u8         reserved_7[0xe0];
+	u8         reserved7[0x10];
+	u8         geneve_protocol_type[0x10];
+	u8         reserved8[0xc0];
 };
 
 struct mlx5_ifc_cmd_pas_bits {
@@ -535,6 +598,35 @@ struct mlx5_ifc_debug_cap_bits {
 	struct mlx5_ifc_diagnostic_counter_cap_bits diagnostic_counter[0x1f0];
 };
 
+struct mlx5_ifc_qos_cap_bits {
+	u8         packet_pacing[0x1];
+	u8         esw_scheduling[0x1];
+	u8         esw_bw_share[0x1];
+	u8         esw_rate_limit[0x1];
+	u8         hll[0x1];
+	u8         packet_pacing_burst_bound[0x1];
+	u8         reserved_at_6[0x1a];
+
+	u8         reserved_at_20[0x20];
+
+	u8         packet_pacing_max_rate[0x20];
+
+	u8         packet_pacing_min_rate[0x20];
+
+	u8         reserved_at_80[0x10];
+	u8         packet_pacing_rate_table_size[0x10];
+
+	u8         esw_element_type[0x10];
+	u8         esw_tsar_type[0x10];
+
+	u8         reserved_at_c0[0x10];
+	u8         max_qos_para_vport[0x10];
+
+	u8         max_tsar_bw_share[0x20];
+
+	u8         reserved_at_100[0x700];
+};
+
 struct mlx5_ifc_snapshot_cap_bits {
 	u8         reserved_0[0x1d];
 	u8         suspend_qp_uc[0x1];
@@ -599,17 +691,6 @@ struct mlx5_ifc_flow_table_nic_cap_bits {
 	u8         reserved_1[0x7200];
 };
 
-struct mlx5_ifc_qos_cap_bits {
-	u8         packet_pacing[0x1];
-	u8         reserved_0[0x1f];
-	u8         reserved_1[0x20];
-	u8         packet_pacing_max_rate[0x20];
-	u8         packet_pacing_min_rate[0x20];
-	u8         reserved_2[0x10];
-	u8         packet_pacing_rate_table_size[0x10];
-	u8         reserved_3[0x760];
-};
-
 struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
 	u8         csum_cap[0x1];
 	u8         vlan_cap[0x1];
@@ -631,7 +712,11 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
 	u8         tunnel_statless_gre[0x1];
 	u8         tunnel_stateless_vxlan[0x1];
 
-	u8         reserved_2[0x20];
+	u8         swp[0x1];
+	u8         swp_csum[0x1];
+	u8         swp_lso[0x1];
+	u8         reserved_2[0x1c];
+	u8         tunnel_stateless_geneve_rx[0x1];
 
 	u8         reserved_3[0x10];
 	u8         lro_min_mss_size[0x10];
@@ -1350,6 +1435,19 @@ struct mlx5_ifc_dcbx_param_reg_bits {
 	u8         reserved_11[0x160];
 };
 
+struct mlx5_ifc_qhll_bits {
+	u8         reserved_at_0[0x8];
+	u8         local_port[0x8];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x1b];
+	u8         hll_time[0x5];
+
+	u8         stall_en[0x1];
+	u8         reserved_at_41[0x1c];
+	u8         stall_cnt[0x3];
+};
+
 struct mlx5_ifc_qetcr_reg_bits {
 	u8         operation_type[0x2];
 	u8         cap_local_admin[0x1];
@@ -2031,14 +2129,16 @@ enum {
 };
 
 struct mlx5_ifc_sqc_bits {
-	u8         rlky[0x1];
+	u8         rlkey[0x1];
 	u8         cd_master[0x1];
 	u8         fre[0x1];
 	u8         flush_in_error_en[0x1];
 	u8         allow_multi_pkt_send_wqe[0x1];
 	u8         min_wqe_inline_mode[0x3];
 	u8         state[0x4];
-	u8         reserved_0[0x14];
+	u8         reg_umr[0x1];
+	u8         allow_swp[0x1];
+	u8         reserved_0[0x12];
 
 	u8         reserved_1[0x8];
 	u8         user_index[0x18];
@@ -2046,7 +2146,9 @@ struct mlx5_ifc_sqc_bits {
 	u8         reserved_2[0x8];
 	u8         cqn[0x18];
 
-	u8         reserved_3[0x90];
+	u8         reserved_3[0x80];
+
+	u8         qos_para_vport_number[0x10];
 	u8         packet_pacing_rate_limit_index[0x10];
 
 	u8         tis_lst_sz[0x10];
@@ -2060,6 +2162,58 @@ struct mlx5_ifc_sqc_bits {
 	struct mlx5_ifc_wq_bits wq;
 };
 
+enum {
+	MLX5_TSAR_TYPE_DWRR = 0,
+	MLX5_TSAR_TYPE_ROUND_ROUBIN = 1,
+	MLX5_TSAR_TYPE_ETS = 2
+};
+
+struct mlx5_ifc_tsar_element_attributes_bits {
+	u8         reserved_0[0x8];
+	u8         tsar_type[0x8];
+	u8	   reserved_1[0x10];
+};
+
+struct mlx5_ifc_vport_element_attributes_bits {
+	u8         reserved_0[0x10];
+	u8         vport_number[0x10];
+};
+
+struct mlx5_ifc_vport_tc_element_attributes_bits {
+	u8         traffic_class[0x10];
+	u8         vport_number[0x10];
+};
+
+struct mlx5_ifc_para_vport_tc_element_attributes_bits {
+	u8         reserved_0[0x0C];
+	u8         traffic_class[0x04];
+	u8         qos_para_vport_number[0x10];
+};
+
+enum {
+	MLX5_SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR           = 0x0,
+	MLX5_SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT          = 0x1,
+	MLX5_SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC       = 0x2,
+	MLX5_SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC  = 0x3,
+};
+
+struct mlx5_ifc_scheduling_context_bits {
+	u8         element_type[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         element_attributes[0x20];
+
+	u8         parent_element_id[0x20];
+
+	u8         reserved_at_60[0x40];
+
+	u8         bw_share[0x20];
+
+	u8         max_average_bw[0x20];
+
+	u8         reserved_at_e0[0x120];
+};
+
 struct mlx5_ifc_rqtc_bits {
 	u8         reserved_0[0xa0];
 
@@ -3709,6 +3863,38 @@ struct mlx5_ifc_query_special_contexts_in_bits {
 	u8         reserved_2[0x40];
 };
 
+struct mlx5_ifc_query_scheduling_element_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         reserved_at_40[0xc0];
+
+	struct mlx5_ifc_scheduling_context_bits scheduling_context;
+
+	u8         reserved_at_300[0x100];
+};
+
+enum {
+	MLX5_SCHEDULING_ELEMENT_IN_HIERARCHY_E_SWITCH = 0x2,
+};
+
+struct mlx5_ifc_query_scheduling_element_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+
+	u8         scheduling_hierarchy[0x8];
+	u8         reserved_at_48[0x18];
+
+	u8         scheduling_element_id[0x20];
+
+	u8         reserved_at_80[0x180];
+};
+
 struct mlx5_ifc_query_rqt_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -4687,6 +4873,12 @@ struct mlx5_ifc_qp_2err_in_bits {
 	u8         reserved_3[0x20];
 };
 
+struct mlx5_ifc_para_vport_element_bits {
+	u8         reserved_at_0[0xc];
+	u8         traffic_class[0x4];
+	u8         qos_para_vport_number[0x10];
+};
+
 struct mlx5_ifc_page_fault_resume_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -4806,6 +4998,12 @@ struct mlx5_ifc_modify_tir_out_bits {
 	u8         reserved_1[0x40];
 };
 
+enum
+{
+	MLX5_MODIFY_SQ_BITMASK_PACKET_PACING_RATE_LIMIT_INDEX = 0x1 << 0,
+	MLX5_MODIFY_SQ_BITMASK_QOS_PARA_VPORT_NUMBER =		0x1 << 1
+};
+
 struct mlx5_ifc_modify_tir_in_bits {
 	u8         opcode[0x10];
 	u8         reserved_0[0x10];
@@ -4854,6 +5052,47 @@ struct mlx5_ifc_modify_sq_in_bits {
 	struct mlx5_ifc_sqc_bits ctx;
 };
 
+struct mlx5_ifc_modify_scheduling_element_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         reserved_at_40[0x1c0];
+};
+
+enum {
+	MLX5_MODIFY_SCHEDULING_ELEMENT_IN_SCHEDULING_HIERARCHY_E_SWITCH  = 0x2,
+};
+
+enum {
+	MLX5_MODIFY_SCHEDULING_ELEMENT_BITMASK_BW_SHARE        = 0x1,
+	MLX5_MODIFY_SCHEDULING_ELEMENT_BITMASK_MAX_AVERAGE_BW  = 0x2,
+};
+
+struct mlx5_ifc_modify_scheduling_element_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+
+	u8         scheduling_hierarchy[0x8];
+	u8         reserved_at_48[0x18];
+
+	u8         scheduling_element_id[0x20];
+
+	u8         reserved_at_80[0x20];
+
+	u8         modify_bitmask[0x20];
+
+	u8         reserved_at_c0[0x40];
+
+	struct mlx5_ifc_scheduling_context_bits scheduling_context;
+
+	u8         reserved_at_300[0x100];
+};
+
 struct mlx5_ifc_modify_rqt_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -5568,6 +5807,34 @@ struct mlx5_ifc_destroy_sq_in_bits {
 	u8         reserved_3[0x20];
 };
 
+struct mlx5_ifc_destroy_scheduling_element_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         reserved_at_40[0x1c0];
+};
+
+enum {
+	MLX5_DESTROY_SCHEDULING_ELEMENT_IN_SCHEDULING_HIERARCHY_E_SWITCH  = 0x2,
+};
+
+struct mlx5_ifc_destroy_scheduling_element_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+
+	u8         scheduling_hierarchy[0x8];
+	u8         reserved_at_48[0x18];
+
+	u8         scheduling_element_id[0x20];
+
+	u8         reserved_at_80[0x180];
+};
+
 struct mlx5_ifc_destroy_rqt_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -5656,6 +5923,30 @@ struct mlx5_ifc_destroy_qp_in_bits {
 	u8         reserved_3[0x20];
 };
 
+struct mlx5_ifc_destroy_qos_para_vport_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         reserved_at_40[0x1c0];
+};
+
+struct mlx5_ifc_destroy_qos_para_vport_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+
+	u8         reserved_at_40[0x20];
+
+	u8         reserved_at_60[0x10];
+	u8         qos_para_vport_number[0x10];
+
+	u8         reserved_at_80[0x180];
+};
+
 struct mlx5_ifc_destroy_psv_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -5991,13 +6282,7 @@ struct mlx5_ifc_counter_id_bits {
 	u8         counter_id[0x10];
 };
 
-struct mlx5_ifc_set_diagnostics_in_bits {
-	u8         opcode[0x10];
-	u8         reserved_0[0x10];
-
-	u8         reserved_1[0x10];
-	u8         op_mod[0x10];
-
+struct mlx5_ifc_diagnostic_params_context_bits {
 	u8         num_of_counters[0x10];
 	u8         reserved_2[0x8];
 	u8         log_num_of_samples[0x8];
@@ -6016,7 +6301,17 @@ struct mlx5_ifc_set_diagnostics_in_bits {
 	struct mlx5_ifc_counter_id_bits counter_id[0];
 };
 
-struct mlx5_ifc_set_diagnostics_out_bits {
+struct mlx5_ifc_set_diagnostic_params_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_0[0x10];
+
+	u8         reserved_1[0x10];
+	u8         op_mod[0x10];
+
+	struct mlx5_ifc_diagnostic_params_context_bits diagnostic_params_ctx;
+};
+
+struct mlx5_ifc_set_diagnostic_params_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
 
@@ -6025,7 +6320,7 @@ struct mlx5_ifc_set_diagnostics_out_bits {
 	u8         reserved_1[0x40];
 };
 
-struct mlx5_ifc_query_diagnostics_in_bits {
+struct mlx5_ifc_query_diagnostic_counters_in_bits {
 	u8         opcode[0x10];
 	u8         reserved_0[0x10];
 
@@ -6049,7 +6344,7 @@ struct mlx5_ifc_diagnostic_counter_bits {
 	u8         counter_value_l[0x20];
 };
 
-struct mlx5_ifc_query_diagnostics_out_bits {
+struct mlx5_ifc_query_diagnostic_counters_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
 
@@ -6266,6 +6561,40 @@ struct mlx5_ifc_create_sq_in_bits {
 	struct mlx5_ifc_sqc_bits ctx;
 };
 
+struct mlx5_ifc_create_scheduling_element_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         reserved_at_40[0x40];
+
+	u8         scheduling_element_id[0x20];
+
+	u8         reserved_at_a0[0x160];
+};
+
+enum {
+	MLX5_CREATE_SCHEDULING_ELEMENT_IN_SCHEDULING_HIERARCHY_E_SWITCH  = 0x2,
+};
+
+struct mlx5_ifc_create_scheduling_element_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+
+	u8         scheduling_hierarchy[0x8];
+	u8         reserved_at_48[0x18];
+
+	u8         reserved_at_60[0xa0];
+
+	struct mlx5_ifc_scheduling_context_bits scheduling_context;
+
+	u8         reserved_at_300[0x100];
+};
+
 struct mlx5_ifc_create_rqt_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -6373,6 +6702,30 @@ struct mlx5_ifc_create_qp_in_bits {
 	u8         pas[0][0x40];
 };
 
+struct mlx5_ifc_create_qos_para_vport_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         reserved_at_40[0x20];
+
+	u8         reserved_at_60[0x10];
+	u8         qos_para_vport_number[0x10];
+
+	u8         reserved_at_80[0x180];
+};
+
+struct mlx5_ifc_create_qos_para_vport_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+
+	u8         reserved_at_40[0x1c0];
+};
+
 struct mlx5_ifc_create_psv_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
@@ -6951,6 +7304,7 @@ struct mlx5_ifc_set_rate_limit_in_bits {
 	u8         reserved_at_60[0x20];
 
 	u8         rate_limit[0x20];
+	u8         burst_upper_bound[0x20];
 };
 
 struct mlx5_ifc_access_register_out_bits {
@@ -7604,6 +7958,39 @@ struct mlx5_ifc_phys_layer_cntrs_bits {
 	u8         reserved_0[0x180];
 };
 
+struct mlx5_ifc_infiniband_port_cntrs_bits {
+	u8         symbol_error_counter[0x10];
+	u8         link_error_recovery_counter[0x8];
+	u8         link_downed_counter[0x8];
+
+	u8         port_rcv_errors[0x10];
+	u8         port_rcv_remote_physical_errors[0x10];
+
+	u8         port_rcv_switch_relay_errors[0x10];
+	u8         port_xmit_discards[0x10];
+
+	u8         port_xmit_constraint_errors[0x8];
+	u8         port_rcv_constraint_errors[0x8];
+	u8         reserved_0[0x8];
+	u8         local_link_integrity_errors[0x4];
+	u8         excessive_buffer_overrun_errors[0x4];
+
+	u8         reserved_1[0x10];
+	u8         vl_15_dropped[0x10];
+
+	u8         port_xmit_data[0x20];
+
+	u8         port_rcv_data[0x20];
+
+	u8         port_xmit_pkts[0x20];
+
+	u8         port_rcv_pkts[0x20];
+
+	u8         port_xmit_wait[0x20];
+
+	u8         reserved_2[0x680];
+};
+
 struct mlx5_ifc_phrr_reg_bits {
 	u8         clr[0x1];
 	u8         reserved_0[0x7];
@@ -7692,7 +8079,10 @@ struct mlx5_ifc_pfcc_reg_bits {
 	u8         reserved_7[0x8];
 	u8         cbfrx[0x8];
 
-	u8         reserved_8[0x80];
+	u8         device_stall_minor_watermark[0x10];
+	u8         device_stall_critical_watermark[0x10];
+
+	u8         reserved_8[0x60];
 };
 
 struct mlx5_ifc_pelc_reg_bits {
@@ -7885,7 +8275,19 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits {
 
 	u8         rx_pause_transition_low[0x20];
 
-	u8         reserved_2[0x400];
+	u8         rx_discards_high[0x20];
+
+	u8         rx_discards_low[0x20];
+
+	u8         device_stall_minor_watermark_cnt_high[0x20];
+
+	u8         device_stall_minor_watermark_cnt_low[0x20];
+
+	u8         device_stall_critical_watermark_cnt_high[0x20];
+
+	u8         device_stall_critical_watermark_cnt_low[0x20];
+
+	u8         reserved_2[0x340];
 };
 
 struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits {
@@ -8782,8 +9184,10 @@ union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits {
 	struct mlx5_ifc_eth_2819_cntrs_grp_data_layout_bits eth_2819_cntrs_grp_data_layout;
 	struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits eth_3635_cntrs_grp_data_layout;
 	struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits eth_extended_cntrs_grp_data_layout;
+	struct mlx5_ifc_eth_discard_cntrs_grp_bits eth_discard_cntrs_grp;
 	struct mlx5_ifc_eth_per_prio_grp_data_layout_bits eth_per_prio_grp_data_layout;
 	struct mlx5_ifc_phys_layer_cntrs_bits phys_layer_cntrs;
+	struct mlx5_ifc_infiniband_port_cntrs_bits infiniband_port_cntrs;
 	u8         reserved_0[0x7c0];
 };
 
@@ -8941,6 +9345,7 @@ union mlx5_ifc_ports_control_registers_document_bits {
 	struct mlx5_ifc_eth_2863_cntrs_grp_data_layout_bits eth_2863_cntrs_grp_data_layout;
 	struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits eth_3635_cntrs_grp_data_layout;
 	struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits eth_802_3_cntrs_grp_data_layout;
+	struct mlx5_ifc_eth_discard_cntrs_grp_bits eth_discard_cntrs_grp;
 	struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits eth_extended_cntrs_grp_data_layout;
 	struct mlx5_ifc_eth_per_prio_grp_data_layout_bits eth_per_prio_grp_data_layout;
 	struct mlx5_ifc_eth_per_traffic_class_cong_layout_bits eth_per_traffic_class_cong_layout;
diff --git a/sys/dev/mlx5/qp.h b/sys/dev/mlx5/qp.h
index c32a6430d2e0..82e3edefc75e 100644
--- a/sys/dev/mlx5/qp.h
+++ b/sys/dev/mlx5/qp.h
@@ -220,10 +220,20 @@ enum {
 	MLX5_ETH_WQE_L4_CSUM		= 1 << 7,
 };
 
+enum {
+	MLX5_ETH_WQE_SWP_OUTER_L3_TYPE = 1 << 0,
+	MLX5_ETH_WQE_SWP_OUTER_L4_TYPE = 1 << 1,
+	MLX5_ETH_WQE_SWP_INNER_L3_TYPE = 1 << 4,
+	MLX5_ETH_WQE_SWP_INNER_L4_TYPE = 1 << 5,
+};
+
 struct mlx5_wqe_eth_seg {
-	u8		rsvd0[4];
+	u8              swp_outer_l4_offset;
+	u8		swp_outer_l3_offset;
+	u8		swp_inner_l4_offset;
+	u8		swp_inner_l3_offset;
 	u8		cs_flags;
-	u8		rsvd1;
+	u8		swp_flags;
 	__be16		mss;
 	__be32		rsvd2;
 	__be16		inline_hdr_sz;

From c1bc87b161dcbd99507414ffb77e22af7f7b989e Mon Sep 17 00:00:00 2001
From: Stanislav Galabov 
Date: Mon, 7 Nov 2016 11:35:14 +0000
Subject: [PATCH 082/127] Generate an error if machine/armreg.h is included
 without sys/cdefs.h

machine/armreg.h requires access to the __ARM_ARCH macro, which is not
always properly defined (especially by gcc 4.2.1). We should include
sys/cdefs.h in order to get the definitions in machine/acle-compat.h,
which would properly define the __ARM_ARCH macro in these cases.

So, in cases where machine/armreg.h is included without _SYS_CDEFS_H_
being defined - generate an #error.

Reviewed by:	andrew
Sponsored by:	Smartcom - Bulgaria AD
Differential Revision:	https://reviews.freebsd.org/D8460
---
 sys/arm/include/armreg.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sys/arm/include/armreg.h b/sys/arm/include/armreg.h
index 6607fde2de51..665e32f6516c 100644
--- a/sys/arm/include/armreg.h
+++ b/sys/arm/include/armreg.h
@@ -41,6 +41,10 @@
 #ifndef MACHINE_ARMREG_H
 #define MACHINE_ARMREG_H
 
+#ifndef _SYS_CDEFS_H_
+#error Please include sys/cdefs.h before including machine/armreg.h
+#endif
+
 #define INSN_SIZE	4
 #define INSN_COND_MASK	0xf0000000	/* Condition mask */
 #define PSR_MODE        0x0000001f      /* mode mask */

From 6f4cab6cc3d3f7f1f7a33b599a97501e055b83c7 Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Mon, 7 Nov 2016 11:39:45 +0000
Subject: [PATCH 083/127] Add timer to watch the RQ when we are out of mbufs.

The firmware/hardware does not generate additional completion
events unless we post new buffers. Use a timer to try to post
more buffers in case we are temporarily out of mbufs. Else
the receive schedule completely stops.

Sponsored by:	Mellanox Technologies
MFC after:	1 week
---
 sys/dev/mlx5/mlx5_en/en.h           | 1 +
 sys/dev/mlx5/mlx5_en/mlx5_en_main.c | 8 ++++++++
 sys/dev/mlx5/mlx5_en/mlx5_en_rx.c   | 5 +++--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h
index 9a8436bd1fe6..bbb71cae0444 100644
--- a/sys/dev/mlx5/mlx5_en/en.h
+++ b/sys/dev/mlx5/mlx5_en/en.h
@@ -478,6 +478,7 @@ struct mlx5e_rq {
 	struct mlx5_wq_ctrl wq_ctrl;
 	u32	rqn;
 	struct mlx5e_channel *channel;
+	struct callout watchdog;
 } __aligned(MLX5E_CACHELINE_SIZE);
 
 struct mlx5e_sq_mbuf {
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
index e9b38b882ec2..6bbc46b8299c 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -855,7 +855,13 @@ mlx5e_open_rq(struct mlx5e_channel *c,
 static void
 mlx5e_close_rq(struct mlx5e_rq *rq)
 {
+	mtx_lock(&rq->mtx);
 	rq->enabled = 0;
+	callout_stop(&rq->watchdog);
+	mtx_unlock(&rq->mtx);
+
+	callout_drain(&rq->watchdog);
+
 	mlx5e_modify_rq(rq, MLX5_RQC_STATE_RDY, MLX5_RQC_STATE_ERR);
 }
 
@@ -1439,6 +1445,8 @@ mlx5e_chan_mtx_init(struct mlx5e_channel *c)
 
 	mtx_init(&c->rq.mtx, "mlx5rx", MTX_NETWORK_LOCK, MTX_DEF);
 
+	callout_init_mtx(&c->rq.watchdog, &c->rq.mtx, 0);
+
 	for (tc = 0; tc < c->num_tc; tc++) {
 		struct mlx5e_sq *sq = c->sq + tc;
 
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
index 5c793473e63c..4d29b2397e64 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
@@ -82,9 +82,10 @@ mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
 	while (!mlx5_wq_ll_is_full(&rq->wq)) {
 		struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, rq->wq.head);
 
-		if (unlikely(mlx5e_alloc_rx_wqe(rq, wqe, rq->wq.head)))
+		if (unlikely(mlx5e_alloc_rx_wqe(rq, wqe, rq->wq.head))) {
+			callout_reset_curcpu(&rq->watchdog, 1, (void *)&mlx5e_post_rx_wqes, rq);
 			break;
-
+		}
 		mlx5_wq_ll_push(&rq->wq, be16_to_cpu(wqe->next.next_wqe_index));
 	}
 

From 95d34803f7412ab9f185d299bf57a2d4b1c877ca Mon Sep 17 00:00:00 2001
From: Andrew Turner 
Date: Mon, 7 Nov 2016 11:56:18 +0000
Subject: [PATCH 084/127] Fix the order of includes so machine/asm.h is first.

MFC after:	1 week
Sponsored by:	ABT Systems Ltd
---
 sys/arm/ti/ti_smc.S | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/arm/ti/ti_smc.S b/sys/arm/ti/ti_smc.S
index 931ad52d003d..287f0a7711f7 100644
--- a/sys/arm/ti/ti_smc.S
+++ b/sys/arm/ti/ti_smc.S
@@ -22,10 +22,11 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include 
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
+
 	.cpu cortex-a8
 	.arch_extension sec
 

From 82f8bfcb0632b0114bdf2d37009caa24e46c030c Mon Sep 17 00:00:00 2001
From: Andrew Turner 
Date: Mon, 7 Nov 2016 14:07:11 +0000
Subject: [PATCH 085/127] Use the armv6 GENERIC in the qemu nanobsd image.

Sponsored by:	ABT Systems Ltd
---
 tools/tools/nanobsd/embedded/qemu-armv7.cfg | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/tools/nanobsd/embedded/qemu-armv7.cfg b/tools/tools/nanobsd/embedded/qemu-armv7.cfg
index dd85c8f030aa..f80fee91320c 100644
--- a/tools/tools/nanobsd/embedded/qemu-armv7.cfg
+++ b/tools/tools/nanobsd/embedded/qemu-armv7.cfg
@@ -29,7 +29,7 @@
 
 NANO_ARCH=armv6
 NANO_DRIVE=vtbd0
-NANO_KERNEL=VIRT
+NANO_KERNEL=GENERIC
 NANO_NAME=qemu-armv7
 NANO_LAYOUT=std-uefi-bios
 NANO_CPUTYPE=cortexa

From e0629b31f347995daaf85b083c0f617589cbdaf6 Mon Sep 17 00:00:00 2001
From: Scott Long 
Date: Mon, 7 Nov 2016 17:34:19 +0000
Subject: [PATCH 086/127] Fix the fallout from r308268 (mpt driver causes
 endless witness warnings in VMWare and elsewhere) with the precision of a
 dull, rusty butter knife.

Reported by:	tuexen
Obtained from:	Netflix
---
 sys/dev/mpt/mpt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index a3fa58e7d3a5..6d7b12626b84 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -2695,7 +2695,11 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
 	 */
 	mpt->max_cam_seg_cnt = min(mpt->max_seg_cnt, (MAXPHYS / PAGE_SIZE) + 1);
 
+	/* XXX Lame Locking! */
+	MPT_UNLOCK(mpt);
 	error = mpt_dma_buf_alloc(mpt);
+	MPT_LOCK(mpt);
+
 	if (error != 0) {
 		mpt_prt(mpt, "mpt_dma_buf_alloc() failed!\n");
 		return (EIO);
@@ -2745,6 +2749,7 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
 		 * retrieved, we are responsible for re-downloading
 		 * the firmware after any hard-reset.
 		 */
+		MPT_UNLOCK(mpt);
 		mpt->fw_image_size = mpt->ioc_facts.FWImageSize;
 		error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0,
 		    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
@@ -2752,6 +2757,7 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
 		    &mpt->fw_dmat);
 		if (error != 0) {
 			mpt_prt(mpt, "cannot create firmware dma tag\n");
+			MPT_LOCK(mpt);
 			return (ENOMEM);
 		}
 		error = bus_dmamem_alloc(mpt->fw_dmat,
@@ -2760,6 +2766,7 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
 		if (error != 0) {
 			mpt_prt(mpt, "cannot allocate firmware memory\n");
 			bus_dma_tag_destroy(mpt->fw_dmat);
+			MPT_LOCK(mpt);
 			return (ENOMEM);
 		}
 		mi.mpt = mpt;
@@ -2768,6 +2775,7 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
 		    mpt->fw_image, mpt->fw_image_size, mpt_map_rquest, &mi, 0);
 		mpt->fw_phys = mi.phys;
 
+		MPT_LOCK(mpt);
 		error = mpt_upload_fw(mpt);
 		if (error != 0) {
 			mpt_prt(mpt, "firmware upload failed.\n");

From 69cab2d1bfb554a690c39a6eda42be3cb6f74418 Mon Sep 17 00:00:00 2001
From: Oleksandr Tymoshenko 
Date: Mon, 7 Nov 2016 17:38:39 +0000
Subject: [PATCH 087/127] Fix locking in bcm2835_audio driver

- Move all VCHI activity to worker thread: channel methods are called with
    non-sleepable lock held and VCHI uses sleepable lock.

- In worker thread use sx(9) lock instead of mutex(9) for the same reason.

PR:		213801, 205979
---
 sys/arm/broadcom/bcm2835/bcm2835_audio.c | 134 +++++++++++++++--------
 1 file changed, 91 insertions(+), 43 deletions(-)

diff --git a/sys/arm/broadcom/bcm2835/bcm2835_audio.c b/sys/arm/broadcom/bcm2835/bcm2835_audio.c
index 8658c2671cd7..7b51054d972c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_audio.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_audio.c
@@ -104,14 +104,17 @@ struct bcm2835_audio_info {
 	struct intr_config_hook intr_hook;
 
 	/* VCHI data */
-	struct mtx vchi_lock;
+	struct sx vchi_lock;
 
 	VCHI_INSTANCE_T vchi_instance;
 	VCHI_CONNECTION_T *vchi_connection;
 	VCHI_SERVICE_HANDLE_T vchi_handle;
 
-	struct mtx data_lock;
-	struct cv data_cv;
+	struct sx worker_lock;
+	struct cv worker_cv;
+
+	bool parameters_update_pending;
+	bool controls_update_pending;
 
 	/* Unloadign module */
 	int unloading;
@@ -121,8 +124,8 @@ struct bcm2835_audio_info {
 #define bcm2835_audio_unlock(_ess) snd_mtxunlock((_ess)->lock)
 #define bcm2835_audio_lock_assert(_ess) snd_mtxassert((_ess)->lock)
 
-#define VCHIQ_VCHI_LOCK(sc)		mtx_lock(&(sc)->vchi_lock)
-#define VCHIQ_VCHI_UNLOCK(sc)		mtx_unlock(&(sc)->vchi_lock)
+#define VCHIQ_VCHI_LOCK(sc)		sx_xlock(&(sc)->vchi_lock)
+#define VCHIQ_VCHI_UNLOCK(sc)		sx_xunlock(&(sc)->vchi_lock)
 
 static const char *
 dest_description(uint32_t dest)
@@ -175,7 +178,7 @@ bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *m
 		chn_intr(sc->pch.channel);
 
 		if (perr || ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE)
-			cv_signal(&sc->data_cv);
+			cv_signal(&sc->worker_cv);
 	} else
 		printf("%s: unknown m.type: %d\n", __func__, m.type);
 }
@@ -261,8 +264,6 @@ bcm2835_audio_start(struct bcm2835_audio_chinfo *ch)
 	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
 		vchi_service_use(sc->vchi_handle);
 
-		bcm2835_audio_reset_channel(ch);
-
 		m.type = VC_AUDIO_MSG_TYPE_START;
 		ret = vchi_msg_queue(sc->vchi_handle,
 		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
@@ -324,7 +325,7 @@ bcm2835_audio_open(struct bcm2835_audio_info *sc)
 }
 
 static void
-bcm2835_audio_update_controls(struct bcm2835_audio_info *sc)
+bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, uint32_t dest)
 {
 	VC_AUDIO_MSG_T m;
 	int ret, db;
@@ -334,10 +335,10 @@ bcm2835_audio_update_controls(struct bcm2835_audio_info *sc)
 		vchi_service_use(sc->vchi_handle);
 
 		m.type = VC_AUDIO_MSG_TYPE_CONTROL;
-		m.u.control.dest = sc->dest;
-		if (sc->volume > 99)
-			sc->volume = 99;
-		db = db_levels[sc->volume/5];
+		m.u.control.dest = dest;
+		if (volume > 99)
+			volume = 99;
+		db = db_levels[volume/5];
 		m.u.control.volume = VCHIQ_AUDIO_VOLUME(db);
 
 		ret = vchi_msg_queue(sc->vchi_handle,
@@ -352,7 +353,7 @@ bcm2835_audio_update_controls(struct bcm2835_audio_info *sc)
 }
 
 static void
-bcm2835_audio_update_params(struct bcm2835_audio_info *sc, struct bcm2835_audio_chinfo *ch)
+bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_t speed)
 {
 	VC_AUDIO_MSG_T m;
 	int ret;
@@ -362,9 +363,9 @@ bcm2835_audio_update_params(struct bcm2835_audio_info *sc, struct bcm2835_audio_
 		vchi_service_use(sc->vchi_handle);
 
 		m.type = VC_AUDIO_MSG_TYPE_CONFIG;
-		m.u.config.channels = AFMT_CHANNEL(ch->fmt);
-		m.u.config.samplerate = ch->spd;
-		m.u.config.bps = AFMT_BIT(ch->fmt);
+		m.u.config.channels = AFMT_CHANNEL(fmt);
+		m.u.config.samplerate = speed;
+		m.u.config.bps = AFMT_BIT(fmt);
 
 		ret = vchi_msg_queue(sc->vchi_handle,
 		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
@@ -474,29 +475,61 @@ bcm2835_audio_worker(void *data)
 {
 	struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)data;
 	struct bcm2835_audio_chinfo *ch = &sc->pch;
-	mtx_lock(&sc->data_lock);
+	uint32_t speed, format;
+	uint32_t volume, dest;
+	bool parameters_changed, controls_changed;
+
+	sx_slock(&sc->worker_lock);
 	while(1) {
 
 		if (sc->unloading)
 			break;
 
+		parameters_changed = false;
+		controls_changed = false;
+		bcm2835_audio_lock(sc);
+		if (sc->parameters_update_pending) {
+			/* TODO: update parameters */
+			speed = ch->spd;
+			format = ch->fmt;
+			sc->parameters_update_pending = false;
+			parameters_changed = true;
+		}
+
+		if (sc->controls_update_pending) {
+			volume = sc->volume;
+			dest = sc->dest;
+			sc->controls_update_pending = false;
+			controls_changed = true;
+		}
+
+		bcm2835_audio_unlock(sc);
+
+		if (parameters_changed) {
+			bcm2835_audio_update_params(sc, format, speed);
+		}
+
+		if (controls_changed) {
+			bcm2835_audio_update_controls(sc, volume, dest);
+		}
+
 		if (ch->playback_state == PLAYBACK_IDLE) {
-			cv_wait_sig(&sc->data_cv, &sc->data_lock);
+			cv_wait_sig(&sc->worker_cv, &sc->worker_lock);
 			continue;
 		}
 
 		if (ch->playback_state == PLAYBACK_STOPPING) {
+			bcm2835_audio_stop(ch);
 			bcm2835_audio_reset_channel(&sc->pch);
 			ch->playback_state = PLAYBACK_IDLE;
 			continue;
 		}
 
 		if (ch->free_buffer < vchiq_unbuffered_bytes(ch)) {
-			cv_timedwait_sig(&sc->data_cv, &sc->data_lock, 10);
+			cv_timedwait_sig(&sc->worker_cv, &sc->worker_lock, 10);
 			continue;
 		}
 
-
 		bcm2835_audio_write_samples(ch);
 
 		if (ch->playback_state == PLAYBACK_STARTING) {
@@ -507,7 +540,7 @@ bcm2835_audio_worker(void *data)
 			}
 		}
 	}
-	mtx_unlock(&sc->data_lock);
+	sx_sunlock(&sc->worker_lock);
 
 	kproc_exit(0);
 }
@@ -547,11 +580,13 @@ bcmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *
 	buffer = malloc(sc->bufsz, M_DEVBUF, M_WAITOK | M_ZERO);
 
 	if (sndbuf_setup(ch->buffer, buffer, sc->bufsz) != 0) {
+		device_printf(sc->dev, "sndbuf_setup failed\n");
 		free(buffer, M_DEVBUF);
 		return NULL;
 	}
 
-	bcm2835_audio_update_params(sc, ch);
+	sc->parameters_update_pending = true;
+	cv_signal(&sc->worker_cv);
 
 	return ch;
 }
@@ -576,12 +611,12 @@ bcmchan_setformat(kobj_t obj, void *data, uint32_t format)
 	struct bcm2835_audio_info *sc = ch->parent;
 
 	bcm2835_audio_lock(sc);
-
 	ch->fmt = format;
-	bcm2835_audio_update_params(sc, ch);
-
+	sc->parameters_update_pending = true;
 	bcm2835_audio_unlock(sc);
 
+	cv_signal(&sc->worker_cv);
+
 	return 0;
 }
 
@@ -592,12 +627,12 @@ bcmchan_setspeed(kobj_t obj, void *data, uint32_t speed)
 	struct bcm2835_audio_info *sc = ch->parent;
 
 	bcm2835_audio_lock(sc);
-
 	ch->spd = speed;
-	bcm2835_audio_update_params(sc, ch);
-
+	sc->parameters_update_pending = true;
 	bcm2835_audio_unlock(sc);
 
+	cv_signal(&sc->worker_cv);
+
 	return ch->spd;
 }
 
@@ -618,26 +653,30 @@ bcmchan_trigger(kobj_t obj, void *data, int go)
 	if (!PCMTRIG_COMMON(go))
 		return (0);
 
-	bcm2835_audio_lock(sc);
 
 	switch (go) {
 	case PCMTRIG_START:
+		bcm2835_audio_lock(sc);
+		bcm2835_audio_reset_channel(ch);
 		ch->playback_state = PLAYBACK_STARTING;
+		bcm2835_audio_unlock(sc);
+		/* kickstart data flow */
+		chn_intr(sc->pch.channel);
 		/* wakeup worker thread */
-		cv_signal(&sc->data_cv);
+		cv_signal(&sc->worker_cv);
 		break;
 
 	case PCMTRIG_STOP:
 	case PCMTRIG_ABORT:
+		bcm2835_audio_lock(sc);
 		ch->playback_state = PLAYBACK_STOPPING;
-		bcm2835_audio_stop(ch);
+		bcm2835_audio_unlock(sc);
+		cv_signal(&sc->worker_cv);
 		break;
 
 	default:
 		break;
 	}
-
-	bcm2835_audio_unlock(sc);
 	return 0;
 }
 
@@ -695,8 +734,11 @@ bcmmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
 
 	switch (dev) {
 	case SOUND_MIXER_VOLUME:
+		bcm2835_audio_lock(sc);
 		sc->volume = left;
-		bcm2835_audio_update_controls(sc);
+		sc->controls_update_pending = true;
+		bcm2835_audio_unlock(sc);
+		cv_signal(&sc->worker_cv);
 		break;
 
 	default:
@@ -729,9 +771,13 @@ sysctl_bcm2835_audio_dest(SYSCTL_HANDLER_ARGS)
 	if ((val < 0) || (val > 2))
 		return (EINVAL);
 
+	bcm2835_audio_lock(sc);
 	sc->dest = val;
+	sc->controls_update_pending = true;
+	bcm2835_audio_unlock(sc);
+
+	cv_signal(&sc->worker_cv);
 	device_printf(sc->dev, "destination set to %s\n", dest_description(val));
-	bcm2835_audio_update_controls(sc);
 
 	return (0);
 }
@@ -821,9 +867,9 @@ bcm2835_audio_attach(device_t dev)
 
 	sc->lock = snd_mtxcreate(device_get_nameunit(dev), "bcm2835_audio softc");
 
-	mtx_init(&sc->vchi_lock, "bcm2835_audio", "vchi_lock", MTX_DEF);
-	mtx_init(&sc->data_lock, "data_mtx", "data_mtx", MTX_DEF);
-	cv_init(&sc->data_cv, "data_cv");
+	sx_init(&sc->vchi_lock, device_get_nameunit(dev));
+	sx_init(&sc->worker_lock, "bcm_audio_worker_lock");
+	cv_init(&sc->worker_cv, "worker_cv");
 	sc->vchi_handle = VCHIQ_SERVICE_HANDLE_INVALID;
 
 	/* 
@@ -850,16 +896,18 @@ bcm2835_audio_detach(device_t dev)
 	sc = pcm_getdevinfo(dev);
 
 	/* Stop worker thread */
+	sx_xlock(&sc->worker_lock);
 	sc->unloading = 1;
-	cv_signal(&sc->data_cv);
+	sx_xunlock(&sc->worker_lock);
+	cv_signal(&sc->worker_cv);
 
 	r = pcm_unregister(dev);
 	if (r)
 		return r;
 
-	mtx_destroy(&sc->vchi_lock);
-	mtx_destroy(&sc->data_lock);
-	cv_destroy(&sc->data_cv);
+	sx_destroy(&sc->vchi_lock);
+	sx_destroy(&sc->worker_lock);
+	cv_destroy(&sc->worker_cv);
 
 	bcm2835_audio_release(sc);
 

From bceff6e30aa5c0c502024a3d4b99f829b6250b0c Mon Sep 17 00:00:00 2001
From: Alexander Motin 
Date: Mon, 7 Nov 2016 18:21:53 +0000
Subject: [PATCH 088/127] Add support for EIIOE flag in Additional Element
 Status.

It was added in SES-3 spec, and its support required to properly link
the Additional Element Status page data to the original elements.

MFC after:	2 weeks
Sponsored by:	iXsystems, Inc.
---
 sys/cam/scsi/scsi_enc_ses.c | 27 +++++++++++++++++++--------
 sys/cam/scsi/scsi_ses.h     |  3 ++-
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 283e2e3ac823..a1a2b3c5a147 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -1758,14 +1758,20 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
 		eip = ses_elm_addlstatus_eip(elm_hdr);
 		if (eip && !ignore_index) {
 			struct ses_elm_addlstatus_eip_hdr *eip_hdr;
-			int expected_index;
+			int expected_index, index;
+			ses_elem_index_type_t index_type;
 
 			eip_hdr = (struct ses_elm_addlstatus_eip_hdr *)elm_hdr;
-			expected_index = iter.individual_element_index;
+			if (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE) {
+				index_type = SES_ELEM_INDEX_GLOBAL;
+				expected_index = iter.global_element_index;
+			} else {
+				index_type = SES_ELEM_INDEX_INDIVIDUAL;
+				expected_index = iter.individual_element_index;
+			}
 			titer = iter;
 			telement = ses_iter_seek_to(&titer,
-						   eip_hdr->element_index,
-						   SES_ELEM_INDEX_INDIVIDUAL);
+			    eip_hdr->element_index, index_type);
 			if (telement != NULL &&
 			    (ses_typehasaddlstatus(enc, titer.type_index) !=
 			     TYPE_ADDLSTATUS_NONE ||
@@ -1775,13 +1781,18 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
 			} else
 				ignore_index = 1;
 
-			if (iter.individual_element_index > expected_index
+			if (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE)
+				index = iter.global_element_index;
+			else
+				index = iter.individual_element_index;
+			if (index > expected_index
 			 && status_type == TYPE_ADDLSTATUS_MANDATORY) {
-				ENC_VLOG(enc, "%s: provided element "
+				ENC_VLOG(enc, "%s: provided %s element"
 					"index %d skips mandatory status "
 					" element at index %d\n",
-					__func__, eip_hdr->element_index,
-					expected_index);
+					__func__, (eip_hdr->byte2 &
+					SES_ADDL_EIP_EIIOE) ? "global " : "",
+					index, expected_index);
 			}
 		}
 		elmpriv = element->elm_private;
diff --git a/sys/cam/scsi/scsi_ses.h b/sys/cam/scsi/scsi_ses.h
index 0aeb22e0c21c..76cd36d140ec 100644
--- a/sys/cam/scsi/scsi_ses.h
+++ b/sys/cam/scsi/scsi_ses.h
@@ -2413,7 +2413,8 @@ int ses_elm_addlstatus_invalid(struct ses_elm_addlstatus_base_hdr *);
 
 struct ses_elm_addlstatus_eip_hdr {
 	struct ses_elm_addlstatus_base_hdr base;
-	uint8_t reserved;
+	uint8_t byte2;
+#define	SES_ADDL_EIP_EIIOE	1
 	uint8_t element_index;
 	/* NB: This define (currently) applies to all eip=1 headers */
 #define	SES_EIP_HDR_EXTRA_LEN	2

From d30e308465d973014a18687829542e3b40c3e8db Mon Sep 17 00:00:00 2001
From: Oleksandr Tymoshenko 
Date: Mon, 7 Nov 2016 20:02:18 +0000
Subject: [PATCH 089/127] Fix include order as required post r308415

---
 sys/cddl/dev/dtrace/arm/dtrace_asm.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/cddl/dev/dtrace/arm/dtrace_asm.S b/sys/cddl/dev/dtrace/arm/dtrace_asm.S
index fd0ce6c86d0f..d7b3ead7197f 100644
--- a/sys/cddl/dev/dtrace/arm/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/arm/dtrace_asm.S
@@ -32,8 +32,8 @@
 #include 
 #include 
 
-#include 
 #include 
+#include 
 
 #include "assym.s"
 

From aabc5ce043340c18d7bc7f7ca956724c66583625 Mon Sep 17 00:00:00 2001
From: Oleksandr Tymoshenko 
Date: Mon, 7 Nov 2016 21:15:39 +0000
Subject: [PATCH 090/127] Refactor FDT part of gpioled driver

- Split driver in two parts: FDT and non-FDT
- Instead of reattach gpioled nodes to GPIO bus use
    gpio_pin_get_by_ofw_idx and add ofwbus and simplebus as parrent buses

Reviewed by:	loos
Differential Revision:	https://reviews.freebsd.org/D8233
---
 sys/conf/files                    |   3 +-
 sys/dev/gpio/gpioled.c            |  99 -------------
 sys/dev/gpio/gpioled_fdt.c        | 230 ++++++++++++++++++++++++++++++
 sys/modules/gpio/gpioled/Makefile |   4 +
 4 files changed, 236 insertions(+), 100 deletions(-)
 create mode 100644 sys/dev/gpio/gpioled_fdt.c

diff --git a/sys/conf/files b/sys/conf/files
index a154b803bb65..7a92df184c73 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1612,7 +1612,8 @@ dev/gpio/gpiobus.c		optional gpio				\
 dev/gpio/gpioc.c		optional gpio				\
 	dependency	"gpio_if.h"
 dev/gpio/gpioiic.c		optional gpioiic
-dev/gpio/gpioled.c		optional gpioled
+dev/gpio/gpioled.c		optional gpioled !fdt
+dev/gpio/gpioled_fdt.c		optional gpioled fdt
 dev/gpio/gpioregulator.c	optional gpioregulator fdt ext_resources
 dev/gpio/gpiospi.c		optional gpiospi
 dev/gpio/gpio_if.m		optional gpio
diff --git a/sys/dev/gpio/gpioled.c b/sys/dev/gpio/gpioled.c
index 2c579e404bc3..27e6ac344653 100644
--- a/sys/dev/gpio/gpioled.c
+++ b/sys/dev/gpio/gpioled.c
@@ -39,11 +39,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef FDT
-#include 
-#include 
-#endif
-
 #include 
 #include 
 
@@ -91,66 +86,9 @@ gpioled_control(void *priv, int onoff)
 	GPIOLED_UNLOCK(sc);
 }
 
-#ifdef FDT
-static void
-gpioled_identify(driver_t *driver, device_t bus)
-{
-	phandle_t child, leds, root;
-
-	root = OF_finddevice("/");
-	if (root == 0)
-		return;
-	for (leds = OF_child(root); leds != 0; leds = OF_peer(leds)) {
-		if (!fdt_is_compatible_strict(leds, "gpio-leds"))
-			continue;
-		/* Traverse the 'gpio-leds' node and add its children. */
-		for (child = OF_child(leds); child != 0; child = OF_peer(child)) {
-			if (!OF_hasprop(child, "gpios"))
-				continue;
-			if (ofw_gpiobus_add_fdt_child(bus, driver->name, child) == NULL)
-				continue;
-		}
-	}
-}
-#endif
-
 static int
 gpioled_probe(device_t dev)
 {
-#ifdef FDT
-	int match;
-	phandle_t node;
-	char *compat;
-
-	/*
-	 * We can match against our own node compatible string and also against
-	 * our parent node compatible string.  The first is normally used to
-	 * describe leds on a gpiobus and the later when there is a common node
-	 * compatible with 'gpio-leds' which is used to concentrate all the
-	 * leds nodes on the dts.
-	 */
-	match = 0;
-	if (ofw_bus_is_compatible(dev, "gpioled"))
-		match = 1;
-
-	if (match == 0) {
-		if ((node = ofw_bus_get_node(dev)) == -1)
-			return (ENXIO);
-		if ((node = OF_parent(node)) == -1)
-			return (ENXIO);
-		if (OF_getprop_alloc(node, "compatible", 1,
-		    (void **)&compat) == -1)
-			return (ENXIO);
-
-		if (strcasecmp(compat, "gpio-leds") == 0)
-			match = 1;
-
-		OF_prop_free(compat);
-	}
-
-	if (match == 0)
-		return (ENXIO);
-#endif
 	device_set_desc(dev, "GPIO led");
 
 	return (BUS_PROBE_DEFAULT);
@@ -161,13 +99,7 @@ gpioled_attach(device_t dev)
 {
 	struct gpioled_softc *sc;
 	int state;
-#ifdef FDT
-	phandle_t node;
-	char *default_state;
-	char *name;
-#else
 	const char *name;
-#endif
 
 	sc = device_get_softc(dev);
 	sc->sc_dev = dev;
@@ -176,42 +108,14 @@ gpioled_attach(device_t dev)
 
 	state = 0;
 
-#ifdef FDT
-	if ((node = ofw_bus_get_node(dev)) == -1)
-		return (ENXIO);
-
-	if (OF_getprop_alloc(node, "default-state",
-	    sizeof(char), (void **)&default_state) != -1) {
-		if (strcasecmp(default_state, "on") == 0)
-			state = 1;
-		else if (strcasecmp(default_state, "off") == 0)
-			state = 0;
-		else if (strcasecmp(default_state, "keep") == 0)
-			state = -1;
-		else {
-			device_printf(dev,
-			    "unknown value for default-state in FDT\n");
-		}
-		OF_prop_free(default_state);
-	}
-
-	name = NULL;
-	if (OF_getprop_alloc(node, "label", 1, (void **)&name) == -1)
-		OF_getprop_alloc(node, "name", 1, (void **)&name);
-#else
 	if (resource_string_value(device_get_name(dev), 
 	    device_get_unit(dev), "name", &name))
 		name = NULL;
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "invert", &sc->sc_invert);
-#endif
 
 	sc->sc_leddev = led_create_state(gpioled_control, sc, name ? name :
 	    device_get_nameunit(dev), state);
-#ifdef FDT
-	if (name != NULL)
-		OF_prop_free(name);
-#endif
 
 	return (0);
 }
@@ -234,9 +138,6 @@ static devclass_t gpioled_devclass;
 
 static device_method_t gpioled_methods[] = {
 	/* Device interface */
-#ifdef FDT
-	DEVMETHOD(device_identify,	gpioled_identify),
-#endif
 	DEVMETHOD(device_probe,		gpioled_probe),
 	DEVMETHOD(device_attach,	gpioled_attach),
 	DEVMETHOD(device_detach,	gpioled_detach),
diff --git a/sys/dev/gpio/gpioled_fdt.c b/sys/dev/gpio/gpioled_fdt.c
new file mode 100644
index 000000000000..3c3478861dfa
--- /dev/null
+++ b/sys/dev/gpio/gpioled_fdt.c
@@ -0,0 +1,230 @@
+/*-
+ * Copyright (c) 2009 Oleksandr Tymoshenko 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "gpiobus_if.h"
+
+struct gpioled
+{
+	struct gpioleds_softc	*parent_sc;
+	gpio_pin_t		pin;
+	struct cdev		*leddev;
+};
+
+struct gpioleds_softc
+{
+	device_t	sc_dev;
+	device_t	sc_busdev;
+	struct gpioled	*sc_leds;
+	int		sc_total_leds;
+};
+
+static void gpioled_control(void *, int);
+static int gpioled_probe(device_t);
+static int gpioled_attach(device_t);
+static int gpioled_detach(device_t);
+
+static void
+gpioled_control(void *priv, int onoff)
+{
+	struct gpioled *led;
+
+	led = (struct gpioled *)priv;
+	if (led->pin)
+		gpio_pin_set_active(led->pin, onoff);
+}
+
+static void
+gpioleds_attach_led(struct gpioleds_softc *sc, phandle_t node,
+    struct gpioled *led)
+{
+	char *name;
+	int state, err;
+	char *default_state;
+
+	led->parent_sc = sc;
+
+	state = 0;
+	if (OF_getprop_alloc(node, "default-state",
+	    sizeof(char), (void **)&default_state) != -1) {
+		if (strcasecmp(default_state, "on") == 0)
+			state = 1;
+		else if (strcasecmp(default_state, "off") == 0)
+			state = 0;
+		else if (strcasecmp(default_state, "keep") == 0)
+			state = -1;
+		else {
+			state = -1;
+			device_printf(sc->sc_dev,
+			    "unknown value for default-state in FDT\n");
+		}
+		OF_prop_free(default_state);
+	}
+
+	name = NULL;
+	if (OF_getprop_alloc(node, "label", 1, (void **)&name) == -1)
+		OF_getprop_alloc(node, "name", 1, (void **)&name);
+
+	if (name == NULL) {
+		device_printf(sc->sc_dev,
+		    "no name provided for gpio LED, skipping\n");
+		return;
+	}
+
+	err = gpio_pin_get_by_ofw_idx(sc->sc_dev, node, 0, &led->pin);
+	if (err) {
+		device_printf(sc->sc_dev, "<%s> failed to map pin\n", name);
+		if (name)
+			OF_prop_free(name);
+		return;
+	}
+	gpio_pin_setflags(led->pin, GPIO_PIN_OUTPUT);
+
+	led->leddev = led_create_state(gpioled_control, led, name,
+	    state);
+
+	if (name != NULL)
+		OF_prop_free(name);
+}
+
+static void
+gpioleds_detach_led(struct gpioled *led)
+{
+
+	if (led->leddev != NULL)
+		led_destroy(led->leddev);
+
+	if (led->pin)
+		gpio_pin_release(led->pin);
+}
+
+static int
+gpioled_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev, "gpio-leds"))
+		return (ENXIO);
+
+	device_set_desc(dev, "GPIO LEDs");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+gpioled_attach(device_t dev)
+{
+	struct gpioleds_softc *sc;
+	phandle_t child, leds;
+	int total_leds;
+
+	if ((leds = ofw_bus_get_node(dev)) == -1)
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_busdev = device_get_parent(dev);
+
+	/* Traverse the 'gpio-leds' node and count leds */
+	total_leds = 0;
+	for (child = OF_child(leds); child != 0; child = OF_peer(child)) {
+		if (!OF_hasprop(child, "gpios"))
+			continue;
+		total_leds++;
+	}
+
+	if (total_leds) {
+		sc->sc_leds =  malloc(sizeof(struct gpioled) * total_leds,
+		    M_DEVBUF, M_WAITOK | M_ZERO);
+
+		sc->sc_total_leds = 0;
+		/* Traverse the 'gpio-leds' node and count leds */
+		for (child = OF_child(leds); child != 0; child = OF_peer(child)) {
+			if (!OF_hasprop(child, "gpios"))
+				continue;
+			gpioleds_attach_led(sc, child, &sc->sc_leds[sc->sc_total_leds]);
+			sc->sc_total_leds++;
+		}
+	}
+
+	return (0);
+}
+
+static int
+gpioled_detach(device_t dev)
+{
+	struct gpioleds_softc *sc;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	for (i = 0; i < sc->sc_total_leds; i++)
+		gpioleds_detach_led(&sc->sc_leds[i]);
+
+	if (sc->sc_leds)
+		free(sc->sc_leds, M_DEVBUF);
+
+	return (0);
+}
+
+static devclass_t gpioled_devclass;
+
+static device_method_t gpioled_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		gpioled_probe),
+	DEVMETHOD(device_attach,	gpioled_attach),
+	DEVMETHOD(device_detach,	gpioled_detach),
+
+	DEVMETHOD_END
+};
+
+static driver_t gpioled_driver = {
+	"gpioled",
+	gpioled_methods,
+	sizeof(struct gpioleds_softc),
+};
+
+DRIVER_MODULE(gpioled, ofwbus, gpioled_driver, gpioled_devclass, 0, 0);
+DRIVER_MODULE(gpioled, simplebus, gpioled_driver, gpioled_devclass, 0, 0);
+MODULE_DEPEND(gpioled, gpiobus, 1, 1, 1);
diff --git a/sys/modules/gpio/gpioled/Makefile b/sys/modules/gpio/gpioled/Makefile
index c50d269b5001..4c70a1fcf520 100644
--- a/sys/modules/gpio/gpioled/Makefile
+++ b/sys/modules/gpio/gpioled/Makefile
@@ -32,7 +32,11 @@
 .PATH:	${.CURDIR}/../../../dev/gpio/
 
 KMOD=	gpioled
+.if !empty(OPT_FDT)
+SRCS=	gpioled_fdt.c
+.else
 SRCS=	gpioled.c
+.endif
 SRCS+=	device_if.h bus_if.h gpio_if.h gpiobus_if.h opt_platform.h ofw_bus_if.h
 
 CFLAGS+=  -I. -I${.CURDIR}/../../../dev/gpio/

From 525e07418c7788fbf9ab63919a0eba57fbbb1d4e Mon Sep 17 00:00:00 2001
From: Sean Bruno 
Date: Mon, 7 Nov 2016 22:24:37 +0000
Subject: [PATCH 091/127] The igb driver currently requires a VF interface to
 have a non-zero MAC address, but the associated PF is giving the VF an all
 zeros MAC address when one is not administratively assigned. The driver
 should check for this case and generate a random address, similar to how the
 linux igbvf driver does.

Submitted by:	skoumjian@juniper.net (Scott Koumjian)
MFH:		2 weeks
Differential Revision:	https://reviews.freebsd.org/D8399
---
 sys/dev/e1000/if_igb.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 8e018995029e..3c9644d9b03b 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -590,11 +590,20 @@ igb_attach(device_t dev)
 		error = EIO;
 		goto err_late;
 	}
-	/* Check its sanity */
-	if (!igb_is_valid_ether_addr(adapter->hw.mac.addr)) {
-		device_printf(dev, "Invalid MAC address\n");
-		error = EIO;
-		goto err_late;
+
+ 	/* Check its sanity */
+ 	if (!igb_is_valid_ether_addr(adapter->hw.mac.addr)) {
+		if (adapter->vf_ifp) {
+			u8 addr[ETHER_ADDR_LEN];
+			arc4rand(&addr, sizeof(addr), 0);
+			addr[0] &= 0xFE;
+			addr[0] |= 0x02;
+			bcopy(addr, adapter->hw.mac.addr, sizeof(addr));
+		} else {
+			device_printf(dev, "Invalid MAC address\n");
+			error = EIO;
+			goto err_late;
+		}
 	}
 
 	/* Setup OS specific network interface */

From adb25d1e1a6237dcd294686bdba6b31015ff33b6 Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Mon, 7 Nov 2016 22:41:52 +0000
Subject: [PATCH 092/127] libelftc: add elf{32,64}-tradbigmips target emulation
 names

Reported by:	theraven
Sponsored by:	The FreeBSD Foundation
---
 .../libelftc/elftc_bfd_find_target.3             |  2 ++
 .../elftoolchain/libelftc/libelftc_bfdtarget.c   | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
index 2e4dbaac8362..15e02d2d58cd 100644
--- a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
+++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
@@ -82,6 +82,7 @@ Known descriptor names and their properties include:
 .It Li elf32-shbig-linux Ta ELF Ta MSB Ta 32
 .It Li elf32-shl-linux Ta ELF Ta LSB Ta 32
 .It Li elf32-sparc Ta ELF Ta MSB Ta 32
+.It Li elf32-tradbigmips Ta ELF Ta MSB Ta 32
 .It Li elf64-alpha Ta ELF Ta LSB Ta 64
 .It Li elf64-alpha-freebsd Ta ELF Ta LSB Ta 64
 .It Li elf64-big Ta ELF Ta MSB Ta 64
@@ -101,6 +102,7 @@ Known descriptor names and their properties include:
 .It Li elf64-sh64-linux Ta ELF Ta LSB Ta 64
 .It Li elf64-sparc Ta ELF Ta MSB Ta 64
 .It Li elf64-sparc-freebsd Ta ELF Ta MSB Ta 64
+.It Li elf64-tradbigmips Ta ELF Ta MSB Ta 64
 .It Li elf64-x86-64 Ta ELF Ta LSB Ta 64
 .It Li elf64-x86-64-freebsd Ta ELF Ta LSB Ta 64
 .It Li ihex Ta IHEX Ta - Ta -
diff --git a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
index d87d4d8b445d..b7e0d625bdf5 100644
--- a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
+++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
@@ -194,6 +194,14 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = {
 		.bt_machine   = EM_SPARC,
 	},
 
+	{
+		.bt_name      = "elf32-tradbigmips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_MIPS,
+	},
+
 	{
 		.bt_name      = "elf64-alpha",
 		.bt_type      = ETF_ELF,
@@ -350,6 +358,14 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = {
 		.bt_osabi     = ELFOSABI_FREEBSD
 	},
 
+	{
+		.bt_name      = "elf64-tradbigmips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_MIPS,
+	},
+
 	{
 		.bt_name      = "elf64-x86-64",
 		.bt_type      = ETF_ELF,

From a965389b5a77dc64dd8ddc3c4340eed16698f4fd Mon Sep 17 00:00:00 2001
From: Scott Long 
Date: Tue, 8 Nov 2016 00:24:49 +0000
Subject: [PATCH 093/127] Convert the Q-Pair and PRP list memory allocations to
 use BUSDMA.  Add a bunch of safery belts and error handling in related
 codepaths.

Reviewed by:	jimharris
Obtained from:	Netflix
Differential Revision:	D8453
---
 sys/dev/nvme/nvme_ctrlr.c   |  25 +++---
 sys/dev/nvme/nvme_private.h |   9 +--
 sys/dev/nvme/nvme_qpair.c   | 154 +++++++++++++++++++++---------------
 3 files changed, 109 insertions(+), 79 deletions(-)

diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index fa889eb21a79..11ab016ba252 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -80,11 +80,12 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr)
 	return (0);
 }
 
-static void
+static int
 nvme_ctrlr_construct_admin_qpair(struct nvme_controller *ctrlr)
 {
 	struct nvme_qpair	*qpair;
 	uint32_t		num_entries;
+	int			error;
 
 	qpair = &ctrlr->adminq;
 
@@ -105,12 +106,13 @@ nvme_ctrlr_construct_admin_qpair(struct nvme_controller *ctrlr)
 	 * The admin queue's max xfer size is treated differently than the
 	 *  max I/O xfer size.  16KB is sufficient here - maybe even less?
 	 */
-	nvme_qpair_construct(qpair, 
-			     0, /* qpair ID */
-			     0, /* vector */
-			     num_entries,
-			     NVME_ADMIN_TRACKERS,
-			     ctrlr);
+	error = nvme_qpair_construct(qpair, 
+				     0, /* qpair ID */
+				     0, /* vector */
+				     num_entries,
+				     NVME_ADMIN_TRACKERS,
+				     ctrlr);
+	return (error);
 }
 
 static int
@@ -118,7 +120,7 @@ nvme_ctrlr_construct_io_qpairs(struct nvme_controller *ctrlr)
 {
 	struct nvme_qpair	*qpair;
 	union cap_lo_register	cap_lo;
-	int			i, num_entries, num_trackers;
+	int			i, error, num_entries, num_trackers;
 
 	num_entries = NVME_IO_ENTRIES;
 	TUNABLE_INT_FETCH("hw.nvme.io_entries", &num_entries);
@@ -163,12 +165,14 @@ nvme_ctrlr_construct_io_qpairs(struct nvme_controller *ctrlr)
 		 * For I/O queues, use the controller-wide max_xfer_size
 		 *  calculated in nvme_attach().
 		 */
-		nvme_qpair_construct(qpair,
+		error = nvme_qpair_construct(qpair,
 				     i+1, /* qpair ID */
 				     ctrlr->msix_enabled ? i+1 : 0, /* vector */
 				     num_entries,
 				     num_trackers,
 				     ctrlr);
+		if (error)
+			return (error);
 
 		/*
 		 * Do not bother binding interrupts if we only have one I/O
@@ -1098,7 +1102,8 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
 	nvme_ctrlr_setup_interrupts(ctrlr);
 
 	ctrlr->max_xfer_size = NVME_MAX_XFER_SIZE;
-	nvme_ctrlr_construct_admin_qpair(ctrlr);
+	if (nvme_ctrlr_construct_admin_qpair(ctrlr) != 0)
+		return (ENXIO);
 
 	ctrlr->cdev = make_dev(&nvme_ctrlr_cdevsw, device_get_unit(dev),
 	    UID_ROOT, GID_WHEEL, 0600, "nvme%d", device_get_unit(dev));
diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h
index bcd2c6a393c9..4930c678630b 100644
--- a/sys/dev/nvme/nvme_private.h
+++ b/sys/dev/nvme/nvme_private.h
@@ -172,9 +172,8 @@ struct nvme_tracker {
 	bus_dmamap_t			payload_dma_map;
 	uint16_t			cid;
 
-	uint64_t			prp[NVME_MAX_PRP_LIST_ENTRIES];
+	uint64_t			*prp;
 	bus_addr_t			prp_bus_addr;
-	bus_dmamap_t			prp_dma_map;
 };
 
 struct nvme_qpair {
@@ -206,10 +205,8 @@ struct nvme_qpair {
 	bus_dma_tag_t		dma_tag;
 	bus_dma_tag_t		dma_tag_payload;
 
-	bus_dmamap_t		cmd_dma_map;
+	bus_dmamap_t		queuemem_map;
 	uint64_t		cmd_bus_addr;
-
-	bus_dmamap_t		cpl_dma_map;
 	uint64_t		cpl_bus_addr;
 
 	TAILQ_HEAD(, nvme_tracker)	free_tr;
@@ -417,7 +414,7 @@ void	nvme_ctrlr_submit_io_request(struct nvme_controller *ctrlr,
 void	nvme_ctrlr_post_failed_request(struct nvme_controller *ctrlr,
 				       struct nvme_request *req);
 
-void	nvme_qpair_construct(struct nvme_qpair *qpair, uint32_t id,
+int	nvme_qpair_construct(struct nvme_qpair *qpair, uint32_t id,
 			     uint16_t vector, uint32_t num_entries,
 			     uint32_t num_trackers,
 			     struct nvme_controller *ctrlr);
diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c
index 92fe6722e4f4..d7d4c74ade4d 100644
--- a/sys/dev/nvme/nvme_qpair.c
+++ b/sys/dev/nvme/nvme_qpair.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 
 static void	_nvme_qpair_submit_request(struct nvme_qpair *qpair,
 					   struct nvme_request *req);
+static void	nvme_qpair_destroy(struct nvme_qpair *qpair);
 
 struct nvme_opcode_string {
 
@@ -289,22 +290,6 @@ nvme_completion_is_retry(const struct nvme_completion *cpl)
 	}
 }
 
-static void
-nvme_qpair_construct_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr,
-    uint16_t cid)
-{
-
-	bus_dmamap_create(qpair->dma_tag_payload, 0, &tr->payload_dma_map);
-	bus_dmamap_create(qpair->dma_tag, 0, &tr->prp_dma_map);
-
-	bus_dmamap_load(qpair->dma_tag, tr->prp_dma_map, tr->prp,
-	    sizeof(tr->prp), nvme_single_map, &tr->prp_bus_addr, 0);
-
-	callout_init(&tr->timer, 1);
-	tr->cid = cid;
-	tr->qpair = qpair;
-}
-
 static void
 nvme_qpair_complete_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr,
     struct nvme_completion *cpl, boolean_t print_on_error)
@@ -457,14 +442,16 @@ nvme_qpair_msix_handler(void *arg)
 	nvme_qpair_process_completions(qpair);
 }
 
-void
+int
 nvme_qpair_construct(struct nvme_qpair *qpair, uint32_t id,
     uint16_t vector, uint32_t num_entries, uint32_t num_trackers,
     struct nvme_controller *ctrlr)
 {
 	struct nvme_tracker	*tr;
-	uint32_t		i;
-	int			err;
+	size_t			cmdsz, cplsz, prpsz, allocsz, prpmemsz;
+	uint64_t		queuemem_phys, prpmem_phys, list_phys;
+	uint8_t			*queuemem, *prpmem, *prp_list;
+	int			i, err;
 
 	qpair->id = id;
 	qpair->vector = vector;
@@ -495,40 +482,51 @@ nvme_qpair_construct(struct nvme_qpair *qpair, uint32_t id,
 	    BUS_SPACE_MAXADDR, NULL, NULL, NVME_MAX_XFER_SIZE,
 	    (NVME_MAX_XFER_SIZE/PAGE_SIZE)+1, PAGE_SIZE, 0,
 	    NULL, NULL, &qpair->dma_tag_payload);
-	if (err != 0)
+	if (err != 0) {
 		nvme_printf(ctrlr, "payload tag create failed %d\n", err);
+		goto out;
+	}
+
+	/*
+	 * Each component must be page aligned, and individual PRP lists
+	 * cannot cross a page boundary.
+	 */
+	cmdsz = qpair->num_entries * sizeof(struct nvme_command);
+	cmdsz = roundup2(cmdsz, PAGE_SIZE);
+	cplsz = qpair->num_entries * sizeof(struct nvme_completion);
+	cplsz = roundup2(cplsz, PAGE_SIZE);
+	prpsz = sizeof(uint64_t) * NVME_MAX_PRP_LIST_ENTRIES;;
+	prpmemsz = qpair->num_trackers * prpsz;
+	allocsz = cmdsz + cplsz + prpmemsz;
 
 	err = bus_dma_tag_create(bus_get_dma_tag(ctrlr->dev),
-	    4, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
-	    BUS_SPACE_MAXSIZE, 1, BUS_SPACE_MAXSIZE, 0,
-	    NULL, NULL, &qpair->dma_tag);
-	if (err != 0)
+	    PAGE_SIZE, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    allocsz, 1, allocsz, 0, NULL, NULL, &qpair->dma_tag);
+	if (err != 0) {
 		nvme_printf(ctrlr, "tag create failed %d\n", err);
+		goto out;
+	}
+
+	if (bus_dmamem_alloc(qpair->dma_tag, (void **)&queuemem,
+	    BUS_DMA_NOWAIT, &qpair->queuemem_map)) {
+		nvme_printf(ctrlr, "failed to alloc qpair memory\n");
+		goto out;
+	}
+
+	if (bus_dmamap_load(qpair->dma_tag, qpair->queuemem_map,
+	    queuemem, allocsz, nvme_single_map, &queuemem_phys, 0) != 0) {
+		nvme_printf(ctrlr, "failed to load qpair memory\n");
+		goto out;
+	}
 
 	qpair->num_cmds = 0;
 	qpair->num_intr_handler_calls = 0;
-
-	qpair->cmd = contigmalloc(qpair->num_entries *
-	    sizeof(struct nvme_command), M_NVME, M_ZERO,
-	    0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
-	qpair->cpl = contigmalloc(qpair->num_entries *
-	    sizeof(struct nvme_completion), M_NVME, M_ZERO,
-	    0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
-
-	err = bus_dmamap_create(qpair->dma_tag, 0, &qpair->cmd_dma_map);
-	if (err != 0)
-		nvme_printf(ctrlr, "cmd_dma_map create failed %d\n", err);
-
-	err = bus_dmamap_create(qpair->dma_tag, 0, &qpair->cpl_dma_map);
-	if (err != 0)
-		nvme_printf(ctrlr, "cpl_dma_map create failed %d\n", err);
-
-	bus_dmamap_load(qpair->dma_tag, qpair->cmd_dma_map,
-	    qpair->cmd, qpair->num_entries * sizeof(struct nvme_command),
-	    nvme_single_map, &qpair->cmd_bus_addr, 0);
-	bus_dmamap_load(qpair->dma_tag, qpair->cpl_dma_map,
-	    qpair->cpl, qpair->num_entries * sizeof(struct nvme_completion),
-	    nvme_single_map, &qpair->cpl_bus_addr, 0);
+	qpair->cmd = (struct nvme_command *)queuemem;
+	qpair->cpl = (struct nvme_completion *)(queuemem + cmdsz);
+	prpmem = (uint8_t *)(queuemem + cmdsz + cplsz);
+	qpair->cmd_bus_addr = queuemem_phys;
+	qpair->cpl_bus_addr = queuemem_phys + cmdsz;
+	prpmem_phys = queuemem_phys + cmdsz + cplsz;
 
 	qpair->sq_tdbl_off = nvme_mmio_offsetof(doorbell[id].sq_tdbl);
 	qpair->cq_hdbl_off = nvme_mmio_offsetof(doorbell[id].cq_hdbl);
@@ -537,14 +535,51 @@ nvme_qpair_construct(struct nvme_qpair *qpair, uint32_t id,
 	TAILQ_INIT(&qpair->outstanding_tr);
 	STAILQ_INIT(&qpair->queued_req);
 
+	list_phys = prpmem_phys;
+	prp_list = prpmem;
 	for (i = 0; i < qpair->num_trackers; i++) {
+
+		if (list_phys + prpsz > prpmem_phys + prpmemsz) {
+			qpair->num_trackers = i;
+			break;
+		}
+
+		/*
+		 * Make sure that the PRP list for this tracker doesn't
+		 * overflow to another page.
+		 */
+		if (trunc_page(list_phys) !=
+		    trunc_page(list_phys + prpsz - 1)) {
+			list_phys = roundup2(list_phys, PAGE_SIZE);
+			prp_list =
+			    (uint8_t *)roundup2((uintptr_t)prp_list, PAGE_SIZE);
+		}
+
 		tr = malloc(sizeof(*tr), M_NVME, M_ZERO | M_WAITOK);
-		nvme_qpair_construct_tracker(qpair, tr, i);
+		bus_dmamap_create(qpair->dma_tag_payload, 0,
+		    &tr->payload_dma_map);
+		callout_init(&tr->timer, 1);
+		tr->cid = i;
+		tr->qpair = qpair;
+		tr->prp = (uint64_t *)prp_list;
+		tr->prp_bus_addr = list_phys;
 		TAILQ_INSERT_HEAD(&qpair->free_tr, tr, tailq);
+		list_phys += prpsz;
+		prp_list += prpsz;
 	}
 
-	qpair->act_tr = malloc(sizeof(struct nvme_tracker *) * qpair->num_entries,
-	    M_NVME, M_ZERO | M_WAITOK);
+	if (qpair->num_trackers == 0) {
+		nvme_printf(ctrlr, "failed to allocate enough trackers\n");
+		goto out;
+	}
+
+	qpair->act_tr = malloc(sizeof(struct nvme_tracker *) *
+	    qpair->num_entries, M_NVME, M_ZERO | M_WAITOK);
+	return (0);
+
+out:
+	nvme_qpair_destroy(qpair);
+	return (ENOMEM);
 }
 
 static void
@@ -555,23 +590,17 @@ nvme_qpair_destroy(struct nvme_qpair *qpair)
 	if (qpair->tag)
 		bus_teardown_intr(qpair->ctrlr->dev, qpair->res, qpair->tag);
 
+	if (mtx_initialized(&qpair->lock))
+		mtx_destroy(&qpair->lock);
+
 	if (qpair->res)
 		bus_release_resource(qpair->ctrlr->dev, SYS_RES_IRQ,
 		    rman_get_rid(qpair->res), qpair->res);
 
-	if (qpair->cmd) {
-		bus_dmamap_unload(qpair->dma_tag, qpair->cmd_dma_map);
-		bus_dmamap_destroy(qpair->dma_tag, qpair->cmd_dma_map);
-		contigfree(qpair->cmd,
-		    qpair->num_entries * sizeof(struct nvme_command), M_NVME);
-	}
-
-	if (qpair->cpl) {
-		bus_dmamap_unload(qpair->dma_tag, qpair->cpl_dma_map);
-		bus_dmamap_destroy(qpair->dma_tag, qpair->cpl_dma_map);
-		contigfree(qpair->cpl,
-		    qpair->num_entries * sizeof(struct nvme_completion),
-		    M_NVME);
+	if (qpair->cmd != NULL) {
+		bus_dmamap_unload(qpair->dma_tag, qpair->queuemem_map);
+		bus_dmamem_free(qpair->dma_tag, qpair->cmd,
+		    qpair->queuemem_map);
 	}
 
 	if (qpair->dma_tag)
@@ -587,7 +616,6 @@ nvme_qpair_destroy(struct nvme_qpair *qpair)
 		tr = TAILQ_FIRST(&qpair->free_tr);
 		TAILQ_REMOVE(&qpair->free_tr, tr, tailq);
 		bus_dmamap_destroy(qpair->dma_tag, tr->payload_dma_map);
-		bus_dmamap_destroy(qpair->dma_tag, tr->prp_dma_map);
 		free(tr, M_NVME);
 	}
 }

From cd1693d3f953314178bc9c1ad75283ed29dc26ba Mon Sep 17 00:00:00 2001
From: Conrad Meyer 
Date: Tue, 8 Nov 2016 05:31:01 +0000
Subject: [PATCH 094/127] Capsicumize some trivial stdio programs

Trivially capsicumize some simple programs that just interact with
stdio.  This list of programs uses 'pledge("stdio")' in OpenBSD.

No objection from:	allanjude, emaste, oshogbo
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D8307
---
 bin/echo/echo.c                       |  5 +++++
 bin/sleep/sleep.c                     |  4 ++++
 usr.bin/basename/basename.c           |  4 ++++
 usr.bin/dc/dc.c                       | 26 +++++++++++++++++++++-----
 usr.bin/dirname/dirname.c             |  4 ++++
 usr.bin/fold/fold.c                   |  4 ++++
 usr.bin/getopt/getopt.c               |  6 ++++++
 usr.bin/locate/bigram/locate.bigram.c |  6 ++++++
 usr.bin/logname/logname.c             |  4 ++++
 usr.bin/printenv/printenv.c           |  5 +++++
 usr.bin/yes/yes.c                     |  5 +++++
 11 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/bin/echo/echo.c b/bin/echo/echo.c
index 68ff581f8475..e40a2a3071a0 100644
--- a/bin/echo/echo.c
+++ b/bin/echo/echo.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -78,6 +80,9 @@ main(int argc, char *argv[])
 	char newline[] = "\n";
 	char *progname = argv[0];
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	/* This utility may NOT do getopt(3) option parsing. */
 	if (*++argv && !strcmp(*argv, "-n")) {
 		++argv;
diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c
index ca082723fbe1..7a991254ec9a 100644
--- a/bin/sleep/sleep.c
+++ b/bin/sleep/sleep.c
@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)sleep.c	8.3 (Berkeley) 4/2/94";
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
 #include 
@@ -69,6 +70,9 @@ main(int argc, char *argv[])
 	time_t original;
 	char buf[2];
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	if (argc != 2)
 		usage();
 
diff --git a/usr.bin/basename/basename.c b/usr.bin/basename/basename.c
index 4c1023f0113d..e82dec55bc5c 100644
--- a/usr.bin/basename/basename.c
+++ b/usr.bin/basename/basename.c
@@ -42,6 +42,7 @@ static char sccsid[] = "@(#)basename.c	8.4 (Berkeley) 5/4/95";
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
 #include 
@@ -64,6 +65,9 @@ main(int argc, char **argv)
 
 	setlocale(LC_ALL, "");
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	aflag = 0;
 	suffix = NULL;
 	suffixlen = 0;
diff --git a/usr.bin/dc/dc.c b/usr.bin/dc/dc.c
index 546b24706eee..8f2cf51fb3bd 100644
--- a/usr.bin/dc/dc.c
+++ b/usr.bin/dc/dc.c
@@ -22,9 +22,11 @@ __FBSDID("$FreeBSD$");
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -58,11 +60,11 @@ usage(void)
 }
 
 static void
-procfile(char *fname) {
+procfd(int fd, char *fname) {
 	struct stat st;
 	FILE *file;
 
-	file = fopen(fname, "r");
+	file = fdopen(fd, "r");
 	if (file == NULL)
 		err(1, "cannot open file %s", fname);
 	if (fstat(fileno(file), &st) == -1)
@@ -80,7 +82,7 @@ procfile(char *fname) {
 int
 main(int argc, char *argv[])
 {
-	int ch;
+	int ch, fd;
 	bool extended_regs = false, preproc_done = false;
 
 	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
@@ -97,7 +99,10 @@ main(int argc, char *argv[])
 		case 'f':
 			if (!preproc_done)
 				init_bmachine(extended_regs);
-			procfile(optarg);
+			fd = open(optarg, O_RDONLY);
+			if (fd < 0)
+				err(1, "cannot open file %s", optarg);
+			procfd(fd, optarg);
 			preproc_done = true;
 			break;
 		case 'x':
@@ -126,12 +131,23 @@ main(int argc, char *argv[])
 	if (argc > 1)
 		usage();
 	if (argc == 1) {
-		procfile(argv[0]);
+		fd = open(argv[0], O_RDONLY);
+		if (fd < 0)
+			err(1, "cannot open file %s", argv[0]);
+
+		if (caph_limit_stream(fd, CAPH_READ) < 0 ||
+		    caph_limit_stdio() < 0 ||
+		    (cap_enter() < 0 && errno != ENOSYS))
+			err(1, "capsicum");
+
+		procfd(fd, argv[0]);
 		preproc_done = true;
 	}
 	if (preproc_done)
 		return (0);
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
 	src_setstream(&src, stdin);
 	reset_bmachine(&src);
 	eval();
diff --git a/usr.bin/dirname/dirname.c b/usr.bin/dirname/dirname.c
index c176995cc1c3..0036c60f4228 100644
--- a/usr.bin/dirname/dirname.c
+++ b/usr.bin/dirname/dirname.c
@@ -39,6 +39,7 @@ static const char sccsid[] = "@(#)dirname.c	8.4 (Berkeley) 5/4/95";
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
 #include 
@@ -53,6 +54,9 @@ main(int argc, char **argv)
 	char *p;
 	int ch;
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	while ((ch = getopt(argc, argv, "")) != -1)
 		switch(ch) {
 		case '?':
diff --git a/usr.bin/fold/fold.c b/usr.bin/fold/fold.c
index 1ce9b5eb3a92..7eedfe252c0a 100644
--- a/usr.bin/fold/fold.c
+++ b/usr.bin/fold/fold.c
@@ -45,6 +45,7 @@ static char sccsid[] = "@(#)fold.c	8.1 (Berkeley) 6/6/93";
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
 #include 
@@ -72,6 +73,9 @@ main(int argc, char **argv)
 
 	(void) setlocale(LC_CTYPE, "");
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	width = -1;
 	previous_ch = 0;
 	while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) {
diff --git a/usr.bin/getopt/getopt.c b/usr.bin/getopt/getopt.c
index d1671a71e5ee..3f55a34f6d50 100644
--- a/usr.bin/getopt/getopt.c
+++ b/usr.bin/getopt/getopt.c
@@ -6,6 +6,9 @@ __FBSDID("$FreeBSD$");
  * into the public domain and is thus not subject to any copyright.
  */
 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -16,6 +19,9 @@ main(int argc, char *argv[])
 	int c;
 	int status = 0;
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	optind = 2;	/* Past the program name and the option letters. */
 	while ((c = getopt(argc, argv, argv[1])) != -1)
 		switch (c) {
diff --git a/usr.bin/locate/bigram/locate.bigram.c b/usr.bin/locate/bigram/locate.bigram.c
index 6fa2d3112928..90111e7e2516 100644
--- a/usr.bin/locate/bigram/locate.bigram.c
+++ b/usr.bin/locate/bigram/locate.bigram.c
@@ -57,6 +57,9 @@ static char sccsid[] = "@(#)locate.bigram.c	8.1 (Berkeley) 6/6/93";
  * Use 'code' to encode a file using this output.
  */
 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 			/* for MAXPATHLEN */
@@ -73,6 +76,9 @@ main(void)
 	u_char *oldpath = buf1, *path = buf2;
 	u_int i, j;
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
      	while (fgets(path, sizeof(buf2), stdin) != NULL) {
 
 		/* 
diff --git a/usr.bin/logname/logname.c b/usr.bin/logname/logname.c
index 8a251ae4b6d5..05aa881e1b40 100644
--- a/usr.bin/logname/logname.c
+++ b/usr.bin/logname/logname.c
@@ -39,6 +39,7 @@ static const char sccsid[] = "@(#)logname.c	8.2 (Berkeley) 4/3/94";
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
 #include 
@@ -51,6 +52,9 @@ main(int argc, char *argv[] __unused)
 {
 	char *p;
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	if (argc != 1)
 		usage();
 	if ((p = getlogin()) == NULL)
diff --git a/usr.bin/printenv/printenv.c b/usr.bin/printenv/printenv.c
index 27882ab91ce3..4ca91ec66dc5 100644
--- a/usr.bin/printenv/printenv.c
+++ b/usr.bin/printenv/printenv.c
@@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$");
 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -65,6 +67,9 @@ main(int argc, char *argv[])
 	size_t len;
 	int ch;
 
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	while ((ch = getopt(argc, argv, "")) != -1)
 		switch(ch) {
 		case '?':
diff --git a/usr.bin/yes/yes.c b/usr.bin/yes/yes.c
index ef98b4ded12d..2336d3f2c688 100644
--- a/usr.bin/yes/yes.c
+++ b/usr.bin/yes/yes.c
@@ -41,12 +41,17 @@ static const char rcsid[] = "$FreeBSD$";
 #endif
 #endif /* not lint */
 
+#include 
 #include 
 #include 
 
 int
 main(int argc, char **argv)
 {
+
+	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
+		err(1, "capsicum");
+
 	if (argc > 1)
 		while (puts(argv[1]) != EOF)
 			;

From cbd6713146d14bb506626d8add767771f9cbfb97 Mon Sep 17 00:00:00 2001
From: Toomas Soome 
Date: Tue, 8 Nov 2016 06:50:18 +0000
Subject: [PATCH 095/127] Loader paged/pageable data is not always paged.

This change does modify devsw dv_print() to return the int value,
enabling walkers to interrupt the walk on non zero value from dv_print().

This will allow the pager_print actually to stop displaying data on
user input, and additionally pager is used in various *dev_print callbacks,
where it was missing.

For test, lsdev [-v] command should display data by screenfuls and should
stop when the key 'q' is pressed on pager prompt.

Reviewed by:	allanjude
Approved by:	allanjude (mentor)
Differential Revision:	https://reviews.freebsd.org/D5461
---
 lib/libstand/stand.h                         |  2 +-
 sys/boot/common/dev_net.c                    | 12 ++--
 sys/boot/common/module.c                     | 18 +++--
 sys/boot/common/part.c                       |  8 +--
 sys/boot/common/util.c                       |  3 +-
 sys/boot/common/util.h                       |  2 +-
 sys/boot/efi/libefi/efinet.c                 | 11 ++--
 sys/boot/efi/libefi/efipart.c                | 21 +++---
 sys/boot/efi/loader/main.c                   | 31 +++++++--
 sys/boot/i386/libfirewire/firewire.c         | 13 ++--
 sys/boot/i386/libi386/bioscd.c               | 13 ++--
 sys/boot/i386/libi386/biosdisk.c             | 20 +++---
 sys/boot/i386/libi386/pxe.c                  | 16 +++--
 sys/boot/mips/beri/loader/beri_disk_cfi.c    | 16 +++--
 sys/boot/mips/beri/loader/beri_disk_sdcard.c | 14 ++--
 sys/boot/ofw/libofw/ofw_disk.c               |  6 +-
 sys/boot/pc98/libpc98/bioscd.c               | 11 ++--
 sys/boot/pc98/libpc98/biosdisk.c             | 29 ++++----
 sys/boot/powerpc/kboot/hostdisk.c            |  6 +-
 sys/boot/powerpc/ps3/ps3cdrom.c              |  5 +-
 sys/boot/powerpc/ps3/ps3disk.c               |  5 +-
 sys/boot/uboot/lib/disk.c                    | 17 ++---
 sys/boot/usb/storage/umass_loader.c          | 11 ++--
 sys/boot/userboot/userboot/host.c            |  6 +-
 sys/boot/userboot/userboot/userboot_disk.c   | 20 ++++--
 sys/boot/zfs/zfs.c                           | 13 ++--
 sys/boot/zfs/zfsimpl.c                       | 69 ++++++++++++++------
 27 files changed, 244 insertions(+), 154 deletions(-)

diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h
index 238f9edad7d1..f77a586fb069 100644
--- a/lib/libstand/stand.h
+++ b/lib/libstand/stand.h
@@ -143,7 +143,7 @@ struct devsw {
     int		(*dv_open)(struct open_file *f, ...);
     int		(*dv_close)(struct open_file *f);
     int		(*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
-    void	(*dv_print)(int verbose);	/* print device information */
+    int		(*dv_print)(int verbose);	/* print device information */
     void	(*dv_cleanup)(void);
 };
 
diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c
index fddb17eefb28..7b178af01902 100644
--- a/sys/boot/common/dev_net.c
+++ b/sys/boot/common/dev_net.c
@@ -80,7 +80,7 @@ static int	net_open(struct open_file *, ...);
 static int	net_close(struct open_file *);
 static void	net_cleanup(void);
 static int	net_strategy();
-static void	net_print(int);
+static int	net_print(int);
 
 static int net_getparams(int sock);
 
@@ -325,23 +325,27 @@ net_getparams(int sock)
 	return (0);
 }
 
-static void
+static int
 net_print(int verbose)
 {
 	struct netif_driver *drv;
 	int i, d, cnt;
+	int ret = 0;
 
 	cnt = 0;
 	for (d = 0; netif_drivers[d]; d++) {
 		drv = netif_drivers[d];
 		for (i = 0; i < drv->netif_nifs; i++) {
 			printf("\t%s%d:", "net", cnt++);
-			if (verbose)
+			if (verbose) {
 				printf(" (%s%d)", drv->netif_bname,
 				    drv->netif_ifs[i].dif_unit);
+			}
+			if ((ret = pager_output("\n")) != 0)
+				return (ret);
 		}
 	}
-	printf("\n");
+	return (ret);
 }
 
 /*
diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c
index e1975ffc9fe1..ce232b690da1 100644
--- a/sys/boot/common/module.c
+++ b/sys/boot/common/module.c
@@ -254,7 +254,7 @@ command_lsmod(int argc, char *argv[])
     struct kernel_module	*mp;
     struct file_metadata	*md;
     char			lbuf[80];
-    int				ch, verbose;
+    int				ch, verbose, ret = 0;
 
     verbose = 0;
     optind = 1;
@@ -273,11 +273,13 @@ command_lsmod(int argc, char *argv[])
 
     pager_open();
     for (fp = preloaded_files; fp; fp = fp->f_next) {
-	sprintf(lbuf, " %p: ", (void *) fp->f_addr);
+	snprintf(lbuf, sizeof(lbuf), " %p: ", (void *) fp->f_addr);
 	pager_output(lbuf);
 	pager_output(fp->f_name);
-	sprintf(lbuf, " (%s, 0x%lx)\n", fp->f_type, (long)fp->f_size);
-	pager_output(lbuf);
+	snprintf(lbuf, sizeof(lbuf), " (%s, 0x%lx)\n", fp->f_type,
+	    (long)fp->f_size);
+	if (pager_output(lbuf))
+	    break;
 	if (fp->f_args != NULL) {
 	    pager_output("    args: ");
 	    pager_output(fp->f_args);
@@ -287,7 +289,8 @@ command_lsmod(int argc, char *argv[])
 	if (fp->f_modules) {
 	    pager_output("  modules: ");
 	    for (mp = fp->f_modules; mp; mp = mp->m_next) {
-		sprintf(lbuf, "%s.%d ", mp->m_name, mp->m_version);
+		snprintf(lbuf, sizeof(lbuf), "%s.%d ", mp->m_name,
+		    mp->m_version);
 		pager_output(lbuf);
 	    }
 	    if (pager_output("\n"))
@@ -296,11 +299,14 @@ command_lsmod(int argc, char *argv[])
 	if (verbose) {
 	    /* XXX could add some formatting smarts here to display some better */
 	    for (md = fp->f_metadata; md != NULL; md = md->md_next) {
-		sprintf(lbuf, "      0x%04x, 0x%lx\n", md->md_type, (long) md->md_size);
+		snprintf(lbuf, sizeof(lbuf), "      0x%04x, 0x%lx\n",
+		    md->md_type, (long) md->md_size);
 		if (pager_output(lbuf))
 			break;
 	    }
 	}
+	if (ret)
+	    break;
     }
     pager_close();
     return(CMD_OK);
diff --git a/sys/boot/common/part.c b/sys/boot/common/part.c
index 51cceca5bb55..a5f76912d386 100644
--- a/sys/boot/common/part.c
+++ b/sys/boot/common/part.c
@@ -834,6 +834,7 @@ ptable_iterate(const struct ptable *table, void *arg, ptable_iterate_t *iter)
 {
 	struct pentry *entry;
 	char name[32];
+	int ret = 0;
 
 	name[0] = '\0';
 	STAILQ_FOREACH(entry, &table->entries, entry) {
@@ -856,9 +857,8 @@ ptable_iterate(const struct ptable *table, void *arg, ptable_iterate_t *iter)
 		if (table->type == PTABLE_BSD)
 			sprintf(name, "%c", (u_char) 'a' +
 			    entry->part.index);
-		if (iter(arg, name, &entry->part))
-			return 1;
+		if ((ret = iter(arg, name, &entry->part)) != 0)
+			return (ret);
 	}
-	return 0;
+	return (ret);
 }
-
diff --git a/sys/boot/common/util.c b/sys/boot/common/util.c
index 5869f97bd5b0..49f42ebe2da9 100644
--- a/sys/boot/common/util.c
+++ b/sys/boot/common/util.c
@@ -114,7 +114,7 @@ strlen(const char *s)
 	return (len);
 }
 
-void
+int
 printf(const char *fmt, ...)
 {
 	va_list ap;
@@ -178,4 +178,5 @@ printf(const char *fmt, ...)
 		}
 	}
 	va_end(ap);
+	return (0);
 }
diff --git a/sys/boot/common/util.h b/sys/boot/common/util.h
index 1ccb78dabb17..88a99f19f0b3 100644
--- a/sys/boot/common/util.h
+++ b/sys/boot/common/util.h
@@ -48,6 +48,6 @@ void strcat(char *dst, const char *src);
 char *strchr(const char *s, char ch);
 size_t strlen(const char *s);
 
-void printf(const char *fmt, ...);
+int printf(const char *fmt, ...);
 
 #endif	/* !_UTIL_H_ */
diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c
index 032b4ca6a591..8d7db1f63f14 100644
--- a/sys/boot/efi/libefi/efinet.c
+++ b/sys/boot/efi/libefi/efinet.c
@@ -252,7 +252,7 @@ efinet_end(struct netif *nif)
 }
 
 static int efinet_dev_init(void);
-static void efinet_dev_print(int);
+static int efinet_dev_print(int);
 
 struct devsw efinet_dev = {
 	.dv_name = "net",
@@ -346,14 +346,13 @@ efinet_dev_init()
 	return (0);
 }
 
-static void
+static int
 efinet_dev_print(int verbose)
 {
 	CHAR16 *text;
 	EFI_HANDLE h;
-	int unit;
+	int unit, ret = 0;
 
-	pager_open();
 	for (unit = 0, h = efi_find_handle(&efinet_dev, 0);
 	    h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) {
 		printf("    %s%d:", efinet_dev.dv_name, unit);
@@ -364,8 +363,8 @@ efinet_dev_print(int verbose)
 				efi_free_devpath_name(text);
 			}
 		}
-		if (pager_output("\n"))
+		if ((ret = pager_output("\n")) != 0)
 			break;
 	}
-	pager_close();
+	return (ret);
 }
diff --git a/sys/boot/efi/libefi/efipart.c b/sys/boot/efi/libefi/efipart.c
index aadacf0935a3..cba94de9d27d 100644
--- a/sys/boot/efi/libefi/efipart.c
+++ b/sys/boot/efi/libefi/efipart.c
@@ -47,7 +47,7 @@ static int efipart_realstrategy(void *, int, daddr_t, size_t, size_t, char *,
     size_t *);
 static int efipart_open(struct open_file *, ...);
 static int efipart_close(struct open_file *);
-static void efipart_print(int);
+static int efipart_print(int);
 
 struct devsw efipart_dev = {
 	.dv_name = "part",
@@ -162,7 +162,7 @@ efipart_init(void)
 	return (err);
 }
 
-static void
+static int
 efipart_print(int verbose)
 {
 	char line[80];
@@ -170,28 +170,29 @@ efipart_print(int verbose)
 	EFI_HANDLE h;
 	EFI_STATUS status;
 	u_int unit;
+	int ret = 0;
 
-	pager_open();
 	for (unit = 0, h = efi_find_handle(&efipart_dev, 0);
 	    h != NULL; h = efi_find_handle(&efipart_dev, ++unit)) {
-		sprintf(line, "    %s%d:", efipart_dev.dv_name, unit);
-		if (pager_output(line))
+		snprintf(line, sizeof(line), "    %s%d:",
+		    efipart_dev.dv_name, unit);
+		if ((ret = pager_output(line)) != 0)
 			break;
 
 		status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
 		if (!EFI_ERROR(status)) {
-			sprintf(line, "    %llu blocks",
+			snprintf(line, sizeof(line), "    %llu blocks",
 			    (unsigned long long)(blkio->Media->LastBlock + 1));
-			if (pager_output(line))
+			if ((ret = pager_output(line)) != 0)
 				break;
 			if (blkio->Media->RemovableMedia)
-				if (pager_output(" (removable)"))
+				if ((ret = pager_output(" (removable)")) != 0)
 					break;
 		}
-		if (pager_output("\n"))
+		if ((ret = pager_output("\n")) != 0)
 			break;
 	}
-	pager_close();
+	return (ret);
 }
 
 static int
diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c
index 8bc85d077d3e..b97f2afb8513 100644
--- a/sys/boot/efi/loader/main.c
+++ b/sys/boot/efi/loader/main.c
@@ -533,6 +533,7 @@ command_memmap(int argc, char *argv[])
 	UINT32 dver;
 	EFI_STATUS status;
 	int i, ndesc;
+	char line[80];
 	static char *types[] = {
 	    "Reserved",
 	    "LoaderCode",
@@ -564,14 +565,19 @@ command_memmap(int argc, char *argv[])
 	}
 
 	ndesc = sz / dsz;
-	printf("%23s %12s %12s %8s %4s\n",
+	snprintf(line, sizeof(line), "%23s %12s %12s %8s %4s\n",
 	    "Type", "Physical", "Virtual", "#Pages", "Attr");
+	pager_open();
+	if (pager_output(line)) {
+		pager_close();
+		return (CMD_OK);
+	}
 
 	for (i = 0, p = map; i < ndesc;
 	     i++, p = NextMemoryDescriptor(p, dsz)) {
 		printf("%23s %012jx %012jx %08jx ", types[p->Type],
-		   (uintmax_t)p->PhysicalStart, (uintmax_t)p->VirtualStart,
-		   (uintmax_t)p->NumberOfPages);
+		    (uintmax_t)p->PhysicalStart, (uintmax_t)p->VirtualStart,
+		    (uintmax_t)p->NumberOfPages);
 		if (p->Attribute & EFI_MEMORY_UC)
 			printf("UC ");
 		if (p->Attribute & EFI_MEMORY_WC)
@@ -588,9 +594,11 @@ command_memmap(int argc, char *argv[])
 			printf("RP ");
 		if (p->Attribute & EFI_MEMORY_XP)
 			printf("XP ");
-		printf("\n");
+		if (pager_output("\n"))
+			break;
 	}
 
+	pager_close();
 	return (CMD_OK);
 }
 
@@ -612,10 +620,17 @@ guid_to_string(EFI_GUID *guid)
 static int
 command_configuration(int argc, char *argv[])
 {
+	char line[80];
 	UINTN i;
 
-	printf("NumberOfTableEntries=%lu\n",
+	snprintf(line, sizeof(line), "NumberOfTableEntries=%lu\n",
 		(unsigned long)ST->NumberOfTableEntries);
+	pager_open();
+	if (pager_output(line)) {
+		pager_close();
+		return (CMD_OK);
+	}
+
 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
 		EFI_GUID *guid;
 
@@ -642,9 +657,13 @@ command_configuration(int argc, char *argv[])
 			printf("FDT Table");
 		else
 			printf("Unknown Table (%s)", guid_to_string(guid));
-		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
+		snprintf(line, sizeof(line), " at %p\n",
+		    ST->ConfigurationTable[i].VendorTable);
+		if (pager_output(line))
+			break;
 	}
 
+	pager_close();
 	return (CMD_OK);
 }
 
diff --git a/sys/boot/i386/libfirewire/firewire.c b/sys/boot/i386/libfirewire/firewire.c
index 2c7ee3245069..fea61f3bad96 100644
--- a/sys/boot/i386/libfirewire/firewire.c
+++ b/sys/boot/i386/libfirewire/firewire.c
@@ -69,7 +69,7 @@ static int	fw_strategy(void *devdata, int flag, daddr_t dblk,
 		    size_t offset, size_t size, char *buf, size_t *rsize);
 static int	fw_open(struct open_file *f, ...);
 static int	fw_close(struct open_file *f);
-static void	fw_print(int verbose);
+static int	fw_print(int verbose);
 static void	fw_cleanup(void);
 
 void		fw_enable(void);
@@ -148,21 +148,26 @@ fw_init(void)
 /*
  * Print information about OHCI chips
  */
-static void
+static int
 fw_print(int verbose)
 {
-	int i;
+	char line[80];
+	int i, ret = 0;
 	struct fwohci_softc *sc;
 
 	for (i = 0; i < MAX_OHCI; i ++) {
 		sc = &fwinfo[i];
 		if (sc->state == FWOHCI_STATE_DEAD)
 			break;
-		printf("%d: locator=0x%04x devid=0x%08x"
+		snprintf(line, sizeof(line), "%d: locator=0x%04x devid=0x%08x"
 			" base_addr=0x%08x handle=0x%08x bus_id=0x%08x\n",
 			i, sc->locator, sc->devid,
 			sc->base_addr, sc->handle, sc->bus_id);
+		ret = pager_output(line);
+		if (ret != 0)
+			break;
 	}
+	return (ret);
 }
 
 static int 
diff --git a/sys/boot/i386/libi386/bioscd.c b/sys/boot/i386/libi386/bioscd.c
index 1ea6906e079e..776ddfa65feb 100644
--- a/sys/boot/i386/libi386/bioscd.c
+++ b/sys/boot/i386/libi386/bioscd.c
@@ -100,7 +100,7 @@ static int	bc_realstrategy(void *devdata, int flag, daddr_t dblk,
     size_t offset, size_t size, char *buf, size_t *rsize);
 static int	bc_open(struct open_file *f, ...);
 static int	bc_close(struct open_file *f);
-static void	bc_print(int verbose);
+static int	bc_print(int verbose);
 
 struct devsw bioscd = {
 	"cd", 
@@ -177,20 +177,19 @@ bc_add(int biosdev)
 /*
  * Print information about disks
  */
-static void
+static int
 bc_print(int verbose)
 {
 	char line[80];
-	int i;
+	int i, ret = 0;
 
-	pager_open();
 	for (i = 0; i < nbcinfo; i++) {
-		sprintf(line, "    cd%d: Device 0x%x\n", i,
+		snprintf(line, sizeof(line), "    cd%d: Device 0x%x\n", i,
 		    bcinfo[i].bc_sp.sp_devicespec);
-		if (pager_output(line))
+		if ((ret = pager_output(line)) != 0)
 			break;
 	}
-	pager_close();
+	return (ret);
 }
 
 /*
diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c
index 04bfac834e3e..0af0c2a4c818 100644
--- a/sys/boot/i386/libi386/biosdisk.c
+++ b/sys/boot/i386/libi386/biosdisk.c
@@ -135,7 +135,7 @@ static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t offset,
 static int bd_open(struct open_file *f, ...);
 static int bd_close(struct open_file *f);
 static int bd_ioctl(struct open_file *f, u_long cmd, void *data);
-static void bd_print(int verbose);
+static int bd_print(int verbose);
 static void bd_cleanup(void);
 
 #ifdef LOADER_GELI_SUPPORT
@@ -321,21 +321,21 @@ bd_int13probe(struct bdinfo *bd)
 /*
  * Print information about disks
  */
-static void
+static int
 bd_print(int verbose)
 {
 	static char line[80];
 	struct disk_devdesc dev;
-	int i;
+	int i, ret = 0;
 
-	pager_open();
 	for (i = 0; i < nbdinfo; i++) {
-		sprintf(line, "    disk%d:   BIOS drive %c (%ju X %u):\n", i,
+		snprintf(line, sizeof(line),
+		    "    disk%d:   BIOS drive %c (%ju X %u):\n", i,
 		    (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit):
 		    ('C' + bdinfo[i].bd_unit - 0x80),
 		    (uintmax_t)bdinfo[i].bd_sectors,
 		    bdinfo[i].bd_sectorsize);
-		if (pager_output(line))
+		if ((ret = pager_output(line)) != 0)
 			break;
 		dev.d_dev = &biosdisk;
 		dev.d_unit = i;
@@ -346,12 +346,14 @@ bd_print(int verbose)
 		    bdinfo[i].bd_sectorsize,
 		    (bdinfo[i].bd_flags & BD_FLOPPY) ?
 		    DISK_F_NOCACHE: 0) == 0) {
-			sprintf(line, "    disk%d", i);
-			disk_print(&dev, line, verbose);
+			snprintf(line, sizeof(line), "    disk%d", i);
+			ret = disk_print(&dev, line, verbose);
 			disk_close(&dev);
+			if (ret != 0)
+			    return (ret);
 		}
 	}
-	pager_close();
+	return (ret);
 }
 
 /*
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index f947ef6ddbe2..a1bb693eeb85 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -75,7 +75,7 @@ static int	pxe_strategy(void *devdata, int flag, daddr_t dblk,
 			     size_t offset, size_t size, char *buf, size_t *rsize);
 static int	pxe_open(struct open_file *f, ...);
 static int	pxe_close(struct open_file *f);
-static void	pxe_print(int verbose);
+static int	pxe_print(int verbose);
 static void	pxe_cleanup(void);
 static void	pxe_setnfshandle(char *rootpath);
 
@@ -381,14 +381,20 @@ pxe_close(struct open_file *f)
     return (0);
 }
 
-static void
+static int
 pxe_print(int verbose)
 {
-
+	char line[255];
 	if (pxe_call == NULL)
-		return;
+		return (0);
 
-	printf("    pxe0:    %s:%s\n", inet_ntoa(rootip), rootpath);
+	if (verbose) {
+		snprintf(line, sizeof(line), "    pxe0:    %s:%s\n",
+		    inet_ntoa(rootip), rootpath);
+	} else {
+		snprintf(line, sizeof(line), "    pxe0:\n");
+	}
+	return (pager_output(line));
 }
 
 static void
diff --git a/sys/boot/mips/beri/loader/beri_disk_cfi.c b/sys/boot/mips/beri/loader/beri_disk_cfi.c
index b2b6d00861b6..7a84cc648b44 100644
--- a/sys/boot/mips/beri/loader/beri_disk_cfi.c
+++ b/sys/boot/mips/beri/loader/beri_disk_cfi.c
@@ -47,7 +47,7 @@ static int	beri_cfi_disk_close(struct open_file *);
 static void	beri_cfi_disk_cleanup(void);
 static int	beri_cfi_disk_strategy(void *, int, daddr_t, size_t, size_t,
 		    char *, size_t *);
-static void	beri_cfi_disk_print(int);
+static int	beri_cfi_disk_print(int);
 
 struct devsw beri_cfi_disk = {
 	.dv_name = "cfi",
@@ -112,25 +112,29 @@ beri_cfi_disk_close(struct open_file *f)
 	return (disk_close(dev));
 }
 
-static void
+static int
 beri_cfi_disk_print(int verbose)
 {
 	struct disk_devdesc dev;
 	char line[80];
+	int ret;
 
-	sprintf(line, "    cfi%d   CFI flash device\n", 0);
-	pager_output(line);
+	snprintf(line, sizeof(line), "    cfi%d   CFI flash device\n", 0);
+	ret = pager_output(line);
+	if (ret != 0)
+		return (ret);
 	dev.d_dev = &beri_cfi_disk;
 	dev.d_unit = 0;
 	dev.d_slice = -1;
 	dev.d_partition = -1;
 	if (disk_open(&dev, cfi_get_mediasize(),
 	    cfi_get_sectorsize(), 0) == 0) {
-		sprintf(line, "    cfi%d", 0);
-		disk_print(&dev, line, verbose);
+		snprintf(line, sizeof(line), "    cfi%d", 0);
+		ret = disk_print(&dev, line, verbose);
 		disk_close(&dev);
 	}
 
+	return (ret);
 }
 
 static void
diff --git a/sys/boot/mips/beri/loader/beri_disk_sdcard.c b/sys/boot/mips/beri/loader/beri_disk_sdcard.c
index 2577e146a636..e1a2e87d11f0 100644
--- a/sys/boot/mips/beri/loader/beri_disk_sdcard.c
+++ b/sys/boot/mips/beri/loader/beri_disk_sdcard.c
@@ -47,7 +47,7 @@ static int	beri_sdcard_disk_close(struct open_file *);
 static void	beri_sdcard_disk_cleanup(void);
 static int	beri_sdcard_disk_strategy(void *, int, daddr_t, size_t, size_t,
 		    char *, size_t *);
-static void	beri_sdcard_disk_print(int);
+static int	beri_sdcard_disk_print(int);
 
 struct devsw beri_sdcard_disk = {
 	.dv_name = "sdcard",
@@ -123,19 +123,23 @@ beri_sdcard_disk_print(int verbose)
 {
 	struct disk_devdesc dev;
 	char line[80];
+	int ret;
 
-	sprintf(line, "    sdcard%d   Altera SD card drive\n", 0);
-	pager_output(line);
+	snprintf(line, sizeof(line), "    sdcard%d   Altera SD card drive\n", 0);
+	ret = pager_output(line);
+	if (ret != 0)
+	    return (ret);
 	dev.d_dev = &beri_sdcard_disk;
 	dev.d_unit = 0;
 	dev.d_slice = -1;
 	dev.d_partition = -1;
 	if (disk_open(&dev, altera_sdcard_get_mediasize(),
 	    altera_sdcard_get_sectorsize(), 0) == 0) {
-		sprintf(line, "    sdcard%d", 0);
-		disk_print(&dev, line, verbose);
+		snprintf(line, sizeof(line), "    sdcard%d", 0);
+		ret = disk_print(&dev, line, verbose);
 		disk_close(&dev);
 	}
+	return (ret);
 }
 
 static void
diff --git a/sys/boot/ofw/libofw/ofw_disk.c b/sys/boot/ofw/libofw/ofw_disk.c
index 9c46ccc94897..54cd825656b7 100644
--- a/sys/boot/ofw/libofw/ofw_disk.c
+++ b/sys/boot/ofw/libofw/ofw_disk.c
@@ -47,7 +47,7 @@ static int	ofwd_strategy(void *devdata, int flag, daddr_t dblk,
 static int	ofwd_open(struct open_file *f, ...);
 static int	ofwd_close(struct open_file *f);
 static int	ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
-static void	ofwd_print(int verbose);
+static int	ofwd_print(int verbose);
 
 struct devsw ofwdisk = {
 	"block",
@@ -161,8 +161,8 @@ ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused,
 	return (EINVAL);
 }
 
-static void
+static int
 ofwd_print(int verbose __unused)
 {
-
+	return (0);
 }
diff --git a/sys/boot/pc98/libpc98/bioscd.c b/sys/boot/pc98/libpc98/bioscd.c
index 15758cccb444..6e520138400b 100644
--- a/sys/boot/pc98/libpc98/bioscd.c
+++ b/sys/boot/pc98/libpc98/bioscd.c
@@ -99,7 +99,7 @@ static int	bc_realstrategy(void *devdata, int flag, daddr_t dblk,
 		    size_t offset, size_t size, char *buf, size_t *rsize);
 static int	bc_open(struct open_file *f, ...);
 static int	bc_close(struct open_file *f);
-static void	bc_print(int verbose);
+static int	bc_print(int verbose);
 
 struct devsw bioscd = {
 	"cd", 
@@ -173,20 +173,19 @@ bc_add(int biosdev)
 /*
  * Print information about disks
  */
-static void
+static int
 bc_print(int verbose)
 {
 	char line[80];
-	int i;
+	int i, ret = 0;
 
-	pager_open();
 	for (i = 0; i < nbcinfo; i++) {
 		sprintf(line, "    cd%d: Device 0x%x\n", i,
 		    bcinfo[i].bc_sp.sp_devicespec);
-		if (pager_output(line))
+		if ((ret = pager_output(line)) != 0)
 			break;
 	}
-	pager_close();
+	return (ret);
 }
 
 /*
diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c
index 0ceeb7bb0754..6ecfa4912a62 100644
--- a/sys/boot/pc98/libpc98/biosdisk.c
+++ b/sys/boot/pc98/libpc98/biosdisk.c
@@ -123,7 +123,7 @@ static int	bd_realstrategy(void *devdata, int flag, daddr_t dblk,
 		    size_t offset, size_t size, char *buf, size_t *rsize);
 static int	bd_open(struct open_file *f, ...);
 static int	bd_close(struct open_file *f);
-static void	bd_print(int verbose);
+static int	bd_print(int verbose);
 
 struct devsw biosdisk = {
     "disk", 
@@ -249,21 +249,20 @@ bd_int13probe(struct bdinfo *bd)
 /*
  * Print information about disks
  */
-static void
+static int
 bd_print(int verbose)
 {
-    int				i, j, done;
+    int				i, j, ret = 0;
     char			line[80];
     struct i386_devdesc		dev;
     struct open_disk		*od;
     struct pc98_partition	*dptr;
     
-    pager_open();
-    done = 0;
-    for (i = 0; i < nbdinfo && !done; i++) {
-	sprintf(line, "    disk%d:   BIOS drive %c:\n", i, 'A' + i);
-	if (pager_output(line))
-		break;
+    for (i = 0; i < nbdinfo; i++) {
+	snprintf(line, sizeof(line), "    disk%d:   BIOS drive %c:\n",
+	    i, 'A' + i);
+	if ((ret = pager_output(line)) != 0)
+	    break;
 
 	/* try to open the whole disk */
 	dev.d_unit = i;
@@ -278,17 +277,17 @@ bd_print(int verbose)
 
 		/* Check for a "dedicated" disk */
 		for (j = 0; j < od->od_nslices; j++) {
-		    sprintf(line, "      disk%ds%d", i, j + 1);
-		    if (bd_printslice(od, &dptr[j], line, verbose)) {
-			    done = 1;
-			    break;
-		    }
+		    snprintf(line, sizeof(line), "      disk%ds%d", i, j + 1);
+		    if ((ret = bd_printslice(od, &dptr[j], line, verbose)) != 0)
+			break;
 		}
 	    }
 	    bd_closedisk(od);
+	    if (ret != 0)
+		break;
 	}
     }
-    pager_close();
+    return (ret);
 }
 
 /* Given a size in 512 byte sectors, convert it to a human-readable number. */
diff --git a/sys/boot/powerpc/kboot/hostdisk.c b/sys/boot/powerpc/kboot/hostdisk.c
index ac4534cf7d9c..e235017b4ec4 100644
--- a/sys/boot/powerpc/kboot/hostdisk.c
+++ b/sys/boot/powerpc/kboot/hostdisk.c
@@ -37,7 +37,7 @@ static int hostdisk_strategy(void *devdata, int flag, daddr_t dblk,
 static int hostdisk_open(struct open_file *f, ...);
 static int hostdisk_close(struct open_file *f);
 static int hostdisk_ioctl(struct open_file *f, u_long cmd, void *data);
-static void hostdisk_print(int verbose);
+static int hostdisk_print(int verbose);
 
 struct devsw hostdisk = {
 	"/dev",
@@ -117,9 +117,9 @@ hostdisk_ioctl(struct open_file *f, u_long cmd, void *data)
 	return (EINVAL);
 }
 
-static void
+static int
 hostdisk_print(int verbose)
 {
-
+	return (0);
 }
 
diff --git a/sys/boot/powerpc/ps3/ps3cdrom.c b/sys/boot/powerpc/ps3/ps3cdrom.c
index c5019e0f6a53..7992044f2422 100644
--- a/sys/boot/powerpc/ps3/ps3cdrom.c
+++ b/sys/boot/powerpc/ps3/ps3cdrom.c
@@ -49,7 +49,7 @@ static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
 	size_t offset, size_t size, char *buf, size_t *rsize);
 static int ps3cdrom_open(struct open_file *f, ...);
 static int ps3cdrom_close(struct open_file *f);
-static void ps3cdrom_print(int verbose);
+static int ps3cdrom_print(int verbose);
 
 struct devsw ps3cdrom = {
 	"cd",
@@ -149,6 +149,7 @@ static int ps3cdrom_close(struct open_file *f)
 	return 0;
 }
 
-static void ps3cdrom_print(int verbose)
+static int ps3cdrom_print(int verbose)
 {
+	return (0);
 }
diff --git a/sys/boot/powerpc/ps3/ps3disk.c b/sys/boot/powerpc/ps3/ps3disk.c
index 52a43f1b9874..7c852031b18e 100644
--- a/sys/boot/powerpc/ps3/ps3disk.c
+++ b/sys/boot/powerpc/ps3/ps3disk.c
@@ -61,7 +61,7 @@ static int ps3disk_strategy(void *devdata, int flag, daddr_t dblk,
 	size_t offset, size_t size, char *buf, size_t *rsize);
 static int ps3disk_open(struct open_file *f, ...);
 static int ps3disk_close(struct open_file *f);
-static void ps3disk_print(int verbose);
+static int ps3disk_print(int verbose);
 
 struct devsw ps3disk = {
 	"disk",
@@ -186,8 +186,9 @@ static int ps3disk_close(struct open_file *f)
 	return 0;
 }
 
-static void ps3disk_print(int verbose)
+static int ps3disk_print(int verbose)
 {
+	return (0);
 }
 
 static int ps3disk_open_gpt(struct ps3_devdesc *dev, struct open_dev *od)
diff --git a/sys/boot/uboot/lib/disk.c b/sys/boot/uboot/lib/disk.c
index 741b1f89db00..c0d187d1f962 100644
--- a/sys/boot/uboot/lib/disk.c
+++ b/sys/boot/uboot/lib/disk.c
@@ -78,7 +78,7 @@ static int stor_strategy(void *, int, daddr_t, size_t, size_t, char *,
 static int stor_open(struct open_file *, ...);
 static int stor_close(struct open_file *);
 static int stor_ioctl(struct open_file *f, u_long cmd, void *data);
-static void stor_print(int);
+static int stor_print(int);
 static void stor_cleanup(void);
 
 struct devsw uboot_storage = {
@@ -238,30 +238,31 @@ stor_readdev(struct disk_devdesc *dev, daddr_t blk, size_t size, char *buf)
 	return (err);
 }
 
-static void
+static int
 stor_print(int verbose)
 {
 	struct disk_devdesc dev;
 	static char line[80];
-	int i;
+	int i, ret = 0;
 
-	pager_open();
 	for (i = 0; i < stor_info_no; i++) {
 		dev.d_dev = &uboot_storage;
 		dev.d_unit = i;
 		dev.d_slice = -1;
 		dev.d_partition = -1;
-		sprintf(line, "\tdisk%d (%s)\n", i,
+		snprintf(line, sizeof(line), "\tdisk%d (%s)\n", i,
 		    ub_stor_type(SI(&dev).type));
-		if (pager_output(line))
+		if ((ret = pager_output(line)) != 0)
 			break;
 		if (stor_opendev(&dev) == 0) {
 			sprintf(line, "\tdisk%d", i);
-			disk_print(&dev, line, verbose);
+			ret = disk_print(&dev, line, verbose);
 			disk_close(&dev);
+			if (ret != 0)
+				break;
 		}
 	}
-	pager_close();
+	return (ret);
 }
 
 static int
diff --git a/sys/boot/usb/storage/umass_loader.c b/sys/boot/usb/storage/umass_loader.c
index 85b89e82b7f3..e6e38bfe9e2a 100644
--- a/sys/boot/usb/storage/umass_loader.c
+++ b/sys/boot/usb/storage/umass_loader.c
@@ -50,7 +50,7 @@ static void umass_disk_cleanup(void);
 static int umass_disk_ioctl(struct open_file *, u_long, void *);
 static int umass_disk_strategy(void *, int, daddr_t, size_t, size_t, char *,
     size_t *);
-static void umass_disk_print(int);
+static int umass_disk_print(int);
 
 struct devsw umass_disk = {
 	.dv_name = "umass",
@@ -170,23 +170,26 @@ umass_disk_close(struct open_file *f)
 	return (disk_close(dev));
 }
 
-static void
+static int
 umass_disk_print(int verbose)
 {
 	struct disk_devdesc dev;
 
 	memset(&dev, 0, sizeof(dev));
 
-	pager_output("    umass0   UMASS device\n");
+	ret = pager_output("    umass0   UMASS device\n");
+	if (ret != 0)
+		return (ret);
 	dev.d_dev = &umass_disk;
 	dev.d_unit = 0;
 	dev.d_slice = -1;
 	dev.d_partition = -1;
 
 	if (umass_disk_open_sub(&dev) == 0) {
-		disk_print(&dev, "    umass0", verbose);
+		ret = disk_print(&dev, "    umass0", verbose);
 		disk_close(&dev);
 	}
+	return (ret);
 }
 
 static void
diff --git a/sys/boot/userboot/userboot/host.c b/sys/boot/userboot/userboot/host.c
index 3320a7f62816..dca2f341ba69 100644
--- a/sys/boot/userboot/userboot/host.c
+++ b/sys/boot/userboot/userboot/host.c
@@ -134,13 +134,13 @@ host_dev_init(void)
 	return (0);
 }
 
-static void
+static int
 host_dev_print(int verbose)
 {
 	char line[80];
 
-	sprintf(line, "    host%d:   Host filesystem\n", 0);
-	pager_output(line);
+	snprintf(line, sizeof(line), "    host%d:   Host filesystem\n", 0);
+	return (pager_output(line));
 }
 
 /*
diff --git a/sys/boot/userboot/userboot/userboot_disk.c b/sys/boot/userboot/userboot/userboot_disk.c
index 56fe7e36e25c..7c0c36820a90 100644
--- a/sys/boot/userboot/userboot/userboot_disk.c
+++ b/sys/boot/userboot/userboot/userboot_disk.c
@@ -60,7 +60,7 @@ static int	userdisk_realstrategy(void *devdata, int flag, daddr_t dblk,
 static int	userdisk_open(struct open_file *f, ...);
 static int	userdisk_close(struct open_file *f);
 static int	userdisk_ioctl(struct open_file *f, u_long cmd, void *data);
-static void	userdisk_print(int verbose);
+static int	userdisk_print(int verbose);
 
 struct devsw userboot_disk = {
 	"disk",
@@ -116,27 +116,33 @@ userdisk_cleanup(void)
 /*
  * Print information about disks
  */
-static void
+static int
 userdisk_print(int verbose)
 {
 	struct disk_devdesc dev;
 	char line[80];
-	int i;
+	int i, ret = 0;
 
 	for (i = 0; i < userdisk_maxunit; i++) {
-		sprintf(line, "    disk%d:   Guest drive image\n", i);
-		pager_output(line);
+		snprintf(line, sizeof(line),
+		    "    disk%d:   Guest drive image\n", i);
+		ret = pager_output(line);
+		if (ret != 0)
+			break;
 		dev.d_dev = &userboot_disk;
 		dev.d_unit = i;
 		dev.d_slice = -1;
 		dev.d_partition = -1;
 		if (disk_open(&dev, ud_info[i].mediasize,
 		    ud_info[i].sectorsize, 0) == 0) {
-			sprintf(line, "    disk%d", i);
-			disk_print(&dev, line, verbose);
+			snprintf(line, sizeof(line), "    disk%d", i);
+			ret = disk_print(&dev, line, verbose);
 			disk_close(&dev);
+			if (ret != 0)
+				break;
 		}
 	}
+	return (ret);
 }
 
 /*
diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c
index 2552e09cdf20..3efa429e84a4 100644
--- a/sys/boot/zfs/zfs.c
+++ b/sys/boot/zfs/zfs.c
@@ -514,20 +514,23 @@ zfs_probe_dev(const char *devname, uint64_t *pool_guid)
 /*
  * Print information about ZFS pools
  */
-static void
+static int
 zfs_dev_print(int verbose)
 {
 	spa_t *spa;
 	char line[80];
+	int ret = 0;
 
 	if (verbose) {
-		spa_all_status();
-		return;
+		return (spa_all_status());
 	}
 	STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-		sprintf(line, "    zfs:%s\n", spa->spa_name);
-		pager_output(line);
+		snprintf(line, sizeof(line), "    zfs:%s\n", spa->spa_name);
+		ret = pager_output(line);
+		if (ret != 0)
+			break;
 	}
+	return (ret);
 }
 
 /*
diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c
index c9f8bbf43314..5f05c35587af 100644
--- a/sys/boot/zfs/zfsimpl.c
+++ b/sys/boot/zfs/zfsimpl.c
@@ -780,7 +780,7 @@ state_name(vdev_state_t state)
 
 #else
 
-static void
+static int
 pager_printf(const char *fmt, ...)
 {
 	char line[80];
@@ -789,14 +789,14 @@ pager_printf(const char *fmt, ...)
 	va_start(args, fmt);
 	vsprintf(line, fmt, args);
 	va_end(args);
-	pager_output(line);
+	return (pager_output(line));
 }
 
 #endif
 
 #define STATUS_FORMAT	"        %s %s\n"
 
-static void
+static int
 print_state(int indent, const char *name, vdev_state_t state)
 {
 	int i;
@@ -806,40 +806,56 @@ print_state(int indent, const char *name, vdev_state_t state)
 	for (i = 0; i < indent; i++)
 		strcat(buf, "  ");
 	strcat(buf, name);
-	pager_printf(STATUS_FORMAT, buf, state_name(state));
+	return (pager_printf(STATUS_FORMAT, buf, state_name(state)));
 	
 }
 
-static void
+static int
 vdev_status(vdev_t *vdev, int indent)
 {
 	vdev_t *kid;
-	print_state(indent, vdev->v_name, vdev->v_state);
+	int ret;
+	ret = print_state(indent, vdev->v_name, vdev->v_state);
+	if (ret != 0)
+		return (ret);
 
 	STAILQ_FOREACH(kid, &vdev->v_children, v_childlink) {
-		vdev_status(kid, indent + 1);
+		ret = vdev_status(kid, indent + 1);
+		if (ret != 0)
+			return (ret);
 	}
+	return (ret);
 }
 
-static void
+static int
 spa_status(spa_t *spa)
 {
 	static char bootfs[ZFS_MAXNAMELEN];
 	uint64_t rootid;
 	vdev_t *vdev;
-	int good_kids, bad_kids, degraded_kids;
+	int good_kids, bad_kids, degraded_kids, ret;
 	vdev_state_t state;
 
-	pager_printf("  pool: %s\n", spa->spa_name);
+	ret = pager_printf("  pool: %s\n", spa->spa_name);
+	if (ret != 0)
+		return (ret);
+
 	if (zfs_get_root(spa, &rootid) == 0 &&
 	    zfs_rlookup(spa, rootid, bootfs) == 0) {
 		if (bootfs[0] == '\0')
-			pager_printf("bootfs: %s\n", spa->spa_name);
+			ret = pager_printf("bootfs: %s\n", spa->spa_name);
 		else
-			pager_printf("bootfs: %s/%s\n", spa->spa_name, bootfs);
+			ret = pager_printf("bootfs: %s/%s\n", spa->spa_name,
+			    bootfs);
+		if (ret != 0)
+			return (ret);
 	}
-	pager_printf("config:\n\n");
-	pager_printf(STATUS_FORMAT, "NAME", "STATE");
+	ret = pager_printf("config:\n\n");
+	if (ret != 0)
+		return (ret);
+	ret = pager_printf(STATUS_FORMAT, "NAME", "STATE");
+	if (ret != 0)
+		return (ret);
 
 	good_kids = 0;
 	degraded_kids = 0;
@@ -859,24 +875,35 @@ spa_status(spa_t *spa)
 	else if ((good_kids + degraded_kids) > 0)
 		state = VDEV_STATE_DEGRADED;
 
-	print_state(0, spa->spa_name, state);
+	ret = print_state(0, spa->spa_name, state);
+	if (ret != 0)
+		return (ret);
 	STAILQ_FOREACH(vdev, &spa->spa_vdevs, v_childlink) {
-		vdev_status(vdev, 1);
+		ret = vdev_status(vdev, 1);
+		if (ret != 0)
+			return (ret);
 	}
+	return (ret);
 }
 
-static void
+static int
 spa_all_status(void)
 {
 	spa_t *spa;
-	int first = 1;
+	int first = 1, ret = 0;
 
 	STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-		if (!first)
-			pager_printf("\n");
+		if (!first) {
+			ret = pager_printf("\n");
+			if (ret != 0)
+				return (ret);
+		}
 		first = 0;
-		spa_status(spa);
+		ret = spa_status(spa);
+		if (ret != 0)
+			return (ret);
 	}
+	return (ret);
 }
 
 static int

From dd3dde9828049e11572d78ad6b79fe5f7268ad4a Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Tue, 8 Nov 2016 08:09:48 +0000
Subject: [PATCH 096/127] Range check the jitter values to avoid bogus sample
 rate adjustments. The expected deviation should not be more than 1Hz per
 second. The USB v2.0 specification also mandates this requirement. Refer to
 chapter 5.12.4.2 about feedback.

PR:		208791
MFC after:	3 days
---
 sys/dev/sound/usb/uaudio.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 7e32b706c2d7..6ed81eef02ea 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -2078,9 +2078,22 @@ uaudio_chan_play_sync_callback(struct usb_xfer *xfer, usb_error_t error)
 		 * Use feedback value as fallback when there is no
 		 * recording channel:
 		 */
-		if (ch->priv_sc->sc_rec_chan.num_alt == 0)
-			ch->jitter_curr = temp - sample_rate;
-
+		if (ch->priv_sc->sc_rec_chan.num_alt == 0) {
+			/*
+			 * Range check the jitter values to avoid
+			 * bogus sample rate adjustments. The expected
+			 * deviation should not be more than 1Hz per
+			 * second. The USB v2.0 specification also
+			 * mandates this requirement. Refer to chapter
+			 * 5.12.4.2 about feedback.
+			 */
+			if (temp > sample_rate)
+				ch->jitter_curr = 1;
+			else if (temp < sample_rate)
+				ch->jitter_curr = -1;
+			else
+				ch->jitter_curr = 0;
+		}
 		ch->feedback_rate = temp;
 		break;
 

From ad6d34179918289bbb607417929cd07d397d68df Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Tue, 8 Nov 2016 10:05:11 +0000
Subject: [PATCH 097/127] Do not warn if the 'assigned-clock-parents' property
 does not exists.

MFC after:	2 weeks
---
 sys/dev/extres/clk/clk.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/sys/dev/extres/clk/clk.c b/sys/dev/extres/clk/clk.c
index 9c189fa86699..b3996c53bdc8 100644
--- a/sys/dev/extres/clk/clk.c
+++ b/sys/dev/extres/clk/clk.c
@@ -1205,7 +1205,9 @@ clk_set_assigned(device_t dev, phandle_t node)
 	    "assigned-clock-parents", "#clock-cells", &nclocks);
 
 	if (error != 0) {
-		device_printf(dev, "cannot parse assigned-clock-parents property\n");
+		if (error != ENOENT)
+			device_printf(dev,
+			    "cannot parse assigned-clock-parents property\n");
 		return (error);
 	}
 

From 328dd395ba9d511649ee3d516b2f87d5067b621d Mon Sep 17 00:00:00 2001
From: Emmanuel Vadot 
Date: Tue, 8 Nov 2016 10:06:43 +0000
Subject: [PATCH 098/127] Do not fail to attach the clock if we cannot set the
 assigned parents as this property isn't mandatory.

MFC after:	2 weeks
---
 sys/arm/allwinner/clk/aw_ahbclk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/arm/allwinner/clk/aw_ahbclk.c b/sys/arm/allwinner/clk/aw_ahbclk.c
index 451ad7e1ef66..36a7356ae4d1 100644
--- a/sys/arm/allwinner/clk/aw_ahbclk.c
+++ b/sys/arm/allwinner/clk/aw_ahbclk.c
@@ -351,7 +351,7 @@ aw_ahbclk_attach(device_t dev)
 	}
 
 	error = clk_set_assigned(dev, node);
-	if (error != 0) {
+	if (error != 0 && error != ENOENT) {
 		device_printf(dev, "cannot set assigned parents: %d\n", error);
 		goto fail;
 	}

From 9a639daf77146468d5e5d3d4c2a687ff2ca49730 Mon Sep 17 00:00:00 2001
From: Konstantin Belousov 
Date: Tue, 8 Nov 2016 10:10:55 +0000
Subject: [PATCH 099/127] Tweaks for the buffer pager.

Pass current thread credentials instead of NOCRED.
Only allow unmapped buffers for filesystem which proclaimed the support.

For all filesystems which currently use buffer pager (UFS, msdosfs and
cd9660), the changes are effectively nop.

Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
---
 sys/kern/vfs_bio.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index b19e4d73b0db..54f32c99d276 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4686,13 +4686,15 @@ vfs_bio_getpages(struct vnode *vp, vm_page_t *ma, int count,
 	vm_page_t m;
 	vm_object_t object;
 	struct buf *bp;
+	struct mount *mp;
 	daddr_t lbn, lbnp;
 	vm_ooffset_t la, lb, poff, poffe;
 	long bsize;
-	int bo_bs, error, i;
+	int bo_bs, br_flags, error, i;
 	bool redo, lpart;
 
 	object = vp->v_object;
+	mp = vp->v_mount;
 	la = IDX_TO_OFF(ma[count - 1]->pindex);
 	if (la >= object->un_pager.vnp.vnp_size)
 		return (VM_PAGER_BAD);
@@ -4709,6 +4711,8 @@ vfs_bio_getpages(struct vnode *vp, vm_page_t *ma, int count,
 			    vnp.vnp_size, PAGE_SIZE) - la);
 		}
 	}
+	br_flags = (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMAPPED_BUFS)
+	    != 0) ? GB_UNMAPPED : 0;
 	VM_OBJECT_WLOCK(object);
 again:
 	for (i = 0; i < count; i++)
@@ -4741,8 +4745,8 @@ vfs_bio_getpages(struct vnode *vp, vm_page_t *ma, int count,
 			lbnp = lbn;
 
 			bsize = get_blksize(vp, lbn);
-			error = bread_gb(vp, lbn, bsize, NOCRED, GB_UNMAPPED,
-			    &bp);
+			error = bread_gb(vp, lbn, bsize, curthread->td_ucred,
+			    br_flags, &bp);
 			if (error != 0)
 				goto end_pages;
 			if (LIST_EMPTY(&bp->b_dep)) {

From 31500ce90d3091027a6a9a2e61f6130db6269a1c Mon Sep 17 00:00:00 2001
From: Marcelo Araujo 
Date: Tue, 8 Nov 2016 11:36:33 +0000
Subject: [PATCH 100/127] Add -d flag that prints domain only.

PR:		212875
Submitted by:	Ben RUBSON 
Reviewed by:	pi
---
 bin/hostname/hostname.1 |  7 +++++--
 bin/hostname/hostname.c | 16 ++++++++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/bin/hostname/hostname.1 b/bin/hostname/hostname.1
index bfff27baa6c6..73255d280041 100644
--- a/bin/hostname/hostname.1
+++ b/bin/hostname/hostname.1
@@ -29,7 +29,7 @@
 .\"	@(#)hostname.1	8.2 (Berkeley) 4/28/95
 .\" $FreeBSD$
 .\"
-.Dd December 7, 2006
+.Dd November 9, 2016
 .Dt HOSTNAME 1
 .Os
 .Sh NAME
@@ -37,7 +37,8 @@
 .Nd set or print name of current host system
 .Sh SYNOPSIS
 .Nm
-.Op Fl fs
+.Op Fl f
+.Op Fl s|d
 .Op Ar name-of-host
 .Sh DESCRIPTION
 The
@@ -62,6 +63,8 @@ This is the default behavior.
 .It Fl s
 Trim off any domain information from the printed
 name.
+.It Fl d
+Only print domain information.
 .El
 .Sh SEE ALSO
 .Xr gethostname 3 ,
diff --git a/bin/hostname/hostname.c b/bin/hostname/hostname.c
index ecc319db6b17..3b07b8b5f537 100644
--- a/bin/hostname/hostname.c
+++ b/bin/hostname/hostname.c
@@ -54,11 +54,12 @@ static void usage(void) __dead2;
 int
 main(int argc, char *argv[])
 {
-	int ch, sflag;
+	int ch, sflag, dflag;
 	char *p, hostname[MAXHOSTNAMELEN];
 
 	sflag = 0;
-	while ((ch = getopt(argc, argv, "fs")) != -1)
+	dflag = 0;
+	while ((ch = getopt(argc, argv, "fsd")) != -1)
 		switch (ch) {
 		case 'f':
 			/*
@@ -70,6 +71,9 @@ main(int argc, char *argv[])
 		case 's':
 			sflag = 1;
 			break;
+		case 'd':
+			dflag = 1;
+			break;
 		case '?':
 		default:
 			usage();
@@ -77,7 +81,7 @@ main(int argc, char *argv[])
 	argc -= optind;
 	argv += optind;
 
-	if (argc > 1)
+	if (argc > 1 || (sflag && dflag))
 		usage();
 
 	if (*argv) {
@@ -90,6 +94,10 @@ main(int argc, char *argv[])
 			p = strchr(hostname, '.');
 			if (p != NULL)
 				*p = '\0';
+		} else if (dflag) {
+			p = strchr(hostname, '.');
+			if (p != NULL)
+				strcpy(hostname, ++p);
 		}
 		(void)printf("%s\n", hostname);
 	}
@@ -100,6 +108,6 @@ static void
 usage(void)
 {
 
-	(void)fprintf(stderr, "usage: hostname [-fs] [name-of-host]\n");
+	(void)fprintf(stderr, "usage: hostname [-f] [s|d] [name-of-host]\n");
 	exit(1);
 }

From feabce61dcd6e6b2be679e6919a0bda5ab27b19a Mon Sep 17 00:00:00 2001
From: Andrew Turner 
Date: Tue, 8 Nov 2016 12:15:57 +0000
Subject: [PATCH 101/127] Start to remove the old pre-INTRNG code from the arm
 platforms. These have all moved to use INTRNG.

Reviewed by:	manu, mmel
Sponsored by:	ABT Systems Ltd
Differential Revision:	https://reviews.freebsd.org/D8469
---
 sys/arm/allwinner/a10/a10_intc.c          |  48 +---
 sys/arm/allwinner/a10_common.c            |  68 -----
 sys/arm/allwinner/files.allwinner         |   1 -
 sys/arm/broadcom/bcm2835/bcm2835_common.c |  78 ------
 sys/arm/broadcom/bcm2835/bcm2835_gpio.c   | 280 +-------------------
 sys/arm/broadcom/bcm2835/bcm2835_intr.c   | 127 ----------
 sys/arm/broadcom/bcm2835/bcm2836.c        | 178 -------------
 sys/arm/broadcom/bcm2835/bcm2836.h        |  40 ---
 sys/arm/broadcom/bcm2835/bcm2836_mp.c     |  40 ---
 sys/arm/broadcom/bcm2835/files.bcm283x    |   1 -
 sys/arm/qemu/files.qemu                   |   1 -
 sys/arm/qemu/virt_common.c                |  45 ----
 sys/arm/ti/aintc.c                        |  73 ------
 sys/arm/ti/files.ti                       |   1 -
 sys/arm/ti/ti_common.c                    |  80 ------
 sys/arm/ti/ti_gpio.c                      | 296 ----------------------
 sys/arm/ti/ti_gpio.h                      |  18 --
 17 files changed, 3 insertions(+), 1372 deletions(-)
 delete mode 100644 sys/arm/allwinner/a10_common.c
 delete mode 100644 sys/arm/broadcom/bcm2835/bcm2835_common.c
 delete mode 100644 sys/arm/broadcom/bcm2835/bcm2836.h
 delete mode 100644 sys/arm/qemu/virt_common.c
 delete mode 100644 sys/arm/ti/ti_common.c

diff --git a/sys/arm/allwinner/a10/a10_intc.c b/sys/arm/allwinner/a10/a10_intc.c
index 41f1f306b55d..fd6c4073fb34 100644
--- a/sys/arm/allwinner/a10/a10_intc.c
+++ b/sys/arm/allwinner/a10/a10_intc.c
@@ -43,9 +43,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#ifdef INTRNG
 #include 
-#endif
 #include 
 #include 
 
@@ -54,9 +52,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef INTRNG
 #include "pic_if.h"
-#endif
 
 /**
  * Interrupt controller registers
@@ -97,12 +93,10 @@ __FBSDID("$FreeBSD$");
 #define	SW_INT_ENABLE_REG(_b)		(0x40 + ((_b) * 4))
 #define	SW_INT_MASK_REG(_b)		(0x50 + ((_b) * 4))
 
-#ifdef INTRNG
 struct a10_intr_irqsrc {
 	struct intr_irqsrc	isrc;
 	u_int			irq;
 };
-#endif
 
 struct a10_aintc_softc {
 	device_t		sc_dev;
@@ -110,9 +104,7 @@ struct a10_aintc_softc {
 	bus_space_tag_t		aintc_bst;
 	bus_space_handle_t	aintc_bsh;
 	struct mtx		mtx;
-#ifdef INTRNG
 	struct a10_intr_irqsrc	isrcs[A10_INTR_MAX_NIRQS];
-#endif
 };
 
 #define	aintc_read_4(sc, reg)						\
@@ -189,31 +181,6 @@ a10_pending_irq(struct a10_aintc_softc *sc)
 	return (-1);
 }
 
-#ifndef INTRNG
-
-static struct a10_aintc_softc *a10_aintc_sc = NULL;
-
-int
-arm_get_next_irq(int last_irq)
-{
-	return (a10_pending_irq(a10_aintc_sc));
-}
-
-void
-arm_mask_irq(uintptr_t irq)
-{
-	a10_intr_mask(a10_aintc_sc, irq);
-}
-
-void
-arm_unmask_irq(uintptr_t irq)
-{
-	a10_intr_unmask(a10_aintc_sc, irq);
-	a10_intr_eoi(a10_aintc_sc, irq);
-}
-
-#else /* INTRNG */
-
 static int
 a10_intr(void *arg)
 {
@@ -340,8 +307,6 @@ a10_intr_post_filter(device_t dev, struct intr_irqsrc *isrc)
 	a10_intr_eoi(sc, irq);
 }
 
-#endif /* INTRNG */
-
 static int
 a10_aintc_probe(device_t dev)
 {
@@ -363,13 +328,6 @@ a10_aintc_attach(device_t dev)
 	int i;
 	sc->sc_dev = dev;
 
-#ifndef INTRNG
-	if (a10_aintc_sc)
-		goto error;
-
-	a10_aintc_sc = sc;
-#endif
-
 	sc->aintc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 	    &rid, RF_ACTIVE);
 	if (!sc->aintc_res) {
@@ -393,12 +351,10 @@ a10_aintc_attach(device_t dev)
 	/* config the external interrupt source type*/
 	aintc_write_4(sc, SW_INT_NMI_CTRL_REG, 0x00);
 
-#ifdef INTRNG
 	if (a10_intr_pic_attach(sc) != 0) {
 		device_printf(dev, "could not attach PIC\n");
 		return (ENXIO);
 	}
-#endif
 
 	return (0);
 
@@ -411,7 +367,7 @@ a10_aintc_attach(device_t dev)
 static device_method_t a10_aintc_methods[] = {
 	DEVMETHOD(device_probe,		a10_aintc_probe),
 	DEVMETHOD(device_attach,	a10_aintc_attach),
-#ifdef INTRNG
+
 	/* Interrupt controller interface */
 	DEVMETHOD(pic_disable_intr,	a10_intr_disable_intr),
 	DEVMETHOD(pic_enable_intr,	a10_intr_enable_intr),
@@ -419,7 +375,7 @@ static device_method_t a10_aintc_methods[] = {
 	DEVMETHOD(pic_post_filter,	a10_intr_post_filter),
 	DEVMETHOD(pic_post_ithread,	a10_intr_post_ithread),
 	DEVMETHOD(pic_pre_ithread,	a10_intr_pre_ithread),
-#endif
+
 	{ 0, 0 }
 };
 
diff --git a/sys/arm/allwinner/a10_common.c b/sys/arm/allwinner/a10_common.c
deleted file mode 100644
index 6b3fded7a3ab..000000000000
--- a/sys/arm/allwinner/a10_common.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * Copyright (c) 2012 Ganbold Tsagaankhuu 
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include 
-__FBSDID("$FreeBSD$");
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include 
-#include 
-
-#ifndef INTRNG
-
-static int
-fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
-    int *pol)
-{
-	int offset;
-
-	if (fdt_is_compatible(node, "allwinner,sun4i-a10-ic"))
-		offset = 0;
-	else if (fdt_is_compatible(node, "arm,gic"))
-		offset = 32;
-	else
-		return (ENXIO);
-
-	*interrupt = fdt32_to_cpu(intr[0]) + offset;
-	*trig = INTR_TRIGGER_CONFORM;
-	*pol = INTR_POLARITY_CONFORM;
-
-	return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
-	&fdt_aintc_decode_ic,
-	NULL
-};
-
-#endif /* INTRNG */
diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner
index 9e56e0d4a847..f66f69e63d95 100644
--- a/sys/arm/allwinner/files.allwinner
+++ b/sys/arm/allwinner/files.allwinner
@@ -3,7 +3,6 @@ kern/kern_clocksource.c			standard
 
 arm/allwinner/a10_ahci.c		optional	ahci
 arm/allwinner/a10_codec.c		optional	sound
-arm/allwinner/a10_common.c		standard
 arm/allwinner/a10_dmac.c		standard
 arm/allwinner/a31_dmac.c		standard
 arm/allwinner/a10_ehci.c		optional	ehci
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_common.c b/sys/arm/broadcom/bcm2835/bcm2835_common.c
deleted file mode 100644
index 7d2ef761fa4a..000000000000
--- a/sys/arm/broadcom/bcm2835/bcm2835_common.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*-
- * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
- * All rights reserved.
- *
- * Developed by Semihalf.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of MARVELL nor the names of contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include 
-__FBSDID("$FreeBSD$");
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include 
-#include 
-
-#ifndef INTRNG
-static int
-fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
-    int *pol)
-{
-
-	if (fdt_is_compatible(node, "broadcom,bcm2835-armctrl-ic") ||
-	    fdt_is_compatible(node, "brcm,bcm2836-armctrl-ic")) {
-		*interrupt = fdt32_to_cpu(intr[0]);
-		*trig = INTR_TRIGGER_CONFORM;
-		*pol = INTR_POLARITY_CONFORM;
-		return (0);
-	}
-#ifdef SOC_BCM2836
-	if (fdt_is_compatible(node, "brcm,bcm2836-l1-intc")) {
-		*interrupt = fdt32_to_cpu(intr[0]) + 72;
-		*trig = INTR_TRIGGER_CONFORM;
-		*pol = INTR_POLARITY_CONFORM;
-		return (0);
-	}
-#endif
-	return (ENXIO);
-}
-
-
-fdt_pic_decode_t fdt_pic_table[] = {
-	&fdt_intc_decode_ic,
-	NULL
-};
-#endif /* INTRNG */
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c
index ed3bbae998fe..07b311e679fd 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c
@@ -53,9 +53,7 @@ __FBSDID("$FreeBSD$");
 
 #include "gpio_if.h"
 
-#ifdef INTRNG
 #include "pic_if.h"
-#endif
 
 #ifdef DEBUG
 #define dprintf(fmt, args...) do { printf("%s(): ", __func__);   \
@@ -68,15 +66,10 @@ __FBSDID("$FreeBSD$");
 #define	BCM_GPIO_PINS		54
 #define	BCM_GPIO_PINS_PER_BANK	32
 
-#ifdef INTRNG
 #define	BCM_GPIO_DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |	\
     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_INTR_LEVEL_LOW |		\
     GPIO_INTR_LEVEL_HIGH | GPIO_INTR_EDGE_RISING |			\
     GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH)
-#else
-#define	BCM_GPIO_DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |	\
-    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
-#endif
 
 static struct resource_spec bcm_gpio_res_spec[] = {
 	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
@@ -90,14 +83,12 @@ struct bcm_gpio_sysctl {
 	uint32_t		pin;
 };
 
-#ifdef INTRNG
 struct bcm_gpio_irqsrc {
 	struct intr_irqsrc	bgi_isrc;
 	uint32_t		bgi_irq;
 	uint32_t		bgi_mode;
 	uint32_t		bgi_mask;
 };
-#endif
 
 struct bcm_gpio_softc {
 	device_t		sc_dev;
@@ -111,16 +102,8 @@ struct bcm_gpio_softc {
 	int			sc_ro_npins;
 	int			sc_ro_pins[BCM_GPIO_PINS];
 	struct gpio_pin		sc_gpio_pins[BCM_GPIO_PINS];
-#ifndef INTRNG
-	struct intr_event *	sc_events[BCM_GPIO_PINS];
-#endif
 	struct bcm_gpio_sysctl	sc_sysctl[BCM_GPIO_PINS];
-#ifdef INTRNG
 	struct bcm_gpio_irqsrc	sc_isrcs[BCM_GPIO_PINS];
-#else
-	enum intr_trigger	sc_irq_trigger[BCM_GPIO_PINS];
-	enum intr_polarity	sc_irq_polarity[BCM_GPIO_PINS];
-#endif
 };
 
 enum bcm_gpio_pud {
@@ -165,12 +148,10 @@ static struct ofw_compat_data compat_data[] = {
 
 static struct bcm_gpio_softc *bcm_gpio_sc = NULL;
 
-#ifdef INTRNG
 static int bcm_gpio_intr_bank0(void *arg);
 static int bcm_gpio_intr_bank1(void *arg);
 static int bcm_gpio_pic_attach(struct bcm_gpio_softc *sc);
 static int bcm_gpio_pic_detach(struct bcm_gpio_softc *sc);
-#endif
 
 static int
 bcm_gpio_pin_is_ro(struct bcm_gpio_softc *sc, int pin)
@@ -703,42 +684,6 @@ bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
 	return (0);
 }
 
-#ifndef INTRNG
-static int
-bcm_gpio_intr(void *arg)
-{
-	int bank_last, irq;
-	struct bcm_gpio_softc *sc;
-	struct intr_event *event;
-	uint32_t bank, mask, reg;
-
-	sc = (struct bcm_gpio_softc *)arg;
-	reg = 0;
-	bank_last = -1;
-	for (irq = 0; irq < BCM_GPIO_PINS; irq++) {
-		bank = BCM_GPIO_BANK(irq);
-		mask = BCM_GPIO_MASK(irq);
-		if (bank != bank_last) {
-			reg = BCM_GPIO_READ(sc, BCM_GPIO_GPEDS(bank));
-			bank_last = bank;
-		}
-		if (reg & mask) {
-			event = sc->sc_events[irq];
-			if (event != NULL && !TAILQ_EMPTY(&event->ie_handlers))
-				intr_event_handle(event, NULL);
-			else {
-				device_printf(sc->sc_dev, "Stray IRQ %d\n",
-				    irq);
-			}
-			/* Clear the Status bit by writing '1' to it. */
-			BCM_GPIO_WRITE(sc, BCM_GPIO_GPEDS(bank), mask);
-		}
-	}
-
-	return (FILTER_HANDLED);
-}
-#endif
-
 static int
 bcm_gpio_probe(device_t dev)
 {
@@ -753,7 +698,6 @@ bcm_gpio_probe(device_t dev)
 	return (BUS_PROBE_DEFAULT);
 }
 
-#ifdef INTRNG
 static int
 bcm_gpio_intr_attach(device_t dev)
 {
@@ -795,41 +739,6 @@ bcm_gpio_intr_detach(device_t dev)
 	bcm_gpio_pic_detach(sc);
 }
 
-#else
-static int
-bcm_gpio_intr_attach(device_t dev)
-{
-	struct bcm_gpio_softc *sc;
-	int i;
-
-	sc = device_get_softc(dev);
-	for (i = 0; i < BCM_GPIO_IRQS; i++) {
-		if (bus_setup_intr(dev, sc->sc_res[i + 1],
-		    INTR_TYPE_MISC | INTR_MPSAFE, bcm_gpio_intr,
-		    NULL, sc, &sc->sc_intrhand[i]) != 0) {
-			return (-1);
-		}
-	}
-
-	return (0);
-}
-
-static void
-bcm_gpio_intr_detach(device_t dev)
-{
-	struct bcm_gpio_softc *sc;
-	int i;
-
-	sc = device_get_softc(dev);
-	for (i = 0; i < BCM_GPIO_IRQS; i++) {
-		if (sc->sc_intrhand[i]) {
-			bus_teardown_intr(dev, sc->sc_res[i + 1],
-			    sc->sc_intrhand[i]);
-		}
-	}
-}
-#endif
-
 static int
 bcm_gpio_attach(device_t dev)
 {
@@ -874,11 +783,6 @@ bcm_gpio_attach(device_t dev)
 		sc->sc_gpio_pins[i].gp_pin = j;
 		sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS;
 		sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func);
-#ifndef INTRNG
-		/* The default is active-low interrupts. */
-		sc->sc_irq_trigger[i] = INTR_TRIGGER_LEVEL;
-		sc->sc_irq_polarity[i] = INTR_POLARITY_LOW;
-#endif
 		i++;
 	}
 	sc->sc_gpio_npins = i;
@@ -904,7 +808,6 @@ bcm_gpio_detach(device_t dev)
 	return (EBUSY);
 }
 
-#ifdef INTRNG
 static inline void
 bcm_gpio_modify(struct bcm_gpio_softc *sc, uint32_t reg, uint32_t mask,
     bool set_bits)
@@ -1275,179 +1178,6 @@ bcm_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
 	return (0);
 }
 
-#else
-static uint32_t
-bcm_gpio_intr_reg(struct bcm_gpio_softc *sc, unsigned int irq, uint32_t bank)
-{
-
-	if (irq > BCM_GPIO_PINS)
-		return (0);
-	if (sc->sc_irq_trigger[irq] == INTR_TRIGGER_LEVEL) {
-		if (sc->sc_irq_polarity[irq] == INTR_POLARITY_LOW)
-			return (BCM_GPIO_GPLEN(bank));
-		else if (sc->sc_irq_polarity[irq] == INTR_POLARITY_HIGH)
-			return (BCM_GPIO_GPHEN(bank));
-	} else if (sc->sc_irq_trigger[irq] == INTR_TRIGGER_EDGE) {
-		if (sc->sc_irq_polarity[irq] == INTR_POLARITY_LOW)
-			return (BCM_GPIO_GPFEN(bank));
-		else if (sc->sc_irq_polarity[irq] == INTR_POLARITY_HIGH)
-			return (BCM_GPIO_GPREN(bank));
-	}
-
-	return (0);
-}
-
-static void
-bcm_gpio_mask_irq(void *source)
-{
-	uint32_t bank, mask, reg;
-	unsigned int irq;
-
-	irq = (unsigned int)source;
-	if (irq > BCM_GPIO_PINS)
-		return;
-	if (bcm_gpio_pin_is_ro(bcm_gpio_sc, irq))
-		return;
-	bank = BCM_GPIO_BANK(irq);
-	mask = BCM_GPIO_MASK(irq);
-	BCM_GPIO_LOCK(bcm_gpio_sc);
-	reg = bcm_gpio_intr_reg(bcm_gpio_sc, irq, bank);
-	if (reg != 0)
-		BCM_GPIO_CLEAR_BITS(bcm_gpio_sc, reg, mask);
-	BCM_GPIO_UNLOCK(bcm_gpio_sc);
-}
-
-static void
-bcm_gpio_unmask_irq(void *source)
-{
-	uint32_t bank, mask, reg;
-	unsigned int irq;
-
-	irq = (unsigned int)source;
-	if (irq > BCM_GPIO_PINS)
-		return;
-	if (bcm_gpio_pin_is_ro(bcm_gpio_sc, irq))
-		return;
-	bank = BCM_GPIO_BANK(irq);
-	mask = BCM_GPIO_MASK(irq);
-	BCM_GPIO_LOCK(bcm_gpio_sc);
-	reg = bcm_gpio_intr_reg(bcm_gpio_sc, irq, bank);
-	if (reg != 0)
-		BCM_GPIO_SET_BITS(bcm_gpio_sc, reg, mask);
-	BCM_GPIO_UNLOCK(bcm_gpio_sc);
-}
-
-static int
-bcm_gpio_activate_resource(device_t bus, device_t child, int type, int rid,
-	struct resource *res)
-{
-	int pin;
-
-	if (type != SYS_RES_IRQ)
-		return (ENXIO);
-	/* Unmask the interrupt. */
-	pin = rman_get_start(res);
-	bcm_gpio_unmask_irq((void *)pin);
-
-	return (0);
-}
-
-static int
-bcm_gpio_deactivate_resource(device_t bus, device_t child, int type, int rid,
-	struct resource *res)
-{
-	int pin;
-
-	if (type != SYS_RES_IRQ)
-		return (ENXIO);
-	/* Mask the interrupt. */
-	pin = rman_get_start(res);
-	bcm_gpio_mask_irq((void *)pin);
-
-	return (0);
-}
-
-static int
-bcm_gpio_config_intr(device_t dev, int irq, enum intr_trigger trig,
-	enum intr_polarity pol)
-{
-	int bank;
-	struct bcm_gpio_softc *sc;
-	uint32_t mask, oldreg, reg;
-
-	if (irq > BCM_GPIO_PINS)
-		return (EINVAL);
-	/* There is no standard trigger or polarity. */
-	if (trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM)
-		return (EINVAL);
-	sc = device_get_softc(dev);
-	if (bcm_gpio_pin_is_ro(sc, irq))
-		return (EINVAL);
-	bank = BCM_GPIO_BANK(irq);
-	mask = BCM_GPIO_MASK(irq);
-	BCM_GPIO_LOCK(sc);
-	oldreg = bcm_gpio_intr_reg(sc, irq, bank);
-	sc->sc_irq_trigger[irq] = trig;
-	sc->sc_irq_polarity[irq] = pol;
-	reg = bcm_gpio_intr_reg(sc, irq, bank);
-	if (reg != 0)
-		BCM_GPIO_SET_BITS(sc, reg, mask);
-	if (reg != oldreg && oldreg != 0)
-		BCM_GPIO_CLEAR_BITS(sc, oldreg, mask);
-	BCM_GPIO_UNLOCK(sc);
-
-	return (0);
-}
-
-static int
-bcm_gpio_setup_intr(device_t bus, device_t child, struct resource *ires,
-	int flags, driver_filter_t *filt, driver_intr_t *handler,
-	void *arg, void **cookiep)
-{
-	struct bcm_gpio_softc *sc;
-	struct intr_event *event;
-	int pin, error;
-
-	sc = device_get_softc(bus);
-	pin = rman_get_start(ires);
-	if (pin > BCM_GPIO_PINS)
-		panic("%s: bad pin %d", __func__, pin);
-	event = sc->sc_events[pin];
-	if (event == NULL) {
-		error = intr_event_create(&event, (void *)pin, 0, pin, 
-		    bcm_gpio_mask_irq, bcm_gpio_unmask_irq, NULL, NULL,
-		    "gpio%d pin%d:", device_get_unit(bus), pin);
-		if (error != 0)
-			return (error);
-		sc->sc_events[pin] = event;
-	}
-	intr_event_add_handler(event, device_get_nameunit(child), filt,
-	    handler, arg, intr_priority(flags), flags, cookiep);
-
-	return (0);
-}
-
-static int
-bcm_gpio_teardown_intr(device_t dev, device_t child, struct resource *ires,
-	void *cookie)
-{
-	struct bcm_gpio_softc *sc;
-	int pin, err;
-
-	sc = device_get_softc(dev);
-	pin = rman_get_start(ires);
-	if (pin > BCM_GPIO_PINS)
-		panic("%s: bad pin %d", __func__, pin);
-	if (sc->sc_events[pin] == NULL)
-		panic("Trying to teardown unoccupied IRQ");
-	err = intr_event_remove_handler(cookie);
-	if (!err)
-		sc->sc_events[pin] = NULL;
-
-	return (err);
-}
-#endif
-
 static phandle_t
 bcm_gpio_get_node(device_t bus, device_t dev)
 {
@@ -1473,7 +1203,6 @@ static device_method_t bcm_gpio_methods[] = {
 	DEVMETHOD(gpio_pin_set,		bcm_gpio_pin_set),
 	DEVMETHOD(gpio_pin_toggle,	bcm_gpio_pin_toggle),
 
-#ifdef INTRNG
 	/* Interrupt controller interface */
 	DEVMETHOD(pic_disable_intr,	bcm_gpio_pic_disable_intr),
 	DEVMETHOD(pic_enable_intr,	bcm_gpio_pic_enable_intr),
@@ -1483,14 +1212,7 @@ static device_method_t bcm_gpio_methods[] = {
 	DEVMETHOD(pic_pre_ithread,	bcm_gpio_pic_pre_ithread),
 	DEVMETHOD(pic_setup_intr,	bcm_gpio_pic_setup_intr),
 	DEVMETHOD(pic_teardown_intr,	bcm_gpio_pic_teardown_intr),
-#else
-	/* Bus interface */
-	DEVMETHOD(bus_activate_resource,	bcm_gpio_activate_resource),
-	DEVMETHOD(bus_deactivate_resource,	bcm_gpio_deactivate_resource),
-	DEVMETHOD(bus_config_intr,	bcm_gpio_config_intr),
-	DEVMETHOD(bus_setup_intr,	bcm_gpio_setup_intr),
-	DEVMETHOD(bus_teardown_intr,	bcm_gpio_teardown_intr),
-#endif
+
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_node,	bcm_gpio_get_node),
 
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_intr.c b/sys/arm/broadcom/bcm2835/bcm2835_intr.c
index 9f7bd7f44d32..f3a5a2832845 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_intr.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_intr.c
@@ -48,13 +48,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef SOC_BCM2836
-#include 
-#endif
-
-#ifdef INTRNG
 #include "pic_if.h"
-#endif
 
 #define	INTC_PENDING_BASIC	0x00
 #define	INTC_PENDING_BANK1	0x04
@@ -105,17 +99,10 @@ __FBSDID("$FreeBSD$");
 #define	BANK1_END	(BANK1_START + 32 - 1)
 #define	BANK2_START	(BANK1_START + 32)
 #define	BANK2_END	(BANK2_START + 32 - 1)
-#ifndef INTRNG
-#define	BANK3_START	(BANK2_START + 32)
-#define	BANK3_END	(BANK3_START + 32 - 1)
-#endif
 
 #define	IS_IRQ_BASIC(n)	(((n) >= 0) && ((n) < BANK1_START))
 #define	IS_IRQ_BANK1(n)	(((n) >= BANK1_START) && ((n) <= BANK1_END))
 #define	IS_IRQ_BANK2(n)	(((n) >= BANK2_START) && ((n) <= BANK2_END))
-#ifndef INTRNG
-#define	ID_IRQ_BCM2836(n) (((n) >= BANK3_START) && ((n) <= BANK3_END))
-#endif
 #define	IRQ_BANK1(n)	((n) - BANK1_START)
 #define	IRQ_BANK2(n)	((n) - BANK2_START)
 
@@ -125,7 +112,6 @@ __FBSDID("$FreeBSD$");
 #define dprintf(fmt, args...)
 #endif
 
-#ifdef INTRNG
 #define BCM_INTC_NIRQS		72	/* 8 + 32 + 32 */
 
 struct bcm_intc_irqsrc {
@@ -135,18 +121,15 @@ struct bcm_intc_irqsrc {
 	uint16_t		bii_enable_reg;
 	uint32_t		bii_mask;
 };
-#endif
 
 struct bcm_intc_softc {
 	device_t		sc_dev;
 	struct resource *	intc_res;
 	bus_space_tag_t		intc_bst;
 	bus_space_handle_t	intc_bsh;
-#ifdef INTRNG
 	struct resource *	intc_irq_res;
 	void *			intc_irq_hdl;
 	struct bcm_intc_irqsrc	intc_isrcs[BCM_INTC_NIRQS];
-#endif
 };
 
 static struct bcm_intc_softc *bcm_intc_sc = NULL;
@@ -156,7 +139,6 @@ static struct bcm_intc_softc *bcm_intc_sc = NULL;
 #define	intc_write_4(_sc, reg, val)		\
     bus_space_write_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg), (val))
 
-#ifdef INTRNG
 static inline void
 bcm_intc_isrc_mask(struct bcm_intc_softc *sc, struct bcm_intc_irqsrc *bii)
 {
@@ -375,7 +357,6 @@ bcm_intc_pic_register(struct bcm_intc_softc *sc, intptr_t xref)
 
 	return (0);
 }
-#endif
 
 static int
 bcm_intc_probe(device_t dev)
@@ -396,9 +377,7 @@ bcm_intc_attach(device_t dev)
 {
 	struct		bcm_intc_softc *sc = device_get_softc(dev);
 	int		rid = 0;
-#ifdef INTRNG
 	intptr_t	xref;
-#endif
 	sc->sc_dev = dev;
 
 	if (bcm_intc_sc)
@@ -410,7 +389,6 @@ bcm_intc_attach(device_t dev)
 		return (ENXIO);
 	}
 
-#ifdef INTRNG
 	xref = OF_xref_from_node(ofw_bus_get_node(dev));
 	if (bcm_intc_pic_register(sc, xref) != 0) {
 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->intc_res);
@@ -435,7 +413,6 @@ bcm_intc_attach(device_t dev)
 			return (ENXIO);
 		}
 	}
-#endif
 	sc->intc_bst = rman_get_bustag(sc->intc_res);
 	sc->intc_bsh = rman_get_bushandle(sc->intc_res);
 
@@ -448,14 +425,12 @@ static device_method_t bcm_intc_methods[] = {
 	DEVMETHOD(device_probe,		bcm_intc_probe),
 	DEVMETHOD(device_attach,	bcm_intc_attach),
 
-#ifdef INTRNG
 	DEVMETHOD(pic_disable_intr,	bcm_intc_disable_intr),
 	DEVMETHOD(pic_enable_intr,	bcm_intc_enable_intr),
 	DEVMETHOD(pic_map_intr,		bcm_intc_map_intr),
 	DEVMETHOD(pic_post_filter,	bcm_intc_post_filter),
 	DEVMETHOD(pic_post_ithread,	bcm_intc_post_ithread),
 	DEVMETHOD(pic_pre_ithread,	bcm_intc_pre_ithread),
-#endif
 
 	{ 0, 0 }
 };
@@ -470,105 +445,3 @@ static devclass_t bcm_intc_devclass;
 
 EARLY_DRIVER_MODULE(intc, simplebus, bcm_intc_driver, bcm_intc_devclass,
     0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
-
-#ifndef INTRNG
-int
-arm_get_next_irq(int last_irq)
-{
-	struct bcm_intc_softc *sc = bcm_intc_sc;
-	uint32_t pending;
-	int32_t irq = last_irq + 1;
-#ifdef SOC_BCM2836
-	int ret;
-#endif
-
-	/* Sanity check */
-	if (irq < 0)
-		irq = 0;
-
-#ifdef SOC_BCM2836
-	if ((ret = bcm2836_get_next_irq(irq)) < 0)
-		return (-1);
-	if (ret != BCM2836_GPU_IRQ)
-		return (ret + BANK3_START);
-#endif
-
-	/* TODO: should we mask last_irq? */
-	if (irq < BANK1_START) {
-		pending = intc_read_4(sc, INTC_PENDING_BASIC);
-		if ((pending & 0xFF) == 0) {
-			irq  = BANK1_START;	/* skip to next bank */
-		} else do {
-			if (pending & (1 << irq))
-				return irq;
-			irq++;
-		} while (irq < BANK1_START);
-	}
-	if (irq < BANK2_START) {
-		pending = intc_read_4(sc, INTC_PENDING_BANK1);
-		if (pending == 0) {
-			irq  = BANK2_START;	/* skip to next bank */
-		} else do {
-			if (pending & (1 << IRQ_BANK1(irq)))
-				return irq;
-			irq++;
-		} while (irq < BANK2_START);
-	}
-	if (irq < BANK3_START) {
-		pending = intc_read_4(sc, INTC_PENDING_BANK2);
-		if (pending != 0) do {
-			if (pending & (1 << IRQ_BANK2(irq)))
-				return irq;
-			irq++;
-		} while (irq < BANK3_START);
-	}
-	return (-1);
-}
-
-void
-arm_mask_irq(uintptr_t nb)
-{
-	struct bcm_intc_softc *sc = bcm_intc_sc;
-	dprintf("%s: %d\n", __func__, nb);
-
-	if (IS_IRQ_BASIC(nb))
-		intc_write_4(sc, INTC_DISABLE_BASIC, (1 << nb));
-	else if (IS_IRQ_BANK1(nb))
-		intc_write_4(sc, INTC_DISABLE_BANK1, (1 << IRQ_BANK1(nb)));
-	else if (IS_IRQ_BANK2(nb))
-		intc_write_4(sc, INTC_DISABLE_BANK2, (1 << IRQ_BANK2(nb)));
-#ifdef SOC_BCM2836
-	else if (ID_IRQ_BCM2836(nb))
-		bcm2836_mask_irq(nb - BANK3_START);
-#endif
-	else
-		printf("arm_mask_irq: Invalid IRQ number: %d\n", nb);
-}
-
-void
-arm_unmask_irq(uintptr_t nb)
-{
-	struct bcm_intc_softc *sc = bcm_intc_sc;
-	dprintf("%s: %d\n", __func__, nb);
-
-	if (IS_IRQ_BASIC(nb))
-		intc_write_4(sc, INTC_ENABLE_BASIC, (1 << nb));
-	else if (IS_IRQ_BANK1(nb))
-		intc_write_4(sc, INTC_ENABLE_BANK1, (1 << IRQ_BANK1(nb)));
-	else if (IS_IRQ_BANK2(nb))
-		intc_write_4(sc, INTC_ENABLE_BANK2, (1 << IRQ_BANK2(nb)));
-#ifdef SOC_BCM2836
-	else if (ID_IRQ_BCM2836(nb))
-		bcm2836_unmask_irq(nb - BANK3_START);
-#endif
-	else
-		printf("arm_mask_irq: Invalid IRQ number: %d\n", nb);
-}
-
-#ifdef SMP
-void
-intr_pic_init_secondary(void)
-{
-}
-#endif
-#endif
diff --git a/sys/arm/broadcom/bcm2835/bcm2836.c b/sys/arm/broadcom/bcm2835/bcm2836.c
index d90e58441a16..fce9fcf8e2b4 100644
--- a/sys/arm/broadcom/bcm2835/bcm2836.c
+++ b/sys/arm/broadcom/bcm2835/bcm2836.c
@@ -53,26 +53,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef INTRNG
 #include "pic_if.h"
-#else
-#include 
 
-#define	ARM_LOCAL_BASE	0x40000000
-#define	ARM_LOCAL_SIZE	0x00001000
-
-#define	ARM_LOCAL_CONTROL		0x00
-#define	ARM_LOCAL_PRESCALER		0x08
-#define	 PRESCALER_19_2			0x80000000 /* 19.2 MHz */
-#define	ARM_LOCAL_INT_TIMER(n)		(0x40 + (n) * 4)
-#define	ARM_LOCAL_INT_MAILBOX(n)	(0x50 + (n) * 4)
-#define	ARM_LOCAL_INT_PENDING(n)	(0x60 + (n) * 4)
-#define	 INT_PENDING_MASK		0x011f
-#define	MAILBOX0_IRQ			4
-#define	MAILBOX0_IRQEN			(1 << 0)
-#endif
-
-#ifdef INTRNG
 #define	BCM_LINTC_CONTROL_REG		0x00
 #define	BCM_LINTC_PRESCALER_REG		0x08
 #define	BCM_LINTC_GPU_ROUTING_REG	0x0c
@@ -751,163 +733,3 @@ static devclass_t bcm_lintc_devclass;
 
 EARLY_DRIVER_MODULE(local_intc, simplebus, bcm_lintc_driver, bcm_lintc_devclass,
     0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
-#else
-/*
- * A driver for features of the bcm2836.
- */
-
-struct bcm2836_softc {
-	device_t	 sc_dev;
-	struct resource *sc_mem;
-};
-
-static device_identify_t bcm2836_identify;
-static device_probe_t bcm2836_probe;
-static device_attach_t bcm2836_attach;
-
-struct bcm2836_softc *softc;
-
-static void
-bcm2836_identify(driver_t *driver, device_t parent)
-{
-
-	if (BUS_ADD_CHILD(parent, 0, "bcm2836", -1) == NULL)
-		device_printf(parent, "add child failed\n");
-}
-
-static int
-bcm2836_probe(device_t dev)
-{
-
-	if (softc != NULL)
-		return (ENXIO);
-
-	device_set_desc(dev, "Broadcom bcm2836");
-
-	return (BUS_PROBE_DEFAULT);
-}
-
-static int
-bcm2836_attach(device_t dev)
-{
-	int i, rid;
-
-	softc = device_get_softc(dev);
-	softc->sc_dev = dev;
-
-	rid = 0;
-	softc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
-	    ARM_LOCAL_BASE, ARM_LOCAL_BASE + ARM_LOCAL_SIZE, ARM_LOCAL_SIZE,
-	    RF_ACTIVE);
-	if (softc->sc_mem == NULL) {
-		device_printf(dev, "could not allocate memory resource\n");
-		return (ENXIO);
-	}
-
-	bus_write_4(softc->sc_mem, ARM_LOCAL_CONTROL, 0);
-	bus_write_4(softc->sc_mem, ARM_LOCAL_PRESCALER, PRESCALER_19_2);
-
-	for (i = 0; i < 4; i++)
-		bus_write_4(softc->sc_mem, ARM_LOCAL_INT_TIMER(i), 0);
-
-	for (i = 0; i < 4; i++)
-		bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(i), 1);
-
-	return (0);
-}
-
-int
-bcm2836_get_next_irq(int last_irq)
-{
-	uint32_t reg;
-	int cpu;
-	int irq;
-
-	cpu = PCPU_GET(cpuid);
-
-	reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_PENDING(cpu));
-	reg &= INT_PENDING_MASK;
-	if (reg == 0)
-		return (-1);
-
-	irq = ffs(reg) - 1;
-
-	return (irq);
-}
-
-void
-bcm2836_mask_irq(uintptr_t irq)
-{
-	uint32_t reg;
-#ifdef SMP
-	int cpu;
-#endif
-	int i;
-
-	if (irq < MAILBOX0_IRQ) {
-		for (i = 0; i < 4; i++) {
-			reg = bus_read_4(softc->sc_mem,
-			    ARM_LOCAL_INT_TIMER(i));
-			reg &= ~(1 << irq);
-			bus_write_4(softc->sc_mem,
-			    ARM_LOCAL_INT_TIMER(i), reg);
-		}
-#ifdef SMP
-	} else if (irq == MAILBOX0_IRQ) {
-		/* Mailbox 0 for IPI */
-		cpu = PCPU_GET(cpuid);
-		reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu));
-		reg &= ~MAILBOX0_IRQEN;
-		bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu), reg);
-#endif
-	}
-}
-
-void
-bcm2836_unmask_irq(uintptr_t irq)
-{
-	uint32_t reg;
-#ifdef SMP
-	int cpu;
-#endif
-	int i;
-
-	if (irq < MAILBOX0_IRQ) {
-		for (i = 0; i < 4; i++) {
-			reg = bus_read_4(softc->sc_mem,
-			    ARM_LOCAL_INT_TIMER(i));
-			reg |= (1 << irq);
-			bus_write_4(softc->sc_mem,
-			    ARM_LOCAL_INT_TIMER(i), reg);
-		}
-#ifdef SMP
-	} else if (irq == MAILBOX0_IRQ) {
-		/* Mailbox 0 for IPI */
-		cpu = PCPU_GET(cpuid);
-		reg = bus_read_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu));
-		reg |= MAILBOX0_IRQEN;
-		bus_write_4(softc->sc_mem, ARM_LOCAL_INT_MAILBOX(cpu), reg);
-#endif
-	}
-}
-
-static device_method_t bcm2836_methods[] = {
-	/* Device interface */
-	DEVMETHOD(device_identify,	bcm2836_identify),
-	DEVMETHOD(device_probe,		bcm2836_probe),
-	DEVMETHOD(device_attach,	bcm2836_attach),
-
-	DEVMETHOD_END
-};
-
-static devclass_t bcm2836_devclass;
-
-static driver_t bcm2836_driver = {
-	"bcm2836",
-	bcm2836_methods,
-	sizeof(struct bcm2836_softc),
-};
-
-EARLY_DRIVER_MODULE(bcm2836, nexus, bcm2836_driver, bcm2836_devclass, 0, 0,
-    BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
-#endif
diff --git a/sys/arm/broadcom/bcm2835/bcm2836.h b/sys/arm/broadcom/bcm2835/bcm2836.h
deleted file mode 100644
index 6068975ee79f..000000000000
--- a/sys/arm/broadcom/bcm2835/bcm2836.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2015 Andrew Turner.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _BCM2815_BCM2836_H
-#define	_BCM2815_BCM2836_H
-
-#ifndef INTRNG
-#define	BCM2836_GPU_IRQ		8
-
-int bcm2836_get_next_irq(int);
-void bcm2836_mask_irq(uintptr_t);
-void bcm2836_unmask_irq(uintptr_t);
-#endif
-#endif
diff --git a/sys/arm/broadcom/bcm2835/bcm2836_mp.c b/sys/arm/broadcom/bcm2835/bcm2836_mp.c
index 2f18470af7db..6caaa504fbb1 100644
--- a/sys/arm/broadcom/bcm2835/bcm2836_mp.c
+++ b/sys/arm/broadcom/bcm2835/bcm2836_mp.c
@@ -142,43 +142,3 @@ bcm2836_mp_start_ap(platform_t plat)
 		CPU_SET(i, &all_cpus);
 	}
 }
-
-#ifndef INTRNG
-void
-pic_ipi_send(cpuset_t cpus, u_int ipi)
-{
-	int i;
-
-	dsb();
-	for (i = 0; i < mp_ncpus; i++) {
-		if (CPU_ISSET(i, &cpus))
-			BSWR4(MBOX0SET_CORE(i), 1 << ipi);
-	}
-	wmb();
-}
-
-int
-pic_ipi_read(int i)
-{
-	uint32_t val;
-	int cpu, ipi;
-
-	cpu = PCPU_GET(cpuid);
-	dsb();
-	if (i != -1) {
-		val = BSRD4(MBOX0CLR_CORE(cpu));
-		if (val == 0)
-			return (0);
-		ipi = ffs(val) - 1;
-		BSWR4(MBOX0CLR_CORE(cpu), 1 << ipi);
-		dsb();
-		return (ipi);
-	}
-	return (0x3ff);
-}
-
-void
-pic_ipi_clear(int ipi)
-{
-}
-#endif
diff --git a/sys/arm/broadcom/bcm2835/files.bcm283x b/sys/arm/broadcom/bcm2835/files.bcm283x
index 21c99c146065..08acfaf4706d 100644
--- a/sys/arm/broadcom/bcm2835/files.bcm283x
+++ b/sys/arm/broadcom/bcm2835/files.bcm283x
@@ -1,7 +1,6 @@
 # $FreeBSD$
 
 arm/broadcom/bcm2835/bcm2835_bsc.c		optional bcm2835_bsc
-arm/broadcom/bcm2835/bcm2835_common.c		optional fdt
 arm/broadcom/bcm2835/bcm2835_cpufreq.c		standard
 arm/broadcom/bcm2835/bcm2835_dma.c		standard
 arm/broadcom/bcm2835/bcm2835_fb.c		optional sc
diff --git a/sys/arm/qemu/files.qemu b/sys/arm/qemu/files.qemu
index 8e2e4973bbc5..600cda594673 100644
--- a/sys/arm/qemu/files.qemu
+++ b/sys/arm/qemu/files.qemu
@@ -8,6 +8,5 @@ kern/kern_clocksource.c			standard
 #
 # Standard qemu virt devices and support.
 #
-arm/qemu/virt_common.c			standard
 arm/qemu/virt_machdep.c			standard
 arm/qemu/virt_mp.c			optional	smp
diff --git a/sys/arm/qemu/virt_common.c b/sys/arm/qemu/virt_common.c
deleted file mode 100644
index cda02e539e66..000000000000
--- a/sys/arm/qemu/virt_common.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 2015 Andrew Turner
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include 
-__FBSDID("$FreeBSD$");
-
-#include "opt_platform.h"
-
-#include 
-#include 
-
-#include 
-
-#include 
-
-#ifndef INTRNG
-fdt_pic_decode_t fdt_pic_table[] = {
-	&gic_decode_fdt,
-	NULL
-};
-#endif
diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c
index ae5bad684241..764f3a0726dc 100644
--- a/sys/arm/ti/aintc.c
+++ b/sys/arm/ti/aintc.c
@@ -48,9 +48,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef INTRNG
 #include "pic_if.h"
-#endif
 
 #define INTC_REVISION		0x00
 #define INTC_SYSCONFIG		0x10
@@ -68,12 +66,10 @@ __FBSDID("$FreeBSD$");
 
 #define INTC_NIRQS	128
 
-#ifdef INTRNG
 struct ti_aintc_irqsrc {
 	struct intr_irqsrc	tai_isrc;
 	u_int			tai_irq;
 };
-#endif
 
 struct ti_aintc_softc {
 	device_t		sc_dev;
@@ -81,9 +77,7 @@ struct ti_aintc_softc {
 	bus_space_tag_t		aintc_bst;
 	bus_space_handle_t	aintc_bsh;
 	uint8_t			ver;
-#ifdef INTRNG
 	struct ti_aintc_irqsrc	aintc_isrcs[INTC_NIRQS];
-#endif
 };
 
 static struct resource_spec ti_aintc_spec[] = {
@@ -91,8 +85,6 @@ static struct resource_spec ti_aintc_spec[] = {
 	{ -1, 0 }
 };
 
-static struct ti_aintc_softc *ti_aintc_sc = NULL;
-
 #define	aintc_read_4(_sc, reg)		\
     bus_space_read_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg))
 #define	aintc_write_4(_sc, reg, val)		\
@@ -105,7 +97,6 @@ static struct ofw_compat_data compat_data[] = {
 	{NULL,		 	0},
 };
 
-#ifdef INTRNG
 static inline void
 ti_aintc_irq_eoi(struct ti_aintc_softc *sc)
 {
@@ -244,16 +235,6 @@ ti_aintc_pic_attach(struct ti_aintc_softc *sc)
 	return (intr_pic_claim_root(sc->sc_dev, xref, ti_aintc_intr, sc, 0));
 }
 
-#else
-static void
-aintc_post_filter(void *arg)
-{
-
-	arm_irq_memory_barrier(0);
-	aintc_write_4(ti_aintc_sc, INTC_CONTROL, 1); /* EOI */
-}
-#endif
-
 static int
 ti_aintc_probe(device_t dev)
 {
@@ -275,9 +256,6 @@ ti_aintc_attach(device_t dev)
 
 	sc->sc_dev = dev;
 
-	if (ti_aintc_sc)
-		return (ENXIO);
-
 	if (bus_alloc_resources(dev, ti_aintc_spec, sc->aintc_res)) {
 		device_printf(dev, "could not allocate resources\n");
 		return (ENXIO);
@@ -286,8 +264,6 @@ ti_aintc_attach(device_t dev)
 	sc->aintc_bst = rman_get_bustag(sc->aintc_res[0]);
 	sc->aintc_bsh = rman_get_bushandle(sc->aintc_res[0]);
 
-	ti_aintc_sc = sc;
-
 	x = aintc_read_4(sc, INTC_REVISION);
 	device_printf(dev, "Revision %u.%u\n",(x >> 4) & 0xF, x & 0xF);
 
@@ -300,14 +276,10 @@ ti_aintc_attach(device_t dev)
 	/*Set Priority Threshold */
 	aintc_write_4(sc, INTC_THRESHOLD, 0xFF);
 
-#ifndef INTRNG
-	arm_post_filter = aintc_post_filter;
-#else
 	if (ti_aintc_pic_attach(sc) != 0) {
 		device_printf(dev, "could not attach PIC\n");
 		return (ENXIO);
 	}
-#endif
 	return (0);
 }
 
@@ -315,14 +287,12 @@ static device_method_t ti_aintc_methods[] = {
 	DEVMETHOD(device_probe,		ti_aintc_probe),
 	DEVMETHOD(device_attach,	ti_aintc_attach),
 
-#ifdef INTRNG
 	DEVMETHOD(pic_disable_intr,	ti_aintc_disable_intr),
 	DEVMETHOD(pic_enable_intr,	ti_aintc_enable_intr),
 	DEVMETHOD(pic_map_intr,		ti_aintc_map_intr),
 	DEVMETHOD(pic_post_filter,	ti_aintc_post_filter),
 	DEVMETHOD(pic_post_ithread,	ti_aintc_post_ithread),
 	DEVMETHOD(pic_pre_ithread,	ti_aintc_pre_ithread),
-#endif
 
 	{ 0, 0 }
 };
@@ -338,46 +308,3 @@ static devclass_t ti_aintc_devclass;
 EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass,
     0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
 SIMPLEBUS_PNP_INFO(compat_data);
-
-#ifndef INTRNG
-int
-arm_get_next_irq(int last_irq)
-{
-	struct ti_aintc_softc *sc = ti_aintc_sc;
-	uint32_t active_irq;
-
-	/* Get the next active interrupt */
-	active_irq = aintc_read_4(sc, INTC_SIR_IRQ);
-
-	/* Check for spurious interrupt */
-	if ((active_irq & 0xffffff80)) {
-		device_printf(sc->sc_dev,
-		    "Spurious interrupt detected (0x%08x)\n", active_irq);
-		aintc_write_4(sc, INTC_SIR_IRQ, 0);
-		return -1;
-	}
-
-	if (active_irq != last_irq)
-		return active_irq;
-	else
-		return -1;
-}
-
-void
-arm_mask_irq(uintptr_t nb)
-{
-	struct ti_aintc_softc *sc = ti_aintc_sc;
-
-	aintc_write_4(sc, INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F)));
-	aintc_write_4(sc, INTC_CONTROL, 1); /* EOI */
-}
-
-void
-arm_unmask_irq(uintptr_t nb)
-{
-	struct ti_aintc_softc *sc = ti_aintc_sc;
-
-	arm_irq_memory_barrier(nb);
-	aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F)));
-}
-#endif
diff --git a/sys/arm/ti/files.ti b/sys/arm/ti/files.ti
index 6f571c6867b6..49f37c1a0398 100644
--- a/sys/arm/ti/files.ti
+++ b/sys/arm/ti/files.ti
@@ -2,7 +2,6 @@
 
 kern/kern_clocksource.c				standard
 
-arm/ti/ti_common.c				standard
 arm/ti/ti_cpuid.c				standard
 arm/ti/ti_hwmods.c				standard
 arm/ti/ti_machdep.c				standard
diff --git a/sys/arm/ti/ti_common.c b/sys/arm/ti/ti_common.c
deleted file mode 100644
index 64a7830f6a5c..000000000000
--- a/sys/arm/ti/ti_common.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-
- * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD.
- * All rights reserved.
- *
- * Developed by Semihalf.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of MARVELL nor the names of contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "opt_platform.h"
-
-#include 
-__FBSDID("$FreeBSD$");
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-
-#ifndef INTRNG
-#ifdef SOC_TI_AM335X
-static int
-fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
-    int *pol)
-{
-
-	if (!fdt_is_compatible(node, "ti,aintc") &&
-	    !fdt_is_compatible(node, "ti,am33xx-intc"))
-		return (ENXIO);
-
-	*interrupt = fdt32_to_cpu(intr[0]);
-	*trig = INTR_TRIGGER_CONFORM;
-	*pol = INTR_POLARITY_CONFORM;
-
-	return (0);
-}
-#endif
-
-fdt_pic_decode_t fdt_pic_table[] = {
-#if defined(SOC_OMAP4)
-	&gic_decode_fdt,
-#endif
-#ifdef SOC_TI_AM335X
-	&fdt_aintc_decode_ic,
-#endif
-	NULL
-};
-#endif /* !INTRNG */
diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
index 583a65a2c678..fe2b5ff06bdf 100644
--- a/sys/arm/ti/ti_gpio.c
+++ b/sys/arm/ti/ti_gpio.c
@@ -66,9 +66,7 @@ __FBSDID("$FreeBSD$");
 
 #include "gpio_if.h"
 #include "ti_gpio_if.h"
-#ifdef INTRNG
 #include "pic_if.h"
-#endif
 
 #if !defined(SOC_OMAP4) && !defined(SOC_TI_AM335X)
 #error "Unknown SoC"
@@ -121,10 +119,8 @@ __FBSDID("$FreeBSD$");
 static int ti_gpio_intr(void *arg);
 static int ti_gpio_detach(device_t);
 
-#ifdef INTRNG
 static int ti_gpio_pic_attach(struct ti_gpio_softc *sc);
 static int ti_gpio_pic_detach(struct ti_gpio_softc *sc);
-#endif
 
 static u_int
 ti_first_gpio_bank(void)
@@ -321,15 +317,10 @@ ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 	if (ti_gpio_valid_pin(sc, pin) != 0)
 		return (EINVAL);
 
-#ifdef INTRNG
 	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP |
 	    GPIO_PIN_PULLDOWN | GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH |
 	    GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING |
 	    GPIO_INTR_EDGE_BOTH);
-#else
-	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP |
-	    GPIO_PIN_PULLDOWN);
-#endif
 
 	return (0);
 }
@@ -558,43 +549,6 @@ ti_gpio_pin_toggle(device_t dev, uint32_t pin)
 	return (0);
 }
 
-#ifndef INTRNG
-/**
- *	ti_gpio_intr - ISR for all GPIO modules
- *	@arg: the soft context pointer
- *
- *	LOCKING:
- *	Internally locks the context
- *
- */
-static int
-ti_gpio_intr(void *arg)
-{
-	int bank_last, irq;
-	struct intr_event *event;
-	struct ti_gpio_softc *sc;
-	uint32_t reg;
-
-	sc = (struct ti_gpio_softc *)arg;
-	bank_last = -1;
-	reg = 0; /* squelch bogus gcc warning */
-	reg = ti_gpio_intr_status(sc);
-	for (irq = 0; irq < sc->sc_maxpin; irq++) {
-		if ((reg & TI_GPIO_MASK(irq)) == 0)
-			continue;
-		event = sc->sc_events[irq];
-		if (event != NULL && !TAILQ_EMPTY(&event->ie_handlers))
-			intr_event_handle(event, NULL);
-		else
-			device_printf(sc->sc_dev, "Stray IRQ %d\n", irq);
-		/* Ack the IRQ Status bit. */
-		ti_gpio_intr_ack(sc, TI_GPIO_MASK(irq));
-	}
-
-	return (FILTER_HANDLED);
-}
-#endif
-
 static int
 ti_gpio_bank_init(device_t dev)
 {
@@ -667,9 +621,6 @@ static int
 ti_gpio_attach(device_t dev)
 {
 	struct ti_gpio_softc *sc;
-#ifndef INTRNG
-	unsigned int i;
-#endif
 	int err;
 
 	sc = device_get_softc(dev);
@@ -708,34 +659,12 @@ ti_gpio_attach(device_t dev)
 		return (ENXIO);
 	}
 
-#ifdef INTRNG
 	if (ti_gpio_pic_attach(sc) != 0) {
 		device_printf(dev, "WARNING: unable to attach PIC\n");
 		ti_gpio_detach(dev);
 		return (ENXIO);
 	}
-#else
-	/*
-	 * Initialize the interrupt settings.  The default is active-low
-	 * interrupts.
-	 */
-	sc->sc_irq_trigger = malloc(
-	    sizeof(*sc->sc_irq_trigger) * sc->sc_maxpin,
-	    M_DEVBUF, M_WAITOK | M_ZERO);
-	sc->sc_irq_polarity = malloc(
-	    sizeof(*sc->sc_irq_polarity) * sc->sc_maxpin,
-	    M_DEVBUF, M_WAITOK | M_ZERO);
-	for (i = 0; i < sc->sc_maxpin; i++) {
-		sc->sc_irq_trigger[i] = INTR_TRIGGER_LEVEL;
-		sc->sc_irq_polarity[i] = INTR_POLARITY_LOW;
-	}
 
-	sc->sc_events = malloc(sizeof(struct intr_event *) * sc->sc_maxpin,
-	    M_DEVBUF, M_WAITOK | M_ZERO);
-
-	sc->sc_mask_args = malloc(sizeof(struct ti_gpio_mask_arg) * sc->sc_maxpin,
-	    M_DEVBUF, M_WAITOK | M_ZERO);
-#endif
 	/* We need to go through each block and ensure the clocks are running and
 	 * the module is enabled.  It might be better to do this only when the
 	 * pins are configured which would result in less power used if the GPIO
@@ -783,19 +712,8 @@ ti_gpio_detach(device_t dev)
 	if (sc->sc_mem_res != NULL)
 		ti_gpio_intr_clr(sc, 0xffffffff);
 	gpiobus_detach_bus(dev);
-#ifdef	INTRNG
 	if (sc->sc_isrcs != NULL)
 		ti_gpio_pic_detach(sc);
-#else
-	if (sc->sc_events)
-		free(sc->sc_events, M_DEVBUF);
-	if (sc->sc_mask_args)
-		free(sc->sc_mask_args, M_DEVBUF);
-	if (sc->sc_irq_polarity)
-		free(sc->sc_irq_polarity, M_DEVBUF);
-	if (sc->sc_irq_trigger)
-		free(sc->sc_irq_trigger, M_DEVBUF);
-#endif
 	/* Release the memory and IRQ resources. */
 	if (sc->sc_irq_hdl) {
 		bus_teardown_intr(dev, sc->sc_irq_res,
@@ -810,7 +728,6 @@ ti_gpio_detach(device_t dev)
 	return (0);
 }
 
-#ifdef INTRNG
 static inline void
 ti_gpio_rwreg_modify(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask,
     bool set_bits)
@@ -1120,210 +1037,6 @@ ti_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
 	return (0);
 }
 
-#else
-static uint32_t
-ti_gpio_intr_reg(struct ti_gpio_softc *sc, int irq)
-{
-
-	if (ti_gpio_valid_pin(sc, irq) != 0)
-		return (0);
-
-	if (sc->sc_irq_trigger[irq] == INTR_TRIGGER_LEVEL) {
-		if (sc->sc_irq_polarity[irq] == INTR_POLARITY_LOW)
-			return (TI_GPIO_LEVELDETECT0);
-		else if (sc->sc_irq_polarity[irq] == INTR_POLARITY_HIGH)
-			return (TI_GPIO_LEVELDETECT1);
-	} else if (sc->sc_irq_trigger[irq] == INTR_TRIGGER_EDGE) {
-		if (sc->sc_irq_polarity[irq] == INTR_POLARITY_LOW)
-			return (TI_GPIO_FALLINGDETECT);
-		else if (sc->sc_irq_polarity[irq] == INTR_POLARITY_HIGH)
-			return (TI_GPIO_RISINGDETECT);
-	}
-
-	return (0);
-}
-
-static void
-ti_gpio_mask_irq_internal(struct ti_gpio_softc *sc, int irq)
-{
-	uint32_t reg, val;
-
-	if (ti_gpio_valid_pin(sc, irq) != 0)
-		return;
-
-	TI_GPIO_LOCK(sc);
-	ti_gpio_intr_clr(sc, TI_GPIO_MASK(irq));
-	reg = ti_gpio_intr_reg(sc, irq);
-	if (reg != 0) {
-		val = ti_gpio_read_4(sc, reg);
-		val &= ~TI_GPIO_MASK(irq);
-		ti_gpio_write_4(sc, reg, val);
-	}
-	TI_GPIO_UNLOCK(sc);
-}
-
-static void
-ti_gpio_unmask_irq_internal(struct ti_gpio_softc *sc, int irq)
-{
-	uint32_t reg, val;
-
-	if (ti_gpio_valid_pin(sc, irq) != 0)
-		return;
-
-	TI_GPIO_LOCK(sc);
-	reg = ti_gpio_intr_reg(sc, irq);
-	if (reg != 0) {
-		val = ti_gpio_read_4(sc, reg);
-		val |= TI_GPIO_MASK(irq);
-		ti_gpio_write_4(sc, reg, val);
-		ti_gpio_intr_set(sc, TI_GPIO_MASK(irq));
-	}
-	TI_GPIO_UNLOCK(sc);
-}
-
-static void
-ti_gpio_mask_irq(void *source)
-{
-	struct ti_gpio_mask_arg *arg = source;
-
-	ti_gpio_mask_irq_internal(arg->softc, arg->pin);
-}
-
-static void
-ti_gpio_unmask_irq(void *source)
-{
-	struct ti_gpio_mask_arg *arg = source;
-
-	ti_gpio_unmask_irq_internal(arg->softc, arg->pin);
-}
-
-static int
-ti_gpio_activate_resource(device_t dev, device_t child, int type, int rid,
-	struct resource *res)
-{
-	struct ti_gpio_mask_arg mask_arg;
-
-	if (type != SYS_RES_IRQ)
-		return (ENXIO);
-
-	/* Unmask the interrupt. */
-	mask_arg.pin = rman_get_start(res);
-	mask_arg.softc = device_get_softc(dev);
-
-	ti_gpio_unmask_irq((void *)&mask_arg);
-
-	return (0);
-}
-
-static int
-ti_gpio_deactivate_resource(device_t dev, device_t child, int type, int rid,
-	struct resource *res)
-{
-	int pin;
-
-	if (type != SYS_RES_IRQ)
-		return (ENXIO);
-
-	/* Mask the interrupt. */
-	pin = rman_get_start(res);
-	ti_gpio_mask_irq((void *)(uintptr_t)pin);
-
-	return (0);
-}
-
-static int
-ti_gpio_config_intr(device_t dev, int irq, enum intr_trigger trig,
-	enum intr_polarity pol)
-{
-	struct ti_gpio_softc *sc;
-	uint32_t oldreg, reg, val;
-
-	sc = device_get_softc(dev);
-	if (ti_gpio_valid_pin(sc, irq) != 0)
-		return (EINVAL);
-
-	/* There is no standard trigger or polarity. */
-	if (trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM)
-		return (EINVAL);
-
-	TI_GPIO_LOCK(sc);
-	/*
-	 * TRM recommends add the new event before remove the old one to
-	 * avoid losing interrupts.
-	 */
-	oldreg = ti_gpio_intr_reg(sc, irq);
-	sc->sc_irq_trigger[irq] = trig;
-	sc->sc_irq_polarity[irq] = pol;
-	reg = ti_gpio_intr_reg(sc, irq);
-	if (reg != 0) {
-		/* Apply the new settings. */
-		val = ti_gpio_read_4(sc, reg);
-		val |= TI_GPIO_MASK(irq);
-		ti_gpio_write_4(sc, reg, val);
-	}
-	if (reg != oldreg && oldreg != 0) {
-		/* Remove the old settings. */
-		val = ti_gpio_read_4(sc, oldreg);
-		val &= ~TI_GPIO_MASK(irq);
-		ti_gpio_write_4(sc, oldreg, val);
-	}
-	TI_GPIO_UNLOCK(sc);
-
-	return (0);
-}
-
-static int
-ti_gpio_setup_intr(device_t dev, device_t child, struct resource *ires,
-	int flags, driver_filter_t *filt, driver_intr_t *handler,
-	void *arg, void **cookiep)
-{
-	struct ti_gpio_softc *sc;
-	struct intr_event *event;
-	int pin, error;
-
-	sc = device_get_softc(dev);
-	pin = rman_get_start(ires);
-	if (ti_gpio_valid_pin(sc, pin) != 0)
-		panic("%s: bad pin %d", __func__, pin);
-
-	event = sc->sc_events[pin];
-	if (event == NULL) {
-		sc->sc_mask_args[pin].softc = sc;
-		sc->sc_mask_args[pin].pin = pin;
-		error = intr_event_create(&event, (void *)&sc->sc_mask_args[pin], 0,
-		    pin, ti_gpio_mask_irq, ti_gpio_unmask_irq, NULL, NULL,
-		    "gpio%d pin%d:", device_get_unit(dev), pin);
-		if (error != 0)
-			return (error);
-		sc->sc_events[pin] = event;
-	}
-	intr_event_add_handler(event, device_get_nameunit(child), filt,
-	    handler, arg, intr_priority(flags), flags, cookiep);
-
-	return (0);
-}
-
-static int
-ti_gpio_teardown_intr(device_t dev, device_t child, struct resource *ires,
-	void *cookie)
-{
-	struct ti_gpio_softc *sc;
-	int pin, err;
-
-	sc = device_get_softc(dev);
-	pin = rman_get_start(ires);
-	if (ti_gpio_valid_pin(sc, pin) != 0)
-		panic("%s: bad pin %d", __func__, pin);
-	if (sc->sc_events[pin] == NULL)
-		panic("Trying to teardown unoccupied IRQ");
-	err = intr_event_remove_handler(cookie);
-	if (!err)
-		sc->sc_events[pin] = NULL;
-
-	return (err);
-}
-#endif
-
 static phandle_t
 ti_gpio_get_node(device_t bus, device_t dev)
 {
@@ -1347,7 +1060,6 @@ static device_method_t ti_gpio_methods[] = {
 	DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
 	DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
 
-#ifdef INTRNG
 	/* Interrupt controller interface */
 	DEVMETHOD(pic_disable_intr,	ti_gpio_pic_disable_intr),
 	DEVMETHOD(pic_enable_intr,	ti_gpio_pic_enable_intr),
@@ -1357,14 +1069,6 @@ static device_method_t ti_gpio_methods[] = {
 	DEVMETHOD(pic_post_filter,	ti_gpio_pic_post_filter),
 	DEVMETHOD(pic_post_ithread,	ti_gpio_pic_post_ithread),
 	DEVMETHOD(pic_pre_ithread,	ti_gpio_pic_pre_ithread),
-#else
-	/* Bus interface */
-	DEVMETHOD(bus_activate_resource, ti_gpio_activate_resource),
-	DEVMETHOD(bus_deactivate_resource, ti_gpio_deactivate_resource),
-	DEVMETHOD(bus_config_intr, ti_gpio_config_intr),
-	DEVMETHOD(bus_setup_intr, ti_gpio_setup_intr),
-	DEVMETHOD(bus_teardown_intr, ti_gpio_teardown_intr),
-#endif
 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
diff --git a/sys/arm/ti/ti_gpio.h b/sys/arm/ti/ti_gpio.h
index c9785dd97961..3ffc8996c8d3 100644
--- a/sys/arm/ti/ti_gpio.h
+++ b/sys/arm/ti/ti_gpio.h
@@ -39,19 +39,12 @@
  */
 #define	MAX_GPIO_INTRS			8
 
-#ifndef INTRNG
-struct ti_gpio_mask_arg {
-	void	*softc;
-	int	pin;
-};
-#else
 struct ti_gpio_irqsrc {
 	struct intr_irqsrc	tgi_isrc;
 	u_int			tgi_irq;
 	uint32_t		tgi_mask;
 	uint32_t		tgi_mode;
 };
-#endif
 
 /**
  *	Structure that stores the driver context.
@@ -61,11 +54,6 @@ struct ti_gpio_irqsrc {
 struct ti_gpio_softc {
 	device_t		sc_dev;
 	device_t		sc_busdev;
-#ifndef INTRNG
-	/* Interrupt trigger type and level. */
-	enum intr_trigger	*sc_irq_trigger;
-	enum intr_polarity	*sc_irq_polarity;
-#endif
 	int			sc_bank;
 	int			sc_maxpin;
 	struct mtx		sc_mtx;
@@ -74,13 +62,7 @@ struct ti_gpio_softc {
 	struct resource		*sc_mem_res;
 	int			sc_irq_rid;
 	struct resource		*sc_irq_res;
-#ifndef INTRNG
-	/* Interrupt events. */
-	struct intr_event	**sc_events;
-	struct ti_gpio_mask_arg	*sc_mask_args;
-#else
 	struct ti_gpio_irqsrc	*sc_isrcs;
-#endif
 	/* The handle for the register IRQ handlers. */
 	void			*sc_irq_hdl;
 };

From 199f4e8d689236b7da89f0ce827de8db2af5f790 Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Tue, 8 Nov 2016 17:36:19 +0000
Subject: [PATCH 102/127] add missing i386 symbols libgcc_s symbol version map

After r308294 they were missing on i386 (and previously were exported
only accidentally).

Reported by:	antoine
---
 lib/libgcc_s/Version.map | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/lib/libgcc_s/Version.map b/lib/libgcc_s/Version.map
index c997b7a3406b..e6d923a5b1dc 100644
--- a/lib/libgcc_s/Version.map
+++ b/lib/libgcc_s/Version.map
@@ -8,9 +8,12 @@ global:
 	__absvsi2;
 	__addvdi3;
 	__addvsi3;
+	__ashldi3;
 	__ashlti3;
+	__ashrdi3;
 	__ashrti3;
 	__clear_cache;
+	__cmpdi2;
 	__cmpti2;
 	__deregister_frame;
 	__deregister_frame_info;
@@ -19,23 +22,36 @@ global:
 	__divti3;
 	__ffsdi2;
 	__ffsti2;
+	__fixdfdi;
 	__fixdfti;
+	__fixsfdi;
 	__fixsfti;
 	__fixunsdfdi;
+	__fixunsdfsi;
 	__fixunsdfti;
 	__fixunssfdi;
+	__fixunssfsi;
 	__fixunssfti;
 	__fixunsxfdi;
+	__fixunsxfsi;
 	__fixunsxfti;
+	__fixxfdi;
 	__fixxfti;
+	__floatdidf;
+	__floatdisf;
+	__floatdixf;
 	__floattidf;
 	__floattisf;
 	__floattixf;
+	__lshrdi3;
 	__lshrti3;
+	__moddi3;
 	__modti3;
+	__muldi3;
 	__mulvdi3;
 	__mulvsi3;
 	__multi3;
+	__negdi2;
 	__negti2;
 	__negvdi2;
 	__negvsi2;
@@ -47,10 +63,13 @@ global:
 	__register_frame_table;
 	__subvdi3;
 	__subvsi3;
+	__ucmpdi2;
 	__ucmpti2;
 	__udivdi3;
+	__udivmoddi4;
 	__udivmodti4;
 	__udivti3;
+	__umoddi3;
 	__umodti3;
 	_Unwind_DeleteException;
 	_Unwind_Find_FDE;
@@ -82,12 +101,16 @@ GCC_3.3.1 {
 
 GCC_3.4 {
 	__clzdi2;
+	__clzsi2;
 	__clzti2;
 	__ctzdi2;
+	__ctzsi2;
 	__ctzti2;
 	__paritydi2;
+	__paritysi2;
 	__parityti2;
 	__popcountdi2;
+	__popcountsi2;
 	__popcountti2;
 } GCC_3.3.1;
 
@@ -116,6 +139,9 @@ GCC_4.0.0 {
 } GCC_3.4.4;
 
 GCC_4.2.0 {
+	__floatundidf;
+	__floatundisf;
+	__floatundixf;
 	__floatuntidf;
 	__floatuntisf;
 	__floatuntixf;

From 8fc77fff81ed32ae03ed910735e06fe15b4c8d0e Mon Sep 17 00:00:00 2001
From: Conrad Meyer 
Date: Tue, 8 Nov 2016 21:17:24 +0000
Subject: [PATCH 103/127] cam: Zero bio pointer in user-supplied SCSI CCBs

The BUF_TRACKING bio pointer only makes sense for kernel consumers of
CCBs.

PR:		214250
Reported by:	trasz@
Reviewed by:	imp@, markj@
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D8477
---
 sys/cam/cam_xpt.c        | 8 ++++++++
 sys/cam/scsi/scsi_pass.c | 8 ++++++++
 2 files changed, 16 insertions(+)

diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 34018052ed60..7a38d745fcf4 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -414,6 +414,10 @@ xptdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *
 		struct cam_eb *bus;
 
 		inccb = (union ccb *)addr;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+		if (inccb->ccb_h.func_code == XPT_SCSI_IO)
+			inccb->csio.bio = NULL;
+#endif
 
 		bus = xpt_find_bus(inccb->ccb_h.path_id);
 		if (bus == NULL)
@@ -593,6 +597,10 @@ xptdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *
 		unit = ccb->cgdl.unit_number;
 		name = ccb->cgdl.periph_name;
 		base_periph_found = 0;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+		if (ccb->ccb_h.func_code == XPT_SCSI_IO)
+			ccb->csio.bio = NULL;
+#endif
 
 		/*
 		 * Sanity check -- make sure we don't get a null peripheral
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index 68412b4a1157..93e45d0b3706 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -1777,6 +1777,10 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
 		int ccb_malloced;
 
 		inccb = (union ccb *)addr;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+		if (inccb->ccb_h.func_code == XPT_SCSI_IO)
+			inccb->csio.bio = NULL;
+#endif
 
 		/*
 		 * Some CCB types, like scan bus and scan lun can only go
@@ -1875,6 +1879,10 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
 			cam_periph_lock(periph);
 			break;
 		}
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+		if (ccb->ccb_h.func_code == XPT_SCSI_IO)
+			ccb->csio.bio = NULL;
+#endif
 
 		if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
 			if (ccb->csio.cdb_len > IOCDBLEN) {

From b5b4f379e0e3193eece6bd52d6e74d3992a6df4f Mon Sep 17 00:00:00 2001
From: John Baldwin 
Date: Tue, 8 Nov 2016 22:41:11 +0000
Subject: [PATCH 104/127] Pass the correct flag to find_symdef() from
 _rtld_bind().

When symbol versioning was added to rtld, the boolean 'in_plt' argument
to find_symdef() was converted to a bitmask of flags.  The first flag
added was 'SYMLOOK_IN_PLT' which replaced the 'in_plt' bool.  This
happened to still work by accident as SYMLOOK_IN_PLT had the value of 1
which is the same as 'true', so there should be no functional change.

Tested on:	amd64
Reviewed by:	kan
MFC after:	2 weeks
Sponsored by:	DARPA / AFRL
---
 libexec/rtld-elf/rtld.c          | 4 ++--
 libexec/rtld-elf/sparc64/reloc.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index fe25e59ec65a..6c8aff44bf9d 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -713,8 +713,8 @@ _rtld_bind(Obj_Entry *obj, Elf_Size reloff)
 	rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
 
     where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
-    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
-	&lockstate);
+    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, SYMLOOK_IN_PLT,
+	NULL, &lockstate);
     if (def == NULL)
 	rtld_die();
     if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC)
diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c
index 242fb8e4d948..f8534e8712f9 100644
--- a/libexec/rtld-elf/sparc64/reloc.c
+++ b/libexec/rtld-elf/sparc64/reloc.c
@@ -503,7 +503,7 @@ reloc_plt(Obj_Entry *obj)
 		assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT);
 		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		    true, NULL, lockstate);
+		    SYMLOOK_IN_PLT, NULL, lockstate);
 		value = (Elf_Addr)(defobj->relocbase + def->st_value);
 		*where = value;
 	}

From 28323add0916d61a7bcea74f30e9b40b837809ce Mon Sep 17 00:00:00 2001
From: Bryan Drewery 
Date: Tue, 8 Nov 2016 23:59:41 +0000
Subject: [PATCH 105/127] Fix improper use of "its".

Sponsored by:	Dell EMC Isilon
---
 sbin/pfctl/pfctl_optimize.c                                | 4 ++--
 sys/amd64/vmm/io/vlapic.c                                  | 2 +-
 sys/arm/include/profile.h                                  | 2 +-
 sys/arm/ti/omap4/omap4_prcm_clks.c                         | 2 +-
 sys/arm64/arm64/identcpu.c                                 | 2 +-
 sys/cam/cam.h                                              | 2 +-
 sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c       | 2 +-
 sys/cddl/dev/dtrace/aarch64/dtrace_subr.c                  | 2 +-
 sys/cddl/dev/dtrace/arm/dtrace_subr.c                      | 2 +-
 sys/cddl/dev/dtrace/riscv/dtrace_subr.c                    | 2 +-
 sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c         | 2 +-
 sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c          | 2 +-
 sys/dev/aic7xxx/aic7xxx.seq                                | 2 +-
 sys/dev/ath/if_ath_tdma.c                                  | 2 +-
 sys/dev/isci/scil/sati_design.h                            | 2 +-
 sys/dev/isci/scil/sci_base_controller.h                    | 2 +-
 sys/dev/sfxge/common/efx_mcdi.c                            | 2 +-
 sys/dev/sound/pci/hda/hdaa.c                               | 4 ++--
 sys/dev/sound/pci/hda/hdac.c                               | 2 +-
 sys/fs/nullfs/null_vnops.c                                 | 4 ++--
 sys/geom/raid/md_ddf.c                                     | 2 +-
 sys/geom/raid/md_intel.c                                   | 2 +-
 sys/geom/raid/md_jmicron.c                                 | 2 +-
 sys/geom/raid/md_nvidia.c                                  | 2 +-
 sys/geom/raid/md_promise.c                                 | 2 +-
 sys/geom/raid/md_sii.c                                     | 2 +-
 sys/i386/include/cserial.h                                 | 2 +-
 sys/kern/init_main.c                                       | 2 +-
 sys/kern/kern_ctf.c                                        | 2 +-
 sys/kern/subr_firmware.c                                   | 2 +-
 sys/kern/uipc_mbuf.c                                       | 2 +-
 sys/net80211/ieee80211_node.h                              | 2 +-
 sys/netgraph/ng_base.c                                     | 6 +++---
 sys/powerpc/powerpc/mmu_if.m                               | 2 +-
 sys/security/mac/mac_inet.c                                | 2 +-
 sys/vm/vm_pageout.c                                        | 2 +-
 sys/x86/xen/xen_intr.c                                     | 2 +-
 usr.bin/du/du.c                                            | 2 +-
 usr.bin/xlint/lint2/read.c                                 | 2 +-
 usr.sbin/bhyve/bhyverun.c                                  | 2 +-
 usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt | 2 +-
 usr.sbin/newsyslog/newsyslog.c                             | 2 +-
 42 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c
index 563d3c2d1442..37b36f5f0126 100644
--- a/sbin/pfctl/pfctl_optimize.c
+++ b/sbin/pfctl/pfctl_optimize.c
@@ -84,7 +84,7 @@ TAILQ_HEAD(superblocks, superblock);
  * Description of the PF rule structure.
  */
 enum {
-    BARRIER,	/* the presence of the field puts the rule in it's own block */
+    BARRIER,	/* the presence of the field puts the rule in its own block */
     BREAK,	/* the field may not differ between rules in a superblock */
     NOMERGE,	/* the field may not differ between rules when combined */
     COMBINED,	/* the field may itself be combined with other rules */
@@ -104,7 +104,7 @@ static struct pf_rule_field {
 
 
     /*
-     * The presence of these fields in a rule put the rule in it's own
+     * The presence of these fields in a rule put the rule in its own
      * superblock.  Thus it will not be optimized.  It also prevents the
      * rule from being re-ordered at all.
      */
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index cdf411b288be..c5af6b481cf8 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -859,7 +859,7 @@ vlapic_calcdest(struct vm *vm, cpuset_t *dmask, uint32_t dest, bool phys,
 
 		/*
 		 * Logical mode: match each APIC that has a bit set
-		 * in it's LDR that matches a bit in the ldest.
+		 * in its LDR that matches a bit in the ldest.
 		 */
 		CPU_ZERO(dmask);
 		amask = vm_active_cpus(vm);
diff --git a/sys/arm/include/profile.h b/sys/arm/include/profile.h
index a28f33e90d3b..49769a93ee82 100644
--- a/sys/arm/include/profile.h
+++ b/sys/arm/include/profile.h
@@ -89,7 +89,7 @@ typedef u_long	fptrdiff_t;
 	__asm__("ldmfd	sp!, {r0-r3, lr}");				\
 	/*								\
 	 * Return to the caller. Loading lr and pc in one instruction	\
-	 * is deprecated on ARMv7 so we need this on it's own.		\
+	 * is deprecated on ARMv7 so we need this on its own.		\
 	 */								\
 	__asm__("ldmfd	sp!, {pc}");
 void bintr(void);
diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c
index 3aa10f675657..782e7ac71111 100644
--- a/sys/arm/ti/omap4/omap4_prcm_clks.c
+++ b/sys/arm/ti/omap4/omap4_prcm_clks.c
@@ -1033,7 +1033,7 @@ omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev,
  *	The USB clocking setup seems to be a bit more tricky than the other modules,
  *	to start with the clocking diagram for the HS host module shows 13 different
  *	clocks.  So to try and make it easier to follow the clocking activation
- *	and deactivation is handled in it's own set of callbacks.
+ *	and deactivation is handled in its own set of callbacks.
  *
  *	LOCKING:
  *	Inherits the locks from the omap_prcm driver, no internal locking.
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 6dd548b30d40..97a91da52fa5 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -205,7 +205,7 @@ print_cpu_features(u_int cpu)
 	 * https://lkml.org/lkml/2016/8/4/722
 	 */
 	/*
-	 * XXX: CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1 on it's own also
+	 * XXX: CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1 on its own also
 	 * triggers on pass 2.0+.
 	 */
 	if (cpu == 0 && CPU_VAR(PCPU_GET(midr)) == 0 &&
diff --git a/sys/cam/cam.h b/sys/cam/cam.h
index ec4df8bbc255..b0c55e7075f4 100644
--- a/sys/cam/cam.h
+++ b/sys/cam/cam.h
@@ -290,7 +290,7 @@ typedef enum {
 	/* SIM ready to take more commands */
 	CAM_RELEASE_SIMQ	= 0x100,
 
-	/* SIM has this command in it's queue */
+	/* SIM has this command in its queue */
 	CAM_SIM_QUEUED		= 0x200,
 
 	/* Quality of service data is valid */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
index 6e9a624513cf..b41b746d3687 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
@@ -3104,7 +3104,7 @@ arc_buf_size(arc_buf_t *buf)
 
 /*
  * Evict the arc_buf_hdr that is provided as a parameter. The resultant
- * state of the header is dependent on it's state prior to entering this
+ * state of the header is dependent on its state prior to entering this
  * function. The following transitions are possible:
  *
  *    - arc_mru -> arc_mru_ghost
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
index d46b9942794a..6f84c063b9cd 100644
--- a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
@@ -186,7 +186,7 @@ dtrace_trap(struct trapframe *frame, u_int type)
 	/*
 	 * A trap can occur while DTrace executes a probe. Before
 	 * executing the probe, DTrace blocks re-scheduling and sets
-	 * a flag in it's per-cpu flags to indicate that it doesn't
+	 * a flag in its per-cpu flags to indicate that it doesn't
 	 * want to fault. On returning from the probe, the no-fault
 	 * flag is cleared and finally re-scheduling is enabled.
 	 *
diff --git a/sys/cddl/dev/dtrace/arm/dtrace_subr.c b/sys/cddl/dev/dtrace/arm/dtrace_subr.c
index 4ff4e71183be..4ecf7becbe99 100644
--- a/sys/cddl/dev/dtrace/arm/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/arm/dtrace_subr.c
@@ -186,7 +186,7 @@ dtrace_trap(struct trapframe *frame, u_int type)
 	/*
 	 * A trap can occur while DTrace executes a probe. Before
 	 * executing the probe, DTrace blocks re-scheduling and sets
-	 * a flag in it's per-cpu flags to indicate that it doesn't
+	 * a flag in its per-cpu flags to indicate that it doesn't
 	 * want to fault. On returning from the probe, the no-fault
 	 * flag is cleared and finally re-scheduling is enabled.
 	 *
diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c
index 429a442aa4d9..3c202737349d 100644
--- a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c
@@ -189,7 +189,7 @@ dtrace_trap(struct trapframe *frame, u_int type)
 	/*
 	 * A trap can occur while DTrace executes a probe. Before
 	 * executing the probe, DTrace blocks re-scheduling and sets
-	 * a flag in it's per-cpu flags to indicate that it doesn't
+	 * a flag in its per-cpu flags to indicate that it doesn't
 	 * want to fault. On returning from the probe, the no-fault
 	 * flag is cleared and finally re-scheduling is enabled.
 	 *
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
index 5e4a0a15ce0b..063075e397d0 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
@@ -4397,7 +4397,7 @@ ar9300_eeprom_restore(struct ath_hal *ah)
 #endif
         /*
          * At this point, mptr points to the eeprom data structure
-         * in it's "default" state.  If this is big endian, swap the
+         * in its "default" state.  If this is big endian, swap the
          * data structures back to "little endian" form.
          */
         if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) {
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
index 89d9b9ef9138..911face4f318 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
@@ -1806,7 +1806,7 @@ vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state)
 **			suspend completion and reset the resume state machine.
 **
 ** VC_RESUME_IDLE - Initialise the resume completion at the same time.  The
-**			resume completion is in it's 'done' state whenever
+**			resume completion is in its 'done' state whenever
 **			videcore is running.  Therfore, the VC_RESUME_IDLE state
 **			implies that videocore is suspended.
 **			Hence, any thread which needs to wait until videocore is
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index e1bf960aeecc..83a273a018ab 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -1446,7 +1446,7 @@ p_command_xfer:
 		test	SSTAT0, SDONE jnz . + 2;
 		test    SSTAT1, PHASEMIS jz . - 1;
 		/*
-		 * Wait for our ACK to go-away on it's own
+		 * Wait for our ACK to go-away on its own
 		 * instead of being killed by SCSIEN getting cleared.
 		 */
 		test	SCSISIGI, ACKI jnz .;
diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c
index c29da1b1de89..e545a3eaf837 100644
--- a/sys/dev/ath/if_ath_tdma.c
+++ b/sys/dev/ath/if_ath_tdma.c
@@ -270,7 +270,7 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap)
 	 * fixed/lowest transmit rate.  Note that the interface
 	 * mtu does not include the 802.11 overhead so we must
 	 * tack that on (ath_hal_computetxtime includes the
-	 * preamble and plcp in it's calculation).
+	 * preamble and plcp in its calculation).
 	 */
 	tdma = vap->iv_tdma;
 	if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
diff --git a/sys/dev/isci/scil/sati_design.h b/sys/dev/isci/scil/sati_design.h
index 372dce0f7d29..47f05b0642cd 100644
--- a/sys/dev/isci/scil/sati_design.h
+++ b/sys/dev/isci/scil/sati_design.h
@@ -130,7 +130,7 @@ block devices (e.g. disks).
 
 @image html Use_Case_Diagram__SATI__SATI_-_SBC.jpg "SCSI Block Command Translation Use Cases"
 
-The SCSI-to-ATA Translation (SAT) specification defines a few of it's own
+The SCSI-to-ATA Translation (SAT) specification defines a few of its own
 commands, parameter data, and log pages.  This use case diagram, however, only
 captures the SAT specific commands being translated.
 
diff --git a/sys/dev/isci/scil/sci_base_controller.h b/sys/dev/isci/scil/sci_base_controller.h
index cdf38a13ae8d..dc28b52627ee 100644
--- a/sys/dev/isci/scil/sci_base_controller.h
+++ b/sys/dev/isci/scil/sci_base_controller.h
@@ -90,7 +90,7 @@ typedef enum _SCI_BASE_CONTROLLER_STATES
 
    /**
     * This state indicates that the controller is reset.  The memory for
-    * the controller is in it's initial state, but the controller requires
+    * the controller is in its initial state, but the controller requires
     * initialization.
     * This state is entered from the INITIAL state.
     * This state is entered from the RESETTING state.
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c
index d50e7c70265d..25006b397cf4 100644
--- a/sys/dev/sfxge/common/efx_mcdi.c
+++ b/sys/dev/sfxge/common/efx_mcdi.c
@@ -1092,7 +1092,7 @@ efx_mcdi_read_assertion(
 
 	/*
 	 * Before we attempt to chat to the MC, we should verify that the MC
-	 * isn't in it's assertion handler, either due to a previous reboot,
+	 * isn't in its assertion handler, either due to a previous reboot,
 	 * or because we're reinitializing due to an eec_exception().
 	 *
 	 * Use GET_ASSERTS to read any assertion state that may be present.
diff --git a/sys/dev/sound/pci/hda/hdaa.c b/sys/dev/sound/pci/hda/hdaa.c
index c24f428399bf..199679ccb9b2 100644
--- a/sys/dev/sound/pci/hda/hdaa.c
+++ b/sys/dev/sound/pci/hda/hdaa.c
@@ -2382,7 +2382,7 @@ hdaa_audio_ctl_source_volume(struct hdaa_pcm_devinfo *pdevinfo,
 	}
 
 	/* If widget has own ossdev - not traverse it.
-	   It will be traversed on it's own. */
+	   It will be traversed on its own. */
 	if (w->ossdev >= 0 && depth > 0)
 		return;
 
@@ -4550,7 +4550,7 @@ hdaa_audio_ctl_source_amp(struct hdaa_devinfo *devinfo, nid_t nid, int index,
 	}
 
 	/* If widget has own ossdev - not traverse it.
-	   It will be traversed on it's own. */
+	   It will be traversed on its own. */
 	if (w->ossdev >= 0 && depth > 0)
 		return (found);
 
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index a63c730e911e..4be6056183d7 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -426,7 +426,7 @@ hdac_reset(struct hdac_softc *sc, int wakeup)
 
 	/*
 	 * Wait for codecs to finish their own reset sequence. The delay here
-	 * should be of 250us but for some reasons, on it's not enough on my
+	 * should be of 250us but for some reasons, it's not enough on my
 	 * computer. Let's use twice as much as necessary to make sure that
 	 * it's reset properly.
 	 */
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 4ee6b4546c08..0bd7edd8d00e 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -649,7 +649,7 @@ null_lock(struct vop_lock1_args *ap)
 	nn = VTONULL(vp);
 	/*
 	 * If we're still active we must ask the lower layer to
-	 * lock as ffs has special lock considerations in it's
+	 * lock as ffs has special lock considerations in its
 	 * vop lock.
 	 */
 	if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL) {
@@ -662,7 +662,7 @@ null_lock(struct vop_lock1_args *ap)
 		 * the lowervp's vop_lock routine.  When we vgone we will
 		 * drop our last ref to the lowervp, which would allow it
 		 * to be reclaimed.  The lowervp could then be recycled,
-		 * in which case it is not legal to be sleeping in it's VOP.
+		 * in which case it is not legal to be sleeping in its VOP.
 		 * We prevent it from being recycled by holding the vnode
 		 * here.
 		 */
diff --git a/sys/geom/raid/md_ddf.c b/sys/geom/raid/md_ddf.c
index a663af22be6b..df58a1e8da03 100644
--- a/sys/geom/raid/md_ddf.c
+++ b/sys/geom/raid/md_ddf.c
@@ -1626,7 +1626,7 @@ g_raid_md_ddf_start_disk(struct g_raid_disk *disk, struct g_raid_volume *vol)
 	vmeta = &pv->pv_meta;
 	gmeta = &mdi->mdio_meta;
 
-	/* Find disk position in metadata by it's reference. */
+	/* Find disk position in metadata by its reference. */
 	disk_pos = ddf_meta_find_disk(vmeta, reference,
 	    &md_disk_bvd, &md_disk_pos);
 	md_pde_pos = ddf_meta_find_pd(gmeta, NULL, reference);
diff --git a/sys/geom/raid/md_intel.c b/sys/geom/raid/md_intel.c
index 11c561cd0222..f3e4998f87de 100644
--- a/sys/geom/raid/md_intel.c
+++ b/sys/geom/raid/md_intel.c
@@ -923,7 +923,7 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk)
 	pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data;
 	olddisk = NULL;
 
-	/* Find disk position in metadata by it's serial. */
+	/* Find disk position in metadata by its serial. */
 	disk_pos = intel_meta_find_disk(meta, pd->pd_disk_meta.serial);
 	if (disk_pos < 0) {
 		G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
diff --git a/sys/geom/raid/md_jmicron.c b/sys/geom/raid/md_jmicron.c
index ae5abab1b7fa..231c27f9ec52 100644
--- a/sys/geom/raid/md_jmicron.c
+++ b/sys/geom/raid/md_jmicron.c
@@ -434,7 +434,7 @@ g_raid_md_jmicron_start_disk(struct g_raid_disk *disk)
 	pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
 	olddisk = NULL;
 
-	/* Find disk position in metadata by it's serial. */
+	/* Find disk position in metadata by its serial. */
 	if (pd->pd_meta != NULL)
 		disk_pos = jmicron_meta_find_disk(meta, pd->pd_disk_id);
 	else
diff --git a/sys/geom/raid/md_nvidia.c b/sys/geom/raid/md_nvidia.c
index d1d2e296317c..460f873ff6fc 100644
--- a/sys/geom/raid/md_nvidia.c
+++ b/sys/geom/raid/md_nvidia.c
@@ -441,7 +441,7 @@ g_raid_md_nvidia_start_disk(struct g_raid_disk *disk)
 	pd = (struct g_raid_md_nvidia_perdisk *)disk->d_md_data;
 	olddisk = NULL;
 
-	/* Find disk position in metadata by it's serial. */
+	/* Find disk position in metadata by its serial. */
 	if (pd->pd_meta != NULL) {
 		disk_pos = pd->pd_meta->disk_number;
 		if (disk_pos >= meta->total_disks || mdi->mdio_started)
diff --git a/sys/geom/raid/md_promise.c b/sys/geom/raid/md_promise.c
index 1cf334f240f7..245cd74f7dbb 100644
--- a/sys/geom/raid/md_promise.c
+++ b/sys/geom/raid/md_promise.c
@@ -673,7 +673,7 @@ g_raid_md_promise_start_disk(struct g_raid_disk *disk, int sdn,
 	meta = pv->pv_meta;
 
 	if (sdn >= 0) {
-		/* Find disk position in metadata by it's serial. */
+		/* Find disk position in metadata by its serial. */
 		md_disk_pos = promise_meta_find_disk(meta, pd->pd_meta[sdn]->disk.id);
 		/* For RAID0+1 we need to translate order. */
 		disk_pos = promise_meta_translate_disk(vol, md_disk_pos);
diff --git a/sys/geom/raid/md_sii.c b/sys/geom/raid/md_sii.c
index f97366041ef4..252b41aea615 100644
--- a/sys/geom/raid/md_sii.c
+++ b/sys/geom/raid/md_sii.c
@@ -489,7 +489,7 @@ g_raid_md_sii_start_disk(struct g_raid_disk *disk)
 	pd = (struct g_raid_md_sii_perdisk *)disk->d_md_data;
 	olddisk = NULL;
 
-	/* Find disk position in metadata by it's serial. */
+	/* Find disk position in metadata by its serial. */
 	if (pd->pd_meta != NULL)
 		disk_pos = sii_meta_disk_pos(meta, pd->pd_meta);
 	else
diff --git a/sys/i386/include/cserial.h b/sys/i386/include/cserial.h
index 1fcb611700e6..314e9f647d43 100644
--- a/sys/i386/include/cserial.h
+++ b/sys/i386/include/cserial.h
@@ -117,7 +117,7 @@ struct e3_statistics {
 
 /*
  * Attach/detach the protocol to the channel.
- * The protocol is given by it's name, char[8].
+ * The protocol is given by its name, char[8].
  * For example "async", "hdlc", "cisco", "fr", "ppp".
  */
 #define SERIAL_GETPROTO		_IOR ('x', 1, char [8])
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 3c42bb72f9d4..82b733077b39 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -793,7 +793,7 @@ start_init(void *dummy)
 }
 
 /*
- * Like kproc_create(), but runs in it's own address space.
+ * Like kproc_create(), but runs in its own address space.
  * We do this early to reserve pid 1.
  *
  * Note special case - do not make it runnable yet.  Other work
diff --git a/sys/kern/kern_ctf.c b/sys/kern/kern_ctf.c
index 09eea1e00f96..a2509f08c3ff 100644
--- a/sys/kern/kern_ctf.c
+++ b/sys/kern/kern_ctf.c
@@ -236,7 +236,7 @@ link_elf_ctf_get(linker_file_t lf, linker_ctf_t *lc)
 	}
 
 	/*
-	 * Allocate memory to buffer the CTF data in it's decompressed
+	 * Allocate memory to buffer the CTF data in its decompressed
 	 * form.
 	 */
 	ctftab = malloc(sz, M_LINKER, M_WAITOK);
diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c
index 172d7198dc66..df720bd211e2 100644
--- a/sys/kern/subr_firmware.c
+++ b/sys/kern/subr_firmware.c
@@ -229,7 +229,7 @@ firmware_unregister(const char *imagename)
 		/*
 		 * It is ok for the lookup to fail; this can happen
 		 * when a module is unloaded on last reference and the
-		 * module unload handler unregister's each of it's
+		 * module unload handler unregister's each of its
 		 * firmware images.
 		 */
 		err = 0;
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 03f2b1780050..1f30dab8a122 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1336,7 +1336,7 @@ m_defrag(struct mbuf *m0, int how)
 /*
  * Defragment an mbuf chain, returning at most maxfrags separate
  * mbufs+clusters.  If this is not possible NULL is returned and
- * the original mbuf chain is left in it's present (potentially
+ * the original mbuf chain is left in its present (potentially
  * modified) state.  We use two techniques: collapsing consecutive
  * mbufs and replacing consecutive mbufs by a cluster.
  *
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 980fe5c45d2e..7bbf9761c970 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -36,7 +36,7 @@
  * IEEE80211_INACT_WAIT seconds to handle "inactivity processing".
  * This is used to do node inactivity processing when operating
  * as an AP, adhoc or mesh mode.  For inactivity processing each node
- * has a timeout set in it's ni_inact field that is decremented
+ * has a timeout set in its ni_inact field that is decremented
  * on each timeout and the node is reclaimed when the counter goes
  * to zero.  We use different inactivity timeout values depending
  * on whether the node is associated and authorized (either by
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 9309938564a9..1253d1cba051 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -1179,7 +1179,7 @@ ng_destroy_hook(hook_p hook)
 		/*
 		 * Set the peer to point to ng_deadhook
 		 * from this moment on we are effectively independent it.
-		 * send it an rmhook message of it's own.
+		 * send it an rmhook message of its own.
 		 */
 		peer->hk_peer = &ng_deadhook;	/* They no longer know us */
 		hook->hk_peer = &ng_deadhook;	/* Nor us, them */
@@ -3005,7 +3005,7 @@ void
 ng_free_item(item_p item)
 {
 	/*
-	 * The item may hold resources on it's own. We need to free
+	 * The item may hold resources on its own. We need to free
 	 * these before we can free the item. What they are depends upon
 	 * what kind of item it is. it is important that nodes zero
 	 * out pointers to resources that they remove from the item
@@ -3577,7 +3577,7 @@ ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
 	ITEM_DEBUG_CHECKS;
 	/*
 	 * Quick sanity check..
-	 * Since a hook holds a reference on it's node, once we know
+	 * Since a hook holds a reference on its node, once we know
 	 * that the peer is still connected (even if invalid,) we know
 	 * that the peer node is present, though maybe invalid.
 	 */
diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m
index b840ead8d334..c8911aadaca6 100644
--- a/sys/powerpc/powerpc/mmu_if.m
+++ b/sys/powerpc/powerpc/mmu_if.m
@@ -725,7 +725,7 @@ METHOD void align_superpage {
 
 /**
  * @brief Bootstrap the VM system. At the completion of this routine, the
- * kernel will be running in it's own address space with full control over
+ * kernel will be running in its own address space with full control over
  * paging.
  *
  * @param _start	start of reserved memory (obsolete ???)
diff --git a/sys/security/mac/mac_inet.c b/sys/security/mac/mac_inet.c
index a1bbea9caeba..9763f8b5e4df 100644
--- a/sys/security/mac/mac_inet.c
+++ b/sys/security/mac/mac_inet.c
@@ -435,7 +435,7 @@ mac_netinet_firewall_send(struct mbuf *m)
 /*
  * These functions really should be referencing the syncache structure
  * instead of the label.  However, due to some of the complexities associated
- * with exposing this syncache structure we operate directly on it's label
+ * with exposing this syncache structure we operate directly on its label
  * pointer.  This should be OK since we aren't making any access control
  * decisions within this code directly, we are merely allocating and copying
  * label storage so we can properly initialize mbuf labels for any packets
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 5c987facede6..ed71109cbf39 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -1410,7 +1410,7 @@ vm_pageout_oom(int shortage)
 	/*
 	 * We keep the process bigproc locked once we find it to keep anyone
 	 * from messing with it; however, there is a possibility of
-	 * deadlock if process B is bigproc and one of it's child processes
+	 * deadlock if process B is bigproc and one of its child processes
 	 * attempts to propagate a signal to B while we are waiting for A's
 	 * lock while walking this list.  To avoid this, we don't block on
 	 * the process lock but just skip a process if it is already locked.
diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c
index 66870b4c37f2..9c78306db87a 100644
--- a/sys/x86/xen/xen_intr.c
+++ b/sys/x86/xen/xen_intr.c
@@ -940,7 +940,7 @@ xen_intr_disable_source(struct intsrc *base_isrc, int eoi)
 	/*
 	 * NB: checking if the event channel is already masked is
 	 * needed because the event channel user-space device
-	 * masks event channels on it's filter as part of it's
+	 * masks event channels on its filter as part of its
 	 * normal operation, and those shouldn't be automatically
 	 * unmasked by the generic interrupt code. The event channel
 	 * device will unmask them when needed.
diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c
index 506c3f5b4338..6415b98eda5c 100644
--- a/usr.bin/du/du.c
+++ b/usr.bin/du/du.c
@@ -421,7 +421,7 @@ linkchk(FTSENT *p)
 		if (le->dev == st->st_dev && le->ino == st->st_ino) {
 			/*
 			 * Save memory by releasing an entry when we've seen
-			 * all of it's links.
+			 * all of its links.
 			 */
 			if (--le->links <= 0) {
 				if (le->previous != NULL)
diff --git a/usr.bin/xlint/lint2/read.c b/usr.bin/xlint/lint2/read.c
index 8ff156efb998..2a01ebb03978 100644
--- a/usr.bin/xlint/lint2/read.c
+++ b/usr.bin/xlint/lint2/read.c
@@ -909,7 +909,7 @@ gettlen(const char *cp, const char **epp)
 }
 
 /*
- * Search a type by it's type string.
+ * Search a type by its type string.
  */
 static u_short
 findtype(const char *cp, size_t len, int h)
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 193b0d99bb45..b072601d5e10 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -908,7 +908,7 @@ main(int argc, char *argv[])
 	sci_init(ctx);
 
 	/*
-	 * Exit if a device emulation finds an error in it's initilization
+	 * Exit if a device emulation finds an error in its initilization
 	 */
 	if (init_pci(ctx) != 0)
 		exit(1);
diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt b/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt
index d55ea3cf27d1..3d01e2bf81a4 100644
--- a/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt
+++ b/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt
@@ -875,7 +875,7 @@ begemotBridgeTpMaxAddresses OBJECT-TYPE
     STATUS	current
     DESCRIPTION
 	"The maximum number of entires that this bridge can
-	learn in it's Forwarding Address Table and use for
+	learn in its Forwarding Address Table and use for
 	making forwarding decisions."
     ::= { begemotBridgeTpEntry 3 }
 
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index 90a9fe209a91..0fcc08c72f4e 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -2062,7 +2062,7 @@ do_zipwork(struct zipwork_entry *zwork)
  * Save information on any process we need to signal.  Any single
  * process may need to be sent different signal-values for different
  * log files, but usually a single signal-value will cause the process
- * to close and re-open all of it's log files.
+ * to close and re-open all of its log files.
  */
 static struct sigwork_entry *
 save_sigwork(const struct conf_entry *ent)

From 3c9cab9453d986c50861323d02ef6b0970450091 Mon Sep 17 00:00:00 2001
From: Luiz Otavio O Souza 
Date: Wed, 9 Nov 2016 04:07:15 +0000
Subject: [PATCH 106/127] Add the DTS for the Netgate SG-1000 (micro-Firewall).

The SG-1000 boots with GENERIC ARM kernel on -head.

Obtained from:	pfSense
Sponsored by:	Rubicon Communications, LLC (Netgate)
---
 sys/boot/fdt/dts/arm/ubmc.dtsi  | 315 ++++++++++++++++++++++++++++++++
 sys/boot/fdt/dts/arm/ufw.dts    |  70 +++++++
 sys/modules/dtb/am335x/Makefile |   3 +-
 3 files changed, 387 insertions(+), 1 deletion(-)
 create mode 100644 sys/boot/fdt/dts/arm/ubmc.dtsi
 create mode 100644 sys/boot/fdt/dts/arm/ufw.dts

diff --git a/sys/boot/fdt/dts/arm/ubmc.dtsi b/sys/boot/fdt/dts/arm/ubmc.dtsi
new file mode 100644
index 000000000000..f23c030dcd9e
--- /dev/null
+++ b/sys/boot/fdt/dts/arm/ubmc.dtsi
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * $FreeBSD$
+ */
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin>;
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE3)	/* uart0_ctsn.i2c1_sda */
+			AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE3)	/* uart0_rtsn.i2c1_scl */
+		>;
+	};
+
+	spi0_pins: pinmux_spi0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* spi0_sclk.spi0_sclk */
+			AM33XX_IOPAD(0x954, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* spi0_d0.spi0_miso */
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)	/* spi0_d1.spi0_mosi */
+			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)	/* spi0_cs0.spi0_cs0 */
+		>;
+	};
+
+	spi1_pins: pinmux_spi1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_col.spi1_sclk */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_crs.spi1_miso */
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rx_er.spi1_mosi */
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLUP | MUX_MODE2)	/* rmii1_ref_clk.spi1_cs0 */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii_1_txen */
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxdv.rgmii_1_rxdv */
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii_1_txd3 */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii_1_txd2 */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii_1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii_1_txd0 */
+			AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii_1_txclk */
+			AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxclk.rgmii_1_rxclk */
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd3.rgmii_1_rxd3 */
+			AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd2.rgmii_1_rxd2 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd1.rgmii_1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE2)	/* mii1_rxd0.rgmii_1_rxd0 */
+
+			/* Slave 2 */
+			AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gmpc_a0.rgmii_2_txen */
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE2)	/* gmpc_a1.rgmii_2_rxdv */
+			AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gmpc_a2.rgmii_2_txd3 */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gmpc_a3.rgmii_2_txd2 */
+			AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gmpc_a4.rgmii_2_txd1 */
+			AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gmpc_a5.rgmii_2_txd0 */
+			AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gmpc_a6.rgmii_2_txclk */
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLUP | MUX_MODE2)	/* gmpc_a7.rgmii_2_rxclk */
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLUP | MUX_MODE2)	/* gmpc_a8.rgmii_2_rxd3 */
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLUP | MUX_MODE2)	/* gmpc_a9.rgmii_2_rxd2 */
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLUP | MUX_MODE2)	/* gmpc_a10.rgmii_2_rxd1 */
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLUP | MUX_MODE2)	/* gmpc_a11.rgmii_2_rxd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value */
+			AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* spi0_cs1.mmc0_cd */
+		>;
+	};
+
+	emmc_pins: pinmux_emmc_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x994, PIN_INPUT_PULLUP | MUX_MODE4) /* mcasp0_fsx.mmc1_cd */
+			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+			AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+			AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+			AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+			AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+		>;
+	};
+
+	ecap0_pins: pinmux_ecap0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x964, PIN_INPUT | MUX_MODE0) /* ecap0_in_pwm0_out.ecap0_in_pwm0_out */
+		>;
+	};
+
+	ecap1_pins: pinmux_ecap1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE2) /* spi0_cs1.ecap1_in_pwm1_out */
+		>;
+	};
+
+	ehrpwm1_pins: pinmux_ehrpwm1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE2) /* lcd_data10.ehrpwm1a */
+		>;
+	};
+
+	ecap2_pins: pinmux_ecap2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x99c, PIN_INPUT | MUX_MODE4) /* mcasp0_ahclkr.ecap2_in_pwm2_out */
+		>;
+	};
+
+	ehrpwm2_pins: pinmux_ehrpwm2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE3) /* lcd_data0.ehrpwm2a */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	baseboard_eeprom: baseboard_eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		baseboard_data: baseboard_data@0 {
+			reg = <0 0x100>;
+		};
+	};
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <2>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	active_slave = <1>;
+	status = "okay";
+	dual_emac;
+	txen-skew-ps = <0>;
+	rxdv-skew-ps = <1400>;
+	rxd0-skew-ps = <1400>;
+	rxd1-skew-ps = <1400>;
+	rxd2-skew-ps = <1400>;
+	rxd3-skew-ps = <1400>;
+	txd0-skew-ps = <0>;
+	txd1-skew-ps = <0>;
+	txd2-skew-ps = <0>;
+	txd3-skew-ps = <0>;
+	rxc-skew-ps = <4400>;
+	txc-skew-ps = <6200>;
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&sham {
+	status = "okay";
+};
diff --git a/sys/boot/fdt/dts/arm/ufw.dts b/sys/boot/fdt/dts/arm/ufw.dts
new file mode 100644
index 000000000000..25fc9a0ae5a4
--- /dev/null
+++ b/sys/boot/fdt/dts/arm/ufw.dts
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "ubmc.dtsi"
+
+/ {
+	model = "AM335x uFW";
+	compatible = "ti,am335x-ufw", "ti,am335x-ubmc", "ti,am33xx";
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	bus-width = <8>;
+	ti,dual-volt;
+	non-removable;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+};
diff --git a/sys/modules/dtb/am335x/Makefile b/sys/modules/dtb/am335x/Makefile
index d149c95fc545..b60f4a9c5ed7 100644
--- a/sys/modules/dtb/am335x/Makefile
+++ b/sys/modules/dtb/am335x/Makefile
@@ -2,6 +2,7 @@
 # All the dts files for am335x systems we support.
 DTS=	\
 	beaglebone.dts \
-        beaglebone-black.dts
+	beaglebone-black.dts \
+	ufw.dts
 
 .include 

From e7d88f5e132034c95934689f5228506b2ec21796 Mon Sep 17 00:00:00 2001
From: Marcelo Araujo 
Date: Wed, 9 Nov 2016 04:42:09 +0000
Subject: [PATCH 107/127] Fix missing '-' for the flags -s and -d on both
 manpage and usage.

Reported by:	garga, bde
---
 bin/hostname/hostname.1 | 4 ++--
 bin/hostname/hostname.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/bin/hostname/hostname.1 b/bin/hostname/hostname.1
index 73255d280041..4da9f63044cb 100644
--- a/bin/hostname/hostname.1
+++ b/bin/hostname/hostname.1
@@ -29,7 +29,7 @@
 .\"	@(#)hostname.1	8.2 (Berkeley) 4/28/95
 .\" $FreeBSD$
 .\"
-.Dd November 9, 2016
+.Dd November 10, 2016
 .Dt HOSTNAME 1
 .Os
 .Sh NAME
@@ -38,7 +38,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl f
-.Op Fl s|d
+.Op Fl s | d
 .Op Ar name-of-host
 .Sh DESCRIPTION
 The
diff --git a/bin/hostname/hostname.c b/bin/hostname/hostname.c
index 3b07b8b5f537..85b692eccdc4 100644
--- a/bin/hostname/hostname.c
+++ b/bin/hostname/hostname.c
@@ -108,6 +108,6 @@ static void
 usage(void)
 {
 
-	(void)fprintf(stderr, "usage: hostname [-f] [s|d] [name-of-host]\n");
+	(void)fprintf(stderr, "usage: hostname [-f] [-s | -d] [name-of-host]\n");
 	exit(1);
 }

From a28ed036b6f66ab3f3d434f82b494801626a2499 Mon Sep 17 00:00:00 2001
From: Kevin Lo 
Date: Wed, 9 Nov 2016 06:47:29 +0000
Subject: [PATCH 108/127] Sort DLINK section and add USB device ID of D-Link
 DWA-131 rev E1.

---
 sys/dev/usb/usbdevs | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 4560efba9262..0540f16ba757 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1621,12 +1621,18 @@ product DLINK DUBE100		0x1a00	10/100 Ethernet
 product DLINK DUBE100C1		0x1a02	DUB-E100 rev C1
 product DLINK DSB650TX4		0x200c	10/100 Ethernet
 product DLINK DWL120E		0x3200	DWL-120 rev E
+product DLINK RTL8192CU_1	0x3307	RTL8192CU
+product DLINK RTL8188CU		0x3308	RTL8188CU
+product DLINK RTL8192CU_2	0x3309	RTL8192CU
+product DLINK RTL8192CU_3	0x330a	RTL8192CU
+product DLINK DWA131B		0x330d	DWA-131 rev B
 product DLINK DWA125D1		0x330f	DWA-125 rev D1
 product DLINK DWA123D1		0x3310	DWA-123 rev D1
 product DLINK DWA171A1		0x3314	DWA-171 rev A1
 product DLINK DWA182C1		0x3315	DWA-182 rev C1
 product DLINK DWA180A1		0x3316	DWA-180 rev A1
 product DLINK DWA172A1		0x3318	DWA-172 rev A1
+product DLINK DWA131E1		0x3319	DWA-131 rev E1
 product DLINK DWL122		0x3700	DWL-122
 product DLINK DWLG120		0x3701	DWL-G120
 product DLINK DWL120F		0x3702	DWL-120 rev F
@@ -1652,17 +1658,12 @@ product DLINK DSB650TX_PNA	0x4003	1/10/100 Ethernet
 product DLINK DSB650TX3		0x400b	10/100 Ethernet
 product DLINK DSB650TX2		0x4102	10/100 Ethernet
 product DLINK DUB1312		0x4a00	10/100/1000 Ethernet
+product DLINK DWM157		0x7d02  DWM-157
+product DLINK DWR510		0x7e12	DWR-510
+product DLINK DWM157_CD		0xa707  DWM-157 CD-ROM Mode
+product DLINK DWR510_CD		0xa805	DWR-510 CD-ROM Mode
 product DLINK DSB650		0xabc1	10/100 Ethernet
 product DLINK DUBH7		0xf103	DUB-H7 USB 2.0 7-Port Hub
-product DLINK DWR510_CD		0xa805	DWR-510 CD-ROM Mode
-product DLINK DWR510		0x7e12	DWR-510
-product DLINK DWM157		0x7d02  DWM-157
-product DLINK DWM157_CD		0xa707  DWM-157 CD-ROM Mode
-product DLINK RTL8188CU		0x3308	RTL8188CU
-product	DLINK RTL8192CU_1	0x3307	RTL8192CU
-product	DLINK RTL8192CU_2	0x3309	RTL8192CU
-product	DLINK RTL8192CU_3	0x330a	RTL8192CU
-product	DLINK DWA131B		0x330d	DWA-131 rev B
 product DLINK2 RTL8192SU_1	0x3300	RTL8192SU
 product DLINK2 RTL8192SU_2	0x3302	RTL8192SU
 product DLINK2 DWA131A1		0x3303	DWA-131 A1
@@ -1673,8 +1674,8 @@ product DLINK2 DWA130D1		0x3a0f	DWA-130 D1
 product DLINK2 DWLG122C1	0x3c03	DWL-G122 c1
 product DLINK2 WUA1340		0x3c04	WUA-1340
 product DLINK2 DWA111		0x3c06	DWA-111
-product DLINK2 RT2870_1		0x3c09	RT2870
 product DLINK2 DWA110		0x3c07	DWA-110
+product DLINK2 RT2870_1		0x3c09	RT2870
 product DLINK2 RT3072		0x3c0a	RT3072
 product DLINK2 RT3072_1		0x3c0b	RT3072
 product DLINK2 RT3070_1		0x3c0d	RT3070
@@ -4477,6 +4478,7 @@ product TOSHIBA TRANSMEMORY	0x6545	USB ThumbDrive
 
 /* TP-Link products */
 product TPLINK T4U		0x0101	Archer T4U
+product TPLINK WN823NV2		0x0109	TL-WN823N v2
 
 /* Trek Technology products */
 product TREK THUMBDRIVE		0x1111	ThumbDrive

From 82364f24b55451723b34b6071b841846fc5993ee Mon Sep 17 00:00:00 2001
From: Hans Petter Selasky 
Date: Wed, 9 Nov 2016 07:09:27 +0000
Subject: [PATCH 109/127] Allow higher sample rates to have more jitter than
 lower ones.

PR:		208791
MFC after:	3 days
---
 sys/dev/sound/usb/uaudio.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 6ed81eef02ea..fcffbe522dfa 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -2079,6 +2079,8 @@ uaudio_chan_play_sync_callback(struct usb_xfer *xfer, usb_error_t error)
 		 * recording channel:
 		 */
 		if (ch->priv_sc->sc_rec_chan.num_alt == 0) {
+			int32_t jitter_max = howmany(sample_rate, 16000);
+
 			/*
 			 * Range check the jitter values to avoid
 			 * bogus sample rate adjustments. The expected
@@ -2087,12 +2089,11 @@ uaudio_chan_play_sync_callback(struct usb_xfer *xfer, usb_error_t error)
 			 * mandates this requirement. Refer to chapter
 			 * 5.12.4.2 about feedback.
 			 */
-			if (temp > sample_rate)
-				ch->jitter_curr = 1;
-			else if (temp < sample_rate)
-				ch->jitter_curr = -1;
-			else
-				ch->jitter_curr = 0;
+			ch->jitter_curr = temp - sample_rate;
+			if (ch->jitter_curr > jitter_max)
+				ch->jitter_curr = jitter_max;
+			else if (ch->jitter_curr < -jitter_max)
+				ch->jitter_curr = -jitter_max;
 		}
 		ch->feedback_rate = temp;
 		break;

From 712a6ae66e893a4f679adb9313aff5b3ab2959b5 Mon Sep 17 00:00:00 2001
From: Marcelo Araujo 
Date: Wed, 9 Nov 2016 07:31:39 +0000
Subject: [PATCH 110/127] Add flag -B which does the same like batch mode but
 without exiting after print. Also add a new flag -s that add blocks size to
 statistics.

PR:		198347, 212726
Submitted by:	Ben RUBSON 
Tested by:	pi
MFC After:	2 weeks.
---
 usr.sbin/gstat/gstat.8 | 10 ++++++--
 usr.sbin/gstat/gstat.c | 53 +++++++++++++++++++++++++++++++++---------
 2 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/usr.sbin/gstat/gstat.8 b/usr.sbin/gstat/gstat.8
index 6c0430e58f78..0c8ce3f75e2f 100644
--- a/usr.sbin/gstat/gstat.8
+++ b/usr.sbin/gstat/gstat.8
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 3, 2014
+.Dd November 10, 2016
 .Dt GSTAT 8
 .Os
 .Sh NAME
@@ -32,7 +32,7 @@
 .Nd print statistics about GEOM disks
 .Sh SYNOPSIS
 .Nm
-.Op Fl abcdop
+.Op Fl abBcdops
 .Op Fl f Ar filter
 .Op Fl I Ar interval
 .Sh DESCRIPTION
@@ -50,6 +50,10 @@ Only display providers that are at least 0.1% busy.
 Batch mode.
 Collect numbers, print and exit.
 Default if stdout is not a tty.
+.It Fl B
+Endless batch mode.
+Same as batch mode, but does not exit after collecting
+the first set of data.
 .It Fl c
 Enable display of
 .Xr geom 4
@@ -72,6 +76,8 @@ The format of the regular expression is described in
 .It Fl o
 Enable display of statistics for other operations
 .Pq Dv BIO_FLUSH .
+.It Fl s
+Enable blocks' size statistics.
 .It Fl I Ar interval
 Refresh the
 .Nm
diff --git a/usr.sbin/gstat/gstat.c b/usr.sbin/gstat/gstat.c
index a360f8f85bb4..480cf3ca163f 100644
--- a/usr.sbin/gstat/gstat.c
+++ b/usr.sbin/gstat/gstat.c
@@ -51,11 +51,11 @@
 #include 
 #include 
 
-static int flag_a, flag_b, flag_c, flag_d, flag_o, flag_p;
+static int flag_a, flag_b, flag_B, flag_c, flag_d, flag_o, flag_p, flag_s;
 static int flag_I = 1000000;
 
 #define PRINTMSG(...) do {						\
-		if (flag_b && !loop)					\
+		if ((flag_b && !loop) || (flag_B))			\
 			printf(__VA_ARGS__);				\
 		else if (!flag_b)					\
 			printw(__VA_ARGS__);				\
@@ -88,7 +88,7 @@ main(int argc, char **argv)
 	char *p;
 	char f_s[100], pf_s[100], tmp_f_s[100];
 	const char *line;
-	long double ld[13];
+	long double ld[16];
 	uint64_t u64;
 	EditLine *el;
 	History *hist;
@@ -104,7 +104,7 @@ main(int argc, char **argv)
 		flag_b = 1;
 
 	f_s[0] = '\0';
-	while ((i = getopt(argc, argv, "abdcf:I:op")) != -1) {
+	while ((i = getopt(argc, argv, "abBdcf:I:ops")) != -1) {
 		switch (i) {
 		case 'a':
 			flag_a = 1;
@@ -112,6 +112,10 @@ main(int argc, char **argv)
 		case 'b':
 			flag_b = 1;
 			break;
+		case 'B':
+			flag_B = 1;
+			flag_b = 1;
+			break;
 		case 'c':
 			flag_c = 1;
 			break;
@@ -146,6 +150,9 @@ main(int argc, char **argv)
 		case 'p':
 			flag_p = 1;
 			break;
+		case 's':
+			flag_s = 1;
+			break;
 		case '?':
 		default:
 			usage();
@@ -208,7 +215,8 @@ main(int argc, char **argv)
 	
 		geom_stats_snapshot_reset(sp);
 		geom_stats_snapshot_reset(sq);
-		move(0,0);
+		if (!flag_b)
+			move(0,0);
 		PRINTMSG("dT: %5.3fs  w: %.3fs", dt, (float)flag_I / 1000000);
 		if (f_s[0] != '\0') {
 			PRINTMSG("  filter: ");
@@ -231,10 +239,20 @@ main(int argc, char **argv)
 		}
 		PRINTMSG("\n");
 		PRINTMSG(" L(q)  ops/s   ");
-		PRINTMSG(" r/s   kBps   ms/r   ");
-		PRINTMSG(" w/s   kBps   ms/w   ");
-		if (flag_d)
-			PRINTMSG(" d/s   kBps   ms/d   ");
+		if (flag_s) {
+			PRINTMSG(" r/s     kB   kBps   ms/r   ");
+			PRINTMSG(" w/s     kB   kBps   ms/w   ");
+		}
+		else {
+			PRINTMSG(" r/s   kBps   ms/r   ");
+			PRINTMSG(" w/s   kBps   ms/w   ");
+		}
+		if (flag_d) {
+			if (flag_s)
+				PRINTMSG(" d/s     kB   kBps   ms/d   ");
+			else
+				PRINTMSG(" d/s   kBps   ms/d   ");
+		}
 		if (flag_o)
 			PRINTMSG(" o/s   ms/o   ");
 		PRINTMSG("%%busy Name\n");
@@ -298,6 +316,10 @@ main(int argc, char **argv)
 			    DSM_TRANSFERS_PER_SECOND_OTHER, &ld[11],
 			    DSM_MS_PER_TRANSACTION_OTHER, &ld[12],
 
+			    DSM_KB_PER_TRANSFER_READ, &ld[13],
+			    DSM_KB_PER_TRANSFER_WRITE, &ld[14],
+			    DSM_KB_PER_TRANSFER_FREE, &ld[15],
+
 			    DSM_NONE);
 
 			if (flag_a && ld[7] < 0.1) {
@@ -308,12 +330,16 @@ main(int argc, char **argv)
 			PRINTMSG(" %4ju", (uintmax_t)u64);
 			PRINTMSG(" %6.0f", (double)ld[0]);
 			PRINTMSG(" %6.0f", (double)ld[1]);
+			if (flag_s)
+				PRINTMSG(" %6.0f", (double)ld[13]);
 			PRINTMSG(" %6.0f", (double)ld[2] * 1024);
 			if (ld[3] > 1e3) 
 				PRINTMSG(" %6.0f", (double)ld[3]);
 			else
 				PRINTMSG(" %6.1f", (double)ld[3]);
 			PRINTMSG(" %6.0f", (double)ld[4]);
+			if (flag_s)
+				PRINTMSG(" %6.0f", (double)ld[14]);
 			PRINTMSG(" %6.0f", (double)ld[5] * 1024);
 			if (ld[6] > 1e3) 
 				PRINTMSG(" %6.0f", (double)ld[6]);
@@ -322,6 +348,8 @@ main(int argc, char **argv)
 
 			if (flag_d) {
 				PRINTMSG(" %6.0f", (double)ld[8]);
+				if (flag_s)
+					PRINTMSG(" %6.0f", (double)ld[15]);
 				PRINTMSG(" %6.0f", (double)ld[9] * 1024);
 				if (ld[10] > 1e3) 
 					PRINTMSG(" %6.0f", (double)ld[10]);
@@ -373,7 +401,10 @@ main(int argc, char **argv)
 			/* We loop extra to make sure we get the information. */
 			if (!loop)
 				break;
-			loop = 0;
+			if (!flag_B)
+				loop = 0;
+			else
+				fflush(stdout);
 			usleep(flag_I);
 			continue;
 		}
@@ -452,7 +483,7 @@ main(int argc, char **argv)
 static void
 usage(void)
 {
-	fprintf(stderr, "usage: gstat [-abcdp] [-f filter] [-I interval]\n");
+	fprintf(stderr, "usage: gstat [-abBcdps] [-f filter] [-I interval]\n");
 	exit(EX_USAGE);
         /* NOTREACHED */
 }

From 2b064d4653e8dbe4b93b6ee7cc967b9b51810e3f Mon Sep 17 00:00:00 2001
From: Alexander Motin 
Date: Wed, 9 Nov 2016 08:57:59 +0000
Subject: [PATCH 111/127] Add some device IDs found in my new laptop.

---
 sys/dev/ichsmb/ichsmb_pci.c       | 4 ++++
 sys/dev/sound/pci/hda/hdac.c      | 2 ++
 sys/dev/sound/pci/hda/hdac.h      | 5 +++++
 sys/dev/sound/pci/hda/hdacc.c     | 3 +++
 sys/dev/usb/controller/xhci_pci.c | 2 ++
 5 files changed, 16 insertions(+)

diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c
index 8f3f106ca9b8..38d8d44b1667 100644
--- a/sys/dev/ichsmb/ichsmb_pci.c
+++ b/sys/dev/ichsmb/ichsmb_pci.c
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
 #define ID_WCPTLP			0x9ca28086
 #define	ID_WELLSBURG			0x8d228086
 #define	ID_SRPT				0xa1238086
+#define	ID_SRPTLP			0x9d238086
 
 #define PCIS_SERIALBUS_SMBUS_PROGIF	0x00
 
@@ -220,6 +221,9 @@ ichsmb_pci_probe(device_t dev)
 	case ID_SRPT:
 		device_set_desc(dev, "Intel Sunrise Point-H SMBus controller");
 		break;
+	case ID_SRPTLP:
+		device_set_desc(dev, "Intel Sunrise Point-LP SMBus controller");
+		break;
 	default:
 		return (ENXIO);
 	}
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index 4be6056183d7..22458ea53ef8 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -94,7 +94,9 @@ static const struct {
 	{ HDA_INTEL_LPTLP1,  "Intel Lynx Point-LP",	0, 0 },
 	{ HDA_INTEL_LPTLP2,  "Intel Lynx Point-LP",	0, 0 },
 	{ HDA_INTEL_SRPTLP,  "Intel Sunrise Point-LP",	0, 0 },
+	{ HDA_INTEL_KBLKLP,  "Intel Kabylake-LP",	0, 0 },
 	{ HDA_INTEL_SRPT,    "Intel Sunrise Point",	0, 0 },
+	{ HDA_INTEL_KBLK,    "Intel Kabylake",	0, 0 },
 	{ HDA_INTEL_82801F,  "Intel 82801F",	0, 0 },
 	{ HDA_INTEL_63XXESB, "Intel 631x/632xESB",	0, 0 },
 	{ HDA_INTEL_82801G,  "Intel 82801G",	0, 0 },
diff --git a/sys/dev/sound/pci/hda/hdac.h b/sys/dev/sound/pci/hda/hdac.h
index 71c9e08243e1..788e5ad923b6 100644
--- a/sys/dev/sound/pci/hda/hdac.h
+++ b/sys/dev/sound/pci/hda/hdac.h
@@ -70,7 +70,9 @@
 #define HDA_INTEL_LPTLP2	HDA_MODEL_CONSTRUCT(INTEL, 0x9c21)
 #define HDA_INTEL_BDW2		HDA_MODEL_CONSTRUCT(INTEL, 0x9ca0)
 #define HDA_INTEL_SRPTLP	HDA_MODEL_CONSTRUCT(INTEL, 0x9d70)
+#define HDA_INTEL_KBLKLP	HDA_MODEL_CONSTRUCT(INTEL, 0x9d71)
 #define HDA_INTEL_SRPT		HDA_MODEL_CONSTRUCT(INTEL, 0xa170)
+#define HDA_INTEL_KBLK		HDA_MODEL_CONSTRUCT(INTEL, 0xa171)
 #define HDA_INTEL_ALL		HDA_MODEL_CONSTRUCT(INTEL, 0xffff)
 
 /* Nvidia */
@@ -348,6 +350,7 @@
 #define HDA_CODEC_ALC275	HDA_CODEC_CONSTRUCT(REALTEK, 0x0275)
 #define HDA_CODEC_ALC276	HDA_CODEC_CONSTRUCT(REALTEK, 0x0276)
 #define HDA_CODEC_ALC292	HDA_CODEC_CONSTRUCT(REALTEK, 0x0292)
+#define HDA_CODEC_ALC295	HDA_CODEC_CONSTRUCT(REALTEK, 0x0295)
 #define HDA_CODEC_ALC660	HDA_CODEC_CONSTRUCT(REALTEK, 0x0660)
 #define HDA_CODEC_ALC662	HDA_CODEC_CONSTRUCT(REALTEK, 0x0662)
 #define HDA_CODEC_ALC663	HDA_CODEC_CONSTRUCT(REALTEK, 0x0663)
@@ -633,6 +636,8 @@
 #define HDA_CODEC_INTELPPT	HDA_CODEC_CONSTRUCT(INTEL, 0x2806)
 #define HDA_CODEC_INTELHSW	HDA_CODEC_CONSTRUCT(INTEL, 0x2807)
 #define HDA_CODEC_INTELBDW	HDA_CODEC_CONSTRUCT(INTEL, 0x2808)
+#define HDA_CODEC_INTELSKLK	HDA_CODEC_CONSTRUCT(INTEL, 0x2809)
+#define HDA_CODEC_INTELKBLK	HDA_CODEC_CONSTRUCT(INTEL, 0x280b)
 #define HDA_CODEC_INTELCL	HDA_CODEC_CONSTRUCT(INTEL, 0x29fb)
 #define HDA_CODEC_INTELXXXX	HDA_CODEC_CONSTRUCT(INTEL, 0xffff)
 
diff --git a/sys/dev/sound/pci/hda/hdacc.c b/sys/dev/sound/pci/hda/hdacc.c
index 5b785a84eaa6..eb45d0cddcc7 100644
--- a/sys/dev/sound/pci/hda/hdacc.c
+++ b/sys/dev/sound/pci/hda/hdacc.c
@@ -88,6 +88,7 @@ static const struct {
 	{ HDA_CODEC_ALC275, 0,		"Realtek ALC275" },
 	{ HDA_CODEC_ALC276, 0,		"Realtek ALC276" },
 	{ HDA_CODEC_ALC292, 0,		"Realtek ALC292" },
+	{ HDA_CODEC_ALC295, 0,		"Realtek ALC295" },
 	{ HDA_CODEC_ALC660, 0,		"Realtek ALC660-VD" },
 	{ HDA_CODEC_ALC662, 0x0002,	"Realtek ALC662 rev2" },
 	{ HDA_CODEC_ALC662, 0,		"Realtek ALC662" },
@@ -321,6 +322,8 @@ static const struct {
 	{ HDA_CODEC_INTELPPT, 0,	"Intel Panther Point" },
 	{ HDA_CODEC_INTELHSW, 0,	"Intel Haswell" },
 	{ HDA_CODEC_INTELBDW, 0,	"Intel Broadwell" },
+	{ HDA_CODEC_INTELSKLK, 0,	"Intel Kabylake" },
+	{ HDA_CODEC_INTELKBLK, 0,	"Intel Kabylake" },
 	{ HDA_CODEC_INTELCL, 0,		"Intel Crestline" },
 	{ HDA_CODEC_SII1390, 0,		"Silicon Image SiI1390" },
 	{ HDA_CODEC_SII1392, 0,		"Silicon Image SiI1392" },
diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c
index 35d1ea475c3f..cb0f3dafef5e 100644
--- a/sys/dev/usb/controller/xhci_pci.c
+++ b/sys/dev/usb/controller/xhci_pci.c
@@ -122,6 +122,8 @@ xhci_pci_match(device_t self)
 		return ("Intel Wellsburg USB 3.0 controller");
 	case 0x9cb18086:
 		return ("Broadwell Integrated PCH-LP chipset USB 3.0 controller");
+	case 0x9d2f8086:
+		return ("Intel Sunrise Point-LP USB 3.0 controller");
 	case 0xa12f8086:
 		return ("Intel Sunrise Point USB 3.0 controller");
 

From a402c1e54f92f42f2e0690ca182e8320c520dd5d Mon Sep 17 00:00:00 2001
From: Ed Maste 
Date: Wed, 9 Nov 2016 15:04:29 +0000
Subject: [PATCH 112/127] c++filt: flush output after newline

Some tools spawn c++filt and pass it a single line at a time for
demangling. This is akin to r276689 for addr2line.

Sponsored by:	The FreeBSD Foundation
---
 contrib/elftoolchain/cxxfilt/cxxfilt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/contrib/elftoolchain/cxxfilt/cxxfilt.c b/contrib/elftoolchain/cxxfilt/cxxfilt.c
index c6d737a05267..f471a5a7f552 100644
--- a/contrib/elftoolchain/cxxfilt/cxxfilt.c
+++ b/contrib/elftoolchain/cxxfilt/cxxfilt.c
@@ -188,6 +188,8 @@ main(int argc, char **argv)
 				if (c == EOF)
 					break;
 				putchar(c);
+				if (c == '\n')
+					fflush(stdout);
 			} else {
 				if ((size_t) p >= sizeof(buf) - 1)
 					warnx("buffer overflowed");

From c925d87e2a64326b2e555ce485b1e933c1472f75 Mon Sep 17 00:00:00 2001
From: Alexander Motin 
Date: Wed, 9 Nov 2016 17:57:55 +0000
Subject: [PATCH 113/127] Fix copy/paste bug in r308464.

MFC after:	1 week
---
 sys/dev/sound/pci/hda/hdacc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/dev/sound/pci/hda/hdacc.c b/sys/dev/sound/pci/hda/hdacc.c
index eb45d0cddcc7..c8d617e34f59 100644
--- a/sys/dev/sound/pci/hda/hdacc.c
+++ b/sys/dev/sound/pci/hda/hdacc.c
@@ -322,7 +322,7 @@ static const struct {
 	{ HDA_CODEC_INTELPPT, 0,	"Intel Panther Point" },
 	{ HDA_CODEC_INTELHSW, 0,	"Intel Haswell" },
 	{ HDA_CODEC_INTELBDW, 0,	"Intel Broadwell" },
-	{ HDA_CODEC_INTELSKLK, 0,	"Intel Kabylake" },
+	{ HDA_CODEC_INTELSKLK, 0,	"Intel Skylake" },
 	{ HDA_CODEC_INTELKBLK, 0,	"Intel Kabylake" },
 	{ HDA_CODEC_INTELCL, 0,		"Intel Crestline" },
 	{ HDA_CODEC_SII1390, 0,		"Silicon Image SiI1390" },

From bde951447fbed7c2669f80b5c7b6d3d16bb144f8 Mon Sep 17 00:00:00 2001
From: Jason Evans 
Date: Wed, 9 Nov 2016 18:42:30 +0000
Subject: [PATCH 114/127] Update jemalloc to 4.3.1.

---
 contrib/jemalloc/ChangeLog                    |    53 +
 contrib/jemalloc/FREEBSD-Xlist                |     2 +
 contrib/jemalloc/FREEBSD-diffs                |    66 +-
 contrib/jemalloc/VERSION                      |     2 +-
 contrib/jemalloc/doc/jemalloc.3               |   724 +-
 .../include/jemalloc/internal/arena.h         |   105 +-
 .../include/jemalloc/internal/chunk.h         |     5 +-
 .../include/jemalloc/internal/chunk_dss.h     |    12 +-
 .../jemalloc/include/jemalloc/internal/ckh.h  |     8 +-
 .../jemalloc/include/jemalloc/internal/huge.h |     2 +-
 .../jemalloc/internal/jemalloc_internal.h     |   124 +-
 .../internal/jemalloc_internal_decls.h        |    10 +
 .../internal/jemalloc_internal_defs.h         |    29 +
 .../jemalloc/include/jemalloc/internal/mb.h   |     4 +-
 .../include/jemalloc/internal/mutex.h         |     9 +
 .../include/jemalloc/internal/nstime.h        |     6 +-
 .../jemalloc/internal/private_namespace.h     |    34 +-
 .../jemalloc/include/jemalloc/internal/prng.h |   152 +-
 .../jemalloc/include/jemalloc/internal/prof.h |     8 +-
 .../include/jemalloc/internal/size_classes.h  | 10175 ++++++++--------
 .../jemalloc/include/jemalloc/internal/spin.h |    51 +
 .../include/jemalloc/internal/tcache.h        |     2 +-
 .../jemalloc/include/jemalloc/internal/tsd.h  |    74 +-
 .../jemalloc/include/jemalloc/internal/util.h |    22 +-
 .../include/jemalloc/internal/witness.h       |    39 +-
 contrib/jemalloc/include/jemalloc/jemalloc.h  |     6 +-
 contrib/jemalloc/src/arena.c                  |   434 +-
 contrib/jemalloc/src/chunk.c                  |    57 +-
 contrib/jemalloc/src/chunk_dss.c              |   193 +-
 contrib/jemalloc/src/ckh.c                    |    47 +-
 contrib/jemalloc/src/ctl.c                    |     8 +-
 contrib/jemalloc/src/huge.c                   |    12 +-
 contrib/jemalloc/src/jemalloc.c               |   138 +-
 contrib/jemalloc/src/mutex.c                  |     2 +
 contrib/jemalloc/src/nstime.c                 |    98 +-
 contrib/jemalloc/src/pages.c                  |    20 +
 contrib/jemalloc/src/prof.c                   |    87 +-
 contrib/jemalloc/src/rtree.c                  |     7 +-
 contrib/jemalloc/src/spin.c                   |     2 +
 contrib/jemalloc/src/stats.c                  |  1267 +-
 contrib/jemalloc/src/tcache.c                 |     8 +-
 contrib/jemalloc/src/tsd.c                    |    10 +-
 contrib/jemalloc/src/util.c                   |     2 +-
 lib/libc/stdlib/jemalloc/Makefile.inc         |     4 +-
 44 files changed, 7567 insertions(+), 6553 deletions(-)
 create mode 100644 contrib/jemalloc/include/jemalloc/internal/spin.h
 create mode 100644 contrib/jemalloc/src/spin.c

diff --git a/contrib/jemalloc/ChangeLog b/contrib/jemalloc/ChangeLog
index 532255d14884..587685d02971 100644
--- a/contrib/jemalloc/ChangeLog
+++ b/contrib/jemalloc/ChangeLog
@@ -4,6 +4,59 @@ brevity.  Much more detail can be found in the git revision history:
 
     https://github.com/jemalloc/jemalloc
 
+* 4.3.1 (November 7, 2016)
+
+  Bug fixes:
+  - Fix a severe virtual memory leak.  This regression was first released in
+    4.3.0.  (@interwq, @jasone)
+  - Refactor atomic and prng APIs to restore support for 32-bit platforms that
+    use pre-C11 toolchains, e.g. FreeBSD's mips.  (@jasone)
+
+* 4.3.0 (November 4, 2016)
+
+  This is the first release that passes the test suite for multiple Windows
+  configurations, thanks in large part to @glandium setting up continuous
+  integration via AppVeyor (and Travis CI for Linux and OS X).
+
+  New features:
+  - Add "J" (JSON) support to malloc_stats_print().  (@jasone)
+  - Add Cray compiler support.  (@ronawho)
+
+  Optimizations:
+  - Add/use adaptive spinning for bootstrapping and radix tree node
+    initialization.  (@jasone)
+
+  Bug fixes:
+  - Fix large allocation to search starting in the optimal size class heap,
+    which can substantially reduce virtual memory churn and fragmentation.  This
+    regression was first released in 4.0.0.  (@mjp41, @jasone)
+  - Fix stats.arenas..nthreads accounting.  (@interwq)
+  - Fix and simplify decay-based purging.  (@jasone)
+  - Make DSS (sbrk(2)-related) operations lockless, which resolves potential
+    deadlocks during thread exit.  (@jasone)
+  - Fix over-sized allocation of radix tree leaf nodes.  (@mjp41, @ogaun,
+    @jasone)
+  - Fix over-sized allocation of arena_t (plus associated stats) data
+    structures.  (@jasone, @interwq)
+  - Fix EXTRA_CFLAGS to not affect configuration.  (@jasone)
+  - Fix a Valgrind integration bug.  (@ronawho)
+  - Disallow 0x5a junk filling when running in Valgrind.  (@jasone)
+  - Fix a file descriptor leak on Linux.  This regression was first released in
+    4.2.0.  (@vsarunas, @jasone)
+  - Fix static linking of jemalloc with glibc.  (@djwatson)
+  - Use syscall(2) rather than {open,read,close}(2) during boot on Linux.  This
+    works around other libraries' system call wrappers performing reentrant
+    allocation.  (@kspinka, @Whissi, @jasone)
+  - Fix OS X default zone replacement to work with OS X 10.12.  (@glandium,
+    @jasone)
+  - Fix cached memory management to avoid needless commit/decommit operations
+    during purging, which resolves permanent virtual memory map fragmentation
+    issues on Windows.  (@mjp41, @jasone)
+  - Fix TSD fetches to avoid (recursive) allocation.  This is relevant to
+    non-TLS and Windows configurations.  (@jasone)
+  - Fix malloc_conf overriding to work on Windows.  (@jasone)
+  - Forcibly disable lazy-lock on Windows (was forcibly *enabled*).  (@jasone)
+
 * 4.2.1 (June 8, 2016)
 
   Bug fixes:
diff --git a/contrib/jemalloc/FREEBSD-Xlist b/contrib/jemalloc/FREEBSD-Xlist
index dff8d26408ac..5d1faad1a956 100644
--- a/contrib/jemalloc/FREEBSD-Xlist
+++ b/contrib/jemalloc/FREEBSD-Xlist
@@ -1,6 +1,8 @@
 $FreeBSD$
+.appveyor.yml
 .autom4te.cfg
 .git*
+.travis.yml
 FREEBSD-*
 INSTALL
 Makefile*
diff --git a/contrib/jemalloc/FREEBSD-diffs b/contrib/jemalloc/FREEBSD-diffs
index df0a538368c9..4b2a527b279d 100644
--- a/contrib/jemalloc/FREEBSD-diffs
+++ b/contrib/jemalloc/FREEBSD-diffs
@@ -1,11 +1,11 @@
 diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in
-index c4a44e3..4626e9b 100644
+index 3d2e721..b361db2 100644
 --- a/doc/jemalloc.xml.in
 +++ b/doc/jemalloc.xml.in
 @@ -53,11 +53,23 @@
      This manual describes jemalloc @jemalloc_version@.  More information
      can be found at the jemalloc website.
+     url="http://jemalloc.net/">jemalloc website.
 +
 +    The following configuration options are enabled in libc's built-in
 +    jemalloc: ,
@@ -27,30 +27,30 @@ index c4a44e3..4626e9b 100644
        
          Standard API
          
-@@ -2961,4 +2973,18 @@ malloc_conf = "lg_chunk:24";]]>
-     The posix_memalign function conforms
-     to IEEE Std 1003.1-2001 (“POSIX.1”).
+@@ -2963,4 +2975,18 @@ malloc_conf = "lg_chunk:24";]]>
+     The posix_memalign() function conforms
+     to IEEE Std 1003.1-2001 (POSIX.1).
    
 +  
 +    HISTORY
-+    The malloc_usable_size and
-+    posix_memalign functions first appeared in
-+    FreeBSD 7.0.
++    The malloc_usable_size() and
++    posix_memalign() functions first appeared in FreeBSD
++    7.0.
 +
-+    The aligned_alloc,
-+    malloc_stats_print, and
-+    mallctl* functions first appeared in
-+    FreeBSD 10.0.
++    The aligned_alloc(),
++    malloc_stats_print(), and
++    mallctl*() functions first appeared in FreeBSD
++    10.0.
 +
-+    The *allocx functions first appeared
-+    in FreeBSD 11.0.
++    The *allocx() functions first appeared in FreeBSD
++    11.0.
 +  
  
 diff --git a/include/jemalloc/internal/arena.h b/include/jemalloc/internal/arena.h
-index b1de2b6..da6b6d2 100644
+index f39ce54..a3ba55d 100644
 --- a/include/jemalloc/internal/arena.h
 +++ b/include/jemalloc/internal/arena.h
-@@ -718,8 +718,13 @@ arena_miscelm_get_mutable(arena_chunk_t *chunk, size_t pageind)
+@@ -719,8 +719,13 @@ arena_miscelm_get_mutable(arena_chunk_t *chunk, size_t pageind)
  JEMALLOC_ALWAYS_INLINE const arena_chunk_map_misc_t *
  arena_miscelm_get_const(const arena_chunk_t *chunk, size_t pageind)
  {
@@ -64,7 +64,7 @@ index b1de2b6..da6b6d2 100644
  }
  
  JEMALLOC_ALWAYS_INLINE size_t
-@@ -778,8 +783,13 @@ arena_mapbitsp_get_mutable(arena_chunk_t *chunk, size_t pageind)
+@@ -779,8 +784,13 @@ arena_mapbitsp_get_mutable(arena_chunk_t *chunk, size_t pageind)
  JEMALLOC_ALWAYS_INLINE const size_t *
  arena_mapbitsp_get_const(const arena_chunk_t *chunk, size_t pageind)
  {
@@ -79,7 +79,7 @@ index b1de2b6..da6b6d2 100644
  
  JEMALLOC_ALWAYS_INLINE size_t
 diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in
-index 8f82edd..78e2df2 100644
+index fdc8fef..56a35a4 100644
 --- a/include/jemalloc/internal/jemalloc_internal.h.in
 +++ b/include/jemalloc/internal/jemalloc_internal.h.in
 @@ -8,6 +8,9 @@
@@ -108,7 +108,7 @@ index 8f82edd..78e2df2 100644
  static const bool config_prof =
  #ifdef JEMALLOC_PROF
 diff --git a/include/jemalloc/internal/jemalloc_internal_decls.h b/include/jemalloc/internal/jemalloc_internal_decls.h
-index 2b8ca5d..42d97f2 100644
+index c907d91..4626632 100644
 --- a/include/jemalloc/internal/jemalloc_internal_decls.h
 +++ b/include/jemalloc/internal/jemalloc_internal_decls.h
 @@ -1,6 +1,9 @@
@@ -122,10 +122,10 @@ index 2b8ca5d..42d97f2 100644
  #ifdef _WIN32
  #  include 
 diff --git a/include/jemalloc/internal/mutex.h b/include/jemalloc/internal/mutex.h
-index 5221799..60ab041 100644
+index b442d2d..76518db 100644
 --- a/include/jemalloc/internal/mutex.h
 +++ b/include/jemalloc/internal/mutex.h
-@@ -52,9 +52,6 @@ struct malloc_mutex_s {
+@@ -57,9 +57,6 @@ struct malloc_mutex_s {
  
  #ifdef JEMALLOC_LAZY_LOCK
  extern bool isthreaded;
@@ -135,7 +135,7 @@ index 5221799..60ab041 100644
  #endif
  
  bool	malloc_mutex_init(malloc_mutex_t *mutex, const char *name,
-@@ -62,6 +59,7 @@ bool	malloc_mutex_init(malloc_mutex_t *mutex, const char *name,
+@@ -67,6 +64,7 @@ bool	malloc_mutex_init(malloc_mutex_t *mutex, const char *name,
  void	malloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex);
  void	malloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex);
  void	malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex);
@@ -144,10 +144,10 @@ index 5221799..60ab041 100644
  
  #endif /* JEMALLOC_H_EXTERNS */
 diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt
-index f2b6a55..69369c9 100644
+index 87c8c9b..df576f6 100644
 --- a/include/jemalloc/internal/private_symbols.txt
 +++ b/include/jemalloc/internal/private_symbols.txt
-@@ -311,7 +311,6 @@ iralloct_realign
+@@ -307,7 +307,6 @@ iralloct_realign
  isalloc
  isdalloct
  isqalloc
@@ -335,7 +335,7 @@ index f943891..47d032c 100755
 +#include "jemalloc_FreeBSD.h"
  EOF
 diff --git a/src/jemalloc.c b/src/jemalloc.c
-index 5d1f493..46dd1d1 100644
+index 38650ff..f659b55 100644
 --- a/src/jemalloc.c
 +++ b/src/jemalloc.c
 @@ -4,6 +4,10 @@
@@ -347,9 +347,9 @@ index 5d1f493..46dd1d1 100644
 +__sym_compat(_malloc_options, __malloc_options_1_0, FBSD_1.0);
 +
  /* Runtime configuration options. */
- const char	*je_malloc_conf JEMALLOC_ATTR(weak);
- bool	opt_abort =
-@@ -2673,6 +2677,107 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
+ const char	*je_malloc_conf
+ #ifndef _WIN32
+@@ -2756,6 +2760,107 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
   */
  /******************************************************************************/
  /*
@@ -457,7 +457,7 @@ index 5d1f493..46dd1d1 100644
   * The following functions are used by threading libraries for protection of
   * malloc during fork().
   */
-@@ -2814,4 +2919,11 @@ jemalloc_postfork_child(void)
+@@ -2894,4 +2999,11 @@ jemalloc_postfork_child(void)
  	ctl_postfork_child(tsd_tsdn(tsd));
  }
  
@@ -470,7 +470,7 @@ index 5d1f493..46dd1d1 100644
 +
  /******************************************************************************/
 diff --git a/src/mutex.c b/src/mutex.c
-index a1fac34..a24e420 100644
+index 6333e73..13f8d79 100644
 --- a/src/mutex.c
 +++ b/src/mutex.c
 @@ -66,6 +66,17 @@ pthread_create(pthread_t *__restrict thread,
@@ -491,7 +491,7 @@ index a1fac34..a24e420 100644
  #endif
  
  bool
-@@ -140,7 +151,7 @@ malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex)
+@@ -142,7 +153,7 @@ malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex)
  }
  
  bool
@@ -500,7 +500,7 @@ index a1fac34..a24e420 100644
  {
  
  #ifdef JEMALLOC_MUTEX_INIT_CB
-@@ -154,3 +165,14 @@ malloc_mutex_boot(void)
+@@ -156,3 +167,14 @@ malloc_mutex_boot(void)
  #endif
  	return (false);
  }
@@ -516,7 +516,7 @@ index a1fac34..a24e420 100644
 +#endif
 +}
 diff --git a/src/util.c b/src/util.c
-index a1c4a2a..04f9153 100644
+index 7905267..bee1c77 100644
 --- a/src/util.c
 +++ b/src/util.c
 @@ -67,6 +67,22 @@ wrtmessage(void *cbopaque, const char *s)
diff --git a/contrib/jemalloc/VERSION b/contrib/jemalloc/VERSION
index b17fa1dc6714..c108ecb84aad 100644
--- a/contrib/jemalloc/VERSION
+++ b/contrib/jemalloc/VERSION
@@ -1 +1 @@
-4.2.1-0-g3de035335255d553bdb344c32ffdb603816195d8
+4.3.1-0-g0110fa8451af905affd77c3bea0d545fee2251b2
diff --git a/contrib/jemalloc/doc/jemalloc.3 b/contrib/jemalloc/doc/jemalloc.3
index 26fb02a05105..5787e6ea446b 100644
--- a/contrib/jemalloc/doc/jemalloc.3
+++ b/contrib/jemalloc/doc/jemalloc.3
@@ -2,12 +2,12 @@
 .\"     Title: JEMALLOC
 .\"    Author: Jason Evans
 .\" Generator: DocBook XSL Stylesheets v1.76.1 
-.\"      Date: 06/08/2016
+.\"      Date: 11/08/2016
 .\"    Manual: User Manual
-.\"    Source: jemalloc 4.2.1-0-g3de035335255d553bdb344c32ffdb603816195d8
+.\"    Source: jemalloc 4.3.1-0-g0110fa8451af905affd77c3bea0d545fee2251b2
 .\"  Language: English
 .\"
-.TH "JEMALLOC" "3" "06/08/2016" "jemalloc 4.2.1-0-g3de035335255" "User Manual"
+.TH "JEMALLOC" "3" "11/08/2016" "jemalloc 4.3.1-0-g0110fa8451af" "User Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -31,7 +31,7 @@
 jemalloc \- general purpose memory allocation functions
 .SH "LIBRARY"
 .PP
-This manual describes jemalloc 4\&.2\&.1\-0\-g3de035335255d553bdb344c32ffdb603816195d8\&. More information can be found at the
+This manual describes jemalloc 4\&.3\&.1\-0\-g0110fa8451af905affd77c3bea0d545fee2251b2\&. More information can be found at the
 \m[blue]\fBjemalloc website\fR\m[]\&\s-2\u[1]\d\s+2\&.
 .PP
 The following configuration options are enabled in libc\*(Aqs built\-in jemalloc:
@@ -101,26 +101,26 @@ const char *\fImalloc_conf\fR;
 .SS "Standard API"
 .PP
 The
-\fBmalloc\fR\fB\fR
+malloc()
 function allocates
 \fIsize\fR
 bytes of uninitialized memory\&. The allocated space is suitably aligned (after possible pointer coercion) for storage of any type of object\&.
 .PP
 The
-\fBcalloc\fR\fB\fR
+calloc()
 function allocates space for
 \fInumber\fR
 objects, each
 \fIsize\fR
 bytes in length\&. The result is identical to calling
-\fBmalloc\fR\fB\fR
+malloc()
 with an argument of
 \fInumber\fR
 *
 \fIsize\fR, with the exception that the allocated memory is explicitly initialized to zero bytes\&.
 .PP
 The
-\fBposix_memalign\fR\fB\fR
+posix_memalign()
 function allocates
 \fIsize\fR
 bytes of memory such that the allocation\*(Aqs base address is a multiple of
@@ -131,7 +131,7 @@ must be a power of 2 at least as large as
 sizeof(\fBvoid *\fR)\&.
 .PP
 The
-\fBaligned_alloc\fR\fB\fR
+aligned_alloc()
 function allocates
 \fIsize\fR
 bytes of memory such that the allocation\*(Aqs base address is a multiple of
@@ -143,7 +143,7 @@ is not an integral multiple of
 \fIalignment\fR\&.
 .PP
 The
-\fBrealloc\fR\fB\fR
+realloc()
 function changes the size of the previously allocated memory referenced by
 \fIptr\fR
 to
@@ -151,19 +151,19 @@ to
 bytes\&. The contents of the memory are unchanged up to the lesser of the new and old sizes\&. If the new size is larger, the contents of the newly allocated portion of the memory are undefined\&. Upon success, the memory referenced by
 \fIptr\fR
 is freed and a pointer to the newly allocated memory is returned\&. Note that
-\fBrealloc\fR\fB\fR
+realloc()
 may move the memory allocation, resulting in a different return value than
 \fIptr\fR\&. If
 \fIptr\fR
 is
 \fBNULL\fR, the
-\fBrealloc\fR\fB\fR
+realloc()
 function behaves identically to
-\fBmalloc\fR\fB\fR
+malloc()
 for the specified size\&.
 .PP
 The
-\fBfree\fR\fB\fR
+free()
 function causes the allocated memory referenced by
 \fIptr\fR
 to be made available for future allocations\&. If
@@ -173,13 +173,13 @@ is
 .SS "Non\-standard API"
 .PP
 The
-\fBmallocx\fR\fB\fR,
-\fBrallocx\fR\fB\fR,
-\fBxallocx\fR\fB\fR,
-\fBsallocx\fR\fB\fR,
-\fBdallocx\fR\fB\fR,
-\fBsdallocx\fR\fB\fR, and
-\fBnallocx\fR\fB\fR
+mallocx(),
+rallocx(),
+xallocx(),
+sallocx(),
+dallocx(),
+sdallocx(), and
+nallocx()
 functions all have a
 \fIflags\fR
 argument that can be used to specify options\&. The functions only check the options that are contextually relevant\&. Use bitwise or (|) operations to specify one or more of the following:
@@ -211,7 +211,7 @@ Initialize newly allocated memory to contain zero bytes\&. In the growing reallo
 .RS 4
 Use the thread\-specific cache (tcache) specified by the identifier
 \fItc\fR, which must have been acquired via the
-"tcache\&.create"
+tcache\&.create
 mallctl\&. This macro does not validate that
 \fItc\fR
 specifies a valid identifier\&.
@@ -238,7 +238,7 @@ specifies an arena index in the valid range\&.
 .RE
 .PP
 The
-\fBmallocx\fR\fB\fR
+mallocx()
 function allocates at least
 \fIsize\fR
 bytes of memory, and returns a pointer to the base address of the allocation\&. Behavior is undefined if
@@ -247,7 +247,7 @@ is
 \fB0\fR\&.
 .PP
 The
-\fBrallocx\fR\fB\fR
+rallocx()
 function resizes the allocation at
 \fIptr\fR
 to be at least
@@ -258,7 +258,7 @@ is
 \fB0\fR\&.
 .PP
 The
-\fBxallocx\fR\fB\fR
+xallocx()
 function resizes the allocation at
 \fIptr\fR
 in place to be at least
@@ -274,33 +274,33 @@ is
 (\fIsize\fR + \fIextra\fR > \fBSIZE_T_MAX\fR)\&.
 .PP
 The
-\fBsallocx\fR\fB\fR
+sallocx()
 function returns the real size of the allocation at
 \fIptr\fR\&.
 .PP
 The
-\fBdallocx\fR\fB\fR
+dallocx()
 function causes the memory referenced by
 \fIptr\fR
 to be made available for future allocations\&.
 .PP
 The
-\fBsdallocx\fR\fB\fR
+sdallocx()
 function is an extension of
-\fBdallocx\fR\fB\fR
+dallocx()
 with a
 \fIsize\fR
 parameter to allow the caller to pass in the allocation size as an optimization\&. The minimum valid input size is the original requested size of the allocation, and the maximum valid input size is the corresponding value returned by
-\fBnallocx\fR\fB\fR
+nallocx()
 or
-\fBsallocx\fR\fB\fR\&.
+sallocx()\&.
 .PP
 The
-\fBnallocx\fR\fB\fR
+nallocx()
 function allocates no memory, but it performs the same size computation as the
-\fBmallocx\fR\fB\fR
+mallocx()
 function, and returns the real size of the allocation that would result from the equivalent
-\fBmallocx\fR\fB\fR
+mallocx()
 function call, or
 \fB0\fR
 if the inputs exceed the maximum supported size class and/or alignment\&. Behavior is undefined if
@@ -309,7 +309,7 @@ is
 \fB0\fR\&.
 .PP
 The
-\fBmallctl\fR\fB\fR
+mallctl()
 function provides a general interface for introspecting the memory allocator, as well as setting modifiable parameters and triggering actions\&. The period\-separated
 \fIname\fR
 argument specifies a location in a tree\-structured namespace; see the
@@ -328,10 +328,12 @@ and
 \fB0\fR\&.
 .PP
 The
-\fBmallctlnametomib\fR\fB\fR
-function provides a way to avoid repeated name lookups for applications that repeatedly query the same portion of the namespace, by translating a name to a \(lqManagement Information Base\(rq (MIB) that can be passed repeatedly to
-\fBmallctlbymib\fR\fB\fR\&. Upon successful return from
-\fBmallctlnametomib\fR\fB\fR,
+mallctlnametomib()
+function provides a way to avoid repeated name lookups for applications that repeatedly query the same portion of the namespace, by translating a name to a
+\(lqManagement Information Base\(rq
+(MIB) that can be passed repeatedly to
+mallctlbymib()\&. Upon successful return from
+mallctlnametomib(),
 \fImibp\fR
 contains an array of
 \fI*miblenp\fR
@@ -343,7 +345,7 @@ and the input value of
 \fI*miblenp\fR\&. Thus it is possible to pass a
 \fI*miblenp\fR
 that is smaller than the number of period\-separated name components, which results in a partial MIB that can be used as the basis for constructing a complete MIB\&. For name components that are integers (e\&.g\&. the 2 in
-"arenas\&.bin\&.2\&.size"), the corresponding MIB component will always be that integer\&. Therefore, it is legitimate to construct code like the following:
+arenas\&.bin\&.2\&.size), the corresponding MIB component will always be that integer\&. Therefore, it is legitimate to construct code like the following:
 .sp
 .if n \{\
 .RS 4
@@ -372,35 +374,50 @@ for (i = 0; i < nbins; i++) {
 .\}
 .PP
 The
-\fBmalloc_stats_print\fR\fB\fR
-function writes human\-readable summary statistics via the
+malloc_stats_print()
+function writes summary statistics via the
 \fIwrite_cb\fR
 callback function pointer and
 \fIcbopaque\fR
 data passed to
 \fIwrite_cb\fR, or
-\fBmalloc_message\fR\fB\fR
+malloc_message()
 if
 \fIwrite_cb\fR
 is
-\fBNULL\fR\&. This function can be called repeatedly\&. General information that never changes during execution can be omitted by specifying "g" as a character within the
+\fBNULL\fR\&. The statistics are presented in human\-readable form unless
+\(lqJ\(rq
+is specified as a character within the
+\fIopts\fR
+string, in which case the statistics are presented in
+\m[blue]\fBJSON format\fR\m[]\&\s-2\u[2]\d\s+2\&. This function can be called repeatedly\&. General information that never changes during execution can be omitted by specifying
+\(lqg\(rq
+as a character within the
 \fIopts\fR
 string\&. Note that
-\fBmalloc_message\fR\fB\fR
+malloc_message()
 uses the
-\fBmallctl*\fR\fB\fR
+mallctl*()
 functions internally, so inconsistent statistics can be reported if multiple threads use these functions simultaneously\&. If
 \fB\-\-enable\-stats\fR
-is specified during configuration, \(lqm\(rq and \(lqa\(rq can be specified to omit merged arena and per arena statistics, respectively; \(lqb\(rq, \(lql\(rq, and \(lqh\(rq can be specified to omit per size class statistics for bins, large objects, and huge objects, respectively\&. Unrecognized characters are silently ignored\&. Note that thread caching may prevent some statistics from being completely up to date, since extra locking would be required to merge counters that track thread cache operations\&.
+is specified during configuration,
+\(lqm\(rq
+and
+\(lqa\(rq
+can be specified to omit merged arena and per arena statistics, respectively;
+\(lqb\(rq,
+\(lql\(rq, and
+\(lqh\(rq
+can be specified to omit per size class statistics for bins, large objects, and huge objects, respectively\&. Unrecognized characters are silently ignored\&. Note that thread caching may prevent some statistics from being completely up to date, since extra locking would be required to merge counters that track thread cache operations\&.
 .PP
 The
-\fBmalloc_usable_size\fR\fB\fR
+malloc_usable_size()
 function returns the usable size of the allocation pointed to by
 \fIptr\fR\&. The return value may be larger than the size that was requested during allocation\&. The
-\fBmalloc_usable_size\fR\fB\fR
+malloc_usable_size()
 function is not a mechanism for in\-place
-\fBrealloc\fR\fB\fR; rather it is provided solely as a tool for introspection purposes\&. Any discrepancy between the requested allocation size and the size reported by
-\fBmalloc_usable_size\fR\fB\fR
+realloc(); rather it is provided solely as a tool for introspection purposes\&. Any discrepancy between the requested allocation size and the size reported by
+malloc_usable_size()
 should not be depended on, since such behavior is entirely implementation\-dependent\&.
 .SH "TUNING"
 .PP
@@ -408,12 +425,14 @@ Once, when the first call is made to one of the memory allocation routines, the
 .PP
 The string specified via
 \fB\-\-with\-malloc\-conf\fR, the string pointed to by the global variable
-\fImalloc_conf\fR, the \(lqname\(rq of the file referenced by the symbolic link named
+\fImalloc_conf\fR, the
+\(lqname\(rq
+of the file referenced by the symbolic link named
 /etc/malloc\&.conf, and the value of the environment variable
 \fBMALLOC_CONF\fR, will be interpreted, in that order, from left to right as options\&. Note that
 \fImalloc_conf\fR
 may be read before
-\fBmain\fR\fB\fR
+main()
 is entered, so the declaration of
 \fImalloc_conf\fR
 should specify an initializer that contains the final value to be read by jemalloc\&.
@@ -427,15 +446,15 @@ and
 can be safely set any time prior to program invocation\&.
 .PP
 An options string is a comma\-separated list of option:value pairs\&. There is one key corresponding to each
-"opt\&.*"
+opt\&.*
 mallctl (see the
 MALLCTL NAMESPACE
 section for options documentation)\&. For example,
 abort:true,narenas:1
 sets the
-"opt\&.abort"
+opt\&.abort
 and
-"opt\&.narenas"
+opt\&.narenas
 options\&. Some options have boolean values (true/false), others have integer values (base 8, 10, or 16, depending on prefix), and yet others have raw string values\&.
 .SH "IMPLEMENTATION NOTES"
 .PP
@@ -460,22 +479,22 @@ Memory is conceptually broken into equal\-sized chunks, where the chunk size is
 .PP
 Small objects are managed in groups by page runs\&. Each run maintains a bitmap to track which regions are in use\&. Allocation requests that are no more than half the quantum (8 or 16, depending on architecture) are rounded up to the nearest power of two that is at least
 sizeof(\fBdouble\fR)\&. All other object size classes are multiples of the quantum, spaced such that there are four size classes for each doubling in size, which limits internal fragmentation to approximately 20% for all but the smallest size classes\&. Small size classes are smaller than four times the page size, large size classes are smaller than the chunk size (see the
-"opt\&.lg_chunk"
+opt\&.lg_chunk
 option), and huge size classes extend from the chunk size up to the largest size class that does not exceed
 \fBPTRDIFF_MAX\fR\&.
 .PP
 Allocations are packed tightly together, which can be an issue for multi\-threaded applications\&. If you need to assure that allocations do not suffer from cacheline sharing, round your allocation requests up to the nearest multiple of the cacheline size, or specify cacheline alignment when allocating\&.
 .PP
 The
-\fBrealloc\fR\fB\fR,
-\fBrallocx\fR\fB\fR, and
-\fBxallocx\fR\fB\fR
+realloc(),
+rallocx(), and
+xallocx()
 functions may resize allocations without moving them under limited circumstances\&. Unlike the
-\fB*allocx\fR\fB\fR
+*allocx()
 API, the standard API does not officially round up the usable size of an allocation to the nearest size class, so technically it is necessary to call
-\fBrealloc\fR\fB\fR
+realloc()
 to grow e\&.g\&. a 9\-byte allocation to 16 bytes, or shrink a 16\-byte allocation to 9 bytes\&. Growth and shrinkage trivially succeeds in place as long as the pre\-size and post\-size both round up to the same size class\&. No other API guarantees are made regarding in\-place resizing, but the current implementation also tries to resize large and huge allocations in place, as long as the pre\-size and post\-size are both large or both huge\&. In such cases shrinkage always succeeds for large size classes, but for huge size classes the chunk allocator must support splitting (see
-"arena\&.\&.chunk_hooks")\&. Growth only succeeds if the trailing memory is currently available, and additionally for huge size classes the chunk allocator must support merging\&.
+arena\&.\&.chunk_hooks)\&. Growth only succeeds if the trailing memory is currently available, and additionally for huge size classes the chunk allocator must support merging\&.
 .PP
 Assuming 2 MiB chunks, 4 KiB pages, and a 16\-byte quantum on a 64\-bit system, the size classes in each category are as shown in
 Table 1\&.
@@ -663,7 +682,7 @@ T}
 .SH "MALLCTL NAMESPACE"
 .PP
 The following names are defined in the namespace accessible via the
-\fBmallctl*\fR\fB\fR
+mallctl*()
 functions\&. Value types are specified in parentheses, their readable/writable statuses are encoded as
 rw,
 r\-,
@@ -673,118 +692,118 @@ r\-,
 or
 
 indicates an integer component, where the integer varies from 0 to some upper value that must be determined via introspection\&. In the case of
-"stats\&.arenas\&.\&.*",
+stats\&.arenas\&.\&.*,
 
 equal to
-"arenas\&.narenas"
+arenas\&.narenas
 can be used to access the summation of statistics from all arenas\&. Take special note of the
-"epoch"
+epoch
 mallctl, which controls refreshing of cached dynamic statistics\&.
 .PP
-"version" (\fBconst char *\fR) r\-
+version (\fBconst char *\fR) r\-
 .RS 4
 Return the jemalloc version string\&.
 .RE
 .PP
-"epoch" (\fBuint64_t\fR) rw
+epoch (\fBuint64_t\fR) rw
 .RS 4
 If a value is passed in, refresh the data from which the
-\fBmallctl*\fR\fB\fR
+mallctl*()
 functions report values, and increment the epoch\&. Return the current epoch\&. This is useful for detecting whether another thread caused a refresh\&.
 .RE
 .PP
-"config\&.cache_oblivious" (\fBbool\fR) r\-
+config\&.cache_oblivious (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-cache\-oblivious\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.debug" (\fBbool\fR) r\-
+config\&.debug (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-debug\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.fill" (\fBbool\fR) r\-
+config\&.fill (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-fill\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.lazy_lock" (\fBbool\fR) r\-
+config\&.lazy_lock (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-lazy\-lock\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.malloc_conf" (\fBconst char *\fR) r\-
+config\&.malloc_conf (\fBconst char *\fR) r\-
 .RS 4
 Embedded configure\-time\-specified run\-time options string, empty unless
 \fB\-\-with\-malloc\-conf\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.munmap" (\fBbool\fR) r\-
+config\&.munmap (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-munmap\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.prof" (\fBbool\fR) r\-
+config\&.prof (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-prof\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.prof_libgcc" (\fBbool\fR) r\-
+config\&.prof_libgcc (\fBbool\fR) r\-
 .RS 4
 \fB\-\-disable\-prof\-libgcc\fR
 was not specified during build configuration\&.
 .RE
 .PP
-"config\&.prof_libunwind" (\fBbool\fR) r\-
+config\&.prof_libunwind (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-prof\-libunwind\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.stats" (\fBbool\fR) r\-
+config\&.stats (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-stats\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.tcache" (\fBbool\fR) r\-
+config\&.tcache (\fBbool\fR) r\-
 .RS 4
 \fB\-\-disable\-tcache\fR
 was not specified during build configuration\&.
 .RE
 .PP
-"config\&.tls" (\fBbool\fR) r\-
+config\&.tls (\fBbool\fR) r\-
 .RS 4
 \fB\-\-disable\-tls\fR
 was not specified during build configuration\&.
 .RE
 .PP
-"config\&.utrace" (\fBbool\fR) r\-
+config\&.utrace (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-utrace\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.valgrind" (\fBbool\fR) r\-
+config\&.valgrind (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-valgrind\fR
 was specified during build configuration\&.
 .RE
 .PP
-"config\&.xmalloc" (\fBbool\fR) r\-
+config\&.xmalloc (\fBbool\fR) r\-
 .RS 4
 \fB\-\-enable\-xmalloc\fR
 was specified during build configuration\&.
 .RE
 .PP
-"opt\&.abort" (\fBbool\fR) r\-
+opt\&.abort (\fBbool\fR) r\-
 .RS 4
 Abort\-on\-warning enabled/disabled\&. If true, most warnings are fatal\&. The process will call
 \fBabort\fR(3)
@@ -793,115 +812,132 @@ in these cases\&. This option is disabled by default unless
 is specified during configuration, in which case it is enabled by default\&.
 .RE
 .PP
-"opt\&.dss" (\fBconst char *\fR) r\-
+opt\&.dss (\fBconst char *\fR) r\-
 .RS 4
 dss (\fBsbrk\fR(2)) allocation precedence as related to
 \fBmmap\fR(2)
 allocation\&. The following settings are supported if
 \fBsbrk\fR(2)
-is supported by the operating system: \(lqdisabled\(rq, \(lqprimary\(rq, and \(lqsecondary\(rq; otherwise only \(lqdisabled\(rq is supported\&. The default is \(lqsecondary\(rq if
+is supported by the operating system:
+\(lqdisabled\(rq,
+\(lqprimary\(rq, and
+\(lqsecondary\(rq; otherwise only
+\(lqdisabled\(rq
+is supported\&. The default is
+\(lqsecondary\(rq
+if
 \fBsbrk\fR(2)
-is supported by the operating system; \(lqdisabled\(rq otherwise\&.
+is supported by the operating system;
+\(lqdisabled\(rq
+otherwise\&.
 .RE
 .PP
-"opt\&.lg_chunk" (\fBsize_t\fR) r\-
+opt\&.lg_chunk (\fBsize_t\fR) r\-
 .RS 4
 Virtual memory chunk size (log base 2)\&. If a chunk size outside the supported size range is specified, the size is silently clipped to the minimum/maximum supported size\&. The default chunk size is 2 MiB (2^21)\&.
 .RE
 .PP
-"opt\&.narenas" (\fBunsigned\fR) r\-
+opt\&.narenas (\fBunsigned\fR) r\-
 .RS 4
 Maximum number of arenas to use for automatic multiplexing of threads and arenas\&. The default is four times the number of CPUs, or one if there is a single CPU\&.
 .RE
 .PP
-"opt\&.purge" (\fBconst char *\fR) r\-
+opt\&.purge (\fBconst char *\fR) r\-
 .RS 4
 Purge mode is \(lqratio\(rq (default) or \(lqdecay\(rq\&. See
-"opt\&.lg_dirty_mult"
+opt\&.lg_dirty_mult
 for details of the ratio mode\&. See
-"opt\&.decay_time"
+opt\&.decay_time
 for details of the decay mode\&.
 .RE
 .PP
-"opt\&.lg_dirty_mult" (\fBssize_t\fR) r\-
+opt\&.lg_dirty_mult (\fBssize_t\fR) r\-
 .RS 4
 Per\-arena minimum ratio (log base 2) of active to dirty pages\&. Some dirty unused pages may be allowed to accumulate, within the limit set by the ratio (or one chunk worth of dirty pages, whichever is greater), before informing the kernel about some of those pages via
 \fBmadvise\fR(2)
 or a similar system call\&. This provides the kernel with sufficient information to recycle dirty pages if physical memory becomes scarce and the pages remain unused\&. The default minimum ratio is 8:1 (2^3:1); an option value of \-1 will disable dirty page purging\&. See
-"arenas\&.lg_dirty_mult"
+arenas\&.lg_dirty_mult
 and
-"arena\&.\&.lg_dirty_mult"
+arena\&.\&.lg_dirty_mult
 for related dynamic control options\&.
 .RE
 .PP
-"opt\&.decay_time" (\fBssize_t\fR) r\-
+opt\&.decay_time (\fBssize_t\fR) r\-
 .RS 4
 Approximate time in seconds from the creation of a set of unused dirty pages until an equivalent set of unused dirty pages is purged and/or reused\&. The pages are incrementally purged according to a sigmoidal decay curve that starts and ends with zero purge rate\&. A decay time of 0 causes all unused dirty pages to be purged immediately upon creation\&. A decay time of \-1 disables purging\&. The default decay time is 10 seconds\&. See
-"arenas\&.decay_time"
+arenas\&.decay_time
 and
-"arena\&.\&.decay_time"
+arena\&.\&.decay_time
 for related dynamic control options\&.
 .RE
 .PP
-"opt\&.stats_print" (\fBbool\fR) r\-
+opt\&.stats_print (\fBbool\fR) r\-
 .RS 4
 Enable/disable statistics printing at exit\&. If enabled, the
-\fBmalloc_stats_print\fR\fB\fR
+malloc_stats_print()
 function is called at program exit via an
 \fBatexit\fR(3)
 function\&. If
 \fB\-\-enable\-stats\fR
 is specified during configuration, this has the potential to cause deadlock for a multi\-threaded process that exits while one or more threads are executing in the memory allocation functions\&. Furthermore,
-\fBatexit\fR\fB\fR
+atexit()
 may allocate memory during application initialization and then deadlock internally when jemalloc in turn calls
-\fBatexit\fR\fB\fR, so this option is not universally usable (though the application can register its own
-\fBatexit\fR\fB\fR
+atexit(), so this option is not universally usable (though the application can register its own
+atexit()
 function with equivalent functionality)\&. Therefore, this option should only be used with care; it is primarily intended as a performance tuning aid during application development\&. This option is disabled by default\&.
 .RE
 .PP
-"opt\&.junk" (\fBconst char *\fR) r\- [\fB\-\-enable\-fill\fR]
+opt\&.junk (\fBconst char *\fR) r\- [\fB\-\-enable\-fill\fR]
 .RS 4
-Junk filling\&. If set to "alloc", each byte of uninitialized allocated memory will be initialized to
-0xa5\&. If set to "free", all deallocated memory will be initialized to
-0x5a\&. If set to "true", both allocated and deallocated memory will be initialized, and if set to "false", junk filling be disabled entirely\&. This is intended for debugging and will impact performance negatively\&. This option is "false" by default unless
+Junk filling\&. If set to
+\(lqalloc\(rq, each byte of uninitialized allocated memory will be initialized to
+0xa5\&. If set to
+\(lqfree\(rq, all deallocated memory will be initialized to
+0x5a\&. If set to
+\(lqtrue\(rq, both allocated and deallocated memory will be initialized, and if set to
+\(lqfalse\(rq, junk filling be disabled entirely\&. This is intended for debugging and will impact performance negatively\&. This option is
+\(lqfalse\(rq
+by default unless
 \fB\-\-enable\-debug\fR
-is specified during configuration, in which case it is "true" by default unless running inside
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2\&.
+is specified during configuration, in which case it is
+\(lqtrue\(rq
+by default unless running inside
+\m[blue]\fBValgrind\fR\m[]\&\s-2\u[3]\d\s+2\&.
 .RE
 .PP
-"opt\&.quarantine" (\fBsize_t\fR) r\- [\fB\-\-enable\-fill\fR]
+opt\&.quarantine (\fBsize_t\fR) r\- [\fB\-\-enable\-fill\fR]
 .RS 4
 Per thread quarantine size in bytes\&. If non\-zero, each thread maintains a FIFO object quarantine that stores up to the specified number of bytes of memory\&. The quarantined memory is not freed until it is released from quarantine, though it is immediately junk\-filled if the
-"opt\&.junk"
+opt\&.junk
 option is enabled\&. This feature is of particular use in combination with
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2, which can detect attempts to access quarantined objects\&. This is intended for debugging and will impact performance negatively\&. The default quarantine size is 0 unless running inside Valgrind, in which case the default is 16 MiB\&.
+\m[blue]\fBValgrind\fR\m[]\&\s-2\u[3]\d\s+2, which can detect attempts to access quarantined objects\&. This is intended for debugging and will impact performance negatively\&. The default quarantine size is 0 unless running inside Valgrind, in which case the default is 16 MiB\&.
 .RE
 .PP
-"opt\&.redzone" (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
+opt\&.redzone (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
 .RS 4
 Redzones enabled/disabled\&. If enabled, small allocations have redzones before and after them\&. Furthermore, if the
-"opt\&.junk"
+opt\&.junk
 option is enabled, the redzones are checked for corruption during deallocation\&. However, the primary intended purpose of this feature is to be used in combination with
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2, which needs redzones in order to do effective buffer overflow/underflow detection\&. This option is intended for debugging and will impact performance negatively\&. This option is disabled by default unless running inside Valgrind\&.
+\m[blue]\fBValgrind\fR\m[]\&\s-2\u[3]\d\s+2, which needs redzones in order to do effective buffer overflow/underflow detection\&. This option is intended for debugging and will impact performance negatively\&. This option is disabled by default unless running inside Valgrind\&.
 .RE
 .PP
-"opt\&.zero" (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
+opt\&.zero (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
 .RS 4
 Zero filling enabled/disabled\&. If enabled, each byte of uninitialized allocated memory will be initialized to 0\&. Note that this initialization only happens once for each byte, so
-\fBrealloc\fR\fB\fR
+realloc()
 and
-\fBrallocx\fR\fB\fR
+rallocx()
 calls do not zero memory that was previously allocated\&. This is intended for debugging and will impact performance negatively\&. This option is disabled by default\&.
 .RE
 .PP
-"opt\&.utrace" (\fBbool\fR) r\- [\fB\-\-enable\-utrace\fR]
+opt\&.utrace (\fBbool\fR) r\- [\fB\-\-enable\-utrace\fR]
 .RS 4
 Allocation tracing based on
 \fButrace\fR(2)
 enabled/disabled\&. This option is disabled by default\&.
 .RE
 .PP
-"opt\&.xmalloc" (\fBbool\fR) r\- [\fB\-\-enable\-xmalloc\fR]
+opt\&.xmalloc (\fBbool\fR) r\- [\fB\-\-enable\-xmalloc\fR]
 .RS 4
 Abort\-on\-out\-of\-memory enabled/disabled\&. If enabled, rather than returning failure for any allocation function, display a diagnostic message on
 \fBSTDERR_FILENO\fR
@@ -921,94 +957,94 @@ malloc_conf = "xmalloc:true";
 This option is disabled by default\&.
 .RE
 .PP
-"opt\&.tcache" (\fBbool\fR) r\- [\fB\-\-enable\-tcache\fR]
+opt\&.tcache (\fBbool\fR) r\- [\fB\-\-enable\-tcache\fR]
 .RS 4
 Thread\-specific caching (tcache) enabled/disabled\&. When there are multiple threads, each thread uses a tcache for objects up to a certain size\&. Thread\-specific caching allows many allocations to be satisfied without performing any thread synchronization, at the cost of increased memory use\&. See the
-"opt\&.lg_tcache_max"
+opt\&.lg_tcache_max
 option for related tuning information\&. This option is enabled by default unless running inside
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2, in which case it is forcefully disabled\&.
+\m[blue]\fBValgrind\fR\m[]\&\s-2\u[3]\d\s+2, in which case it is forcefully disabled\&.
 .RE
 .PP
-"opt\&.lg_tcache_max" (\fBsize_t\fR) r\- [\fB\-\-enable\-tcache\fR]
+opt\&.lg_tcache_max (\fBsize_t\fR) r\- [\fB\-\-enable\-tcache\fR]
 .RS 4
 Maximum size class (log base 2) to cache in the thread\-specific cache (tcache)\&. At a minimum, all small size classes are cached, and at a maximum all large size classes are cached\&. The default maximum is 32 KiB (2^15)\&.
 .RE
 .PP
-"opt\&.prof" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Memory profiling enabled/disabled\&. If enabled, profile memory allocation activity\&. See the
-"opt\&.prof_active"
+opt\&.prof_active
 option for on\-the\-fly activation/deactivation\&. See the
-"opt\&.lg_prof_sample"
+opt\&.lg_prof_sample
 option for probabilistic sampling control\&. See the
-"opt\&.prof_accum"
+opt\&.prof_accum
 option for control of cumulative sample reporting\&. See the
-"opt\&.lg_prof_interval"
+opt\&.lg_prof_interval
 option for information on interval\-triggered profile dumping, the
-"opt\&.prof_gdump"
+opt\&.prof_gdump
 option for information on high\-water\-triggered profile dumping, and the
-"opt\&.prof_final"
+opt\&.prof_final
 option for final profile dumping\&. Profile output is compatible with the
 \fBjeprof\fR
 command, which is based on the
 \fBpprof\fR
 that is developed as part of the
-\m[blue]\fBgperftools package\fR\m[]\&\s-2\u[3]\d\s+2\&. See
+\m[blue]\fBgperftools package\fR\m[]\&\s-2\u[4]\d\s+2\&. See
 HEAP PROFILE FORMAT
 for heap profile format documentation\&.
 .RE
 .PP
-"opt\&.prof_prefix" (\fBconst char *\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_prefix (\fBconst char *\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Filename prefix for profile dumps\&. If the prefix is set to the empty string, no automatic dumps will occur; this is primarily useful for disabling the automatic final heap dump (which also disables leak reporting, if enabled)\&. The default prefix is
 jeprof\&.
 .RE
 .PP
-"opt\&.prof_active" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_active (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Profiling activated/deactivated\&. This is a secondary control mechanism that makes it possible to start the application with profiling enabled (see the
-"opt\&.prof"
+opt\&.prof
 option) but inactive, then toggle profiling at any time during program execution with the
-"prof\&.active"
+prof\&.active
 mallctl\&. This option is enabled by default\&.
 .RE
 .PP
-"opt\&.prof_thread_active_init" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_thread_active_init (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Initial setting for
-"thread\&.prof\&.active"
+thread\&.prof\&.active
 in newly created threads\&. The initial setting for newly created threads can also be changed during execution via the
-"prof\&.thread_active_init"
+prof\&.thread_active_init
 mallctl\&. This option is enabled by default\&.
 .RE
 .PP
-"opt\&.lg_prof_sample" (\fBsize_t\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.lg_prof_sample (\fBsize_t\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Average interval (log base 2) between allocation samples, as measured in bytes of allocation activity\&. Increasing the sampling interval decreases profile fidelity, but also decreases the computational overhead\&. The default sample interval is 512 KiB (2^19 B)\&.
 .RE
 .PP
-"opt\&.prof_accum" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_accum (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Reporting of cumulative object/byte counts in profile dumps enabled/disabled\&. If this option is enabled, every unique backtrace must be stored for the duration of execution\&. Depending on the application, this can impose a large memory overhead, and the cumulative counts are not always of interest\&. This option is disabled by default\&.
 .RE
 .PP
-"opt\&.lg_prof_interval" (\fBssize_t\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.lg_prof_interval (\fBssize_t\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Average interval (log base 2) between memory profile dumps, as measured in bytes of allocation activity\&. The actual interval between dumps may be sporadic because decentralized allocation counters are used to avoid synchronization bottlenecks\&. Profiles are dumped to files named according to the pattern
 \&.\&.\&.i\&.heap, where
 
 is controlled by the
-"opt\&.prof_prefix"
+opt\&.prof_prefix
 option\&. By default, interval\-triggered profile dumping is disabled (encoded as \-1)\&.
 .RE
 .PP
-"opt\&.prof_gdump" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_gdump (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Set the initial state of
-"prof\&.gdump", which when enabled triggers a memory profile dump every time the total virtual memory exceeds the previous maximum\&. This option is disabled by default\&.
+prof\&.gdump, which when enabled triggers a memory profile dump every time the total virtual memory exceeds the previous maximum\&. This option is disabled by default\&.
 .RE
 .PP
-"opt\&.prof_final" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_final (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Use an
 \fBatexit\fR(3)
@@ -1016,71 +1052,71 @@ function to dump final memory usage to a file named according to the pattern
 \&.\&.\&.f\&.heap, where
 
 is controlled by the
-"opt\&.prof_prefix"
+opt\&.prof_prefix
 option\&. Note that
-\fBatexit\fR\fB\fR
+atexit()
 may allocate memory during application initialization and then deadlock internally when jemalloc in turn calls
-\fBatexit\fR\fB\fR, so this option is not universally usable (though the application can register its own
-\fBatexit\fR\fB\fR
+atexit(), so this option is not universally usable (though the application can register its own
+atexit()
 function with equivalent functionality)\&. This option is disabled by default\&.
 .RE
 .PP
-"opt\&.prof_leak" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
+opt\&.prof_leak (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Leak reporting enabled/disabled\&. If enabled, use an
 \fBatexit\fR(3)
 function to report memory leaks detected by allocation sampling\&. See the
-"opt\&.prof"
+opt\&.prof
 option for information on analyzing heap profile output\&. This option is disabled by default\&.
 .RE
 .PP
-"thread\&.arena" (\fBunsigned\fR) rw
+thread\&.arena (\fBunsigned\fR) rw
 .RS 4
 Get or set the arena associated with the calling thread\&. If the specified arena was not initialized beforehand (see the
-"arenas\&.initialized"
+arenas\&.initialized
 mallctl), it will be automatically initialized as a side effect of calling this interface\&.
 .RE
 .PP
-"thread\&.allocated" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+thread\&.allocated (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Get the total number of bytes ever allocated by the calling thread\&. This counter has the potential to wrap around; it is up to the application to appropriately interpret the counter in such cases\&.
 .RE
 .PP
-"thread\&.allocatedp" (\fBuint64_t *\fR) r\- [\fB\-\-enable\-stats\fR]
+thread\&.allocatedp (\fBuint64_t *\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Get a pointer to the the value that is returned by the
-"thread\&.allocated"
+thread\&.allocated
 mallctl\&. This is useful for avoiding the overhead of repeated
-\fBmallctl*\fR\fB\fR
+mallctl*()
 calls\&.
 .RE
 .PP
-"thread\&.deallocated" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+thread\&.deallocated (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Get the total number of bytes ever deallocated by the calling thread\&. This counter has the potential to wrap around; it is up to the application to appropriately interpret the counter in such cases\&.
 .RE
 .PP
-"thread\&.deallocatedp" (\fBuint64_t *\fR) r\- [\fB\-\-enable\-stats\fR]
+thread\&.deallocatedp (\fBuint64_t *\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Get a pointer to the the value that is returned by the
-"thread\&.deallocated"
+thread\&.deallocated
 mallctl\&. This is useful for avoiding the overhead of repeated
-\fBmallctl*\fR\fB\fR
+mallctl*()
 calls\&.
 .RE
 .PP
-"thread\&.tcache\&.enabled" (\fBbool\fR) rw [\fB\-\-enable\-tcache\fR]
+thread\&.tcache\&.enabled (\fBbool\fR) rw [\fB\-\-enable\-tcache\fR]
 .RS 4
 Enable/disable calling thread\*(Aqs tcache\&. The tcache is implicitly flushed as a side effect of becoming disabled (see
-"thread\&.tcache\&.flush")\&.
+thread\&.tcache\&.flush)\&.
 .RE
 .PP
-"thread\&.tcache\&.flush" (\fBvoid\fR) \-\- [\fB\-\-enable\-tcache\fR]
+thread\&.tcache\&.flush (\fBvoid\fR) \-\- [\fB\-\-enable\-tcache\fR]
 .RS 4
 Flush calling thread\*(Aqs thread\-specific cache (tcache)\&. This interface releases all cached objects and internal data structures associated with the calling thread\*(Aqs tcache\&. Ordinarily, this interface need not be called, since automatic periodic incremental garbage collection occurs, and the thread cache is automatically discarded when a thread exits\&. However, garbage collection is triggered by allocation activity, so it is possible for a thread that stops allocating/deallocating to retain its cache indefinitely, in which case the developer may find manual flushing useful\&.
 .RE
 .PP
-"thread\&.prof\&.name" (\fBconst char *\fR) r\- or \-w [\fB\-\-enable\-prof\fR]
+thread\&.prof\&.name (\fBconst char *\fR) r\- or \-w [\fB\-\-enable\-prof\fR]
 .RS 4
 Get/set the descriptive name associated with the calling thread in memory profile dumps\&. An internal copy of the name string is created, so the input string need not be maintained after this interface completes execution\&. The output string of this interface should be copied for non\-ephemeral uses, because multiple implementation details can cause asynchronous string deallocation\&. Furthermore, each invocation of this interface can only read or write; simultaneous read/write is not supported due to string lifetime limitations\&. The name string must be nil\-terminated and comprised only of characters in the sets recognized by
 \fBisgraph\fR(3)
@@ -1088,78 +1124,78 @@ and
 \fBisblank\fR(3)\&.
 .RE
 .PP
-"thread\&.prof\&.active" (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
+thread\&.prof\&.active (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
 .RS 4
 Control whether sampling is currently active for the calling thread\&. This is an activation mechanism in addition to
-"prof\&.active"; both must be active for the calling thread to sample\&. This flag is enabled by default\&.
+prof\&.active; both must be active for the calling thread to sample\&. This flag is enabled by default\&.
 .RE
 .PP
-"tcache\&.create" (\fBunsigned\fR) r\- [\fB\-\-enable\-tcache\fR]
+tcache\&.create (\fBunsigned\fR) r\- [\fB\-\-enable\-tcache\fR]
 .RS 4
 Create an explicit thread\-specific cache (tcache) and return an identifier that can be passed to the
 \fBMALLOCX_TCACHE(\fR\fB\fItc\fR\fR\fB)\fR
 macro to explicitly use the specified cache rather than the automatically managed one that is used by default\&. Each explicit cache can be used by only one thread at a time; the application must assure that this constraint holds\&.
 .RE
 .PP
-"tcache\&.flush" (\fBunsigned\fR) \-w [\fB\-\-enable\-tcache\fR]
+tcache\&.flush (\fBunsigned\fR) \-w [\fB\-\-enable\-tcache\fR]
 .RS 4
 Flush the specified thread\-specific cache (tcache)\&. The same considerations apply to this interface as to
-"thread\&.tcache\&.flush", except that the tcache will never be automatically discarded\&.
+thread\&.tcache\&.flush, except that the tcache will never be automatically discarded\&.
 .RE
 .PP
-"tcache\&.destroy" (\fBunsigned\fR) \-w [\fB\-\-enable\-tcache\fR]
+tcache\&.destroy (\fBunsigned\fR) \-w [\fB\-\-enable\-tcache\fR]
 .RS 4
 Flush the specified thread\-specific cache (tcache) and make the identifier available for use during a future tcache creation\&.
 .RE
 .PP
-"arena\&.\&.purge" (\fBvoid\fR) \-\-
+arena\&.\&.purge (\fBvoid\fR) \-\-
 .RS 4
 Purge all unused dirty pages for arena , or for all arenas if  equals
-"arenas\&.narenas"\&.
+arenas\&.narenas\&.
 .RE
 .PP
-"arena\&.\&.decay" (\fBvoid\fR) \-\-
+arena\&.\&.decay (\fBvoid\fR) \-\-
 .RS 4
 Trigger decay\-based purging of unused dirty pages for arena , or for all arenas if  equals
-"arenas\&.narenas"\&. The proportion of unused dirty pages to be purged depends on the current time; see
-"opt\&.decay_time"
+arenas\&.narenas\&. The proportion of unused dirty pages to be purged depends on the current time; see
+opt\&.decay_time
 for details\&.
 .RE
 .PP
-"arena\&.\&.reset" (\fBvoid\fR) \-\-
+arena\&.\&.reset (\fBvoid\fR) \-\-
 .RS 4
 Discard all of the arena\*(Aqs extant allocations\&. This interface can only be used with arenas created via
-"arenas\&.extend"\&. None of the arena\*(Aqs discarded/cached allocations may accessed afterward\&. As part of this requirement, all thread caches which were used to allocate/deallocate in conjunction with the arena must be flushed beforehand\&. This interface cannot be used if running inside Valgrind, nor if the
+arenas\&.extend\&. None of the arena\*(Aqs discarded/cached allocations may accessed afterward\&. As part of this requirement, all thread caches which were used to allocate/deallocate in conjunction with the arena must be flushed beforehand\&. This interface cannot be used if running inside Valgrind, nor if the
 quarantine
 size is non\-zero\&.
 .RE
 .PP
-"arena\&.\&.dss" (\fBconst char *\fR) rw
+arena\&.\&.dss (\fBconst char *\fR) rw
 .RS 4
 Set the precedence of dss allocation as related to mmap allocation for arena , or for all arenas if  equals
-"arenas\&.narenas"\&. See
-"opt\&.dss"
+arenas\&.narenas\&. See
+opt\&.dss
 for supported settings\&.
 .RE
 .PP
-"arena\&.\&.lg_dirty_mult" (\fBssize_t\fR) rw
+arena\&.\&.lg_dirty_mult (\fBssize_t\fR) rw
 .RS 4
 Current per\-arena minimum ratio (log base 2) of active to dirty pages for arena \&. Each time this interface is set and the ratio is increased, pages are synchronously purged as necessary to impose the new ratio\&. See
-"opt\&.lg_dirty_mult"
+opt\&.lg_dirty_mult
 for additional information\&.
 .RE
 .PP
-"arena\&.\&.decay_time" (\fBssize_t\fR) rw
+arena\&.\&.decay_time (\fBssize_t\fR) rw
 .RS 4
 Current per\-arena approximate time in seconds from the creation of a set of unused dirty pages until an equivalent set of unused dirty pages is purged and/or reused\&. Each time this interface is set, all currently unused dirty pages are considered to have fully decayed, which causes immediate purging of all unused dirty pages unless the decay time is set to \-1 (i\&.e\&. purging disabled)\&. See
-"opt\&.decay_time"
+opt\&.decay_time
 for additional information\&.
 .RE
 .PP
-"arena\&.\&.chunk_hooks" (\fBchunk_hooks_t\fR) rw
+arena\&.\&.chunk_hooks (\fBchunk_hooks_t\fR) rw
 .RS 4
 Get or set the chunk management hook functions for arena \&. The functions must be capable of operating on all extant chunks associated with arena , usually by passing unknown chunks to the replaced functions\&. In practice, it is feasible to control allocation for arenas created via
-"arenas\&.extend"
+arenas\&.extend
 such that all chunks originate from an application\-supplied chunk allocator (by setting custom chunk hook functions just after arena creation), but the automatically created arenas may have already created chunks prior to the application having an opportunity to take over chunk allocation\&.
 .sp
 .if n \{\
@@ -1228,7 +1264,7 @@ is not
 on success or
 \fBNULL\fR
 on error\&. Committed memory may be committed in absolute terms as on a system that does not overcommit, or in implicit terms as on a system that overcommits and satisfies physical memory needs on demand via soft page faults\&. Note that replacing the default chunk allocation function makes the arena\*(Aqs
-"arena\&.\&.dss"
+arena\&.\&.dss
 setting irrelevant\&.
 .HP \w'typedef\ bool\ (chunk_dalloc_t)('u
 .BI "typedef bool (chunk_dalloc_t)(void\ *" "chunk" ", size_t\ " "size" ", bool\ " "committed" ", unsigned\ " "arena_ind" ");"
@@ -1375,436 +1411,436 @@ into one contiguous chunk, operating on
 \fIarena_ind\fR, returning false upon success\&. If the function returns true, this indicates that the chunks remain distinct mappings and therefore should continue to be operated on independently\&.
 .RE
 .PP
-"arenas\&.narenas" (\fBunsigned\fR) r\-
+arenas\&.narenas (\fBunsigned\fR) r\-
 .RS 4
 Current limit on number of arenas\&.
 .RE
 .PP
-"arenas\&.initialized" (\fBbool *\fR) r\-
+arenas\&.initialized (\fBbool *\fR) r\-
 .RS 4
 An array of
-"arenas\&.narenas"
+arenas\&.narenas
 booleans\&. Each boolean indicates whether the corresponding arena is initialized\&.
 .RE
 .PP
-"arenas\&.lg_dirty_mult" (\fBssize_t\fR) rw
+arenas\&.lg_dirty_mult (\fBssize_t\fR) rw
 .RS 4
 Current default per\-arena minimum ratio (log base 2) of active to dirty pages, used to initialize
-"arena\&.\&.lg_dirty_mult"
+arena\&.\&.lg_dirty_mult
 during arena creation\&. See
-"opt\&.lg_dirty_mult"
+opt\&.lg_dirty_mult
 for additional information\&.
 .RE
 .PP
-"arenas\&.decay_time" (\fBssize_t\fR) rw
+arenas\&.decay_time (\fBssize_t\fR) rw
 .RS 4
 Current default per\-arena approximate time in seconds from the creation of a set of unused dirty pages until an equivalent set of unused dirty pages is purged and/or reused, used to initialize
-"arena\&.\&.decay_time"
+arena\&.\&.decay_time
 during arena creation\&. See
-"opt\&.decay_time"
+opt\&.decay_time
 for additional information\&.
 .RE
 .PP
-"arenas\&.quantum" (\fBsize_t\fR) r\-
+arenas\&.quantum (\fBsize_t\fR) r\-
 .RS 4
 Quantum size\&.
 .RE
 .PP
-"arenas\&.page" (\fBsize_t\fR) r\-
+arenas\&.page (\fBsize_t\fR) r\-
 .RS 4
 Page size\&.
 .RE
 .PP
-"arenas\&.tcache_max" (\fBsize_t\fR) r\- [\fB\-\-enable\-tcache\fR]
+arenas\&.tcache_max (\fBsize_t\fR) r\- [\fB\-\-enable\-tcache\fR]
 .RS 4
 Maximum thread\-cached size class\&.
 .RE
 .PP
-"arenas\&.nbins" (\fBunsigned\fR) r\-
+arenas\&.nbins (\fBunsigned\fR) r\-
 .RS 4
 Number of bin size classes\&.
 .RE
 .PP
-"arenas\&.nhbins" (\fBunsigned\fR) r\- [\fB\-\-enable\-tcache\fR]
+arenas\&.nhbins (\fBunsigned\fR) r\- [\fB\-\-enable\-tcache\fR]
 .RS 4
 Total number of thread cache bin size classes\&.
 .RE
 .PP
-"arenas\&.bin\&.\&.size" (\fBsize_t\fR) r\-
+arenas\&.bin\&.\&.size (\fBsize_t\fR) r\-
 .RS 4
 Maximum size supported by size class\&.
 .RE
 .PP
-"arenas\&.bin\&.\&.nregs" (\fBuint32_t\fR) r\-
+arenas\&.bin\&.\&.nregs (\fBuint32_t\fR) r\-
 .RS 4
 Number of regions per page run\&.
 .RE
 .PP
-"arenas\&.bin\&.\&.run_size" (\fBsize_t\fR) r\-
+arenas\&.bin\&.\&.run_size (\fBsize_t\fR) r\-
 .RS 4
 Number of bytes per page run\&.
 .RE
 .PP
-"arenas\&.nlruns" (\fBunsigned\fR) r\-
+arenas\&.nlruns (\fBunsigned\fR) r\-
 .RS 4
 Total number of large size classes\&.
 .RE
 .PP
-"arenas\&.lrun\&.\&.size" (\fBsize_t\fR) r\-
+arenas\&.lrun\&.\&.size (\fBsize_t\fR) r\-
 .RS 4
 Maximum size supported by this large size class\&.
 .RE
 .PP
-"arenas\&.nhchunks" (\fBunsigned\fR) r\-
+arenas\&.nhchunks (\fBunsigned\fR) r\-
 .RS 4
 Total number of huge size classes\&.
 .RE
 .PP
-"arenas\&.hchunk\&.\&.size" (\fBsize_t\fR) r\-
+arenas\&.hchunk\&.\&.size (\fBsize_t\fR) r\-
 .RS 4
 Maximum size supported by this huge size class\&.
 .RE
 .PP
-"arenas\&.extend" (\fBunsigned\fR) r\-
+arenas\&.extend (\fBunsigned\fR) r\-
 .RS 4
 Extend the array of arenas by appending a new arena, and returning the new arena index\&.
 .RE
 .PP
-"prof\&.thread_active_init" (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
+prof\&.thread_active_init (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
 .RS 4
 Control the initial setting for
-"thread\&.prof\&.active"
+thread\&.prof\&.active
 in newly created threads\&. See the
-"opt\&.prof_thread_active_init"
+opt\&.prof_thread_active_init
 option for additional information\&.
 .RE
 .PP
-"prof\&.active" (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
+prof\&.active (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
 .RS 4
 Control whether sampling is currently active\&. See the
-"opt\&.prof_active"
+opt\&.prof_active
 option for additional information, as well as the interrelated
-"thread\&.prof\&.active"
+thread\&.prof\&.active
 mallctl\&.
 .RE
 .PP
-"prof\&.dump" (\fBconst char *\fR) \-w [\fB\-\-enable\-prof\fR]
+prof\&.dump (\fBconst char *\fR) \-w [\fB\-\-enable\-prof\fR]
 .RS 4
 Dump a memory profile to the specified file, or if NULL is specified, to a file according to the pattern
 \&.\&.\&.m\&.heap, where
 
 is controlled by the
-"opt\&.prof_prefix"
+opt\&.prof_prefix
 option\&.
 .RE
 .PP
-"prof\&.gdump" (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
+prof\&.gdump (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
 .RS 4
 When enabled, trigger a memory profile dump every time the total virtual memory exceeds the previous maximum\&. Profiles are dumped to files named according to the pattern
 \&.\&.\&.u\&.heap, where
 
 is controlled by the
-"opt\&.prof_prefix"
+opt\&.prof_prefix
 option\&.
 .RE
 .PP
-"prof\&.reset" (\fBsize_t\fR) \-w [\fB\-\-enable\-prof\fR]
+prof\&.reset (\fBsize_t\fR) \-w [\fB\-\-enable\-prof\fR]
 .RS 4
 Reset all memory profile statistics, and optionally update the sample rate (see
-"opt\&.lg_prof_sample"
+opt\&.lg_prof_sample
 and
-"prof\&.lg_sample")\&.
+prof\&.lg_sample)\&.
 .RE
 .PP
-"prof\&.lg_sample" (\fBsize_t\fR) r\- [\fB\-\-enable\-prof\fR]
+prof\&.lg_sample (\fBsize_t\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Get the current sample rate (see
-"opt\&.lg_prof_sample")\&.
+opt\&.lg_prof_sample)\&.
 .RE
 .PP
-"prof\&.interval" (\fBuint64_t\fR) r\- [\fB\-\-enable\-prof\fR]
+prof\&.interval (\fBuint64_t\fR) r\- [\fB\-\-enable\-prof\fR]
 .RS 4
 Average number of bytes allocated between interval\-based profile dumps\&. See the
-"opt\&.lg_prof_interval"
+opt\&.lg_prof_interval
 option for additional information\&.
 .RE
 .PP
-"stats\&.cactive" (\fBsize_t *\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.cactive (\fBsize_t *\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Pointer to a counter that contains an approximate count of the current number of bytes in active pages\&. The estimate may be high, but never low, because each arena rounds up when computing its contribution to the counter\&. Note that the
-"epoch"
+epoch
 mallctl has no bearing on this counter\&. Furthermore, counter consistency is maintained via atomic operations, so it is necessary to use an atomic operation in order to guarantee a consistent read when dereferencing the pointer\&.
 .RE
 .PP
-"stats\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.allocated (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Total number of bytes allocated by the application\&.
 .RE
 .PP
-"stats\&.active" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.active (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Total number of bytes in active pages allocated by the application\&. This is a multiple of the page size, and greater than or equal to
-"stats\&.allocated"\&. This does not include
-"stats\&.arenas\&.\&.pdirty", nor pages entirely devoted to allocator metadata\&.
+stats\&.allocated\&. This does not include
+stats\&.arenas\&.\&.pdirty, nor pages entirely devoted to allocator metadata\&.
 .RE
 .PP
-"stats\&.metadata" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.metadata (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Total number of bytes dedicated to metadata, which comprise base allocations used for bootstrap\-sensitive internal allocator data structures, arena chunk headers (see
-"stats\&.arenas\&.\&.metadata\&.mapped"), and internal allocations (see
-"stats\&.arenas\&.\&.metadata\&.allocated")\&.
+stats\&.arenas\&.\&.metadata\&.mapped), and internal allocations (see
+stats\&.arenas\&.\&.metadata\&.allocated)\&.
 .RE
 .PP
-"stats\&.resident" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.resident (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Maximum number of bytes in physically resident data pages mapped by the allocator, comprising all pages dedicated to allocator metadata, pages backing active allocations, and unused dirty pages\&. This is a maximum rather than precise because pages may not actually be physically resident if they correspond to demand\-zeroed virtual memory that has not yet been touched\&. This is a multiple of the page size, and is larger than
-"stats\&.active"\&.
+stats\&.active\&.
 .RE
 .PP
-"stats\&.mapped" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.mapped (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Total number of bytes in active chunks mapped by the allocator\&. This is a multiple of the chunk size, and is larger than
-"stats\&.active"\&. This does not include inactive chunks, even those that contain unused dirty pages, which means that there is no strict ordering between this and
-"stats\&.resident"\&.
+stats\&.active\&. This does not include inactive chunks, even those that contain unused dirty pages, which means that there is no strict ordering between this and
+stats\&.resident\&.
 .RE
 .PP
-"stats\&.retained" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.retained (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Total number of bytes in virtual memory mappings that were retained rather than being returned to the operating system via e\&.g\&.
 \fBmunmap\fR(2)\&. Retained virtual memory is typically untouched, decommitted, or purged, so it has no strongly associated physical memory (see
 chunk hooks
 for details)\&. Retained memory is excluded from mapped memory statistics, e\&.g\&.
-"stats\&.mapped"\&.
+stats\&.mapped\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.dss" (\fBconst char *\fR) r\-
+stats\&.arenas\&.\&.dss (\fBconst char *\fR) r\-
 .RS 4
 dss (\fBsbrk\fR(2)) allocation precedence as related to
 \fBmmap\fR(2)
 allocation\&. See
-"opt\&.dss"
+opt\&.dss
 for details\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.lg_dirty_mult" (\fBssize_t\fR) r\-
+stats\&.arenas\&.\&.lg_dirty_mult (\fBssize_t\fR) r\-
 .RS 4
 Minimum ratio (log base 2) of active to dirty pages\&. See
-"opt\&.lg_dirty_mult"
+opt\&.lg_dirty_mult
 for details\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.decay_time" (\fBssize_t\fR) r\-
+stats\&.arenas\&.\&.decay_time (\fBssize_t\fR) r\-
 .RS 4
 Approximate time in seconds from the creation of a set of unused dirty pages until an equivalent set of unused dirty pages is purged and/or reused\&. See
-"opt\&.decay_time"
+opt\&.decay_time
 for details\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.nthreads" (\fBunsigned\fR) r\-
+stats\&.arenas\&.\&.nthreads (\fBunsigned\fR) r\-
 .RS 4
 Number of threads currently assigned to arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.pactive" (\fBsize_t\fR) r\-
+stats\&.arenas\&.\&.pactive (\fBsize_t\fR) r\-
 .RS 4
 Number of pages in active runs\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.pdirty" (\fBsize_t\fR) r\-
+stats\&.arenas\&.\&.pdirty (\fBsize_t\fR) r\-
 .RS 4
 Number of pages within unused runs that are potentially dirty, and for which
-\fBmadvise\fR\fB\fI\&.\&.\&.\fR\fR\fB \fR\fB\fI\fBMADV_DONTNEED\fR\fR\fR
+madvise\fI\&.\&.\&.\fR \fI\fBMADV_DONTNEED\fR\fR
 or similar has not been called\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.mapped" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.mapped (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of mapped bytes\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.retained" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.retained (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of retained bytes\&. See
-"stats\&.retained"
+stats\&.retained
 for details\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.metadata\&.mapped" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.metadata\&.mapped (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of mapped bytes in arena chunk headers, which track the states of the non\-metadata pages\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.metadata\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.metadata\&.allocated (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of bytes dedicated to internal allocations\&. Internal allocations differ from application\-originated allocations in that they are for internal use, and that they are omitted from heap profiles\&. This statistic is reported separately from
-"stats\&.metadata"
+stats\&.metadata
 and
-"stats\&.arenas\&.\&.metadata\&.mapped"
+stats\&.arenas\&.\&.metadata\&.mapped
 because it overlaps with e\&.g\&. the
-"stats\&.allocated"
+stats\&.allocated
 and
-"stats\&.active"
+stats\&.active
 statistics, whereas the other metadata statistics do not\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.npurge" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.npurge (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of dirty page purge sweeps performed\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.nmadvise" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.nmadvise (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of
-\fBmadvise\fR\fB\fI\&.\&.\&.\fR\fR\fB \fR\fB\fI\fBMADV_DONTNEED\fR\fR\fR
+madvise\fI\&.\&.\&.\fR \fI\fBMADV_DONTNEED\fR\fR
 or similar calls made to purge dirty pages\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.purged" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.purged (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of pages purged\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.small\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.small\&.allocated (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of bytes currently allocated by small objects\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.small\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.small\&.nmalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocation requests served by small bins\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.small\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.small\&.ndalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of small objects returned to bins\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.small\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.small\&.nrequests (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of small allocation requests\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.large\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.large\&.allocated (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of bytes currently allocated by large objects\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.large\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.large\&.nmalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of large allocation requests served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.large\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.large\&.ndalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of large deallocation requests served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.large\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.large\&.nrequests (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of large allocation requests\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.huge\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.huge\&.allocated (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Number of bytes currently allocated by huge objects\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.huge\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.huge\&.nmalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of huge allocation requests served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.huge\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.huge\&.ndalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of huge deallocation requests served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.huge\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.huge\&.nrequests (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of huge allocation requests\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.nmalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocations served by bin\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.ndalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocations returned to bin\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.nrequests (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocation requests\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.curregs" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.curregs (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Current number of regions for this size class\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.nfills" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR \fB\-\-enable\-tcache\fR]
+stats\&.arenas\&.\&.bins\&.\&.nfills (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR \fB\-\-enable\-tcache\fR]
 .RS 4
 Cumulative number of tcache fills\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.nflushes" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR \fB\-\-enable\-tcache\fR]
+stats\&.arenas\&.\&.bins\&.\&.nflushes (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR \fB\-\-enable\-tcache\fR]
 .RS 4
 Cumulative number of tcache flushes\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.nruns" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.nruns (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of runs created\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.nreruns" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.nreruns (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of times the current run from which to allocate changed\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.bins\&.\&.curruns" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.bins\&.\&.curruns (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Current number of runs\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.lruns\&.\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.lruns\&.\&.nmalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocation requests for this size class served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.lruns\&.\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.lruns\&.\&.ndalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of deallocation requests for this size class served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.lruns\&.\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.lruns\&.\&.nrequests (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocation requests for this size class\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.lruns\&.\&.curruns" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.lruns\&.\&.curruns (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Current number of runs for this size class\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.hchunks\&.\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.hchunks\&.\&.nmalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocation requests for this size class served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.hchunks\&.\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.hchunks\&.\&.ndalloc (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of deallocation requests for this size class served directly by the arena\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.hchunks\&.\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.hchunks\&.\&.nrequests (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Cumulative number of allocation requests for this size class\&.
 .RE
 .PP
-"stats\&.arenas\&.\&.hchunks\&.\&.curhchunks" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
+stats\&.arenas\&.\&.hchunks\&.\&.curhchunks (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
 .RS 4
 Current number of huge allocations for this size class\&.
 .RE
@@ -1813,7 +1849,7 @@ Current number of huge allocations for this size class\&.
 Although the heap profiling functionality was originally designed to be compatible with the
 \fBpprof\fR
 command that is developed as part of the
-\m[blue]\fBgperftools package\fR\m[]\&\s-2\u[3]\d\s+2, the addition of per thread heap profiling functionality required a different heap profile format\&. The
+\m[blue]\fBgperftools package\fR\m[]\&\s-2\u[4]\d\s+2, the addition of per thread heap profiling functionality required a different heap profile format\&. The
 \fBjeprof\fR
 command is derived from
 \fBpprof\fR, with enhancements to support the heap profile format described here\&.
@@ -1881,14 +1917,16 @@ and
 \fB\-\-enable\-fill\fR
 options, and recompile the program with suitable options and symbols for debugger support\&. When so configured, jemalloc incorporates a wide variety of run\-time assertions that catch application errors such as double\-free, write\-after\-free, etc\&.
 .PP
-Programs often accidentally depend on \(lquninitialized\(rq memory actually being filled with zero bytes\&. Junk filling (see the
-"opt\&.junk"
+Programs often accidentally depend on
+\(lquninitialized\(rq
+memory actually being filled with zero bytes\&. Junk filling (see the
+opt\&.junk
 option) tends to expose such bugs in the form of obviously incorrect results and/or coredumps\&. Conversely, zero filling (see the
-"opt\&.zero"
+opt\&.zero
 option) eliminates the symptoms of such bugs\&. Between these two options, it is usually possible to quickly detect, diagnose, and eliminate such bugs\&.
 .PP
 This implementation does not provide much detail about the problems it detects, because the performance impact for storing such information would be prohibitive\&. However, jemalloc does integrate with the most excellent
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2
+\m[blue]\fBValgrind\fR\m[]\&\s-2\u[3]\d\s+2
 tool if the
 \fB\-\-enable\-valgrind\fR
 configuration option is enabled\&.
@@ -1896,7 +1934,7 @@ configuration option is enabled\&.
 .PP
 If any of the memory allocation/deallocation functions detect an error or warning condition, a message will be printed to file descriptor
 \fBSTDERR_FILENO\fR\&. Errors will result in the process dumping core\&. If the
-"opt\&.abort"
+opt\&.abort
 option is set, most warnings are treated as errors\&.
 .PP
 The
@@ -1904,22 +1942,23 @@ The
 variable allows the programmer to override the function which emits the text strings forming the errors and warnings if for some reason the
 \fBSTDERR_FILENO\fR
 file descriptor is not suitable for this\&.
-\fBmalloc_message\fR\fB\fR
+malloc_message()
 takes the
 \fIcbopaque\fR
 pointer argument that is
 \fBNULL\fR
 unless overridden by the arguments in a call to
-\fBmalloc_stats_print\fR\fB\fR, followed by a string pointer\&. Please note that doing anything which tries to allocate memory in this function is likely to result in a crash or deadlock\&.
+malloc_stats_print(), followed by a string pointer\&. Please note that doing anything which tries to allocate memory in this function is likely to result in a crash or deadlock\&.
 .PP
-All messages are prefixed by \(lq:\(rq\&.
+All messages are prefixed by
+\(lq: \(rq\&.
 .SH "RETURN VALUES"
 .SS "Standard API"
 .PP
 The
-\fBmalloc\fR\fB\fR
+malloc()
 and
-\fBcalloc\fR\fB\fR
+calloc()
 functions return a pointer to the allocated memory if successful; otherwise a
 \fBNULL\fR
 pointer is returned and
@@ -1928,9 +1967,9 @@ is set to
 ENOMEM\&.
 .PP
 The
-\fBposix_memalign\fR\fB\fR
+posix_memalign()
 function returns the value 0 if successful; otherwise it returns an error value\&. The
-\fBposix_memalign\fR\fB\fR
+posix_memalign()
 function will fail if:
 .PP
 EINVAL
@@ -1947,13 +1986,13 @@ Memory allocation error\&.
 .RE
 .PP
 The
-\fBaligned_alloc\fR\fB\fR
+aligned_alloc()
 function returns a pointer to the allocated memory if successful; otherwise a
 \fBNULL\fR
 pointer is returned and
 \fIerrno\fR
 is set\&. The
-\fBaligned_alloc\fR\fB\fR
+aligned_alloc()
 function will fail if:
 .PP
 EINVAL
@@ -1969,7 +2008,7 @@ Memory allocation error\&.
 .RE
 .PP
 The
-\fBrealloc\fR\fB\fR
+realloc()
 function returns a pointer, possibly identical to
 \fIptr\fR, to the allocated memory if successful; otherwise a
 \fBNULL\fR
@@ -1978,44 +2017,44 @@ pointer is returned, and
 is set to
 ENOMEM
 if the error was the result of an allocation failure\&. The
-\fBrealloc\fR\fB\fR
+realloc()
 function always leaves the original buffer intact when an error occurs\&.
 .PP
 The
-\fBfree\fR\fB\fR
+free()
 function returns no value\&.
 .SS "Non\-standard API"
 .PP
 The
-\fBmallocx\fR\fB\fR
+mallocx()
 and
-\fBrallocx\fR\fB\fR
+rallocx()
 functions return a pointer to the allocated memory if successful; otherwise a
 \fBNULL\fR
 pointer is returned to indicate insufficient contiguous memory was available to service the allocation request\&.
 .PP
 The
-\fBxallocx\fR\fB\fR
+xallocx()
 function returns the real size of the resulting resized allocation pointed to by
 \fIptr\fR, which is a value less than
 \fIsize\fR
 if the allocation could not be adequately grown in place\&.
 .PP
 The
-\fBsallocx\fR\fB\fR
+sallocx()
 function returns the real size of the allocation pointed to by
 \fIptr\fR\&.
 .PP
 The
-\fBnallocx\fR\fB\fR
+nallocx()
 returns the real size that would result from a successful equivalent
-\fBmallocx\fR\fB\fR
+mallocx()
 function call, or zero if insufficient memory is available to perform the size computation\&.
 .PP
 The
-\fBmallctl\fR\fB\fR,
-\fBmallctlnametomib\fR\fB\fR, and
-\fBmallctlbymib\fR\fB\fR
+mallctl(),
+mallctlnametomib(), and
+mallctlbymib()
 functions return 0 on success; otherwise they return an error value\&. The functions will fail if:
 .PP
 EINVAL
@@ -2050,12 +2089,12 @@ A memory allocation failure occurred\&.
 EFAULT
 .RS 4
 An interface with side effects failed in some way not directly related to
-\fBmallctl*\fR\fB\fR
+mallctl*()
 read/write processing\&.
 .RE
 .PP
 The
-\fBmalloc_usable_size\fR\fB\fR
+malloc_usable_size()
 function returns the usable size of the allocation pointed to by
 \fIptr\fR\&.
 .SH "ENVIRONMENT"
@@ -2105,31 +2144,31 @@ malloc_conf = "lg_chunk:24";
 .SH "STANDARDS"
 .PP
 The
-\fBmalloc\fR\fB\fR,
-\fBcalloc\fR\fB\fR,
-\fBrealloc\fR\fB\fR, and
-\fBfree\fR\fB\fR
+malloc(),
+calloc(),
+realloc(), and
+free()
 functions conform to ISO/IEC 9899:1990 (\(lqISO C90\(rq)\&.
 .PP
 The
-\fBposix_memalign\fR\fB\fR
+posix_memalign()
 function conforms to IEEE Std 1003\&.1\-2001 (\(lqPOSIX\&.1\(rq)\&.
 .SH "HISTORY"
 .PP
 The
-\fBmalloc_usable_size\fR\fB\fR
+malloc_usable_size()
 and
-\fBposix_memalign\fR\fB\fR
+posix_memalign()
 functions first appeared in FreeBSD 7\&.0\&.
 .PP
 The
-\fBaligned_alloc\fR\fB\fR,
-\fBmalloc_stats_print\fR\fB\fR, and
-\fBmallctl*\fR\fB\fR
+aligned_alloc(),
+malloc_stats_print(), and
+mallctl*()
 functions first appeared in FreeBSD 10\&.0\&.
 .PP
 The
-\fB*allocx\fR\fB\fR
+*allocx()
 functions first appeared in FreeBSD 11\&.0\&.
 .SH "AUTHOR"
 .PP
@@ -2140,14 +2179,19 @@ functions first appeared in FreeBSD 11\&.0\&.
 .IP " 1." 4
 jemalloc website
 .RS 4
-\%http://www.canonware.com/jemalloc/
+\%http://jemalloc.net/
 .RE
 .IP " 2." 4
+JSON format
+.RS 4
+\%http://www.json.org/
+.RE
+.IP " 3." 4
 Valgrind
 .RS 4
 \%http://valgrind.org/
 .RE
-.IP " 3." 4
+.IP " 4." 4
 gperftools package
 .RS 4
 \%http://code.google.com/p/gperftools/
diff --git a/contrib/jemalloc/include/jemalloc/internal/arena.h b/contrib/jemalloc/include/jemalloc/internal/arena.h
index da6b6d2b6069..a3ba55d88552 100644
--- a/contrib/jemalloc/include/jemalloc/internal/arena.h
+++ b/contrib/jemalloc/include/jemalloc/internal/arena.h
@@ -42,6 +42,7 @@ typedef struct arena_chunk_map_bits_s arena_chunk_map_bits_t;
 typedef struct arena_chunk_map_misc_s arena_chunk_map_misc_t;
 typedef struct arena_chunk_s arena_chunk_t;
 typedef struct arena_bin_info_s arena_bin_info_t;
+typedef struct arena_decay_s arena_decay_t;
 typedef struct arena_bin_s arena_bin_t;
 typedef struct arena_s arena_t;
 typedef struct arena_tdata_s arena_tdata_t;
@@ -257,6 +258,49 @@ struct arena_bin_info_s {
 	uint32_t		reg0_offset;
 };
 
+struct arena_decay_s {
+	/*
+	 * Approximate time in seconds from the creation of a set of unused
+	 * dirty pages until an equivalent set of unused dirty pages is purged
+	 * and/or reused.
+	 */
+	ssize_t			time;
+	/* time / SMOOTHSTEP_NSTEPS. */
+	nstime_t		interval;
+	/*
+	 * Time at which the current decay interval logically started.  We do
+	 * not actually advance to a new epoch until sometime after it starts
+	 * because of scheduling and computation delays, and it is even possible
+	 * to completely skip epochs.  In all cases, during epoch advancement we
+	 * merge all relevant activity into the most recently recorded epoch.
+	 */
+	nstime_t		epoch;
+	/* Deadline randomness generator. */
+	uint64_t		jitter_state;
+	/*
+	 * Deadline for current epoch.  This is the sum of interval and per
+	 * epoch jitter which is a uniform random variable in [0..interval).
+	 * Epochs always advance by precise multiples of interval, but we
+	 * randomize the deadline to reduce the likelihood of arenas purging in
+	 * lockstep.
+	 */
+	nstime_t		deadline;
+	/*
+	 * Number of dirty pages at beginning of current epoch.  During epoch
+	 * advancement we use the delta between arena->decay.ndirty and
+	 * arena->ndirty to determine how many dirty pages, if any, were
+	 * generated.
+	 */
+	size_t			ndirty;
+	/*
+	 * Trailing log of how many unused dirty pages were generated during
+	 * each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last
+	 * element is the most recent epoch.  Corresponding epoch times are
+	 * relative to epoch.
+	 */
+	size_t			backlog[SMOOTHSTEP_NSTEPS];
+};
+
 struct arena_bin_s {
 	/*
 	 * All operations on runcur, runs, and stats require that lock be
@@ -326,7 +370,7 @@ struct arena_s {
 	 * PRNG state for cache index randomization of large allocation base
 	 * pointers.
 	 */
-	uint64_t		offset_state;
+	size_t			offset_state;
 
 	dss_prec_t		dss_prec;
 
@@ -394,52 +438,8 @@ struct arena_s {
 	arena_runs_dirty_link_t	runs_dirty;
 	extent_node_t		chunks_cache;
 
-	/*
-	 * Approximate time in seconds from the creation of a set of unused
-	 * dirty pages until an equivalent set of unused dirty pages is purged
-	 * and/or reused.
-	 */
-	ssize_t			decay_time;
-	/* decay_time / SMOOTHSTEP_NSTEPS. */
-	nstime_t		decay_interval;
-	/*
-	 * Time at which the current decay interval logically started.  We do
-	 * not actually advance to a new epoch until sometime after it starts
-	 * because of scheduling and computation delays, and it is even possible
-	 * to completely skip epochs.  In all cases, during epoch advancement we
-	 * merge all relevant activity into the most recently recorded epoch.
-	 */
-	nstime_t		decay_epoch;
-	/* decay_deadline randomness generator. */
-	uint64_t		decay_jitter_state;
-	/*
-	 * Deadline for current epoch.  This is the sum of decay_interval and
-	 * per epoch jitter which is a uniform random variable in
-	 * [0..decay_interval).  Epochs always advance by precise multiples of
-	 * decay_interval, but we randomize the deadline to reduce the
-	 * likelihood of arenas purging in lockstep.
-	 */
-	nstime_t		decay_deadline;
-	/*
-	 * Number of dirty pages at beginning of current epoch.  During epoch
-	 * advancement we use the delta between decay_ndirty and ndirty to
-	 * determine how many dirty pages, if any, were generated, and record
-	 * the result in decay_backlog.
-	 */
-	size_t			decay_ndirty;
-	/*
-	 * Memoized result of arena_decay_backlog_npages_limit() corresponding
-	 * to the current contents of decay_backlog, i.e. the limit on how many
-	 * pages are allowed to exist for the decay epochs.
-	 */
-	size_t			decay_backlog_npages_limit;
-	/*
-	 * Trailing log of how many unused dirty pages were generated during
-	 * each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last
-	 * element is the most recent epoch.  Corresponding epoch times are
-	 * relative to decay_epoch.
-	 */
-	size_t			decay_backlog[SMOOTHSTEP_NSTEPS];
+	/* Decay-based purging state. */
+	arena_decay_t		decay;
 
 	/* Extant huge allocations. */
 	ql_head(extent_node_t)	huge;
@@ -470,10 +470,12 @@ struct arena_s {
 	arena_bin_t		bins[NBINS];
 
 	/*
-	 * Quantized address-ordered heaps of this arena's available runs.  The
-	 * heaps are used for first-best-fit run allocation.
+	 * Size-segregated address-ordered heaps of this arena's available runs,
+	 * used for first-best-fit run allocation.  Runs are quantized, i.e.
+	 * they reside in the last heap which corresponds to a size class less
+	 * than or equal to the run size.
 	 */
-	arena_run_heap_t	runs_avail[1]; /* Dynamically sized. */
+	arena_run_heap_t	runs_avail[NPSIZES];
 };
 
 /* Used in conjunction with tsd for fast arena-related context lookup. */
@@ -505,7 +507,6 @@ extern size_t		map_bias; /* Number of arena chunk header pages. */
 extern size_t		map_misc_offset;
 extern size_t		arena_maxrun; /* Max run size for arenas. */
 extern size_t		large_maxclass; /* Max large size class. */
-extern size_t		run_quantize_max; /* Max run_quantize_*() input. */
 extern unsigned		nlclasses; /* Number of large size classes. */
 extern unsigned		nhclasses; /* Number of huge size classes. */
 
@@ -601,7 +602,7 @@ unsigned	arena_nthreads_get(arena_t *arena, bool internal);
 void	arena_nthreads_inc(arena_t *arena, bool internal);
 void	arena_nthreads_dec(arena_t *arena, bool internal);
 arena_t	*arena_new(tsdn_t *tsdn, unsigned ind);
-bool	arena_boot(void);
+void	arena_boot(void);
 void	arena_prefork0(tsdn_t *tsdn, arena_t *arena);
 void	arena_prefork1(tsdn_t *tsdn, arena_t *arena);
 void	arena_prefork2(tsdn_t *tsdn, arena_t *arena);
diff --git a/contrib/jemalloc/include/jemalloc/internal/chunk.h b/contrib/jemalloc/include/jemalloc/internal/chunk.h
index c9fd4ecbd059..38c9a012da11 100644
--- a/contrib/jemalloc/include/jemalloc/internal/chunk.h
+++ b/contrib/jemalloc/include/jemalloc/internal/chunk.h
@@ -58,7 +58,7 @@ void	chunk_deregister(const void *chunk, const extent_node_t *node);
 void	*chunk_alloc_base(size_t size);
 void	*chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
-    bool *zero, bool dalloc_node);
+    bool *zero, bool *commit, bool dalloc_node);
 void	*chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
     bool *zero, bool *commit);
@@ -71,9 +71,6 @@ bool	chunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t offset,
     size_t length);
 bool	chunk_boot(void);
-void	chunk_prefork(tsdn_t *tsdn);
-void	chunk_postfork_parent(tsdn_t *tsdn);
-void	chunk_postfork_child(tsdn_t *tsdn);
 
 #endif /* JEMALLOC_H_EXTERNS */
 /******************************************************************************/
diff --git a/contrib/jemalloc/include/jemalloc/internal/chunk_dss.h b/contrib/jemalloc/include/jemalloc/internal/chunk_dss.h
index 724fa579a2cf..da8511ba06b0 100644
--- a/contrib/jemalloc/include/jemalloc/internal/chunk_dss.h
+++ b/contrib/jemalloc/include/jemalloc/internal/chunk_dss.h
@@ -21,15 +21,13 @@ extern const char *dss_prec_names[];
 /******************************************************************************/
 #ifdef JEMALLOC_H_EXTERNS
 
-dss_prec_t	chunk_dss_prec_get(tsdn_t *tsdn);
-bool	chunk_dss_prec_set(tsdn_t *tsdn, dss_prec_t dss_prec);
+dss_prec_t	chunk_dss_prec_get(void);
+bool	chunk_dss_prec_set(dss_prec_t dss_prec);
 void	*chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr,
     size_t size, size_t alignment, bool *zero, bool *commit);
-bool	chunk_in_dss(tsdn_t *tsdn, void *chunk);
-bool	chunk_dss_boot(void);
-void	chunk_dss_prefork(tsdn_t *tsdn);
-void	chunk_dss_postfork_parent(tsdn_t *tsdn);
-void	chunk_dss_postfork_child(tsdn_t *tsdn);
+bool	chunk_in_dss(void *chunk);
+bool	chunk_dss_mergeable(void *chunk_a, void *chunk_b);
+void	chunk_dss_boot(void);
 
 #endif /* JEMALLOC_H_EXTERNS */
 /******************************************************************************/
diff --git a/contrib/jemalloc/include/jemalloc/internal/ckh.h b/contrib/jemalloc/include/jemalloc/internal/ckh.h
index 46e151cdd7f9..f75ad90b73cc 100644
--- a/contrib/jemalloc/include/jemalloc/internal/ckh.h
+++ b/contrib/jemalloc/include/jemalloc/internal/ckh.h
@@ -64,13 +64,13 @@ struct ckh_s {
 /******************************************************************************/
 #ifdef JEMALLOC_H_EXTERNS
 
-bool	ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
+bool	ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
     ckh_keycomp_t *keycomp);
-void	ckh_delete(tsdn_t *tsdn, ckh_t *ckh);
+void	ckh_delete(tsd_t *tsd, ckh_t *ckh);
 size_t	ckh_count(ckh_t *ckh);
 bool	ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);
-bool	ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data);
-bool	ckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,
+bool	ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data);
+bool	ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key,
     void **data);
 bool	ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data);
 void	ckh_string_hash(const void *key, size_t r_hash[2]);
diff --git a/contrib/jemalloc/include/jemalloc/internal/huge.h b/contrib/jemalloc/include/jemalloc/internal/huge.h
index b5fa9e63691c..22184d9bbd45 100644
--- a/contrib/jemalloc/include/jemalloc/internal/huge.h
+++ b/contrib/jemalloc/include/jemalloc/internal/huge.h
@@ -17,7 +17,7 @@ bool	huge_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize,
 void	*huge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,
     size_t usize, size_t alignment, bool zero, tcache_t *tcache);
 #ifdef JEMALLOC_JET
-typedef void (huge_dalloc_junk_t)(tsdn_t *, void *, size_t);
+typedef void (huge_dalloc_junk_t)(void *, size_t);
 extern huge_dalloc_junk_t *huge_dalloc_junk;
 #endif
 void	huge_dalloc(tsdn_t *tsdn, void *ptr);
diff --git a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h
index 49f14a51ee13..15483e271dd6 100644
--- a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h
+++ b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h
@@ -159,7 +159,9 @@ static const bool config_cache_oblivious =
 #endif
 
 #include "jemalloc/internal/ph.h"
+#ifndef __PGI
 #define	RB_COMPACT
+#endif
 #include "jemalloc/internal/rb.h"
 #include "jemalloc/internal/qr.h"
 #include "jemalloc/internal/ql.h"
@@ -182,6 +184,9 @@ static const bool config_cache_oblivious =
 
 #include "jemalloc/internal/jemalloc_internal_macros.h"
 
+/* Page size index type. */
+typedef unsigned pszind_t;
+
 /* Size class index type. */
 typedef unsigned szind_t;
 
@@ -231,7 +236,7 @@ typedef unsigned szind_t;
 #  ifdef __alpha__
 #    define LG_QUANTUM		4
 #  endif
-#  if (defined(__sparc64__) || defined(__sparcv9))
+#  if (defined(__sparc64__) || defined(__sparcv9) || defined(__sparc_v9__))
 #    define LG_QUANTUM		4
 #  endif
 #  if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
@@ -361,6 +366,7 @@ typedef unsigned szind_t;
 #include "jemalloc/internal/valgrind.h"
 #include "jemalloc/internal/util.h"
 #include "jemalloc/internal/atomic.h"
+#include "jemalloc/internal/spin.h"
 #include "jemalloc/internal/prng.h"
 #include "jemalloc/internal/ticker.h"
 #include "jemalloc/internal/ckh.h"
@@ -393,6 +399,7 @@ typedef unsigned szind_t;
 #include "jemalloc/internal/valgrind.h"
 #include "jemalloc/internal/util.h"
 #include "jemalloc/internal/atomic.h"
+#include "jemalloc/internal/spin.h"
 #include "jemalloc/internal/prng.h"
 #include "jemalloc/internal/ticker.h"
 #include "jemalloc/internal/ckh.h"
@@ -452,11 +459,16 @@ extern unsigned	narenas_auto;
  */
 extern arena_t	**arenas;
 
+/*
+ * pind2sz_tab encodes the same information as could be computed by
+ * pind2sz_compute().
+ */
+extern size_t const	pind2sz_tab[NPSIZES];
 /*
  * index2size_tab encodes the same information as could be computed (at
  * unacceptable cost in some code paths) by index2size_compute().
  */
-extern size_t const	index2size_tab[NSIZES+1];
+extern size_t const	index2size_tab[NSIZES];
 /*
  * size2index_tab is a compact lookup table that rounds request sizes up to
  * size classes.  In order to reduce cache footprint, the table is compressed,
@@ -464,6 +476,7 @@ extern size_t const	index2size_tab[NSIZES+1];
  */
 extern uint8_t const	size2index_tab[];
 
+arena_t	*a0get(void);
 void	*a0malloc(size_t size);
 void	a0dalloc(void *ptr);
 void	*bootstrap_malloc(size_t size);
@@ -489,6 +502,7 @@ void	jemalloc_postfork_child(void);
 #include "jemalloc/internal/valgrind.h"
 #include "jemalloc/internal/util.h"
 #include "jemalloc/internal/atomic.h"
+#include "jemalloc/internal/spin.h"
 #include "jemalloc/internal/prng.h"
 #include "jemalloc/internal/ticker.h"
 #include "jemalloc/internal/ckh.h"
@@ -521,6 +535,7 @@ void	jemalloc_postfork_child(void);
 #include "jemalloc/internal/valgrind.h"
 #include "jemalloc/internal/util.h"
 #include "jemalloc/internal/atomic.h"
+#include "jemalloc/internal/spin.h"
 #include "jemalloc/internal/prng.h"
 #include "jemalloc/internal/ticker.h"
 #include "jemalloc/internal/ckh.h"
@@ -540,6 +555,11 @@ void	jemalloc_postfork_child(void);
 #include "jemalloc/internal/huge.h"
 
 #ifndef JEMALLOC_ENABLE_INLINE
+pszind_t	psz2ind(size_t psz);
+size_t	pind2sz_compute(pszind_t pind);
+size_t	pind2sz_lookup(pszind_t pind);
+size_t	pind2sz(pszind_t pind);
+size_t	psz2u(size_t psz);
 szind_t	size2index_compute(size_t size);
 szind_t	size2index_lookup(size_t size);
 szind_t	size2index(size_t size);
@@ -552,7 +572,7 @@ size_t	s2u(size_t size);
 size_t	sa2u(size_t size, size_t alignment);
 arena_t	*arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal);
 arena_t	*arena_choose(tsd_t *tsd, arena_t *arena);
-arena_t	*arena_ichoose(tsdn_t *tsdn, arena_t *arena);
+arena_t	*arena_ichoose(tsd_t *tsd, arena_t *arena);
 arena_tdata_t	*arena_tdata_get(tsd_t *tsd, unsigned ind,
     bool refresh_if_missing);
 arena_t	*arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing);
@@ -560,10 +580,90 @@ ticker_t	*decay_ticker_get(tsd_t *tsd, unsigned ind);
 #endif
 
 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
+JEMALLOC_INLINE pszind_t
+psz2ind(size_t psz)
+{
+
+	if (unlikely(psz > HUGE_MAXCLASS))
+		return (NPSIZES);
+	{
+		pszind_t x = lg_floor((psz<<1)-1);
+		pszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_PAGE) ? 0 : x -
+		    (LG_SIZE_CLASS_GROUP + LG_PAGE);
+		pszind_t grp = shift << LG_SIZE_CLASS_GROUP;
+
+		pszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
+		    LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
+
+		size_t delta_inverse_mask = ZI(-1) << lg_delta;
+		pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) &
+		    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
+
+		pszind_t ind = grp + mod;
+		return (ind);
+	}
+}
+
+JEMALLOC_INLINE size_t
+pind2sz_compute(pszind_t pind)
+{
+
+	{
+		size_t grp = pind >> LG_SIZE_CLASS_GROUP;
+		size_t mod = pind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
+
+		size_t grp_size_mask = ~((!!grp)-1);
+		size_t grp_size = ((ZU(1) << (LG_PAGE +
+		    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
+
+		size_t shift = (grp == 0) ? 1 : grp;
+		size_t lg_delta = shift + (LG_PAGE-1);
+		size_t mod_size = (mod+1) << lg_delta;
+
+		size_t sz = grp_size + mod_size;
+		return (sz);
+	}
+}
+
+JEMALLOC_INLINE size_t
+pind2sz_lookup(pszind_t pind)
+{
+	size_t ret = (size_t)pind2sz_tab[pind];
+	assert(ret == pind2sz_compute(pind));
+	return (ret);
+}
+
+JEMALLOC_INLINE size_t
+pind2sz(pszind_t pind)
+{
+
+	assert(pind < NPSIZES);
+	return (pind2sz_lookup(pind));
+}
+
+JEMALLOC_INLINE size_t
+psz2u(size_t psz)
+{
+
+	if (unlikely(psz > HUGE_MAXCLASS))
+		return (0);
+	{
+		size_t x = lg_floor((psz<<1)-1);
+		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
+		    LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
+		size_t delta = ZU(1) << lg_delta;
+		size_t delta_mask = delta - 1;
+		size_t usize = (psz + delta_mask) & ~delta_mask;
+		return (usize);
+	}
+}
+
 JEMALLOC_INLINE szind_t
 size2index_compute(size_t size)
 {
 
+	if (unlikely(size > HUGE_MAXCLASS))
+		return (NSIZES);
 #if (NTBINS != 0)
 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
 		szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
@@ -572,9 +672,7 @@ size2index_compute(size_t size)
 	}
 #endif
 	{
-		szind_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
-		    (ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))
-		    : lg_floor((size<<1)-1);
+		szind_t x = lg_floor((size<<1)-1);
 		szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
 		    x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
 		szind_t grp = shift << LG_SIZE_CLASS_GROUP;
@@ -660,6 +758,8 @@ JEMALLOC_ALWAYS_INLINE size_t
 s2u_compute(size_t size)
 {
 
+	if (unlikely(size > HUGE_MAXCLASS))
+		return (0);
 #if (NTBINS > 0)
 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
 		size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
@@ -669,9 +769,7 @@ s2u_compute(size_t size)
 	}
 #endif
 	{
-		size_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
-		    (ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))
-		    : lg_floor((size<<1)-1);
+		size_t x = lg_floor((size<<1)-1);
 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
 		    ?  LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
 		size_t delta = ZU(1) << lg_delta;
@@ -812,14 +910,10 @@ arena_choose(tsd_t *tsd, arena_t *arena)
 }
 
 JEMALLOC_INLINE arena_t *
-arena_ichoose(tsdn_t *tsdn, arena_t *arena)
+arena_ichoose(tsd_t *tsd, arena_t *arena)
 {
 
-	assert(!tsdn_null(tsdn) || arena != NULL);
-
-	if (!tsdn_null(tsdn))
-		return (arena_choose_impl(tsdn_tsd(tsdn), NULL, true));
-	return (arena);
+	return (arena_choose_impl(tsd, arena, true));
 }
 
 JEMALLOC_INLINE arena_tdata_t *
diff --git a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h
index 42d97f2a6459..46266325684c 100644
--- a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h
+++ b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h
@@ -20,8 +20,18 @@
 #    include 
 #  endif
 #  include 
+#  ifdef JEMALLOC_OS_UNFAIR_LOCK
+#    include 
+#  endif
+#  ifdef JEMALLOC_GLIBC_MALLOC_HOOK
+#    include 
+#  endif
 #  include 
 #  include 
+#  include 
+#  ifdef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
+#    include 
+#  endif
 #endif
 #include 
 
diff --git a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h
index 32f6f155d350..7636ac49d745 100644
--- a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h
+++ b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h
@@ -61,12 +61,20 @@
  */
 #define JEMALLOC_HAVE_MADVISE 
 
+/*
+ * Defined if os_unfair_lock_*() functions are available, as provided by Darwin.
+ */
+/* #undef JEMALLOC_OS_UNFAIR_LOCK */
+
 /*
  * Defined if OSSpin*() functions are available, as provided by Darwin, and
  * documented in the spinlock(3) manual page.
  */
 /* #undef JEMALLOC_OSSPIN */
 
+/* Defined if syscall(2) is available. */
+#define JEMALLOC_HAVE_SYSCALL 
+
 /*
  * Defined if secure_getenv(3) is available.
  */
@@ -77,6 +85,21 @@
  */
 #define JEMALLOC_HAVE_ISSETUGID 
 
+/*
+ * Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available.
+ */
+/* #undef JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE */
+
+/*
+ * Defined if clock_gettime(CLOCK_MONOTONIC, ...) is available.
+ */
+#define JEMALLOC_HAVE_CLOCK_MONOTONIC 1
+
+/*
+ * Defined if mach_absolute_time() is available.
+ */
+/* #undef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME */
+
 /*
  * Defined if _malloc_thread_cleanup() exists.  At least in the case of
  * FreeBSD, pthread_key_create() allocates, which if used during malloc
@@ -189,6 +212,12 @@
 /* TLS is used to map arenas and magazine caches to threads. */
 #define JEMALLOC_TLS 
 
+/*
+ * Used to mark unreachable code to quiet "end of non-void" compiler warnings.
+ * Don't use this directly; instead use unreachable() from util.h
+ */
+#define JEMALLOC_INTERNAL_UNREACHABLE abort
+
 /*
  * ffs*() functions to use for bitmapping.  Don't use these directly; instead,
  * use ffs_*() from util.h.
diff --git a/contrib/jemalloc/include/jemalloc/internal/mb.h b/contrib/jemalloc/include/jemalloc/internal/mb.h
index 437c86f72341..5384728fd50e 100644
--- a/contrib/jemalloc/include/jemalloc/internal/mb.h
+++ b/contrib/jemalloc/include/jemalloc/internal/mb.h
@@ -105,8 +105,8 @@ mb_write(void)
 	malloc_mutex_t mtx;
 
 	malloc_mutex_init(&mtx, "mb", WITNESS_RANK_OMIT);
-	malloc_mutex_lock(NULL, &mtx);
-	malloc_mutex_unlock(NULL, &mtx);
+	malloc_mutex_lock(TSDN_NULL, &mtx);
+	malloc_mutex_unlock(TSDN_NULL, &mtx);
 }
 #endif
 #endif
diff --git a/contrib/jemalloc/include/jemalloc/internal/mutex.h b/contrib/jemalloc/include/jemalloc/internal/mutex.h
index 60ab0416500c..76518db7575c 100644
--- a/contrib/jemalloc/include/jemalloc/internal/mutex.h
+++ b/contrib/jemalloc/include/jemalloc/internal/mutex.h
@@ -5,6 +5,9 @@ typedef struct malloc_mutex_s malloc_mutex_t;
 
 #ifdef _WIN32
 #  define MALLOC_MUTEX_INITIALIZER
+#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
+#  define MALLOC_MUTEX_INITIALIZER					\
+     {OS_UNFAIR_LOCK_INIT, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}
 #elif (defined(JEMALLOC_OSSPIN))
 #  define MALLOC_MUTEX_INITIALIZER {0, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}
 #elif (defined(JEMALLOC_MUTEX_INIT_CB))
@@ -35,6 +38,8 @@ struct malloc_mutex_s {
 #  else
 	CRITICAL_SECTION	lock;
 #  endif
+#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
+	os_unfair_lock		lock;
 #elif (defined(JEMALLOC_OSSPIN))
 	OSSpinLock		lock;
 #elif (defined(JEMALLOC_MUTEX_INIT_CB))
@@ -86,6 +91,8 @@ malloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex)
 #  else
 		EnterCriticalSection(&mutex->lock);
 #  endif
+#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
+		os_unfair_lock_lock(&mutex->lock);
 #elif (defined(JEMALLOC_OSSPIN))
 		OSSpinLockLock(&mutex->lock);
 #else
@@ -107,6 +114,8 @@ malloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex)
 #  else
 		LeaveCriticalSection(&mutex->lock);
 #  endif
+#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
+		os_unfair_lock_unlock(&mutex->lock);
 #elif (defined(JEMALLOC_OSSPIN))
 		OSSpinLockUnlock(&mutex->lock);
 #else
diff --git a/contrib/jemalloc/include/jemalloc/internal/nstime.h b/contrib/jemalloc/include/jemalloc/internal/nstime.h
index dc293b73b9f3..93b27dc80a05 100644
--- a/contrib/jemalloc/include/jemalloc/internal/nstime.h
+++ b/contrib/jemalloc/include/jemalloc/internal/nstime.h
@@ -1,9 +1,6 @@
 /******************************************************************************/
 #ifdef JEMALLOC_H_TYPES
 
-#define	JEMALLOC_CLOCK_GETTIME defined(_POSIX_MONOTONIC_CLOCK) \
-    && _POSIX_MONOTONIC_CLOCK >= 0
-
 typedef struct nstime_s nstime_t;
 
 /* Maximum supported number of seconds (~584 years). */
@@ -34,9 +31,12 @@ void	nstime_imultiply(nstime_t *time, uint64_t multiplier);
 void	nstime_idivide(nstime_t *time, uint64_t divisor);
 uint64_t	nstime_divide(const nstime_t *time, const nstime_t *divisor);
 #ifdef JEMALLOC_JET
+typedef bool (nstime_monotonic_t)(void);
+extern nstime_monotonic_t *nstime_monotonic;
 typedef bool (nstime_update_t)(nstime_t *);
 extern nstime_update_t *nstime_update;
 #else
+bool	nstime_monotonic(void);
 bool	nstime_update(nstime_t *time);
 #endif
 
diff --git a/contrib/jemalloc/include/jemalloc/internal/private_namespace.h b/contrib/jemalloc/include/jemalloc/internal/private_namespace.h
index 00bedbabec26..350835cbe641 100644
--- a/contrib/jemalloc/include/jemalloc/internal/private_namespace.h
+++ b/contrib/jemalloc/include/jemalloc/internal/private_namespace.h
@@ -1,4 +1,5 @@
 #define	a0dalloc JEMALLOC_N(a0dalloc)
+#define	a0get JEMALLOC_N(a0get)
 #define	a0malloc JEMALLOC_N(a0malloc)
 #define	arena_aalloc JEMALLOC_N(arena_aalloc)
 #define	arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small)
@@ -167,20 +168,15 @@
 #define	chunk_dalloc_wrapper JEMALLOC_N(chunk_dalloc_wrapper)
 #define	chunk_deregister JEMALLOC_N(chunk_deregister)
 #define	chunk_dss_boot JEMALLOC_N(chunk_dss_boot)
-#define	chunk_dss_postfork_child JEMALLOC_N(chunk_dss_postfork_child)
-#define	chunk_dss_postfork_parent JEMALLOC_N(chunk_dss_postfork_parent)
+#define	chunk_dss_mergeable JEMALLOC_N(chunk_dss_mergeable)
 #define	chunk_dss_prec_get JEMALLOC_N(chunk_dss_prec_get)
 #define	chunk_dss_prec_set JEMALLOC_N(chunk_dss_prec_set)
-#define	chunk_dss_prefork JEMALLOC_N(chunk_dss_prefork)
 #define	chunk_hooks_default JEMALLOC_N(chunk_hooks_default)
 #define	chunk_hooks_get JEMALLOC_N(chunk_hooks_get)
 #define	chunk_hooks_set JEMALLOC_N(chunk_hooks_set)
 #define	chunk_in_dss JEMALLOC_N(chunk_in_dss)
 #define	chunk_lookup JEMALLOC_N(chunk_lookup)
 #define	chunk_npages JEMALLOC_N(chunk_npages)
-#define	chunk_postfork_child JEMALLOC_N(chunk_postfork_child)
-#define	chunk_postfork_parent JEMALLOC_N(chunk_postfork_parent)
-#define	chunk_prefork JEMALLOC_N(chunk_prefork)
 #define	chunk_purge_wrapper JEMALLOC_N(chunk_purge_wrapper)
 #define	chunk_register JEMALLOC_N(chunk_register)
 #define	chunks_rtree JEMALLOC_N(chunks_rtree)
@@ -359,6 +355,7 @@
 #define	nstime_imultiply JEMALLOC_N(nstime_imultiply)
 #define	nstime_init JEMALLOC_N(nstime_init)
 #define	nstime_init2 JEMALLOC_N(nstime_init2)
+#define	nstime_monotonic JEMALLOC_N(nstime_monotonic)
 #define	nstime_ns JEMALLOC_N(nstime_ns)
 #define	nstime_nsec JEMALLOC_N(nstime_nsec)
 #define	nstime_sec JEMALLOC_N(nstime_sec)
@@ -400,11 +397,22 @@
 #define	pages_purge JEMALLOC_N(pages_purge)
 #define	pages_trim JEMALLOC_N(pages_trim)
 #define	pages_unmap JEMALLOC_N(pages_unmap)
+#define	pind2sz JEMALLOC_N(pind2sz)
+#define	pind2sz_compute JEMALLOC_N(pind2sz_compute)
+#define	pind2sz_lookup JEMALLOC_N(pind2sz_lookup)
+#define	pind2sz_tab JEMALLOC_N(pind2sz_tab)
 #define	pow2_ceil_u32 JEMALLOC_N(pow2_ceil_u32)
 #define	pow2_ceil_u64 JEMALLOC_N(pow2_ceil_u64)
 #define	pow2_ceil_zu JEMALLOC_N(pow2_ceil_zu)
-#define	prng_lg_range JEMALLOC_N(prng_lg_range)
-#define	prng_range JEMALLOC_N(prng_range)
+#define	prng_lg_range_u32 JEMALLOC_N(prng_lg_range_u32)
+#define	prng_lg_range_u64 JEMALLOC_N(prng_lg_range_u64)
+#define	prng_lg_range_zu JEMALLOC_N(prng_lg_range_zu)
+#define	prng_range_u32 JEMALLOC_N(prng_range_u32)
+#define	prng_range_u64 JEMALLOC_N(prng_range_u64)
+#define	prng_range_zu JEMALLOC_N(prng_range_zu)
+#define	prng_state_next_u32 JEMALLOC_N(prng_state_next_u32)
+#define	prng_state_next_u64 JEMALLOC_N(prng_state_next_u64)
+#define	prng_state_next_zu JEMALLOC_N(prng_state_next_zu)
 #define	prof_active JEMALLOC_N(prof_active)
 #define	prof_active_get JEMALLOC_N(prof_active_get)
 #define	prof_active_get_unlocked JEMALLOC_N(prof_active_get_unlocked)
@@ -453,12 +461,13 @@
 #define	prof_thread_active_set JEMALLOC_N(prof_thread_active_set)
 #define	prof_thread_name_get JEMALLOC_N(prof_thread_name_get)
 #define	prof_thread_name_set JEMALLOC_N(prof_thread_name_set)
+#define	psz2ind JEMALLOC_N(psz2ind)
+#define	psz2u JEMALLOC_N(psz2u)
 #define	purge_mode_names JEMALLOC_N(purge_mode_names)
 #define	quarantine JEMALLOC_N(quarantine)
 #define	quarantine_alloc_hook JEMALLOC_N(quarantine_alloc_hook)
 #define	quarantine_alloc_hook_work JEMALLOC_N(quarantine_alloc_hook_work)
 #define	quarantine_cleanup JEMALLOC_N(quarantine_cleanup)
-#define	register_zone JEMALLOC_N(register_zone)
 #define	rtree_child_read JEMALLOC_N(rtree_child_read)
 #define	rtree_child_read_hard JEMALLOC_N(rtree_child_read_hard)
 #define	rtree_child_tryread JEMALLOC_N(rtree_child_tryread)
@@ -476,7 +485,6 @@
 #define	rtree_val_write JEMALLOC_N(rtree_val_write)
 #define	run_quantize_ceil JEMALLOC_N(run_quantize_ceil)
 #define	run_quantize_floor JEMALLOC_N(run_quantize_floor)
-#define	run_quantize_max JEMALLOC_N(run_quantize_max)
 #define	s2u JEMALLOC_N(s2u)
 #define	s2u_compute JEMALLOC_N(s2u_compute)
 #define	s2u_lookup JEMALLOC_N(s2u_lookup)
@@ -486,6 +494,8 @@
 #define	size2index_compute JEMALLOC_N(size2index_compute)
 #define	size2index_lookup JEMALLOC_N(size2index_lookup)
 #define	size2index_tab JEMALLOC_N(size2index_tab)
+#define	spin_adaptive JEMALLOC_N(spin_adaptive)
+#define	spin_init JEMALLOC_N(spin_init)
 #define	stats_cactive JEMALLOC_N(stats_cactive)
 #define	stats_cactive_add JEMALLOC_N(stats_cactive_add)
 #define	stats_cactive_get JEMALLOC_N(stats_cactive_get)
@@ -544,7 +554,9 @@
 #define	tsd_cleanup JEMALLOC_N(tsd_cleanup)
 #define	tsd_cleanup_wrapper JEMALLOC_N(tsd_cleanup_wrapper)
 #define	tsd_fetch JEMALLOC_N(tsd_fetch)
+#define	tsd_fetch_impl JEMALLOC_N(tsd_fetch_impl)
 #define	tsd_get JEMALLOC_N(tsd_get)
+#define	tsd_get_allocates JEMALLOC_N(tsd_get_allocates)
 #define	tsd_iarena_get JEMALLOC_N(tsd_iarena_get)
 #define	tsd_iarena_set JEMALLOC_N(tsd_iarena_set)
 #define	tsd_iarenap_get JEMALLOC_N(tsd_iarenap_get)
@@ -603,9 +615,11 @@
 #define	witness_lock_error JEMALLOC_N(witness_lock_error)
 #define	witness_lockless_error JEMALLOC_N(witness_lockless_error)
 #define	witness_not_owner_error JEMALLOC_N(witness_not_owner_error)
+#define	witness_owner JEMALLOC_N(witness_owner)
 #define	witness_owner_error JEMALLOC_N(witness_owner_error)
 #define	witness_postfork_child JEMALLOC_N(witness_postfork_child)
 #define	witness_postfork_parent JEMALLOC_N(witness_postfork_parent)
 #define	witness_prefork JEMALLOC_N(witness_prefork)
 #define	witness_unlock JEMALLOC_N(witness_unlock)
 #define	witnesses_cleanup JEMALLOC_N(witnesses_cleanup)
+#define	zone_register JEMALLOC_N(zone_register)
diff --git a/contrib/jemalloc/include/jemalloc/internal/prng.h b/contrib/jemalloc/include/jemalloc/internal/prng.h
index 5830f8b7b327..c2bda19c6b09 100644
--- a/contrib/jemalloc/include/jemalloc/internal/prng.h
+++ b/contrib/jemalloc/include/jemalloc/internal/prng.h
@@ -19,8 +19,12 @@
  * the next has a cycle of 4, etc.  For this reason, we prefer to use the upper
  * bits.
  */
-#define	PRNG_A	UINT64_C(6364136223846793005)
-#define	PRNG_C	UINT64_C(1442695040888963407)
+
+#define	PRNG_A_32	UINT32_C(1103515241)
+#define	PRNG_C_32	UINT32_C(12347)
+
+#define	PRNG_A_64	UINT64_C(6364136223846793005)
+#define	PRNG_C_64	UINT64_C(1442695040888963407)
 
 #endif /* JEMALLOC_H_TYPES */
 /******************************************************************************/
@@ -35,28 +39,133 @@
 #ifdef JEMALLOC_H_INLINES
 
 #ifndef JEMALLOC_ENABLE_INLINE
-uint64_t	prng_lg_range(uint64_t *state, unsigned lg_range);
-uint64_t	prng_range(uint64_t *state, uint64_t range);
+uint32_t	prng_state_next_u32(uint32_t state);
+uint64_t	prng_state_next_u64(uint64_t state);
+size_t	prng_state_next_zu(size_t state);
+
+uint32_t	prng_lg_range_u32(uint32_t *state, unsigned lg_range,
+    bool atomic);
+uint64_t	prng_lg_range_u64(uint64_t *state, unsigned lg_range);
+size_t	prng_lg_range_zu(size_t *state, unsigned lg_range, bool atomic);
+
+uint32_t	prng_range_u32(uint32_t *state, uint32_t range, bool atomic);
+uint64_t	prng_range_u64(uint64_t *state, uint64_t range);
+size_t	prng_range_zu(size_t *state, size_t range, bool atomic);
 #endif
 
 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PRNG_C_))
-JEMALLOC_ALWAYS_INLINE uint64_t
-prng_lg_range(uint64_t *state, unsigned lg_range)
+JEMALLOC_ALWAYS_INLINE uint32_t
+prng_state_next_u32(uint32_t state)
 {
-	uint64_t ret;
+
+	return ((state * PRNG_A_32) + PRNG_C_32);
+}
+
+JEMALLOC_ALWAYS_INLINE uint64_t
+prng_state_next_u64(uint64_t state)
+{
+
+	return ((state * PRNG_A_64) + PRNG_C_64);
+}
+
+JEMALLOC_ALWAYS_INLINE size_t
+prng_state_next_zu(size_t state)
+{
+
+#if LG_SIZEOF_PTR == 2
+	return ((state * PRNG_A_32) + PRNG_C_32);
+#elif LG_SIZEOF_PTR == 3
+	return ((state * PRNG_A_64) + PRNG_C_64);
+#else
+#error Unsupported pointer size
+#endif
+}
+
+JEMALLOC_ALWAYS_INLINE uint32_t
+prng_lg_range_u32(uint32_t *state, unsigned lg_range, bool atomic)
+{
+	uint32_t ret, state1;
+
+	assert(lg_range > 0);
+	assert(lg_range <= 32);
+
+	if (atomic) {
+		uint32_t state0;
+
+		do {
+			state0 = atomic_read_uint32(state);
+			state1 = prng_state_next_u32(state0);
+		} while (atomic_cas_uint32(state, state0, state1));
+	} else {
+		state1 = prng_state_next_u32(*state);
+		*state = state1;
+	}
+	ret = state1 >> (32 - lg_range);
+
+	return (ret);
+}
+
+/* 64-bit atomic operations cannot be supported on all relevant platforms. */
+JEMALLOC_ALWAYS_INLINE uint64_t
+prng_lg_range_u64(uint64_t *state, unsigned lg_range)
+{
+	uint64_t ret, state1;
 
 	assert(lg_range > 0);
 	assert(lg_range <= 64);
 
-	ret = (*state * PRNG_A) + PRNG_C;
-	*state = ret;
-	ret >>= (64 - lg_range);
+	state1 = prng_state_next_u64(*state);
+	*state = state1;
+	ret = state1 >> (64 - lg_range);
+
+	return (ret);
+}
+
+JEMALLOC_ALWAYS_INLINE size_t
+prng_lg_range_zu(size_t *state, unsigned lg_range, bool atomic)
+{
+	size_t ret, state1;
+
+	assert(lg_range > 0);
+	assert(lg_range <= ZU(1) << (3 + LG_SIZEOF_PTR));
+
+	if (atomic) {
+		size_t state0;
+
+		do {
+			state0 = atomic_read_z(state);
+			state1 = prng_state_next_zu(state0);
+		} while (atomic_cas_z(state, state0, state1));
+	} else {
+		state1 = prng_state_next_zu(*state);
+		*state = state1;
+	}
+	ret = state1 >> ((ZU(1) << (3 + LG_SIZEOF_PTR)) - lg_range);
+
+	return (ret);
+}
+
+JEMALLOC_ALWAYS_INLINE uint32_t
+prng_range_u32(uint32_t *state, uint32_t range, bool atomic)
+{
+	uint32_t ret;
+	unsigned lg_range;
+
+	assert(range > 1);
+
+	/* Compute the ceiling of lg(range). */
+	lg_range = ffs_u32(pow2_ceil_u32(range)) - 1;
+
+	/* Generate a result in [0..range) via repeated trial. */
+	do {
+		ret = prng_lg_range_u32(state, lg_range, atomic);
+	} while (ret >= range);
 
 	return (ret);
 }
 
 JEMALLOC_ALWAYS_INLINE uint64_t
-prng_range(uint64_t *state, uint64_t range)
+prng_range_u64(uint64_t *state, uint64_t range)
 {
 	uint64_t ret;
 	unsigned lg_range;
@@ -68,7 +177,26 @@ prng_range(uint64_t *state, uint64_t range)
 
 	/* Generate a result in [0..range) via repeated trial. */
 	do {
-		ret = prng_lg_range(state, lg_range);
+		ret = prng_lg_range_u64(state, lg_range);
+	} while (ret >= range);
+
+	return (ret);
+}
+
+JEMALLOC_ALWAYS_INLINE size_t
+prng_range_zu(size_t *state, size_t range, bool atomic)
+{
+	size_t ret;
+	unsigned lg_range;
+
+	assert(range > 1);
+
+	/* Compute the ceiling of lg(range). */
+	lg_range = ffs_u64(pow2_ceil_u64(range)) - 1;
+
+	/* Generate a result in [0..range) via repeated trial. */
+	do {
+		ret = prng_lg_range_zu(state, lg_range, atomic);
 	} while (ret >= range);
 
 	return (ret);
diff --git a/contrib/jemalloc/include/jemalloc/internal/prof.h b/contrib/jemalloc/include/jemalloc/internal/prof.h
index 21dff5fbcd8c..8293b71edc65 100644
--- a/contrib/jemalloc/include/jemalloc/internal/prof.h
+++ b/contrib/jemalloc/include/jemalloc/internal/prof.h
@@ -299,9 +299,9 @@ extern prof_dump_header_t *prof_dump_header;
 void	prof_idump(tsdn_t *tsdn);
 bool	prof_mdump(tsd_t *tsd, const char *filename);
 void	prof_gdump(tsdn_t *tsdn);
-prof_tdata_t	*prof_tdata_init(tsdn_t *tsdn);
+prof_tdata_t	*prof_tdata_init(tsd_t *tsd);
 prof_tdata_t	*prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata);
-void	prof_reset(tsdn_t *tsdn, size_t lg_sample);
+void	prof_reset(tsd_t *tsd, size_t lg_sample);
 void	prof_tdata_cleanup(tsd_t *tsd);
 bool	prof_active_get(tsdn_t *tsdn);
 bool	prof_active_set(tsdn_t *tsdn, bool active);
@@ -315,7 +315,7 @@ bool	prof_gdump_get(tsdn_t *tsdn);
 bool	prof_gdump_set(tsdn_t *tsdn, bool active);
 void	prof_boot0(void);
 void	prof_boot1(void);
-bool	prof_boot2(tsdn_t *tsdn);
+bool	prof_boot2(tsd_t *tsd);
 void	prof_prefork0(tsdn_t *tsdn);
 void	prof_prefork1(tsdn_t *tsdn);
 void	prof_postfork_parent(tsdn_t *tsdn);
@@ -384,7 +384,7 @@ prof_tdata_get(tsd_t *tsd, bool create)
 	if (create) {
 		if (unlikely(tdata == NULL)) {
 			if (tsd_nominal(tsd)) {
-				tdata = prof_tdata_init(tsd_tsdn(tsd));
+				tdata = prof_tdata_init(tsd);
 				tsd_prof_tdata_set(tsd, tdata);
 			}
 		} else if (unlikely(tdata->expired)) {
diff --git a/contrib/jemalloc/include/jemalloc/internal/size_classes.h b/contrib/jemalloc/include/jemalloc/internal/size_classes.h
index 615586d29eb9..b12d262bb06b 100644
--- a/contrib/jemalloc/include/jemalloc/internal/size_classes.h
+++ b/contrib/jemalloc/include/jemalloc/internal/size_classes.h
@@ -7,13 +7,13 @@
  * be defined prior to inclusion, and it in turn defines:
  *
  *   LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling.
- *   SIZE_CLASSES: Complete table of
- *                 SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)
- *                 tuples.
+ *   SIZE_CLASSES: Complete table of SC(index, lg_grp, lg_delta, ndelta, psz,
+ *                 bin, lg_delta_lookup) tuples.
  *     index: Size class index.
  *     lg_grp: Lg group base size (no deltas added).
  *     lg_delta: Lg delta to previous size class.
  *     ndelta: Delta multiplier.  size == 1<iteration = 0;
+}
+
+JEMALLOC_INLINE void
+spin_adaptive(spin_t *spin)
+{
+	volatile uint64_t i;
+
+	for (i = 0; i < (KQU(1) << spin->iteration); i++)
+		CPU_SPINWAIT;
+
+	if (spin->iteration < 63)
+		spin->iteration++;
+}
+
+#endif
+
+#endif /* JEMALLOC_H_INLINES */
+/******************************************************************************/
+
diff --git a/contrib/jemalloc/include/jemalloc/internal/tcache.h b/contrib/jemalloc/include/jemalloc/internal/tcache.h
index 70883b1a7a62..01ba062dea6f 100644
--- a/contrib/jemalloc/include/jemalloc/internal/tcache.h
+++ b/contrib/jemalloc/include/jemalloc/internal/tcache.h
@@ -145,7 +145,7 @@ tcache_t *tcache_create(tsdn_t *tsdn, arena_t *arena);
 void	tcache_cleanup(tsd_t *tsd);
 void	tcache_enabled_cleanup(tsd_t *tsd);
 void	tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena);
-bool	tcaches_create(tsdn_t *tsdn, unsigned *r_ind);
+bool	tcaches_create(tsd_t *tsd, unsigned *r_ind);
 void	tcaches_flush(tsd_t *tsd, unsigned ind);
 void	tcaches_destroy(tsd_t *tsd, unsigned ind);
 bool	tcache_boot(tsdn_t *tsdn);
diff --git a/contrib/jemalloc/include/jemalloc/internal/tsd.h b/contrib/jemalloc/include/jemalloc/internal/tsd.h
index bf1134110c19..9055acafd2e7 100644
--- a/contrib/jemalloc/include/jemalloc/internal/tsd.h
+++ b/contrib/jemalloc/include/jemalloc/internal/tsd.h
@@ -48,7 +48,7 @@ typedef enum {
  *
  *   bool example_tsd_boot(void) {...}
  *   bool example_tsd_booted_get(void) {...}
- *   example_t *example_tsd_get() {...}
+ *   example_t *example_tsd_get(bool init) {...}
  *   void example_tsd_set(example_t *val) {...}
  *
  * Note that all of the functions deal in terms of (a_type *) rather than
@@ -105,7 +105,7 @@ a_name##tsd_boot(void);							\
 a_attr bool								\
 a_name##tsd_booted_get(void);						\
 a_attr a_type *								\
-a_name##tsd_get(void);							\
+a_name##tsd_get(bool init);						\
 a_attr void								\
 a_name##tsd_set(a_type *val);
 
@@ -213,9 +213,15 @@ a_name##tsd_booted_get(void)						\
 									\
 	return (a_name##tsd_booted);					\
 }									\
+a_attr bool								\
+a_name##tsd_get_allocates(void)						\
+{									\
+									\
+	return (false);							\
+}									\
 /* Get/set. */								\
 a_attr a_type *								\
-a_name##tsd_get(void)							\
+a_name##tsd_get(bool init)						\
 {									\
 									\
 	assert(a_name##tsd_booted);					\
@@ -264,9 +270,15 @@ a_name##tsd_booted_get(void)						\
 									\
 	return (a_name##tsd_booted);					\
 }									\
+a_attr bool								\
+a_name##tsd_get_allocates(void)						\
+{									\
+									\
+	return (false);							\
+}									\
 /* Get/set. */								\
 a_attr a_type *								\
-a_name##tsd_get(void)							\
+a_name##tsd_get(bool init)						\
 {									\
 									\
 	assert(a_name##tsd_booted);					\
@@ -325,14 +337,14 @@ a_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)			\
 	}								\
 }									\
 a_attr a_name##tsd_wrapper_t *						\
-a_name##tsd_wrapper_get(void)						\
+a_name##tsd_wrapper_get(bool init)					\
 {									\
 	DWORD error = GetLastError();					\
 	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
 	    TlsGetValue(a_name##tsd_tsd);				\
 	SetLastError(error);						\
 									\
-	if (unlikely(wrapper == NULL)) {				\
+	if (init && unlikely(wrapper == NULL)) {			\
 		wrapper = (a_name##tsd_wrapper_t *)			\
 		    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));	\
 		if (wrapper == NULL) {					\
@@ -392,14 +404,22 @@ a_name##tsd_booted_get(void)						\
 									\
 	return (a_name##tsd_booted);					\
 }									\
+a_attr bool								\
+a_name##tsd_get_allocates(void)						\
+{									\
+									\
+	return (true);							\
+}									\
 /* Get/set. */								\
 a_attr a_type *								\
-a_name##tsd_get(void)							\
+a_name##tsd_get(bool init)						\
 {									\
 	a_name##tsd_wrapper_t *wrapper;					\
 									\
 	assert(a_name##tsd_booted);					\
-	wrapper = a_name##tsd_wrapper_get();				\
+	wrapper = a_name##tsd_wrapper_get(init);			\
+	if (a_name##tsd_get_allocates() && !init && wrapper == NULL)	\
+		return (NULL);						\
 	return (&wrapper->val);						\
 }									\
 a_attr void								\
@@ -408,7 +428,7 @@ a_name##tsd_set(a_type *val)						\
 	a_name##tsd_wrapper_t *wrapper;					\
 									\
 	assert(a_name##tsd_booted);					\
-	wrapper = a_name##tsd_wrapper_get();				\
+	wrapper = a_name##tsd_wrapper_get(true);			\
 	wrapper->val = *(val);						\
 	if (a_cleanup != malloc_tsd_no_cleanup)				\
 		wrapper->initialized = true;				\
@@ -452,12 +472,12 @@ a_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)			\
 	}								\
 }									\
 a_attr a_name##tsd_wrapper_t *						\
-a_name##tsd_wrapper_get(void)						\
+a_name##tsd_wrapper_get(bool init)					\
 {									\
 	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
 	    pthread_getspecific(a_name##tsd_tsd);			\
 									\
-	if (unlikely(wrapper == NULL)) {				\
+	if (init && unlikely(wrapper == NULL)) {			\
 		tsd_init_block_t block;					\
 		wrapper = tsd_init_check_recursion(			\
 		    &a_name##tsd_init_head, &block);			\
@@ -520,14 +540,22 @@ a_name##tsd_booted_get(void)						\
 									\
 	return (a_name##tsd_booted);					\
 }									\
+a_attr bool								\
+a_name##tsd_get_allocates(void)						\
+{									\
+									\
+	return (true);							\
+}									\
 /* Get/set. */								\
 a_attr a_type *								\
-a_name##tsd_get(void)							\
+a_name##tsd_get(bool init)						\
 {									\
 	a_name##tsd_wrapper_t *wrapper;					\
 									\
 	assert(a_name##tsd_booted);					\
-	wrapper = a_name##tsd_wrapper_get();				\
+	wrapper = a_name##tsd_wrapper_get(init);			\
+	if (a_name##tsd_get_allocates() && !init && wrapper == NULL)	\
+		return (NULL);						\
 	return (&wrapper->val);						\
 }									\
 a_attr void								\
@@ -536,7 +564,7 @@ a_name##tsd_set(a_type *val)						\
 	a_name##tsd_wrapper_t *wrapper;					\
 									\
 	assert(a_name##tsd_booted);					\
-	wrapper = a_name##tsd_wrapper_get();				\
+	wrapper = a_name##tsd_wrapper_get(true);			\
 	wrapper->val = *(val);						\
 	if (a_cleanup != malloc_tsd_no_cleanup)				\
 		wrapper->initialized = true;				\
@@ -639,6 +667,7 @@ void	tsd_cleanup(void *arg);
 #ifndef JEMALLOC_ENABLE_INLINE
 malloc_tsd_protos(JEMALLOC_ATTR(unused), , tsd_t)
 
+tsd_t	*tsd_fetch_impl(bool init);
 tsd_t	*tsd_fetch(void);
 tsdn_t	*tsd_tsdn(tsd_t *tsd);
 bool	tsd_nominal(tsd_t *tsd);
@@ -658,9 +687,13 @@ malloc_tsd_externs(, tsd_t)
 malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, , tsd_t, tsd_initializer, tsd_cleanup)
 
 JEMALLOC_ALWAYS_INLINE tsd_t *
-tsd_fetch(void)
+tsd_fetch_impl(bool init)
 {
-	tsd_t *tsd = tsd_get();
+	tsd_t *tsd = tsd_get(init);
+
+	if (!init && tsd_get_allocates() && tsd == NULL)
+		return (NULL);
+	assert(tsd != NULL);
 
 	if (unlikely(tsd->state != tsd_state_nominal)) {
 		if (tsd->state == tsd_state_uninitialized) {
@@ -677,6 +710,13 @@ tsd_fetch(void)
 	return (tsd);
 }
 
+JEMALLOC_ALWAYS_INLINE tsd_t *
+tsd_fetch(void)
+{
+
+	return (tsd_fetch_impl(true));
+}
+
 JEMALLOC_ALWAYS_INLINE tsdn_t *
 tsd_tsdn(tsd_t *tsd)
 {
@@ -723,7 +763,7 @@ tsdn_fetch(void)
 	if (!tsd_booted_get())
 		return (NULL);
 
-	return (tsd_tsdn(tsd_fetch()));
+	return (tsd_tsdn(tsd_fetch_impl(false)));
 }
 
 JEMALLOC_ALWAYS_INLINE bool
diff --git a/contrib/jemalloc/include/jemalloc/internal/util.h b/contrib/jemalloc/include/jemalloc/internal/util.h
index a0c2203dfe1a..aee00d6d9a47 100644
--- a/contrib/jemalloc/include/jemalloc/internal/util.h
+++ b/contrib/jemalloc/include/jemalloc/internal/util.h
@@ -61,30 +61,20 @@
 #	define JEMALLOC_CC_SILENCE_INIT(v)
 #endif
 
-#define	JEMALLOC_GNUC_PREREQ(major, minor)				\
-    (!defined(__clang__) &&						\
-    (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
-#ifndef __has_builtin
-#  define __has_builtin(builtin) (0)
-#endif
-#define	JEMALLOC_CLANG_HAS_BUILTIN(builtin)				\
-    (defined(__clang__) && __has_builtin(builtin))
-
 #ifdef __GNUC__
 #	define likely(x)   __builtin_expect(!!(x), 1)
 #	define unlikely(x) __builtin_expect(!!(x), 0)
-#  if JEMALLOC_GNUC_PREREQ(4, 6) ||					\
-      JEMALLOC_CLANG_HAS_BUILTIN(__builtin_unreachable)
-#	define unreachable() __builtin_unreachable()
-#  else
-#	define unreachable() abort()
-#  endif
 #else
 #	define likely(x)   !!(x)
 #	define unlikely(x) !!(x)
-#	define unreachable() abort()
 #endif
 
+#if !defined(JEMALLOC_INTERNAL_UNREACHABLE)
+#  error JEMALLOC_INTERNAL_UNREACHABLE should have been defined by configure
+#endif
+
+#define unreachable() JEMALLOC_INTERNAL_UNREACHABLE()
+
 #include "jemalloc/internal/assert.h"
 
 /* Use to assert a particular configuration, e.g., cassert(config_debug). */
diff --git a/contrib/jemalloc/include/jemalloc/internal/witness.h b/contrib/jemalloc/include/jemalloc/internal/witness.h
index d78dca2d6c7e..cdf15d797d0c 100644
--- a/contrib/jemalloc/include/jemalloc/internal/witness.h
+++ b/contrib/jemalloc/include/jemalloc/internal/witness.h
@@ -108,6 +108,7 @@ void	witness_postfork_child(tsd_t *tsd);
 #ifdef JEMALLOC_H_INLINES
 
 #ifndef JEMALLOC_ENABLE_INLINE
+bool	witness_owner(tsd_t *tsd, const witness_t *witness);
 void	witness_assert_owner(tsdn_t *tsdn, const witness_t *witness);
 void	witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);
 void	witness_assert_lockless(tsdn_t *tsdn);
@@ -116,12 +117,25 @@ void	witness_unlock(tsdn_t *tsdn, witness_t *witness);
 #endif
 
 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
+JEMALLOC_INLINE bool
+witness_owner(tsd_t *tsd, const witness_t *witness)
+{
+	witness_list_t *witnesses;
+	witness_t *w;
+
+	witnesses = tsd_witnessesp_get(tsd);
+	ql_foreach(w, witnesses, link) {
+		if (w == witness)
+			return (true);
+	}
+
+	return (false);
+}
+
 JEMALLOC_INLINE void
 witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
 {
 	tsd_t *tsd;
-	witness_list_t *witnesses;
-	witness_t *w;
 
 	if (!config_debug)
 		return;
@@ -132,11 +146,8 @@ witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
 	if (witness->rank == WITNESS_RANK_OMIT)
 		return;
 
-	witnesses = tsd_witnessesp_get(tsd);
-	ql_foreach(w, witnesses, link) {
-		if (w == witness)
-			return;
-	}
+	if (witness_owner(tsd, witness))
+		return;
 	witness_owner_error(witness);
 }
 
@@ -238,10 +249,16 @@ witness_unlock(tsdn_t *tsdn, witness_t *witness)
 	if (witness->rank == WITNESS_RANK_OMIT)
 		return;
 
-	witness_assert_owner(tsdn, witness);
-
-	witnesses = tsd_witnessesp_get(tsd);
-	ql_remove(witnesses, witness, link);
+	/*
+	 * Check whether owner before removal, rather than relying on
+	 * witness_assert_owner() to abort, so that unit tests can test this
+	 * function's failure mode without causing undefined behavior.
+	 */
+	if (witness_owner(tsd, witness)) {
+		witnesses = tsd_witnessesp_get(tsd);
+		ql_remove(witnesses, witness, link);
+	} else
+		witness_assert_owner(tsdn, witness);
 }
 #endif
 
diff --git a/contrib/jemalloc/include/jemalloc/jemalloc.h b/contrib/jemalloc/include/jemalloc/jemalloc.h
index d2c876e91841..a8b2a6c33998 100644
--- a/contrib/jemalloc/include/jemalloc/jemalloc.h
+++ b/contrib/jemalloc/include/jemalloc/jemalloc.h
@@ -87,12 +87,12 @@ extern "C" {
 #include 
 #include 
 
-#define	JEMALLOC_VERSION "4.2.1-0-g3de035335255d553bdb344c32ffdb603816195d8"
+#define	JEMALLOC_VERSION "4.3.1-0-g0110fa8451af905affd77c3bea0d545fee2251b2"
 #define	JEMALLOC_VERSION_MAJOR 4
-#define	JEMALLOC_VERSION_MINOR 2
+#define	JEMALLOC_VERSION_MINOR 3
 #define	JEMALLOC_VERSION_BUGFIX 1
 #define	JEMALLOC_VERSION_NREV 0
-#define	JEMALLOC_VERSION_GID "3de035335255d553bdb344c32ffdb603816195d8"
+#define	JEMALLOC_VERSION_GID "0110fa8451af905affd77c3bea0d545fee2251b2"
 
 #  define MALLOCX_LG_ALIGN(la)	((int)(la))
 #  if LG_SIZEOF_PTR == 2
diff --git a/contrib/jemalloc/src/arena.c b/contrib/jemalloc/src/arena.c
index ce62590b9200..e196b13378e6 100644
--- a/contrib/jemalloc/src/arena.c
+++ b/contrib/jemalloc/src/arena.c
@@ -21,15 +21,8 @@ size_t		map_bias;
 size_t		map_misc_offset;
 size_t		arena_maxrun; /* Max run size for arenas. */
 size_t		large_maxclass; /* Max large size class. */
-size_t		run_quantize_max; /* Max run_quantize_*() input. */
-static size_t	small_maxrun; /* Max run size for small size classes. */
-static bool	*small_run_tab; /* Valid small run page multiples. */
-static size_t	*run_quantize_floor_tab; /* run_quantize_floor() memoization. */
-static size_t	*run_quantize_ceil_tab; /* run_quantize_ceil() memoization. */
 unsigned	nlclasses; /* Number of large size classes. */
 unsigned	nhclasses; /* Number of huge size classes. */
-static szind_t	runs_avail_bias; /* Size index for first runs_avail tree. */
-static szind_t	runs_avail_nclasses; /* Number of runs_avail trees. */
 
 /******************************************************************************/
 /*
@@ -37,6 +30,8 @@ static szind_t	runs_avail_nclasses; /* Number of runs_avail trees. */
  * definition.
  */
 
+static void	arena_chunk_dalloc(tsdn_t *tsdn, arena_t *arena,
+    arena_chunk_t *chunk);
 static void	arena_purge_to_limit(tsdn_t *tsdn, arena_t *arena,
     size_t ndirty_limit);
 static void	arena_run_dalloc(tsdn_t *tsdn, arena_t *arena, arena_run_t *run,
@@ -77,83 +72,6 @@ arena_run_addr_comp(const arena_chunk_map_misc_t *a,
 ph_gen(static UNUSED, arena_run_heap_, arena_run_heap_t, arena_chunk_map_misc_t,
     ph_link, arena_run_addr_comp)
 
-static size_t
-run_quantize_floor_compute(size_t size)
-{
-	size_t qsize;
-
-	assert(size != 0);
-	assert(size == PAGE_CEILING(size));
-
-	/* Don't change sizes that are valid small run sizes. */
-	if (size <= small_maxrun && small_run_tab[size >> LG_PAGE])
-		return (size);
-
-	/*
-	 * Round down to the nearest run size that can actually be requested
-	 * during normal large allocation.  Add large_pad so that cache index
-	 * randomization can offset the allocation from the page boundary.
-	 */
-	qsize = index2size(size2index(size - large_pad + 1) - 1) + large_pad;
-	if (qsize <= SMALL_MAXCLASS + large_pad)
-		return (run_quantize_floor_compute(size - large_pad));
-	assert(qsize <= size);
-	return (qsize);
-}
-
-static size_t
-run_quantize_ceil_compute_hard(size_t size)
-{
-	size_t large_run_size_next;
-
-	assert(size != 0);
-	assert(size == PAGE_CEILING(size));
-
-	/*
-	 * Return the next quantized size greater than the input size.
-	 * Quantized sizes comprise the union of run sizes that back small
-	 * region runs, and run sizes that back large regions with no explicit
-	 * alignment constraints.
-	 */
-
-	if (size > SMALL_MAXCLASS) {
-		large_run_size_next = PAGE_CEILING(index2size(size2index(size -
-		    large_pad) + 1) + large_pad);
-	} else
-		large_run_size_next = SIZE_T_MAX;
-	if (size >= small_maxrun)
-		return (large_run_size_next);
-
-	while (true) {
-		size += PAGE;
-		assert(size <= small_maxrun);
-		if (small_run_tab[size >> LG_PAGE]) {
-			if (large_run_size_next < size)
-				return (large_run_size_next);
-			return (size);
-		}
-	}
-}
-
-static size_t
-run_quantize_ceil_compute(size_t size)
-{
-	size_t qsize = run_quantize_floor_compute(size);
-
-	if (qsize < size) {
-		/*
-		 * Skip a quantization that may have an adequately large run,
-		 * because under-sized runs may be mixed in.  This only happens
-		 * when an unusual size is requested, i.e. for aligned
-		 * allocation, and is just one of several places where linear
-		 * search would potentially find sufficiently aligned available
-		 * memory somewhere lower.
-		 */
-		qsize = run_quantize_ceil_compute_hard(qsize);
-	}
-	return (qsize);
-}
-
 #ifdef JEMALLOC_JET
 #undef run_quantize_floor
 #define	run_quantize_floor JEMALLOC_N(n_run_quantize_floor)
@@ -162,13 +80,27 @@ static size_t
 run_quantize_floor(size_t size)
 {
 	size_t ret;
+	pszind_t pind;
 
 	assert(size > 0);
-	assert(size <= run_quantize_max);
+	assert(size <= HUGE_MAXCLASS);
 	assert((size & PAGE_MASK) == 0);
 
-	ret = run_quantize_floor_tab[(size >> LG_PAGE) - 1];
-	assert(ret == run_quantize_floor_compute(size));
+	assert(size != 0);
+	assert(size == PAGE_CEILING(size));
+
+	pind = psz2ind(size - large_pad + 1);
+	if (pind == 0) {
+		/*
+		 * Avoid underflow.  This short-circuit would also do the right
+		 * thing for all sizes in the range for which there are
+		 * PAGE-spaced size classes, but it's simplest to just handle
+		 * the one case that would cause erroneous results.
+		 */
+		return (size);
+	}
+	ret = pind2sz(pind - 1) + large_pad;
+	assert(ret <= size);
 	return (ret);
 }
 #ifdef JEMALLOC_JET
@@ -187,11 +119,21 @@ run_quantize_ceil(size_t size)
 	size_t ret;
 
 	assert(size > 0);
-	assert(size <= run_quantize_max);
+	assert(size <= HUGE_MAXCLASS);
 	assert((size & PAGE_MASK) == 0);
 
-	ret = run_quantize_ceil_tab[(size >> LG_PAGE) - 1];
-	assert(ret == run_quantize_ceil_compute(size));
+	ret = run_quantize_floor(size);
+	if (ret < size) {
+		/*
+		 * Skip a quantization that may have an adequately large run,
+		 * because under-sized runs may be mixed in.  This only happens
+		 * when an unusual size is requested, i.e. for aligned
+		 * allocation, and is just one of several places where linear
+		 * search would potentially find sufficiently aligned available
+		 * memory somewhere lower.
+		 */
+		ret = pind2sz(psz2ind(ret - large_pad + 1)) + large_pad;
+	}
 	return (ret);
 }
 #ifdef JEMALLOC_JET
@@ -200,25 +142,17 @@ run_quantize_ceil(size_t size)
 run_quantize_t *run_quantize_ceil = JEMALLOC_N(n_run_quantize_ceil);
 #endif
 
-static arena_run_heap_t *
-arena_runs_avail_get(arena_t *arena, szind_t ind)
-{
-
-	assert(ind >= runs_avail_bias);
-	assert(ind - runs_avail_bias < runs_avail_nclasses);
-
-	return (&arena->runs_avail[ind - runs_avail_bias]);
-}
-
 static void
 arena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,
     size_t npages)
 {
-	szind_t ind = size2index(run_quantize_floor(arena_miscelm_size_get(
+	pszind_t pind = psz2ind(run_quantize_floor(arena_miscelm_size_get(
 	    arena_miscelm_get_const(chunk, pageind))));
 	assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>
 	    LG_PAGE));
-	arena_run_heap_insert(arena_runs_avail_get(arena, ind),
+	assert((npages << LG_PAGE) < chunksize);
+	assert(pind2sz(pind) <= chunksize);
+	arena_run_heap_insert(&arena->runs_avail[pind],
 	    arena_miscelm_get_mutable(chunk, pageind));
 }
 
@@ -226,11 +160,13 @@ static void
 arena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,
     size_t npages)
 {
-	szind_t ind = size2index(run_quantize_floor(arena_miscelm_size_get(
+	pszind_t pind = psz2ind(run_quantize_floor(arena_miscelm_size_get(
 	    arena_miscelm_get_const(chunk, pageind))));
 	assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>
 	    LG_PAGE));
-	arena_run_heap_remove(arena_runs_avail_get(arena, ind),
+	assert((npages << LG_PAGE) < chunksize);
+	assert(pind2sz(pind) <= chunksize);
+	arena_run_heap_remove(&arena->runs_avail[pind],
 	    arena_miscelm_get_mutable(chunk, pageind));
 }
 
@@ -649,14 +585,13 @@ arena_chunk_alloc_internal(tsdn_t *tsdn, arena_t *arena, bool *zero,
 	chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
 
 	chunk = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, chunksize,
-	    chunksize, zero, true);
+	    chunksize, zero, commit, true);
 	if (chunk != NULL) {
 		if (arena_chunk_register(tsdn, arena, chunk, *zero)) {
 			chunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk,
 			    chunksize, true);
 			return (NULL);
 		}
-		*commit = true;
 	}
 	if (chunk == NULL) {
 		chunk = arena_chunk_alloc_internal_hard(tsdn, arena,
@@ -953,6 +888,7 @@ arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
 	void *ret;
 	chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
 	size_t csize = CHUNK_CEILING(usize);
+	bool commit = true;
 
 	malloc_mutex_lock(tsdn, &arena->lock);
 
@@ -964,7 +900,7 @@ arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
 	arena_nactive_add(arena, usize >> LG_PAGE);
 
 	ret = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, csize,
-	    alignment, zero, true);
+	    alignment, zero, &commit, true);
 	malloc_mutex_unlock(tsdn, &arena->lock);
 	if (ret == NULL) {
 		ret = arena_chunk_alloc_huge_hard(tsdn, arena, &chunk_hooks,
@@ -1074,6 +1010,7 @@ arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena, void *chunk,
 	void *nchunk = (void *)((uintptr_t)chunk + CHUNK_CEILING(oldsize));
 	size_t udiff = usize - oldsize;
 	size_t cdiff = CHUNK_CEILING(usize) - CHUNK_CEILING(oldsize);
+	bool commit = true;
 
 	malloc_mutex_lock(tsdn, &arena->lock);
 
@@ -1085,7 +1022,7 @@ arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena, void *chunk,
 	arena_nactive_add(arena, udiff >> LG_PAGE);
 
 	err = (chunk_alloc_cache(tsdn, arena, &chunk_hooks, nchunk, cdiff,
-	    chunksize, zero, true) == NULL);
+	    chunksize, zero, &commit, true) == NULL);
 	malloc_mutex_unlock(tsdn, &arena->lock);
 	if (err) {
 		err = arena_chunk_ralloc_huge_expand_hard(tsdn, arena,
@@ -1109,12 +1046,13 @@ arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena, void *chunk,
 static arena_run_t *
 arena_run_first_best_fit(arena_t *arena, size_t size)
 {
-	szind_t ind, i;
+	pszind_t pind, i;
 
-	ind = size2index(run_quantize_ceil(size));
-	for (i = ind; i < runs_avail_nclasses + runs_avail_bias; i++) {
+	pind = psz2ind(run_quantize_ceil(size));
+
+	for (i = pind; pind2sz(i) <= chunksize; i++) {
 		arena_chunk_map_misc_t *miscelm = arena_run_heap_first(
-		    arena_runs_avail_get(arena, i));
+		    &arena->runs_avail[i]);
 		if (miscelm != NULL)
 			return (&miscelm->run);
 	}
@@ -1125,7 +1063,7 @@ arena_run_first_best_fit(arena_t *arena, size_t size)
 static arena_run_t *
 arena_run_alloc_large_helper(arena_t *arena, size_t size, bool zero)
 {
-	arena_run_t *run = arena_run_first_best_fit(arena, s2u(size));
+	arena_run_t *run = arena_run_first_best_fit(arena, size);
 	if (run != NULL) {
 		if (arena_run_split_large(arena, run, size, zero))
 			run = NULL;
@@ -1256,14 +1194,14 @@ arena_decay_deadline_init(arena_t *arena)
 	 * Generate a new deadline that is uniformly random within the next
 	 * epoch after the current one.
 	 */
-	nstime_copy(&arena->decay_deadline, &arena->decay_epoch);
-	nstime_add(&arena->decay_deadline, &arena->decay_interval);
-	if (arena->decay_time > 0) {
+	nstime_copy(&arena->decay.deadline, &arena->decay.epoch);
+	nstime_add(&arena->decay.deadline, &arena->decay.interval);
+	if (arena->decay.time > 0) {
 		nstime_t jitter;
 
-		nstime_init(&jitter, prng_range(&arena->decay_jitter_state,
-		    nstime_ns(&arena->decay_interval)));
-		nstime_add(&arena->decay_deadline, &jitter);
+		nstime_init(&jitter, prng_range_u64(&arena->decay.jitter_state,
+		    nstime_ns(&arena->decay.interval)));
+		nstime_add(&arena->decay.deadline, &jitter);
 	}
 }
 
@@ -1273,7 +1211,7 @@ arena_decay_deadline_reached(const arena_t *arena, const nstime_t *time)
 
 	assert(opt_purge == purge_mode_decay);
 
-	return (nstime_compare(&arena->decay_deadline, time) <= 0);
+	return (nstime_compare(&arena->decay.deadline, time) <= 0);
 }
 
 static size_t
@@ -1298,92 +1236,103 @@ arena_decay_backlog_npages_limit(const arena_t *arena)
 	 */
 	sum = 0;
 	for (i = 0; i < SMOOTHSTEP_NSTEPS; i++)
-		sum += arena->decay_backlog[i] * h_steps[i];
+		sum += arena->decay.backlog[i] * h_steps[i];
 	npages_limit_backlog = (size_t)(sum >> SMOOTHSTEP_BFP);
 
 	return (npages_limit_backlog);
 }
 
 static void
-arena_decay_epoch_advance(arena_t *arena, const nstime_t *time)
+arena_decay_backlog_update_last(arena_t *arena)
 {
-	uint64_t nadvance_u64;
-	nstime_t delta;
-	size_t ndirty_delta;
+	size_t ndirty_delta = (arena->ndirty > arena->decay.ndirty) ?
+	    arena->ndirty - arena->decay.ndirty : 0;
+	arena->decay.backlog[SMOOTHSTEP_NSTEPS-1] = ndirty_delta;
+}
 
-	assert(opt_purge == purge_mode_decay);
-	assert(arena_decay_deadline_reached(arena, time));
+static void
+arena_decay_backlog_update(arena_t *arena, uint64_t nadvance_u64)
+{
 
-	nstime_copy(&delta, time);
-	nstime_subtract(&delta, &arena->decay_epoch);
-	nadvance_u64 = nstime_divide(&delta, &arena->decay_interval);
-	assert(nadvance_u64 > 0);
-
-	/* Add nadvance_u64 decay intervals to epoch. */
-	nstime_copy(&delta, &arena->decay_interval);
-	nstime_imultiply(&delta, nadvance_u64);
-	nstime_add(&arena->decay_epoch, &delta);
-
-	/* Set a new deadline. */
-	arena_decay_deadline_init(arena);
-
-	/* Update the backlog. */
 	if (nadvance_u64 >= SMOOTHSTEP_NSTEPS) {
-		memset(arena->decay_backlog, 0, (SMOOTHSTEP_NSTEPS-1) *
+		memset(arena->decay.backlog, 0, (SMOOTHSTEP_NSTEPS-1) *
 		    sizeof(size_t));
 	} else {
 		size_t nadvance_z = (size_t)nadvance_u64;
 
 		assert((uint64_t)nadvance_z == nadvance_u64);
 
-		memmove(arena->decay_backlog, &arena->decay_backlog[nadvance_z],
+		memmove(arena->decay.backlog, &arena->decay.backlog[nadvance_z],
 		    (SMOOTHSTEP_NSTEPS - nadvance_z) * sizeof(size_t));
 		if (nadvance_z > 1) {
-			memset(&arena->decay_backlog[SMOOTHSTEP_NSTEPS -
+			memset(&arena->decay.backlog[SMOOTHSTEP_NSTEPS -
 			    nadvance_z], 0, (nadvance_z-1) * sizeof(size_t));
 		}
 	}
-	ndirty_delta = (arena->ndirty > arena->decay_ndirty) ? arena->ndirty -
-	    arena->decay_ndirty : 0;
-	arena->decay_ndirty = arena->ndirty;
-	arena->decay_backlog[SMOOTHSTEP_NSTEPS-1] = ndirty_delta;
-	arena->decay_backlog_npages_limit =
-	    arena_decay_backlog_npages_limit(arena);
+
+	arena_decay_backlog_update_last(arena);
 }
 
-static size_t
-arena_decay_npages_limit(arena_t *arena)
+static void
+arena_decay_epoch_advance_helper(arena_t *arena, const nstime_t *time)
 {
-	size_t npages_limit;
+	uint64_t nadvance_u64;
+	nstime_t delta;
 
 	assert(opt_purge == purge_mode_decay);
+	assert(arena_decay_deadline_reached(arena, time));
 
-	npages_limit = arena->decay_backlog_npages_limit;
+	nstime_copy(&delta, time);
+	nstime_subtract(&delta, &arena->decay.epoch);
+	nadvance_u64 = nstime_divide(&delta, &arena->decay.interval);
+	assert(nadvance_u64 > 0);
 
-	/* Add in any dirty pages created during the current epoch. */
-	if (arena->ndirty > arena->decay_ndirty)
-		npages_limit += arena->ndirty - arena->decay_ndirty;
+	/* Add nadvance_u64 decay intervals to epoch. */
+	nstime_copy(&delta, &arena->decay.interval);
+	nstime_imultiply(&delta, nadvance_u64);
+	nstime_add(&arena->decay.epoch, &delta);
 
-	return (npages_limit);
+	/* Set a new deadline. */
+	arena_decay_deadline_init(arena);
+
+	/* Update the backlog. */
+	arena_decay_backlog_update(arena, nadvance_u64);
+}
+
+static void
+arena_decay_epoch_advance_purge(tsdn_t *tsdn, arena_t *arena)
+{
+	size_t ndirty_limit = arena_decay_backlog_npages_limit(arena);
+
+	if (arena->ndirty > ndirty_limit)
+		arena_purge_to_limit(tsdn, arena, ndirty_limit);
+	arena->decay.ndirty = arena->ndirty;
+}
+
+static void
+arena_decay_epoch_advance(tsdn_t *tsdn, arena_t *arena, const nstime_t *time)
+{
+
+	arena_decay_epoch_advance_helper(arena, time);
+	arena_decay_epoch_advance_purge(tsdn, arena);
 }
 
 static void
 arena_decay_init(arena_t *arena, ssize_t decay_time)
 {
 
-	arena->decay_time = decay_time;
+	arena->decay.time = decay_time;
 	if (decay_time > 0) {
-		nstime_init2(&arena->decay_interval, decay_time, 0);
-		nstime_idivide(&arena->decay_interval, SMOOTHSTEP_NSTEPS);
+		nstime_init2(&arena->decay.interval, decay_time, 0);
+		nstime_idivide(&arena->decay.interval, SMOOTHSTEP_NSTEPS);
 	}
 
-	nstime_init(&arena->decay_epoch, 0);
-	nstime_update(&arena->decay_epoch);
-	arena->decay_jitter_state = (uint64_t)(uintptr_t)arena;
+	nstime_init(&arena->decay.epoch, 0);
+	nstime_update(&arena->decay.epoch);
+	arena->decay.jitter_state = (uint64_t)(uintptr_t)arena;
 	arena_decay_deadline_init(arena);
-	arena->decay_ndirty = arena->ndirty;
-	arena->decay_backlog_npages_limit = 0;
-	memset(arena->decay_backlog, 0, SMOOTHSTEP_NSTEPS * sizeof(size_t));
+	arena->decay.ndirty = arena->ndirty;
+	memset(arena->decay.backlog, 0, SMOOTHSTEP_NSTEPS * sizeof(size_t));
 }
 
 static bool
@@ -1403,7 +1352,7 @@ arena_decay_time_get(tsdn_t *tsdn, arena_t *arena)
 	ssize_t decay_time;
 
 	malloc_mutex_lock(tsdn, &arena->lock);
-	decay_time = arena->decay_time;
+	decay_time = arena->decay.time;
 	malloc_mutex_unlock(tsdn, &arena->lock);
 
 	return (decay_time);
@@ -1464,35 +1413,44 @@ static void
 arena_maybe_purge_decay(tsdn_t *tsdn, arena_t *arena)
 {
 	nstime_t time;
-	size_t ndirty_limit;
 
 	assert(opt_purge == purge_mode_decay);
 
 	/* Purge all or nothing if the option is disabled. */
-	if (arena->decay_time <= 0) {
-		if (arena->decay_time == 0)
+	if (arena->decay.time <= 0) {
+		if (arena->decay.time == 0)
 			arena_purge_to_limit(tsdn, arena, 0);
 		return;
 	}
 
-	nstime_copy(&time, &arena->decay_epoch);
-	if (unlikely(nstime_update(&time))) {
-		/* Time went backwards.  Force an epoch advance. */
-		nstime_copy(&time, &arena->decay_deadline);
+	nstime_init(&time, 0);
+	nstime_update(&time);
+	if (unlikely(!nstime_monotonic() && nstime_compare(&arena->decay.epoch,
+	    &time) > 0)) {
+		/*
+		 * Time went backwards.  Move the epoch back in time and
+		 * generate a new deadline, with the expectation that time
+		 * typically flows forward for long enough periods of time that
+		 * epochs complete.  Unfortunately, this strategy is susceptible
+		 * to clock jitter triggering premature epoch advances, but
+		 * clock jitter estimation and compensation isn't feasible here
+		 * because calls into this code are event-driven.
+		 */
+		nstime_copy(&arena->decay.epoch, &time);
+		arena_decay_deadline_init(arena);
+	} else {
+		/* Verify that time does not go backwards. */
+		assert(nstime_compare(&arena->decay.epoch, &time) <= 0);
 	}
 
-	if (arena_decay_deadline_reached(arena, &time))
-		arena_decay_epoch_advance(arena, &time);
-
-	ndirty_limit = arena_decay_npages_limit(arena);
-
 	/*
-	 * Don't try to purge unless the number of purgeable pages exceeds the
-	 * current limit.
+	 * If the deadline has been reached, advance to the current epoch and
+	 * purge to the new limit if necessary.  Note that dirty pages created
+	 * during the current epoch are not subject to purge until a future
+	 * epoch, so as a result purging only happens during epoch advances.
 	 */
-	if (arena->ndirty <= ndirty_limit)
-		return;
-	arena_purge_to_limit(tsdn, arena, ndirty_limit);
+	if (arena_decay_deadline_reached(arena, &time))
+		arena_decay_epoch_advance(tsdn, arena, &time);
 }
 
 void
@@ -1561,7 +1519,7 @@ arena_stash_dirty(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
 
 		if (rdelm == &chunkselm->rd) {
 			extent_node_t *chunkselm_next;
-			bool zero;
+			bool zero, commit;
 			UNUSED void *chunk;
 
 			npages = extent_node_size_get(chunkselm) >> LG_PAGE;
@@ -1575,10 +1533,11 @@ arena_stash_dirty(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
 			 * dalloc_node=false argument to chunk_alloc_cache().
 			 */
 			zero = false;
+			commit = false;
 			chunk = chunk_alloc_cache(tsdn, arena, chunk_hooks,
 			    extent_node_addr_get(chunkselm),
 			    extent_node_size_get(chunkselm), chunksize, &zero,
-			    false);
+			    &commit, false);
 			assert(chunk == extent_node_addr_get(chunkselm));
 			assert(zero == extent_node_zeroed_get(chunkselm));
 			extent_node_dirty_insert(chunkselm, purge_runs_sentinel,
@@ -1967,7 +1926,7 @@ arena_reset(tsd_t *tsd, arena_t *arena)
 	assert(!arena->purging);
 	arena->nactive = 0;
 
-	for(i = 0; i < runs_avail_nclasses; i++)
+	for (i = 0; i < NPSIZES; i++)
 		arena_run_heap_new(&arena->runs_avail[i]);
 
 	malloc_mutex_unlock(tsd_tsdn(tsd), &arena->lock);
@@ -2606,7 +2565,8 @@ arena_malloc_large(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero)
 		 * that is a multiple of the cacheline size, e.g. [0 .. 63) * 64
 		 * for 4 KiB pages and 64-byte cachelines.
 		 */
-		r = prng_lg_range(&arena->offset_state, LG_PAGE - LG_CACHELINE);
+		r = prng_lg_range_zu(&arena->offset_state, LG_PAGE -
+		    LG_CACHELINE, false);
 		random_offset = ((uintptr_t)r) << LG_CACHELINE;
 	} else
 		random_offset = 0;
@@ -3391,7 +3351,7 @@ arena_basic_stats_merge_locked(arena_t *arena, unsigned *nthreads,
 	*nthreads += arena_nthreads_get(arena, false);
 	*dss = dss_prec_names[arena->dss_prec];
 	*lg_dirty_mult = arena->lg_dirty_mult;
-	*decay_time = arena->decay_time;
+	*decay_time = arena->decay.time;
 	*nactive += arena->nactive;
 	*ndirty += arena->ndirty;
 }
@@ -3496,23 +3456,19 @@ arena_t *
 arena_new(tsdn_t *tsdn, unsigned ind)
 {
 	arena_t *arena;
-	size_t arena_size;
 	unsigned i;
 
-	/* Compute arena size to incorporate sufficient runs_avail elements. */
-	arena_size = offsetof(arena_t, runs_avail) + (sizeof(arena_run_heap_t) *
-	    runs_avail_nclasses);
 	/*
 	 * Allocate arena, arena->lstats, and arena->hstats contiguously, mainly
 	 * because there is no way to clean up if base_alloc() OOMs.
 	 */
 	if (config_stats) {
 		arena = (arena_t *)base_alloc(tsdn,
-		    CACHELINE_CEILING(arena_size) + QUANTUM_CEILING(nlclasses *
-		    sizeof(malloc_large_stats_t) + nhclasses) *
-		    sizeof(malloc_huge_stats_t));
+		    CACHELINE_CEILING(sizeof(arena_t)) +
+		    QUANTUM_CEILING((nlclasses * sizeof(malloc_large_stats_t)))
+		    + (nhclasses * sizeof(malloc_huge_stats_t)));
 	} else
-		arena = (arena_t *)base_alloc(tsdn, arena_size);
+		arena = (arena_t *)base_alloc(tsdn, sizeof(arena_t));
 	if (arena == NULL)
 		return (NULL);
 
@@ -3524,11 +3480,11 @@ arena_new(tsdn_t *tsdn, unsigned ind)
 	if (config_stats) {
 		memset(&arena->stats, 0, sizeof(arena_stats_t));
 		arena->stats.lstats = (malloc_large_stats_t *)((uintptr_t)arena
-		    + CACHELINE_CEILING(arena_size));
+		    + CACHELINE_CEILING(sizeof(arena_t)));
 		memset(arena->stats.lstats, 0, nlclasses *
 		    sizeof(malloc_large_stats_t));
 		arena->stats.hstats = (malloc_huge_stats_t *)((uintptr_t)arena
-		    + CACHELINE_CEILING(arena_size) +
+		    + CACHELINE_CEILING(sizeof(arena_t)) +
 		    QUANTUM_CEILING(nlclasses * sizeof(malloc_large_stats_t)));
 		memset(arena->stats.hstats, 0, nhclasses *
 		    sizeof(malloc_huge_stats_t));
@@ -3548,10 +3504,10 @@ arena_new(tsdn_t *tsdn, unsigned ind)
 		 * deterministic seed.
 		 */
 		arena->offset_state = config_debug ? ind :
-		    (uint64_t)(uintptr_t)arena;
+		    (size_t)(uintptr_t)arena;
 	}
 
-	arena->dss_prec = chunk_dss_prec_get(tsdn);
+	arena->dss_prec = chunk_dss_prec_get();
 
 	ql_new(&arena->achunks);
 
@@ -3562,8 +3518,9 @@ arena_new(tsdn_t *tsdn, unsigned ind)
 	arena->nactive = 0;
 	arena->ndirty = 0;
 
-	for(i = 0; i < runs_avail_nclasses; i++)
+	for (i = 0; i < NPSIZES; i++)
 		arena_run_heap_new(&arena->runs_avail[i]);
+
 	qr_new(&arena->runs_dirty, rd_link);
 	qr_new(&arena->chunks_cache, cc_link);
 
@@ -3693,9 +3650,6 @@ bin_info_run_size_calc(arena_bin_info_t *bin_info)
 	bin_info->reg0_offset = (uint32_t)(actual_run_size - (actual_nregs *
 	    bin_info->reg_interval) - pad_size + bin_info->redzone_size);
 
-	if (actual_run_size > small_maxrun)
-		small_maxrun = actual_run_size;
-
 	assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs
 	    * bin_info->reg_interval) + pad_size == bin_info->run_size);
 }
@@ -3711,7 +3665,7 @@ bin_info_init(void)
 	bin_info_run_size_calc(bin_info);				\
 	bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs);
 #define	BIN_INFO_INIT_bin_no(index, size)
-#define	SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)	\
+#define	SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup)	\
 	BIN_INFO_INIT_bin_##bin(index, (ZU(1)<>
-	    LG_PAGE));
-	if (small_run_tab == NULL)
-		return (true);
-
-#define	TAB_INIT_bin_yes(index, size) {					\
-		arena_bin_info_t *bin_info = &arena_bin_info[index];	\
-		small_run_tab[bin_info->run_size >> LG_PAGE] = true;	\
-	}
-#define	TAB_INIT_bin_no(index, size)
-#define	SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)	\
-	TAB_INIT_bin_##bin(index, (ZU(1)<> LG_PAGE));
-	if (run_quantize_floor_tab == NULL)
-		return (true);
-
-	run_quantize_ceil_tab = (size_t *)base_alloc(NULL, sizeof(size_t) *
-	    (run_quantize_max >> LG_PAGE));
-	if (run_quantize_ceil_tab == NULL)
-		return (true);
-
-	for (i = 1; i <= run_quantize_max >> LG_PAGE; i++) {
-		size_t run_size = i << LG_PAGE;
-
-		run_quantize_floor_tab[i-1] =
-		    run_quantize_floor_compute(run_size);
-		run_quantize_ceil_tab[i-1] =
-		    run_quantize_ceil_compute(run_size);
-	}
-
-	return (false);
-}
-
-bool
+void
 arena_boot(void)
 {
 	unsigned i;
@@ -3822,15 +3721,6 @@ arena_boot(void)
 	nhclasses = NSIZES - nlclasses - NBINS;
 
 	bin_info_init();
-	if (small_run_size_init())
-		return (true);
-	if (run_quantize_init())
-		return (true);
-
-	runs_avail_bias = size2index(PAGE);
-	runs_avail_nclasses = size2index(run_quantize_max)+1 - runs_avail_bias;
-
-	return (false);
 }
 
 void
diff --git a/contrib/jemalloc/src/chunk.c b/contrib/jemalloc/src/chunk.c
index f292c980c51e..07e26f77c9f3 100644
--- a/contrib/jemalloc/src/chunk.c
+++ b/contrib/jemalloc/src/chunk.c
@@ -316,10 +316,11 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
 			size_t i;
 			size_t *p = (size_t *)(uintptr_t)ret;
 
-			JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size);
 			for (i = 0; i < size / sizeof(size_t); i++)
 				assert(p[i] == 0);
 		}
+		if (config_valgrind)
+			JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size);
 	}
 	return (ret);
 }
@@ -384,23 +385,21 @@ chunk_alloc_base(size_t size)
 
 void *
 chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
-    void *new_addr, size_t size, size_t alignment, bool *zero, bool dalloc_node)
+    void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit,
+    bool dalloc_node)
 {
 	void *ret;
-	bool commit;
 
 	assert(size != 0);
 	assert((size & chunksize_mask) == 0);
 	assert(alignment != 0);
 	assert((alignment & chunksize_mask) == 0);
 
-	commit = true;
 	ret = chunk_recycle(tsdn, arena, chunk_hooks,
 	    &arena->chunks_szad_cached, &arena->chunks_ad_cached, true,
-	    new_addr, size, alignment, zero, &commit, dalloc_node);
+	    new_addr, size, alignment, zero, commit, dalloc_node);
 	if (ret == NULL)
 		return (NULL);
-	assert(commit);
 	if (config_valgrind)
 		JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
 	return (ret);
@@ -610,10 +609,10 @@ chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
 }
 
 static bool
-chunk_dalloc_default_impl(tsdn_t *tsdn, void *chunk, size_t size)
+chunk_dalloc_default_impl(void *chunk, size_t size)
 {
 
-	if (!have_dss || !chunk_in_dss(tsdn, chunk))
+	if (!have_dss || !chunk_in_dss(chunk))
 		return (chunk_dalloc_mmap(chunk, size));
 	return (true);
 }
@@ -622,11 +621,8 @@ static bool
 chunk_dalloc_default(void *chunk, size_t size, bool committed,
     unsigned arena_ind)
 {
-	tsdn_t *tsdn;
 
-	tsdn = tsdn_fetch();
-
-	return (chunk_dalloc_default_impl(tsdn, chunk, size));
+	return (chunk_dalloc_default_impl(chunk, size));
 }
 
 void
@@ -644,7 +640,7 @@ chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
 	/* Try to deallocate. */
 	if (chunk_hooks->dalloc == chunk_dalloc_default) {
 		/* Call directly to propagate tsdn. */
-		err = chunk_dalloc_default_impl(tsdn, chunk, size);
+		err = chunk_dalloc_default_impl(chunk, size);
 	} else
 		err = chunk_hooks->dalloc(chunk, size, committed, arena->ind);
 
@@ -717,13 +713,12 @@ chunk_split_default(void *chunk, size_t size, size_t size_a, size_t size_b,
 }
 
 static bool
-chunk_merge_default_impl(tsdn_t *tsdn, void *chunk_a, void *chunk_b)
+chunk_merge_default_impl(void *chunk_a, void *chunk_b)
 {
 
 	if (!maps_coalesce)
 		return (true);
-	if (have_dss && chunk_in_dss(tsdn, chunk_a) != chunk_in_dss(tsdn,
-	    chunk_b))
+	if (have_dss && !chunk_dss_mergeable(chunk_a, chunk_b))
 		return (true);
 
 	return (false);
@@ -733,11 +728,8 @@ static bool
 chunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,
     bool committed, unsigned arena_ind)
 {
-	tsdn_t *tsdn;
 
-	tsdn = tsdn_fetch();
-
-	return (chunk_merge_default_impl(tsdn, chunk_a, chunk_b));
+	return (chunk_merge_default_impl(chunk_a, chunk_b));
 }
 
 static rtree_node_elm_t *
@@ -781,32 +773,11 @@ chunk_boot(void)
 	chunksize_mask = chunksize - 1;
 	chunk_npages = (chunksize >> LG_PAGE);
 
-	if (have_dss && chunk_dss_boot())
-		return (true);
+	if (have_dss)
+		chunk_dss_boot();
 	if (rtree_new(&chunks_rtree, (unsigned)((ZU(1) << (LG_SIZEOF_PTR+3)) -
 	    opt_lg_chunk), chunks_rtree_node_alloc, NULL))
 		return (true);
 
 	return (false);
 }
-
-void
-chunk_prefork(tsdn_t *tsdn)
-{
-
-	chunk_dss_prefork(tsdn);
-}
-
-void
-chunk_postfork_parent(tsdn_t *tsdn)
-{
-
-	chunk_dss_postfork_parent(tsdn);
-}
-
-void
-chunk_postfork_child(tsdn_t *tsdn)
-{
-
-	chunk_dss_postfork_child(tsdn);
-}
diff --git a/contrib/jemalloc/src/chunk_dss.c b/contrib/jemalloc/src/chunk_dss.c
index 0b1f82bde8b8..85a13548f403 100644
--- a/contrib/jemalloc/src/chunk_dss.c
+++ b/contrib/jemalloc/src/chunk_dss.c
@@ -10,20 +10,19 @@ const char	*dss_prec_names[] = {
 	"N/A"
 };
 
-/* Current dss precedence default, used when creating new arenas. */
-static dss_prec_t	dss_prec_default = DSS_PREC_DEFAULT;
-
 /*
- * Protects sbrk() calls.  This avoids malloc races among threads, though it
- * does not protect against races with threads that call sbrk() directly.
+ * Current dss precedence default, used when creating new arenas.  NB: This is
+ * stored as unsigned rather than dss_prec_t because in principle there's no
+ * guarantee that sizeof(dss_prec_t) is the same as sizeof(unsigned), and we use
+ * atomic operations to synchronize the setting.
  */
-static malloc_mutex_t	dss_mtx;
+static unsigned		dss_prec_default = (unsigned)DSS_PREC_DEFAULT;
 
 /* Base address of the DSS. */
 static void		*dss_base;
-/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */
-static void		*dss_prev;
-/* Current upper limit on DSS addresses. */
+/* Atomic boolean indicating whether the DSS is exhausted. */
+static unsigned		dss_exhausted;
+/* Atomic current upper limit on DSS addresses. */
 static void		*dss_max;
 
 /******************************************************************************/
@@ -41,30 +40,59 @@ chunk_dss_sbrk(intptr_t increment)
 }
 
 dss_prec_t
-chunk_dss_prec_get(tsdn_t *tsdn)
+chunk_dss_prec_get(void)
 {
 	dss_prec_t ret;
 
 	if (!have_dss)
 		return (dss_prec_disabled);
-	malloc_mutex_lock(tsdn, &dss_mtx);
-	ret = dss_prec_default;
-	malloc_mutex_unlock(tsdn, &dss_mtx);
+	ret = (dss_prec_t)atomic_read_u(&dss_prec_default);
 	return (ret);
 }
 
 bool
-chunk_dss_prec_set(tsdn_t *tsdn, dss_prec_t dss_prec)
+chunk_dss_prec_set(dss_prec_t dss_prec)
 {
 
 	if (!have_dss)
 		return (dss_prec != dss_prec_disabled);
-	malloc_mutex_lock(tsdn, &dss_mtx);
-	dss_prec_default = dss_prec;
-	malloc_mutex_unlock(tsdn, &dss_mtx);
+	atomic_write_u(&dss_prec_default, (unsigned)dss_prec);
 	return (false);
 }
 
+static void *
+chunk_dss_max_update(void *new_addr)
+{
+	void *max_cur;
+	spin_t spinner;
+
+	/*
+	 * Get the current end of the DSS as max_cur and assure that dss_max is
+	 * up to date.
+	 */
+	spin_init(&spinner);
+	while (true) {
+		void *max_prev = atomic_read_p(&dss_max);
+
+		max_cur = chunk_dss_sbrk(0);
+		if ((uintptr_t)max_prev > (uintptr_t)max_cur) {
+			/*
+			 * Another thread optimistically updated dss_max.  Wait
+			 * for it to finish.
+			 */
+			spin_adaptive(&spinner);
+			continue;
+		}
+		if (!atomic_cas_p(&dss_max, max_prev, max_cur))
+			break;
+	}
+	/* Fixed new_addr can only be supported if it is at the edge of DSS. */
+	if (new_addr != NULL && max_cur != new_addr)
+		return (NULL);
+
+	return (max_cur);
+}
+
 void *
 chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
     size_t alignment, bool *zero, bool *commit)
@@ -80,28 +108,20 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
 	if ((intptr_t)size < 0)
 		return (NULL);
 
-	malloc_mutex_lock(tsdn, &dss_mtx);
-	if (dss_prev != (void *)-1) {
-
+	if (!atomic_read_u(&dss_exhausted)) {
 		/*
 		 * The loop is necessary to recover from races with other
 		 * threads that are using the DSS for something other than
 		 * malloc.
 		 */
-		do {
-			void *ret, *cpad, *dss_next;
+		while (true) {
+			void *ret, *cpad, *max_cur, *dss_next, *dss_prev;
 			size_t gap_size, cpad_size;
 			intptr_t incr;
-			/* Avoid an unnecessary system call. */
-			if (new_addr != NULL && dss_max != new_addr)
-				break;
 
-			/* Get the current end of the DSS. */
-			dss_max = chunk_dss_sbrk(0);
-
-			/* Make sure the earlier condition still holds. */
-			if (new_addr != NULL && dss_max != new_addr)
-				break;
+			max_cur = chunk_dss_max_update(new_addr);
+			if (max_cur == NULL)
+				goto label_oom;
 
 			/*
 			 * Calculate how much padding is necessary to
@@ -120,17 +140,23 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
 			cpad_size = (uintptr_t)ret - (uintptr_t)cpad;
 			dss_next = (void *)((uintptr_t)ret + size);
 			if ((uintptr_t)ret < (uintptr_t)dss_max ||
-			    (uintptr_t)dss_next < (uintptr_t)dss_max) {
-				/* Wrap-around. */
-				malloc_mutex_unlock(tsdn, &dss_mtx);
-				return (NULL);
-			}
+			    (uintptr_t)dss_next < (uintptr_t)dss_max)
+				goto label_oom; /* Wrap-around. */
 			incr = gap_size + cpad_size + size;
+
+			/*
+			 * Optimistically update dss_max, and roll back below if
+			 * sbrk() fails.  No other thread will try to extend the
+			 * DSS while dss_max is greater than the current DSS
+			 * max reported by sbrk(0).
+			 */
+			if (atomic_cas_p(&dss_max, max_cur, dss_next))
+				continue;
+
+			/* Try to allocate. */
 			dss_prev = chunk_dss_sbrk(incr);
-			if (dss_prev == dss_max) {
+			if (dss_prev == max_cur) {
 				/* Success. */
-				dss_max = dss_next;
-				malloc_mutex_unlock(tsdn, &dss_mtx);
 				if (cpad_size != 0) {
 					chunk_hooks_t chunk_hooks =
 					    CHUNK_HOOKS_INITIALIZER;
@@ -147,68 +173,65 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
 					*commit = pages_decommit(ret, size);
 				return (ret);
 			}
-		} while (dss_prev != (void *)-1);
-	}
-	malloc_mutex_unlock(tsdn, &dss_mtx);
 
+			/*
+			 * Failure, whether due to OOM or a race with a raw
+			 * sbrk() call from outside the allocator.  Try to roll
+			 * back optimistic dss_max update; if rollback fails,
+			 * it's due to another caller of this function having
+			 * succeeded since this invocation started, in which
+			 * case rollback is not necessary.
+			 */
+			atomic_cas_p(&dss_max, dss_next, max_cur);
+			if (dss_prev == (void *)-1) {
+				/* OOM. */
+				atomic_write_u(&dss_exhausted, (unsigned)true);
+				goto label_oom;
+			}
+		}
+	}
+label_oom:
 	return (NULL);
 }
 
-bool
-chunk_in_dss(tsdn_t *tsdn, void *chunk)
+static bool
+chunk_in_dss_helper(void *chunk, void *max)
 {
-	bool ret;
 
-	cassert(have_dss);
-
-	malloc_mutex_lock(tsdn, &dss_mtx);
-	if ((uintptr_t)chunk >= (uintptr_t)dss_base
-	    && (uintptr_t)chunk < (uintptr_t)dss_max)
-		ret = true;
-	else
-		ret = false;
-	malloc_mutex_unlock(tsdn, &dss_mtx);
-
-	return (ret);
+	return ((uintptr_t)chunk >= (uintptr_t)dss_base && (uintptr_t)chunk <
+	    (uintptr_t)max);
 }
 
 bool
+chunk_in_dss(void *chunk)
+{
+
+	cassert(have_dss);
+
+	return (chunk_in_dss_helper(chunk, atomic_read_p(&dss_max)));
+}
+
+bool
+chunk_dss_mergeable(void *chunk_a, void *chunk_b)
+{
+	void *max;
+
+	cassert(have_dss);
+
+	max = atomic_read_p(&dss_max);
+	return (chunk_in_dss_helper(chunk_a, max) ==
+	    chunk_in_dss_helper(chunk_b, max));
+}
+
+void
 chunk_dss_boot(void)
 {
 
 	cassert(have_dss);
 
-	if (malloc_mutex_init(&dss_mtx, "dss", WITNESS_RANK_DSS))
-		return (true);
 	dss_base = chunk_dss_sbrk(0);
-	dss_prev = dss_base;
+	dss_exhausted = (unsigned)(dss_base == (void *)-1);
 	dss_max = dss_base;
-
-	return (false);
-}
-
-void
-chunk_dss_prefork(tsdn_t *tsdn)
-{
-
-	if (have_dss)
-		malloc_mutex_prefork(tsdn, &dss_mtx);
-}
-
-void
-chunk_dss_postfork_parent(tsdn_t *tsdn)
-{
-
-	if (have_dss)
-		malloc_mutex_postfork_parent(tsdn, &dss_mtx);
-}
-
-void
-chunk_dss_postfork_child(tsdn_t *tsdn)
-{
-
-	if (have_dss)
-		malloc_mutex_postfork_child(tsdn, &dss_mtx);
 }
 
 /******************************************************************************/
diff --git a/contrib/jemalloc/src/ckh.c b/contrib/jemalloc/src/ckh.c
index 747c1c865fa3..159bd8ae1618 100644
--- a/contrib/jemalloc/src/ckh.c
+++ b/contrib/jemalloc/src/ckh.c
@@ -40,8 +40,8 @@
 /******************************************************************************/
 /* Function prototypes for non-inline static functions. */
 
-static bool	ckh_grow(tsdn_t *tsdn, ckh_t *ckh);
-static void	ckh_shrink(tsdn_t *tsdn, ckh_t *ckh);
+static bool	ckh_grow(tsd_t *tsd, ckh_t *ckh);
+static void	ckh_shrink(tsd_t *tsd, ckh_t *ckh);
 
 /******************************************************************************/
 
@@ -99,7 +99,8 @@ ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key,
 	 * Cycle through the cells in the bucket, starting at a random position.
 	 * The randomness avoids worst-case search overhead as buckets fill up.
 	 */
-	offset = (unsigned)prng_lg_range(&ckh->prng_state, LG_CKH_BUCKET_CELLS);
+	offset = (unsigned)prng_lg_range_u64(&ckh->prng_state,
+	    LG_CKH_BUCKET_CELLS);
 	for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {
 		cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +
 		    ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];
@@ -141,7 +142,7 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,
 		 * were an item for which both hashes indicated the same
 		 * bucket.
 		 */
-		i = (unsigned)prng_lg_range(&ckh->prng_state,
+		i = (unsigned)prng_lg_range_u64(&ckh->prng_state,
 		    LG_CKH_BUCKET_CELLS);
 		cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];
 		assert(cell->key != NULL);
@@ -244,7 +245,7 @@ ckh_rebuild(ckh_t *ckh, ckhc_t *aTab)
 }
 
 static bool
-ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
+ckh_grow(tsd_t *tsd, ckh_t *ckh)
 {
 	bool ret;
 	ckhc_t *tab, *ttab;
@@ -270,8 +271,8 @@ ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
 			ret = true;
 			goto label_return;
 		}
-		tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL,
-		    true, arena_ichoose(tsdn, NULL));
+		tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE,
+		    true, NULL, true, arena_ichoose(tsd, NULL));
 		if (tab == NULL) {
 			ret = true;
 			goto label_return;
@@ -283,12 +284,12 @@ ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
 		ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
 
 		if (!ckh_rebuild(ckh, tab)) {
-			idalloctm(tsdn, tab, NULL, true, true);
+			idalloctm(tsd_tsdn(tsd), tab, NULL, true, true);
 			break;
 		}
 
 		/* Rebuilding failed, so back out partially rebuilt table. */
-		idalloctm(tsdn, ckh->tab, NULL, true, true);
+		idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, true, true);
 		ckh->tab = tab;
 		ckh->lg_curbuckets = lg_prevbuckets;
 	}
@@ -299,7 +300,7 @@ ckh_grow(tsdn_t *tsdn, ckh_t *ckh)
 }
 
 static void
-ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
+ckh_shrink(tsd_t *tsd, ckh_t *ckh)
 {
 	ckhc_t *tab, *ttab;
 	size_t usize;
@@ -314,8 +315,8 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
 	usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);
 	if (unlikely(usize == 0 || usize > HUGE_MAXCLASS))
 		return;
-	tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL, true,
-	    arena_ichoose(tsdn, NULL));
+	tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true, NULL,
+	    true, arena_ichoose(tsd, NULL));
 	if (tab == NULL) {
 		/*
 		 * An OOM error isn't worth propagating, since it doesn't
@@ -330,7 +331,7 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
 	ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
 
 	if (!ckh_rebuild(ckh, tab)) {
-		idalloctm(tsdn, tab, NULL, true, true);
+		idalloctm(tsd_tsdn(tsd), tab, NULL, true, true);
 #ifdef CKH_COUNT
 		ckh->nshrinks++;
 #endif
@@ -338,7 +339,7 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
 	}
 
 	/* Rebuilding failed, so back out partially rebuilt table. */
-	idalloctm(tsdn, ckh->tab, NULL, true, true);
+	idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, true, true);
 	ckh->tab = tab;
 	ckh->lg_curbuckets = lg_prevbuckets;
 #ifdef CKH_COUNT
@@ -347,7 +348,7 @@ ckh_shrink(tsdn_t *tsdn, ckh_t *ckh)
 }
 
 bool
-ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
+ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
     ckh_keycomp_t *keycomp)
 {
 	bool ret;
@@ -391,8 +392,8 @@ ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
 		ret = true;
 		goto label_return;
 	}
-	ckh->tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL,
-	    true, arena_ichoose(tsdn, NULL));
+	ckh->tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true,
+	    NULL, true, arena_ichoose(tsd, NULL));
 	if (ckh->tab == NULL) {
 		ret = true;
 		goto label_return;
@@ -404,7 +405,7 @@ ckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
 }
 
 void
-ckh_delete(tsdn_t *tsdn, ckh_t *ckh)
+ckh_delete(tsd_t *tsd, ckh_t *ckh)
 {
 
 	assert(ckh != NULL);
@@ -421,7 +422,7 @@ ckh_delete(tsdn_t *tsdn, ckh_t *ckh)
 	    (unsigned long long)ckh->nrelocs);
 #endif
 
-	idalloctm(tsdn, ckh->tab, NULL, true, true);
+	idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, true, true);
 	if (config_debug)
 		memset(ckh, JEMALLOC_FREE_JUNK, sizeof(ckh_t));
 }
@@ -456,7 +457,7 @@ ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data)
 }
 
 bool
-ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data)
+ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data)
 {
 	bool ret;
 
@@ -468,7 +469,7 @@ ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data)
 #endif
 
 	while (ckh_try_insert(ckh, &key, &data)) {
-		if (ckh_grow(tsdn, ckh)) {
+		if (ckh_grow(tsd, ckh)) {
 			ret = true;
 			goto label_return;
 		}
@@ -480,7 +481,7 @@ ckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data)
 }
 
 bool
-ckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,
+ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key,
     void **data)
 {
 	size_t cell;
@@ -502,7 +503,7 @@ ckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,
 		    + LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets
 		    > ckh->lg_minbuckets) {
 			/* Ignore error due to OOM. */
-			ckh_shrink(tsdn, ckh);
+			ckh_shrink(tsd, ckh);
 		}
 
 		return (false);
diff --git a/contrib/jemalloc/src/ctl.c b/contrib/jemalloc/src/ctl.c
index dad800861679..bc78b20558a5 100644
--- a/contrib/jemalloc/src/ctl.c
+++ b/contrib/jemalloc/src/ctl.c
@@ -1478,7 +1478,7 @@ tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
 
 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
 	READONLY();
-	if (tcaches_create(tsd_tsdn(tsd), &tcache_ind)) {
+	if (tcaches_create(tsd, &tcache_ind)) {
 		ret = EFAULT;
 		goto label_return;
 	}
@@ -1685,11 +1685,11 @@ arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
 		dss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);
 	} else {
 		if (dss_prec != dss_prec_limit &&
-		    chunk_dss_prec_set(tsd_tsdn(tsd), dss_prec)) {
+		    chunk_dss_prec_set(dss_prec)) {
 			ret = EFAULT;
 			goto label_return;
 		}
-		dss_prec_old = chunk_dss_prec_get(tsd_tsdn(tsd));
+		dss_prec_old = chunk_dss_prec_get();
 	}
 
 	dss = dss_prec_names[dss_prec_old];
@@ -2100,7 +2100,7 @@ prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
 	if (lg_sample >= (sizeof(uint64_t) << 3))
 		lg_sample = (sizeof(uint64_t) << 3) - 1;
 
-	prof_reset(tsd_tsdn(tsd), lg_sample);
+	prof_reset(tsd, lg_sample);
 
 	ret = 0;
 label_return:
diff --git a/contrib/jemalloc/src/huge.c b/contrib/jemalloc/src/huge.c
index 3a2877ca8d6e..62e6932b7f00 100644
--- a/contrib/jemalloc/src/huge.c
+++ b/contrib/jemalloc/src/huge.c
@@ -54,6 +54,7 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
 {
 	void *ret;
 	size_t ausize;
+	arena_t *iarena;
 	extent_node_t *node;
 	bool is_zeroed;
 
@@ -67,8 +68,9 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
 	assert(ausize >= chunksize);
 
 	/* Allocate an extent node with which to track the chunk. */
+	iarena = (!tsdn_null(tsdn)) ? arena_ichoose(tsdn_tsd(tsdn), NULL) : a0get();
 	node = ipallocztm(tsdn, CACHELINE_CEILING(sizeof(extent_node_t)),
-	    CACHELINE, false, NULL, true, arena_ichoose(tsdn, arena));
+	    CACHELINE, false, NULL, true, iarena);
 	if (node == NULL)
 		return (NULL);
 
@@ -114,7 +116,7 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
 #define	huge_dalloc_junk JEMALLOC_N(huge_dalloc_junk_impl)
 #endif
 static void
-huge_dalloc_junk(tsdn_t *tsdn, void *ptr, size_t usize)
+huge_dalloc_junk(void *ptr, size_t usize)
 {
 
 	if (config_fill && have_dss && unlikely(opt_junk_free)) {
@@ -122,7 +124,7 @@ huge_dalloc_junk(tsdn_t *tsdn, void *ptr, size_t usize)
 		 * Only bother junk filling if the chunk isn't about to be
 		 * unmapped.
 		 */
-		if (!config_munmap || (have_dss && chunk_in_dss(tsdn, ptr)))
+		if (!config_munmap || (have_dss && chunk_in_dss(ptr)))
 			memset(ptr, JEMALLOC_FREE_JUNK, usize);
 	}
 }
@@ -221,7 +223,7 @@ huge_ralloc_no_move_shrink(tsdn_t *tsdn, void *ptr, size_t oldsize,
 	if (oldsize > usize) {
 		size_t sdiff = oldsize - usize;
 		if (config_fill && unlikely(opt_junk_free)) {
-			huge_dalloc_junk(tsdn, (void *)((uintptr_t)ptr + usize),
+			huge_dalloc_junk((void *)((uintptr_t)ptr + usize),
 			    sdiff);
 			post_zeroed = false;
 		} else {
@@ -402,7 +404,7 @@ huge_dalloc(tsdn_t *tsdn, void *ptr)
 	ql_remove(&arena->huge, node, ql_link);
 	malloc_mutex_unlock(tsdn, &arena->huge_mtx);
 
-	huge_dalloc_junk(tsdn, extent_node_addr_get(node),
+	huge_dalloc_junk(extent_node_addr_get(node),
 	    extent_node_size_get(node));
 	arena_chunk_dalloc_huge(tsdn, extent_node_arena_get(node),
 	    extent_node_addr_get(node), extent_node_size_get(node));
diff --git a/contrib/jemalloc/src/jemalloc.c b/contrib/jemalloc/src/jemalloc.c
index 46dd1d12110e..f659b55c395a 100644
--- a/contrib/jemalloc/src/jemalloc.c
+++ b/contrib/jemalloc/src/jemalloc.c
@@ -9,7 +9,11 @@ const char	*__malloc_options_1_0 = NULL;
 __sym_compat(_malloc_options, __malloc_options_1_0, FBSD_1.0);
 
 /* Runtime configuration options. */
-const char	*je_malloc_conf JEMALLOC_ATTR(weak);
+const char	*je_malloc_conf
+#ifndef _WIN32
+    JEMALLOC_ATTR(weak)
+#endif
+    ;
 bool	opt_abort =
 #ifdef JEMALLOC_DEBUG
     true
@@ -89,14 +93,25 @@ enum {
 };
 static uint8_t	malloc_slow_flags;
 
-/* Last entry for overflow detection only.  */
 JEMALLOC_ALIGNED(CACHELINE)
-const size_t	index2size_tab[NSIZES+1] = {
-#define	SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \
+const size_t	pind2sz_tab[NPSIZES] = {
+#define	PSZ_yes(lg_grp, ndelta, lg_delta)				\
+	(((ZU(1)<= 2.6 has the CPU_COUNT macro.
+	 *
+	 * glibc's sysconf() uses isspace().  glibc allocates for the first time
+	 * *before* setting up the isspace tables.  Therefore we need a
+	 * different method to get the number of CPUs.
+	 */
+	{
+		cpu_set_t set;
+
+		pthread_getaffinity_np(pthread_self(), sizeof(set), &set);
+		result = CPU_COUNT(&set);
+	}
 #else
 	result = sysconf(_SC_NPROCESSORS_ONLN);
 #endif
@@ -1107,8 +1144,7 @@ malloc_conf_init(void)
 				for (i = 0; i < dss_prec_limit; i++) {
 					if (strncmp(dss_prec_names[i], v, vlen)
 					    == 0) {
-						if (chunk_dss_prec_set(NULL,
-						   i)) {
+						if (chunk_dss_prec_set(i)) {
 							malloc_conf_error(
 							    "Error setting dss",
 							    k, klen, v, vlen);
@@ -1153,9 +1189,20 @@ malloc_conf_init(void)
 			if (config_fill) {
 				if (CONF_MATCH("junk")) {
 					if (CONF_MATCH_VALUE("true")) {
-						opt_junk = "true";
-						opt_junk_alloc = opt_junk_free =
-						    true;
+						if (config_valgrind &&
+						    unlikely(in_valgrind)) {
+							malloc_conf_error(
+							"Deallocation-time "
+							"junk filling cannot "
+							"be enabled while "
+							"running inside "
+							"Valgrind", k, klen, v,
+							vlen);
+						} else {
+							opt_junk = "true";
+							opt_junk_alloc = true;
+							opt_junk_free = true;
+						}
 					} else if (CONF_MATCH_VALUE("false")) {
 						opt_junk = "false";
 						opt_junk_alloc = opt_junk_free =
@@ -1165,9 +1212,20 @@ malloc_conf_init(void)
 						opt_junk_alloc = true;
 						opt_junk_free = false;
 					} else if (CONF_MATCH_VALUE("free")) {
-						opt_junk = "free";
-						opt_junk_alloc = false;
-						opt_junk_free = true;
+						if (config_valgrind &&
+						    unlikely(in_valgrind)) {
+							malloc_conf_error(
+							"Deallocation-time "
+							"junk filling cannot "
+							"be enabled while "
+							"running inside "
+							"Valgrind", k, klen, v,
+							vlen);
+						} else {
+							opt_junk = "free";
+							opt_junk_alloc = false;
+							opt_junk_free = true;
+						}
 					} else {
 						malloc_conf_error(
 						    "Invalid conf value", k,
@@ -1253,11 +1311,14 @@ malloc_init_hard_needed(void)
 	}
 #ifdef JEMALLOC_THREADED_INIT
 	if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {
+		spin_t spinner;
+
 		/* Busy-wait until the initializing thread completes. */
+		spin_init(&spinner);
 		do {
-			malloc_mutex_unlock(NULL, &init_lock);
-			CPU_SPINWAIT;
-			malloc_mutex_lock(NULL, &init_lock);
+			malloc_mutex_unlock(TSDN_NULL, &init_lock);
+			spin_adaptive(&spinner);
+			malloc_mutex_lock(TSDN_NULL, &init_lock);
 		} while (!malloc_initialized());
 		return (false);
 	}
@@ -1291,8 +1352,7 @@ malloc_init_hard_a0_locked()
 		return (true);
 	if (config_prof)
 		prof_boot1();
-	if (arena_boot())
-		return (true);
+	arena_boot();
 	if (config_tcache && tcache_boot(TSDN_NULL))
 		return (true);
 	if (malloc_mutex_init(&arenas_lock, "arenas", WITNESS_RANK_ARENAS))
@@ -1423,7 +1483,7 @@ malloc_init_hard(void)
 		return (true);
 	malloc_mutex_lock(tsd_tsdn(tsd), &init_lock);
 
-	if (config_prof && prof_boot2(tsd_tsdn(tsd))) {
+	if (config_prof && prof_boot2(tsd)) {
 		malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);
 		return (true);
 	}
@@ -1998,6 +2058,29 @@ JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;
 JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =
     je_memalign;
 # endif
+
+#ifdef CPU_COUNT
+/*
+ * To enable static linking with glibc, the libc specific malloc interface must
+ * be implemented also, so none of glibc's malloc.o functions are added to the
+ * link.
+ */
+#define	ALIAS(je_fn)	__attribute__((alias (#je_fn), used))
+/* To force macro expansion of je_ prefix before stringification. */
+#define	PREALIAS(je_fn)  ALIAS(je_fn)
+void	*__libc_malloc(size_t size) PREALIAS(je_malloc);
+void	__libc_free(void* ptr) PREALIAS(je_free);
+void	*__libc_realloc(void* ptr, size_t size) PREALIAS(je_realloc);
+void	*__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc);
+void	*__libc_memalign(size_t align, size_t s) PREALIAS(je_memalign);
+void	*__libc_valloc(size_t size) PREALIAS(je_valloc);
+int	__posix_memalign(void** r, size_t a, size_t s)
+    PREALIAS(je_posix_memalign);
+#undef PREALIAS
+#undef ALIAS
+
+#endif
+
 #endif
 
 /*
@@ -2852,7 +2935,6 @@ _malloc_prefork(void)
 		}
 	}
 	base_prefork(tsd_tsdn(tsd));
-	chunk_prefork(tsd_tsdn(tsd));
 	for (i = 0; i < narenas; i++) {
 		if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
 			arena_prefork3(tsd_tsdn(tsd), arena);
@@ -2881,7 +2963,6 @@ _malloc_postfork(void)
 
 	witness_postfork_parent(tsd);
 	/* Release all mutexes, now that fork() has completed. */
-	chunk_postfork_parent(tsd_tsdn(tsd));
 	base_postfork_parent(tsd_tsdn(tsd));
 	for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
 		arena_t *arena;
@@ -2906,7 +2987,6 @@ jemalloc_postfork_child(void)
 
 	witness_postfork_child(tsd);
 	/* Release all mutexes, now that fork() has completed. */
-	chunk_postfork_child(tsd_tsdn(tsd));
 	base_postfork_child(tsd_tsdn(tsd));
 	for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
 		arena_t *arena;
diff --git a/contrib/jemalloc/src/mutex.c b/contrib/jemalloc/src/mutex.c
index a24e42012d6c..13f8d799de1e 100644
--- a/contrib/jemalloc/src/mutex.c
+++ b/contrib/jemalloc/src/mutex.c
@@ -91,6 +91,8 @@ malloc_mutex_init(malloc_mutex_t *mutex, const char *name, witness_rank_t rank)
 	    _CRT_SPINCOUNT))
 		return (true);
 #  endif
+#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
+	mutex->lock = OS_UNFAIR_LOCK_INIT;
 #elif (defined(JEMALLOC_OSSPIN))
 	mutex->lock = 0;
 #elif (defined(JEMALLOC_MUTEX_INIT_CB))
diff --git a/contrib/jemalloc/src/nstime.c b/contrib/jemalloc/src/nstime.c
index aad2c260e66c..0948e29faffa 100644
--- a/contrib/jemalloc/src/nstime.c
+++ b/contrib/jemalloc/src/nstime.c
@@ -97,6 +97,76 @@ nstime_divide(const nstime_t *time, const nstime_t *divisor)
 	return (time->ns / divisor->ns);
 }
 
+#ifdef _WIN32
+#  define NSTIME_MONOTONIC true
+static void
+nstime_get(nstime_t *time)
+{
+	FILETIME ft;
+	uint64_t ticks_100ns;
+
+	GetSystemTimeAsFileTime(&ft);
+	ticks_100ns = (((uint64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+
+	nstime_init(time, ticks_100ns * 100);
+}
+#elif JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE
+#  define NSTIME_MONOTONIC true
+static void
+nstime_get(nstime_t *time)
+{
+	struct timespec ts;
+
+	clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
+	nstime_init2(time, ts.tv_sec, ts.tv_nsec);
+}
+#elif JEMALLOC_HAVE_CLOCK_MONOTONIC
+#  define NSTIME_MONOTONIC true
+static void
+nstime_get(nstime_t *time)
+{
+	struct timespec ts;
+
+	clock_gettime(CLOCK_MONOTONIC, &ts);
+	nstime_init2(time, ts.tv_sec, ts.tv_nsec);
+}
+#elif JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
+#  define NSTIME_MONOTONIC true
+static void
+nstime_get(nstime_t *time)
+{
+
+	nstime_init(time, mach_absolute_time());
+}
+#else
+#  define NSTIME_MONOTONIC false
+static void
+nstime_get(nstime_t *time)
+{
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+	nstime_init2(time, tv.tv_sec, tv.tv_usec * 1000);
+}
+#endif
+
+#ifdef JEMALLOC_JET
+#undef nstime_monotonic
+#define	nstime_monotonic JEMALLOC_N(n_nstime_monotonic)
+#endif
+bool
+nstime_monotonic(void)
+{
+
+	return (NSTIME_MONOTONIC);
+#undef NSTIME_MONOTONIC
+}
+#ifdef JEMALLOC_JET
+#undef nstime_monotonic
+#define	nstime_monotonic JEMALLOC_N(nstime_monotonic)
+nstime_monotonic_t *nstime_monotonic = JEMALLOC_N(n_nstime_monotonic);
+#endif
+
 #ifdef JEMALLOC_JET
 #undef nstime_update
 #define	nstime_update JEMALLOC_N(n_nstime_update)
@@ -107,33 +177,7 @@ nstime_update(nstime_t *time)
 	nstime_t old_time;
 
 	nstime_copy(&old_time, time);
-
-#ifdef _WIN32
-	{
-		FILETIME ft;
-		uint64_t ticks;
-		GetSystemTimeAsFileTime(&ft);
-		ticks = (((uint64_t)ft.dwHighDateTime) << 32) |
-		    ft.dwLowDateTime;
-		time->ns = ticks * 100;
-	}
-#elif JEMALLOC_CLOCK_GETTIME
-	{
-		struct timespec ts;
-
-		if (sysconf(_SC_MONOTONIC_CLOCK) > 0)
-			clock_gettime(CLOCK_MONOTONIC, &ts);
-		else
-			clock_gettime(CLOCK_REALTIME, &ts);
-		time->ns = ts.tv_sec * BILLION + ts.tv_nsec;
-	}
-#else
-	{
-		struct timeval tv;
-		gettimeofday(&tv, NULL);
-		time->ns = tv.tv_sec * BILLION + tv.tv_usec * 1000;
-	}
-#endif
+	nstime_get(time);
 
 	/* Handle non-monotonic clocks. */
 	if (unlikely(nstime_compare(&old_time, time) > 0)) {
diff --git a/contrib/jemalloc/src/pages.c b/contrib/jemalloc/src/pages.c
index 2a9b7e374cd0..647952ac3ef6 100644
--- a/contrib/jemalloc/src/pages.c
+++ b/contrib/jemalloc/src/pages.c
@@ -207,6 +207,11 @@ os_overcommits_sysctl(void)
 #endif
 
 #ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
+/*
+ * Use syscall(2) rather than {open,read,close}(2) when possible to avoid
+ * reentry during bootstrapping if another library has interposed system call
+ * wrappers.
+ */
 static bool
 os_overcommits_proc(void)
 {
@@ -214,11 +219,26 @@ os_overcommits_proc(void)
 	char buf[1];
 	ssize_t nread;
 
+#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_open)
+	fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY);
+#else
 	fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
+#endif
 	if (fd == -1)
 		return (false); /* Error. */
 
+#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_read)
+	nread = (ssize_t)syscall(SYS_read, fd, &buf, sizeof(buf));
+#else
 	nread = read(fd, &buf, sizeof(buf));
+#endif
+
+#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_close)
+	syscall(SYS_close, fd);
+#else
+	close(fd);
+#endif
+
 	if (nread < 1)
 		return (false); /* Error. */
 	/*
diff --git a/contrib/jemalloc/src/prof.c b/contrib/jemalloc/src/prof.c
index c1f58d462bec..c89dade1f192 100644
--- a/contrib/jemalloc/src/prof.c
+++ b/contrib/jemalloc/src/prof.c
@@ -125,7 +125,7 @@ static bool	prof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx);
 static void	prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx);
 static bool	prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
     bool even_if_attached);
-static void	prof_tdata_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
+static void	prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata,
     bool even_if_attached);
 static char	*prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name);
 
@@ -591,7 +591,7 @@ prof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx,
 	assert(gctx->nlimbo != 0);
 	if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) {
 		/* Remove gctx from bt2gctx. */
-		if (ckh_remove(tsd_tsdn(tsd), &bt2gctx, &gctx->bt, NULL, NULL))
+		if (ckh_remove(tsd, &bt2gctx, &gctx->bt, NULL, NULL))
 			not_reached();
 		prof_leave(tsd, tdata_self);
 		/* Destroy gctx. */
@@ -651,7 +651,7 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)
 	assert(tctx->cnts.accumobjs == 0);
 	assert(tctx->cnts.accumbytes == 0);
 
-	ckh_remove(tsd_tsdn(tsd), &tdata->bt2tctx, &gctx->bt, NULL, NULL);
+	ckh_remove(tsd, &tdata->bt2tctx, &gctx->bt, NULL, NULL);
 	destroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata, false);
 	malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
 
@@ -704,7 +704,7 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)
 	malloc_mutex_assert_not_owner(tsd_tsdn(tsd), tctx->tdata->lock);
 
 	if (destroy_tdata)
-		prof_tdata_destroy(tsd_tsdn(tsd), tdata, false);
+		prof_tdata_destroy(tsd, tdata, false);
 
 	if (destroy_tctx)
 		idalloctm(tsd_tsdn(tsd), tctx, NULL, true, true);
@@ -733,7 +733,7 @@ prof_lookup_global(tsd_t *tsd, prof_bt_t *bt, prof_tdata_t *tdata,
 			return (true);
 		}
 		btkey.p = &gctx.p->bt;
-		if (ckh_insert(tsd_tsdn(tsd), &bt2gctx, btkey.v, gctx.v)) {
+		if (ckh_insert(tsd, &bt2gctx, btkey.v, gctx.v)) {
 			/* OOM. */
 			prof_leave(tsd, tdata);
 			idalloctm(tsd_tsdn(tsd), gctx.v, NULL, true, true);
@@ -795,7 +795,7 @@ prof_lookup(tsd_t *tsd, prof_bt_t *bt)
 		/* Link a prof_tctx_t into gctx for this thread. */
 		ret.v = iallocztm(tsd_tsdn(tsd), sizeof(prof_tctx_t),
 		    size2index(sizeof(prof_tctx_t)), false, NULL, true,
-		    arena_ichoose(tsd_tsdn(tsd), NULL), true);
+		    arena_ichoose(tsd, NULL), true);
 		if (ret.p == NULL) {
 			if (new_gctx)
 				prof_gctx_try_destroy(tsd, tdata, gctx, tdata);
@@ -810,8 +810,7 @@ prof_lookup(tsd_t *tsd, prof_bt_t *bt)
 		ret.p->prepared = true;
 		ret.p->state = prof_tctx_state_initializing;
 		malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock);
-		error = ckh_insert(tsd_tsdn(tsd), &tdata->bt2tctx, btkey,
-		    ret.v);
+		error = ckh_insert(tsd, &tdata->bt2tctx, btkey, ret.v);
 		malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
 		if (error) {
 			if (new_gctx)
@@ -875,7 +874,7 @@ prof_sample_threshold_update(prof_tdata_t *tdata)
 	 *   pp 500
 	 *   (http://luc.devroye.org/rnbookindex.html)
 	 */
-	r = prng_lg_range(&tdata->prng_state, 53);
+	r = prng_lg_range_u64(&tdata->prng_state, 53);
 	u = (double)r * (1.0/9007199254740992.0L);
 	tdata->bytes_until_sample = (uint64_t)(log(u) /
 	    log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample))))
@@ -1791,7 +1790,7 @@ prof_thr_uid_alloc(tsdn_t *tsdn)
 }
 
 static prof_tdata_t *
-prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
+prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid, uint64_t thr_discrim,
     char *thread_name, bool active)
 {
 	prof_tdata_t *tdata;
@@ -1799,7 +1798,7 @@ prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
 	cassert(config_prof);
 
 	/* Initialize an empty cache for this thread. */
-	tdata = (prof_tdata_t *)iallocztm(tsdn, sizeof(prof_tdata_t),
+	tdata = (prof_tdata_t *)iallocztm(tsd_tsdn(tsd), sizeof(prof_tdata_t),
 	    size2index(sizeof(prof_tdata_t)), false, NULL, true,
 	    arena_get(TSDN_NULL, 0, true), true);
 	if (tdata == NULL)
@@ -1813,9 +1812,9 @@ prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
 	tdata->expired = false;
 	tdata->tctx_uid_next = 0;
 
-	if (ckh_new(tsdn, &tdata->bt2tctx, PROF_CKH_MINITEMS,
-	    prof_bt_hash, prof_bt_keycomp)) {
-		idalloctm(tsdn, tdata, NULL, true, true);
+	if (ckh_new(tsd, &tdata->bt2tctx, PROF_CKH_MINITEMS, prof_bt_hash,
+	    prof_bt_keycomp)) {
+		idalloctm(tsd_tsdn(tsd), tdata, NULL, true, true);
 		return (NULL);
 	}
 
@@ -1829,19 +1828,19 @@ prof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,
 	tdata->dumping = false;
 	tdata->active = active;
 
-	malloc_mutex_lock(tsdn, &tdatas_mtx);
+	malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);
 	tdata_tree_insert(&tdatas, tdata);
-	malloc_mutex_unlock(tsdn, &tdatas_mtx);
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);
 
 	return (tdata);
 }
 
 prof_tdata_t *
-prof_tdata_init(tsdn_t *tsdn)
+prof_tdata_init(tsd_t *tsd)
 {
 
-	return (prof_tdata_init_impl(tsdn, prof_thr_uid_alloc(tsdn), 0, NULL,
-	    prof_thread_active_init_get(tsdn)));
+	return (prof_tdata_init_impl(tsd, prof_thr_uid_alloc(tsd_tsdn(tsd)), 0,
+	    NULL, prof_thread_active_init_get(tsd_tsdn(tsd))));
 }
 
 static bool
@@ -1866,31 +1865,29 @@ prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,
 }
 
 static void
-prof_tdata_destroy_locked(tsdn_t *tsdn, prof_tdata_t *tdata,
+prof_tdata_destroy_locked(tsd_t *tsd, prof_tdata_t *tdata,
     bool even_if_attached)
 {
 
-	malloc_mutex_assert_owner(tsdn, &tdatas_mtx);
-
-	assert(tsdn_null(tsdn) || tsd_prof_tdata_get(tsdn_tsd(tsdn)) != tdata);
+	malloc_mutex_assert_owner(tsd_tsdn(tsd), &tdatas_mtx);
 
 	tdata_tree_remove(&tdatas, tdata);
 
 	assert(prof_tdata_should_destroy_unlocked(tdata, even_if_attached));
 
 	if (tdata->thread_name != NULL)
-		idalloctm(tsdn, tdata->thread_name, NULL, true, true);
-	ckh_delete(tsdn, &tdata->bt2tctx);
-	idalloctm(tsdn, tdata, NULL, true, true);
+		idalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, true, true);
+	ckh_delete(tsd, &tdata->bt2tctx);
+	idalloctm(tsd_tsdn(tsd), tdata, NULL, true, true);
 }
 
 static void
-prof_tdata_destroy(tsdn_t *tsdn, prof_tdata_t *tdata, bool even_if_attached)
+prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata, bool even_if_attached)
 {
 
-	malloc_mutex_lock(tsdn, &tdatas_mtx);
-	prof_tdata_destroy_locked(tsdn, tdata, even_if_attached);
-	malloc_mutex_unlock(tsdn, &tdatas_mtx);
+	malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);
+	prof_tdata_destroy_locked(tsd, tdata, even_if_attached);
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);
 }
 
 static void
@@ -1913,7 +1910,7 @@ prof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata)
 		destroy_tdata = false;
 	malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);
 	if (destroy_tdata)
-		prof_tdata_destroy(tsd_tsdn(tsd), tdata, true);
+		prof_tdata_destroy(tsd, tdata, true);
 }
 
 prof_tdata_t *
@@ -1926,8 +1923,8 @@ prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata)
 	bool active = tdata->active;
 
 	prof_tdata_detach(tsd, tdata);
-	return (prof_tdata_init_impl(tsd_tsdn(tsd), thr_uid, thr_discrim,
-	    thread_name, active));
+	return (prof_tdata_init_impl(tsd, thr_uid, thr_discrim, thread_name,
+	    active));
 }
 
 static bool
@@ -1956,30 +1953,30 @@ prof_tdata_reset_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)
 }
 
 void
-prof_reset(tsdn_t *tsdn, size_t lg_sample)
+prof_reset(tsd_t *tsd, size_t lg_sample)
 {
 	prof_tdata_t *next;
 
 	assert(lg_sample < (sizeof(uint64_t) << 3));
 
-	malloc_mutex_lock(tsdn, &prof_dump_mtx);
-	malloc_mutex_lock(tsdn, &tdatas_mtx);
+	malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_mtx);
+	malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);
 
 	lg_prof_sample = lg_sample;
 
 	next = NULL;
 	do {
 		prof_tdata_t *to_destroy = tdata_tree_iter(&tdatas, next,
-		    prof_tdata_reset_iter, (void *)tsdn);
+		    prof_tdata_reset_iter, (void *)tsd);
 		if (to_destroy != NULL) {
 			next = tdata_tree_next(&tdatas, to_destroy);
-			prof_tdata_destroy_locked(tsdn, to_destroy, false);
+			prof_tdata_destroy_locked(tsd, to_destroy, false);
 		} else
 			next = NULL;
 	} while (next != NULL);
 
-	malloc_mutex_unlock(tsdn, &tdatas_mtx);
-	malloc_mutex_unlock(tsdn, &prof_dump_mtx);
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);
+	malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx);
 }
 
 void
@@ -2189,7 +2186,7 @@ prof_boot1(void)
 }
 
 bool
-prof_boot2(tsdn_t *tsdn)
+prof_boot2(tsd_t *tsd)
 {
 
 	cassert(config_prof);
@@ -2215,7 +2212,7 @@ prof_boot2(tsdn_t *tsdn)
 		    WITNESS_RANK_PROF_THREAD_ACTIVE_INIT))
 			return (true);
 
-		if (ckh_new(tsdn, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash,
+		if (ckh_new(tsd, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash,
 		    prof_bt_keycomp))
 			return (true);
 		if (malloc_mutex_init(&bt2gctx_mtx, "prof_bt2gctx",
@@ -2246,8 +2243,8 @@ prof_boot2(tsdn_t *tsdn)
 				abort();
 		}
 
-		gctx_locks = (malloc_mutex_t *)base_alloc(tsdn, PROF_NCTX_LOCKS
-		    * sizeof(malloc_mutex_t));
+		gctx_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd),
+		    PROF_NCTX_LOCKS * sizeof(malloc_mutex_t));
 		if (gctx_locks == NULL)
 			return (true);
 		for (i = 0; i < PROF_NCTX_LOCKS; i++) {
@@ -2256,7 +2253,7 @@ prof_boot2(tsdn_t *tsdn)
 				return (true);
 		}
 
-		tdata_locks = (malloc_mutex_t *)base_alloc(tsdn,
+		tdata_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd),
 		    PROF_NTDATA_LOCKS * sizeof(malloc_mutex_t));
 		if (tdata_locks == NULL)
 			return (true);
diff --git a/contrib/jemalloc/src/rtree.c b/contrib/jemalloc/src/rtree.c
index 3166b45faeed..f2e2997d5535 100644
--- a/contrib/jemalloc/src/rtree.c
+++ b/contrib/jemalloc/src/rtree.c
@@ -96,12 +96,15 @@ rtree_node_init(rtree_t *rtree, unsigned level, rtree_node_elm_t **elmp)
 	rtree_node_elm_t *node;
 
 	if (atomic_cas_p((void **)elmp, NULL, RTREE_NODE_INITIALIZING)) {
+		spin_t spinner;
+
 		/*
 		 * Another thread is already in the process of initializing.
 		 * Spin-wait until initialization is complete.
 		 */
+		spin_init(&spinner);
 		do {
-			CPU_SPINWAIT;
+			spin_adaptive(&spinner);
 			node = atomic_read_p((void **)elmp);
 		} while (node == RTREE_NODE_INITIALIZING);
 	} else {
@@ -125,5 +128,5 @@ rtree_node_elm_t *
 rtree_child_read_hard(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level)
 {
 
-	return (rtree_node_init(rtree, level, &elm->child));
+	return (rtree_node_init(rtree, level+1, &elm->child));
 }
diff --git a/contrib/jemalloc/src/spin.c b/contrib/jemalloc/src/spin.c
new file mode 100644
index 000000000000..5242d95aa10f
--- /dev/null
+++ b/contrib/jemalloc/src/spin.c
@@ -0,0 +1,2 @@
+#define	JEMALLOC_SPIN_C_
+#include "jemalloc/internal/jemalloc_internal.h"
diff --git a/contrib/jemalloc/src/stats.c b/contrib/jemalloc/src/stats.c
index 073be4fe1539..bd8af3999ba9 100644
--- a/contrib/jemalloc/src/stats.c
+++ b/contrib/jemalloc/src/stats.c
@@ -32,86 +32,107 @@ bool	opt_stats_print = false;
 
 size_t	stats_cactive = 0;
 
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void	stats_arena_bins_print(void (*write_cb)(void *, const char *),
-    void *cbopaque, unsigned i);
-static void	stats_arena_lruns_print(void (*write_cb)(void *, const char *),
-    void *cbopaque, unsigned i);
-static void	stats_arena_hchunks_print(
-    void (*write_cb)(void *, const char *), void *cbopaque, unsigned i);
-static void	stats_arena_print(void (*write_cb)(void *, const char *),
-    void *cbopaque, unsigned i, bool bins, bool large, bool huge);
-
 /******************************************************************************/
 
 static void
 stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
-    unsigned i)
+    bool json, bool large, bool huge, unsigned i)
 {
 	size_t page;
-	bool config_tcache, in_gap;
+	bool config_tcache, in_gap, in_gap_prev;
 	unsigned nbins, j;
 
 	CTL_GET("arenas.page", &page, size_t);
 
-	CTL_GET("config.tcache", &config_tcache, bool);
-	if (config_tcache) {
-		malloc_cprintf(write_cb, cbopaque,
-		    "bins:           size ind    allocated      nmalloc"
-		    "      ndalloc    nrequests      curregs      curruns regs"
-		    " pgs  util       nfills     nflushes      newruns"
-		    "       reruns\n");
-	} else {
-		malloc_cprintf(write_cb, cbopaque,
-		    "bins:           size ind    allocated      nmalloc"
-		    "      ndalloc    nrequests      curregs      curruns regs"
-		    " pgs  util      newruns       reruns\n");
-	}
 	CTL_GET("arenas.nbins", &nbins, unsigned);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"bins\": [\n");
+	} else {
+		CTL_GET("config.tcache", &config_tcache, bool);
+		if (config_tcache) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "bins:           size ind    allocated      nmalloc"
+			    "      ndalloc    nrequests      curregs"
+			    "      curruns regs pgs  util       nfills"
+			    "     nflushes      newruns       reruns\n");
+		} else {
+			malloc_cprintf(write_cb, cbopaque,
+			    "bins:           size ind    allocated      nmalloc"
+			    "      ndalloc    nrequests      curregs"
+			    "      curruns regs pgs  util      newruns"
+			    "       reruns\n");
+		}
+	}
 	for (j = 0, in_gap = false; j < nbins; j++) {
 		uint64_t nruns;
+		size_t reg_size, run_size, curregs;
+		size_t curruns;
+		uint32_t nregs;
+		uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;
+		uint64_t nreruns;
 
 		CTL_M2_M4_GET("stats.arenas.0.bins.0.nruns", i, j, &nruns,
 		    uint64_t);
-		if (nruns == 0)
-			in_gap = true;
-		else {
-			size_t reg_size, run_size, curregs, availregs, milli;
-			size_t curruns;
-			uint32_t nregs;
-			uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;
-			uint64_t reruns;
-			char util[6]; /* "x.yyy". */
+		in_gap_prev = in_gap;
+		in_gap = (nruns == 0);
 
-			if (in_gap) {
-				malloc_cprintf(write_cb, cbopaque,
-				    "                     ---\n");
-				in_gap = false;
-			}
-			CTL_M2_GET("arenas.bin.0.size", j, ®_size, size_t);
-			CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t);
-			CTL_M2_GET("arenas.bin.0.run_size", j, &run_size,
-			    size_t);
-			CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j,
-			    &nmalloc, uint64_t);
-			CTL_M2_M4_GET("stats.arenas.0.bins.0.ndalloc", i, j,
-			    &ndalloc, uint64_t);
-			CTL_M2_M4_GET("stats.arenas.0.bins.0.curregs", i, j,
-			    &curregs, size_t);
-			CTL_M2_M4_GET("stats.arenas.0.bins.0.nrequests", i, j,
-			    &nrequests, uint64_t);
+		if (!json && in_gap_prev && !in_gap) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "                     ---\n");
+		}
+
+		CTL_M2_GET("arenas.bin.0.size", j, ®_size, size_t);
+		CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t);
+		CTL_M2_GET("arenas.bin.0.run_size", j, &run_size, size_t);
+
+		CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j, &nmalloc,
+		    uint64_t);
+		CTL_M2_M4_GET("stats.arenas.0.bins.0.ndalloc", i, j, &ndalloc,
+		    uint64_t);
+		CTL_M2_M4_GET("stats.arenas.0.bins.0.curregs", i, j, &curregs,
+		    size_t);
+		CTL_M2_M4_GET("stats.arenas.0.bins.0.nrequests", i, j,
+		    &nrequests, uint64_t);
+		if (config_tcache) {
+			CTL_M2_M4_GET("stats.arenas.0.bins.0.nfills", i, j,
+			    &nfills, uint64_t);
+			CTL_M2_M4_GET("stats.arenas.0.bins.0.nflushes", i, j,
+			    &nflushes, uint64_t);
+		}
+		CTL_M2_M4_GET("stats.arenas.0.bins.0.nreruns", i, j, &nreruns,
+		    uint64_t);
+		CTL_M2_M4_GET("stats.arenas.0.bins.0.curruns", i, j, &curruns,
+		    size_t);
+
+		if (json) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t{\n"
+			    "\t\t\t\t\t\t\"nmalloc\": %"FMTu64",\n"
+			    "\t\t\t\t\t\t\"ndalloc\": %"FMTu64",\n"
+			    "\t\t\t\t\t\t\"curregs\": %zu,\n"
+			    "\t\t\t\t\t\t\"nrequests\": %"FMTu64",\n",
+			    nmalloc,
+			    ndalloc,
+			    curregs,
+			    nrequests);
 			if (config_tcache) {
-				CTL_M2_M4_GET("stats.arenas.0.bins.0.nfills", i,
-				    j, &nfills, uint64_t);
-				CTL_M2_M4_GET("stats.arenas.0.bins.0.nflushes",
-				    i, j, &nflushes, uint64_t);
+				malloc_cprintf(write_cb, cbopaque,
+				    "\t\t\t\t\t\t\"nfills\": %"FMTu64",\n"
+				    "\t\t\t\t\t\t\"nflushes\": %"FMTu64",\n",
+				    nfills,
+				    nflushes);
 			}
-			CTL_M2_M4_GET("stats.arenas.0.bins.0.nreruns", i, j,
-			    &reruns, uint64_t);
-			CTL_M2_M4_GET("stats.arenas.0.bins.0.curruns", i, j,
-			    &curruns, size_t);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t\t\"nreruns\": %"FMTu64",\n"
+			    "\t\t\t\t\t\t\"curruns\": %zu\n"
+			    "\t\t\t\t\t}%s\n",
+			    nreruns,
+			    curruns,
+			    (j + 1 < nbins) ? "," : "");
+		} else if (!in_gap) {
+			size_t availregs, milli;
+			char util[6]; /* "x.yyy". */
 
 			availregs = nregs * curruns;
 			milli = (availregs != 0) ? (1000 * curregs) / availregs
@@ -138,7 +159,7 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
 				    reg_size, j, curregs * reg_size, nmalloc,
 				    ndalloc, nrequests, curregs, curruns, nregs,
 				    run_size / page, util, nfills, nflushes,
-				    nruns, reruns);
+				    nruns, nreruns);
 			} else {
 				malloc_cprintf(write_cb, cbopaque,
 				    "%20zu %3u %12zu %12"FMTu64
@@ -147,28 +168,38 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
 				    " %12"FMTu64"\n",
 				    reg_size, j, curregs * reg_size, nmalloc,
 				    ndalloc, nrequests, curregs, curruns, nregs,
-				    run_size / page, util, nruns, reruns);
+				    run_size / page, util, nruns, nreruns);
 			}
 		}
 	}
-	if (in_gap) {
+	if (json) {
 		malloc_cprintf(write_cb, cbopaque,
-		    "                     ---\n");
+		    "\t\t\t\t]%s\n", (large || huge) ? "," : "");
+	} else {
+		if (in_gap) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "                     ---\n");
+		}
 	}
 }
 
 static void
 stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
-    unsigned i)
+    bool json, bool huge, unsigned i)
 {
 	unsigned nbins, nlruns, j;
-	bool in_gap;
+	bool in_gap, in_gap_prev;
 
-	malloc_cprintf(write_cb, cbopaque,
-	    "large:          size ind    allocated      nmalloc      ndalloc"
-	    "    nrequests      curruns\n");
 	CTL_GET("arenas.nbins", &nbins, unsigned);
 	CTL_GET("arenas.nlruns", &nlruns, unsigned);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"lruns\": [\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "large:          size ind    allocated      nmalloc"
+		    "      ndalloc    nrequests      curruns\n");
+	}
 	for (j = 0, in_gap = false; j < nlruns; j++) {
 		uint64_t nmalloc, ndalloc, nrequests;
 		size_t run_size, curruns;
@@ -179,17 +210,25 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
 		    uint64_t);
 		CTL_M2_M4_GET("stats.arenas.0.lruns.0.nrequests", i, j,
 		    &nrequests, uint64_t);
-		if (nrequests == 0)
-			in_gap = true;
-		else {
-			CTL_M2_GET("arenas.lrun.0.size", j, &run_size, size_t);
-			CTL_M2_M4_GET("stats.arenas.0.lruns.0.curruns", i, j,
-			    &curruns, size_t);
-			if (in_gap) {
-				malloc_cprintf(write_cb, cbopaque,
-				    "                     ---\n");
-				in_gap = false;
-			}
+		in_gap_prev = in_gap;
+		in_gap = (nrequests == 0);
+
+		if (!json && in_gap_prev && !in_gap) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "                     ---\n");
+		}
+
+		CTL_M2_GET("arenas.lrun.0.size", j, &run_size, size_t);
+		CTL_M2_M4_GET("stats.arenas.0.lruns.0.curruns", i, j, &curruns,
+		    size_t);
+		if (json) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t{\n"
+			    "\t\t\t\t\t\t\"curruns\": %zu\n"
+			    "\t\t\t\t\t}%s\n",
+			    curruns,
+			    (j + 1 < nlruns) ? "," : "");
+		} else if (!in_gap) {
 			malloc_cprintf(write_cb, cbopaque,
 			    "%20zu %3u %12zu %12"FMTu64" %12"FMTu64
 			    " %12"FMTu64" %12zu\n",
@@ -197,25 +236,35 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
 			    ndalloc, nrequests, curruns);
 		}
 	}
-	if (in_gap) {
+	if (json) {
 		malloc_cprintf(write_cb, cbopaque,
-		    "                     ---\n");
+		    "\t\t\t\t]%s\n", huge ? "," : "");
+	} else {
+		if (in_gap) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "                     ---\n");
+		}
 	}
 }
 
 static void
 stats_arena_hchunks_print(void (*write_cb)(void *, const char *),
-    void *cbopaque, unsigned i)
+    void *cbopaque, bool json, unsigned i)
 {
 	unsigned nbins, nlruns, nhchunks, j;
-	bool in_gap;
+	bool in_gap, in_gap_prev;
 
-	malloc_cprintf(write_cb, cbopaque,
-	    "huge:           size ind    allocated      nmalloc      ndalloc"
-	    "    nrequests   curhchunks\n");
 	CTL_GET("arenas.nbins", &nbins, unsigned);
 	CTL_GET("arenas.nlruns", &nlruns, unsigned);
 	CTL_GET("arenas.nhchunks", &nhchunks, unsigned);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"hchunks\": [\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "huge:           size ind    allocated      nmalloc"
+		    "      ndalloc    nrequests   curhchunks\n");
+	}
 	for (j = 0, in_gap = false; j < nhchunks; j++) {
 		uint64_t nmalloc, ndalloc, nrequests;
 		size_t hchunk_size, curhchunks;
@@ -226,18 +275,25 @@ stats_arena_hchunks_print(void (*write_cb)(void *, const char *),
 		    &ndalloc, uint64_t);
 		CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nrequests", i, j,
 		    &nrequests, uint64_t);
-		if (nrequests == 0)
-			in_gap = true;
-		else {
-			CTL_M2_GET("arenas.hchunk.0.size", j, &hchunk_size,
-			    size_t);
-			CTL_M2_M4_GET("stats.arenas.0.hchunks.0.curhchunks", i,
-			    j, &curhchunks, size_t);
-			if (in_gap) {
-				malloc_cprintf(write_cb, cbopaque,
-				    "                     ---\n");
-				in_gap = false;
-			}
+		in_gap_prev = in_gap;
+		in_gap = (nrequests == 0);
+
+		if (!json && in_gap_prev && !in_gap) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "                     ---\n");
+		}
+
+		CTL_M2_GET("arenas.hchunk.0.size", j, &hchunk_size, size_t);
+		CTL_M2_M4_GET("stats.arenas.0.hchunks.0.curhchunks", i, j,
+		    &curhchunks, size_t);
+		if (json) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t{\n"
+			    "\t\t\t\t\t\t\"curhchunks\": %zu\n"
+			    "\t\t\t\t\t}%s\n",
+			    curhchunks,
+			    (j + 1 < nhchunks) ? "," : "");
+		} else if (!in_gap) {
 			malloc_cprintf(write_cb, cbopaque,
 			    "%20zu %3u %12zu %12"FMTu64" %12"FMTu64
 			    " %12"FMTu64" %12zu\n",
@@ -246,15 +302,20 @@ stats_arena_hchunks_print(void (*write_cb)(void *, const char *),
 			    nrequests, curhchunks);
 		}
 	}
-	if (in_gap) {
+	if (json) {
 		malloc_cprintf(write_cb, cbopaque,
-		    "                     ---\n");
+		    "\t\t\t\t]\n");
+	} else {
+		if (in_gap) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "                     ---\n");
+		}
 	}
 }
 
 static void
 stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
-    unsigned i, bool bins, bool large, bool huge)
+    bool json, unsigned i, bool bins, bool large, bool huge)
 {
 	unsigned nthreads;
 	const char *dss;
@@ -272,100 +333,731 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
 	CTL_GET("arenas.page", &page, size_t);
 
 	CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned);
-	malloc_cprintf(write_cb, cbopaque,
-	    "assigned threads: %u\n", nthreads);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"nthreads\": %u,\n", nthreads);
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "assigned threads: %u\n", nthreads);
+	}
+
 	CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *);
-	malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n",
-	    dss);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"dss\": \"%s\",\n", dss);
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "dss allocation precedence: %s\n", dss);
+	}
+
 	CTL_M2_GET("stats.arenas.0.lg_dirty_mult", i, &lg_dirty_mult, ssize_t);
-	if (opt_purge == purge_mode_ratio) {
-		if (lg_dirty_mult >= 0) {
-			malloc_cprintf(write_cb, cbopaque,
-			    "min active:dirty page ratio: %u:1\n",
-			    (1U << lg_dirty_mult));
-		} else {
-			malloc_cprintf(write_cb, cbopaque,
-			    "min active:dirty page ratio: N/A\n");
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"lg_dirty_mult\": %zd,\n", lg_dirty_mult);
+	} else {
+		if (opt_purge == purge_mode_ratio) {
+			if (lg_dirty_mult >= 0) {
+				malloc_cprintf(write_cb, cbopaque,
+				    "min active:dirty page ratio: %u:1\n",
+				    (1U << lg_dirty_mult));
+			} else {
+				malloc_cprintf(write_cb, cbopaque,
+				    "min active:dirty page ratio: N/A\n");
+			}
 		}
 	}
+
 	CTL_M2_GET("stats.arenas.0.decay_time", i, &decay_time, ssize_t);
-	if (opt_purge == purge_mode_decay) {
-		if (decay_time >= 0) {
-			malloc_cprintf(write_cb, cbopaque, "decay time: %zd\n",
-			    decay_time);
-		} else
-			malloc_cprintf(write_cb, cbopaque, "decay time: N/A\n");
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"decay_time\": %zd,\n", decay_time);
+	} else {
+		if (opt_purge == purge_mode_decay) {
+			if (decay_time >= 0) {
+				malloc_cprintf(write_cb, cbopaque,
+				    "decay time: %zd\n", decay_time);
+			} else {
+				malloc_cprintf(write_cb, cbopaque,
+				    "decay time: N/A\n");
+			}
+		}
 	}
+
 	CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t);
 	CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t);
 	CTL_M2_GET("stats.arenas.0.npurge", i, &npurge, uint64_t);
 	CTL_M2_GET("stats.arenas.0.nmadvise", i, &nmadvise, uint64_t);
 	CTL_M2_GET("stats.arenas.0.purged", i, &purged, uint64_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "purging: dirty: %zu, sweeps: %"FMTu64", madvises: %"FMTu64", "
-	    "purged: %"FMTu64"\n", pdirty, npurge, nmadvise, purged);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"pactive\": %zu,\n", pactive);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"pdirty\": %zu,\n", pdirty);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"npurge\": %"FMTu64",\n", npurge);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"nmadvise\": %"FMTu64",\n", nmadvise);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"purged\": %"FMTu64",\n", purged);
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "purging: dirty: %zu, sweeps: %"FMTu64", madvises: %"FMTu64
+		    ", purged: %"FMTu64"\n", pdirty, npurge, nmadvise, purged);
+	}
 
-	malloc_cprintf(write_cb, cbopaque,
-	    "                            allocated      nmalloc      ndalloc"
-	    "    nrequests\n");
 	CTL_M2_GET("stats.arenas.0.small.allocated", i, &small_allocated,
 	    size_t);
 	CTL_M2_GET("stats.arenas.0.small.nmalloc", i, &small_nmalloc, uint64_t);
 	CTL_M2_GET("stats.arenas.0.small.ndalloc", i, &small_ndalloc, uint64_t);
 	CTL_M2_GET("stats.arenas.0.small.nrequests", i, &small_nrequests,
 	    uint64_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "small:                   %12zu %12"FMTu64" %12"FMTu64
-	    " %12"FMTu64"\n",
-	    small_allocated, small_nmalloc, small_ndalloc, small_nrequests);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"small\": {\n");
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"allocated\": %zu,\n", small_allocated);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", small_nmalloc);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", small_ndalloc);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", small_nrequests);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t},\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "                            allocated      nmalloc"
+		    "      ndalloc    nrequests\n");
+		malloc_cprintf(write_cb, cbopaque,
+		    "small:                   %12zu %12"FMTu64" %12"FMTu64
+		    " %12"FMTu64"\n",
+		    small_allocated, small_nmalloc, small_ndalloc,
+		    small_nrequests);
+	}
+
 	CTL_M2_GET("stats.arenas.0.large.allocated", i, &large_allocated,
 	    size_t);
 	CTL_M2_GET("stats.arenas.0.large.nmalloc", i, &large_nmalloc, uint64_t);
 	CTL_M2_GET("stats.arenas.0.large.ndalloc", i, &large_ndalloc, uint64_t);
 	CTL_M2_GET("stats.arenas.0.large.nrequests", i, &large_nrequests,
 	    uint64_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "large:                   %12zu %12"FMTu64" %12"FMTu64
-	    " %12"FMTu64"\n",
-	    large_allocated, large_nmalloc, large_ndalloc, large_nrequests);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"large\": {\n");
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"allocated\": %zu,\n", large_allocated);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", large_nmalloc);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", large_ndalloc);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", large_nrequests);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t},\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "large:                   %12zu %12"FMTu64" %12"FMTu64
+		    " %12"FMTu64"\n",
+		    large_allocated, large_nmalloc, large_ndalloc,
+		    large_nrequests);
+	}
+
 	CTL_M2_GET("stats.arenas.0.huge.allocated", i, &huge_allocated, size_t);
 	CTL_M2_GET("stats.arenas.0.huge.nmalloc", i, &huge_nmalloc, uint64_t);
 	CTL_M2_GET("stats.arenas.0.huge.ndalloc", i, &huge_ndalloc, uint64_t);
 	CTL_M2_GET("stats.arenas.0.huge.nrequests", i, &huge_nrequests,
 	    uint64_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "huge:                    %12zu %12"FMTu64" %12"FMTu64
-	    " %12"FMTu64"\n",
-	    huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests);
-	malloc_cprintf(write_cb, cbopaque,
-	    "total:                   %12zu %12"FMTu64" %12"FMTu64
-	    " %12"FMTu64"\n",
-	    small_allocated + large_allocated + huge_allocated,
-	    small_nmalloc + large_nmalloc + huge_nmalloc,
-	    small_ndalloc + large_ndalloc + huge_ndalloc,
-	    small_nrequests + large_nrequests + huge_nrequests);
-	malloc_cprintf(write_cb, cbopaque,
-	    "active:                  %12zu\n", pactive * page);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"huge\": {\n");
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"allocated\": %zu,\n", huge_allocated);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", huge_nmalloc);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", huge_ndalloc);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", huge_nrequests);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t},\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "huge:                    %12zu %12"FMTu64" %12"FMTu64
+		    " %12"FMTu64"\n",
+		    huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests);
+		malloc_cprintf(write_cb, cbopaque,
+		    "total:                   %12zu %12"FMTu64" %12"FMTu64
+		    " %12"FMTu64"\n",
+		    small_allocated + large_allocated + huge_allocated,
+		    small_nmalloc + large_nmalloc + huge_nmalloc,
+		    small_ndalloc + large_ndalloc + huge_ndalloc,
+		    small_nrequests + large_nrequests + huge_nrequests);
+	}
+	if (!json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "active:                  %12zu\n", pactive * page);
+	}
+
 	CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "mapped:                  %12zu\n", mapped);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"mapped\": %zu,\n", mapped);
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "mapped:                  %12zu\n", mapped);
+	}
+
 	CTL_M2_GET("stats.arenas.0.retained", i, &retained, size_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "retained:                %12zu\n", retained);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"retained\": %zu,\n", retained);
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "retained:                %12zu\n", retained);
+	}
+
 	CTL_M2_GET("stats.arenas.0.metadata.mapped", i, &metadata_mapped,
 	    size_t);
 	CTL_M2_GET("stats.arenas.0.metadata.allocated", i, &metadata_allocated,
 	    size_t);
-	malloc_cprintf(write_cb, cbopaque,
-	    "metadata: mapped: %zu, allocated: %zu\n",
-	    metadata_mapped, metadata_allocated);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\"metadata\": {\n");
 
-	if (bins)
-		stats_arena_bins_print(write_cb, cbopaque, i);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"mapped\": %zu,\n", metadata_mapped);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t\t\"allocated\": %zu\n", metadata_allocated);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\t},\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "metadata: mapped: %zu, allocated: %zu\n",
+		    metadata_mapped, metadata_allocated);
+	}
+
+	if (bins) {
+		stats_arena_bins_print(write_cb, cbopaque, json, large, huge,
+		    i);
+	}
 	if (large)
-		stats_arena_lruns_print(write_cb, cbopaque, i);
+		stats_arena_lruns_print(write_cb, cbopaque, json, huge, i);
 	if (huge)
-		stats_arena_hchunks_print(write_cb, cbopaque, i);
+		stats_arena_hchunks_print(write_cb, cbopaque, json, i);
+}
+
+static void
+stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
+    bool json, bool merged, bool unmerged)
+{
+	const char *cpv;
+	bool bv;
+	unsigned uv;
+	uint32_t u32v;
+	uint64_t u64v;
+	ssize_t ssv;
+	size_t sv, bsz, usz, ssz, sssz, cpsz;
+
+	bsz = sizeof(bool);
+	usz = sizeof(unsigned);
+	ssz = sizeof(size_t);
+	sssz = sizeof(ssize_t);
+	cpsz = sizeof(const char *);
+
+	CTL_GET("version", &cpv, const char *);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		"\t\t\"version\": \"%s\",\n", cpv);
+	} else
+		malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv);
+
+	/* config. */
+#define	CONFIG_WRITE_BOOL_JSON(n, c)					\
+	if (json) {							\
+		CTL_GET("config."#n, &bv, bool);			\
+		malloc_cprintf(write_cb, cbopaque,			\
+		    "\t\t\t\""#n"\": %s%s\n", bv ? "true" : "false",	\
+		    (c));						\
+	}
+
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\"config\": {\n");
+	}
+
+	CONFIG_WRITE_BOOL_JSON(cache_oblivious, ",")
+
+	CTL_GET("config.debug", &bv, bool);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"debug\": %s,\n", bv ? "true" : "false");
+	} else {
+		malloc_cprintf(write_cb, cbopaque, "Assertions %s\n",
+		    bv ? "enabled" : "disabled");
+	}
+
+	CONFIG_WRITE_BOOL_JSON(fill, ",")
+	CONFIG_WRITE_BOOL_JSON(lazy_lock, ",")
+
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"malloc_conf\": \"%s\",\n",
+		    config_malloc_conf);
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "config.malloc_conf: \"%s\"\n", config_malloc_conf);
+	}
+
+	CONFIG_WRITE_BOOL_JSON(munmap, ",")
+	CONFIG_WRITE_BOOL_JSON(prof, ",")
+	CONFIG_WRITE_BOOL_JSON(prof_libgcc, ",")
+	CONFIG_WRITE_BOOL_JSON(prof_libunwind, ",")
+	CONFIG_WRITE_BOOL_JSON(stats, ",")
+	CONFIG_WRITE_BOOL_JSON(tcache, ",")
+	CONFIG_WRITE_BOOL_JSON(tls, ",")
+	CONFIG_WRITE_BOOL_JSON(utrace, ",")
+	CONFIG_WRITE_BOOL_JSON(valgrind, ",")
+	CONFIG_WRITE_BOOL_JSON(xmalloc, "")
+
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t},\n");
+	}
+#undef CONFIG_WRITE_BOOL_JSON
+
+	/* opt. */
+#define	OPT_WRITE_BOOL(n, c)						\
+	if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0) {	\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": %s%s\n", bv ? "true" :	\
+			    "false", (c));				\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "  opt."#n": %s\n", bv ? "true" : "false");	\
+		}							\
+	}
+#define	OPT_WRITE_BOOL_MUTABLE(n, m, c) {				\
+	bool bv2;							\
+	if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0 &&	\
+	    je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) {			\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": %s%s\n", bv ? "true" :	\
+			    "false", (c));				\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "  opt."#n": %s ("#m": %s)\n", bv ? "true"	\
+			    : "false", bv2 ? "true" : "false");		\
+		}							\
+	}								\
+}
+#define	OPT_WRITE_UNSIGNED(n, c)					\
+	if (je_mallctl("opt."#n, (void *)&uv, &usz, NULL, 0) == 0) {	\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": %u%s\n", uv, (c));		\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			"  opt."#n": %u\n", uv);			\
+		}							\
+	}
+#define	OPT_WRITE_SIZE_T(n, c)						\
+	if (je_mallctl("opt."#n, (void *)&sv, &ssz, NULL, 0) == 0) {	\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": %zu%s\n", sv, (c));	\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			"  opt."#n": %zu\n", sv);			\
+		}							\
+	}
+#define	OPT_WRITE_SSIZE_T(n, c)						\
+	if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0) {	\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": %zd%s\n", ssv, (c));	\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "  opt."#n": %zd\n", ssv);			\
+		}							\
+	}
+#define	OPT_WRITE_SSIZE_T_MUTABLE(n, m, c) {				\
+	ssize_t ssv2;							\
+	if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0 &&	\
+	    je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) {		\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": %zd%s\n", ssv, (c));	\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "  opt."#n": %zd ("#m": %zd)\n",		\
+			    ssv, ssv2);					\
+		}							\
+	}								\
+}
+#define	OPT_WRITE_CHAR_P(n, c)						\
+	if (je_mallctl("opt."#n, (void *)&cpv, &cpsz, NULL, 0) == 0) {	\
+		if (json) {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "\t\t\t\""#n"\": \"%s\"%s\n", cpv, (c));	\
+		} else {						\
+			malloc_cprintf(write_cb, cbopaque,		\
+			    "  opt."#n": \"%s\"\n", cpv);		\
+		}							\
+	}
+
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\"opt\": {\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "Run-time option settings:\n");
+	}
+	OPT_WRITE_BOOL(abort, ",")
+	OPT_WRITE_SIZE_T(lg_chunk, ",")
+	OPT_WRITE_CHAR_P(dss, ",")
+	OPT_WRITE_UNSIGNED(narenas, ",")
+	OPT_WRITE_CHAR_P(purge, ",")
+	if (json || opt_purge == purge_mode_ratio) {
+		OPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult,
+		    arenas.lg_dirty_mult, ",")
+	}
+	if (json || opt_purge == purge_mode_decay) {
+		OPT_WRITE_SSIZE_T_MUTABLE(decay_time, arenas.decay_time, ",")
+	}
+	OPT_WRITE_CHAR_P(junk, ",")
+	OPT_WRITE_SIZE_T(quarantine, ",")
+	OPT_WRITE_BOOL(redzone, ",")
+	OPT_WRITE_BOOL(zero, ",")
+	OPT_WRITE_BOOL(utrace, ",")
+	OPT_WRITE_BOOL(xmalloc, ",")
+	OPT_WRITE_BOOL(tcache, ",")
+	OPT_WRITE_SSIZE_T(lg_tcache_max, ",")
+	OPT_WRITE_BOOL(prof, ",")
+	OPT_WRITE_CHAR_P(prof_prefix, ",")
+	OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active, ",")
+	OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init, prof.thread_active_init,
+	    ",")
+	OPT_WRITE_SSIZE_T_MUTABLE(lg_prof_sample, prof.lg_sample, ",")
+	OPT_WRITE_BOOL(prof_accum, ",")
+	OPT_WRITE_SSIZE_T(lg_prof_interval, ",")
+	OPT_WRITE_BOOL(prof_gdump, ",")
+	OPT_WRITE_BOOL(prof_final, ",")
+	OPT_WRITE_BOOL(prof_leak, ",")
+	/*
+	 * stats_print is always emitted, so as long as stats_print comes last
+	 * it's safe to unconditionally omit the comma here (rather than having
+	 * to conditionally omit it elsewhere depending on configuration).
+	 */
+	OPT_WRITE_BOOL(stats_print, "")
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t},\n");
+	}
+
+#undef OPT_WRITE_BOOL
+#undef OPT_WRITE_BOOL_MUTABLE
+#undef OPT_WRITE_SIZE_T
+#undef OPT_WRITE_SSIZE_T
+#undef OPT_WRITE_CHAR_P
+
+	/* arenas. */
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\"arenas\": {\n");
+	}
+
+	CTL_GET("arenas.narenas", &uv, unsigned);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"narenas\": %u,\n", uv);
+	} else
+		malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv);
+
+	CTL_GET("arenas.lg_dirty_mult", &ssv, ssize_t);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"lg_dirty_mult\": %zd,\n", ssv);
+	} else if (opt_purge == purge_mode_ratio) {
+		if (ssv >= 0) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "Min active:dirty page ratio per arena: "
+			    "%u:1\n", (1U << ssv));
+		} else {
+			malloc_cprintf(write_cb, cbopaque,
+			    "Min active:dirty page ratio per arena: "
+			    "N/A\n");
+		}
+	}
+	CTL_GET("arenas.decay_time", &ssv, ssize_t);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"decay_time\": %zd,\n", ssv);
+	} else if (opt_purge == purge_mode_decay) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "Unused dirty page decay time: %zd%s\n",
+		    ssv, (ssv < 0) ? " (no decay)" : "");
+	}
+
+	CTL_GET("arenas.quantum", &sv, size_t);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"quantum\": %zu,\n", sv);
+	} else
+		malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv);
+
+	CTL_GET("arenas.page", &sv, size_t);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"page\": %zu,\n", sv);
+	} else
+		malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv);
+
+	if (je_mallctl("arenas.tcache_max", (void *)&sv, &ssz, NULL, 0) == 0) {
+		if (json) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\"tcache_max\": %zu,\n", sv);
+		} else {
+			malloc_cprintf(write_cb, cbopaque,
+			    "Maximum thread-cached size class: %zu\n", sv);
+		}
+	}
+
+	if (json) {
+		unsigned nbins, nlruns, nhchunks, i;
+
+		CTL_GET("arenas.nbins", &nbins, unsigned);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"nbins\": %u,\n", nbins);
+
+		CTL_GET("arenas.nhbins", &uv, unsigned);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"nhbins\": %u,\n", uv);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"bin\": [\n");
+		for (i = 0; i < nbins; i++) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t{\n");
+
+			CTL_M2_GET("arenas.bin.0.size", i, &sv, size_t);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t\"size\": %zu,\n", sv);
+
+			CTL_M2_GET("arenas.bin.0.nregs", i, &u32v, uint32_t);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t\"nregs\": %"FMTu32",\n", u32v);
+
+			CTL_M2_GET("arenas.bin.0.run_size", i, &sv, size_t);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t\"run_size\": %zu\n", sv);
+
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t}%s\n", (i + 1 < nbins) ? "," : "");
+		}
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t],\n");
+
+		CTL_GET("arenas.nlruns", &nlruns, unsigned);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"nlruns\": %u,\n", nlruns);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"lrun\": [\n");
+		for (i = 0; i < nlruns; i++) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t{\n");
+
+			CTL_M2_GET("arenas.lrun.0.size", i, &sv, size_t);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t\"size\": %zu\n", sv);
+
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t}%s\n", (i + 1 < nlruns) ? "," : "");
+		}
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t],\n");
+
+		CTL_GET("arenas.nhchunks", &nhchunks, unsigned);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"nhchunks\": %u,\n", nhchunks);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"hchunk\": [\n");
+		for (i = 0; i < nhchunks; i++) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t{\n");
+
+			CTL_M2_GET("arenas.hchunk.0.size", i, &sv, size_t);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t\t\"size\": %zu\n", sv);
+
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\t}%s\n", (i + 1 < nhchunks) ? "," : "");
+		}
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t]\n");
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t},\n");
+	}
+
+	/* prof. */
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\"prof\": {\n");
+
+		CTL_GET("prof.thread_active_init", &bv, bool);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"thread_active_init\": %s,\n", bv ? "true" :
+		    "false");
+
+		CTL_GET("prof.active", &bv, bool);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"active\": %s,\n", bv ? "true" : "false");
+
+		CTL_GET("prof.gdump", &bv, bool);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"gdump\": %s,\n", bv ? "true" : "false");
+
+		CTL_GET("prof.interval", &u64v, uint64_t);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"interval\": %"FMTu64",\n", u64v);
+
+		CTL_GET("prof.lg_sample", &ssv, ssize_t);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"lg_sample\": %zd\n", ssv);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t}%s\n", (config_stats || merged || unmerged) ? "," :
+		    "");
+	}
+}
+
+static void
+stats_print_helper(void (*write_cb)(void *, const char *), void *cbopaque,
+    bool json, bool merged, bool unmerged, bool bins, bool large, bool huge)
+{
+	size_t *cactive;
+	size_t allocated, active, metadata, resident, mapped, retained;
+
+	CTL_GET("stats.cactive", &cactive, size_t *);
+	CTL_GET("stats.allocated", &allocated, size_t);
+	CTL_GET("stats.active", &active, size_t);
+	CTL_GET("stats.metadata", &metadata, size_t);
+	CTL_GET("stats.resident", &resident, size_t);
+	CTL_GET("stats.mapped", &mapped, size_t);
+	CTL_GET("stats.retained", &retained, size_t);
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\"stats\": {\n");
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"cactive\": %zu,\n", atomic_read_z(cactive));
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"allocated\": %zu,\n", allocated);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"active\": %zu,\n", active);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"metadata\": %zu,\n", metadata);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"resident\": %zu,\n", resident);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"mapped\": %zu,\n", mapped);
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t\t\"retained\": %zu\n", retained);
+
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t\t}%s\n", (merged || unmerged) ? "," : "");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "Allocated: %zu, active: %zu, metadata: %zu,"
+		    " resident: %zu, mapped: %zu, retained: %zu\n",
+		    allocated, active, metadata, resident, mapped, retained);
+		malloc_cprintf(write_cb, cbopaque,
+		    "Current active ceiling: %zu\n",
+		    atomic_read_z(cactive));
+	}
+
+	if (merged || unmerged) {
+		unsigned narenas;
+
+		if (json) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\"stats.arenas\": {\n");
+		}
+
+		CTL_GET("arenas.narenas", &narenas, unsigned);
+		{
+			VARIABLE_ARRAY(bool, initialized, narenas);
+			size_t isz;
+			unsigned i, j, ninitialized;
+
+			isz = sizeof(bool) * narenas;
+			xmallctl("arenas.initialized", (void *)initialized,
+			    &isz, NULL, 0);
+			for (i = ninitialized = 0; i < narenas; i++) {
+				if (initialized[i])
+					ninitialized++;
+			}
+
+			/* Merged stats. */
+			if (merged && (ninitialized > 1 || !unmerged)) {
+				/* Print merged arena stats. */
+				if (json) {
+					malloc_cprintf(write_cb, cbopaque,
+					    "\t\t\t\"merged\": {\n");
+				} else {
+					malloc_cprintf(write_cb, cbopaque,
+					    "\nMerged arenas stats:\n");
+				}
+				stats_arena_print(write_cb, cbopaque, json,
+				    narenas, bins, large, huge);
+				if (json) {
+					malloc_cprintf(write_cb, cbopaque,
+					    "\t\t\t}%s\n", (ninitialized > 1) ?
+					    "," : "");
+				}
+			}
+
+			/* Unmerged stats. */
+			for (i = j = 0; i < narenas; i++) {
+				if (initialized[i]) {
+					if (json) {
+						j++;
+						malloc_cprintf(write_cb,
+						    cbopaque,
+						    "\t\t\t\"%u\": {\n", i);
+					} else {
+						malloc_cprintf(write_cb,
+						    cbopaque, "\narenas[%u]:\n",
+						    i);
+					}
+					stats_arena_print(write_cb, cbopaque,
+					    json, i, bins, large, huge);
+					if (json) {
+						malloc_cprintf(write_cb,
+						    cbopaque,
+						    "\t\t\t}%s\n", (j <
+						    ninitialized) ? "," : "");
+					}
+				}
+			}
+		}
+
+		if (json) {
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t}\n");
+		}
+	}
 }
 
 void
@@ -375,6 +1067,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
 	int err;
 	uint64_t epoch;
 	size_t u64sz;
+	bool json = false;
 	bool general = true;
 	bool merged = true;
 	bool unmerged = true;
@@ -408,6 +1101,9 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
 
 		for (i = 0; opts[i] != '\0'; i++) {
 			switch (opts[i]) {
+			case 'J':
+				json = true;
+				break;
 			case 'g':
 				general = false;
 				break;
@@ -431,246 +1127,27 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
 		}
 	}
 
-	malloc_cprintf(write_cb, cbopaque,
-	    "___ Begin jemalloc statistics ___\n");
-	if (general) {
-		const char *cpv;
-		bool bv;
-		unsigned uv;
-		ssize_t ssv;
-		size_t sv, bsz, usz, ssz, sssz, cpsz;
-
-		bsz = sizeof(bool);
-		usz = sizeof(unsigned);
-		ssz = sizeof(size_t);
-		sssz = sizeof(ssize_t);
-		cpsz = sizeof(const char *);
-
-		CTL_GET("version", &cpv, const char *);
-		malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv);
-		CTL_GET("config.debug", &bv, bool);
-		malloc_cprintf(write_cb, cbopaque, "Assertions %s\n",
-		    bv ? "enabled" : "disabled");
+	if (json) {
 		malloc_cprintf(write_cb, cbopaque,
-		    "config.malloc_conf: \"%s\"\n", config_malloc_conf);
-
-#define	OPT_WRITE_BOOL(n)						\
-		if (je_mallctl("opt."#n, &bv, &bsz, NULL, 0) == 0) {	\
-			malloc_cprintf(write_cb, cbopaque,		\
-			    "  opt."#n": %s\n", bv ? "true" : "false");	\
-		}
-#define	OPT_WRITE_BOOL_MUTABLE(n, m) {					\
-		bool bv2;						\
-		if (je_mallctl("opt."#n, &bv, &bsz, NULL, 0) == 0 &&	\
-		    je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) {		\
-			malloc_cprintf(write_cb, cbopaque,		\
-			    "  opt."#n": %s ("#m": %s)\n", bv ? "true"	\
-			    : "false", bv2 ? "true" : "false");		\
-		}							\
-}
-#define	OPT_WRITE_UNSIGNED(n)						\
-		if (je_mallctl("opt."#n, &uv, &usz, NULL, 0) == 0) {	\
-			malloc_cprintf(write_cb, cbopaque,		\
-			"  opt."#n": %u\n", uv);			\
-		}
-#define	OPT_WRITE_SIZE_T(n)						\
-		if (je_mallctl("opt."#n, &sv, &ssz, NULL, 0) == 0) {	\
-			malloc_cprintf(write_cb, cbopaque,		\
-			"  opt."#n": %zu\n", sv);			\
-		}
-#define	OPT_WRITE_SSIZE_T(n)						\
-		if (je_mallctl("opt."#n, &ssv, &sssz, NULL, 0) == 0) {	\
-			malloc_cprintf(write_cb, cbopaque,		\
-			    "  opt."#n": %zd\n", ssv);			\
-		}
-#define	OPT_WRITE_SSIZE_T_MUTABLE(n, m) {				\
-		ssize_t ssv2;						\
-		if (je_mallctl("opt."#n, &ssv, &sssz, NULL, 0) == 0 &&	\
-		    je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) {	\
-			malloc_cprintf(write_cb, cbopaque,		\
-			    "  opt."#n": %zd ("#m": %zd)\n",		\
-			    ssv, ssv2);					\
-		}							\
-}
-#define	OPT_WRITE_CHAR_P(n)						\
-		if (je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0) == 0) {	\
-			malloc_cprintf(write_cb, cbopaque,		\
-			    "  opt."#n": \"%s\"\n", cpv);		\
-		}
-
+		    "{\n"
+		    "\t\"jemalloc\": {\n");
+	} else {
 		malloc_cprintf(write_cb, cbopaque,
-		    "Run-time option settings:\n");
-		OPT_WRITE_BOOL(abort)
-		OPT_WRITE_SIZE_T(lg_chunk)
-		OPT_WRITE_CHAR_P(dss)
-		OPT_WRITE_UNSIGNED(narenas)
-		OPT_WRITE_CHAR_P(purge)
-		if (opt_purge == purge_mode_ratio) {
-			OPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult,
-			    arenas.lg_dirty_mult)
-		}
-		if (opt_purge == purge_mode_decay)
-			OPT_WRITE_SSIZE_T_MUTABLE(decay_time, arenas.decay_time)
-		OPT_WRITE_BOOL(stats_print)
-		OPT_WRITE_CHAR_P(junk)
-		OPT_WRITE_SIZE_T(quarantine)
-		OPT_WRITE_BOOL(redzone)
-		OPT_WRITE_BOOL(zero)
-		OPT_WRITE_BOOL(utrace)
-		OPT_WRITE_BOOL(valgrind)
-		OPT_WRITE_BOOL(xmalloc)
-		OPT_WRITE_BOOL(tcache)
-		OPT_WRITE_SSIZE_T(lg_tcache_max)
-		OPT_WRITE_BOOL(prof)
-		OPT_WRITE_CHAR_P(prof_prefix)
-		OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active)
-		OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init,
-		    prof.thread_active_init)
-		OPT_WRITE_SSIZE_T(lg_prof_sample)
-		OPT_WRITE_BOOL(prof_accum)
-		OPT_WRITE_SSIZE_T(lg_prof_interval)
-		OPT_WRITE_BOOL(prof_gdump)
-		OPT_WRITE_BOOL(prof_final)
-		OPT_WRITE_BOOL(prof_leak)
-
-#undef OPT_WRITE_BOOL
-#undef OPT_WRITE_BOOL_MUTABLE
-#undef OPT_WRITE_SIZE_T
-#undef OPT_WRITE_SSIZE_T
-#undef OPT_WRITE_CHAR_P
-
-		malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus);
-
-		CTL_GET("arenas.narenas", &uv, unsigned);
-		malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv);
-
-		malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n",
-		    sizeof(void *));
-
-		CTL_GET("arenas.quantum", &sv, size_t);
-		malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n",
-		    sv);
-
-		CTL_GET("arenas.page", &sv, size_t);
-		malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv);
-
-		CTL_GET("arenas.lg_dirty_mult", &ssv, ssize_t);
-		if (opt_purge == purge_mode_ratio) {
-			if (ssv >= 0) {
-				malloc_cprintf(write_cb, cbopaque,
-				    "Min active:dirty page ratio per arena: "
-				    "%u:1\n", (1U << ssv));
-			} else {
-				malloc_cprintf(write_cb, cbopaque,
-				    "Min active:dirty page ratio per arena: "
-				    "N/A\n");
-			}
-		}
-		CTL_GET("arenas.decay_time", &ssv, ssize_t);
-		if (opt_purge == purge_mode_decay) {
-			malloc_cprintf(write_cb, cbopaque,
-			    "Unused dirty page decay time: %zd%s\n",
-			    ssv, (ssv < 0) ? " (no decay)" : "");
-		}
-		if (je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0) == 0) {
-			malloc_cprintf(write_cb, cbopaque,
-			    "Maximum thread-cached size class: %zu\n", sv);
-		}
-		if (je_mallctl("opt.prof", &bv, &bsz, NULL, 0) == 0 && bv) {
-			CTL_GET("prof.lg_sample", &sv, size_t);
-			malloc_cprintf(write_cb, cbopaque,
-			    "Average profile sample interval: %"FMTu64
-			    " (2^%zu)\n", (((uint64_t)1U) << sv), sv);
-
-			CTL_GET("opt.lg_prof_interval", &ssv, ssize_t);
-			if (ssv >= 0) {
-				malloc_cprintf(write_cb, cbopaque,
-				    "Average profile dump interval: %"FMTu64
-				    " (2^%zd)\n",
-				    (((uint64_t)1U) << ssv), ssv);
-			} else {
-				malloc_cprintf(write_cb, cbopaque,
-				    "Average profile dump interval: N/A\n");
-			}
-		}
-		CTL_GET("opt.lg_chunk", &sv, size_t);
-		malloc_cprintf(write_cb, cbopaque,
-		    "Chunk size: %zu (2^%zu)\n", (ZU(1) << sv), sv);
+		    "___ Begin jemalloc statistics ___\n");
 	}
 
+	if (general)
+		stats_general_print(write_cb, cbopaque, json, merged, unmerged);
 	if (config_stats) {
-		size_t *cactive;
-		size_t allocated, active, metadata, resident, mapped, retained;
-
-		CTL_GET("stats.cactive", &cactive, size_t *);
-		CTL_GET("stats.allocated", &allocated, size_t);
-		CTL_GET("stats.active", &active, size_t);
-		CTL_GET("stats.metadata", &metadata, size_t);
-		CTL_GET("stats.resident", &resident, size_t);
-		CTL_GET("stats.mapped", &mapped, size_t);
-		CTL_GET("stats.retained", &retained, size_t);
-		malloc_cprintf(write_cb, cbopaque,
-		    "Allocated: %zu, active: %zu, metadata: %zu,"
-		    " resident: %zu, mapped: %zu, retained: %zu\n",
-		    allocated, active, metadata, resident, mapped, retained);
-		malloc_cprintf(write_cb, cbopaque,
-		    "Current active ceiling: %zu\n",
-		    atomic_read_z(cactive));
-
-		if (merged) {
-			unsigned narenas;
-
-			CTL_GET("arenas.narenas", &narenas, unsigned);
-			{
-				VARIABLE_ARRAY(bool, initialized, narenas);
-				size_t isz;
-				unsigned i, ninitialized;
-
-				isz = sizeof(bool) * narenas;
-				xmallctl("arenas.initialized", initialized,
-				    &isz, NULL, 0);
-				for (i = ninitialized = 0; i < narenas; i++) {
-					if (initialized[i])
-						ninitialized++;
-				}
-
-				if (ninitialized > 1 || !unmerged) {
-					/* Print merged arena stats. */
-					malloc_cprintf(write_cb, cbopaque,
-					    "\nMerged arenas stats:\n");
-					stats_arena_print(write_cb, cbopaque,
-					    narenas, bins, large, huge);
-				}
-			}
-		}
-
-		if (unmerged) {
-			unsigned narenas;
-
-			/* Print stats for each arena. */
-
-			CTL_GET("arenas.narenas", &narenas, unsigned);
-			{
-				VARIABLE_ARRAY(bool, initialized, narenas);
-				size_t isz;
-				unsigned i;
-
-				isz = sizeof(bool) * narenas;
-				xmallctl("arenas.initialized", initialized,
-				    &isz, NULL, 0);
-
-				for (i = 0; i < narenas; i++) {
-					if (initialized[i]) {
-						malloc_cprintf(write_cb,
-						    cbopaque,
-						    "\narenas[%u]:\n", i);
-						stats_arena_print(write_cb,
-						    cbopaque, i, bins, large,
-						    huge);
-					}
-				}
-			}
-		}
+		stats_print_helper(write_cb, cbopaque, json, merged, unmerged,
+		    bins, large, huge);
+	}
+	if (json) {
+		malloc_cprintf(write_cb, cbopaque,
+		    "\t}\n"
+		    "}\n");
+	} else {
+		malloc_cprintf(write_cb, cbopaque,
+		    "--- End jemalloc statistics ---\n");
 	}
-	malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n");
 }
diff --git a/contrib/jemalloc/src/tcache.c b/contrib/jemalloc/src/tcache.c
index 175759c7c51d..f97aa420ca49 100644
--- a/contrib/jemalloc/src/tcache.c
+++ b/contrib/jemalloc/src/tcache.c
@@ -445,14 +445,14 @@ tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena)
 }
 
 bool
-tcaches_create(tsdn_t *tsdn, unsigned *r_ind)
+tcaches_create(tsd_t *tsd, unsigned *r_ind)
 {
 	arena_t *arena;
 	tcache_t *tcache;
 	tcaches_t *elm;
 
 	if (tcaches == NULL) {
-		tcaches = base_alloc(tsdn, sizeof(tcache_t *) *
+		tcaches = base_alloc(tsd_tsdn(tsd), sizeof(tcache_t *) *
 		    (MALLOCX_TCACHE_MAX+1));
 		if (tcaches == NULL)
 			return (true);
@@ -460,10 +460,10 @@ tcaches_create(tsdn_t *tsdn, unsigned *r_ind)
 
 	if (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX)
 		return (true);
-	arena = arena_ichoose(tsdn, NULL);
+	arena = arena_ichoose(tsd, NULL);
 	if (unlikely(arena == NULL))
 		return (true);
-	tcache = tcache_create(tsdn, arena);
+	tcache = tcache_create(tsd_tsdn(tsd), arena);
 	if (tcache == NULL)
 		return (true);
 
diff --git a/contrib/jemalloc/src/tsd.c b/contrib/jemalloc/src/tsd.c
index aeaa5e18ffe7..ec69a51c3d36 100644
--- a/contrib/jemalloc/src/tsd.c
+++ b/contrib/jemalloc/src/tsd.c
@@ -171,10 +171,10 @@ tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)
 	tsd_init_block_t *iter;
 
 	/* Check whether this thread has already inserted into the list. */
-	malloc_mutex_lock(NULL, &head->lock);
+	malloc_mutex_lock(TSDN_NULL, &head->lock);
 	ql_foreach(iter, &head->blocks, link) {
 		if (iter->thread == self) {
-			malloc_mutex_unlock(NULL, &head->lock);
+			malloc_mutex_unlock(TSDN_NULL, &head->lock);
 			return (iter->data);
 		}
 	}
@@ -182,7 +182,7 @@ tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)
 	ql_elm_new(block, link);
 	block->thread = self;
 	ql_tail_insert(&head->blocks, block, link);
-	malloc_mutex_unlock(NULL, &head->lock);
+	malloc_mutex_unlock(TSDN_NULL, &head->lock);
 	return (NULL);
 }
 
@@ -190,8 +190,8 @@ void
 tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)
 {
 
-	malloc_mutex_lock(NULL, &head->lock);
+	malloc_mutex_lock(TSDN_NULL, &head->lock);
 	ql_remove(&head->blocks, block, link);
-	malloc_mutex_unlock(NULL, &head->lock);
+	malloc_mutex_unlock(TSDN_NULL, &head->lock);
 }
 #endif
diff --git a/contrib/jemalloc/src/util.c b/contrib/jemalloc/src/util.c
index 04f9153dc5c4..bee1c77e7ece 100644
--- a/contrib/jemalloc/src/util.c
+++ b/contrib/jemalloc/src/util.c
@@ -49,7 +49,7 @@ static void
 wrtmessage(void *cbopaque, const char *s)
 {
 
-#ifdef SYS_write
+#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_write)
 	/*
 	 * Use syscall(2) rather than write(2) when possible in order to avoid
 	 * the possibility of memory allocation within libc.  This is necessary
diff --git a/lib/libc/stdlib/jemalloc/Makefile.inc b/lib/libc/stdlib/jemalloc/Makefile.inc
index 8b22fdac2815..f507e00d2ae0 100644
--- a/lib/libc/stdlib/jemalloc/Makefile.inc
+++ b/lib/libc/stdlib/jemalloc/Makefile.inc
@@ -4,8 +4,8 @@
 
 JEMALLOCSRCS:= jemalloc.c arena.c atomic.c base.c bitmap.c chunk.c \
 	chunk_dss.c chunk_mmap.c ckh.c ctl.c extent.c hash.c huge.c mb.c \
-	mutex.c nstime.c pages.c prng.c prof.c quarantine.c rtree.c stats.c \
-	tcache.c ticker.c tsd.c util.c witness.c
+	mutex.c nstime.c pages.c prng.c prof.c quarantine.c rtree.c spin.c \
+	stats.c tcache.c ticker.c tsd.c util.c witness.c
 
 SYM_MAPS+=${LIBC_SRCTOP}/stdlib/jemalloc/Symbol.map
 

From ebcddc721771e8c70f98b61576242d2e4983682b Mon Sep 17 00:00:00 2001
From: Alan Cox 
Date: Wed, 9 Nov 2016 18:48:37 +0000
Subject: [PATCH 115/127] Introduce a new page queue, PQ_LAUNDRY, for storing
 unreferenced, dirty pages, specificially, dirty pages that have passed once
 through the inactive queue.  A new, dedicated thread is responsible for both
 deciding when to launder pages and actually laundering them.  The new policy
 uses the relative sizes of the inactive and laundry queues to determine
 whether to launder pages at a given point in time.  In general, this leads to
 more intelligent swapping behavior, since the laundry thread will avoid
 pageouts when the marginal benefit of doing so is low.  Previously, without a
 dedicated queue for dirty pages, the page daemon didn't have the information
 to determine whether pageout provides any benefit to the system.  Thus, the
 previous policy often resulted in small but steadily increasing amounts of
 swap usage when the system is under memory pressure, even when the inactive
 queue consisted mostly of clean pages.  This change addresses that issue, and
 also paves the way for some future virtual memory system improvements by
 removing the last source of object-cached clean pages, i.e., PG_CACHE pages.

The new laundry thread sleeps while waiting for a request from the page
daemon thread(s).  A request is raised by setting the variable
vm_laundry_request and waking the laundry thread.  We request launderings
for two reasons: to try and balance the inactive and laundry queue sizes
("background laundering"), and to quickly make up for a shortage of free
pages and clean inactive pages ("shortfall laundering").  When background
laundering is requested, the laundry thread computes the number of page
daemon wakeups that have taken place since the last laundering.  If this
number is large enough relative to the ratio of the laundry and (global)
inactive queue sizes, we will launder vm_background_launder_target pages at
vm_background_launder_rate KB/s.  Otherwise, the laundry thread goes back
to sleep without doing any work.  When scanning the laundry queue during
background laundering, reactivated pages are counted towards the laundry
thread's target.

In contrast, shortfall laundering is requested when an inactive queue scan
fails to meet its target.  In this case, the laundry thread attempts to
launder enough pages to meet v_free_target within 0.5s, which is the
inactive queue scan period.

A laundry request can be latched while another is currently being
serviced.  In particular, a shortfall request will immediately preempt a
background laundering.

This change also redefines the meaning of vm_cnt.v_reactivated and removes
the functions vm_page_cache() and vm_page_try_to_cache().  The new meaning
of vm_cnt.v_reactivated now better reflects its name.  It represents the
number of inactive or laundry pages that are returned to the active queue
on account of a reference.

In collaboration with:	markj
Reviewed by:	kib
Tested by:	pho
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D8302
---
 sys/sys/vmmeter.h   |  24 +-
 sys/vm/swap_pager.c |  28 +-
 sys/vm/vm_fault.c   |   9 +-
 sys/vm/vm_meter.c   |  38 ++-
 sys/vm/vm_object.c  |   4 +-
 sys/vm/vm_page.c    | 180 +++---------
 sys/vm/vm_page.h    |  30 +-
 sys/vm/vm_pageout.c | 693 +++++++++++++++++++++++++++++++++++---------
 8 files changed, 686 insertions(+), 320 deletions(-)

diff --git a/sys/sys/vmmeter.h b/sys/sys/vmmeter.h
index 39f03d0d7075..54291f5f0308 100644
--- a/sys/sys/vmmeter.h
+++ b/sys/sys/vmmeter.h
@@ -75,9 +75,10 @@ struct vmmeter {
 	u_int v_vnodepgsin;	/* (p) vnode_pager pages paged in */
 	u_int v_vnodepgsout;	/* (p) vnode pager pages paged out */
 	u_int v_intrans;	/* (p) intransit blocking page faults */
-	u_int v_reactivated;	/* (f) pages reactivated from free list */
+	u_int v_reactivated;	/* (p) pages reactivated by the pagedaemon */
 	u_int v_pdwakeups;	/* (p) times daemon has awaken from sleep */
 	u_int v_pdpages;	/* (p) pages analyzed by daemon */
+	u_int v_pdshortfalls;	/* (p) page reclamation shortfalls */
 
 	u_int v_tcached;	/* (p) total pages cached */
 	u_int v_dfree;		/* (p) pages freed by daemon */
@@ -96,6 +97,7 @@ struct vmmeter {
 	u_int v_active_count;	/* (q) pages active */
 	u_int v_inactive_target; /* (c) pages desired inactive */
 	u_int v_inactive_count;	/* (q) pages inactive */
+	u_int v_laundry_count;	/* (q) pages eligible for laundering */
 	u_int v_cache_count;	/* (f) pages on cache queue */
 	u_int v_pageout_free_min;   /* (c) min pages reserved for kernel */
 	u_int v_interrupt_free_min; /* (c) reserved pages for int code */
@@ -111,7 +113,6 @@ struct vmmeter {
 	u_int v_vforkpages;	/* (p) VM pages affected by vfork() */
 	u_int v_rforkpages;	/* (p) VM pages affected by rfork() */
 	u_int v_kthreadpages;	/* (p) VM pages affected by fork() by kernel */
-	u_int v_spare[2];
 };
 #ifdef _KERNEL
 
@@ -184,6 +185,25 @@ vm_paging_needed(void)
 	    vm_pageout_wakeup_thresh);
 }
 
+/*
+ * Return the number of pages we need to launder.
+ * A positive number indicates that we have a shortfall of clean pages.
+ */
+static inline int
+vm_laundry_target(void)
+{
+
+	return (vm_paging_target());
+}
+
+/*
+ * Obtain the value of a per-CPU counter.
+ */
+#define	VM_METER_PCPU_CNT(member)					\
+	vm_meter_cnt(__offsetof(struct vmmeter, member))
+
+u_int	vm_meter_cnt(size_t);
+
 #endif
 
 /* systemwide totals computed every five seconds */
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 04cd349dfc25..8f46cf38e7bc 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -1549,17 +1549,18 @@ swp_pager_async_iodone(struct buf *bp)
 			 * For write success, clear the dirty
 			 * status, then finish the I/O ( which decrements the
 			 * busy count and possibly wakes waiter's up ).
+			 * A page is only written to swap after a period of
+			 * inactivity.  Therefore, we do not expect it to be
+			 * reused.
 			 */
 			KASSERT(!pmap_page_is_write_mapped(m),
 			    ("swp_pager_async_iodone: page %p is not write"
 			    " protected", m));
 			vm_page_undirty(m);
+			vm_page_lock(m);
+			vm_page_deactivate_noreuse(m);
+			vm_page_unlock(m);
 			vm_page_sunbusy(m);
-			if (vm_page_count_severe()) {
-				vm_page_lock(m);
-				vm_page_try_to_cache(m);
-				vm_page_unlock(m);
-			}
 		}
 	}
 
@@ -1635,12 +1636,15 @@ swap_pager_isswapped(vm_object_t object, struct swdevt *sp)
 /*
  * SWP_PAGER_FORCE_PAGEIN() - force a swap block to be paged in
  *
- *	This routine dissociates the page at the given index within a
- *	swap block from its backing store, paging it in if necessary.
- *	If the page is paged in, it is placed in the inactive queue,
- *	since it had its backing store ripped out from under it.
- *	We also attempt to swap in all other pages in the swap block,
- *	we only guarantee that the one at the specified index is
+ *	This routine dissociates the page at the given index within an object
+ *	from its backing store, paging it in if it does not reside in memory.
+ *	If the page is paged in, it is marked dirty and placed in the laundry
+ *	queue.  The page is marked dirty because it no longer has backing
+ *	store.  It is placed in the laundry queue because it has not been
+ *	accessed recently.  Otherwise, it would already reside in memory.
+ *
+ *	We also attempt to swap in all other pages in the swap block.
+ *	However, we only guarantee that the one at the specified index is
  *	paged in.
  *
  *	XXX - The code to page the whole block in doesn't work, so we
@@ -1669,7 +1673,7 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex)
 	vm_object_pip_wakeup(object);
 	vm_page_dirty(m);
 	vm_page_lock(m);
-	vm_page_deactivate(m);
+	vm_page_launder(m);
 	vm_page_unlock(m);
 	vm_page_xunbusy(m);
 	vm_pager_page_unswapped(m);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 11993054d0c0..b73cf6459188 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -290,12 +290,13 @@ int
 vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
     int fault_flags, vm_page_t *m_hold)
 {
-	vm_prot_t prot;
-	vm_object_t next_object;
 	struct faultstate fs;
 	struct vnode *vp;
+	vm_object_t next_object, retry_object;
 	vm_offset_t e_end, e_start;
 	vm_page_t m;
+	vm_pindex_t retry_pindex;
+	vm_prot_t prot, retry_prot;
 	int ahead, alloc_req, behind, cluster_offset, error, era, faultcount;
 	int locked, map_generation, nera, result, rv;
 	u_char behavior;
@@ -946,10 +947,6 @@ RetryFault:;
 	 * lookup.
 	 */
 	if (!fs.lookup_still_valid) {
-		vm_object_t retry_object;
-		vm_pindex_t retry_pindex;
-		vm_prot_t retry_prot;
-
 		if (!vm_map_trylock_read(fs.map)) {
 			release_page(&fs);
 			unlock_and_deallocate(&fs);
diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c
index d06cab33f366..862b2e3740f0 100644
--- a/sys/vm/vm_meter.c
+++ b/sys/vm/vm_meter.c
@@ -216,29 +216,37 @@ vmtotal(SYSCTL_HANDLER_ARGS)
 }
 
 /*
- * vcnt() -	accumulate statistics from all cpus and the global cnt
- *		structure.
+ * vm_meter_cnt() -	accumulate statistics from all cpus and the global cnt
+ *			structure.
  *
  *	The vmmeter structure is now per-cpu as well as global.  Those
  *	statistics which can be kept on a per-cpu basis (to avoid cache
  *	stalls between cpus) can be moved to the per-cpu vmmeter.  Remaining
  *	statistics, such as v_free_reserved, are left in the global
  *	structure.
- *
- * (sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req)
  */
-static int
-vcnt(SYSCTL_HANDLER_ARGS)
+u_int
+vm_meter_cnt(size_t offset)
 {
-	int count = *(int *)arg1;
-	int offset = (char *)arg1 - (char *)&vm_cnt;
+	struct pcpu *pcpu;
+	u_int count;
 	int i;
 
+	count = *(u_int *)((char *)&vm_cnt + offset);
 	CPU_FOREACH(i) {
-		struct pcpu *pcpu = pcpu_find(i);
-		count += *(int *)((char *)&pcpu->pc_cnt + offset);
+		pcpu = pcpu_find(i);
+		count += *(u_int *)((char *)&pcpu->pc_cnt + offset);
 	}
-	return (SYSCTL_OUT(req, &count, sizeof(int)));
+	return (count);
+}
+
+static int
+cnt_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	u_int count;
+
+	count = vm_meter_cnt((char *)arg1 - (char *)&vm_cnt);
+	return (SYSCTL_OUT(req, &count, sizeof(count)));
 }
 
 SYSCTL_PROC(_vm, VM_TOTAL, vmtotal, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,
@@ -253,8 +261,8 @@ SYSCTL_NODE(_vm_stats, OID_AUTO, misc, CTLFLAG_RW, 0, "VM meter misc stats");
 
 #define	VM_STATS(parent, var, descr) \
 	SYSCTL_PROC(parent, OID_AUTO, var, \
-	    CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, &vm_cnt.var, 0, vcnt, \
-	    "IU", descr)
+	    CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, &vm_cnt.var, 0,	\
+	    cnt_sysctl, "IU", descr)
 #define	VM_STATS_VM(var, descr)		VM_STATS(_vm_stats_vm, var, descr)
 #define	VM_STATS_SYS(var, descr)	VM_STATS(_vm_stats_sys, var, descr)
 
@@ -278,9 +286,10 @@ VM_STATS_VM(v_vnodeout, "Vnode pager pageouts");
 VM_STATS_VM(v_vnodepgsin, "Vnode pages paged in");
 VM_STATS_VM(v_vnodepgsout, "Vnode pages paged out");
 VM_STATS_VM(v_intrans, "In transit page faults");
-VM_STATS_VM(v_reactivated, "Pages reactivated from free list");
+VM_STATS_VM(v_reactivated, "Pages reactivated by pagedaemon");
 VM_STATS_VM(v_pdwakeups, "Pagedaemon wakeups");
 VM_STATS_VM(v_pdpages, "Pages analyzed by pagedaemon");
+VM_STATS_VM(v_pdshortfalls, "Page reclamation shortfalls");
 VM_STATS_VM(v_tcached, "Total pages cached");
 VM_STATS_VM(v_dfree, "Pages freed by pagedaemon");
 VM_STATS_VM(v_pfree, "Pages freed by exiting processes");
@@ -295,6 +304,7 @@ VM_STATS_VM(v_wire_count, "Wired pages");
 VM_STATS_VM(v_active_count, "Active pages");
 VM_STATS_VM(v_inactive_target, "Desired inactive pages");
 VM_STATS_VM(v_inactive_count, "Inactive pages");
+VM_STATS_VM(v_laundry_count, "Pages eligible for laundering");
 VM_STATS_VM(v_cache_count, "Pages on cache queue");
 VM_STATS_VM(v_pageout_free_min, "Min pages reserved for kernel");
 VM_STATS_VM(v_interrupt_free_min, "Reserved pages for interrupt code");
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 7321990c5408..0cf364fcaa47 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -2329,9 +2329,9 @@ sysctl_vm_object_list(SYSCTL_HANDLER_ARGS)
 			 * sysctl is only meant to give an
 			 * approximation of the system anyway.
 			 */
-			if (m->queue == PQ_ACTIVE)
+			if (vm_page_active(m))
 				kvo.kvo_active++;
-			else if (m->queue == PQ_INACTIVE)
+			else if (vm_page_inactive(m))
 				kvo.kvo_inactive++;
 		}
 
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index a012a1697f2f..78bf98ae0164 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -390,6 +390,10 @@ vm_page_domain_init(struct vm_domain *vmd)
 	    "vm active pagequeue";
 	*__DECONST(u_int **, &vmd->vmd_pagequeues[PQ_ACTIVE].pq_vcnt) =
 	    &vm_cnt.v_active_count;
+	*__DECONST(char **, &vmd->vmd_pagequeues[PQ_LAUNDRY].pq_name) =
+	    "vm laundry pagequeue";
+	*__DECONST(int **, &vmd->vmd_pagequeues[PQ_LAUNDRY].pq_vcnt) =
+	    &vm_cnt.v_laundry_count;
 	vmd->vmd_page_count = 0;
 	vmd->vmd_free_count = 0;
 	vmd->vmd_segs = 0;
@@ -1730,9 +1734,7 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
 		    ("vm_page_alloc: cached page %p is PG_ZERO", m));
 		KASSERT(m->valid != 0,
 		    ("vm_page_alloc: cached page %p is invalid", m));
-		if (m->object == object && m->pindex == pindex)
-			vm_cnt.v_reactivated++;
-		else
+		if (m->object != object || m->pindex != pindex)
 			m->valid = 0;
 		m_object = m->object;
 		vm_page_cache_remove(m);
@@ -2254,7 +2256,7 @@ vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
 			}
 			KASSERT((m->flags & PG_UNHOLDFREE) == 0,
 			    ("page %p is PG_UNHOLDFREE", m));
-			/* Don't care: PG_NODUMP, PG_WINATCFLS, PG_ZERO. */
+			/* Don't care: PG_NODUMP, PG_ZERO. */
 			if (object->type != OBJT_DEFAULT &&
 			    object->type != OBJT_SWAP &&
 			    object->type != OBJT_VNODE)
@@ -2450,7 +2452,7 @@ vm_page_reclaim_run(int req_class, u_long npages, vm_page_t m_run,
 			}
 			KASSERT((m->flags & PG_UNHOLDFREE) == 0,
 			    ("page %p is PG_UNHOLDFREE", m));
-			/* Don't care: PG_NODUMP, PG_WINATCFLS, PG_ZERO. */
+			/* Don't care: PG_NODUMP, PG_ZERO. */
 			if (object->type != OBJT_DEFAULT &&
 			    object->type != OBJT_SWAP &&
 			    object->type != OBJT_VNODE)
@@ -2778,7 +2780,10 @@ struct vm_pagequeue *
 vm_page_pagequeue(vm_page_t m)
 {
 
-	return (&vm_phys_domain(m)->vmd_pagequeues[m->queue]);
+	if (vm_page_in_laundry(m))
+		return (&vm_dom[0].vmd_pagequeues[m->queue]);
+	else
+		return (&vm_phys_domain(m)->vmd_pagequeues[m->queue]);
 }
 
 /*
@@ -2840,7 +2845,10 @@ vm_page_enqueue(uint8_t queue, vm_page_t m)
 	KASSERT(queue < PQ_COUNT,
 	    ("vm_page_enqueue: invalid queue %u request for page %p",
 	    queue, m));
-	pq = &vm_phys_domain(m)->vmd_pagequeues[queue];
+	if (queue == PQ_LAUNDRY)
+		pq = &vm_dom[0].vmd_pagequeues[queue];
+	else
+		pq = &vm_phys_domain(m)->vmd_pagequeues[queue];
 	vm_pagequeue_lock(pq);
 	m->queue = queue;
 	TAILQ_INSERT_TAIL(&pq->pq_pl, m, plinks.q);
@@ -3124,11 +3132,8 @@ vm_page_unwire(vm_page_t m, uint8_t queue)
 		if (m->wire_count == 0) {
 			atomic_subtract_int(&vm_cnt.v_wire_count, 1);
 			if ((m->oflags & VPO_UNMANAGED) == 0 &&
-			    m->object != NULL && queue != PQ_NONE) {
-				if (queue == PQ_INACTIVE)
-					m->flags &= ~PG_WINATCFLS;
+			    m->object != NULL && queue != PQ_NONE)
 				vm_page_enqueue(queue, m);
-			}
 			return (TRUE);
 		} else
 			return (FALSE);
@@ -3181,7 +3186,6 @@ _vm_page_deactivate(vm_page_t m, boolean_t noreuse)
 		} else {
 			if (queue != PQ_NONE)
 				vm_page_dequeue(m);
-			m->flags &= ~PG_WINATCFLS;
 			vm_pagequeue_lock(pq);
 		}
 		m->queue = PQ_INACTIVE;
@@ -3221,24 +3225,25 @@ vm_page_deactivate_noreuse(vm_page_t m)
 }
 
 /*
- * vm_page_try_to_cache:
+ * vm_page_launder
  *
- * Returns 0 on failure, 1 on success
+ * 	Put a page in the laundry.
  */
-int
-vm_page_try_to_cache(vm_page_t m)
+void
+vm_page_launder(vm_page_t m)
 {
+	int queue;
 
-	vm_page_lock_assert(m, MA_OWNED);
-	VM_OBJECT_ASSERT_WLOCKED(m->object);
-	if (m->dirty || m->hold_count || m->wire_count ||
-	    (m->oflags & VPO_UNMANAGED) != 0 || vm_page_busied(m))
-		return (0);
-	pmap_remove_all(m);
-	if (m->dirty)
-		return (0);
-	vm_page_cache(m);
-	return (1);
+	vm_page_assert_locked(m);
+	if ((queue = m->queue) != PQ_LAUNDRY) {
+		if (m->wire_count == 0 && (m->oflags & VPO_UNMANAGED) == 0) {
+			if (queue != PQ_NONE)
+				vm_page_dequeue(m);
+			vm_page_enqueue(PQ_LAUNDRY, m);
+		} else
+			KASSERT(queue == PQ_NONE,
+			    ("wired page %p is queued", m));
+	}
 }
 
 /*
@@ -3264,112 +3269,6 @@ vm_page_try_to_free(vm_page_t m)
 	return (1);
 }
 
-/*
- * vm_page_cache
- *
- * Put the specified page onto the page cache queue (if appropriate).
- *
- * The object and page must be locked.
- */
-void
-vm_page_cache(vm_page_t m)
-{
-	vm_object_t object;
-	boolean_t cache_was_empty;
-
-	vm_page_lock_assert(m, MA_OWNED);
-	object = m->object;
-	VM_OBJECT_ASSERT_WLOCKED(object);
-	if (vm_page_busied(m) || (m->oflags & VPO_UNMANAGED) ||
-	    m->hold_count || m->wire_count)
-		panic("vm_page_cache: attempting to cache busy page");
-	KASSERT(!pmap_page_is_mapped(m),
-	    ("vm_page_cache: page %p is mapped", m));
-	KASSERT(m->dirty == 0, ("vm_page_cache: page %p is dirty", m));
-	if (m->valid == 0 || object->type == OBJT_DEFAULT ||
-	    (object->type == OBJT_SWAP &&
-	    !vm_pager_has_page(object, m->pindex, NULL, NULL))) {
-		/*
-		 * Hypothesis: A cache-eligible page belonging to a
-		 * default object or swap object but without a backing
-		 * store must be zero filled.
-		 */
-		vm_page_free(m);
-		return;
-	}
-	KASSERT((m->flags & PG_CACHED) == 0,
-	    ("vm_page_cache: page %p is already cached", m));
-
-	/*
-	 * Remove the page from the paging queues.
-	 */
-	vm_page_remque(m);
-
-	/*
-	 * Remove the page from the object's collection of resident
-	 * pages.
-	 */
-	vm_radix_remove(&object->rtree, m->pindex);
-	TAILQ_REMOVE(&object->memq, m, listq);
-	object->resident_page_count--;
-
-	/*
-	 * Restore the default memory attribute to the page.
-	 */
-	if (pmap_page_get_memattr(m) != VM_MEMATTR_DEFAULT)
-		pmap_page_set_memattr(m, VM_MEMATTR_DEFAULT);
-
-	/*
-	 * Insert the page into the object's collection of cached pages
-	 * and the physical memory allocator's cache/free page queues.
-	 */
-	m->flags &= ~PG_ZERO;
-	mtx_lock(&vm_page_queue_free_mtx);
-	cache_was_empty = vm_radix_is_empty(&object->cache);
-	if (vm_radix_insert(&object->cache, m)) {
-		mtx_unlock(&vm_page_queue_free_mtx);
-		if (object->type == OBJT_VNODE &&
-		    object->resident_page_count == 0)
-			vdrop(object->handle);
-		m->object = NULL;
-		vm_page_free(m);
-		return;
-	}
-
-	/*
-	 * The above call to vm_radix_insert() could reclaim the one pre-
-	 * existing cached page from this object, resulting in a call to
-	 * vdrop().
-	 */
-	if (!cache_was_empty)
-		cache_was_empty = vm_radix_is_singleton(&object->cache);
-
-	m->flags |= PG_CACHED;
-	vm_cnt.v_cache_count++;
-	PCPU_INC(cnt.v_tcached);
-#if VM_NRESERVLEVEL > 0
-	if (!vm_reserv_free_page(m)) {
-#else
-	if (TRUE) {
-#endif
-		vm_phys_free_pages(m, 0);
-	}
-	vm_page_free_wakeup();
-	mtx_unlock(&vm_page_queue_free_mtx);
-
-	/*
-	 * Increment the vnode's hold count if this is the object's only
-	 * cached page.  Decrement the vnode's hold count if this was
-	 * the object's only resident page.
-	 */
-	if (object->type == OBJT_VNODE) {
-		if (cache_was_empty && object->resident_page_count != 0)
-			vhold(object->handle);
-		else if (!cache_was_empty && object->resident_page_count == 0)
-			vdrop(object->handle);
-	}
-}
-
 /*
  * vm_page_advise
  *
@@ -3413,11 +3312,13 @@ vm_page_advise(vm_page_t m, int advice)
 	/*
 	 * Place clean pages near the head of the inactive queue rather than
 	 * the tail, thus defeating the queue's LRU operation and ensuring that
-	 * the page will be reused quickly.  Dirty pages are given a chance to
-	 * cycle once through the inactive queue before becoming eligible for
-	 * laundering.
+	 * the page will be reused quickly.  Dirty pages not already in the
+	 * laundry are moved there.
 	 */
-	_vm_page_deactivate(m, m->dirty == 0);
+	if (m->dirty == 0)
+		vm_page_deactivate_noreuse(m);
+	else
+		vm_page_launder(m);
 }
 
 /*
@@ -3926,6 +3827,7 @@ DB_SHOW_COMMAND(page, vm_page_print_page_info)
 	db_printf("vm_cnt.v_cache_count: %d\n", vm_cnt.v_cache_count);
 	db_printf("vm_cnt.v_inactive_count: %d\n", vm_cnt.v_inactive_count);
 	db_printf("vm_cnt.v_active_count: %d\n", vm_cnt.v_active_count);
+	db_printf("vm_cnt.v_laundry_count: %d\n", vm_cnt.v_laundry_count);
 	db_printf("vm_cnt.v_wire_count: %d\n", vm_cnt.v_wire_count);
 	db_printf("vm_cnt.v_free_reserved: %d\n", vm_cnt.v_free_reserved);
 	db_printf("vm_cnt.v_free_min: %d\n", vm_cnt.v_free_min);
@@ -3940,12 +3842,14 @@ DB_SHOW_COMMAND(pageq, vm_page_print_pageq_info)
 	db_printf("pq_free %d pq_cache %d\n",
 	    vm_cnt.v_free_count, vm_cnt.v_cache_count);
 	for (dom = 0; dom < vm_ndomains; dom++) {
-		db_printf("dom %d page_cnt %d free %d pq_act %d pq_inact %d\n",
+		db_printf(
+	    "dom %d page_cnt %d free %d pq_act %d pq_inact %d pq_laund %d\n",
 		    dom,
 		    vm_dom[dom].vmd_page_count,
 		    vm_dom[dom].vmd_free_count,
 		    vm_dom[dom].vmd_pagequeues[PQ_ACTIVE].pq_cnt,
-		    vm_dom[dom].vmd_pagequeues[PQ_INACTIVE].pq_cnt);
+		    vm_dom[dom].vmd_pagequeues[PQ_INACTIVE].pq_cnt,
+		    vm_dom[dom].vmd_pagequeues[PQ_LAUNDRY].pq_cnt);
 	}
 }
 
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 8aca3c1d7125..417d9d87a72b 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -206,7 +206,8 @@ struct vm_page {
 #define	PQ_NONE		255
 #define	PQ_INACTIVE	0
 #define	PQ_ACTIVE	1
-#define	PQ_COUNT	2
+#define	PQ_LAUNDRY	2
+#define	PQ_COUNT	3
 
 TAILQ_HEAD(pglist, vm_page);
 SLIST_HEAD(spglist, vm_page);
@@ -228,6 +229,7 @@ struct vm_domain {
 	boolean_t vmd_oom;
 	int vmd_oom_seq;
 	int vmd_last_active_scan;
+	struct vm_page vmd_laundry_marker;
 	struct vm_page vmd_marker; /* marker for pagedaemon private use */
 	struct vm_page vmd_inacthead; /* marker for LRU-defeating insertions */
 };
@@ -236,6 +238,7 @@ extern struct vm_domain vm_dom[MAXMEMDOM];
 
 #define	vm_pagequeue_assert_locked(pq)	mtx_assert(&(pq)->pq_mutex, MA_OWNED)
 #define	vm_pagequeue_lock(pq)		mtx_lock(&(pq)->pq_mutex)
+#define	vm_pagequeue_lockptr(pq)	(&(pq)->pq_mutex)
 #define	vm_pagequeue_unlock(pq)		mtx_unlock(&(pq)->pq_mutex)
 
 #ifdef _KERNEL
@@ -327,7 +330,6 @@ extern struct mtx_padalign pa_lock[];
 #define	PG_FICTITIOUS	0x0004		/* physical page doesn't exist */
 #define	PG_ZERO		0x0008		/* page is zeroed */
 #define	PG_MARKER	0x0010		/* special queue marker page */
-#define	PG_WINATCFLS	0x0040		/* flush dirty page on inactive q */
 #define	PG_NODUMP	0x0080		/* don't include this page in a dump */
 #define	PG_UNHOLDFREE	0x0100		/* delayed free of a held page */
 
@@ -451,10 +453,8 @@ vm_page_t vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req,
     vm_paddr_t boundary, vm_memattr_t memattr);
 vm_page_t vm_page_alloc_freelist(int, int);
 vm_page_t vm_page_grab (vm_object_t, vm_pindex_t, int);
-void vm_page_cache(vm_page_t);
 void vm_page_cache_free(vm_object_t, vm_pindex_t, vm_pindex_t);
 void vm_page_cache_transfer(vm_object_t, vm_pindex_t, vm_object_t);
-int vm_page_try_to_cache (vm_page_t);
 int vm_page_try_to_free (vm_page_t);
 void vm_page_deactivate (vm_page_t);
 void vm_page_deactivate_noreuse(vm_page_t);
@@ -465,6 +465,7 @@ vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr);
 void vm_page_initfake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr);
 int vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t);
 boolean_t vm_page_is_cached(vm_object_t object, vm_pindex_t pindex);
+void vm_page_launder(vm_page_t m);
 vm_page_t vm_page_lookup (vm_object_t, vm_pindex_t);
 vm_page_t vm_page_next(vm_page_t m);
 int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
@@ -697,5 +698,26 @@ vm_page_replace_checked(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex,
 	(void)mret;
 }
 
+static inline bool
+vm_page_active(vm_page_t m)
+{
+
+	return (m->queue == PQ_ACTIVE);
+}
+
+static inline bool
+vm_page_inactive(vm_page_t m)
+{
+
+	return (m->queue == PQ_INACTIVE);
+}
+
+static inline bool
+vm_page_in_laundry(vm_page_t m)
+{
+
+	return (m->queue == PQ_LAUNDRY);
+}
+
 #endif				/* _KERNEL */
 #endif				/* !_VM_PAGE_ */
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index ed71109cbf39..6c2cefe6462c 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -119,7 +119,7 @@ __FBSDID("$FreeBSD$");
 /* the kernel process "vm_pageout"*/
 static void vm_pageout(void);
 static void vm_pageout_init(void);
-static int vm_pageout_clean(vm_page_t m);
+static int vm_pageout_clean(vm_page_t m, int *numpagedout);
 static int vm_pageout_cluster(vm_page_t m);
 static bool vm_pageout_scan(struct vm_domain *vmd, int pass);
 static void vm_pageout_mightbe_oom(struct vm_domain *vmd, int page_shortage,
@@ -154,6 +154,9 @@ static struct kproc_desc vm_kp = {
 SYSINIT(vmdaemon, SI_SUB_KTHREAD_VM, SI_ORDER_FIRST, kproc_start, &vm_kp);
 #endif
 
+/* Pagedaemon activity rates, in subdivisions of one second. */
+#define	VM_LAUNDER_RATE		10
+#define	VM_INACT_SCAN_RATE	2
 
 int vm_pageout_deficit;		/* Estimated number of pages deficit */
 u_int vm_pageout_wakeup_thresh;
@@ -161,6 +164,13 @@ static int vm_pageout_oom_seq = 12;
 bool vm_pageout_wanted;		/* Event on which pageout daemon sleeps */
 bool vm_pages_needed;		/* Are threads waiting for free pages? */
 
+/* Pending request for dirty page laundering. */
+static enum {
+	VM_LAUNDRY_IDLE,
+	VM_LAUNDRY_BACKGROUND,
+	VM_LAUNDRY_SHORTFALL
+} vm_laundry_request = VM_LAUNDRY_IDLE;
+
 #if !defined(NO_SWAPPING)
 static int vm_pageout_req_swapout;	/* XXX */
 static int vm_daemon_needed;
@@ -168,9 +178,7 @@ static struct mtx vm_daemon_mtx;
 /* Allow for use by vm_pageout before vm_daemon is initialized. */
 MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
 #endif
-static int vm_max_launder = 32;
 static int vm_pageout_update_period;
-static int defer_swap_pageouts;
 static int disable_swap_pageouts;
 static int lowmem_period = 10;
 static time_t lowmem_uptime;
@@ -193,9 +201,6 @@ SYSCTL_INT(_vm, OID_AUTO, pageout_wakeup_thresh,
 	CTLFLAG_RW, &vm_pageout_wakeup_thresh, 0,
 	"free page threshold for waking up the pageout daemon");
 
-SYSCTL_INT(_vm, OID_AUTO, max_launder,
-	CTLFLAG_RW, &vm_max_launder, 0, "Limit dirty flushes in pageout");
-
 SYSCTL_INT(_vm, OID_AUTO, pageout_update_period,
 	CTLFLAG_RW, &vm_pageout_update_period, 0,
 	"Maximum active LRU update period");
@@ -215,9 +220,6 @@ SYSCTL_INT(_vm, OID_AUTO, swap_idle_enabled,
 	CTLFLAG_RW, &vm_swap_idle_enabled, 0, "Allow swapout on idle criteria");
 #endif
 
-SYSCTL_INT(_vm, OID_AUTO, defer_swapspace_pageouts,
-	CTLFLAG_RW, &defer_swap_pageouts, 0, "Give preference to dirty pages in mem");
-
 SYSCTL_INT(_vm, OID_AUTO, disable_swapspace_pageouts,
 	CTLFLAG_RW, &disable_swap_pageouts, 0, "Disallow swapout of dirty pages");
 
@@ -229,6 +231,25 @@ SYSCTL_INT(_vm, OID_AUTO, pageout_oom_seq,
 	CTLFLAG_RW, &vm_pageout_oom_seq, 0,
 	"back-to-back calls to oom detector to start OOM");
 
+static int act_scan_laundry_weight = 3;
+SYSCTL_INT(_vm, OID_AUTO, act_scan_laundry_weight, CTLFLAG_RW,
+    &act_scan_laundry_weight, 0,
+    "weight given to clean vs. dirty pages in active queue scans");
+
+static u_int vm_background_launder_target;
+SYSCTL_UINT(_vm, OID_AUTO, background_launder_target, CTLFLAG_RW,
+    &vm_background_launder_target, 0,
+    "background laundering target, in pages");
+
+static u_int vm_background_launder_rate = 4096;
+SYSCTL_UINT(_vm, OID_AUTO, background_launder_rate, CTLFLAG_RW,
+    &vm_background_launder_rate, 0,
+    "background laundering rate, in kilobytes per second");
+
+static u_int vm_background_launder_max = 20 * 1024;
+SYSCTL_UINT(_vm, OID_AUTO, background_launder_max, CTLFLAG_RW,
+    &vm_background_launder_max, 0, "background laundering cap, in kilobytes");
+
 #define VM_PAGEOUT_PAGE_COUNT 16
 int vm_pageout_page_count = VM_PAGEOUT_PAGE_COUNT;
 
@@ -236,7 +257,11 @@ int vm_page_max_wired;		/* XXX max # of wired pages system-wide */
 SYSCTL_INT(_vm, OID_AUTO, max_wired,
 	CTLFLAG_RW, &vm_page_max_wired, 0, "System-wide limit to wired page count");
 
+static u_int isqrt(u_int num);
 static boolean_t vm_pageout_fallback_object_lock(vm_page_t, vm_page_t *);
+static int vm_pageout_launder(struct vm_domain *vmd, int launder,
+    bool in_shortfall);
+static void vm_pageout_laundry_worker(void *arg);
 #if !defined(NO_SWAPPING)
 static void vm_pageout_map_deactivate_pages(vm_map_t, long);
 static void vm_pageout_object_deactivate_pages(pmap_t, vm_object_t, long);
@@ -387,7 +412,7 @@ vm_pageout_cluster(vm_page_t m)
 
 	/*
 	 * We can cluster only if the page is not clean, busy, or held, and
-	 * the page is inactive.
+	 * the page is in the laundry queue.
 	 *
 	 * During heavy mmap/modification loads the pageout
 	 * daemon can really fragment the underlying file
@@ -413,7 +438,7 @@ vm_pageout_cluster(vm_page_t m)
 			break;
 		}
 		vm_page_lock(p);
-		if (p->queue != PQ_INACTIVE ||
+		if (!vm_page_in_laundry(p) ||
 		    p->hold_count != 0) {	/* may be undergoing I/O */
 			vm_page_unlock(p);
 			ib = 0;
@@ -439,7 +464,7 @@ vm_pageout_cluster(vm_page_t m)
 		if (p->dirty == 0)
 			break;
 		vm_page_lock(p);
-		if (p->queue != PQ_INACTIVE ||
+		if (!vm_page_in_laundry(p) ||
 		    p->hold_count != 0) {	/* may be undergoing I/O */
 			vm_page_unlock(p);
 			break;
@@ -519,23 +544,33 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags, int mreq, int *prunlen,
 		    ("vm_pageout_flush: page %p is not write protected", mt));
 		switch (pageout_status[i]) {
 		case VM_PAGER_OK:
+			vm_page_lock(mt);
+			if (vm_page_in_laundry(mt))
+				vm_page_deactivate_noreuse(mt);
+			vm_page_unlock(mt);
+			/* FALLTHROUGH */
 		case VM_PAGER_PEND:
 			numpagedout++;
 			break;
 		case VM_PAGER_BAD:
 			/*
-			 * Page outside of range of object. Right now we
-			 * essentially lose the changes by pretending it
-			 * worked.
+			 * The page is outside the object's range.  We pretend
+			 * that the page out worked and clean the page, so the
+			 * changes will be lost if the page is reclaimed by
+			 * the page daemon.
 			 */
 			vm_page_undirty(mt);
+			vm_page_lock(mt);
+			if (vm_page_in_laundry(mt))
+				vm_page_deactivate_noreuse(mt);
+			vm_page_unlock(mt);
 			break;
 		case VM_PAGER_ERROR:
 		case VM_PAGER_FAIL:
 			/*
-			 * If page couldn't be paged out, then reactivate the
-			 * page so it doesn't clog the inactive list.  (We
-			 * will try paging out it again later).
+			 * If the page couldn't be paged out, then reactivate
+			 * it so that it doesn't clog the laundry and inactive
+			 * queues.  (We will try paging it out again later).
 			 */
 			vm_page_lock(mt);
 			vm_page_activate(mt);
@@ -617,10 +652,10 @@ vm_pageout_object_deactivate_pages(pmap_t pmap, vm_object_t first_object,
 					act_delta = 1;
 				vm_page_aflag_clear(p, PGA_REFERENCED);
 			}
-			if (p->queue != PQ_ACTIVE && act_delta != 0) {
+			if (!vm_page_active(p) && act_delta != 0) {
 				vm_page_activate(p);
 				p->act_count += act_delta;
-			} else if (p->queue == PQ_ACTIVE) {
+			} else if (vm_page_active(p)) {
 				if (act_delta == 0) {
 					p->act_count -= min(p->act_count,
 					    ACT_DECLINE);
@@ -636,7 +671,7 @@ vm_pageout_object_deactivate_pages(pmap_t pmap, vm_object_t first_object,
 						p->act_count += ACT_ADVANCE;
 					vm_page_requeue(p);
 				}
-			} else if (p->queue == PQ_INACTIVE)
+			} else if (vm_page_inactive(p))
 				pmap_remove_all(p);
 			vm_page_unlock(p);
 		}
@@ -739,7 +774,7 @@ vm_pageout_map_deactivate_pages(map, desired)
  * Returns 0 on success and an errno otherwise.
  */
 static int
-vm_pageout_clean(vm_page_t m)
+vm_pageout_clean(vm_page_t m, int *numpagedout)
 {
 	struct vnode *vp;
 	struct mount *mp;
@@ -797,7 +832,7 @@ vm_pageout_clean(vm_page_t m)
 		 * (3) reallocated to a different offset, or
 		 * (4) cleaned.
 		 */
-		if (m->queue != PQ_INACTIVE || m->object != object ||
+		if (!vm_page_in_laundry(m) || m->object != object ||
 		    m->pindex != pindex || m->dirty == 0) {
 			vm_page_unlock(m);
 			error = ENXIO;
@@ -821,7 +856,7 @@ vm_pageout_clean(vm_page_t m)
 	 * laundry.  If it is still in the laundry, then we
 	 * start the cleaning operation. 
 	 */
-	if (vm_pageout_cluster(m) == 0)
+	if ((*numpagedout = vm_pageout_cluster(m)) == 0)
 		error = EIO;
 
 unlock_all:
@@ -839,12 +874,391 @@ vm_pageout_clean(vm_page_t m)
 	return (error);
 }
 
+/*
+ * Attempt to launder the specified number of pages.
+ *
+ * Returns the number of pages successfully laundered.
+ */
+static int
+vm_pageout_launder(struct vm_domain *vmd, int launder, bool in_shortfall)
+{
+	struct vm_pagequeue *pq;
+	vm_object_t object;
+	vm_page_t m, next;
+	int act_delta, error, maxscan, numpagedout, starting_target;
+	int vnodes_skipped;
+	bool pageout_ok, queue_locked;
+
+	starting_target = launder;
+	vnodes_skipped = 0;
+
+	/*
+	 * Scan the laundry queue for pages eligible to be laundered.  We stop
+	 * once the target number of dirty pages have been laundered, or once
+	 * we've reached the end of the queue.  A single iteration of this loop
+	 * may cause more than one page to be laundered because of clustering.
+	 *
+	 * maxscan ensures that we don't re-examine requeued pages.  Any
+	 * additional pages written as part of a cluster are subtracted from
+	 * maxscan since they must be taken from the laundry queue.
+	 */
+	pq = &vmd->vmd_pagequeues[PQ_LAUNDRY];
+	maxscan = pq->pq_cnt;
+
+	vm_pagequeue_lock(pq);
+	queue_locked = true;
+	for (m = TAILQ_FIRST(&pq->pq_pl);
+	    m != NULL && maxscan-- > 0 && launder > 0;
+	    m = next) {
+		vm_pagequeue_assert_locked(pq);
+		KASSERT(queue_locked, ("unlocked laundry queue"));
+		KASSERT(vm_page_in_laundry(m),
+		    ("page %p has an inconsistent queue", m));
+		next = TAILQ_NEXT(m, plinks.q);
+		if ((m->flags & PG_MARKER) != 0)
+			continue;
+		KASSERT((m->flags & PG_FICTITIOUS) == 0,
+		    ("PG_FICTITIOUS page %p cannot be in laundry queue", m));
+		KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+		    ("VPO_UNMANAGED page %p cannot be in laundry queue", m));
+		if (!vm_pageout_page_lock(m, &next) || m->hold_count != 0) {
+			vm_page_unlock(m);
+			continue;
+		}
+		object = m->object;
+		if ((!VM_OBJECT_TRYWLOCK(object) &&
+		    (!vm_pageout_fallback_object_lock(m, &next) ||
+		    m->hold_count != 0)) || vm_page_busied(m)) {
+			VM_OBJECT_WUNLOCK(object);
+			vm_page_unlock(m);
+			continue;
+		}
+
+		/*
+		 * Unlock the laundry queue, invalidating the 'next' pointer.
+		 * Use a marker to remember our place in the laundry queue.
+		 */
+		TAILQ_INSERT_AFTER(&pq->pq_pl, m, &vmd->vmd_laundry_marker,
+		    plinks.q);
+		vm_pagequeue_unlock(pq);
+		queue_locked = false;
+
+		/*
+		 * Invalid pages can be easily freed.  They cannot be
+		 * mapped; vm_page_free() asserts this.
+		 */
+		if (m->valid == 0)
+			goto free_page;
+
+		/*
+		 * If the page has been referenced and the object is not dead,
+		 * reactivate or requeue the page depending on whether the
+		 * object is mapped.
+		 */
+		if ((m->aflags & PGA_REFERENCED) != 0) {
+			vm_page_aflag_clear(m, PGA_REFERENCED);
+			act_delta = 1;
+		} else
+			act_delta = 0;
+		if (object->ref_count != 0)
+			act_delta += pmap_ts_referenced(m);
+		else {
+			KASSERT(!pmap_page_is_mapped(m),
+			    ("page %p is mapped", m));
+		}
+		if (act_delta != 0) {
+			if (object->ref_count != 0) {
+				PCPU_INC(cnt.v_reactivated);
+				vm_page_activate(m);
+
+				/*
+				 * Increase the activation count if the page
+				 * was referenced while in the laundry queue.
+				 * This makes it less likely that the page will
+				 * be returned prematurely to the inactive
+				 * queue.
+ 				 */
+				m->act_count += act_delta + ACT_ADVANCE;
+
+				/*
+				 * If this was a background laundering, count
+				 * activated pages towards our target.  The
+				 * purpose of background laundering is to ensure
+				 * that pages are eventually cycled through the
+				 * laundry queue, and an activation is a valid
+				 * way out.
+				 */
+				if (!in_shortfall)
+					launder--;
+				goto drop_page;
+			} else if ((object->flags & OBJ_DEAD) == 0)
+				goto requeue_page;
+		}
+
+		/*
+		 * If the page appears to be clean at the machine-independent
+		 * layer, then remove all of its mappings from the pmap in
+		 * anticipation of freeing it.  If, however, any of the page's
+		 * mappings allow write access, then the page may still be
+		 * modified until the last of those mappings are removed.
+		 */
+		if (object->ref_count != 0) {
+			vm_page_test_dirty(m);
+			if (m->dirty == 0)
+				pmap_remove_all(m);
+		}
+
+		/*
+		 * Clean pages are freed, and dirty pages are paged out unless
+		 * they belong to a dead object.  Requeueing dirty pages from
+		 * dead objects is pointless, as they are being paged out and
+		 * freed by the thread that destroyed the object.
+		 */
+		if (m->dirty == 0) {
+free_page:
+			vm_page_free(m);
+			PCPU_INC(cnt.v_dfree);
+		} else if ((object->flags & OBJ_DEAD) == 0) {
+			if (object->type != OBJT_SWAP &&
+			    object->type != OBJT_DEFAULT)
+				pageout_ok = true;
+			else if (disable_swap_pageouts)
+				pageout_ok = false;
+			else
+				pageout_ok = true;
+			if (!pageout_ok) {
+requeue_page:
+				vm_pagequeue_lock(pq);
+				queue_locked = true;
+				vm_page_requeue_locked(m);
+				goto drop_page;
+			}
+
+			/*
+			 * Form a cluster with adjacent, dirty pages from the
+			 * same object, and page out that entire cluster.
+			 *
+			 * The adjacent, dirty pages must also be in the
+			 * laundry.  However, their mappings are not checked
+			 * for new references.  Consequently, a recently
+			 * referenced page may be paged out.  However, that
+			 * page will not be prematurely reclaimed.  After page
+			 * out, the page will be placed in the inactive queue,
+			 * where any new references will be detected and the
+			 * page reactivated.
+			 */
+			error = vm_pageout_clean(m, &numpagedout);
+			if (error == 0) {
+				launder -= numpagedout;
+				maxscan -= numpagedout - 1;
+			} else if (error == EDEADLK) {
+				pageout_lock_miss++;
+				vnodes_skipped++;
+			}
+			goto relock_queue;
+		}
+drop_page:
+		vm_page_unlock(m);
+		VM_OBJECT_WUNLOCK(object);
+relock_queue:
+		if (!queue_locked) {
+			vm_pagequeue_lock(pq);
+			queue_locked = true;
+		}
+		next = TAILQ_NEXT(&vmd->vmd_laundry_marker, plinks.q);
+		TAILQ_REMOVE(&pq->pq_pl, &vmd->vmd_laundry_marker, plinks.q);
+	}
+	vm_pagequeue_unlock(pq);
+
+	/*
+	 * Wakeup the sync daemon if we skipped a vnode in a writeable object
+	 * and we didn't launder enough pages.
+	 */
+	if (vnodes_skipped > 0 && launder > 0)
+		(void)speedup_syncer();
+
+	return (starting_target - launder);
+}
+
+/*
+ * Compute the integer square root.
+ */
+static u_int
+isqrt(u_int num)
+{
+	u_int bit, root, tmp;
+
+	bit = 1u << ((NBBY * sizeof(u_int)) - 2);
+	while (bit > num)
+		bit >>= 2;
+	root = 0;
+	while (bit != 0) {
+		tmp = root + bit;
+		root >>= 1;
+		if (num >= tmp) {
+			num -= tmp;
+			root += bit;
+		}
+		bit >>= 2;
+	}
+	return (root);
+}
+
+/*
+ * Perform the work of the laundry thread: periodically wake up and determine
+ * whether any pages need to be laundered.  If so, determine the number of pages
+ * that need to be laundered, and launder them.
+ */
+static void
+vm_pageout_laundry_worker(void *arg)
+{
+	struct vm_domain *domain;
+	struct vm_pagequeue *pq;
+	uint64_t nclean, ndirty;
+	u_int last_launder, wakeups;
+	int domidx, last_target, launder, shortfall, shortfall_cycle, target;
+	bool in_shortfall;
+
+	domidx = (uintptr_t)arg;
+	domain = &vm_dom[domidx];
+	pq = &domain->vmd_pagequeues[PQ_LAUNDRY];
+	KASSERT(domain->vmd_segs != 0, ("domain without segments"));
+	vm_pageout_init_marker(&domain->vmd_laundry_marker, PQ_LAUNDRY);
+
+	shortfall = 0;
+	in_shortfall = false;
+	shortfall_cycle = 0;
+	target = 0;
+	last_launder = 0;
+
+	/*
+	 * The pageout laundry worker is never done, so loop forever.
+	 */
+	for (;;) {
+		KASSERT(target >= 0, ("negative target %d", target));
+		KASSERT(shortfall_cycle >= 0,
+		    ("negative cycle %d", shortfall_cycle));
+		launder = 0;
+		wakeups = VM_METER_PCPU_CNT(v_pdwakeups);
+
+		/*
+		 * First determine whether we need to launder pages to meet a
+		 * shortage of free pages.
+		 */
+		if (shortfall > 0) {
+			in_shortfall = true;
+			shortfall_cycle = VM_LAUNDER_RATE / VM_INACT_SCAN_RATE;
+			target = shortfall;
+		} else if (!in_shortfall)
+			goto trybackground;
+		else if (shortfall_cycle == 0 || vm_laundry_target() <= 0) {
+			/*
+			 * We recently entered shortfall and began laundering
+			 * pages.  If we have completed that laundering run
+			 * (and we are no longer in shortfall) or we have met
+			 * our laundry target through other activity, then we
+			 * can stop laundering pages.
+			 */
+			in_shortfall = false;
+			target = 0;
+			goto trybackground;
+		}
+		last_launder = wakeups;
+		launder = target / shortfall_cycle--;
+		goto dolaundry;
+
+		/*
+		 * There's no immediate need to launder any pages; see if we
+		 * meet the conditions to perform background laundering:
+		 *
+		 * 1. The ratio of dirty to clean inactive pages exceeds the
+		 *    background laundering threshold and the pagedaemon has
+		 *    been woken up to reclaim pages since our last
+		 *    laundering, or
+		 * 2. we haven't yet reached the target of the current
+		 *    background laundering run.
+		 *
+		 * The background laundering threshold is not a constant.
+		 * Instead, it is a slowly growing function of the number of
+		 * page daemon wakeups since the last laundering.  Thus, as the
+		 * ratio of dirty to clean inactive pages grows, the amount of
+		 * memory pressure required to trigger laundering decreases.
+		 */
+trybackground:
+		nclean = vm_cnt.v_inactive_count + vm_cnt.v_free_count;
+		ndirty = vm_cnt.v_laundry_count;
+		if (target == 0 && wakeups != last_launder &&
+		    ndirty * isqrt(wakeups - last_launder) >= nclean) {
+			target = vm_background_launder_target;
+		}
+
+		/*
+		 * We have a non-zero background laundering target.  If we've
+		 * laundered up to our maximum without observing a page daemon
+		 * wakeup, just stop.  This is a safety belt that ensures we
+		 * don't launder an excessive amount if memory pressure is low
+		 * and the ratio of dirty to clean pages is large.  Otherwise,
+		 * proceed at the background laundering rate.
+		 */
+		if (target > 0) {
+			if (wakeups != last_launder) {
+				last_launder = wakeups;
+				last_target = target;
+			} else if (last_target - target >=
+			    vm_background_launder_max * PAGE_SIZE / 1024) {
+				target = 0;
+			}
+			launder = vm_background_launder_rate * PAGE_SIZE / 1024;
+			launder /= VM_LAUNDER_RATE;
+			if (launder > target)
+				launder = target;
+		}
+
+dolaundry:
+		if (launder > 0) {
+			/*
+			 * Because of I/O clustering, the number of laundered
+			 * pages could exceed "target" by the maximum size of
+			 * a cluster minus one. 
+			 */
+			target -= min(vm_pageout_launder(domain, launder,
+			    in_shortfall), target);
+			pause("laundp", hz / VM_LAUNDER_RATE);
+		}
+
+		/*
+		 * If we're not currently laundering pages and the page daemon
+		 * hasn't posted a new request, sleep until the page daemon
+		 * kicks us.
+		 */
+		vm_pagequeue_lock(pq);
+		if (target == 0 && vm_laundry_request == VM_LAUNDRY_IDLE)
+			(void)mtx_sleep(&vm_laundry_request,
+			    vm_pagequeue_lockptr(pq), PVM, "launds", 0);
+
+		/*
+		 * If the pagedaemon has indicated that it's in shortfall, start
+		 * a shortfall laundering unless we're already in the middle of
+		 * one.  This may preempt a background laundering.
+		 */
+		if (vm_laundry_request == VM_LAUNDRY_SHORTFALL &&
+		    (!in_shortfall || shortfall_cycle == 0)) {
+			shortfall = vm_laundry_target() + vm_pageout_deficit;
+			target = 0;
+		} else
+			shortfall = 0;
+
+		if (target == 0)
+			vm_laundry_request = VM_LAUNDRY_IDLE;
+		vm_pagequeue_unlock(pq);
+	}
+}
+
 /*
  *	vm_pageout_scan does the dirty work for the pageout daemon.
  *
- *	pass 0 - Update active LRU/deactivate pages
- *	pass 1 - Free inactive pages
- *	pass 2 - Launder dirty pages
+ *	pass == 0: Update active LRU/deactivate pages
+ *	pass >= 1: Free inactive pages
  *
  * Returns true if pass was zero or enough pages were freed by the inactive
  * queue scan to meet the target.
@@ -856,10 +1270,9 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 	struct vm_pagequeue *pq;
 	vm_object_t object;
 	long min_scan;
-	int act_delta, addl_page_shortage, deficit, error, inactq_shortage;
-	int maxlaunder, maxscan, page_shortage, scan_tick, scanned;
-	int starting_page_shortage, vnodes_skipped;
-	boolean_t pageout_ok, queue_locked;
+	int act_delta, addl_page_shortage, deficit, inactq_shortage, maxscan;
+	int page_shortage, scan_tick, scanned, starting_page_shortage;
+	boolean_t queue_locked;
 
 	/*
 	 * If we need to reclaim memory ask kernel caches to return
@@ -900,23 +1313,6 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 		page_shortage = deficit = 0;
 	starting_page_shortage = page_shortage;
 
-	/*
-	 * maxlaunder limits the number of dirty pages we flush per scan.
-	 * For most systems a smaller value (16 or 32) is more robust under
-	 * extreme memory and disk pressure because any unnecessary writes
-	 * to disk can result in extreme performance degredation.  However,
-	 * systems with excessive dirty pages (especially when MAP_NOSYNC is
-	 * used) will die horribly with limited laundering.  If the pageout
-	 * daemon cannot clean enough pages in the first pass, we let it go
-	 * all out in succeeding passes.
-	 */
-	if ((maxlaunder = vm_max_launder) <= 1)
-		maxlaunder = 1;
-	if (pass > 1)
-		maxlaunder = 10000;
-
-	vnodes_skipped = 0;
-
 	/*
 	 * Start scanning the inactive queue for pages that we can free.  The
 	 * scan will stop when we reach the target or we have scanned the
@@ -932,7 +1328,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 	     m = next) {
 		vm_pagequeue_assert_locked(pq);
 		KASSERT(queue_locked, ("unlocked inactive queue"));
-		KASSERT(m->queue == PQ_INACTIVE, ("Inactive queue %p", m));
+		KASSERT(vm_page_inactive(m), ("Inactive queue %p", m));
 
 		PCPU_INC(cnt.v_pdpages);
 		next = TAILQ_NEXT(m, plinks.q);
@@ -995,11 +1391,15 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 		KASSERT(m->hold_count == 0, ("Held page %p", m));
 
 		/*
-		 * We unlock the inactive page queue, invalidating the
-		 * 'next' pointer.  Use our marker to remember our
-		 * place.
+		 * Dequeue the inactive page and unlock the inactive page
+		 * queue, invalidating the 'next' pointer.  Dequeueing the
+		 * page here avoids a later reacquisition (and release) of
+		 * the inactive page queue lock when vm_page_activate(),
+		 * vm_page_free(), or vm_page_launder() is called.  Use a
+		 * marker to remember our place in the inactive queue.
 		 */
 		TAILQ_INSERT_AFTER(&pq->pq_pl, m, &vmd->vmd_marker, plinks.q);
+		vm_page_dequeue_locked(m);
 		vm_pagequeue_unlock(pq);
 		queue_locked = FALSE;
 
@@ -1028,6 +1428,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 		}
 		if (act_delta != 0) {
 			if (object->ref_count != 0) {
+				PCPU_INC(cnt.v_reactivated);
 				vm_page_activate(m);
 
 				/*
@@ -1039,8 +1440,14 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
  				 */
 				m->act_count += act_delta + ACT_ADVANCE;
 				goto drop_page;
-			} else if ((object->flags & OBJ_DEAD) == 0)
-				goto requeue_page;
+			} else if ((object->flags & OBJ_DEAD) == 0) {
+				vm_pagequeue_lock(pq);
+				queue_locked = TRUE;
+				m->queue = PQ_INACTIVE;
+				TAILQ_INSERT_TAIL(&pq->pq_pl, m, plinks.q);
+				vm_pagequeue_cnt_inc(pq);
+				goto drop_page;
+			}
 		}
 
 		/*
@@ -1056,83 +1463,23 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 				pmap_remove_all(m);
 		}
 
+		/*
+		 * Clean pages can be freed, but dirty pages must be sent back
+		 * to the laundry, unless they belong to a dead object.
+		 * Requeueing dirty pages from dead objects is pointless, as
+		 * they are being paged out and freed by the thread that
+		 * destroyed the object.
+		 */
 		if (m->dirty == 0) {
-			/*
-			 * Clean pages can be freed.
-			 */
 free_page:
 			vm_page_free(m);
 			PCPU_INC(cnt.v_dfree);
 			--page_shortage;
-		} else if ((object->flags & OBJ_DEAD) != 0) {
-			/*
-			 * Leave dirty pages from dead objects at the front of
-			 * the queue.  They are being paged out and freed by
-			 * the thread that destroyed the object.  They will
-			 * leave the queue shortly after the scan finishes, so 
-			 * they should be discounted from the inactive count.
-			 */
-			addl_page_shortage++;
-		} else if ((m->flags & PG_WINATCFLS) == 0 && pass < 2) {
-			/*
-			 * Dirty pages need to be paged out, but flushing
-			 * a page is extremely expensive versus freeing
-			 * a clean page.  Rather then artificially limiting
-			 * the number of pages we can flush, we instead give
-			 * dirty pages extra priority on the inactive queue
-			 * by forcing them to be cycled through the queue
-			 * twice before being flushed, after which the
-			 * (now clean) page will cycle through once more
-			 * before being freed.  This significantly extends
-			 * the thrash point for a heavily loaded machine.
-			 */
-			m->flags |= PG_WINATCFLS;
-requeue_page:
-			vm_pagequeue_lock(pq);
-			queue_locked = TRUE;
-			vm_page_requeue_locked(m);
-		} else if (maxlaunder > 0) {
-			/*
-			 * We always want to try to flush some dirty pages if
-			 * we encounter them, to keep the system stable.
-			 * Normally this number is small, but under extreme
-			 * pressure where there are insufficient clean pages
-			 * on the inactive queue, we may have to go all out.
-			 */
-
-			if (object->type != OBJT_SWAP &&
-			    object->type != OBJT_DEFAULT)
-				pageout_ok = TRUE;
-			else if (disable_swap_pageouts)
-				pageout_ok = FALSE;
-			else if (defer_swap_pageouts)
-				pageout_ok = vm_page_count_min();
-			else
-				pageout_ok = TRUE;
-			if (!pageout_ok)
-				goto requeue_page;
-			error = vm_pageout_clean(m);
-			/*
-			 * Decrement page_shortage on success to account for
-			 * the (future) cleaned page.  Otherwise we could wind
-			 * up laundering or cleaning too many pages.
-			 */
-			if (error == 0) {
-				page_shortage--;
-				maxlaunder--;
-			} else if (error == EDEADLK) {
-				pageout_lock_miss++;
-				vnodes_skipped++;
-			} else if (error == EBUSY) {
-				addl_page_shortage++;
-			}
-			vm_page_lock_assert(m, MA_NOTOWNED);
-			goto relock_queue;
-		}
+		} else if ((object->flags & OBJ_DEAD) == 0)
+			vm_page_launder(m);
 drop_page:
 		vm_page_unlock(m);
 		VM_OBJECT_WUNLOCK(object);
-relock_queue:
 		if (!queue_locked) {
 			vm_pagequeue_lock(pq);
 			queue_locked = TRUE;
@@ -1142,6 +1489,24 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 	}
 	vm_pagequeue_unlock(pq);
 
+	/*
+	 * Wake up the laundry thread so that it can perform any needed
+	 * laundering.  If we didn't meet our target, we're in shortfall and
+	 * need to launder more aggressively.
+	 */
+	if (vm_laundry_request == VM_LAUNDRY_IDLE &&
+	    starting_page_shortage > 0) {
+		pq = &vm_dom[0].vmd_pagequeues[PQ_LAUNDRY];
+		vm_pagequeue_lock(pq);
+		if (page_shortage > 0) {
+			vm_laundry_request = VM_LAUNDRY_SHORTFALL;
+			PCPU_INC(cnt.v_pdshortfalls);
+		} else if (vm_laundry_request != VM_LAUNDRY_SHORTFALL)
+			vm_laundry_request = VM_LAUNDRY_BACKGROUND;
+		wakeup(&vm_laundry_request);
+		vm_pagequeue_unlock(pq);
+	}
+
 #if !defined(NO_SWAPPING)
 	/*
 	 * Wakeup the swapout daemon if we didn't free the targeted number of
@@ -1151,14 +1516,6 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 		vm_req_vmdaemon(VM_SWAP_NORMAL);
 #endif
 
-	/*
-	 * Wakeup the sync daemon if we skipped a vnode in a writeable object
-	 * and we didn't free enough pages.
-	 */
-	if (vnodes_skipped > 0 && page_shortage > vm_cnt.v_free_target -
-	    vm_cnt.v_free_min)
-		(void)speedup_syncer();
-
 	/*
 	 * If the inactive queue scan fails repeatedly to meet its
 	 * target, kill the largest process.
@@ -1167,10 +1524,20 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 
 	/*
 	 * Compute the number of pages we want to try to move from the
-	 * active queue to the inactive queue.
+	 * active queue to either the inactive or laundry queue.
+	 *
+	 * When scanning active pages, we make clean pages count more heavily
+	 * towards the page shortage than dirty pages.  This is because dirty
+	 * pages must be laundered before they can be reused and thus have less
+	 * utility when attempting to quickly alleviate a shortage.  However,
+	 * this weighting also causes the scan to deactivate dirty pages more
+	 * more aggressively, improving the effectiveness of clustering and
+	 * ensuring that they can eventually be reused.
 	 */
-	inactq_shortage = vm_cnt.v_inactive_target - vm_cnt.v_inactive_count +
+	inactq_shortage = vm_cnt.v_inactive_target - (vm_cnt.v_inactive_count +
+	    vm_cnt.v_laundry_count / act_scan_laundry_weight) +
 	    vm_paging_target() + deficit + addl_page_shortage;
+	page_shortage *= act_scan_laundry_weight;
 
 	pq = &vmd->vmd_pagequeues[PQ_ACTIVE];
 	vm_pagequeue_lock(pq);
@@ -1254,14 +1621,44 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
 			m->act_count -= min(m->act_count, ACT_DECLINE);
 
 		/*
-		 * Move this page to the tail of the active or inactive
+		 * Move this page to the tail of the active, inactive or laundry
 		 * queue depending on usage.
 		 */
 		if (m->act_count == 0) {
 			/* Dequeue to avoid later lock recursion. */
 			vm_page_dequeue_locked(m);
-			vm_page_deactivate(m);
-			inactq_shortage--;
+
+			/*
+			 * When not short for inactive pages, let dirty pages go
+			 * through the inactive queue before moving to the
+			 * laundry queues.  This gives them some extra time to
+			 * be reactivated, potentially avoiding an expensive
+			 * pageout.  During a page shortage, the inactive queue
+			 * is necessarily small, so we may move dirty pages
+			 * directly to the laundry queue.
+			 */
+			if (inactq_shortage <= 0)
+				vm_page_deactivate(m);
+			else {
+				/*
+				 * Calling vm_page_test_dirty() here would
+				 * require acquisition of the object's write
+				 * lock.  However, during a page shortage,
+				 * directing dirty pages into the laundry
+				 * queue is only an optimization and not a
+				 * requirement.  Therefore, we simply rely on
+				 * the opportunistic updates to the page's
+				 * dirty field by the pmap.
+				 */
+				if (m->dirty == 0) {
+					vm_page_deactivate(m);
+					inactq_shortage -=
+					    act_scan_laundry_weight;
+				} else {
+					vm_page_launder(m);
+					inactq_shortage--;
+				}
+			}
 		} else
 			vm_page_requeue_locked(m);
 		vm_page_unlock(m);
@@ -1570,14 +1967,14 @@ vm_pageout_worker(void *arg)
 			 * thread during the previous scan, which must have
 			 * been a level 0 scan, or vm_pageout_wanted was
 			 * already set and the scan failed to free enough
-			 * pages.  If we haven't yet performed a level >= 2
-			 * scan (unlimited dirty cleaning), then upgrade the
-			 * level and scan again now.  Otherwise, sleep a bit
-			 * and try again later.
+			 * pages.  If we haven't yet performed a level >= 1
+			 * (page reclamation) scan, then increase the level
+			 * and scan again now.  Otherwise, sleep a bit and
+			 * try again later.
 			 */
 			mtx_unlock(&vm_page_queue_free_mtx);
-			if (pass > 1)
-				pause("psleep", hz / 2);
+			if (pass >= 1)
+				pause("psleep", hz / VM_INACT_SCAN_RATE);
 			pass++;
 		} else {
 			/*
@@ -1648,6 +2045,14 @@ vm_pageout_init(void)
 	/* XXX does not really belong here */
 	if (vm_page_max_wired == 0)
 		vm_page_max_wired = vm_cnt.v_free_count / 3;
+
+	/*
+	 * Target amount of memory to move out of the laundry queue during a
+	 * background laundering.  This is proportional to the amount of system
+	 * memory.
+	 */
+	vm_background_launder_target = (vm_cnt.v_free_target -
+	    vm_cnt.v_free_min) / 10;
 }
 
 /*
@@ -1662,6 +2067,10 @@ vm_pageout(void)
 #endif
 
 	swap_pager_swap_init();
+	error = kthread_add(vm_pageout_laundry_worker, NULL, curproc, NULL,
+	    0, 0, "laundry: dom0");
+	if (error != 0)
+		panic("starting laundry for domain 0, error %d", error);
 #ifdef VM_NUMA_ALLOC
 	for (i = 1; i < vm_ndomains; i++) {
 		error = kthread_add(vm_pageout_worker, (void *)(uintptr_t)i,

From fc0d6c840e265651bd67db7d5781e6096874f58d Mon Sep 17 00:00:00 2001
From: Toomas Soome 
Date: Wed, 9 Nov 2016 21:28:46 +0000
Subject: [PATCH 116/127] boot/forth spelling issue in forth word

Reviewed by:	dteske, imp
Approved by:	imp (mentor)
Differential Revision:	https://reviews.freebsd.org/D8484
---
 sys/boot/forth/support.4th | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th
index aac258d80539..7ce9e5289acf 100644
--- a/sys/boot/forth/support.4th
+++ b/sys/boot/forth/support.4th
@@ -1115,7 +1115,7 @@ string current_file_name_ref	\ used to print the file name
 
 : load_error_message verbose? if ." failed!" cr then ;
 
-: load_succesful_message verbose? if ." ok" cr then ;
+: load_successful_message verbose? if ." ok" cr then ;
 
 : load_module
   load_parameters load
@@ -1133,7 +1133,7 @@ string current_file_name_ref	\ used to print the file name
       then
     else
       after_load
-      load_succesful_message true	\ Successful, do not retry
+      load_successful_message true	\ Successful, do not retry
     then
   until
 ;

From 9625abb35977c6e36ca65fa322005aa8c6674600 Mon Sep 17 00:00:00 2001
From: Baptiste Daroussin 
Date: Wed, 9 Nov 2016 21:51:48 +0000
Subject: [PATCH 117/127] make pxeboot consistent with common/dev_net.c

Always define boot.netif.server in kenv in pxeboot
Add "boot.tftproot.server" to kenv when pxeboot uses tftpfs
Change the code order when setting env for TFTP or NFS to be the same as
common/dev_net.c

Reported by:	tsoome
---
 sys/boot/i386/libi386/pxe.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index a1bb693eeb85..a246e8356247 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -311,6 +311,7 @@ pxe_open(struct open_file *f, ...)
 		setenv("boot.netif.ip", inet_ntoa(myip), 1);
 		setenv("boot.netif.netmask", intoa(netmask), 1);
 		setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
+		setenv("boot.netif.server", inet_ntoa(rootip), 1);
 		if (bootplayer.Hardware == ETHER_TYPE) {
 		    sprintf(temp, "%6D", bootplayer.CAddr, ":");
 		    setenv("boot.netif.hwaddr", temp, 1);
@@ -324,12 +325,12 @@ pxe_open(struct open_file *f, ...)
 		printf("pxe_open: server path: %s\n", rootpath);
 		printf("pxe_open: gateway ip:  %s\n", inet_ntoa(gateip));
 
-		if (netproto == NET_NFS) {
+		if (netproto == NET_TFTP) {
+			setenv("boot.tftproot.server", inet_ntoa(rootip), 1);
+			setenv("boot.tftproot.path", rootpath, 1);
+		} else if (netproto == NET_NFS) {
 			setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
 			setenv("boot.nfsroot.path", rootpath, 1);
-		} else if (netproto == NET_TFTP) {
-			setenv("boot.netif.server", inet_ntoa(rootip), 1);
-			setenv("boot.tftproot.path", rootpath, 1);
 		}
 		setenv("dhcp.host-name", hostname, 1);
 

From 46542a426e4e361a5b16723e3ebcc683f7800dbf Mon Sep 17 00:00:00 2001
From: Marcelo Araujo 
Date: Thu, 10 Nov 2016 07:05:41 +0000
Subject: [PATCH 118/127] We can't use protect(1) inside a jail(8)! To avoid
 have warning for services that are using oomprotect, oomprotect will only be
 applied on services that won't run inside jails.

Reported by:	allanjude
MFC after:	2 weeks.
---
 etc/rc.subr | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/etc/rc.subr b/etc/rc.subr
index 5b29ccf2e0b7..0201f0595c67 100644
--- a/etc/rc.subr
+++ b/etc/rc.subr
@@ -1205,6 +1205,11 @@ $command $rc_flags $command_args"
 		# Apply protect(1) to the PID if ${name}_oomprotect is set.
 		case "$rc_arg" in
 		start)
+			# We cannot use protect(1) inside jails.
+			jailed="$(sysctl -n security.jail.jailed)"
+			if [ ${jailed} -eq 1 ]; then
+				return $_return
+			fi
 			if [ -n "$_oomprotect" ]; then
 				if [ -f "${PROTECT}" ]; then
 					pid=$(check_process $command)

From a18f280538bce0eff94c36f12382bff0211f1725 Mon Sep 17 00:00:00 2001
From: Andriy Gapon 
Date: Thu, 10 Nov 2016 10:45:12 +0000
Subject: [PATCH 119/127] fix a watchdogd regression introduced in r308040

The code assumed that 'timeout' and 'timeout_sec' are in sync
which they weren't if no '-t' option was passed to watchdogd.

Reported by:	Olivier Smedts ,
		Alex Deiter 
Tested by:	Olivier Smedts ,
		Alex Deiter 
MFC after:	5 days
X-MFC with:	r308040
---
 usr.sbin/watchdogd/watchdogd.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c
index 9ed9de31683d..1271bbfe35dc 100644
--- a/usr.sbin/watchdogd/watchdogd.c
+++ b/usr.sbin/watchdogd/watchdogd.c
@@ -685,10 +685,15 @@ seconds_to_pow2ns(int seconds)
 static void
 parseargs(int argc, char *argv[])
 {
+	struct timespec ts;
 	int longindex;
 	int c;
 	const char *lopt;
 
+	/* Get the default value of timeout_sec from the default timeout. */
+	pow2ns_to_ts(timeout, &ts);
+	timeout_sec = ts.tv_sec;
+
 	/*
 	 * if we end with a 'd' aka 'watchdogd' then we are the daemon program,
 	 * otherwise run as a command line utility.
@@ -731,9 +736,9 @@ parseargs(int argc, char *argv[])
 		case 't':
 			timeout_sec = atoi(optarg);
 			timeout = parse_timeout_to_pow2ns(c, NULL, optarg);
- 			if (debugging)
- 				printf("Timeout is 2^%d nanoseconds\n",
- 				    timeout);
+			if (debugging)
+				printf("Timeout is 2^%d nanoseconds\n",
+				    timeout);
 			break;
 		case 'T':
 			carp_thresh_seconds =
@@ -782,10 +787,7 @@ parseargs(int argc, char *argv[])
 	if (is_daemon && timeout < WD_TO_1SEC)
 		errx(EX_USAGE, "-t argument is less than one second.");
 	if (pretimeout_set) {
-		struct timespec ts;
-
-		pow2ns_to_ts(timeout, &ts);
-		if (pretimeout >= (uintmax_t)ts.tv_sec) {
+		if (pretimeout >= timeout_sec) {
 			errx(EX_USAGE,
 			    "pretimeout (%d) >= timeout (%d -> %ld)\n"
 			    "see manual section TIMEOUT RESOLUTION",

From 593077d613b6bed8c4607015c7a2d86f87868155 Mon Sep 17 00:00:00 2001
From: Andriy Gapon 
Date: Thu, 10 Nov 2016 11:12:45 +0000
Subject: [PATCH 120/127] pmc_process_csw_out: ignore deleted counters

I see the fllowing panic on AMD when exiting pmcstat:

panic: [pmc,1473] pp_pmcval outside of expected range cpu=2 ri=17
pp_pmcval=fffffffffa529f5b pm_reloadcount=10000

It seems that at least on AMD a performance counter keeps counting after
overflowing.  When pmcstat exits it sets counters that it used to
PMC_STATE_DELETED and waits until their use count goes to zero.
amd_intr() wouldn't reload a counter in that state and, thus, a counter
would be allowed to overflow.  That means that the counter's value would
be allowed to go outside the expected range.

MFC after:	2 weeks
---
 sys/dev/hwpmc/hwpmc_mod.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 55dc499b1c40..36bcccb8c27a 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1431,8 +1431,8 @@ pmc_process_csw_out(struct thread *td)
 		 * save the reading.
 		 */
 
-		if (pp != NULL && pp->pp_pmcs[ri].pp_pmc != NULL) {
-
+		if (pm->pm_state != PMC_STATE_DELETED && pp != NULL &&
+		    pp->pp_pmcs[ri].pp_pmc != NULL) {
 			KASSERT(pm == pp->pp_pmcs[ri].pp_pmc,
 			    ("[pmc,%d] pm %p != pp_pmcs[%d] %p", __LINE__,
 				pm, ri, pp->pp_pmcs[ri].pp_pmc));

From ef37962496683da0e9309dfd0efa6fa67ece8ef0 Mon Sep 17 00:00:00 2001
From: Ruslan Bukin 
Date: Thu, 10 Nov 2016 12:54:33 +0000
Subject: [PATCH 121/127] Implement riscv jumpto() so world can be compiled.

Sponsored by:	DARPA, AFRL
Sponsored by:	HEIF5
---
 .../libunwind/src/UnwindRegistersRestore.S    | 46 ++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S b/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
index 534d79592240..8e37c13036f6 100644
--- a/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
+++ b/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
@@ -480,6 +480,50 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
 
 #elif defined(__riscv__)
 
-/* RISCVTODO */
+//
+// void libunwind::Registers_riscv::jumpto()
+//
+// On entry:
+//  thread_state pointer is in a0
+//
+  .p2align 2
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
+  // x0 is zero
+  ld    x1, (8 * 1)(a0)
+  ld    x2, (8 * 2)(a0)
+  ld    x3, (8 * 3)(a0)
+  ld    x4, (8 * 4)(a0)
+  ld    x5, (8 * 5)(a0)
+  ld    x6, (8 * 6)(a0)
+  ld    x7, (8 * 7)(a0)
+  ld    x8, (8 * 8)(a0)
+  ld    x9, (8 * 9)(a0)
+  // skip a0 for now
+  ld    x11, (8 * 11)(a0)
+  ld    x12, (8 * 12)(a0)
+  ld    x13, (8 * 13)(a0)
+  ld    x14, (8 * 14)(a0)
+  ld    x15, (8 * 15)(a0)
+  ld    x16, (8 * 16)(a0)
+  ld    x17, (8 * 17)(a0)
+  ld    x18, (8 * 18)(a0)
+  ld    x19, (8 * 19)(a0)
+  ld    x20, (8 * 20)(a0)
+  ld    x21, (8 * 21)(a0)
+  ld    x22, (8 * 22)(a0)
+  ld    x23, (8 * 23)(a0)
+  ld    x24, (8 * 24)(a0)
+  ld    x25, (8 * 25)(a0)
+  ld    x26, (8 * 26)(a0)
+  ld    x27, (8 * 27)(a0)
+  ld    x28, (8 * 28)(a0)
+  ld    x29, (8 * 29)(a0)
+  ld    x30, (8 * 30)(a0)
+  ld    x31, (8 * 31)(a0)
+  ld    x10, (8 * 10)(a0)   // restore a0
+
+  /* RISCVTODO: restore FPU registers */
+
+  ret                       // jump to ra
 
 #endif

From 111bf579e39bb72682da334ce763789eb3c73461 Mon Sep 17 00:00:00 2001
From: Antoine Brodin 
Date: Thu, 10 Nov 2016 16:27:34 +0000
Subject: [PATCH 122/127] Add limits(1) to native-xtools so that it can be used
 in qemu user-mode jails

---
 Makefile.inc1 | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile.inc1 b/Makefile.inc1
index eaa3d3fcbdf3..5db4acbeaa36 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -1954,6 +1954,7 @@ native-xtools: .PHONY
     usr.bin/gzip \
     usr.bin/id \
     usr.bin/lex \
+    usr.bin/limits \
     usr.bin/lorder \
     usr.bin/mktemp \
     usr.bin/mt \

From 339be86fdb3b2535bcb31aa28d29caf44c525a7e Mon Sep 17 00:00:00 2001
From: Adrian Chadd 
Date: Thu, 10 Nov 2016 18:36:40 +0000
Subject: [PATCH 123/127] [net80211] implement "first RX defines the BAW" hack.

Unfortunately (sigh) some firmware doesn't provide the RX BA starting point,
so we need to cope and set a "close enough" sequence number so we (hopefully!)
don't discard frames as duplicates.

Tested:

* QCA9880v2, athp driver (under development), STA mode
---
 sys/net80211/ieee80211_ht.c | 22 ++++++++++++++++++++--
 sys/net80211/ieee80211_ht.h |  1 +
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index a3ef87c7c438..7f8d191644a6 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -582,7 +582,13 @@ ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, int seq, int ba
 	memset(rap, 0, sizeof(*rap));
 	rap->rxa_wnd = (baw== 0) ?
 	    IEEE80211_AGGR_BAWMAX : min(baw, IEEE80211_AGGR_BAWMAX);
-	rap->rxa_start = seq;
+	if (seq == -1) {
+		/* Wait for the first RX frame, use that as BAW */
+		rap->rxa_start = 0;
+		rap->rxa_flags |= IEEE80211_AGGR_WAITRX;
+	} else {
+		rap->rxa_start = seq;
+	}
 	rap->rxa_flags |=  IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND;
 
 	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
@@ -617,7 +623,9 @@ ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
 {
 
 	ampdu_rx_purge(rap);
-	rap->rxa_flags &= ~(IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND);
+	rap->rxa_flags &= ~(IEEE80211_AGGR_RUNNING
+	    | IEEE80211_AGGR_XCHGPEND
+	    | IEEE80211_AGGR_WAITRX);
 }
 
 /*
@@ -842,6 +850,16 @@ ieee80211_ampdu_reorder(struct ieee80211_node *ni, struct mbuf *m)
 	}
 	rxseq >>= IEEE80211_SEQ_SEQ_SHIFT;
 	rap->rxa_nframes++;
+
+	/*
+	 * Handle waiting for the first frame to define the BAW.
+	 * Some firmware doesn't provide the RX of the starting point
+	 * of the BAW and we have to cope.
+	 */
+	if (rap->rxa_flags & IEEE80211_AGGR_WAITRX) {
+		rap->rxa_flags &= ~IEEE80211_AGGR_WAITRX;
+		rap->rxa_start = rxseq;
+	}
 again:
 	if (rxseq == rap->rxa_start) {
 		/*
diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h
index 629971d1bdc9..dfc7d1c312a0 100644
--- a/sys/net80211/ieee80211_ht.h
+++ b/sys/net80211/ieee80211_ht.h
@@ -44,6 +44,7 @@ struct ieee80211_tx_ampdu {
 #define	IEEE80211_AGGR_SETUP		0x0008	/* deferred state setup */
 #define	IEEE80211_AGGR_NAK		0x0010	/* peer NAK'd ADDBA request */
 #define	IEEE80211_AGGR_BARPEND		0x0020	/* BAR response pending */
+#define	IEEE80211_AGGR_WAITRX		0x0040	/* Wait for first RX frame to define BAW */
 	uint8_t		txa_tid;
 	uint8_t		txa_token;	/* dialog token */
 	int		txa_lastsample;	/* ticks @ last traffic sample */

From 2fd47dea4e89f184ff31fb5c1eacc2bd872f2b0d Mon Sep 17 00:00:00 2001
From: Kristof Provost 
Date: Thu, 10 Nov 2016 18:41:43 +0000
Subject: [PATCH 124/127] pfctl: fix nested inline anchors

Import the OpenBSD fix for nested inline anchors.

PR:		196314
Submitted by:	krichy@cflinux.hu
Obtained from:	OpenBSD
---
 sbin/pfctl/pfctl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index ceb428b90d04..c00f4c3b8045 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1339,7 +1339,7 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
 			else
 				snprintf(&path[len], MAXPATHLEN - len,
 				    "%s", r->anchor->name);
-			name = path;
+			name = r->anchor->name;
 		} else
 			name = r->anchor->path;
 	} else

From 0ef0edf2bb8eaa2b27020b38b5e6eb2339717d2f Mon Sep 17 00:00:00 2001
From: Dimitry Andric 
Date: Thu, 10 Nov 2016 19:40:14 +0000
Subject: [PATCH 125/127] Pull in r263301 from upstream llvm trunk (by Ahmed
 Bougacha):

  [AArch64] Don't blindly lower f16/f128 FCCMPs.

  Instead, extend f16 (like we do when lowering a standalone SETCC),
  and let f128 be legalized to the RT calls.

  Fixes PR26803.

This fixes a fatal "Cannot select" backend error when building the
net/freerdp port for AArch64.

PR:		214380
MFC after:	3 days
---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9cbf48820e99..29fbed1b5880 100644
--- a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1177,8 +1177,14 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
                               SDLoc dl, SelectionDAG &DAG) {
   EVT VT = LHS.getValueType();
 
-  if (VT.isFloatingPoint())
+  if (VT.isFloatingPoint()) {
+    assert(VT != MVT::f128);
+    if (VT == MVT::f16) {
+      LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, LHS);
+      RHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, RHS);
+    }
     return DAG.getNode(AArch64ISD::FCMP, dl, VT, LHS, RHS);
+  }
 
   // The CMP instruction is just an alias for SUBS, and representing it as
   // SUBS means that it's possible to get CSE with subtract operations.
@@ -1261,9 +1267,14 @@ static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
                                          SDValue Condition, unsigned NZCV,
                                          SDLoc DL, SelectionDAG &DAG) {
   unsigned Opcode = 0;
-  if (LHS.getValueType().isFloatingPoint())
+  if (LHS.getValueType().isFloatingPoint()) {
+    assert(LHS.getValueType() != MVT::f128);
+    if (LHS.getValueType() == MVT::f16) {
+      LHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, LHS);
+      RHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, RHS);
+    }
     Opcode = AArch64ISD::FCCMP;
-  else if (RHS.getOpcode() == ISD::SUB) {
+  } else if (RHS.getOpcode() == ISD::SUB) {
     SDValue SubOp0 = RHS.getOperand(0);
     if (isNullConstant(SubOp0) && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
         // See emitComparison() on why we can only do this for SETEQ and SETNE.
@@ -1290,6 +1301,8 @@ static bool isConjunctionDisjunctionTree(const SDValue Val, bool &CanPushNegate,
     return false;
   unsigned Opcode = Val->getOpcode();
   if (Opcode == ISD::SETCC) {
+    if (Val->getOperand(0).getValueType() == MVT::f128)
+      return false;
     CanPushNegate = true;
     return true;
   }

From cc59e3a79b5caf0bba3e9452c7cbae16f2b521ac Mon Sep 17 00:00:00 2001
From: Mark Johnston 
Date: Thu, 10 Nov 2016 19:55:45 +0000
Subject: [PATCH 126/127] Add the laundry page count to the displays of systat,
 top, and vmstat.

Reviewed by:	alc, kib
Differential Revision:	https://reviews.freebsd.org/D8467
---
 usr.bin/systat/systat.1 |  4 ++--
 usr.bin/systat/vmstat.c | 10 +++++-----
 usr.bin/top/machine.c   |  6 +++---
 usr.bin/top/top.local.1 | 13 ++++++-------
 usr.bin/vmstat/vmstat.c | 12 +++++++-----
 5 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1
index f66de6420ff2..139a69fb6720 100644
--- a/usr.bin/systat/systat.1
+++ b/usr.bin/systat/systat.1
@@ -28,7 +28,7 @@
 .\"	@(#)systat.1	8.2 (Berkeley) 12/30/93
 .\" $FreeBSD$
 .\"
-.Dd October 24, 2015
+.Dd November 10, 2016
 .Dt SYSTAT 1
 .Os
 .Sh NAME
@@ -411,7 +411,7 @@ as amounts of memory in kilobytes,
 pages wired down (`wire'),
 active pages (`act'),
 inactive pages (`inact'),
-pages on the cache queue (`cache'),
+dirty pages queued for laundering (`laund'),
 and
 free pages (`free').
 Note that the values displayed are the current transient ones;
diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c
index ca8b6bcd437a..25f79d7e9308 100644
--- a/usr.bin/systat/vmstat.c
+++ b/usr.bin/systat/vmstat.c
@@ -92,7 +92,7 @@ static struct Info {
 	u_int v_vnodepgsin;	/* vnode_pager pages paged in */
 	u_int v_vnodepgsout;	/* vnode pager pages paged out */
 	u_int v_intrans;	/* intransit blocking page faults */
-	u_int v_reactivated;	/* number of pages reactivated from free list */
+	u_int v_reactivated;	/* number of pages reactivated by pagedaemon */
 	u_int v_pdwakeups;	/* number of times daemon has awaken from sleep */
 	u_int v_pdpages;	/* number of pages analyzed by daemon */
 
@@ -107,7 +107,7 @@ static struct Info {
 	u_int v_wire_count;	/* number of pages wired down */
 	u_int v_active_count;	/* number of pages active */
 	u_int v_inactive_count;	/* number of pages inactive */
-	u_int v_cache_count;	/* number of pages on buffer cache queue */
+	u_int v_laundry_count;	/* number of pages in laundry queue */
 	u_long v_kmem_map_size;	/* Current kmem allocation size */
 	struct	vmtotal Total;
 	struct	nchstats nchstats;
@@ -343,7 +343,7 @@ labelkre(void)
 	mvprintw(VMSTATROW + 12, VMSTATCOL + 9, "wire");
 	mvprintw(VMSTATROW + 13, VMSTATCOL + 9, "act");
 	mvprintw(VMSTATROW + 14, VMSTATCOL + 9, "inact");
-	mvprintw(VMSTATROW + 15, VMSTATCOL + 9, "cache");
+	mvprintw(VMSTATROW + 15, VMSTATCOL + 9, "laund");
 	mvprintw(VMSTATROW + 16, VMSTATCOL + 9, "free");
 	if (LINES - 1 > VMSTATROW + 17)
 		mvprintw(VMSTATROW + 17, VMSTATCOL + 9, "buf");
@@ -519,7 +519,7 @@ showkre(void)
 	putint(pgtokb(s.v_wire_count), VMSTATROW + 12, VMSTATCOL, 8);
 	putint(pgtokb(s.v_active_count), VMSTATROW + 13, VMSTATCOL, 8);
 	putint(pgtokb(s.v_inactive_count), VMSTATROW + 14, VMSTATCOL, 8);
-	putint(pgtokb(s.v_cache_count), VMSTATROW + 15, VMSTATCOL, 8);
+	putint(pgtokb(s.v_laundry_count), VMSTATROW + 15, VMSTATCOL, 8);
 	putint(pgtokb(s.v_free_count), VMSTATROW + 16, VMSTATCOL, 8);
 	if (LINES - 1 > VMSTATROW + 17)
 		putint(s.bufspace / 1024, VMSTATROW + 17, VMSTATCOL, 8);
@@ -794,7 +794,7 @@ getinfo(struct Info *ls)
 	GETSYSCTL("vm.stats.vm.v_wire_count", ls->v_wire_count);
 	GETSYSCTL("vm.stats.vm.v_active_count", ls->v_active_count);
 	GETSYSCTL("vm.stats.vm.v_inactive_count", ls->v_inactive_count);
-	GETSYSCTL("vm.stats.vm.v_cache_count", ls->v_cache_count);
+	GETSYSCTL("vm.stats.vm.v_laundry_count", ls->v_laundry_count);
 	GETSYSCTL("vfs.bufspace", ls->bufspace);
 	GETSYSCTL("kern.maxvnodes", ls->desiredvnodes);
 	GETSYSCTL("vfs.numvnodes", ls->numvnodes);
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index e6ceb9251326..885639462c95 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -178,7 +178,7 @@ char *cpustatenames[] = {
 
 int memory_stats[7];
 char *memorynames[] = {
-	"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ",
+	"K Active, ", "K Inact, ", "K Laundry, ", "K Wired, ", "K Buf, ",
 	"K Free", NULL
 };
 
@@ -503,8 +503,8 @@ get_system_info(struct system_info *si)
 		GETSYSCTL("vfs.bufspace", bufspace);
 		GETSYSCTL("vm.stats.vm.v_active_count", memory_stats[0]);
 		GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stats[1]);
-		GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[2]);
-		GETSYSCTL("vm.stats.vm.v_cache_count", memory_stats[3]);
+		GETSYSCTL("vm.stats.vm.v_laundry_count", memory_stats[2]);
+		GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[3]);
 		GETSYSCTL("vm.stats.vm.v_free_count", memory_stats[5]);
 		GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin);
 		GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout);
diff --git a/usr.bin/top/top.local.1 b/usr.bin/top/top.local.1
index 864ab8d65c4b..46a959f84c02 100644
--- a/usr.bin/top/top.local.1
+++ b/usr.bin/top/top.local.1
@@ -2,8 +2,8 @@
 .SH "FreeBSD NOTES"
 
 .SH DESCRIPTION OF MEMORY
-Mem: 9220K Active, 1M Inact, 3284K Wired, 1M Cache, 2M Buf, 1320K Free
-ARC: 2048K Total, 342K MRU, 760K MFU, 272K Anon, 232K Header, 442K Other
+Mem: 9220K Active, 1M Inact, 1M Laundry, 3284K Wired, 2M Buf, 932K Free
+ARC: 2048K Total, 342K MRU, 760K MFU, 272K Anon, 96K Header, 442K Other
 Swap: 91M Total, 79M Free, 13% Inuse, 80K In, 104K Out
 .TP
 .B K:
@@ -23,15 +23,14 @@ Gigabyte
 number of bytes active
 .TP
 .B Inact:
-number of bytes inactive
+number of clean bytes inactive
+.TP
+.B Laundry:
+number of dirty bytes queued for laundering
 .TP
 .B Wired:
 number of bytes wired down, including BIO-level cached file data pages
 .TP
-.B Cache:
-number of clean bytes caching data that are available for
-immediate reallocation
-.TP
 .B Buf:
 number of bytes used for BIO-level disk caching
 .TP
diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c
index 0dbd2d165dda..14fad8ca392f 100644
--- a/usr.bin/vmstat/vmstat.c
+++ b/usr.bin/vmstat/vmstat.c
@@ -567,7 +567,7 @@ fill_vmmeter(struct vmmeter *vmmp)
 		GET_VM_STATS(vm, v_reactivated);
 		GET_VM_STATS(vm, v_pdwakeups);
 		GET_VM_STATS(vm, v_pdpages);
-		GET_VM_STATS(vm, v_tcached);
+		GET_VM_STATS(vm, v_pdshortfalls);
 		GET_VM_STATS(vm, v_dfree);
 		GET_VM_STATS(vm, v_pfree);
 		GET_VM_STATS(vm, v_tfree);
@@ -581,7 +581,7 @@ fill_vmmeter(struct vmmeter *vmmp)
 		GET_VM_STATS(vm, v_active_count);
 		GET_VM_STATS(vm, v_inactive_target);
 		GET_VM_STATS(vm, v_inactive_count);
-		GET_VM_STATS(vm, v_cache_count);
+		GET_VM_STATS(vm, v_laundry_count);
 		GET_VM_STATS(vm, v_pageout_free_min);
 		GET_VM_STATS(vm, v_interrupt_free_min);
 		/*GET_VM_STATS(vm, v_free_severe);*/
@@ -1059,7 +1059,9 @@ dosum(void)
 		sum.v_pdwakeups);
 	xo_emit("{:page-daemon-pages/%9u} {N:pages examined by the page daemon}\n",
 		sum.v_pdpages);
-	xo_emit("{:reactivated/%9u} {N:pages reactivated}\n",
+	xo_emit("{:page-reclamation-shortfalls/%9u} {N:clean page reclamation shortfalls}\n",
+		sum.v_pdshortfalls);
+	xo_emit("{:reactivated/%9u} {N:pages reactivated by the page daemon}\n",
 		sum.v_reactivated);
 	xo_emit("{:copy-on-write-faults/%9u} {N:copy-on-write faults}\n",
 		sum.v_cow_faults);
@@ -1095,8 +1097,8 @@ dosum(void)
 		sum.v_active_count);
 	xo_emit("{:inactive-pages/%9u} {N:pages inactive}\n",
 		sum.v_inactive_count);
-	xo_emit("{:vm-cache/%9u} {N:pages in VM cache}\n",
-		sum.v_cache_count);
+	xo_emit("{:laundry-pages/%9u} {N:pages in the laundry queue}\n",
+		sum.v_laundry_count);
 	xo_emit("{:wired-pages/%9u} {N:pages wired down}\n",
 		sum.v_wire_count);
 	xo_emit("{:free-pages/%9u} {N:pages free}\n",

From 3b49535a5a124165d6521ca19e12c0a457ca13b8 Mon Sep 17 00:00:00 2001
From: Shteryana Shopova 
Date: Thu, 10 Nov 2016 20:51:26 +0000
Subject: [PATCH 127/127] Reply to a snmpEngineID discovery PDU with a Report
 PDU as per the requirements of RFC 3414 section 4.

PR:	174974
Submitted by:	pguyot@kallisys.net
Reported by:	several people
Reviewed by:	bz@
---
 contrib/bsnmp/lib/snmpagent.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/contrib/bsnmp/lib/snmpagent.c b/contrib/bsnmp/lib/snmpagent.c
index a425c376d62e..f0bb2f389729 100644
--- a/contrib/bsnmp/lib/snmpagent.c
+++ b/contrib/bsnmp/lib/snmpagent.c
@@ -171,7 +171,10 @@ snmp_pdu_create_response(const struct snmp_pdu *pdu, struct snmp_pdu *resp)
 	memset(resp, 0, sizeof(*resp));
 	strcpy(resp->community, pdu->community);
 	resp->version = pdu->version;
-	resp->type = SNMP_PDU_RESPONSE;
+	if (pdu->flags & SNMP_MSG_AUTODISCOVER)
+		resp->type = SNMP_PDU_REPORT; /* RFC 3414.4 */
+	else
+		resp->type = SNMP_PDU_RESPONSE;
 	resp->request_id = pdu->request_id;
 	resp->version = pdu->version;