diff -druNp --no-dereference linux-libre-3.2.88-gnu1/arch/mips/cavium-octeon/octeon-memcpy.S linux-libre-3.2.89-gnu1/arch/mips/cavium-octeon/octeon-memcpy.S
--- linux-libre-3.2.88-gnu1/arch/mips/cavium-octeon/octeon-memcpy.S	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/arch/mips/cavium-octeon/octeon-memcpy.S	2017-06-05 16:13:58.000000000 -0400
@@ -223,18 +223,18 @@ EXC(	STORE	t2, UNIT(6)(dst),	s_exc_p10u)
 	ADD	src, src, 16*NBYTES
 EXC(	STORE	t3, UNIT(7)(dst),	s_exc_p9u)
 	ADD	dst, dst, 16*NBYTES
-EXC(	LOAD	t0, UNIT(-8)(src),	l_exc_copy)
-EXC(	LOAD	t1, UNIT(-7)(src),	l_exc_copy)
-EXC(	LOAD	t2, UNIT(-6)(src),	l_exc_copy)
-EXC(	LOAD	t3, UNIT(-5)(src),	l_exc_copy)
+EXC(	LOAD	t0, UNIT(-8)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t1, UNIT(-7)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t2, UNIT(-6)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t3, UNIT(-5)(src),	l_exc_copy_rewind16)
 EXC(	STORE	t0, UNIT(-8)(dst),	s_exc_p8u)
 EXC(	STORE	t1, UNIT(-7)(dst),	s_exc_p7u)
 EXC(	STORE	t2, UNIT(-6)(dst),	s_exc_p6u)
 EXC(	STORE	t3, UNIT(-5)(dst),	s_exc_p5u)
-EXC(	LOAD	t0, UNIT(-4)(src),	l_exc_copy)
-EXC(	LOAD	t1, UNIT(-3)(src),	l_exc_copy)
-EXC(	LOAD	t2, UNIT(-2)(src),	l_exc_copy)
-EXC(	LOAD	t3, UNIT(-1)(src),	l_exc_copy)
+EXC(	LOAD	t0, UNIT(-4)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t1, UNIT(-3)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t2, UNIT(-2)(src),	l_exc_copy_rewind16)
+EXC(	LOAD	t3, UNIT(-1)(src),	l_exc_copy_rewind16)
 EXC(	STORE	t0, UNIT(-4)(dst),	s_exc_p4u)
 EXC(	STORE	t1, UNIT(-3)(dst),	s_exc_p3u)
 EXC(	STORE	t2, UNIT(-2)(dst),	s_exc_p2u)
@@ -400,6 +400,10 @@ done:
 	 nop
 	END(memcpy)
 
+l_exc_copy_rewind16:
+	/* Rewind src and dst by 16*NBYTES for l_exc_copy */
+	SUB	src, src, 16*NBYTES
+	SUB	dst, dst, 16*NBYTES
 l_exc_copy:
 	/*
 	 * Copy bytes from src until faulting load address (or until a
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/arch/mips/configs/ip27_defconfig linux-libre-3.2.89-gnu1/arch/mips/configs/ip27_defconfig
--- linux-libre-3.2.88-gnu1/arch/mips/configs/ip27_defconfig	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/arch/mips/configs/ip27_defconfig	2017-06-05 16:13:58.000000000 -0400
@@ -206,7 +206,6 @@ CONFIG_MLX4_EN=m
 # CONFIG_MLX4_DEBUG is not set
 CONFIG_TEHUTI=m
 CONFIG_BNX2X=m
-CONFIG_QLGE=m
 CONFIG_SFC=m
 CONFIG_BE2NET=m
 CONFIG_LIBERTAS_THINFIRM=m
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/arch/mips/include/asm/checksum.h linux-libre-3.2.89-gnu1/arch/mips/include/asm/checksum.h
--- linux-libre-3.2.88-gnu1/arch/mips/include/asm/checksum.h	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/arch/mips/include/asm/checksum.h	2017-06-05 16:13:58.000000000 -0400
@@ -155,7 +155,9 @@ static inline __wsum csum_tcpudp_nofold(
 	"	daddu	%0, %4		\n"
 	"	dsll32	$1, %0, 0	\n"
 	"	daddu	%0, $1		\n"
+	"	sltu	$1, %0, $1	\n"
 	"	dsra32	%0, %0, 0	\n"
+	"	addu	%0, $1		\n"
 #endif
 	"	.set	pop"
 	: "=r" (sum)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/arch/mips/Makefile linux-libre-3.2.89-gnu1/arch/mips/Makefile
--- linux-libre-3.2.88-gnu1/arch/mips/Makefile	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/arch/mips/Makefile	2017-06-05 16:13:58.000000000 -0400
@@ -285,11 +285,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64
 
 archprepare:
 ifdef CONFIG_MIPS32_N32
-	@echo '  Checking missing-syscalls for N32'
+	@$(kecho) '  Checking missing-syscalls for N32'
 	$(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
-	@echo '  Checking missing-syscalls for O32'
+	@$(kecho) '  Checking missing-syscalls for O32'
 	$(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=32"
 endif
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/arch/powerpc/kernel/hw_breakpoint.c linux-libre-3.2.89-gnu1/arch/powerpc/kernel/hw_breakpoint.c
--- linux-libre-3.2.88-gnu1/arch/powerpc/kernel/hw_breakpoint.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/arch/powerpc/kernel/hw_breakpoint.c	2017-06-05 16:13:58.000000000 -0400
@@ -226,8 +226,10 @@ int __kprobes hw_breakpoint_handler(stru
 	rcu_read_lock();
 
 	bp = __get_cpu_var(bp_per_reg);
-	if (!bp)
+	if (!bp) {
+		rc = NOTIFY_DONE;
 		goto out;
+	}
 	info = counter_arch_bp(bp);
 
 	/*
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/arch/x86/kernel/pci-calgary_64.c linux-libre-3.2.89-gnu1/arch/x86/kernel/pci-calgary_64.c
--- linux-libre-3.2.88-gnu1/arch/x86/kernel/pci-calgary_64.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/arch/x86/kernel/pci-calgary_64.c	2017-06-05 16:13:58.000000000 -0400
@@ -295,7 +295,7 @@ static void iommu_free(struct iommu_tabl
 
 	/* were we called with bad_dma_address? */
 	badend = DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE);
-	if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) {
+	if (unlikely(dma_addr < badend)) {
 		WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "
 		       "address 0x%Lx\n", dma_addr);
 		return;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/crypto/ahash.c linux-libre-3.2.89-gnu1/crypto/ahash.c
--- linux-libre-3.2.88-gnu1/crypto/ahash.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/crypto/ahash.c	2017-06-05 16:13:58.000000000 -0400
@@ -30,6 +30,7 @@ struct ahash_request_priv {
 	crypto_completion_t complete;
 	void *data;
 	u8 *result;
+	u32 flags;
 	void *ubuf[] CRYPTO_MINALIGN_ATTR;
 };
 
@@ -191,58 +192,133 @@ static inline unsigned int ahash_align_b
 	return len + (mask & ~(crypto_tfm_ctx_alignment() - 1));
 }
 
-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
+static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
 {
-	struct ahash_request_priv *priv = req->priv;
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	unsigned long alignmask = crypto_ahash_alignmask(tfm);
+	unsigned int ds = crypto_ahash_digestsize(tfm);
+	struct ahash_request_priv *priv;
 
-	if (err == -EINPROGRESS)
-		return;
+	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
+		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+		       GFP_KERNEL : GFP_ATOMIC);
+	if (!priv)
+		return -ENOMEM;
+
+	/*
+	 * WARNING: Voodoo programming below!
+	 *
+	 * The code below is obscure and hard to understand, thus explanation
+	 * is necessary. See include/crypto/hash.h and include/linux/crypto.h
+	 * to understand the layout of structures used here!
+	 *
+	 * The code here will replace portions of the ORIGINAL request with
+	 * pointers to new code and buffers so the hashing operation can store
+	 * the result in aligned buffer. We will call the modified request
+	 * an ADJUSTED request.
+	 *
+	 * The newly mangled request will look as such:
+	 *
+	 * req {
+	 *   .result        = ADJUSTED[new aligned buffer]
+	 *   .base.complete = ADJUSTED[pointer to completion function]
+	 *   .base.data     = ADJUSTED[*req (pointer to self)]
+	 *   .priv          = ADJUSTED[new priv] {
+	 *           .result   = ORIGINAL(result)
+	 *           .complete = ORIGINAL(base.complete)
+	 *           .data     = ORIGINAL(base.data)
+	 *   }
+	 */
+
+	priv->result = req->result;
+	priv->complete = req->base.complete;
+	priv->data = req->base.data;
+	priv->flags = req->base.flags;
+
+	/*
+	 * WARNING: We do not backup req->priv here! The req->priv
+	 *          is for internal use of the Crypto API and the
+	 *          user must _NOT_ _EVER_ depend on it's content!
+	 */
+
+	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
+	req->base.complete = cplt;
+	req->base.data = req;
+	req->priv = priv;
+
+	return 0;
+}
+
+static void ahash_restore_req(struct ahash_request *req, int err)
+{
+	struct ahash_request_priv *priv = req->priv;
 
 	if (!err)
 		memcpy(priv->result, req->result,
 		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
 
+	/* Restore the original crypto request. */
+	req->result = priv->result;
+
+	ahash_request_set_callback(req, priv->flags,
+				   priv->complete, priv->data);
+	req->priv = NULL;
+
+	/* Free the req->priv.priv from the ADJUSTED request. */
 	kzfree(priv);
 }
 
+static void ahash_notify_einprogress(struct ahash_request *req)
+{
+	struct ahash_request_priv *priv = req->priv;
+	struct crypto_async_request oreq;
+
+	oreq.data = priv->data;
+
+	priv->complete(&oreq, -EINPROGRESS);
+}
+
 static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
 {
 	struct ahash_request *areq = req->data;
-	struct ahash_request_priv *priv = areq->priv;
-	crypto_completion_t complete = priv->complete;
-	void *data = priv->data;
 
-	ahash_op_unaligned_finish(areq, err);
+	if (err == -EINPROGRESS) {
+		ahash_notify_einprogress(areq);
+		return;
+	}
 
-	complete(data, err);
+	/*
+	 * Restore the original request, see ahash_op_unaligned() for what
+	 * goes where.
+	 *
+	 * The "struct ahash_request *req" here is in fact the "req.base"
+	 * from the ADJUSTED request from ahash_op_unaligned(), thus as it
+	 * is a pointer to self, it is also the ADJUSTED "req" .
+	 */
+
+	/* First copy req->result into req->priv.result */
+	ahash_restore_req(areq, err);
+
+	/* Complete the ORIGINAL request. */
+	areq->base.complete(&areq->base, err);
 }
 
 static int ahash_op_unaligned(struct ahash_request *req,
 			      int (*op)(struct ahash_request *))
 {
-	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-	unsigned long alignmask = crypto_ahash_alignmask(tfm);
-	unsigned int ds = crypto_ahash_digestsize(tfm);
-	struct ahash_request_priv *priv;
 	int err;
 
-	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
-		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
-		       GFP_KERNEL : GFP_ATOMIC);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->result = req->result;
-	priv->complete = req->base.complete;
-	priv->data = req->base.data;
-
-	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
-	req->base.complete = ahash_op_unaligned_done;
-	req->base.data = req;
-	req->priv = priv;
+	err = ahash_save_req(req, ahash_op_unaligned_done);
+	if (err)
+		return err;
 
 	err = op(req);
-	ahash_op_unaligned_finish(req, err);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (ahash_request_flags(req) &
+			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return err;
+
+	ahash_restore_req(req, err);
 
 	return err;
 }
@@ -277,30 +353,16 @@ int crypto_ahash_digest(struct ahash_req
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_digest);
 
-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
+static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
 {
-	struct ahash_request_priv *priv = req->priv;
+	struct ahash_request *areq = req->data;
 
 	if (err == -EINPROGRESS)
 		return;
 
-	if (!err)
-		memcpy(priv->result, req->result,
-		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
-	kzfree(priv);
-}
-
-static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
-{
-	struct ahash_request *areq = req->data;
-	struct ahash_request_priv *priv = areq->priv;
-	crypto_completion_t complete = priv->complete;
-	void *data = priv->data;
-
-	ahash_def_finup_finish2(areq, err);
+	ahash_restore_req(areq, err);
 
-	complete(data, err);
+	areq->base.complete(&areq->base, err);
 }
 
 static int ahash_def_finup_finish1(struct ahash_request *req, int err)
@@ -309,49 +371,52 @@ static int ahash_def_finup_finish1(struc
 		goto out;
 
 	req->base.complete = ahash_def_finup_done2;
-	req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
 	err = crypto_ahash_reqtfm(req)->final(req);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (ahash_request_flags(req) &
+			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return err;
 
 out:
-	ahash_def_finup_finish2(req, err);
+	ahash_restore_req(req, err);
 	return err;
 }
 
 static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
 {
 	struct ahash_request *areq = req->data;
-	struct ahash_request_priv *priv = areq->priv;
-	crypto_completion_t complete = priv->complete;
-	void *data = priv->data;
+
+	if (err == -EINPROGRESS) {
+		ahash_notify_einprogress(areq);
+		return;
+	}
+
+	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	err = ahash_def_finup_finish1(areq, err);
+	if (areq->priv)
+		return;
 
-	complete(data, err);
+	areq->base.complete(&areq->base, err);
 }
 
 static int ahash_def_finup(struct ahash_request *req)
 {
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-	unsigned long alignmask = crypto_ahash_alignmask(tfm);
-	unsigned int ds = crypto_ahash_digestsize(tfm);
-	struct ahash_request_priv *priv;
-
-	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
-		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
-		       GFP_KERNEL : GFP_ATOMIC);
-	if (!priv)
-		return -ENOMEM;
+	int err;
 
-	priv->result = req->result;
-	priv->complete = req->base.complete;
-	priv->data = req->base.data;
+	err = ahash_save_req(req, ahash_def_finup_done1);
+	if (err)
+		return err;
 
-	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
-	req->base.complete = ahash_def_finup_done1;
-	req->base.data = req;
-	req->priv = priv;
+	err = tfm->update(req);
+	if (err == -EINPROGRESS ||
+	    (err == -EBUSY && (ahash_request_flags(req) &
+			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
+		return err;
 
-	return ahash_def_finup_finish1(req, tfm->update(req));
+	return ahash_def_finup_finish1(req, err);
 }
 
 static int ahash_no_export(struct ahash_request *req, void *out)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/bcma/main.c linux-libre-3.2.89-gnu1/drivers/bcma/main.c
--- linux-libre-3.2.88-gnu1/drivers/bcma/main.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/bcma/main.c	2017-06-05 16:13:58.000000000 -0400
@@ -297,8 +297,11 @@ static int bcma_device_probe(struct devi
 					       drv);
 	int err = 0;
 
+	get_device(dev);
 	if (adrv->probe)
 		err = adrv->probe(core);
+	if (err)
+		put_device(dev);
 
 	return err;
 }
@@ -311,6 +314,7 @@ static int bcma_device_remove(struct dev
 
 	if (adrv->remove)
 		adrv->remove(core);
+	put_device(dev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/bluetooth/ath3k.c linux-libre-3.2.89-gnu1/drivers/bluetooth/ath3k.c
--- linux-libre-3.2.88-gnu1/drivers/bluetooth/ath3k.c	2017-04-05 09:31:55.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/bluetooth/ath3k.c	2017-06-06 13:23:50.000000000 -0400
@@ -91,6 +91,7 @@ static struct usb_device_id ath3k_table[
 	{ USB_DEVICE(0x04CA, 0x300f) },
 	{ USB_DEVICE(0x04CA, 0x3010) },
 	{ USB_DEVICE(0x04CA, 0x3014) },
+	{ USB_DEVICE(0x04CA, 0x3018) },
 	{ USB_DEVICE(0x0930, 0x0219) },
 	{ USB_DEVICE(0x0930, 0x021c) },
 	{ USB_DEVICE(0x0930, 0x0220) },
@@ -157,6 +158,7 @@ static struct usb_device_id ath3k_blist_
 	{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/bluetooth/btusb.c linux-libre-3.2.89-gnu1/drivers/bluetooth/btusb.c
--- linux-libre-3.2.88-gnu1/drivers/bluetooth/btusb.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/bluetooth/btusb.c	2017-06-05 16:13:58.000000000 -0400
@@ -176,6 +176,7 @@ static struct usb_device_id blacklist_ta
 	{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/gpu/drm/radeon/radeon_bios.c linux-libre-3.2.89-gnu1/drivers/gpu/drm/radeon/radeon_bios.c
--- linux-libre-3.2.88-gnu1/drivers/gpu/drm/radeon/radeon_bios.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/gpu/drm/radeon/radeon_bios.c	2017-06-05 16:13:58.000000000 -0400
@@ -570,51 +570,57 @@ static bool radeon_read_disabled_bios(st
 #ifdef CONFIG_ACPI
 static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
 {
-	bool ret = false;
 	struct acpi_table_header *hdr;
 	acpi_size tbl_size;
 	UEFI_ACPI_VFCT *vfct;
-	GOP_VBIOS_CONTENT *vbios;
-	VFCT_IMAGE_HEADER *vhdr;
+	unsigned offset;
 
 	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
 		return false;
 	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
 		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
-		goto out_unmap;
+		return false;
 	}
 
 	vfct = (UEFI_ACPI_VFCT *)hdr;
-	if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
-		DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
-		goto out_unmap;
-	}
+	offset = vfct->VBIOSImageOffset;
 
-	vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
-	vhdr = &vbios->VbiosHeader;
-	DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
-			vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
-			vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
+	while (offset < tbl_size) {
+		GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
+		VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
 
-	if (vhdr->PCIBus != rdev->pdev->bus->number ||
-	    vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) ||
-	    vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) ||
-	    vhdr->VendorID != rdev->pdev->vendor ||
-	    vhdr->DeviceID != rdev->pdev->device) {
-		DRM_INFO("ACPI VFCT table is not for this card\n");
-		goto out_unmap;
-	};
+		offset += sizeof(VFCT_IMAGE_HEADER);
+		if (offset > tbl_size) {
+			DRM_ERROR("ACPI VFCT image header truncated\n");
+			return false;
+		}
 
-	if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
-		DRM_ERROR("ACPI VFCT image truncated\n");
-		goto out_unmap;
-	}
+		offset += vhdr->ImageLength;
+		if (offset > tbl_size) {
+			DRM_ERROR("ACPI VFCT image truncated\n");
+			return false;
+		}
 
-	rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
-	ret = !!rdev->bios;
+		if (vhdr->ImageLength &&
+		    vhdr->PCIBus == rdev->pdev->bus->number &&
+		    vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) &&
+		    vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) &&
+		    vhdr->VendorID == rdev->pdev->vendor &&
+		    vhdr->DeviceID == rdev->pdev->device) {
+			rdev->bios = kmemdup(&vbios->VbiosContent,
+					     vhdr->ImageLength,
+					     GFP_KERNEL);
 
-out_unmap:
-	return ret;
+			if (!rdev->bios) {
+				kfree(rdev->bios);
+				return false;
+			}
+			return true;
+		}
+	}
+
+	DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+	return false;
 }
 #else
 static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-3.2.89-gnu1/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-3.2.88-gnu1/drivers/gpu/drm/ttm/ttm_bo.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/gpu/drm/ttm/ttm_bo.c	2017-06-05 16:13:58.000000000 -0400
@@ -1807,7 +1807,6 @@ static int ttm_bo_swapout(struct ttm_mem
 	struct ttm_buffer_object *bo;
 	int ret = -EBUSY;
 	int put_count;
-	uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);
 
 	spin_lock(&glob->lru_lock);
 	while (ret == -EBUSY) {
@@ -1860,7 +1859,8 @@ static int ttm_bo_swapout(struct ttm_mem
 	if (unlikely(ret != 0))
 		goto out;
 
-	if ((bo->mem.placement & swap_placement) != swap_placement) {
+	if (bo->mem.mem_type != TTM_PL_SYSTEM ||
+	    bo->ttm->caching_state != tt_cached) {
 		struct ttm_mem_reg evict_mem;
 
 		evict_mem = bo->mem;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c linux-libre-3.2.89-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux-libre-3.2.88-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2017-06-05 16:13:58.000000000 -0400
@@ -1304,11 +1304,14 @@ int vmw_surface_define_ioctl(struct drm_
 			128;
 
 	num_sizes = 0;
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
+			return -EINVAL;
 		num_sizes += req->mip_levels[i];
+	}
 
-	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
-	    DRM_VMW_MAX_MIP_LEVELS)
+	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
+	    num_sizes == 0)
 		return -EINVAL;
 
 	size = vmw_user_surface_size + 128 +
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/hv/hv.c linux-libre-3.2.89-gnu1/drivers/hv/hv.c
--- linux-libre-3.2.88-gnu1/drivers/hv/hv.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/hv/hv.c	2017-06-05 16:13:58.000000000 -0400
@@ -178,7 +178,7 @@ int hv_init(void)
 	/* See if the hypercall page is already set */
 	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
 
-	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
+	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
 
 	if (!virtaddr)
 		goto cleanup;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/infiniband/core/cma.c linux-libre-3.2.89-gnu1/drivers/infiniband/core/cma.c
--- linux-libre-3.2.88-gnu1/drivers/infiniband/core/cma.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/infiniband/core/cma.c	2017-06-05 16:13:58.000000000 -0400
@@ -2737,6 +2737,9 @@ static int cma_accept_iw(struct rdma_id_
 	struct iw_cm_conn_param iw_param;
 	int ret;
 
+	if (!conn_param)
+		return -EINVAL;
+
 	ret = cma_modify_qp_rtr(id_priv, conn_param);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-3.2.89-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-3.2.88-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2017-06-05 16:13:58.000000000 -0400
@@ -1366,7 +1366,7 @@ static void ipoib_cm_tx_reap(struct work
 
 	while (!list_empty(&priv->cm.reap_list)) {
 		p = list_entry(priv->cm.reap_list.next, typeof(*p), list);
-		list_del(&p->list);
+		list_del_init(&p->list);
 		spin_unlock_irqrestore(&priv->lock, flags);
 		netif_tx_unlock_bh(dev);
 		ipoib_cm_tx_destroy(p);
@@ -1480,6 +1480,14 @@ static ssize_t set_mode(struct device *d
 	if (!rtnl_trylock())
 		return restart_syscall();
 
+	if ((test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) &&
+	     !strcmp(buf, "connected\n")) ||
+	     (!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) &&
+	     !strcmp(buf, "datagram\n"))) {
+		rtnl_unlock();
+		return 0;
+	}
+
 	/* flush paths if we switch modes so that connections are restarted */
 	if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) {
 		set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/md/linear.c linux-libre-3.2.89-gnu1/drivers/md/linear.c
--- linux-libre-3.2.88-gnu1/drivers/md/linear.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/md/linear.c	2017-06-05 16:13:58.000000000 -0400
@@ -88,6 +88,12 @@ static int linear_mergeable_bvec(struct
 	return maxsectors << 9;
 }
 
+/*
+ * In linear_congested() conf->raid_disks is used as a copy of
+ * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks
+ * and conf->disks[] are created in linear_conf(), they are always
+ * consitent with each other, but mddev->raid_disks does not.
+ */
 static int linear_congested(void *data, int bits)
 {
 	struct mddev *mddev = data;
@@ -100,7 +106,7 @@ static int linear_congested(void *data,
 	rcu_read_lock();
 	conf = rcu_dereference(mddev->private);
 
-	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
+	for (i = 0; i < conf->raid_disks && !ret ; i++) {
 		struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
 		ret |= bdi_congested(&q->backing_dev_info, bits);
 	}
@@ -188,6 +194,19 @@ static struct linear_conf *linear_conf(s
 			conf->disks[i-1].end_sector +
 			conf->disks[i].rdev->sectors;
 
+	/*
+	 * conf->raid_disks is copy of mddev->raid_disks. The reason to
+	 * keep a copy of mddev->raid_disks in struct linear_conf is,
+	 * mddev->raid_disks may not be consistent with pointers number of
+	 * conf->disks[] when it is updated in linear_add() and used to
+	 * iterate old conf->disks[] earray in linear_congested().
+	 * Here conf->raid_disks is always consitent with number of
+	 * pointers in conf->disks[] array, and mddev->private is updated
+	 * with rcu_assign_pointer() in linear_addr(), such race can be
+	 * avoided.
+	 */
+	conf->raid_disks = raid_disks;
+
 	return conf;
 
 out:
@@ -237,8 +256,16 @@ static int linear_add(struct mddev *mdde
 	if (!newconf)
 		return -ENOMEM;
 
+	/* newconf->raid_disks already keeps a copy of * the increased
+	 * value of mddev->raid_disks, WARN_ONCE() is just used to make
+	 * sure of this. It is possible that oldconf is still referenced
+	 * in linear_congested(), therefore kfree_rcu() is used to free
+	 * oldconf until no one uses it anymore.
+	 */
 	oldconf = rcu_dereference(mddev->private);
 	mddev->raid_disks++;
+	WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
+		"copied raid_disks doesn't match mddev->raid_disks");
 	rcu_assign_pointer(mddev->private, newconf);
 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
 	set_capacity(mddev->gendisk, mddev->array_sectors);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/md/linear.h linux-libre-3.2.89-gnu1/drivers/md/linear.h
--- linux-libre-3.2.88-gnu1/drivers/md/linear.h	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/md/linear.h	2017-06-05 16:13:58.000000000 -0400
@@ -10,6 +10,7 @@ struct linear_conf
 {
 	struct rcu_head		rcu;
 	sector_t		array_sectors;
+	int			raid_disks; /* a copy of mddev->raid_disks */
 	struct dev_info		disks[0];
 };
 #endif
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/md/md.c linux-libre-3.2.89-gnu1/drivers/md/md.c
--- linux-libre-3.2.88-gnu1/drivers/md/md.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/md/md.c	2017-06-05 16:13:58.000000000 -0400
@@ -8292,7 +8292,14 @@ static __exit void md_exit(void)
 	remove_proc_entry("mdstat", NULL);
 	for_each_mddev(mddev, tmp) {
 		export_array(mddev);
+		mddev->ctime = 0;
 		mddev->hold_active = 0;
+		/*
+		 * for_each_mddev() will call mddev_put() at the end of each
+		 * iteration.  As the mddev is now fully clear, this will
+		 * schedule the mddev for destruction by a workqueue, and the
+		 * destroy_workqueue() below will wait for that to complete.
+		 */
 	}
 	destroy_workqueue(md_misc_wq);
 	destroy_workqueue(md_wq);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/media/dvb/dm1105/Kconfig linux-libre-3.2.89-gnu1/drivers/media/dvb/dm1105/Kconfig
--- linux-libre-3.2.88-gnu1/drivers/media/dvb/dm1105/Kconfig	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/media/dvb/dm1105/Kconfig	2017-06-05 16:13:58.000000000 -0400
@@ -1,6 +1,6 @@
 config DVB_DM1105
 	tristate "SDMC DM1105 based PCI cards"
-	depends on DVB_CORE && PCI && I2C
+	depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT
 	select DVB_PLL if !DVB_FE_CUSTOMISE
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
 	select DVB_STV0288 if !DVB_FE_CUSTOMISE
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/mmc/host/omap_hsmmc.c linux-libre-3.2.89-gnu1/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-3.2.88-gnu1/drivers/mmc/host/omap_hsmmc.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/mmc/host/omap_hsmmc.c	2017-06-05 16:13:58.000000000 -0400
@@ -1499,10 +1499,11 @@ static int omap_hsmmc_start_dma_transfer
 }
 
 static void set_data_timeout(struct omap_hsmmc_host *host,
-			     unsigned int timeout_ns,
+			     unsigned long long timeout_ns,
 			     unsigned int timeout_clks)
 {
-	unsigned int timeout, cycle_ns;
+	unsigned long long timeout = timeout_ns;
+	unsigned int cycle_ns;
 	uint32_t reg, clkd, dto = 0;
 
 	reg = OMAP_HSMMC_READ(host->base, SYSCTL);
@@ -1511,7 +1512,7 @@ static void set_data_timeout(struct omap
 		clkd = 1;
 
 	cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
-	timeout = timeout_ns / cycle_ns;
+	do_div(timeout, cycle_ns);
 	timeout += timeout_clks;
 	if (timeout) {
 		while ((timeout & 0x80000000) == 0) {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/net/wireless/adm8211.c linux-libre-3.2.89-gnu1/drivers/net/wireless/adm8211.c
--- linux-libre-3.2.88-gnu1/drivers/net/wireless/adm8211.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/net/wireless/adm8211.c	2017-06-05 16:13:58.000000000 -0400
@@ -1842,7 +1842,8 @@ static int __devinit adm8211_probe(struc
 	priv->rx_ring_size = rx_ring_size;
 	priv->tx_ring_size = tx_ring_size;
 
-	if (adm8211_alloc_rings(dev)) {
+	err = adm8211_alloc_rings(dev);
+	if (err) {
 		printk(KERN_ERR "%s (adm8211): Cannot allocate TX/RX ring\n",
 		       pci_name(pdev));
 		goto err_iounmap;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c linux-libre-3.2.89-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c
--- linux-libre-3.2.88-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2017-06-05 16:13:58.000000000 -0400
@@ -493,8 +493,7 @@ ath5k_set_key(struct ieee80211_hw *hw, e
 			break;
 		return -EOPNOTSUPP;
 	default:
-		WARN_ON(1);
-		return -EINVAL;
+		return -EOPNOTSUPP;
 	}
 
 	mutex_lock(&ah->lock);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/net/wireless/mwifiex/debugfs.c linux-libre-3.2.89-gnu1/drivers/net/wireless/mwifiex/debugfs.c
--- linux-libre-3.2.88-gnu1/drivers/net/wireless/mwifiex/debugfs.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/net/wireless/mwifiex/debugfs.c	2017-06-05 16:13:58.000000000 -0400
@@ -221,7 +221,8 @@ mwifiex_info_read(struct file *file, cha
 	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
 		p += sprintf(p, "multicast_count=\"%d\"\n",
 			     netdev_mc_count(netdev));
-		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
+		p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len,
+			     info.ssid.ssid);
 		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
 		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
 		p += sprintf(p, "region_code = \"%02x\"\n", info.region_code);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/s390/cio/qdio_thinint.c linux-libre-3.2.89-gnu1/drivers/s390/cio/qdio_thinint.c
--- linux-libre-3.2.88-gnu1/drivers/s390/cio/qdio_thinint.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/s390/cio/qdio_thinint.c	2017-06-05 16:13:58.000000000 -0400
@@ -146,11 +146,11 @@ static inline void tiqdio_call_inq_handl
 	struct qdio_q *q;
 	int i;
 
-	for_each_input_queue(irq, q, i) {
-		if (!references_shared_dsci(irq) &&
-		    has_multiple_inq_on_dsci(irq))
-			xchg(q->irq_ptr->dsci, 0);
+	if (!references_shared_dsci(irq) &&
+	    has_multiple_inq_on_dsci(irq))
+		xchg(irq->dsci, 0);
 
+	for_each_input_queue(irq, q, i) {
 		if (q->u.in.queue_start_poll) {
 			/* skip if polling is enabled or already in work */
 			if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/scsi/aacraid/commsup.c linux-libre-3.2.89-gnu1/drivers/scsi/aacraid/commsup.c
--- linux-libre-3.2.88-gnu1/drivers/scsi/aacraid/commsup.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/scsi/aacraid/commsup.c	2017-06-05 16:13:58.000000000 -0400
@@ -83,12 +83,20 @@ static int fib_map_alloc(struct aac_dev
 
 void aac_fib_map_free(struct aac_dev *dev)
 {
-	if (dev->hw_fib_va && dev->max_fib_size) {
-		pci_free_consistent(dev->pdev,
-		(dev->max_fib_size *
-		(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)),
-		dev->hw_fib_va, dev->hw_fib_pa);
-	}
+	size_t alloc_size;
+	size_t fib_size;
+	int num_fibs;
+
+	if(!dev->hw_fib_va || !dev->max_fib_size)
+		return;
+
+	num_fibs = dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB;
+	fib_size = dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
+	alloc_size = fib_size * num_fibs + ALIGN32 - 1;
+
+	pci_free_consistent(dev->pdev, alloc_size, dev->hw_fib_va,
+							dev->hw_fib_pa);
+
 	dev->hw_fib_va = NULL;
 	dev->hw_fib_pa = 0;
 }
@@ -116,22 +124,20 @@ int aac_fib_setup(struct aac_dev * dev)
 	if (i<0)
 		return -ENOMEM;
 
-	/* 32 byte alignment for PMC */
-	hw_fib_pa = (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1);
-	dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
-		(hw_fib_pa - dev->hw_fib_pa));
-	dev->hw_fib_pa = hw_fib_pa;
 	memset(dev->hw_fib_va, 0,
 		(dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) *
 		(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
 
+	/* 32 byte alignment for PMC */
+	hw_fib_pa = (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1);
+	hw_fib    = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
+					(hw_fib_pa - dev->hw_fib_pa));
+
 	/* add Xport header */
-	dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
+	hw_fib = (struct hw_fib *)((unsigned char *)hw_fib +
 		sizeof(struct aac_fib_xporthdr));
-	dev->hw_fib_pa += sizeof(struct aac_fib_xporthdr);
+	hw_fib_pa += sizeof(struct aac_fib_xporthdr);
 
-	hw_fib = dev->hw_fib_va;
-	hw_fib_pa = dev->hw_fib_pa;
 	/*
 	 *	Initialise the fibs
 	 */
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/scsi/aacraid/src.c linux-libre-3.2.89-gnu1/drivers/scsi/aacraid/src.c
--- linux-libre-3.2.88-gnu1/drivers/scsi/aacraid/src.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/scsi/aacraid/src.c	2017-06-05 16:13:58.000000000 -0400
@@ -317,16 +317,23 @@ static int aac_src_check_health(struct a
 	u32 status = src_readl(dev, MUnit.OMR);
 
 	/*
+	 *	Check to see if the board panic'd.
+	 */
+	if (unlikely(status & KERNEL_PANIC))
+		goto err_blink;
+
+	/*
 	 *	Check to see if the board failed any self tests.
 	 */
 	if (unlikely(status & SELF_TEST_FAILED))
-		return -1;
+		goto err_out;
 
 	/*
-	 *	Check to see if the board panic'd.
+	 *	Check to see if the board failed any self tests.
 	 */
-	if (unlikely(status & KERNEL_PANIC))
-		return (status >> 16) & 0xFF;
+	if (unlikely(status & MONITOR_PANIC))
+		goto err_out;
+
 	/*
 	 *	Wait for the adapter to be up and running.
 	 */
@@ -336,6 +343,12 @@ static int aac_src_check_health(struct a
 	 *	Everything is OK
 	 */
 	return 0;
+
+err_out:
+	return -1;
+
+err_blink:
+	return (status > 16) & 0xFF;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/staging/rtl8712/rtl871x_recv.c linux-libre-3.2.89-gnu1/drivers/staging/rtl8712/rtl871x_recv.c
--- linux-libre-3.2.88-gnu1/drivers/staging/rtl8712/rtl871x_recv.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/staging/rtl8712/rtl871x_recv.c	2017-06-05 16:13:58.000000000 -0400
@@ -641,11 +641,16 @@ sint r8712_wlanhdr_to_ethhdr(union recv_
 		/* append rx status for mp test packets */
 		ptr = recvframe_pull(precvframe, (rmv_len -
 		      sizeof(struct ethhdr) + 2) - 24);
+		if (!ptr)
+			return _FAIL;
 		memcpy(ptr, get_rxmem(precvframe), 24);
 		ptr += 24;
-	} else
+	} else {
 		ptr = recvframe_pull(precvframe, (rmv_len -
 		      sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
+		if (!ptr)
+			return _FAIL;
+	}
 
 	memcpy(ptr, pattrib->dst, ETH_ALEN);
 	memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/tty/serial/8250_pci.c linux-libre-3.2.89-gnu1/drivers/tty/serial/8250_pci.c
--- linux-libre-3.2.88-gnu1/drivers/tty/serial/8250_pci.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/tty/serial/8250_pci.c	2017-06-05 16:13:58.000000000 -0400
@@ -1768,6 +1768,8 @@ enum pci_board_num_t {
 
 	pbn_b0_4_1152000,
 
+	pbn_b0_4_1250000,
+
 	pbn_b0_2_1843200,
 	pbn_b0_4_1843200,
 
@@ -1964,6 +1966,13 @@ static struct pciserial_board pci_boards
 		.uart_offset	= 8,
 	},
 
+	[pbn_b0_4_1250000] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 1250000,
+		.uart_offset	= 8,
+	},
+
 	[pbn_b0_2_1843200] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 2,
@@ -4162,6 +4171,10 @@ static struct pci_device_id serial_pci_t
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_brcm_trumanage },
 
+	/* MKS Tenta SCOM-080x serial cards */
+	{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
+	{ PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 },
+
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/tty/serial/msm_serial.c linux-libre-3.2.89-gnu1/drivers/tty/serial/msm_serial.c
--- linux-libre-3.2.88-gnu1/drivers/tty/serial/msm_serial.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/tty/serial/msm_serial.c	2017-06-05 16:13:58.000000000 -0400
@@ -930,6 +930,7 @@ static struct of_device_id msm_match_tab
 	{ .compatible = "qcom,msm-uart" },
 	{}
 };
+MODULE_DEVICE_TABLE(of, msm_match_table);
 
 static struct platform_driver msm_platform_driver = {
 	.remove = msm_serial_remove,
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/dwc3/gadget.c linux-libre-3.2.89-gnu1/drivers/usb/dwc3/gadget.c
--- linux-libre-3.2.88-gnu1/drivers/usb/dwc3/gadget.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/dwc3/gadget.c	2017-06-05 16:13:58.000000000 -0400
@@ -925,6 +925,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc
 	memset(&params, 0x00, sizeof(params));
 
 	if (value) {
+		if (dep->flags & DWC3_EP_STALL)
+			return 0;
+
 		if (dep->number == 0 || dep->number == 1) {
 			/*
 			 * Whenever EP0 is stalled, we will restart
@@ -943,6 +946,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc
 		else
 			dep->flags |= DWC3_EP_STALL;
 	} else {
+		if (!(dep->flags & DWC3_EP_STALL))
+			return 0;
+
 		ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
 			DWC3_DEPCMD_CLEARSTALL, &params);
 		if (ret)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/gadget/f_hid.c linux-libre-3.2.89-gnu1/drivers/usb/gadget/f_hid.c
--- linux-libre-3.2.88-gnu1/drivers/usb/gadget/f_hid.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/gadget/f_hid.c	2017-06-05 16:13:58.000000000 -0400
@@ -37,11 +37,11 @@ struct f_hidg {
 	/* recv report */
 	char				*set_report_buff;
 	unsigned short			set_report_length;
-	spinlock_t			spinlock;
+	spinlock_t			read_spinlock;
 	wait_queue_head_t		read_queue;
 
 	/* send report */
-	struct mutex			lock;
+	spinlock_t			write_spinlock;
 	bool				write_pending;
 	wait_queue_head_t		write_queue;
 	struct usb_request		*req;
@@ -140,19 +140,19 @@ static ssize_t f_hidg_read(struct file *
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
 
-	spin_lock_irqsave(&hidg->spinlock, flags);
+	spin_lock_irqsave(&hidg->read_spinlock, flags);
 
 #define READ_COND (hidg->set_report_buff != NULL)
 
 	while (!READ_COND) {
-		spin_unlock_irqrestore(&hidg->spinlock, flags);
+		spin_unlock_irqrestore(&hidg->read_spinlock, flags);
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
 		if (wait_event_interruptible(hidg->read_queue, READ_COND))
 			return -ERESTARTSYS;
 
-		spin_lock_irqsave(&hidg->spinlock, flags);
+		spin_lock_irqsave(&hidg->read_spinlock, flags);
 	}
 
 
@@ -160,7 +160,7 @@ static ssize_t f_hidg_read(struct file *
 	tmp_buff = hidg->set_report_buff;
 	hidg->set_report_buff = NULL;
 
-	spin_unlock_irqrestore(&hidg->spinlock, flags);
+	spin_unlock_irqrestore(&hidg->read_spinlock, flags);
 
 	if (tmp_buff != NULL) {
 		/* copy to user outside spinlock */
@@ -175,13 +175,16 @@ static ssize_t f_hidg_read(struct file *
 static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
+	unsigned long flags;
 
 	if (req->status != 0) {
 		ERROR(hidg->func.config->cdev,
 			"End Point Request ERROR: %d\n", req->status);
 	}
 
+	spin_lock_irqsave(&hidg->write_spinlock, flags);
 	hidg->write_pending = 0;
+	spin_unlock_irqrestore(&hidg->write_spinlock, flags);
 	wake_up(&hidg->write_queue);
 }
 
@@ -189,18 +192,19 @@ static ssize_t f_hidg_write(struct file
 			    size_t count, loff_t *offp)
 {
 	struct f_hidg *hidg  = file->private_data;
+	unsigned long flags;
 	ssize_t status = -ENOMEM;
 
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 
-	mutex_lock(&hidg->lock);
+	spin_lock_irqsave(&hidg->write_spinlock, flags);
 
 #define WRITE_COND (!hidg->write_pending)
 
 	/* write queue */
 	while (!WRITE_COND) {
-		mutex_unlock(&hidg->lock);
+		spin_unlock_irqrestore(&hidg->write_spinlock, flags);
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
@@ -208,17 +212,20 @@ static ssize_t f_hidg_write(struct file
 				hidg->write_queue, WRITE_COND))
 			return -ERESTARTSYS;
 
-		mutex_lock(&hidg->lock);
+		spin_lock_irqsave(&hidg->write_spinlock, flags);
 	}
 
+	hidg->write_pending = 1;
 	count  = min_t(unsigned, count, hidg->report_length);
+
+	spin_unlock_irqrestore(&hidg->write_spinlock, flags);
 	status = copy_from_user(hidg->req->buf, buffer, count);
 
 	if (status != 0) {
 		ERROR(hidg->func.config->cdev,
 			"copy_from_user error\n");
-		mutex_unlock(&hidg->lock);
-		return -EINVAL;
+		status = -EINVAL;
+		goto release_write_pending;
 	}
 
 	hidg->req->status   = 0;
@@ -226,19 +233,23 @@ static ssize_t f_hidg_write(struct file
 	hidg->req->length   = count;
 	hidg->req->complete = f_hidg_req_complete;
 	hidg->req->context  = hidg;
-	hidg->write_pending = 1;
 
 	status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
 	if (status < 0) {
 		ERROR(hidg->func.config->cdev,
 			"usb_ep_queue error on int endpoint %zd\n", status);
-		hidg->write_pending = 0;
-		wake_up(&hidg->write_queue);
+		goto release_write_pending;
 	} else {
 		status = count;
 	}
 
-	mutex_unlock(&hidg->lock);
+	return status;
+release_write_pending:
+	spin_lock_irqsave(&hidg->write_spinlock, flags);
+	hidg->write_pending = 0;
+	spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+
+	wake_up(&hidg->write_queue);
 
 	return status;
 }
@@ -291,19 +302,19 @@ static void hidg_set_report_complete(str
 		return;
 	}
 
-	spin_lock(&hidg->spinlock);
+	spin_lock(&hidg->read_spinlock);
 
 	hidg->set_report_buff = krealloc(hidg->set_report_buff,
 					 req->actual, GFP_ATOMIC);
 
 	if (hidg->set_report_buff == NULL) {
-		spin_unlock(&hidg->spinlock);
+		spin_unlock(&hidg->read_spinlock);
 		return;
 	}
 	hidg->set_report_length = req->actual;
 	memcpy(hidg->set_report_buff, req->buf, req->actual);
 
-	spin_unlock(&hidg->spinlock);
+	spin_unlock(&hidg->read_spinlock);
 
 	wake_up(&hidg->read_queue);
 }
@@ -505,8 +516,8 @@ static int __init hidg_bind(struct usb_c
 			goto fail;
 	}
 
-	mutex_init(&hidg->lock);
-	spin_lock_init(&hidg->spinlock);
+	spin_lock_init(&hidg->write_spinlock);
+	spin_lock_init(&hidg->read_spinlock);
 	init_waitqueue_head(&hidg->write_queue);
 	init_waitqueue_head(&hidg->read_queue);
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/misc/iowarrior.c linux-libre-3.2.89-gnu1/drivers/usb/misc/iowarrior.c
--- linux-libre-3.2.88-gnu1/drivers/usb/misc/iowarrior.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/misc/iowarrior.c	2017-06-05 16:13:58.000000000 -0400
@@ -792,12 +792,6 @@ static int iowarrior_probe(struct usb_in
 	iface_desc = interface->cur_altsetting;
 	dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
 
-	if (iface_desc->desc.bNumEndpoints < 1) {
-		dev_err(&interface->dev, "Invalid number of endpoints\n");
-		retval = -EINVAL;
-		goto error;
-	}
-
 	/* set up the endpoint information */
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
@@ -808,6 +802,13 @@ static int iowarrior_probe(struct usb_in
 			/* this one will match for the IOWarrior56 only */
 			dev->int_out_endpoint = endpoint;
 	}
+
+	if (!dev->int_in_endpoint) {
+		dev_err(&interface->dev, "no interrupt-in endpoint found\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
 	/* we have to check the report_size often, so remember it in the endianess suitable for our machine */
 	dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);
 	if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/ark3116.c linux-libre-3.2.89-gnu1/drivers/usb/serial/ark3116.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/ark3116.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/ark3116.c	2017-06-05 16:13:58.000000000 -0400
@@ -107,10 +107,17 @@ static int ark3116_read_reg(struct usb_s
 				 usb_rcvctrlpipe(serial->dev, 0),
 				 0xfe, 0xc0, 0, reg,
 				 buf, 1, ARK_TIMEOUT);
-	if (result < 0)
+	if (result < 1) {
+		dev_err(&serial->interface->dev,
+				"failed to read register %u: %d\n",
+				reg, result);
+		if (result >= 0)
+			result = -EIO;
+
 		return result;
-	else
-		return buf[0];
+	}
+
+	return buf[0];
 }
 
 static inline int calc_divisor(int bps)
@@ -375,23 +382,29 @@ static int ark3116_open(struct tty_struc
 	if (result) {
 		dbg("%s - usb_serial_generic_open failed: %d",
 		    __func__, result);
-		goto err_out;
+		goto err_free;
 	}
 
 	/* remove any data still left: also clears error state */
 	ark3116_read_reg(serial, UART_RX, buf);
 
 	/* read modem status */
-	priv->msr = ark3116_read_reg(serial, UART_MSR, buf);
+	result = ark3116_read_reg(serial, UART_MSR, buf);
+	if (result < 0)
+		goto err_close;
+	priv->msr = *buf;
+
 	/* read line status */
-	priv->lsr = ark3116_read_reg(serial, UART_LSR, buf);
+	result = ark3116_read_reg(serial, UART_LSR, buf);
+	if (result < 0)
+		goto err_close;
+	priv->lsr = *buf;
 
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 	if (result) {
 		dev_err(&port->dev, "submit irq_in urb failed %d\n",
 			result);
-		ark3116_close(port);
-		goto err_out;
+		goto err_close;
 	}
 
 	/* activate interrupts */
@@ -404,8 +417,15 @@ static int ark3116_open(struct tty_struc
 	if (tty)
 		ark3116_set_termios(tty, port, NULL);
 
-err_out:
 	kfree(buf);
+
+	return 0;
+
+err_close:
+	usb_serial_generic_close(port);
+err_free:
+	kfree(buf);
+
 	return result;
 }
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/ch341.c linux-libre-3.2.89-gnu1/drivers/usb/serial/ch341.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/ch341.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/ch341.c	2017-06-05 16:13:58.000000000 -0400
@@ -255,21 +255,11 @@ static int ch341_configure(struct usb_de
 	if (r < 0)
 		goto out;
 
-	/* expect 0xff 0xee */
-	r = ch341_get_status(dev, priv);
-	if (r < 0)
-		goto out;
-
 	r = ch341_set_baudrate_lcr(dev, priv, 0);
 	if (r < 0)
 		goto out;
 
 	r = ch341_set_handshake(dev, priv->line_control);
-	if (r < 0)
-		goto out;
-
-	/* expect 0x9f 0xee */
-	r = ch341_get_status(dev, priv);
 
 out:	kfree(buffer);
 	return r;
@@ -345,10 +335,6 @@ static int ch341_open(struct tty_struct
 
 	dbg("ch341_open()");
 
-	r = ch341_configure(serial->dev, priv);
-	if (r)
-		return r;
-
 	if (tty)
 		ch341_set_termios(tty, port, NULL);
 
@@ -361,6 +347,12 @@ static int ch341_open(struct tty_struct
 		return r;
 	}
 
+	r = ch341_get_status(port->serial->dev, priv);
+	if (r < 0) {
+		dev_err(&port->dev, "failed to read modem status: %d\n", r);
+		goto err_kill_interrupt_urb;
+	}
+
 	r = usb_serial_generic_open(tty, port);
 	if (r)
 		goto err_kill_interrupt_urb;
@@ -656,6 +648,12 @@ static int ch341_reset_resume(struct usb
 				ret);
 			return ret;
 		}
+
+		ret = ch341_get_status(port->serial->dev, priv);
+		if (ret < 0) {
+			dev_err(&port->dev, "failed to read modem status: %d\n",
+				ret);
+		}
 	}
 
 	return usb_serial_generic_resume(serial);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/cp210x.c linux-libre-3.2.89-gnu1/drivers/usb/serial/cp210x.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/cp210x.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/cp210x.c	2017-06-05 16:13:58.000000000 -0400
@@ -177,6 +177,8 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
 	{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
 	{ USB_DEVICE(0x1901, 0x0194) },	/* GE Healthcare Remote Alarm Box */
+	{ USB_DEVICE(0x1901, 0x0195) },	/* GE B850/B650/B450 CP2104 DP UART interface */
+	{ USB_DEVICE(0x1901, 0x0196) },	/* GE B850 CP2105 DP UART interface */
 	{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
 	{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
 	{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/digi_acceleport.c linux-libre-3.2.89-gnu1/drivers/usb/serial/digi_acceleport.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/digi_acceleport.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/digi_acceleport.c	2017-06-05 16:13:58.000000000 -0400
@@ -1660,25 +1660,30 @@ static int digi_read_inb_callback(struct
 	struct usb_serial_port *port = urb->context;
 	struct tty_struct *tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
-	int len = ((unsigned char *)urb->transfer_buffer)[1];
-	int port_status = ((unsigned char *)urb->transfer_buffer)[2];
-	unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
+	unsigned char *buf = urb->transfer_buffer;
+	int opcode;
+	int len;
+	int port_status;
+	unsigned char *data;
 	int flag, throttled;
-	int status = urb->status;
-
-	/* do not process callbacks on closed ports */
-	/* but do continue the read chain */
-	if (urb->status == -ENOENT)
-		return 0;
 
 	/* short/multiple packet check */
+	if (urb->actual_length < 2) {
+		dev_warn(&port->dev, "short packet received\n");
+		return -1;
+	}
+
+	opcode = buf[0];
+	len = buf[1];
+
 	if (urb->actual_length != len + 2) {
-		dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, "
-			"status=%d, port=%d, opcode=%d, len=%d, "
-			"actual_length=%d, status=%d\n", __func__, status,
-			priv->dp_port_num, opcode, len, urb->actual_length,
-			port_status);
+		dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n",
+			priv->dp_port_num, opcode, len, urb->actual_length);
+		return -1;
+	}
+
+	if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) {
+		dev_err(&port->dev, "malformed data packet received\n");
 		return -1;
 	}
 
@@ -1693,6 +1698,9 @@ static int digi_read_inb_callback(struct
 
 	/* receive data */
 	if (tty && opcode == DIGI_CMD_RECEIVE_DATA) {
+		port_status = buf[2];
+		data = &buf[3];
+
 		/* get flag from port_status */
 		flag = 0;
 
@@ -1746,6 +1754,7 @@ static int digi_read_oob_callback(struct
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
+	unsigned char *buf = urb->transfer_buffer;
 	int opcode, line, status, val;
 	int i;
 	unsigned int rts;
@@ -1753,12 +1762,15 @@ static int digi_read_oob_callback(struct
 	dbg("digi_read_oob_callback: port=%d, len=%d",
 			priv->dp_port_num, urb->actual_length);
 
+	if (urb->actual_length < 4)
+		return -1;
+
 	/* handle each oob command */
-	for (i = 0; i < urb->actual_length - 3;) {
-		opcode = ((unsigned char *)urb->transfer_buffer)[i++];
-		line = ((unsigned char *)urb->transfer_buffer)[i++];
-		status = ((unsigned char *)urb->transfer_buffer)[i++];
-		val = ((unsigned char *)urb->transfer_buffer)[i++];
+	for (i = 0; i < urb->actual_length - 3; i += 4) {
+		opcode = buf[i];
+		line = buf[i + 1];
+		status = buf[i + 2];
+		val = buf[i + 3];
 
 		dbg("digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d",
 			opcode, line, status, val);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/ftdi_sio.c linux-libre-3.2.89-gnu1/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/ftdi_sio.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/ftdi_sio.c	2017-06-05 16:13:58.000000000 -0400
@@ -1475,10 +1475,13 @@ static int read_latency_timer(struct usb
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
 			     0, priv->interface,
 			     buf, 1, WDR_TIMEOUT);
-	if (rv < 0)
+	if (rv < 1) {
 		dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
-	else
+		if (rv >= 0)
+			rv = -EIO;
+	} else {
 		priv->latency = buf[0];
+	}
 
 	kfree(buf);
 
@@ -1861,8 +1864,6 @@ static int ftdi_sio_port_probe(struct us
 	mutex_init(&priv->cfg_lock);
 	memset(&priv->icount, 0x00, sizeof(priv->icount));
 
-	priv->flags = ASYNC_LOW_LATENCY;
-
 	if (quirk && quirk->port_probe)
 		quirk->port_probe(priv);
 
@@ -2186,6 +2187,20 @@ static int ftdi_process_packet(struct tt
 		priv->prev_status = status;
 	}
 
+	/* save if the transmitter is empty or not */
+	if (packet[1] & FTDI_RS_TEMT)
+		priv->transmit_empty = 1;
+	else
+		priv->transmit_empty = 0;
+
+	len -= 2;
+	if (!len)
+		return 0;	/* status only */
+
+	/*
+	 * Break and error status must only be processed for packets with
+	 * data payload to avoid over-reporting.
+	 */
 	flag = TTY_NORMAL;
 	if (packet[1] & FTDI_RS_ERR_MASK) {
 		/* Break takes precedence over parity, which takes precedence
@@ -2208,15 +2223,6 @@ static int ftdi_process_packet(struct tt
 		}
 	}
 
-	/* save if the transmitter is empty or not */
-	if (packet[1] & FTDI_RS_TEMT)
-		priv->transmit_empty = 1;
-	else
-		priv->transmit_empty = 0;
-
-	len -= 2;
-	if (!len)
-		return 0;	/* status only */
 	priv->icount.rx += len;
 	ch = packet + 2;
 
@@ -2542,8 +2548,13 @@ static int ftdi_tiocmget(struct tty_stru
 			FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
 			0, priv->interface,
 			buf, len, WDR_TIMEOUT);
-	if (ret < 0)
+
+	/* NOTE: We allow short responses and handle that below. */
+	if (ret < 1) {
+		if (ret >= 0)
+			ret = -EIO;
 		goto out;
+	}
 
 	ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
 		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/io_edgeport.c linux-libre-3.2.89-gnu1/drivers/usb/serial/io_edgeport.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/io_edgeport.c	2017-04-05 09:34:13.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/io_edgeport.c	2017-06-06 13:25:47.000000000 -0400
@@ -496,21 +496,25 @@ static int get_epic_descriptor(struct ed
 	int result;
 	struct usb_serial *serial = ep->serial;
 	struct edgeport_product_info *product_info = &ep->product_info;
-	struct edge_compatibility_descriptor *epic = &ep->epic_descriptor;
+	struct edge_compatibility_descriptor *epic;
 	struct edge_compatibility_bits *bits;
 
 	ep->is_epic = 0;
+
+	epic = kmalloc(sizeof(*epic), GFP_KERNEL);
+	if (!epic)
+		return -ENOMEM;
+
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				 USB_REQUEST_ION_GET_EPIC_DESC,
 				 0xC0, 0x00, 0x00,
-				 &ep->epic_descriptor,
-				 sizeof(struct edge_compatibility_descriptor),
+				 epic, sizeof(*epic),
 				 300);
-
 	dbg("%s result = %d", __func__, result);
 
-	if (result > 0) {
+	if (result == sizeof(*epic)) {
 		ep->is_epic = 1;
+		memcpy(&ep->epic_descriptor, epic, sizeof(*epic));
 		memset(product_info, 0, sizeof(struct edgeport_product_info));
 
 		product_info->NumPorts = epic->NumPorts;
@@ -539,8 +543,16 @@ static int get_epic_descriptor(struct ed
 		dbg("  IOSPWriteLCR     : %s", bits->IOSPWriteLCR	? "TRUE": "FALSE");
 		dbg("  IOSPSetBaudRate  : %s", bits->IOSPSetBaudRate	? "TRUE": "FALSE");
 		dbg("  TrueEdgeport     : %s", bits->TrueEdgeport	? "TRUE": "FALSE");
+
+		result = 0;
+	} else if (result >= 0) {
+		dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n",
+			 result);
+		result = -EIO;
 	}
 
+	kfree(epic);
+
 	return result;
 }
 
@@ -2251,8 +2263,7 @@ static int rom_write(struct usb_serial *
  * rom_read
  *	reads a number of bytes from the Edgeport device starting at the given
  *	address.
- *	If successful returns the number of bytes read, otherwise it returns
- *	a negative error number of the problem.
+ *	Returns zero on success or a negative error number.
  ****************************************************************************/
 static int rom_read(struct usb_serial *serial, __u16 extAddr,
 					__u16 addr, __u16 length, __u8 *data)
@@ -2284,12 +2295,17 @@ static int rom_read(struct usb_serial *s
 					USB_REQUEST_ION_READ_ROM,
 					0xC0, addr, extAddr, transfer_buffer,
 					current_length, 300);
-		if (result < 0)
+		if (result < current_length) {
+			if (result >= 0)
+				result = -EIO;
 			break;
+		}
 		memcpy(data, transfer_buffer, current_length);
 		length -= current_length;
 		addr += current_length;
 		data += current_length;
+
+		result = 0;
 	}
 
 	kfree(transfer_buffer);
@@ -2760,10 +2776,11 @@ static void get_manufacturing_desc(struc
 				EDGE_MANUF_DESC_LEN,
 				(__u8 *)(&edge_serial->manuf_descriptor));
 
-	if (response < 1)
+	if (response < 0) {
 		dev_err(&edge_serial->serial->dev->dev,
-			"error in getting manufacturer descriptor\n");
-	else {
+			"error in getting manufacturer descriptor: %d\n",
+			response);
+	} else {
 		char string[30];
 		dbg("**Manufacturer Descriptor");
 		dbg("  RomSize:        %dK",
@@ -2819,10 +2836,11 @@ static void get_boot_desc(struct edgepor
 				EDGE_BOOT_DESC_LEN,
 				(__u8 *)(&edge_serial->boot_descriptor));
 
-	if (response < 1)
+	if (response < 0) {
 		dev_err(&edge_serial->serial->dev->dev,
-				"error in getting boot descriptor\n");
-	else {
+			"error in getting boot descriptor: %d\n",
+			response);
+	} else {
 		dbg("**Boot Descriptor:");
 		dbg("  BootCodeLength: %d",
 		    le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
@@ -2965,7 +2983,7 @@ static int edge_startup(struct usb_seria
 	dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
 
 	/* Read the epic descriptor */
-	if (get_epic_descriptor(edge_serial) <= 0) {
+	if (get_epic_descriptor(edge_serial) < 0) {
 		/* memcpy descriptor to Supports structures */
 		memcpy(&edge_serial->epic_descriptor.Supports, descriptor,
 		       sizeof(struct edge_compatibility_bits));
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/io_ti.c linux-libre-3.2.89-gnu1/drivers/usb/serial/io_ti.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/io_ti.c	2017-04-05 09:34:18.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/io_ti.c	2017-06-06 13:25:52.000000000 -0400
@@ -1766,7 +1766,7 @@ static void edge_bulk_in_callback(struct
 
 	port_number = edge_port->port->number - edge_port->port->serial->minor;
 
-	if (edge_port->lsr_event) {
+	if (urb->actual_length > 0 && edge_port->lsr_event) {
 		edge_port->lsr_event = 0;
 		dbg("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
 		     __func__, port_number, edge_port->lsr_mask, *data);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/keyspan_pda.c linux-libre-3.2.89-gnu1/drivers/usb/serial/keyspan_pda.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/keyspan_pda.c	2017-04-05 09:34:02.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/keyspan_pda.c	2017-06-06 13:25:38.000000000 -0400
@@ -212,6 +212,7 @@ static void keyspan_pda_rx_interrupt(str
 	struct usb_serial_port *port = urb->context;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned int len = urb->actual_length;
 	int retval;
 	int status = urb->status;
 	struct keyspan_pda_private *priv;
@@ -234,20 +235,28 @@ static void keyspan_pda_rx_interrupt(str
 		goto exit;
 	}
 
+	if (len < 1) {
+		dev_warn(&port->dev, "short message received\n");
+		goto exit;
+	}
+
 	/* see if the message is data or a status interrupt */
 	switch (data[0]) {
 	case 0:
 		tty = tty_port_tty_get(&port->port);
 		 /* rest of message is rx data */
-		if (tty && urb->actual_length) {
-			tty_insert_flip_string(tty, data + 1,
-						urb->actual_length - 1);
-			tty_flip_buffer_push(tty);
-		}
+		if (!tty || len < 2)
+			break;
+		tty_insert_flip_string(tty, data + 1, len - 1);
+		tty_flip_buffer_push(tty);
 		tty_kref_put(tty);
 		break;
 	case 1:
 		/* status interrupt */
+		if (len < 3) {
+			dev_warn(&port->dev, "short interrupt message received\n");
+			break;
+		}
 		dbg(" rx int, d1=%d, d2=%d", data[1], data[2]);
 		switch (data[1]) {
 		case 1: /* modemline change */
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/mct_u232.c linux-libre-3.2.89-gnu1/drivers/usb/serial/mct_u232.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/mct_u232.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/mct_u232.c	2017-06-05 16:13:58.000000000 -0400
@@ -385,9 +385,13 @@ static int mct_u232_get_modem_stat(struc
 			MCT_U232_GET_REQUEST_TYPE,
 			0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
 			WDR_TIMEOUT);
-	if (rc < 0) {
+	if (rc < MCT_U232_GET_MODEM_STAT_SIZE) {
 		dev_err(&serial->dev->dev,
 			"Get MODEM STATus failed (error = %d)\n", rc);
+
+		if (rc >= 0)
+			rc = -EIO;
+
 		*msr = 0;
 	} else {
 		*msr = buf[0];
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/mos7840.c linux-libre-3.2.89-gnu1/drivers/usb/serial/mos7840.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/mos7840.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/mos7840.c	2017-06-05 16:13:58.000000000 -0400
@@ -1058,6 +1058,7 @@ static int mos7840_open(struct tty_struc
 	 * (can't set it up in mos7840_startup as the structures *
 	 * were not set up at that time.)                        */
 	if (port0->open_ports == 1) {
+		/* FIXME: Buffer never NULL, so URB is not submitted. */
 		if (serial->port[0]->interrupt_in_buffer == NULL) {
 			/* set up interrupt urb */
 			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
@@ -2385,7 +2386,8 @@ static int mos7840_startup(struct usb_se
 	}
 
 	if (serial->num_bulk_in < serial->num_ports ||
-			serial->num_bulk_out < serial->num_ports) {
+			serial->num_bulk_out < serial->num_ports ||
+			serial->num_interrupt_in < 1) {
 		dev_err(&serial->interface->dev, "missing endpoints\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/omninet.c linux-libre-3.2.89-gnu1/drivers/usb/serial/omninet.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/omninet.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/omninet.c	2017-06-05 16:13:58.000000000 -0400
@@ -171,14 +171,10 @@ static int omninet_attach(struct usb_ser
 static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct usb_serial	*serial = port->serial;
-	struct usb_serial_port	*wport;
 	int			result = 0;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	wport = serial->port[1];
-	tty_port_tty_set(&wport->port, tty);
-
 	/* Start reading from the device */
 	usb_fill_bulk_urb(port->read_urb, serial->dev,
 			usb_rcvbulkpipe(serial->dev,
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/ssu100.c linux-libre-3.2.89-gnu1/drivers/usb/serial/ssu100.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/ssu100.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/ssu100.c	2017-06-05 16:13:58.000000000 -0400
@@ -107,9 +107,17 @@ static inline int ssu100_setdevice(struc
 
 static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
-			       data, 3, 300);
+	int ret;
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_DEVICE, 0xc0, 0, 0,
+			      data, 3, 300);
+	if (ret < 3) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 static inline int ssu100_getregister(struct usb_device *dev,
@@ -117,10 +125,17 @@ static inline int ssu100_getregister(str
 				     unsigned short reg,
 				     u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_REGISTER, 0xc0, reg,
-			       uart, data, sizeof(*data), 300);
+	int ret;
 
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_REGISTER, 0xc0, reg,
+			      uart, data, sizeof(*data), 300);
+	if (ret < sizeof(*data)) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 
@@ -322,8 +337,10 @@ static int ssu100_open(struct tty_struct
 				 QT_OPEN_CLOSE_CHANNEL,
 				 QT_TRANSFER_IN, 0x01,
 				 0, data, 2, 300);
-	if (result < 0) {
+	if (result < 2) {
 		dbg("%s - open failed %i", __func__, result);
+		if (result >= 0)
+			result = -EIO;
 		kfree(data);
 		return result;
 	}
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/drivers/usb/serial/ti_usb_3410_5052.c linux-libre-3.2.89-gnu1/drivers/usb/serial/ti_usb_3410_5052.c
--- linux-libre-3.2.88-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2017-04-05 09:34:22.000000000 -0400
+++ linux-libre-3.2.89-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2017-06-06 13:25:55.000000000 -0400
@@ -1608,13 +1608,10 @@ static int ti_command_out_sync(struct ti
 		(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
 		value, moduleid, data, size, 1000);
 
-	if (status == size)
-		status = 0;
-
-	if (status > 0)
-		status = -ECOMM;
+	if (status < 0)
+		return status;
 
-	return status;
+	return 0;
 }
 
 
@@ -1630,8 +1627,7 @@ static int ti_command_in_sync(struct ti_
 
 	if (status == size)
 		status = 0;
-
-	if (status > 0)
+	else if (status >= 0)
 		status = -ECOMM;
 
 	return status;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/ext4/inode.c linux-libre-3.2.89-gnu1/fs/ext4/inode.c
--- linux-libre-3.2.88-gnu1/fs/ext4/inode.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/ext4/inode.c	2017-06-05 16:13:58.000000000 -0400
@@ -1068,6 +1068,40 @@ static int ext4_writeback_write_end(stru
 	return ret ? ret : copied;
 }
 
+/*
+ * This is a private version of page_zero_new_buffers() which doesn't
+ * set the buffer to be dirty, since in data=journalled mode we need
+ * to call ext4_handle_dirty_metadata() instead.
+ */
+static void ext4_journalled_zero_new_buffers(handle_t *handle,
+					    struct page *page,
+					    unsigned from, unsigned to)
+{
+	unsigned int block_start = 0, block_end;
+	struct buffer_head *head, *bh;
+
+	bh = head = page_buffers(page);
+	do {
+		block_end = block_start + bh->b_size;
+		if (buffer_new(bh)) {
+			if (block_end > from && block_start < to) {
+				if (!PageUptodate(page)) {
+					unsigned start, size;
+
+					start = max(from, block_start);
+					size = min(to, block_end) - start;
+
+					zero_user(page, start, size);
+					write_end_fn(handle, bh);
+				}
+				clear_buffer_new(bh);
+			}
+		}
+		block_start = block_end;
+		bh = bh->b_this_page;
+	} while (bh != head);
+}
+
 static int ext4_journalled_write_end(struct file *file,
 				     struct address_space *mapping,
 				     loff_t pos, unsigned len, unsigned copied,
@@ -1086,16 +1120,19 @@ static int ext4_journalled_write_end(str
 
 	BUG_ON(!ext4_handle_valid(handle));
 
-	if (copied < len) {
-		if (!PageUptodate(page))
-			copied = 0;
-		page_zero_new_buffers(page, from+copied, to);
+	if (unlikely(copied < len) && !PageUptodate(page)) {
+		copied = 0;
+		ext4_journalled_zero_new_buffers(handle, page, from, to);
+	} else {
+		if (unlikely(copied < len))
+			ext4_journalled_zero_new_buffers(handle, page,
+							 from + copied, to);
+		ret = walk_page_buffers(handle, page_buffers(page), from,
+					from + copied, &partial,
+					write_end_fn);
+		if (!partial)
+			SetPageUptodate(page);
 	}
-
-	ret = walk_page_buffers(handle, page_buffers(page), from,
-				to, &partial, write_end_fn);
-	if (!partial)
-		SetPageUptodate(page);
 	new_i_size = pos + copied;
 	if (new_i_size > inode->i_size)
 		i_size_write(inode, pos+copied);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/ext4/mballoc.c linux-libre-3.2.89-gnu1/fs/ext4/mballoc.c
--- linux-libre-3.2.88-gnu1/fs/ext4/mballoc.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/ext4/mballoc.c	2017-06-05 16:13:58.000000000 -0400
@@ -3003,6 +3003,13 @@ ext4_mb_normalize_request(struct ext4_al
 	if (ar->pright && start + size - 1 >= ar->lright)
 		size -= start + size - ar->lright;
 
+	/*
+	 * Trim allocation request for filesystems with artificially small
+	 * groups.
+	 */
+	if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb))
+		size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb);
+
 	end = start + size;
 
 	/* check we don't cross already preallocated blocks */
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/ext4/super.c linux-libre-3.2.89-gnu1/fs/ext4/super.c
--- linux-libre-3.2.88-gnu1/fs/ext4/super.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/ext4/super.c	2017-06-05 16:13:58.000000000 -0400
@@ -808,6 +808,7 @@ static void ext4_put_super(struct super_
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_super_block *es = sbi->s_es;
+	int aborted = 0;
 	int i, err;
 
 	ext4_unregister_li_request(sb);
@@ -821,9 +822,10 @@ static void ext4_put_super(struct super_
 		ext4_commit_super(sb, 1);
 
 	if (sbi->s_journal) {
+		aborted = is_journal_aborted(sbi->s_journal);
 		err = jbd2_journal_destroy(sbi->s_journal);
 		sbi->s_journal = NULL;
-		if (err < 0)
+		if ((err < 0) && !aborted)
 			ext4_abort(sb, "Couldn't clean up the journal");
 	}
 
@@ -833,7 +835,7 @@ static void ext4_put_super(struct super_
 	ext4_ext_release(sb);
 	ext4_xattr_put_super(sb);
 
-	if (!(sb->s_flags & MS_RDONLY)) {
+	if (!(sb->s_flags & MS_RDONLY) && !aborted) {
 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		ext4_commit_super(sb, 1);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/fuse/file.c linux-libre-3.2.89-gnu1/fs/fuse/file.c
--- linux-libre-3.2.88-gnu1/fs/fuse/file.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/fuse/file.c	2017-06-05 16:13:58.000000000 -0400
@@ -126,6 +126,7 @@ static void fuse_file_put(struct fuse_fi
 		struct fuse_req *req = ff->reserved_req;
 
 		if (sync) {
+			req->force = 1;
 			fuse_request_send(ff->fc, req);
 			path_put(&req->misc.release.path);
 			fuse_put_request(ff->fc, req);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/jbd2/transaction.c linux-libre-3.2.89-gnu1/fs/jbd2/transaction.c
--- linux-libre-3.2.88-gnu1/fs/jbd2/transaction.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/jbd2/transaction.c	2017-06-05 16:13:58.000000000 -0400
@@ -1601,7 +1601,9 @@ void __jbd2_journal_temp_unlink_buffer(s
 
 	__blist_del_buffer(list, jh);
 	jh->b_jlist = BJ_None;
-	if (test_clear_buffer_jbddirty(bh))
+	if (transaction && is_journal_aborted(transaction->t_journal))
+		clear_buffer_jbddirty(bh);
+	else if (test_clear_buffer_jbddirty(bh))
 		mark_buffer_dirty(bh);	/* Expose it to the VM */
 }
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/nfs/nfs4proc.c linux-libre-3.2.89-gnu1/fs/nfs/nfs4proc.c
--- linux-libre-3.2.88-gnu1/fs/nfs/nfs4proc.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/nfs/nfs4proc.c	2017-06-05 16:13:58.000000000 -0400
@@ -3455,11 +3455,11 @@ static inline int nfs4_server_supports_a
 		&& (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
 }
 
-/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
- * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
+/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that
+ * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on
  * the stack.
  */
-#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
+#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
 
 static int buf_to_pages_noslab(const void *buf, size_t buflen,
 		struct page **pages, unsigned int *pgbase)
@@ -3470,7 +3470,7 @@ static int buf_to_pages_noslab(const voi
 	spages = pages;
 
 	do {
-		len = min_t(size_t, PAGE_CACHE_SIZE, buflen);
+		len = min_t(size_t, PAGE_SIZE, buflen);
 		newpage = alloc_page(GFP_KERNEL);
 
 		if (newpage == NULL)
@@ -3569,7 +3569,7 @@ out:
  */
 static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
 {
-	struct page *pages[NFS4ACL_MAXPAGES] = {NULL, };
+	struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, };
 	struct nfs_getaclargs args = {
 		.fh = NFS_FH(inode),
 		.acl_pages = pages,
@@ -3583,17 +3583,12 @@ static ssize_t __nfs4_get_acl_uncached(s
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	int ret = -ENOMEM, npages, i;
+	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
+	int ret = -ENOMEM, i;
 	size_t acl_len = 0;
 
-	npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	/* As long as we're doing a round trip to the server anyway,
-	 * let's be prepared for a page of acl data. */
-	if (npages == 0)
-		npages = 1;
-
-	/* Add an extra page to handle the bitmap returned */
-	npages++;
+	if (npages > ARRAY_SIZE(pages))
+		return -ERANGE;
 
 	for (i = 0; i < npages; i++) {
 		pages[i] = alloc_page(GFP_KERNEL);
@@ -3692,10 +3687,13 @@ static int __nfs4_proc_set_acl(struct in
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 	};
+	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
 	int ret, i;
 
 	if (!nfs4_server_supports_acls(server))
 		return -EOPNOTSUPP;
+	if (npages > ARRAY_SIZE(pages))
+		return -ERANGE;
 	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
 	if (i < 0)
 		return i;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/nfs/nfs4xdr.c linux-libre-3.2.89-gnu1/fs/nfs/nfs4xdr.c
--- linux-libre-3.2.88-gnu1/fs/nfs/nfs4xdr.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/nfs/nfs4xdr.c	2017-06-05 16:13:58.000000000 -0400
@@ -149,8 +149,10 @@ static int nfs4_stat_to_errno(int);
 				open_owner_id_maxsz + \
 				encode_opentype_maxsz + \
 				encode_claim_null_maxsz)
+#define decode_space_limit_maxsz	(3)
 #define decode_ace_maxsz	(3 + nfs4_owner_maxsz)
 #define decode_delegation_maxsz	(1 + decode_stateid_maxsz + 1 + \
+				decode_space_limit_maxsz + \
 				decode_ace_maxsz)
 #define decode_change_info_maxsz	(5)
 #define decode_open_maxsz	(op_decode_hdr_maxsz + \
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/nfsd/nfs3xdr.c linux-libre-3.2.89-gnu1/fs/nfsd/nfs3xdr.c
--- linux-libre-3.2.88-gnu1/fs/nfsd/nfs3xdr.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/nfsd/nfs3xdr.c	2017-06-05 16:13:58.000000000 -0400
@@ -354,6 +354,7 @@ nfs3svc_decode_writeargs(struct svc_rqst
 {
 	unsigned int len, v, hdr, dlen;
 	u32 max_blocksize = svc_max_payload(rqstp);
+	struct kvec *head = rqstp->rq_arg.head;
 
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
@@ -362,6 +363,8 @@ nfs3svc_decode_writeargs(struct svc_rqst
 	args->count = ntohl(*p++);
 	args->stable = ntohl(*p++);
 	len = args->len = ntohl(*p++);
+	if ((void *)p > head->iov_base + head->iov_len)
+		return 0;
 	/*
 	 * The count must equal the amount of data passed.
 	 */
@@ -372,9 +375,8 @@ nfs3svc_decode_writeargs(struct svc_rqst
 	 * Check to make sure that we got the right number of
 	 * bytes.
 	 */
-	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
-		- hdr;
+	hdr = (void*)p - head->iov_base;
+	dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
 	/*
 	 * Round the length of the data which was specified up to
 	 * the next multiple of XDR units and then compare that
@@ -391,7 +393,7 @@ nfs3svc_decode_writeargs(struct svc_rqst
 		len = args->len = max_blocksize;
 	}
 	rqstp->rq_vec[0].iov_base = (void*)p;
-	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+	rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
 	v = 0;
 	while (len > rqstp->rq_vec[v].iov_len) {
 		len -= rqstp->rq_vec[v].iov_len;
@@ -467,6 +469,8 @@ nfs3svc_decode_symlinkargs(struct svc_rq
 	/* first copy and check from the first page */
 	old = (char*)p;
 	vec = &rqstp->rq_arg.head[0];
+	if ((void *)old > vec->iov_base + vec->iov_len)
+		return 0;
 	avail = vec->iov_len - (old - (char*)vec->iov_base);
 	while (len && avail && *old) {
 		*new++ = *old++;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/nfsd/nfssvc.c linux-libre-3.2.89-gnu1/fs/nfsd/nfssvc.c
--- linux-libre-3.2.88-gnu1/fs/nfsd/nfssvc.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/nfsd/nfssvc.c	2017-06-05 16:13:58.000000000 -0400
@@ -561,6 +561,37 @@ static __be32 map_new_errors(u32 vers, _
 	return nfserr;
 }
 
+/*
+ * A write procedure can have a large argument, and a read procedure can
+ * have a large reply, but no NFSv2 or NFSv3 procedure has argument and
+ * reply that can both be larger than a page.  The xdr code has taken
+ * advantage of this assumption to be a sloppy about bounds checking in
+ * some cases.  Pending a rewrite of the NFSv2/v3 xdr code to fix that
+ * problem, we enforce these assumptions here:
+ */
+static bool nfs_request_too_big(struct svc_rqst *rqstp,
+				struct svc_procedure *proc)
+{
+	/*
+	 * The ACL code has more careful bounds-checking and is not
+	 * susceptible to this problem:
+	 */
+	if (rqstp->rq_prog != NFS_PROGRAM)
+		return false;
+	/*
+	 * Ditto NFSv4 (which can in theory have argument and reply both
+	 * more than a page):
+	 */
+	if (rqstp->rq_vers >= 4)
+		return false;
+	/* The reply will be small, we're OK: */
+	if (proc->pc_xdrressize > 0 &&
+	    proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE))
+		return false;
+
+	return rqstp->rq_arg.len > PAGE_SIZE;
+}
+
 int
 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
@@ -573,6 +604,11 @@ nfsd_dispatch(struct svc_rqst *rqstp, __
 				rqstp->rq_vers, rqstp->rq_proc);
 	proc = rqstp->rq_procinfo;
 
+	if (nfs_request_too_big(rqstp, proc)) {
+		dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
+		*statp = rpc_garbage_args;
+		return 1;
+	}
 	/*
 	 * Give the xdr decoder a chance to change this if it wants
 	 * (necessary in the NFSv4.0 compound case)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/nfsd/nfsxdr.c linux-libre-3.2.89-gnu1/fs/nfsd/nfsxdr.c
--- linux-libre-3.2.88-gnu1/fs/nfsd/nfsxdr.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/nfsd/nfsxdr.c	2017-06-05 16:13:58.000000000 -0400
@@ -277,6 +277,7 @@ nfssvc_decode_writeargs(struct svc_rqst
 					struct nfsd_writeargs *args)
 {
 	unsigned int len, hdr, dlen;
+	struct kvec *head = rqstp->rq_arg.head;
 	int v;
 
 	if (!(p = decode_fh(p, &args->fh)))
@@ -296,9 +297,10 @@ nfssvc_decode_writeargs(struct svc_rqst
 	 * Check to make sure that we got the right number of
 	 * bytes.
 	 */
-	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
-		- hdr;
+	hdr = (void*)p - head->iov_base;
+	if (hdr > head->iov_len)
+		return 0;
+	dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
 
 	/*
 	 * Round the length of the data which was specified up to
@@ -312,7 +314,7 @@ nfssvc_decode_writeargs(struct svc_rqst
 		return 0;
 
 	rqstp->rq_vec[0].iov_base = (void*)p;
-	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+	rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
 	v = 0;
 	while (len > rqstp->rq_vec[v].iov_len) {
 		len -= rqstp->rq_vec[v].iov_len;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/fs/nfsd/vfs.c linux-libre-3.2.89-gnu1/fs/nfsd/vfs.c
--- linux-libre-3.2.88-gnu1/fs/nfsd/vfs.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/fs/nfsd/vfs.c	2017-06-05 16:13:58.000000000 -0400
@@ -409,7 +409,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
 	__be32		err;
 	int		host_err;
 	bool		get_write_count;
-	int		size_change = 0;
+	bool		size_change = (iap->ia_valid & ATTR_SIZE);
 
 	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
 		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
@@ -422,11 +422,11 @@ nfsd_setattr(struct svc_rqst *rqstp, str
 	/* Get inode */
 	err = fh_verify(rqstp, fhp, ftype, accmode);
 	if (err)
-		goto out;
+		return err;
 	if (get_write_count) {
 		host_err = fh_want_write(fhp);
 		if (host_err)
-			return nfserrno(host_err);
+			goto out;
 	}
 
 	dentry = fhp->fh_dentry;
@@ -437,26 +437,24 @@ nfsd_setattr(struct svc_rqst *rqstp, str
 		iap->ia_valid &= ~ATTR_MODE;
 
 	if (!iap->ia_valid)
-		goto out;
+		return 0;
 
 	nfsd_sanitize_attrs(dentry, iap);
 
+	if (check_guard && guardtime != inode->i_ctime.tv_sec)
+		return nfserr_notsync;
+
 	/*
 	 * The size case is special, it changes the file in addition to the
-	 * attributes.
+	 * attributes, and file systems don't expect it to be mixed with
+	 * "random" attribute changes.  We thus split out the size change
+	 * into a separate call to ->setattr, and do the rest as a separate
+	 * setattr call.
 	 */
-	if (iap->ia_valid & ATTR_SIZE) {
+	if (size_change) {
 		err = nfsd_get_write_access(rqstp, fhp, iap);
 		if (err)
-			goto out;
-		size_change = 1;
-	}
-
-	iap->ia_valid |= ATTR_CTIME;
-
-	if (check_guard && guardtime != inode->i_ctime.tv_sec) {
-		err = nfserr_notsync;
-		goto out_put_write_access;
+			return err;
 	}
 
 	host_err = nfsd_break_lease(inode);
@@ -464,18 +462,45 @@ nfsd_setattr(struct svc_rqst *rqstp, str
 		goto out_put_write_access_nfserror;
 
 	fh_lock(fhp);
+	if (size_change) {
+		/*
+		 * RFC5661, Section 18.30.4:
+		 *   Changing the size of a file with SETATTR indirectly
+		 *   changes the time_modify and change attributes.
+		 *
+		 * (and similar for the older RFCs)
+		 */
+		struct iattr size_attr = {
+			.ia_valid	= ATTR_SIZE | ATTR_CTIME | ATTR_MTIME,
+			.ia_size	= iap->ia_size,
+		};
+
+		host_err = notify_change(dentry, &size_attr);
+		if (host_err)
+			goto out_unlock;
+		iap->ia_valid &= ~ATTR_SIZE;
+
+		/*
+		 * Avoid the additional setattr call below if the only other
+		 * attribute that the client sends is the mtime, as we update
+		 * it as part of the size change above.
+		 */
+		if ((iap->ia_valid & ~ATTR_MTIME) == 0)
+			goto out_unlock;
+	}
+
+	iap->ia_valid |= ATTR_CTIME;
 	host_err = notify_change(dentry, iap);
-	fh_unlock(fhp);
 
+out_unlock:
+	fh_unlock(fhp);
 out_put_write_access_nfserror:
-	err = nfserrno(host_err);
-out_put_write_access:
 	if (size_change)
 		put_write_access(inode);
-	if (!err)
-		commit_metadata(fhp);
 out:
-	return err;
+	if (!host_err)
+		commit_metadata(fhp);
+	return nfserrno(host_err);
 }
 
 #if defined(CONFIG_NFSD_V2_ACL) || \
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/include/crypto/internal/hash.h linux-libre-3.2.89-gnu1/include/crypto/internal/hash.h
--- linux-libre-3.2.88-gnu1/include/crypto/internal/hash.h	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/include/crypto/internal/hash.h	2017-06-05 16:13:58.000000000 -0400
@@ -149,6 +149,16 @@ static inline struct ahash_instance *aha
 	return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
 }
 
+static inline void ahash_request_complete(struct ahash_request *req, int err)
+{
+	req->base.complete(&req->base, err);
+}
+
+static inline u32 ahash_request_flags(struct ahash_request *req)
+{
+	return req->base.flags;
+}
+
 static inline struct crypto_ahash *crypto_spawn_ahash(
 	struct crypto_ahash_spawn *spawn)
 {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/include/linux/lockd/lockd.h linux-libre-3.2.89-gnu1/include/linux/lockd/lockd.h
--- linux-libre-3.2.88-gnu1/include/linux/lockd/lockd.h	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/include/linux/lockd/lockd.h	2017-06-05 16:13:58.000000000 -0400
@@ -348,7 +348,8 @@ static inline int nlm_privileged_request
 static inline int nlm_compare_locks(const struct file_lock *fl1,
 				    const struct file_lock *fl2)
 {
-	return	fl1->fl_pid   == fl2->fl_pid
+	return fl1->fl_file->f_dentry->d_inode == fl2->fl_file->f_dentry->d_inode
+	     && fl1->fl_pid   == fl2->fl_pid
 	     && fl1->fl_owner == fl2->fl_owner
 	     && fl1->fl_start == fl2->fl_start
 	     && fl1->fl_end   == fl2->fl_end
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/include/rdma/ib_sa.h linux-libre-3.2.89-gnu1/include/rdma/ib_sa.h
--- linux-libre-3.2.88-gnu1/include/rdma/ib_sa.h	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/include/rdma/ib_sa.h	2017-06-05 16:13:58.000000000 -0400
@@ -137,12 +137,12 @@ struct ib_sa_path_rec {
 	union ib_gid sgid;
 	__be16       dlid;
 	__be16       slid;
-	int          raw_traffic;
+	u8           raw_traffic;
 	/* reserved */
 	__be32       flow_label;
 	u8           hop_limit;
 	u8           traffic_class;
-	int          reversible;
+	u8           reversible;
 	u8           numb_path;
 	__be16       pkey;
 	__be16       qos_class;
@@ -193,7 +193,7 @@ struct ib_sa_mcmember_rec {
 	u8           hop_limit;
 	u8           scope;
 	u8           join_state;
-	int          proxy_join;
+	u8           proxy_join;
 };
 
 /* Service Record Component Mask Sec 15.2.5.14 Ver 1.1	*/
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/kernel/trace/trace.c linux-libre-3.2.89-gnu1/kernel/trace/trace.c
--- linux-libre-3.2.88-gnu1/kernel/trace/trace.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/kernel/trace/trace.c	2017-06-05 16:13:58.000000000 -0400
@@ -1100,7 +1100,7 @@ void trace_find_cmdline(int pid, char co
 	arch_spin_lock(&trace_cmdline_lock);
 	map = map_pid_to_cmdline[pid];
 	if (map != NO_CMDLINE_MAP)
-		strcpy(comm, saved_cmdlines[map]);
+		strlcpy(comm, saved_cmdlines[map], TASK_COMM_LEN);
 	else
 		strcpy(comm, "<...>");
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/Makefile linux-libre-3.2.89-gnu1/Makefile
--- linux-libre-3.2.88-gnu1/Makefile	2017-04-05 09:18:29.000000000 -0400
+++ linux-libre-3.2.89-gnu1/Makefile	2017-06-06 13:11:41.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 2
-SUBLEVEL = 88
+SUBLEVEL = 89
 EXTRAVERSION =-gnu1
 NAME = Saber-toothed Squirrel
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/mm/mempolicy.c linux-libre-3.2.89-gnu1/mm/mempolicy.c
--- linux-libre-3.2.88-gnu1/mm/mempolicy.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/mm/mempolicy.c	2017-06-05 16:13:58.000000000 -0400
@@ -1446,7 +1446,6 @@ asmlinkage long compat_sys_get_mempolicy
 asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
 				     compat_ulong_t maxnode)
 {
-	long err = 0;
 	unsigned long __user *nm = NULL;
 	unsigned long nr_bits, alloc_size;
 	DECLARE_BITMAP(bm, MAX_NUMNODES);
@@ -1455,14 +1454,13 @@ asmlinkage long compat_sys_set_mempolicy
 	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
 	if (nmask) {
-		err = compat_get_bitmap(bm, nmask, nr_bits);
+		if (compat_get_bitmap(bm, nmask, nr_bits))
+			return -EFAULT;
 		nm = compat_alloc_user_space(alloc_size);
-		err |= copy_to_user(nm, bm, alloc_size);
+		if (copy_to_user(nm, bm, alloc_size))
+			return -EFAULT;
 	}
 
-	if (err)
-		return -EFAULT;
-
 	return sys_set_mempolicy(mode, nm, nr_bits+1);
 }
 
@@ -1470,7 +1468,6 @@ asmlinkage long compat_sys_mbind(compat_
 			     compat_ulong_t mode, compat_ulong_t __user *nmask,
 			     compat_ulong_t maxnode, compat_ulong_t flags)
 {
-	long err = 0;
 	unsigned long __user *nm = NULL;
 	unsigned long nr_bits, alloc_size;
 	nodemask_t bm;
@@ -1479,14 +1476,13 @@ asmlinkage long compat_sys_mbind(compat_
 	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
 	if (nmask) {
-		err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits);
+		if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits))
+			return -EFAULT;
 		nm = compat_alloc_user_space(alloc_size);
-		err |= copy_to_user(nm, nodes_addr(bm), alloc_size);
+		if (copy_to_user(nm, nodes_addr(bm), alloc_size))
+			return -EFAULT;
 	}
 
-	if (err)
-		return -EFAULT;
-
 	return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
 }
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/dccp/ipv4.c linux-libre-3.2.89-gnu1/net/dccp/ipv4.c
--- linux-libre-3.2.88-gnu1/net/dccp/ipv4.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/dccp/ipv4.c	2017-06-05 16:13:58.000000000 -0400
@@ -1032,9 +1032,15 @@ static void __net_exit dccp_v4_exit_net(
 	inet_ctl_sock_destroy(net->dccp.v4_ctl_sk);
 }
 
+static void __net_exit dccp_v4_exit_batch(struct list_head *net_exit_list)
+{
+	inet_twsk_purge(&dccp_hashinfo, &dccp_death_row, AF_INET);
+}
+
 static struct pernet_operations dccp_v4_ops = {
 	.init	= dccp_v4_init_net,
 	.exit	= dccp_v4_exit_net,
+	.exit_batch = dccp_v4_exit_batch,
 };
 
 static int __init dccp_v4_init(void)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/dccp/ipv6.c linux-libre-3.2.89-gnu1/net/dccp/ipv6.c
--- linux-libre-3.2.88-gnu1/net/dccp/ipv6.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/dccp/ipv6.c	2017-06-05 16:13:58.000000000 -0400
@@ -499,6 +499,9 @@ static struct sock *dccp_v6_request_recv
 		newsk->sk_backlog_rcv = dccp_v4_do_rcv;
 		newnp->pktoptions  = NULL;
 		newnp->opt	   = NULL;
+		newnp->ipv6_mc_list = NULL;
+		newnp->ipv6_ac_list = NULL;
+		newnp->ipv6_fl_list = NULL;
 		newnp->mcast_oif   = inet6_iif(skb);
 		newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
 
@@ -574,6 +577,9 @@ static struct sock *dccp_v6_request_recv
 	/* Clone RX bits */
 	newnp->rxopt.all = np->rxopt.all;
 
+	newnp->ipv6_mc_list = NULL;
+	newnp->ipv6_ac_list = NULL;
+	newnp->ipv6_fl_list = NULL;
 	/* Clone pktoptions received with SYN */
 	newnp->pktoptions = NULL;
 	if (ireq6->pktopts != NULL) {
@@ -1157,9 +1163,15 @@ static void __net_exit dccp_v6_exit_net(
 	inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
 }
 
+static void __net_exit dccp_v6_exit_batch(struct list_head *net_exit_list)
+{
+	inet_twsk_purge(&dccp_hashinfo, &dccp_death_row, AF_INET6);
+}
+
 static struct pernet_operations dccp_v6_ops = {
 	.init   = dccp_v6_init_net,
 	.exit   = dccp_v6_exit_net,
+	.exit_batch = dccp_v6_exit_batch,
 };
 
 static int __init dccp_v6_init(void)
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipv4/inet_connection_sock.c linux-libre-3.2.89-gnu1/net/ipv4/inet_connection_sock.c
--- linux-libre-3.2.88-gnu1/net/ipv4/inet_connection_sock.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipv4/inet_connection_sock.c	2017-06-05 16:13:58.000000000 -0400
@@ -604,6 +604,8 @@ struct sock *inet_csk_clone(struct sock
 		inet_sk(newsk)->inet_sport = inet_rsk(req)->loc_port;
 		newsk->sk_write_space = sk_stream_write_space;
 
+		inet_sk(newsk)->mc_list = NULL;
+
 		newicsk->icsk_retransmits = 0;
 		newicsk->icsk_backoff	  = 0;
 		newicsk->icsk_probes_out  = 0;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipv4/ping.c linux-libre-3.2.89-gnu1/net/ipv4/ping.c
--- linux-libre-3.2.88-gnu1/net/ipv4/ping.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipv4/ping.c	2017-06-05 16:13:58.000000000 -0400
@@ -135,16 +135,17 @@ static void ping_v4_hash(struct sock *sk
 static void ping_v4_unhash(struct sock *sk)
 {
 	struct inet_sock *isk = inet_sk(sk);
+
 	pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+	write_lock_bh(&ping_table.lock);
 	if (sk_hashed(sk)) {
-		write_lock_bh(&ping_table.lock);
 		hlist_nulls_del(&sk->sk_nulls_node);
 		sk_nulls_node_init(&sk->sk_nulls_node);
 		sock_put(sk);
 		isk->inet_num = isk->inet_sport = 0;
 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-		write_unlock_bh(&ping_table.lock);
 	}
+	write_unlock_bh(&ping_table.lock);
 }
 
 static struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr,
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipv6/af_inet6.c linux-libre-3.2.89-gnu1/net/ipv6/af_inet6.c
--- linux-libre-3.2.88-gnu1/net/ipv6/af_inet6.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipv6/af_inet6.c	2017-06-05 16:13:58.000000000 -0400
@@ -785,7 +785,6 @@ static struct sk_buff *ipv6_gso_segment(
 	const struct inet6_protocol *ops;
 	int proto;
 	struct frag_hdr *fptr;
-	unsigned int unfrag_ip6hlen;
 	u8 *prevhdr;
 	int offset = 0;
 
@@ -824,9 +823,11 @@ static struct sk_buff *ipv6_gso_segment(
 		ipv6h->payload_len = htons(skb->len - skb->mac_len -
 					   sizeof(*ipv6h));
 		if (proto == IPPROTO_UDP) {
-			unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+			int err = ip6_find_1stfragopt(skb, &prevhdr);
+			if (err < 0)
+				return ERR_PTR(err);
 			fptr = (struct frag_hdr *)(skb_network_header(skb) +
-				unfrag_ip6hlen);
+				err);
 			fptr->frag_off = htons(offset);
 			if (skb->next != NULL)
 				fptr->frag_off |= htons(IP6_MF);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipv6/ip6_output.c linux-libre-3.2.89-gnu1/net/ipv6/ip6_output.c
--- linux-libre-3.2.88-gnu1/net/ipv6/ip6_output.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipv6/ip6_output.c	2017-06-05 16:13:58.000000000 -0400
@@ -562,13 +562,12 @@ static void ip6_copy_metadata(struct sk_
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
 	u16 offset = sizeof(struct ipv6hdr);
-	struct ipv6_opt_hdr *exthdr =
-				(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
 	unsigned int packet_len = skb->tail - skb->network_header;
 	int found_rhdr = 0;
 	*nexthdr = &ipv6_hdr(skb)->nexthdr;
 
-	while (offset + 1 <= packet_len) {
+	while (offset <= packet_len) {
+		struct ipv6_opt_hdr *exthdr;
 
 		switch (**nexthdr) {
 
@@ -589,13 +588,16 @@ int ip6_find_1stfragopt(struct sk_buff *
 			return offset;
 		}
 
-		offset += ipv6_optlen(exthdr);
-		*nexthdr = &exthdr->nexthdr;
+		if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
+			return -EINVAL;
+
 		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
 						 offset);
+		offset += ipv6_optlen(exthdr);
+		*nexthdr = &exthdr->nexthdr;
 	}
 
-	return offset;
+	return -EINVAL;
 }
 
 void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
@@ -629,7 +631,10 @@ int ip6_fragment(struct sk_buff *skb, in
 	u8 *prevhdr, nexthdr = 0;
 	struct net *net = dev_net(skb_dst(skb)->dev);
 
-	hlen = ip6_find_1stfragopt(skb, &prevhdr);
+	err = ip6_find_1stfragopt(skb, &prevhdr);
+	if (err < 0)
+		goto fail;
+	hlen = err;
 	nexthdr = *prevhdr;
 
 	mtu = ip6_skb_dst_mtu(skb);
@@ -1411,6 +1416,11 @@ alloc_new_skb:
 			 */
 			alloclen += sizeof(struct frag_hdr);
 
+			copy = datalen - transhdrlen - fraggap;
+			if (copy < 0) {
+				err = -EINVAL;
+				goto error;
+			}
 			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len,
@@ -1462,13 +1472,9 @@ alloc_new_skb:
 				data += fraggap;
 				pskb_trim_unique(skb_prev, maxfraglen);
 			}
-			copy = datalen - transhdrlen - fraggap;
-
-			if (copy < 0) {
-				err = -EINVAL;
-				kfree_skb(skb);
-				goto error;
-			} else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
+			if (copy > 0 &&
+			    getfrag(from, data + transhdrlen, offset,
+				    copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipv6/tcp_ipv6.c linux-libre-3.2.89-gnu1/net/ipv6/tcp_ipv6.c
--- linux-libre-3.2.88-gnu1/net/ipv6/tcp_ipv6.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipv6/tcp_ipv6.c	2017-06-05 16:13:58.000000000 -0400
@@ -1386,6 +1386,7 @@ static struct sock * tcp_v6_syn_recv_soc
 		newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
 #endif
 
+		newnp->ipv6_mc_list = NULL;
 		newnp->ipv6_ac_list = NULL;
 		newnp->ipv6_fl_list = NULL;
 		newnp->pktoptions  = NULL;
@@ -1451,6 +1452,7 @@ static struct sock * tcp_v6_syn_recv_soc
 	   First: no IPv4 options.
 	 */
 	newinet->inet_opt = NULL;
+	newnp->ipv6_mc_list = NULL;
 	newnp->ipv6_ac_list = NULL;
 	newnp->ipv6_fl_list = NULL;
 
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipv6/udp.c linux-libre-3.2.89-gnu1/net/ipv6/udp.c
--- linux-libre-3.2.88-gnu1/net/ipv6/udp.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipv6/udp.c	2017-06-05 16:13:58.000000000 -0400
@@ -1316,6 +1316,7 @@ static struct sk_buff *udp6_ufo_fragment
 	u8 frag_hdr_sz = sizeof(struct frag_hdr);
 	int offset;
 	__wsum csum;
+	int err;
 
 	mss = skb_shinfo(skb)->gso_size;
 	if (unlikely(skb->len <= mss))
@@ -1352,7 +1353,10 @@ static struct sk_buff *udp6_ufo_fragment
 	/* Find the unfragmentable header and shift it left by frag_hdr_sz
 	 * bytes to insert fragment header.
 	 */
-	unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+	err = ip6_find_1stfragopt(skb, &prevhdr);
+	if (err < 0)
+		return ERR_PTR(err);
+	unfrag_ip6hlen = err;
 	nexthdr = *prevhdr;
 	*prevhdr = NEXTHDR_FRAGMENT;
 	unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/ipx/af_ipx.c linux-libre-3.2.89-gnu1/net/ipx/af_ipx.c
--- linux-libre-3.2.88-gnu1/net/ipx/af_ipx.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/ipx/af_ipx.c	2017-06-05 16:13:58.000000000 -0400
@@ -1194,11 +1194,10 @@ static int ipxitf_ioctl(unsigned int cmd
 		sipx->sipx_network	= ipxif->if_netnum;
 		memcpy(sipx->sipx_node, ipxif->if_node,
 			sizeof(sipx->sipx_node));
-		rc = -EFAULT;
+		rc = 0;
 		if (copy_to_user(arg, &ifr, sizeof(ifr)))
-			break;
+			rc = -EFAULT;
 		ipxitf_put(ipxif);
-		rc = 0;
 		break;
 	}
 	case SIOCAIPXITFCRT:
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/packet/af_packet.c linux-libre-3.2.89-gnu1/net/packet/af_packet.c
--- linux-libre-3.2.88-gnu1/net/packet/af_packet.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/packet/af_packet.c	2017-06-05 16:13:58.000000000 -0400
@@ -195,6 +195,7 @@ struct tpacket_kbdq_core {
 	char		*pkblk_start;
 	char		*pkblk_end;
 	int		kblk_size;
+	unsigned int	max_frame_len;
 	unsigned int	knum_blocks;
 	uint64_t	knxt_seq_num;
 	char		*prev;
@@ -616,6 +617,7 @@ static void init_prb_bdqc(struct packet_
 	p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov);
 	p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv;
 
+	p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv);
 	prb_init_ft_ops(p1, req_u);
 	prb_setup_retire_blk_timer(po, tx_ring);
 	prb_open_block(p1, pbd);
@@ -1775,6 +1777,18 @@ static int tpacket_rcv(struct sk_buff *s
 			if ((int)snaplen < 0)
 				snaplen = 0;
 		}
+	} else if (unlikely(macoff + snaplen >
+			    GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) {
+		u32 nval;
+
+		nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff;
+		pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n",
+			    snaplen, nval, macoff);
+		snaplen = nval;
+		if (unlikely((int)snaplen < 0)) {
+			snaplen = 0;
+			macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len;
+		}
 	}
 	spin_lock(&sk->sk_receive_queue.lock);
 	h.raw = packet_current_rx_frame(po, skb,
@@ -3122,6 +3136,8 @@ packet_setsockopt(struct socket *sock, i
 			return -EBUSY;
 		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
+		if (val > INT_MAX)
+			return -EINVAL;
 		po->tp_reserve = val;
 		return 0;
 	}
@@ -3622,6 +3638,10 @@ static int packet_set_ring(struct sock *
 			goto out;
 		if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
 			goto out;
+		if (po->tp_version >= TPACKET_V3 &&
+		    req->tp_block_size <=
+			  BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
+			goto out;
 		if (unlikely(req->tp_frame_size < po->tp_hdrlen +
 					po->tp_reserve))
 			goto out;
@@ -3631,6 +3651,8 @@ static int packet_set_ring(struct sock *
 		rb->frames_per_block = req->tp_block_size/req->tp_frame_size;
 		if (unlikely(rb->frames_per_block <= 0))
 			goto out;
+		if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+			goto out;
 		if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
 					req->tp_frame_nr))
 			goto out;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/sched/act_api.c linux-libre-3.2.89-gnu1/net/sched/act_api.c
--- linux-libre-3.2.88-gnu1/net/sched/act_api.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/sched/act_api.c	2017-06-05 16:13:58.000000000 -0400
@@ -807,10 +807,8 @@ static int tca_action_flush(struct net *
 		goto nla_put_failure;
 
 	err = a->ops->walk(skb, &dcb, RTM_DELACTION, a);
-	if (err < 0)
+	if (err <= 0)
 		goto nla_put_failure;
-	if (err == 0)
-		goto noflush_out;
 
 	nla_nest_end(skb, nest);
 
@@ -829,7 +827,6 @@ nla_put_failure:
 nlmsg_failure:
 	module_put(a->ops->owner);
 err_out:
-noflush_out:
 	kfree_skb(skb);
 	kfree(a);
 	return err;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/sctp/ipv6.c linux-libre-3.2.89-gnu1/net/sctp/ipv6.c
--- linux-libre-3.2.88-gnu1/net/sctp/ipv6.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/sctp/ipv6.c	2017-06-05 16:13:58.000000000 -0400
@@ -655,6 +655,9 @@ static struct sock *sctp_v6_create_accep
 	newnp = inet6_sk(newsk);
 
 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
+	newnp->ipv6_mc_list = NULL;
+	newnp->ipv6_ac_list = NULL;
+	newnp->ipv6_fl_list = NULL;
 
 	rcu_read_lock();
 	opt = rcu_dereference(np->opt);
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/net/xfrm/xfrm_user.c linux-libre-3.2.89-gnu1/net/xfrm/xfrm_user.c
--- linux-libre-3.2.88-gnu1/net/xfrm/xfrm_user.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/net/xfrm/xfrm_user.c	2017-06-05 16:13:58.000000000 -0400
@@ -390,7 +390,14 @@ static inline int xfrm_replay_verify_len
 	up = nla_data(rp);
 	ulen = xfrm_replay_state_esn_len(up);
 
-	if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
+	/* Check the overall length and the internal bitmap length to avoid
+	 * potential overflow. */
+	if (nla_len(rp) < ulen ||
+	    xfrm_replay_state_esn_len(replay_esn) != ulen ||
+	    replay_esn->bmp_len != up->bmp_len)
+		return -EINVAL;
+
+	if (up->replay_window > up->bmp_len * sizeof(__u32) * 8)
 		return -EINVAL;
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/security/keys/encrypted-keys/encrypted.c linux-libre-3.2.89-gnu1/security/keys/encrypted-keys/encrypted.c
--- linux-libre-3.2.88-gnu1/security/keys/encrypted-keys/encrypted.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/security/keys/encrypted-keys/encrypted.c	2017-06-05 16:13:58.000000000 -0400
@@ -428,7 +428,7 @@ static int init_blkcipher_desc(struct bl
 static struct key *request_master_key(struct encrypted_key_payload *epayload,
 				      u8 **master_key, size_t *master_keylen)
 {
-	struct key *mkey = NULL;
+	struct key *mkey = ERR_PTR(-EINVAL);
 
 	if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX,
 		     KEY_TRUSTED_PREFIX_LEN)) {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/security/keys/keyctl.c linux-libre-3.2.89-gnu1/security/keys/keyctl.c
--- linux-libre-3.2.88-gnu1/security/keys/keyctl.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/security/keys/keyctl.c	2017-06-05 16:13:58.000000000 -0400
@@ -75,6 +75,10 @@ SYSCALL_DEFINE5(add_key, const char __us
 	if (IS_ERR(description)) {
 		ret = PTR_ERR(description);
 		goto error;
+	} else if ((description[0] == '.') &&
+		   (strncmp(type, "keyring", 7) == 0)) {
+		ret = -EPERM;
+		goto error2;
 	}
 
 	/* pull the payload in if one was supplied */
@@ -259,7 +263,8 @@ error:
  * Create and join an anonymous session keyring or join a named session
  * keyring, creating it if necessary.  A named session keyring must have Search
  * permission for it to be joined.  Session keyrings without this permit will
- * be skipped over.
+ * be skipped over.  It is not permitted for userspace to create or join
+ * keyrings whose name begin with a dot.
  *
  * If successful, the ID of the joined session keyring will be returned.
  */
@@ -276,12 +281,16 @@ long keyctl_join_session_keyring(const c
 			ret = PTR_ERR(name);
 			goto error;
 		}
+
+		ret = -EPERM;
+		if (name[0] == '.')
+			goto error_name;
 	}
 
 	/* join the session */
 	ret = join_session_keyring(name);
+error_name:
 	kfree(name);
-
 error:
 	return ret;
 }
@@ -1174,8 +1183,8 @@ error:
  * Read or set the default keyring in which request_key() will cache keys and
  * return the old setting.
  *
- * If a process keyring is specified then this will be created if it doesn't
- * yet exist.  The old setting will be returned if successful.
+ * If a thread or process keyring is specified then it will be created if it
+ * doesn't yet exist.  The old setting will be returned if successful.
  */
 long keyctl_set_reqkey_keyring(int reqkey_defl)
 {
@@ -1200,11 +1209,8 @@ long keyctl_set_reqkey_keyring(int reqke
 
 	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
 		ret = install_process_keyring_to_cred(new);
-		if (ret < 0) {
-			if (ret != -EEXIST)
-				goto error;
-			ret = 0;
-		}
+		if (ret < 0)
+			goto error;
 		goto set;
 
 	case KEY_REQKEY_DEFL_DEFAULT:
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/security/keys/process_keys.c linux-libre-3.2.89-gnu1/security/keys/process_keys.c
--- linux-libre-3.2.88-gnu1/security/keys/process_keys.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/security/keys/process_keys.c	2017-06-05 16:13:58.000000000 -0400
@@ -121,13 +121,18 @@ error:
 }
 
 /*
- * Install a fresh thread keyring directly to new credentials.  This keyring is
- * allowed to overrun the quota.
+ * Install a thread keyring to the given credentials struct if it didn't have
+ * one already.  This is allowed to overrun the quota.
+ *
+ * Return: 0 if a thread keyring is now present; -errno on failure.
  */
 int install_thread_keyring_to_cred(struct cred *new)
 {
 	struct key *keyring;
 
+	if (new->thread_keyring)
+		return 0;
+
 	keyring = keyring_alloc("_tid", new->uid, new->gid, new,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring))
@@ -138,7 +143,9 @@ int install_thread_keyring_to_cred(struc
 }
 
 /*
- * Install a fresh thread keyring, discarding the old one.
+ * Install a thread keyring to the current task if it didn't have one already.
+ *
+ * Return: 0 if a thread keyring is now present; -errno on failure.
  */
 static int install_thread_keyring(void)
 {
@@ -149,8 +156,6 @@ static int install_thread_keyring(void)
 	if (!new)
 		return -ENOMEM;
 
-	BUG_ON(new->thread_keyring);
-
 	ret = install_thread_keyring_to_cred(new);
 	if (ret < 0) {
 		abort_creds(new);
@@ -161,10 +166,10 @@ static int install_thread_keyring(void)
 }
 
 /*
- * Install a process keyring directly to a credentials struct.
+ * Install a process keyring to the given credentials struct if it didn't have
+ * one already.  This is allowed to overrun the quota.
  *
- * Returns -EEXIST if there was already a process keyring, 0 if one installed,
- * and other value on any other error
+ * Return: 0 if a process keyring is now present; -errno on failure.
  */
 int install_process_keyring_to_cred(struct cred *new)
 {
@@ -172,7 +177,7 @@ int install_process_keyring_to_cred(stru
 	int ret;
 
 	if (new->tgcred->process_keyring)
-		return -EEXIST;
+		return 0;
 
 	keyring = keyring_alloc("_pid", new->uid, new->gid,
 				new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
@@ -193,11 +198,9 @@ int install_process_keyring_to_cred(stru
 }
 
 /*
- * Make sure a process keyring is installed for the current process.  The
- * existing process keyring is not replaced.
+ * Install a process keyring to the current task if it didn't have one already.
  *
- * Returns 0 if there is a process keyring by the end of this function, some
- * error otherwise.
+ * Return: 0 if a process keyring is now present; -errno on failure.
  */
 static int install_process_keyring(void)
 {
@@ -211,14 +214,18 @@ static int install_process_keyring(void)
 	ret = install_process_keyring_to_cred(new);
 	if (ret < 0) {
 		abort_creds(new);
-		return ret != -EEXIST ? ret : 0;
+		return ret;
 	}
 
 	return commit_creds(new);
 }
 
 /*
- * Install a session keyring directly to a credentials struct.
+ * Install the given keyring as the session keyring of the given credentials
+ * struct, replacing the existing one if any.  If the given keyring is NULL,
+ * then install a new anonymous session keyring.
+ *
+ * Return: 0 on success; -errno on failure.
  */
 int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
 {
@@ -258,8 +265,11 @@ int install_session_keyring_to_cred(stru
 }
 
 /*
- * Install a session keyring, discarding the old one.  If a keyring is not
- * supplied, an empty one is invented.
+ * Install the given keyring as the session keyring of the current task,
+ * replacing the existing one if any.  If the given keyring is NULL, then
+ * install a new anonymous session keyring.
+ *
+ * Return: 0 on success; -errno on failure.
  */
 static int install_session_keyring(struct key *keyring)
 {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/sound/core/seq/seq_fifo.c linux-libre-3.2.89-gnu1/sound/core/seq/seq_fifo.c
--- linux-libre-3.2.88-gnu1/sound/core/seq/seq_fifo.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/sound/core/seq/seq_fifo.c	2017-06-05 16:13:58.000000000 -0400
@@ -137,6 +137,7 @@ int snd_seq_fifo_event_in(struct snd_seq
 	f->tail = cell;
 	if (f->head == NULL)
 		f->head = cell;
+	cell->next = NULL;
 	f->cells++;
 	spin_unlock_irqrestore(&f->lock, flags);
 
@@ -216,6 +217,8 @@ void snd_seq_fifo_cell_putback(struct sn
 		spin_lock_irqsave(&f->lock, flags);
 		cell->next = f->head;
 		f->head = cell;
+		if (!f->tail)
+			f->tail = cell;
 		f->cells++;
 		spin_unlock_irqrestore(&f->lock, flags);
 	}
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/sound/core/timer.c linux-libre-3.2.89-gnu1/sound/core/timer.c
--- linux-libre-3.2.88-gnu1/sound/core/timer.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/sound/core/timer.c	2017-06-05 16:13:58.000000000 -0400
@@ -1669,9 +1669,21 @@ static int snd_timer_user_params(struct
 		return -EBADFD;
 	if (copy_from_user(&params, _params, sizeof(params)))
 		return -EFAULT;
-	if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
-		err = -EINVAL;
-		goto _end;
+	if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
+		u64 resolution;
+
+		if (params.ticks < 1) {
+			err = -EINVAL;
+			goto _end;
+		}
+
+		/* Don't allow resolution less than 1ms */
+		resolution = snd_timer_resolution(tu->timeri);
+		resolution *= params.ticks;
+		if (resolution < 1000000) {
+			err = -EINVAL;
+			goto _end;
+		}
 	}
 	if (params.queue_size > 0 &&
 	    (params.queue_size < 32 || params.queue_size > 1024)) {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/sound/pci/ctxfi/cthw20k1.c linux-libre-3.2.89-gnu1/sound/pci/ctxfi/cthw20k1.c
--- linux-libre-3.2.88-gnu1/sound/pci/ctxfi/cthw20k1.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/sound/pci/ctxfi/cthw20k1.c	2017-06-05 16:13:58.000000000 -0400
@@ -27,12 +27,6 @@
 #include "cthw20k1.h"
 #include "ct20k1reg.h"
 
-#if BITS_PER_LONG == 32
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(32) /* 32 bit PTE */
-#else
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(64) /* 64 bit PTE */
-#endif
-
 struct hw20k1 {
 	struct hw hw;
 	spinlock_t reg_20k1_lock;
@@ -1903,19 +1897,18 @@ static int hw_card_start(struct hw *hw)
 {
 	int err;
 	struct pci_dev *pci = hw->pci;
+	const unsigned int dma_bits = BITS_PER_LONG;
 
 	err = pci_enable_device(pci);
 	if (err < 0)
 		return err;
 
 	/* Set DMA transfer mask */
-	if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 ||
-	    pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) {
-		printk(KERN_ERR "architecture does not support PCI "
-				"busmaster DMA with mask 0x%llx\n",
-		       CT_XFI_DMA_MASK);
-		err = -ENXIO;
-		goto error1;
+	if (dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
+	} else {
+		dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
 	}
 
 	if (!hw->io_base) {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/sound/pci/ctxfi/cthw20k2.c linux-libre-3.2.89-gnu1/sound/pci/ctxfi/cthw20k2.c
--- linux-libre-3.2.88-gnu1/sound/pci/ctxfi/cthw20k2.c	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/sound/pci/ctxfi/cthw20k2.c	2017-06-05 16:13:58.000000000 -0400
@@ -26,12 +26,6 @@
 #include "cthw20k2.h"
 #include "ct20k2reg.h"
 
-#if BITS_PER_LONG == 32
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(32) /* 32 bit PTE */
-#else
-#define CT_XFI_DMA_MASK		DMA_BIT_MASK(64) /* 64 bit PTE */
-#endif
-
 struct hw20k2 {
 	struct hw hw;
 	/* for i2c */
@@ -2026,18 +2020,18 @@ static int hw_card_start(struct hw *hw)
 	int err = 0;
 	struct pci_dev *pci = hw->pci;
 	unsigned int gctl;
+	const unsigned int dma_bits = BITS_PER_LONG;
 
 	err = pci_enable_device(pci);
 	if (err < 0)
 		return err;
 
 	/* Set DMA transfer mask */
-	if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 ||
-	    pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) {
-		printk(KERN_ERR "ctxfi: architecture does not support PCI "
-		"busmaster DMA with mask 0x%llx\n", CT_XFI_DMA_MASK);
-		err = -ENXIO;
-		goto error1;
+	if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
+	} else {
+		dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
+		dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
 	}
 
 	if (!hw->io_base) {
diff -druNp --no-dereference linux-libre-3.2.88-gnu1/tools/perf/Documentation/perf-script.txt linux-libre-3.2.89-gnu1/tools/perf/Documentation/perf-script.txt
--- linux-libre-3.2.88-gnu1/tools/perf/Documentation/perf-script.txt	2017-04-04 17:18:33.000000000 -0400
+++ linux-libre-3.2.89-gnu1/tools/perf/Documentation/perf-script.txt	2017-06-05 16:13:58.000000000 -0400
@@ -36,7 +36,7 @@ There are several variants of perf scrip
 
   'perf script report <script> [args]' to run and display the results
   of <script>.  <script> is the name displayed in the output of 'perf
-  trace --list' i.e. the actual script name minus any language
+  script --list' i.e. the actual script name minus any language
   extension.  The perf.data output from a previous run of 'perf script
   record <script>' is used and should be present for this command to
   succeed.  [args] refers to the (mainly optional) args expected by
@@ -76,7 +76,7 @@ OPTIONS
 	Any command you can specify in a shell.
 
 -D::
---dump-raw-script=::
+--dump-raw-trace=::
         Display verbose dump of the trace data.
 
 -L::
