diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/arm/kvm/psci.c linux-libre-4.4.69-gnu/arch/arm/kvm/psci.c
--- linux-libre-4.4.68-gnu/arch/arm/kvm/psci.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/arm/kvm/psci.c	2017-05-20 08:27:22.000000000 -0400
@@ -208,9 +208,10 @@ int kvm_psci_version(struct kvm_vcpu *vc
 
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
-	int ret = 1;
+	struct kvm *kvm = vcpu->kvm;
 	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
+	int ret = 1;
 
 	switch (psci_fn) {
 	case PSCI_0_2_FN_PSCI_VERSION:
@@ -230,7 +231,9 @@ static int kvm_psci_0_2_call(struct kvm_
 		break;
 	case PSCI_0_2_FN_CPU_ON:
 	case PSCI_0_2_FN64_CPU_ON:
+		mutex_lock(&kvm->lock);
 		val = kvm_psci_vcpu_on(vcpu);
+		mutex_unlock(&kvm->lock);
 		break;
 	case PSCI_0_2_FN_AFFINITY_INFO:
 	case PSCI_0_2_FN64_AFFINITY_INFO:
@@ -279,6 +282,7 @@ static int kvm_psci_0_2_call(struct kvm_
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
 	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
 
@@ -288,7 +292,9 @@ static int kvm_psci_0_1_call(struct kvm_
 		val = PSCI_RET_SUCCESS;
 		break;
 	case KVM_PSCI_FN_CPU_ON:
+		mutex_lock(&kvm->lock);
 		val = kvm_psci_vcpu_on(vcpu);
+		mutex_unlock(&kvm->lock);
 		break;
 	default:
 		val = PSCI_RET_NOT_SUPPORTED;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/arm64/kvm/sys_regs.c linux-libre-4.4.69-gnu/arch/arm64/kvm/sys_regs.c
--- linux-libre-4.4.68-gnu/arch/arm64/kvm/sys_regs.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/arm64/kvm/sys_regs.c	2017-05-20 08:27:22.000000000 -0400
@@ -1054,8 +1054,8 @@ static int kvm_handle_cp_64(struct kvm_v
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (hsr >> 5) & 0xf;
-	int Rt2 = (hsr >> 10) & 0xf;
+	int Rt = (hsr >> 5) & 0x1f;
+	int Rt2 = (hsr >> 10) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = false;
@@ -1106,7 +1106,7 @@ static int kvm_handle_cp_32(struct kvm_v
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt  = (hsr >> 5) & 0xf;
+	int Rt  = (hsr >> 5) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = true;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/x86/boot/boot.h linux-libre-4.4.69-gnu/arch/x86/boot/boot.h
--- linux-libre-4.4.68-gnu/arch/x86/boot/boot.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/x86/boot/boot.h	2017-05-20 08:27:22.000000000 -0400
@@ -16,7 +16,7 @@
 #ifndef BOOT_BOOT_H
 #define BOOT_BOOT_H
 
-#define STACK_SIZE	512	/* Minimum number of bytes for stack */
+#define STACK_SIZE	1024	/* Minimum number of bytes for stack */
 
 #ifndef __ASSEMBLY__
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/x86/include/asm/pmem.h linux-libre-4.4.69-gnu/arch/x86/include/asm/pmem.h
--- linux-libre-4.4.68-gnu/arch/x86/include/asm/pmem.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/x86/include/asm/pmem.h	2017-05-20 08:27:22.000000000 -0400
@@ -122,7 +122,7 @@ static inline size_t arch_copy_from_iter
 
 		if (bytes < 8) {
 			if (!IS_ALIGNED(dest, 4) || (bytes != 4))
-				__arch_wb_cache_pmem(addr, 1);
+				__arch_wb_cache_pmem(addr, bytes);
 		} else {
 			if (!IS_ALIGNED(dest, 8)) {
 				dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/x86/kvm/x86.c linux-libre-4.4.69-gnu/arch/x86/kvm/x86.c
--- linux-libre-4.4.68-gnu/arch/x86/kvm/x86.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/x86/kvm/x86.c	2017-05-20 08:27:22.000000000 -0400
@@ -2960,6 +2960,12 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_e
 			      | KVM_VCPUEVENT_VALID_SMM))
 		return -EINVAL;
 
+	/* INITs are latched while in SMM */
+	if (events->flags & KVM_VCPUEVENT_VALID_SMM &&
+	    (events->smi.smm || events->smi.pending) &&
+	    vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED)
+		return -EINVAL;
+
 	process_nmi(vcpu);
 	vcpu->arch.exception.pending = events->exception.injected;
 	vcpu->arch.exception.nr = events->exception.nr;
@@ -6993,6 +6999,12 @@ int kvm_arch_vcpu_ioctl_set_mpstate(stru
 	    mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
 		return -EINVAL;
 
+	/* INITs are latched while in SMM */
+	if ((is_smm(vcpu) || vcpu->arch.smi_pending) &&
+	    (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED ||
+	     mp_state->mp_state == KVM_MP_STATE_INIT_RECEIVED))
+		return -EINVAL;
+
 	if (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED) {
 		vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
 		set_bit(KVM_APIC_SIPI, &vcpu->arch.apic->pending_events);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/x86/um/ptrace_64.c linux-libre-4.4.69-gnu/arch/x86/um/ptrace_64.c
--- linux-libre-4.4.68-gnu/arch/x86/um/ptrace_64.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/x86/um/ptrace_64.c	2017-05-20 08:27:22.000000000 -0400
@@ -121,7 +121,7 @@ int poke_user(struct task_struct *child,
 	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
 		(addr <= offsetof(struct user, u_debugreg[7]))) {
 		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
+		addr = addr >> 3;
 		if ((addr == 4) || (addr == 5))
 			return -EIO;
 		child->thread.arch.debugregs[addr] = data;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/arch/x86/xen/mmu.c linux-libre-4.4.69-gnu/arch/x86/xen/mmu.c
--- linux-libre-4.4.68-gnu/arch/x86/xen/mmu.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/arch/x86/xen/mmu.c	2017-05-20 08:27:22.000000000 -0400
@@ -2038,7 +2038,8 @@ static unsigned long __init xen_read_phy
 
 /*
  * Translate a virtual address to a physical one without relying on mapped
- * page tables.
+ * page tables. Don't rely on big pages being aligned in (guest) physical
+ * space!
  */
 static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
 {
@@ -2059,7 +2060,7 @@ static phys_addr_t __init xen_early_virt
 						       sizeof(pud)));
 	if (!pud_present(pud))
 		return 0;
-	pa = pud_pfn(pud) << PAGE_SHIFT;
+	pa = pud_val(pud) & PTE_PFN_MASK;
 	if (pud_large(pud))
 		return pa + (vaddr & ~PUD_MASK);
 
@@ -2067,7 +2068,7 @@ static phys_addr_t __init xen_early_virt
 						       sizeof(pmd)));
 	if (!pmd_present(pmd))
 		return 0;
-	pa = pmd_pfn(pmd) << PAGE_SHIFT;
+	pa = pmd_val(pmd) & PTE_PFN_MASK;
 	if (pmd_large(pmd))
 		return pa + (vaddr & ~PMD_MASK);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/block/blk-integrity.c linux-libre-4.4.69-gnu/block/blk-integrity.c
--- linux-libre-4.4.68-gnu/block/blk-integrity.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/block/blk-integrity.c	2017-05-20 08:27:22.000000000 -0400
@@ -412,7 +412,8 @@ void blk_integrity_register(struct gendi
 
 	bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
 		template->flags;
-	bi->interval_exp = ilog2(queue_logical_block_size(disk->queue));
+	bi->interval_exp = template->interval_exp ? :
+		ilog2(queue_logical_block_size(disk->queue));
 	bi->profile = template->profile ? template->profile : &nop_profile;
 	bi->tuple_size = template->tuple_size;
 	bi->tag_size = template->tag_size;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/crypto/algif_aead.c linux-libre-4.4.69-gnu/crypto/algif_aead.c
--- linux-libre-4.4.68-gnu/crypto/algif_aead.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/crypto/algif_aead.c	2017-05-20 08:27:22.000000000 -0400
@@ -29,6 +29,11 @@ struct aead_sg_list {
 	struct scatterlist sg[ALG_MAX_PAGES];
 };
 
+struct aead_tfm {
+	struct crypto_aead *aead;
+	bool has_key;
+};
+
 struct aead_ctx {
 	struct aead_sg_list tsgl;
 	/*
@@ -513,24 +518,146 @@ static struct proto_ops algif_aead_ops =
 	.poll		=	aead_poll,
 };
 
+static int aead_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct aead_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t size)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_sendmsg(sock, msg, size);
+}
+
+static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page,
+				       int offset, size_t size, int flags)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_sendpage(sock, page, offset, size, flags);
+}
+
+static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t ignored, int flags)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_recvmsg(sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_aead_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	aead_sendmsg_nokey,
+	.sendpage	=	aead_sendpage_nokey,
+	.recvmsg	=	aead_recvmsg_nokey,
+	.poll		=	aead_poll,
+};
+
 static void *aead_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_aead(name, type, mask);
+	struct aead_tfm *tfm;
+	struct crypto_aead *aead;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	aead = crypto_alloc_aead(name, type, mask);
+	if (IS_ERR(aead)) {
+		kfree(tfm);
+		return ERR_CAST(aead);
+	}
+
+	tfm->aead = aead;
+
+	return tfm;
 }
 
 static void aead_release(void *private)
 {
-	crypto_free_aead(private);
+	struct aead_tfm *tfm = private;
+
+	crypto_free_aead(tfm->aead);
+	kfree(tfm);
 }
 
 static int aead_setauthsize(void *private, unsigned int authsize)
 {
-	return crypto_aead_setauthsize(private, authsize);
+	struct aead_tfm *tfm = private;
+
+	return crypto_aead_setauthsize(tfm->aead, authsize);
 }
 
 static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_aead_setkey(private, key, keylen);
+	struct aead_tfm *tfm = private;
+	int err;
+
+	err = crypto_aead_setkey(tfm->aead, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void aead_sock_destruct(struct sock *sk)
@@ -546,12 +673,14 @@ static void aead_sock_destruct(struct so
 	af_alg_release_parent(sk);
 }
 
-static int aead_accept_parent(void *private, struct sock *sk)
+static int aead_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct aead_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private);
-	unsigned int ivlen = crypto_aead_ivsize(private);
+	struct aead_tfm *tfm = private;
+	struct crypto_aead *aead = tfm->aead;
+	unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(aead);
+	unsigned int ivlen = crypto_aead_ivsize(aead);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -577,7 +706,7 @@ static int aead_accept_parent(void *priv
 
 	ask->private = ctx;
 
-	aead_request_set_tfm(&ctx->aead_req, private);
+	aead_request_set_tfm(&ctx->aead_req, aead);
 	aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				  af_alg_complete, &ctx->completion);
 
@@ -586,13 +715,25 @@ static int aead_accept_parent(void *priv
 	return 0;
 }
 
+static int aead_accept_parent(void *private, struct sock *sk)
+{
+	struct aead_tfm *tfm = private;
+
+	if (!tfm->has_key)
+		return -ENOKEY;
+
+	return aead_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_aead = {
 	.bind		=	aead_bind,
 	.release	=	aead_release,
 	.setkey		=	aead_setkey,
 	.setauthsize	=	aead_setauthsize,
 	.accept		=	aead_accept_parent,
+	.accept_nokey	=	aead_accept_parent_nokey,
 	.ops		=	&algif_aead_ops,
+	.ops_nokey	=	&algif_aead_ops_nokey,
 	.name		=	"aead",
 	.owner		=	THIS_MODULE
 };
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/bluetooth/hci_bcm.c linux-libre-4.4.69-gnu/drivers/bluetooth/hci_bcm.c
--- linux-libre-4.4.68-gnu/drivers/bluetooth/hci_bcm.c	2017-05-14 16:55:13.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/bluetooth/hci_bcm.c	2017-05-20 11:33:27.000000000 -0400
@@ -287,6 +287,9 @@ static int bcm_open(struct hci_uart *hu)
 
 	hu->priv = bcm;
 
+	if (!hu->tty->dev)
+		goto out;
+
 	mutex_lock(&bcm_device_lock);
 	list_for_each(p, &bcm_device_list) {
 		struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@@ -307,7 +310,7 @@ static int bcm_open(struct hci_uart *hu)
 	}
 
 	mutex_unlock(&bcm_device_lock);
-
+out:
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/bluetooth/hci_intel.c linux-libre-4.4.69-gnu/drivers/bluetooth/hci_intel.c
--- linux-libre-4.4.68-gnu/drivers/bluetooth/hci_intel.c	2017-05-14 16:55:49.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/bluetooth/hci_intel.c	2017-05-20 11:34:01.000000000 -0400
@@ -307,6 +307,9 @@ static int intel_set_power(struct hci_ua
 	struct list_head *p;
 	int err = -ENODEV;
 
+	if (!hu->tty->dev)
+		return err;
+
 	mutex_lock(&intel_device_list_lock);
 
 	list_for_each(p, &intel_device_list) {
@@ -379,6 +382,9 @@ static void intel_busy_work(struct work_
 	struct intel_data *intel = container_of(work, struct intel_data,
 						busy_work);
 
+	if (!intel->hu->tty->dev)
+		return;
+
 	/* Link is busy, delay the suspend */
 	mutex_lock(&intel_device_list_lock);
 	list_for_each(p, &intel_device_list) {
@@ -913,6 +919,8 @@ done:
 	list_for_each(p, &intel_device_list) {
 		struct intel_device *dev = list_entry(p, struct intel_device,
 						      list);
+		if (!hu->tty->dev)
+			break;
 		if (hu->tty->dev->parent == dev->pdev->dev.parent) {
 			if (device_may_wakeup(&dev->pdev->dev))
 				idev = dev;
@@ -1094,6 +1102,9 @@ static int intel_enqueue(struct hci_uart
 
 	BT_DBG("hu %p skb %p", hu, skb);
 
+	if (!hu->tty->dev)
+		goto out_enqueue;
+
 	/* Be sure our controller is resumed and potential LPM transaction
 	 * completed before enqueuing any packet.
 	 */
@@ -1110,7 +1121,7 @@ static int intel_enqueue(struct hci_uart
 		}
 	}
 	mutex_unlock(&intel_device_list_lock);
-
+out_enqueue:
 	skb_queue_tail(&intel->txq, skb);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/char/ipmi/ipmi_ssif.c linux-libre-4.4.69-gnu/drivers/char/ipmi/ipmi_ssif.c
--- linux-libre-4.4.68-gnu/drivers/char/ipmi/ipmi_ssif.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/char/ipmi/ipmi_ssif.c	2017-05-20 08:27:22.000000000 -0400
@@ -888,6 +888,7 @@ static void msg_written_handler(struct s
 		 * for details on the intricacies of this.
 		 */
 		int left;
+		unsigned char *data_to_send;
 
 		ssif_inc_stat(ssif_info, sent_messages_parts);
 
@@ -896,6 +897,7 @@ static void msg_written_handler(struct s
 			left = 32;
 		/* Length byte. */
 		ssif_info->multi_data[ssif_info->multi_pos] = left;
+		data_to_send = ssif_info->multi_data + ssif_info->multi_pos;
 		ssif_info->multi_pos += left;
 		if (left < 32)
 			/*
@@ -909,7 +911,7 @@ static void msg_written_handler(struct s
 		rv = ssif_i2c_send(ssif_info, msg_written_handler,
 				  I2C_SMBUS_WRITE,
 				  SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
-				  ssif_info->multi_data + ssif_info->multi_pos,
+				  data_to_send,
 				  I2C_SMBUS_BLOCK_DATA);
 		if (rv < 0) {
 			/* request failed, just return the error. */
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/infiniband/core/sysfs.c linux-libre-4.4.69-gnu/drivers/infiniband/core/sysfs.c
--- linux-libre-4.4.68-gnu/drivers/infiniband/core/sysfs.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/infiniband/core/sysfs.c	2017-05-20 08:27:22.000000000 -0400
@@ -863,7 +863,7 @@ err_put:
 	free_port_list_attributes(device);
 
 err_unregister:
-	device_unregister(class_dev);
+	device_del(class_dev);
 
 err:
 	return ret;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/infiniband/hw/mlx4/main.c linux-libre-4.4.69-gnu/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-4.4.68-gnu/drivers/infiniband/hw/mlx4/main.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/infiniband/hw/mlx4/main.c	2017-05-20 08:27:22.000000000 -0400
@@ -2491,6 +2491,7 @@ err_counter:
 		mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[i]);
 
 err_map:
+	mlx4_ib_free_eqs(dev, ibdev);
 	iounmap(ibdev->uar_map);
 
 err_uar:
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/infiniband/hw/mlx4/mcg.c linux-libre-4.4.69-gnu/drivers/infiniband/hw/mlx4/mcg.c
--- linux-libre-4.4.68-gnu/drivers/infiniband/hw/mlx4/mcg.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/infiniband/hw/mlx4/mcg.c	2017-05-20 08:27:22.000000000 -0400
@@ -1105,7 +1105,8 @@ static void _mlx4_ib_mcg_port_cleanup(st
 	while ((p = rb_first(&ctx->mcg_table)) != NULL) {
 		group = rb_entry(p, struct mcast_group, node);
 		if (atomic_read(&group->refcount))
-			mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", atomic_read(&group->refcount), group);
+			mcg_debug_group(group, "group refcount %d!!! (pointer %p)\n",
+					atomic_read(&group->refcount), group);
 
 		force_clean_group(group);
 	}
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c linux-libre-4.4.69-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c
--- linux-libre-4.4.68-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2017-05-20 08:27:22.000000000 -0400
@@ -281,8 +281,11 @@ void ipoib_delete_debug_files(struct net
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
+	WARN_ONCE(!priv->mcg_dentry, "null mcg debug file\n");
+	WARN_ONCE(!priv->path_dentry, "null path debug file\n");
 	debugfs_remove(priv->mcg_dentry);
 	debugfs_remove(priv->path_dentry);
+	priv->mcg_dentry = priv->path_dentry = NULL;
 }
 
 int ipoib_register_debugfs(void)
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-4.4.69-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-4.4.68-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2017-05-20 08:27:22.000000000 -0400
@@ -106,6 +106,33 @@ static struct ib_client ipoib_client = {
 	.get_net_dev_by_params = ipoib_get_net_dev_by_params,
 };
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+static int ipoib_netdev_event(struct notifier_block *this,
+			      unsigned long event, void *ptr)
+{
+	struct netdev_notifier_info *ni = ptr;
+	struct net_device *dev = ni->dev;
+
+	if (dev->netdev_ops->ndo_open != ipoib_open)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_REGISTER:
+		ipoib_create_debug_files(dev);
+		break;
+	case NETDEV_CHANGENAME:
+		ipoib_delete_debug_files(dev);
+		ipoib_create_debug_files(dev);
+		break;
+	case NETDEV_UNREGISTER:
+		ipoib_delete_debug_files(dev);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+#endif
+
 int ipoib_open(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -1595,8 +1622,6 @@ void ipoib_dev_cleanup(struct net_device
 
 	ASSERT_RTNL();
 
-	ipoib_delete_debug_files(dev);
-
 	/* Delete any child interfaces first */
 	list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
 		/* Stop GC on child */
@@ -1908,8 +1933,6 @@ static struct net_device *ipoib_add_port
 		goto register_failed;
 	}
 
-	ipoib_create_debug_files(priv->dev);
-
 	if (ipoib_cm_add_mode_attr(priv->dev))
 		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
@@ -1924,7 +1947,6 @@ static struct net_device *ipoib_add_port
 	return priv->dev;
 
 sysfs_failed:
-	ipoib_delete_debug_files(priv->dev);
 	unregister_netdev(priv->dev);
 
 register_failed:
@@ -2006,6 +2028,12 @@ static void ipoib_remove_one(struct ib_d
 	kfree(dev_list);
 }
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+static struct notifier_block ipoib_netdev_notifier = {
+	.notifier_call = ipoib_netdev_event,
+};
+#endif
+
 static int __init ipoib_init_module(void)
 {
 	int ret;
@@ -2057,6 +2085,9 @@ static int __init ipoib_init_module(void
 	if (ret)
 		goto err_client;
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+	register_netdevice_notifier(&ipoib_netdev_notifier);
+#endif
 	return 0;
 
 err_client:
@@ -2074,6 +2105,9 @@ err_fs:
 
 static void __exit ipoib_cleanup_module(void)
 {
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+	unregister_netdevice_notifier(&ipoib_netdev_notifier);
+#endif
 	ipoib_netlink_fini();
 	ib_unregister_client(&ipoib_client);
 	ib_sa_unregister_client(&ipoib_sa_client);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c linux-libre-4.4.69-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
--- linux-libre-4.4.68-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	2017-05-20 08:27:22.000000000 -0400
@@ -85,8 +85,6 @@ int __ipoib_vlan_add(struct ipoib_dev_pr
 		goto register_failed;
 	}
 
-	ipoib_create_debug_files(priv->dev);
-
 	/* RTNL childs don't need proprietary sysfs entries */
 	if (type == IPOIB_LEGACY_CHILD) {
 		if (ipoib_cm_add_mode_attr(priv->dev))
@@ -107,7 +105,6 @@ int __ipoib_vlan_add(struct ipoib_dev_pr
 
 sysfs_failed:
 	result = -ENOMEM;
-	ipoib_delete_debug_files(priv->dev);
 	unregister_netdevice(priv->dev);
 
 register_failed:
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/Makefile linux-libre-4.4.69-gnu/drivers/Makefile
--- linux-libre-4.4.68-gnu/drivers/Makefile	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/Makefile	2017-05-20 08:27:22.000000000 -0400
@@ -98,6 +98,7 @@ obj-$(CONFIG_USB_PHY)		+= usb/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/
+obj-$(CONFIG_OF)		+= usb/
 obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
 obj-$(CONFIG_INPUT)		+= input/
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/md/dm-era-target.c linux-libre-4.4.69-gnu/drivers/md/dm-era-target.c
--- linux-libre-4.4.68-gnu/drivers/md/dm-era-target.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/md/dm-era-target.c	2017-05-20 08:27:22.000000000 -0400
@@ -961,15 +961,15 @@ static int metadata_commit(struct era_me
 		}
 	}
 
-	r = save_sm_root(md);
+	r = dm_tm_pre_commit(md->tm);
 	if (r) {
-		DMERR("%s: save_sm_root failed", __func__);
+		DMERR("%s: pre commit failed", __func__);
 		return r;
 	}
 
-	r = dm_tm_pre_commit(md->tm);
+	r = save_sm_root(md);
 	if (r) {
-		DMERR("%s: pre commit failed", __func__);
+		DMERR("%s: save_sm_root failed", __func__);
 		return r;
 	}
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ath/ath10k/mac.c linux-libre-4.4.69-gnu/drivers/net/wireless/ath/ath10k/mac.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ath/ath10k/mac.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ath/ath10k/mac.c	2017-05-20 08:27:22.000000000 -0400
@@ -6351,12 +6351,13 @@ static u64 ath10k_get_tsf(struct ieee802
 
 static int ath10k_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
-			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			       u8 buf_size, bool amsdu)
+			       struct ieee80211_ampdu_params *params)
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
 		   arvif->vdev_id, sta->addr, tid, action);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c linux-libre-4.4.69-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2017-05-20 08:27:22.000000000 -0400
@@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct i
 
 static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
-				  enum ieee80211_ampdu_mlme_action action,
-				  struct ieee80211_sta *sta,
-				  u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+				  struct ieee80211_ampdu_params *params)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_sta *ista;
 	int ret = 0;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
 
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ath/ath9k/main.c linux-libre-4.4.69-gnu/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ath/ath9k/main.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ath/ath9k/main.c	2017-05-20 08:27:22.000000000 -0400
@@ -1855,14 +1855,16 @@ static void ath9k_reset_tsf(struct ieee8
 
 static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
-			      enum ieee80211_ampdu_mlme_action action,
-			      struct ieee80211_sta *sta,
-			      u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+			      struct ieee80211_ampdu_params *params)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	bool flush = false;
 	int ret = 0;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	mutex_lock(&sc->mutex);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ath/carl9170/main.c linux-libre-4.4.69-gnu/drivers/net/wireless/ath/carl9170/main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ath/carl9170/main.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ath/carl9170/main.c	2017-05-20 08:27:22.000000000 -0400
@@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct w
 
 static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
-				    enum ieee80211_ampdu_mlme_action action,
-				    struct ieee80211_sta *sta,
-				    u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+				    struct ieee80211_ampdu_params *params)
 {
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 	struct ar9170 *ar = hw->priv;
 	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
 	struct carl9170_sta_tid *tid_info;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ath/wcn36xx/main.c linux-libre-4.4.69-gnu/drivers/net/wireless/ath/wcn36xx/main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ath/wcn36xx/main.c	2017-05-14 16:54:44.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ath/wcn36xx/main.c	2017-05-20 11:32:52.000000000 -0400
@@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee802
 
 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
 		    struct ieee80211_vif *vif,
-		    enum ieee80211_ampdu_mlme_action action,
-		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		    u8 buf_size, bool amsdu)
+		    struct ieee80211_ampdu_params *params)
 {
 	struct wcn36xx *wcn = hw->priv;
 	struct wcn36xx_sta *sta_priv = NULL;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
 		    action, tid);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c linux-libre-4.4.69-gnu/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c	2017-05-14 16:46:18.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c	2017-05-20 11:20:57.000000000 -0400
@@ -817,13 +817,15 @@ brcms_ops_sta_add(struct ieee80211_hw *h
 static int
 brcms_ops_ampdu_action(struct ieee80211_hw *hw,
 		    struct ieee80211_vif *vif,
-		    enum ieee80211_ampdu_mlme_action action,
-		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		    u8 buf_size, bool amsdu)
+		    struct ieee80211_ampdu_params *params)
 {
 	struct brcms_info *wl = hw->priv;
 	struct scb *scb = &wl->wlc->pri_scb;
 	int status;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u8 buf_size = params->buf_size;
 
 	if (WARN_ON(scb->magic != SCB_MAGIC))
 		return -EIDRM;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/cw1200/sta.c linux-libre-4.4.69-gnu/drivers/net/wireless/cw1200/sta.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/cw1200/sta.c	2017-05-14 16:50:13.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/cw1200/sta.c	2017-05-20 11:26:39.000000000 -0400
@@ -2135,9 +2135,7 @@ void cw1200_mcast_timeout(unsigned long
 
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu)
+			struct ieee80211_ampdu_params *params)
 {
 	/* Aggregation is implemented fully in firmware,
 	 * including block ack negotiation. Do not allow
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/cw1200/sta.h linux-libre-4.4.69-gnu/drivers/net/wireless/cw1200/sta.h
--- linux-libre-4.4.68-gnu/drivers/net/wireless/cw1200/sta.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/cw1200/sta.h	2017-05-20 08:27:22.000000000 -0400
@@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee
 			     u32 changed);
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu);
+			struct ieee80211_ampdu_params *params);
 
 void cw1200_suspend_resume(struct cw1200_common *priv,
 			  struct wsm_suspend_resume *arg);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/iwlegacy/4965.h linux-libre-4.4.69-gnu/drivers/net/wireless/iwlegacy/4965.h
--- linux-libre-4.4.68-gnu/drivers/net/wireless/iwlegacy/4965.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/iwlegacy/4965.h	2017-05-20 08:27:22.000000000 -0400
@@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct i
 				struct ieee80211_sta *sta, u32 iv32,
 				u16 *phase1key);
 int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 * ssn,
-			    u8 buf_size, bool amsdu);
+			    struct ieee80211_ampdu_params *params);
 int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
 void
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/iwlegacy/4965-mac.c linux-libre-4.4.69-gnu/drivers/net/wireless/iwlegacy/4965-mac.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/iwlegacy/4965-mac.c	2017-05-14 16:47:29.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/iwlegacy/4965-mac.c	2017-05-20 11:22:26.000000000 -0400
@@ -5982,12 +5982,14 @@ il4965_mac_set_key(struct ieee80211_hw *
 
 int
 il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 * ssn,
-			u8 buf_size, bool amsdu)
+			struct ieee80211_ampdu_params *params)
 {
 	struct il_priv *il = hw->priv;
 	int ret = -EINVAL;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c linux-libre-4.4.69-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/iwlwifi/dvm/mac80211.c	2017-05-20 08:27:22.000000000 -0400
@@ -729,12 +729,15 @@ static inline bool iwl_enable_tx_ampdu(c
 
 static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
-				   enum ieee80211_ampdu_mlme_action action,
-				   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-				   u8 buf_size, bool amsdu)
+				   struct ieee80211_ampdu_params *params)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 	int ret = -EINVAL;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 	struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c linux-libre-4.4.69-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/iwlwifi/mvm/mac80211.c	2017-05-20 08:27:22.000000000 -0400
@@ -826,13 +826,16 @@ iwl_mvm_ampdu_check_trigger(struct iwl_m
 
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
-				    enum ieee80211_ampdu_mlme_action action,
-				    struct ieee80211_sta *sta, u16 tid,
-				    u16 *ssn, u8 buf_size, bool amsdu)
+				    struct ieee80211_ampdu_params *params)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
 	bool tx_agg_ref = false;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 
 	IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n",
 		     sta->addr, tid, action);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/mac80211_hwsim.c linux-libre-4.4.69-gnu/drivers/net/wireless/mac80211_hwsim.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/mac80211_hwsim.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/mac80211_hwsim.c	2017-05-20 08:27:22.000000000 -0400
@@ -1817,10 +1817,12 @@ static int mac80211_hwsim_testmode_cmd(s
 
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
-				       enum ieee80211_ampdu_mlme_action action,
-				       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-				       u8 buf_size, bool amsdu)
+				       struct ieee80211_ampdu_params *params)
 {
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
 		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/mediatek/mt7601u/main.c linux-libre-4.4.69-gnu/drivers/net/wireless/mediatek/mt7601u/main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/mediatek/mt7601u/main.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/mediatek/mt7601u/main.c	2017-05-20 08:27:22.000000000 -0400
@@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(str
 
 static int
 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		  enum ieee80211_ampdu_mlme_action action,
-		  struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
-		  bool amsdu)
+		  struct ieee80211_ampdu_params *params)
 {
 	struct mt7601u_dev *dev = hw->priv;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 	struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
 
 	WARN_ON(msta->wcid.idx > GROUP_WCID(0));
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/mwl8k.c linux-libre-4.4.69-gnu/drivers/net/wireless/mwl8k.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/mwl8k.c	2017-05-14 16:49:10.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/mwl8k.c	2017-05-20 11:25:10.000000000 -0400
@@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee8
 
 static int
 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		   enum ieee80211_ampdu_mlme_action action,
-		   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		   u8 buf_size, bool amsdu)
+		   struct ieee80211_ampdu_params *params)
 {
-
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 	int i, rc = 0;
 	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_ampdu_stream *stream;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c linux-libre-4.4.69-gnu/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c	2017-05-14 16:52:10.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c	2017-05-20 11:28:50.000000000 -0400
@@ -5370,13 +5370,13 @@ static int rtl8xxxu_set_key(struct ieee8
 
 static int
 rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		      enum ieee80211_ampdu_mlme_action action,
-		      struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
-		      bool amsdu)
+		      struct ieee80211_ampdu_params *params)
 {
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
 	u8 ampdu_factor, ampdu_density;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
 
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/realtek/rtlwifi/core.c linux-libre-4.4.69-gnu/drivers/net/wireless/realtek/rtlwifi/core.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/realtek/rtlwifi/core.c	2017-05-14 16:52:11.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/realtek/rtlwifi/core.c	2017-05-20 11:28:53.000000000 -0400
@@ -1369,11 +1369,13 @@ static void rtl_op_sta_notify(struct iee
 
 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
-			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			       u8 buf_size, bool amsdu)
+			       struct ieee80211_ampdu_params *params)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c linux-libre-4.4.69-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/rsi/rsi_91x_mac80211.c	2017-05-20 08:27:22.000000000 -0400
@@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct i
  *				 informs the f/w regarding this.
  * @hw: Pointer to the ieee80211_hw structure.
  * @vif: Pointer to the ieee80211_vif structure.
- * @action: ieee80211_ampdu_mlme_action enum.
- * @sta: Pointer to the ieee80211_sta structure.
- * @tid: Traffic identifier.
- * @ssn: Pointer to ssn value.
- * @buf_size: Buffer size (for kernel version > 2.6.38).
- * @amsdu: is AMSDU in AMPDU allowed
+ * @params: Pointer to A-MPDU action parameters
  *
  * Return: status: 0 on success, negative error code on failure.
  */
 static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
-				     enum ieee80211_ampdu_mlme_action action,
-				     struct ieee80211_sta *sta,
-				     unsigned short tid,
-				     unsigned short *ssn,
-				     unsigned char buf_size,
-				     bool amsdu)
+				     struct ieee80211_ampdu_params *params)
 {
 	int status = -EOPNOTSUPP;
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
 	u16 seq_no = 0;
 	u8 ii = 0;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
+	u8 buf_size = params->buf_size;
 
 	for (ii = 0; ii < RSI_MAX_VIFS; ii++) {
 		if (vif == adapter->vifs[ii])
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/rt2x00/rt2800lib.c linux-libre-4.4.69-gnu/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2017-05-20 08:27:22.000000000 -0400
@@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *
 EXPORT_SYMBOL_GPL(rt2800_get_tsf);
 
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu)
+			struct ieee80211_ampdu_params *params)
 {
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
 	struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
 	int ret = 0;
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/rt2x00/rt2800lib.h linux-libre-4.4.69-gnu/drivers/net/wireless/rt2x00/rt2800lib.h
--- linux-libre-4.4.68-gnu/drivers/net/wireless/rt2x00/rt2800lib.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/rt2x00/rt2800lib.h	2017-05-20 08:27:22.000000000 -0400
@@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *
 		   const struct ieee80211_tx_queue_params *params);
 u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			u8 buf_size, bool amsdu);
+			struct ieee80211_ampdu_params *params);
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 		      struct survey_info *survey);
 void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wl18xx/event.c linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wl18xx/event.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wl18xx/event.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wl18xx/event.c	2017-05-20 08:27:22.000000000 -0400
@@ -206,5 +206,33 @@ int wl18xx_process_mailbox_events(struct
 						 mbox->sc_pwd_len,
 						 mbox->sc_pwd);
 
+	if (vector & RX_BA_WIN_SIZE_CHANGE_EVENT_ID) {
+		struct wl12xx_vif *wlvif;
+		struct ieee80211_vif *vif;
+		struct ieee80211_sta *sta;
+		u8 link_id = mbox->rx_ba_link_id;
+		u8 win_size = mbox->rx_ba_win_size;
+		const u8 *addr;
+
+		wlvif = wl->links[link_id].wlvif;
+		vif = wl12xx_wlvif_to_vif(wlvif);
+
+		/* Update RX aggregation window size and call
+		 * MAC routine to stop active RX aggregations for this link
+		 */
+		if (wlvif->bss_type != BSS_TYPE_AP_BSS)
+			addr = vif->bss_conf.bssid;
+		else
+			addr = wl->links[link_id].addr;
+
+		sta = ieee80211_find_sta(vif, addr);
+		if (sta) {
+			sta->max_rx_aggregation_subframes = win_size;
+			ieee80211_stop_rx_ba_session(vif,
+						wl->links[link_id].ba_bitmap,
+						addr);
+		}
+	}
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wl18xx/event.h linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wl18xx/event.h
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wl18xx/event.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wl18xx/event.h	2017-05-20 08:27:22.000000000 -0400
@@ -38,6 +38,7 @@ enum {
 	REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID      = BIT(18),
 	DFS_CHANNELS_CONFIG_COMPLETE_EVENT       = BIT(19),
 	PERIODIC_SCAN_REPORT_EVENT_ID            = BIT(20),
+	RX_BA_WIN_SIZE_CHANGE_EVENT_ID           = BIT(21),
 	SMART_CONFIG_SYNC_EVENT_ID               = BIT(22),
 	SMART_CONFIG_DECODE_EVENT_ID             = BIT(23),
 	TIME_SYNC_EVENT_ID                       = BIT(24),
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wl18xx/main.c linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wl18xx/main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wl18xx/main.c	2017-05-14 16:54:16.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wl18xx/main.c	2017-05-20 11:32:02.000000000 -0400
@@ -1029,7 +1029,8 @@ static int wl18xx_boot(struct wl1271 *wl
 		DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
 		SMART_CONFIG_SYNC_EVENT_ID |
 		SMART_CONFIG_DECODE_EVENT_ID |
-		TIME_SYNC_EVENT_ID;
+		TIME_SYNC_EVENT_ID |
+		RX_BA_WIN_SIZE_CHANGE_EVENT_ID;
 
 	wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wlcore/acx.c linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wlcore/acx.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wlcore/acx.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wlcore/acx.c	2017-05-20 08:27:22.000000000 -0400
@@ -1419,7 +1419,8 @@ out:
 
 /* setup BA session receiver setting in the FW. */
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
-				       u16 ssn, bool enable, u8 peer_hlid)
+				       u16 ssn, bool enable, u8 peer_hlid,
+				       u8 win_size)
 {
 	struct wl1271_acx_ba_receiver_setup *acx;
 	int ret;
@@ -1435,7 +1436,7 @@ int wl12xx_acx_set_ba_receiver_session(s
 	acx->hlid = peer_hlid;
 	acx->tid = tid_index;
 	acx->enable = enable;
-	acx->win_size = wl->conf.ht.rx_ba_win_size;
+	acx->win_size =	win_size;
 	acx->ssn = ssn;
 
 	ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx,
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wlcore/acx.h linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wlcore/acx.h
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wlcore/acx.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wlcore/acx.h	2017-05-20 08:27:22.000000000 -0400
@@ -1112,7 +1112,8 @@ int wl1271_acx_set_ht_information(struct
 int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
 				       struct wl12xx_vif *wlvif);
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
-				       u16 ssn, bool enable, u8 peer_hlid);
+				       u16 ssn, bool enable, u8 peer_hlid,
+				       u8 win_size);
 int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			u64 *mactime);
 int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wlcore/main.c linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wlcore/main.c
--- linux-libre-4.4.68-gnu/drivers/net/wireless/ti/wlcore/main.c	2017-05-14 16:54:24.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/net/wireless/ti/wlcore/main.c	2017-05-20 11:32:10.000000000 -0400
@@ -5261,14 +5261,16 @@ out:
 
 static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
-				  enum ieee80211_ampdu_mlme_action action,
-				  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-				  u8 buf_size, bool amsdu)
+				  struct ieee80211_ampdu_params *params)
 {
 	struct wl1271 *wl = hw->priv;
 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 	int ret;
 	u8 hlid, *ba_bitmap;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u16 *ssn = &params->ssn;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
 		     tid);
@@ -5326,7 +5328,9 @@ static int wl1271_op_ampdu_action(struct
 		}
 
 		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
-							 hlid);
+				hlid,
+				params->buf_size);
+
 		if (!ret) {
 			*ba_bitmap |= BIT(tid);
 			wl->ba_rx_session_count++;
@@ -5347,7 +5351,7 @@ static int wl1271_op_ampdu_action(struct
 		}
 
 		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
-							 hlid);
+							 hlid, 0);
 		if (!ret) {
 			*ba_bitmap &= ~BIT(tid);
 			wl->ba_rx_session_count--;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/staging/comedi/drivers/jr3_pci.c linux-libre-4.4.69-gnu/drivers/staging/comedi/drivers/jr3_pci.c
--- linux-libre-4.4.68-gnu/drivers/staging/comedi/drivers/jr3_pci.c	2017-05-14 16:59:14.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/staging/comedi/drivers/jr3_pci.c	2017-05-20 11:37:26.000000000 -0400
@@ -605,7 +605,7 @@ static void jr3_pci_poll_dev(unsigned lo
 		s = &dev->subdevices[i];
 		spriv = s->private;
 
-		if (now > spriv->next_time_min) {
+		if (time_after_eq(now, spriv->next_time_min)) {
 			struct jr3_pci_poll_delay sub_delay;
 
 			sub_delay = jr3_pci_poll_subdevice(s);
@@ -721,11 +721,12 @@ static int jr3_pci_auto_attach(struct co
 		s->insn_read	= jr3_pci_ai_insn_read;
 
 		spriv = jr3_pci_alloc_spriv(dev, s);
-		if (spriv) {
-			/* Channel specific range and maxdata */
-			s->range_table_list	= spriv->range_table_list;
-			s->maxdata_list		= spriv->maxdata_list;
-		}
+		if (!spriv)
+			return -ENOMEM;
+
+		/* Channel specific range and maxdata */
+		s->range_table_list	= spriv->range_table_list;
+		s->maxdata_list		= spriv->maxdata_list;
 	}
 
 	/*  Reset DSP card */
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/staging/gdm724x/gdm_mux.c linux-libre-4.4.69-gnu/drivers/staging/gdm724x/gdm_mux.c
--- linux-libre-4.4.68-gnu/drivers/staging/gdm724x/gdm_mux.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/staging/gdm724x/gdm_mux.c	2017-05-20 08:27:22.000000000 -0400
@@ -670,14 +670,14 @@ static int __init gdm_usb_mux_init(void)
 
 static void __exit gdm_usb_mux_exit(void)
 {
-	unregister_lte_tty_driver();
-
 	if (mux_rx_wq) {
 		flush_workqueue(mux_rx_wq);
 		destroy_workqueue(mux_rx_wq);
 	}
 
 	usb_deregister(&gdm_mux_driver);
+	unregister_lte_tty_driver();
+
 }
 
 module_init(gdm_usb_mux_init);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/staging/vt6656/usbpipe.c linux-libre-4.4.69-gnu/drivers/staging/vt6656/usbpipe.c
--- linux-libre-4.4.68-gnu/drivers/staging/vt6656/usbpipe.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/staging/vt6656/usbpipe.c	2017-05-20 08:27:22.000000000 -0400
@@ -50,15 +50,25 @@ int vnt_control_out(struct vnt_private *
 		u16 index, u16 length, u8 *buffer)
 {
 	int status = 0;
+	u8 *usb_buffer;
 
 	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
 		return STATUS_FAILURE;
 
 	mutex_lock(&priv->usb_lock);
 
+	usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
+	if (!usb_buffer) {
+		mutex_unlock(&priv->usb_lock);
+		return -ENOMEM;
+	}
+
 	status = usb_control_msg(priv->usb,
-		usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
-			index, buffer, length, USB_CTL_WAIT);
+				 usb_sndctrlpipe(priv->usb, 0),
+				 request, 0x40, value,
+				 index, usb_buffer, length, USB_CTL_WAIT);
+
+	kfree(usb_buffer);
 
 	mutex_unlock(&priv->usb_lock);
 
@@ -78,15 +88,28 @@ int vnt_control_in(struct vnt_private *p
 		u16 index, u16 length, u8 *buffer)
 {
 	int status;
+	u8 *usb_buffer;
 
 	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
 		return STATUS_FAILURE;
 
 	mutex_lock(&priv->usb_lock);
 
+	usb_buffer = kmalloc(length, GFP_KERNEL);
+	if (!usb_buffer) {
+		mutex_unlock(&priv->usb_lock);
+		return -ENOMEM;
+	}
+
 	status = usb_control_msg(priv->usb,
-		usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
-			index, buffer, length, USB_CTL_WAIT);
+				 usb_rcvctrlpipe(priv->usb, 0),
+				 request, 0xc0, value,
+				 index, usb_buffer, length, USB_CTL_WAIT);
+
+	if (status == length)
+		memcpy(buffer, usb_buffer, length);
+
+	kfree(usb_buffer);
 
 	mutex_unlock(&priv->usb_lock);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target.c linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target.c
--- linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target.c	2017-05-20 08:27:22.000000000 -0400
@@ -4821,6 +4821,7 @@ int iscsit_release_sessions_for_tpg(stru
 			continue;
 		}
 		atomic_set(&sess->session_reinstatement, 1);
+		atomic_set(&sess->session_fall_back_to_erl0, 1);
 		spin_unlock(&sess->conn_lock);
 
 		list_move_tail(&se_sess->sess_list, &free_list);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_configfs.c linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_configfs.c
--- linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_configfs.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_configfs.c	2017-05-20 08:27:22.000000000 -0400
@@ -725,11 +725,8 @@ static ssize_t lio_target_nacl_cmdsn_dep
 
 	if (iscsit_get_tpg(tpg) < 0)
 		return -EINVAL;
-	/*
-	 * iscsit_tpg_set_initiator_node_queue_depth() assumes force=1
-	 */
-	ret = iscsit_tpg_set_initiator_node_queue_depth(tpg,
-				config_item_name(acl_ci), cmdsn_depth, 1);
+
+	ret = core_tpg_set_initiator_node_queue_depth(se_nacl, cmdsn_depth);
 
 	pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for"
 		"InitiatorName: %s\n", config_item_name(wwn_ci),
@@ -1593,42 +1590,31 @@ static int lio_tpg_check_prot_fabric_onl
 }
 
 /*
- * Called with spin_lock_irq(struct se_portal_group->session_lock) held
- * or not held.
- *
- * Also, this function calls iscsit_inc_session_usage_count() on the
+ * This function calls iscsit_inc_session_usage_count() on the
  * struct iscsi_session in question.
  */
 static int lio_tpg_shutdown_session(struct se_session *se_sess)
 {
 	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
-	struct se_portal_group *se_tpg = se_sess->se_tpg;
-	bool local_lock = false;
-
-	if (!spin_is_locked(&se_tpg->session_lock)) {
-		spin_lock_irq(&se_tpg->session_lock);
-		local_lock = true;
-	}
+	struct se_portal_group *se_tpg = &sess->tpg->tpg_se_tpg;
 
+	spin_lock_bh(&se_tpg->session_lock);
 	spin_lock(&sess->conn_lock);
 	if (atomic_read(&sess->session_fall_back_to_erl0) ||
 	    atomic_read(&sess->session_logout) ||
 	    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
 		spin_unlock(&sess->conn_lock);
-		if (local_lock)
-			spin_unlock_irq(&sess->conn_lock);
+		spin_unlock_bh(&se_tpg->session_lock);
 		return 0;
 	}
 	atomic_set(&sess->session_reinstatement, 1);
+	atomic_set(&sess->session_fall_back_to_erl0, 1);
 	spin_unlock(&sess->conn_lock);
 
 	iscsit_stop_time2retain_timer(sess);
-	spin_unlock_irq(&se_tpg->session_lock);
+	spin_unlock_bh(&se_tpg->session_lock);
 
 	iscsit_stop_session(sess, 1, 1);
-	if (!local_lock)
-		spin_lock_irq(&se_tpg->session_lock);
-
 	return 1;
 }
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_login.c linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_login.c
--- linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_login.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_login.c	2017-05-20 08:27:22.000000000 -0400
@@ -195,6 +195,7 @@ int iscsi_check_for_session_reinstatemen
 			    initiatorname_param->value) &&
 		   (sess_p->sess_ops->SessionType == sessiontype))) {
 			atomic_set(&sess_p->session_reinstatement, 1);
+			atomic_set(&sess_p->session_fall_back_to_erl0, 1);
 			spin_unlock(&sess_p->conn_lock);
 			iscsit_inc_session_usage_count(sess_p);
 			iscsit_stop_time2retain_timer(sess_p);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_tpg.c linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_tpg.c
--- linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_tpg.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_tpg.c	2017-05-20 08:27:22.000000000 -0400
@@ -589,16 +589,6 @@ int iscsit_tpg_del_network_portal(
 	return iscsit_tpg_release_np(tpg_np, tpg, np);
 }
 
-int iscsit_tpg_set_initiator_node_queue_depth(
-	struct iscsi_portal_group *tpg,
-	unsigned char *initiatorname,
-	u32 queue_depth,
-	int force)
-{
-	return core_tpg_set_initiator_node_queue_depth(&tpg->tpg_se_tpg,
-		initiatorname, queue_depth, force);
-}
-
 int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
 {
 	unsigned char buf1[256], buf2[256], *none = NULL;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_tpg.h linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_tpg.h
--- linux-libre-4.4.68-gnu/drivers/target/iscsi/iscsi_target_tpg.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/iscsi/iscsi_target_tpg.h	2017-05-20 08:27:22.000000000 -0400
@@ -26,8 +26,6 @@ extern struct iscsi_tpg_np *iscsit_tpg_a
 			int);
 extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
 			struct iscsi_tpg_np *);
-extern int iscsit_tpg_set_initiator_node_queue_depth(struct iscsi_portal_group *,
-			unsigned char *, u32, int);
 extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_login_timeout(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_netif_timeout(struct iscsi_portal_group *, u32);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/target_core_file.c linux-libre-4.4.69-gnu/drivers/target/target_core_file.c
--- linux-libre-4.4.68-gnu/drivers/target/target_core_file.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/target_core_file.c	2017-05-20 08:27:22.000000000 -0400
@@ -594,8 +594,7 @@ fd_execute_rw(struct se_cmd *cmd, struct
 	if (ret < 0)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	if (ret)
-		target_complete_cmd(cmd, SAM_STAT_GOOD);
+	target_complete_cmd(cmd, SAM_STAT_GOOD);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/target_core_sbc.c linux-libre-4.4.69-gnu/drivers/target/target_core_sbc.c
--- linux-libre-4.4.68-gnu/drivers/target/target_core_sbc.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/target_core_sbc.c	2017-05-20 08:27:22.000000000 -0400
@@ -498,8 +498,11 @@ static sense_reason_t compare_and_write_
 	 * been failed with a non-zero SCSI status.
 	 */
 	if (cmd->scsi_status) {
-		pr_err("compare_and_write_callback: non zero scsi_status:"
+		pr_debug("compare_and_write_callback: non zero scsi_status:"
 			" 0x%02x\n", cmd->scsi_status);
+		*post_ret = 1;
+		if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		goto out;
 	}
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/target_core_tpg.c linux-libre-4.4.69-gnu/drivers/target/target_core_tpg.c
--- linux-libre-4.4.68-gnu/drivers/target/target_core_tpg.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/target_core_tpg.c	2017-05-20 08:27:22.000000000 -0400
@@ -169,28 +169,25 @@ void core_tpg_add_node_to_devs(
 	mutex_unlock(&tpg->tpg_lun_mutex);
 }
 
-/*      core_set_queue_depth_for_node():
- *
- *
- */
-static int core_set_queue_depth_for_node(
-	struct se_portal_group *tpg,
-	struct se_node_acl *acl)
+static void
+target_set_nacl_queue_depth(struct se_portal_group *tpg,
+			    struct se_node_acl *acl, u32 queue_depth)
 {
+	acl->queue_depth = queue_depth;
+
 	if (!acl->queue_depth) {
-		pr_err("Queue depth for %s Initiator Node: %s is 0,"
+		pr_warn("Queue depth for %s Initiator Node: %s is 0,"
 			"defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(),
 			acl->initiatorname);
 		acl->queue_depth = 1;
 	}
-
-	return 0;
 }
 
 static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg,
 		const unsigned char *initiatorname)
 {
 	struct se_node_acl *acl;
+	u32 queue_depth;
 
 	acl = kzalloc(max(sizeof(*acl), tpg->se_tpg_tfo->node_acl_size),
 			GFP_KERNEL);
@@ -205,24 +202,20 @@ static struct se_node_acl *target_alloc_
 	spin_lock_init(&acl->nacl_sess_lock);
 	mutex_init(&acl->lun_entry_mutex);
 	atomic_set(&acl->acl_pr_ref_count, 0);
+
 	if (tpg->se_tpg_tfo->tpg_get_default_depth)
-		acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
+		queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
 	else
-		acl->queue_depth = 1;
+		queue_depth = 1;
+	target_set_nacl_queue_depth(tpg, acl, queue_depth);
+
 	snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
 	acl->se_tpg = tpg;
 	acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
 
 	tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
-	if (core_set_queue_depth_for_node(tpg, acl) < 0)
-		goto out_free_acl;
-
 	return acl;
-
-out_free_acl:
-	kfree(acl);
-	return NULL;
 }
 
 static void target_add_node_acl(struct se_node_acl *acl)
@@ -369,7 +362,8 @@ void core_tpg_del_initiator_node_acl(str
 		if (sess->sess_tearing_down != 0)
 			continue;
 
-		target_get_session(sess);
+		if (!target_get_session(sess))
+			continue;
 		list_move(&sess->sess_acl_list, &sess_list);
 	}
 	spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
@@ -406,108 +400,52 @@ void core_tpg_del_initiator_node_acl(str
  *
  */
 int core_tpg_set_initiator_node_queue_depth(
-	struct se_portal_group *tpg,
-	unsigned char *initiatorname,
-	u32 queue_depth,
-	int force)
+	struct se_node_acl *acl,
+	u32 queue_depth)
 {
-	struct se_session *sess, *init_sess = NULL;
-	struct se_node_acl *acl;
+	LIST_HEAD(sess_list);
+	struct se_portal_group *tpg = acl->se_tpg;
+	struct se_session *sess, *sess_tmp;
 	unsigned long flags;
-	int dynamic_acl = 0;
-
-	mutex_lock(&tpg->acl_node_mutex);
-	acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if (!acl) {
-		pr_err("Access Control List entry for %s Initiator"
-			" Node %s does not exists for TPG %hu, ignoring"
-			" request.\n", tpg->se_tpg_tfo->get_fabric_name(),
-			initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
-		mutex_unlock(&tpg->acl_node_mutex);
-		return -ENODEV;
-	}
-	if (acl->dynamic_node_acl) {
-		acl->dynamic_node_acl = 0;
-		dynamic_acl = 1;
-	}
-	mutex_unlock(&tpg->acl_node_mutex);
-
-	spin_lock_irqsave(&tpg->session_lock, flags);
-	list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
-		if (sess->se_node_acl != acl)
-			continue;
-
-		if (!force) {
-			pr_err("Unable to change queue depth for %s"
-				" Initiator Node: %s while session is"
-				" operational.  To forcefully change the queue"
-				" depth and force session reinstatement"
-				" use the \"force=1\" parameter.\n",
-				tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
-			spin_unlock_irqrestore(&tpg->session_lock, flags);
-
-			mutex_lock(&tpg->acl_node_mutex);
-			if (dynamic_acl)
-				acl->dynamic_node_acl = 1;
-			mutex_unlock(&tpg->acl_node_mutex);
-			return -EEXIST;
-		}
-		/*
-		 * Determine if the session needs to be closed by our context.
-		 */
-		if (!tpg->se_tpg_tfo->shutdown_session(sess))
-			continue;
-
-		init_sess = sess;
-		break;
-	}
+	int rc;
 
 	/*
 	 * User has requested to change the queue depth for a Initiator Node.
 	 * Change the value in the Node's struct se_node_acl, and call
-	 * core_set_queue_depth_for_node() to add the requested queue depth.
-	 *
-	 * Finally call  tpg->se_tpg_tfo->close_session() to force session
-	 * reinstatement to occur if there is an active session for the
-	 * $FABRIC_MOD Initiator Node in question.
+	 * target_set_nacl_queue_depth() to set the new queue depth.
 	 */
-	acl->queue_depth = queue_depth;
+	target_set_nacl_queue_depth(tpg, acl, queue_depth);
+
+	spin_lock_irqsave(&acl->nacl_sess_lock, flags);
+	list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list,
+				 sess_acl_list) {
+		if (sess->sess_tearing_down != 0)
+			continue;
+		if (!target_get_session(sess))
+			continue;
+		spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
 
-	if (core_set_queue_depth_for_node(tpg, acl) < 0) {
-		spin_unlock_irqrestore(&tpg->session_lock, flags);
 		/*
-		 * Force session reinstatement if
-		 * core_set_queue_depth_for_node() failed, because we assume
-		 * the $FABRIC_MOD has already the set session reinstatement
-		 * bit from tpg->se_tpg_tfo->shutdown_session() called above.
+		 * Finally call tpg->se_tpg_tfo->close_session() to force session
+		 * reinstatement to occur if there is an active session for the
+		 * $FABRIC_MOD Initiator Node in question.
 		 */
-		if (init_sess)
-			tpg->se_tpg_tfo->close_session(init_sess);
-
-		mutex_lock(&tpg->acl_node_mutex);
-		if (dynamic_acl)
-			acl->dynamic_node_acl = 1;
-		mutex_unlock(&tpg->acl_node_mutex);
-		return -EINVAL;
+		rc = tpg->se_tpg_tfo->shutdown_session(sess);
+		target_put_session(sess);
+		if (!rc) {
+			spin_lock_irqsave(&acl->nacl_sess_lock, flags);
+			continue;
+		}
+		target_put_session(sess);
+		spin_lock_irqsave(&acl->nacl_sess_lock, flags);
 	}
-	spin_unlock_irqrestore(&tpg->session_lock, flags);
-	/*
-	 * If the $FABRIC_MOD session for the Initiator Node ACL exists,
-	 * forcefully shutdown the $FABRIC_MOD session/nexus.
-	 */
-	if (init_sess)
-		tpg->se_tpg_tfo->close_session(init_sess);
+	spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
 
 	pr_debug("Successfully changed queue depth to: %d for Initiator"
-		" Node: %s on %s Target Portal Group: %u\n", queue_depth,
-		initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
+		" Node: %s on %s Target Portal Group: %u\n", acl->queue_depth,
+		acl->initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
 		tpg->se_tpg_tfo->tpg_get_tag(tpg));
 
-	mutex_lock(&tpg->acl_node_mutex);
-	if (dynamic_acl)
-		acl->dynamic_node_acl = 1;
-	mutex_unlock(&tpg->acl_node_mutex);
-
 	return 0;
 }
 EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/target/target_core_transport.c linux-libre-4.4.69-gnu/drivers/target/target_core_transport.c
--- linux-libre-4.4.68-gnu/drivers/target/target_core_transport.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/target/target_core_transport.c	2017-05-20 08:27:22.000000000 -0400
@@ -383,9 +383,9 @@ static void target_release_session(struc
 	se_tpg->se_tpg_tfo->close_session(se_sess);
 }
 
-void target_get_session(struct se_session *se_sess)
+int target_get_session(struct se_session *se_sess)
 {
-	kref_get(&se_sess->sess_kref);
+	return kref_get_unless_zero(&se_sess->sess_kref);
 }
 EXPORT_SYMBOL(target_get_session);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/tty/pty.c linux-libre-4.4.69-gnu/drivers/tty/pty.c
--- linux-libre-4.4.68-gnu/drivers/tty/pty.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/tty/pty.c	2017-05-20 08:27:22.000000000 -0400
@@ -216,16 +216,11 @@ static int pty_signal(struct tty_struct
 static void pty_flush_buffer(struct tty_struct *tty)
 {
 	struct tty_struct *to = tty->link;
-	struct tty_ldisc *ld;
 
 	if (!to)
 		return;
 
-	ld = tty_ldisc_ref(to);
-	tty_buffer_flush(to, ld);
-	if (ld)
-		tty_ldisc_deref(ld);
-
+	tty_buffer_flush(to, NULL);
 	if (to->packet) {
 		spin_lock_irq(&tty->ctrl_lock);
 		tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/tty/serial/omap-serial.c linux-libre-4.4.69-gnu/drivers/tty/serial/omap-serial.c
--- linux-libre-4.4.68-gnu/drivers/tty/serial/omap-serial.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/tty/serial/omap-serial.c	2017-05-20 08:27:22.000000000 -0400
@@ -1712,7 +1712,8 @@ static int serial_omap_probe(struct plat
 	return 0;
 
 err_add_port:
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_qos_remove_request(&up->pm_qos_request);
 	device_init_wakeup(up->dev, false);
@@ -1725,9 +1726,13 @@ static int serial_omap_remove(struct pla
 {
 	struct uart_omap_port *up = platform_get_drvdata(dev);
 
+	pm_runtime_get_sync(up->dev);
+
+	uart_remove_one_port(&serial_omap_reg, &up->port);
+
+	pm_runtime_dont_use_autosuspend(up->dev);
 	pm_runtime_put_sync(up->dev);
 	pm_runtime_disable(up->dev);
-	uart_remove_one_port(&serial_omap_reg, &up->port);
 	pm_qos_remove_request(&up->pm_qos_request);
 	device_init_wakeup(&dev->dev, false);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/tty/serial/samsung.c linux-libre-4.4.69-gnu/drivers/tty/serial/samsung.c
--- linux-libre-4.4.68-gnu/drivers/tty/serial/samsung.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/tty/serial/samsung.c	2017-05-20 08:27:22.000000000 -0400
@@ -900,14 +900,13 @@ static int s3c24xx_serial_request_dma(st
 		return -ENOMEM;
 	}
 
-	dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
+	dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
 				dma->rx_size, DMA_FROM_DEVICE);
 
 	spin_lock_irqsave(&p->port.lock, flags);
 
 	/* TX buffer */
-	dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
-				p->port.state->xmit.buf,
+	dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 
 	spin_unlock_irqrestore(&p->port.lock, flags);
@@ -921,7 +920,7 @@ static void s3c24xx_serial_release_dma(s
 
 	if (dma->rx_chan) {
 		dmaengine_terminate_all(dma->rx_chan);
-		dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+		dma_unmap_single(p->port.dev, dma->rx_addr,
 				dma->rx_size, DMA_FROM_DEVICE);
 		kfree(dma->rx_buf);
 		dma_release_channel(dma->rx_chan);
@@ -930,7 +929,7 @@ static void s3c24xx_serial_release_dma(s
 
 	if (dma->tx_chan) {
 		dmaengine_terminate_all(dma->tx_chan);
-		dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
+		dma_unmap_single(p->port.dev, dma->tx_addr,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 		dma_release_channel(dma->tx_chan);
 		dma->tx_chan = NULL;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/core/driver.c linux-libre-4.4.69-gnu/drivers/usb/core/driver.c
--- linux-libre-4.4.68-gnu/drivers/usb/core/driver.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/core/driver.c	2017-05-20 08:27:22.000000000 -0400
@@ -1328,6 +1328,24 @@ static int usb_suspend_both(struct usb_d
 		 */
 		if (udev->parent && !PMSG_IS_AUTO(msg))
 			status = 0;
+
+		/*
+		 * If the device is inaccessible, don't try to resume
+		 * suspended interfaces and just return the error.
+		 */
+		if (status && status != -EBUSY) {
+			int err;
+			u16 devstat;
+
+			err = usb_get_status(udev, USB_RECIP_DEVICE, 0,
+					     &devstat);
+			if (err) {
+				dev_err(&udev->dev,
+					"Failed to suspend device, error %d\n",
+					status);
+				goto done;
+			}
+		}
 	}
 
 	/* If the suspend failed, resume interfaces that did get suspended */
@@ -1760,6 +1778,9 @@ static int autosuspend_check(struct usb_
 	int			w, i;
 	struct usb_interface	*intf;
 
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
+
 	/* Fail if autosuspend is disabled, or any interfaces are in use, or
 	 * any interface drivers require remote wakeup but it isn't available.
 	 */
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/core/file.c linux-libre-4.4.69-gnu/drivers/usb/core/file.c
--- linux-libre-4.4.68-gnu/drivers/usb/core/file.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/core/file.c	2017-05-20 08:27:22.000000000 -0400
@@ -26,6 +26,7 @@
 #define MAX_USB_MINORS	256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
 static DECLARE_RWSEM(minor_rwsem);
+static DEFINE_MUTEX(init_usb_class_mutex);
 
 static int usb_open(struct inode *inode, struct file *file)
 {
@@ -108,8 +109,9 @@ static void release_usb_class(struct kre
 
 static void destroy_usb_class(void)
 {
-	if (usb_class)
-		kref_put(&usb_class->kref, release_usb_class);
+	mutex_lock(&init_usb_class_mutex);
+	kref_put(&usb_class->kref, release_usb_class);
+	mutex_unlock(&init_usb_class_mutex);
 }
 
 int usb_major_init(void)
@@ -171,7 +173,10 @@ int usb_register_dev(struct usb_interfac
 	if (intf->minor >= 0)
 		return -EADDRINUSE;
 
+	mutex_lock(&init_usb_class_mutex);
 	retval = init_usb_class();
+	mutex_unlock(&init_usb_class_mutex);
+
 	if (retval)
 		return retval;
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/core/hub.c linux-libre-4.4.69-gnu/drivers/usb/core/hub.c
--- linux-libre-4.4.68-gnu/drivers/usb/core/hub.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/core/hub.c	2017-05-20 08:27:22.000000000 -0400
@@ -1048,6 +1048,9 @@ static void hub_activate(struct usb_hub
 
 		portstatus = portchange = 0;
 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+		if (status)
+			goto abort;
+
 		if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
 			dev_dbg(&port_dev->dev, "status %04x change %04x\n",
 					portstatus, portchange);
@@ -1180,7 +1183,7 @@ static void hub_activate(struct usb_hub
 
 	/* Scan all ports that need attention */
 	kick_hub_wq(hub);
-
+ abort:
 	if (type == HUB_INIT2 || type == HUB_INIT3) {
 		/* Allow autosuspend if it was suppressed */
  disconnected:
@@ -2068,6 +2071,12 @@ void usb_disconnect(struct usb_device **
 	dev_info(&udev->dev, "USB disconnect, device number %d\n",
 			udev->devnum);
 
+	/*
+	 * Ensure that the pm runtime code knows that the USB device
+	 * is in the process of being disconnected.
+	 */
+	pm_runtime_barrier(&udev->dev);
+
 	usb_lock_device(udev);
 
 	hub_disconnect_children(udev);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/host/xhci-mem.c linux-libre-4.4.69-gnu/drivers/usb/host/xhci-mem.c
--- linux-libre-4.4.68-gnu/drivers/usb/host/xhci-mem.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/host/xhci-mem.c	2017-05-20 08:27:22.000000000 -0400
@@ -2493,7 +2493,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
 		(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
 		xhci->cmd_ring->cycle_state;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Setting command ring address to 0x%x", val);
+			"// Setting command ring address to 0x%016llx", val_64);
 	xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
 	xhci_dbg_cmd_ptrs(xhci);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/misc/usbtest.c linux-libre-4.4.69-gnu/drivers/usb/misc/usbtest.c
--- linux-libre-4.4.68-gnu/drivers/usb/misc/usbtest.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/misc/usbtest.c	2017-05-20 08:27:22.000000000 -0400
@@ -135,6 +135,7 @@ get_endpoints(struct usbtest_dev *dev, s
 			case USB_ENDPOINT_XFER_INT:
 				if (dev->info->intr)
 					goto try_intr;
+				continue;
 			case USB_ENDPOINT_XFER_ISOC:
 				if (dev->info->iso)
 					goto try_iso;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/serial/ftdi_sio.c linux-libre-4.4.69-gnu/drivers/usb/serial/ftdi_sio.c
--- linux-libre-4.4.68-gnu/drivers/usb/serial/ftdi_sio.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/serial/ftdi_sio.c	2017-05-20 08:27:22.000000000 -0400
@@ -873,6 +873,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
 					USB_CLASS_VENDOR_SPEC,
 					USB_SUBCLASS_VENDOR_SPEC, 0x00) },
+	{ USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) },
 	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
 	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/usb/serial/ftdi_sio_ids.h linux-libre-4.4.69-gnu/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-4.4.68-gnu/drivers/usb/serial/ftdi_sio_ids.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/usb/serial/ftdi_sio_ids.h	2017-05-20 08:27:22.000000000 -0400
@@ -873,6 +873,12 @@
 #define	FIC_VID			0x1457
 #define	FIC_NEO1973_DEBUG_PID	0x5118
 
+/*
+ * Actel / Microsemi
+ */
+#define ACTEL_VID				0x1514
+#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID	0x2008
+
 /* Olimex */
 #define OLIMEX_VID			0x15BA
 #define OLIMEX_ARM_USB_OCD_PID		0x0003
diff -druNp --no-dereference linux-libre-4.4.68-gnu/drivers/vfio/vfio_iommu_type1.c linux-libre-4.4.69-gnu/drivers/vfio/vfio_iommu_type1.c
--- linux-libre-4.4.68-gnu/drivers/vfio/vfio_iommu_type1.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/drivers/vfio/vfio_iommu_type1.c	2017-05-20 08:27:22.000000000 -0400
@@ -130,57 +130,34 @@ static void vfio_unlink_dma(struct vfio_
 	rb_erase(&old->node, &iommu->dma_list);
 }
 
-struct vwork {
-	struct mm_struct	*mm;
-	long			npage;
-	struct work_struct	work;
-};
-
-/* delayed decrement/increment for locked_vm */
-static void vfio_lock_acct_bg(struct work_struct *work)
+static int vfio_lock_acct(long npage, bool *lock_cap)
 {
-	struct vwork *vwork = container_of(work, struct vwork, work);
-	struct mm_struct *mm;
+	int ret = 0;
 
-	mm = vwork->mm;
-	down_write(&mm->mmap_sem);
-	mm->locked_vm += vwork->npage;
-	up_write(&mm->mmap_sem);
-	mmput(mm);
-	kfree(vwork);
-}
+	if (!npage)
+		return 0;
 
-static void vfio_lock_acct(long npage)
-{
-	struct vwork *vwork;
-	struct mm_struct *mm;
+	if (!current->mm)
+		return -ESRCH; /* process exited */
 
-	if (!current->mm || !npage)
-		return; /* process exited or nothing to do */
+	down_write(&current->mm->mmap_sem);
+	if (npage > 0) {
+		if (lock_cap ? !*lock_cap : !capable(CAP_IPC_LOCK)) {
+			unsigned long limit;
 
-	if (down_write_trylock(&current->mm->mmap_sem)) {
-		current->mm->locked_vm += npage;
-		up_write(&current->mm->mmap_sem);
-		return;
-	}
+			limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 
-	/*
-	 * Couldn't get mmap_sem lock, so must setup to update
-	 * mm->locked_vm later. If locked_vm were atomic, we
-	 * wouldn't need this silliness
-	 */
-	vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
-	if (!vwork)
-		return;
-	mm = get_task_mm(current);
-	if (!mm) {
-		kfree(vwork);
-		return;
+			if (current->mm->locked_vm + npage > limit)
+				ret = -ENOMEM;
+		}
 	}
-	INIT_WORK(&vwork->work, vfio_lock_acct_bg);
-	vwork->mm = mm;
-	vwork->npage = npage;
-	schedule_work(&vwork->work);
+
+	if (!ret)
+		current->mm->locked_vm += npage;
+
+	up_write(&current->mm->mmap_sem);
+
+	return ret;
 }
 
 /*
@@ -262,9 +239,9 @@ static int vaddr_get_pfn(unsigned long v
 static long vfio_pin_pages(unsigned long vaddr, long npage,
 			   int prot, unsigned long *pfn_base)
 {
-	unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+	unsigned long pfn = 0, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 	bool lock_cap = capable(CAP_IPC_LOCK);
-	long ret, i;
+	long ret, i = 1;
 	bool rsvd;
 
 	if (!current->mm)
@@ -283,16 +260,11 @@ static long vfio_pin_pages(unsigned long
 		return -ENOMEM;
 	}
 
-	if (unlikely(disable_hugepages)) {
-		if (!rsvd)
-			vfio_lock_acct(1);
-		return 1;
-	}
+	if (unlikely(disable_hugepages))
+		goto out;
 
 	/* Lock all the consecutive pages from pfn_base */
-	for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
-		unsigned long pfn = 0;
-
+	for (vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
 		ret = vaddr_get_pfn(vaddr, prot, &pfn);
 		if (ret)
 			break;
@@ -308,12 +280,24 @@ static long vfio_pin_pages(unsigned long
 			put_pfn(pfn, prot);
 			pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
 				__func__, limit << PAGE_SHIFT);
-			break;
+			ret = -ENOMEM;
+			goto unpin_out;
 		}
 	}
 
+out:
 	if (!rsvd)
-		vfio_lock_acct(i);
+		ret = vfio_lock_acct(i, &lock_cap);
+
+unpin_out:
+	if (ret) {
+		if (!rsvd) {
+			for (pfn = *pfn_base ; i ; pfn++, i--)
+				put_pfn(pfn, prot);
+		}
+
+		return ret;
+	}
 
 	return i;
 }
@@ -328,7 +312,7 @@ static long vfio_unpin_pages(unsigned lo
 		unlocked += put_pfn(pfn++, prot);
 
 	if (do_accounting)
-		vfio_lock_acct(-unlocked);
+		vfio_lock_acct(-unlocked, NULL);
 
 	return unlocked;
 }
@@ -390,7 +374,7 @@ static void vfio_unmap_unpin(struct vfio
 		cond_resched();
 	}
 
-	vfio_lock_acct(-unlocked);
+	vfio_lock_acct(-unlocked, NULL);
 }
 
 static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/block_dev.c linux-libre-4.4.69-gnu/fs/block_dev.c
--- linux-libre-4.4.68-gnu/fs/block_dev.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/block_dev.c	2017-05-20 08:27:22.000000000 -0400
@@ -88,12 +88,11 @@ void invalidate_bdev(struct block_device
 {
 	struct address_space *mapping = bdev->bd_inode->i_mapping;
 
-	if (mapping->nrpages == 0)
-		return;
-
-	invalidate_bh_lrus();
-	lru_add_drain_all();	/* make sure all lru add caches are flushed */
-	invalidate_mapping_pages(mapping, 0, -1);
+	if (mapping->nrpages) {
+		invalidate_bh_lrus();
+		lru_add_drain_all();	/* make sure all lru add caches are flushed */
+		invalidate_mapping_pages(mapping, 0, -1);
+	}
 	/* 99% of the time, we don't need to flush the cleancache on the bdev.
 	 * But, for the strange corners, lets be cautious
 	 */
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/ceph/xattr.c linux-libre-4.4.69-gnu/fs/ceph/xattr.c
--- linux-libre-4.4.68-gnu/fs/ceph/xattr.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/ceph/xattr.c	2017-05-20 08:27:22.000000000 -0400
@@ -369,6 +369,7 @@ static int __set_xattr(struct ceph_inode
 
 	if (update_xattr) {
 		int err = 0;
+
 		if (xattr && (flags & XATTR_CREATE))
 			err = -EEXIST;
 		else if (!xattr && (flags & XATTR_REPLACE))
@@ -376,12 +377,14 @@ static int __set_xattr(struct ceph_inode
 		if (err) {
 			kfree(name);
 			kfree(val);
+			kfree(*newxattr);
 			return err;
 		}
 		if (update_xattr < 0) {
 			if (xattr)
 				__remove_xattr(ci, xattr);
 			kfree(name);
+			kfree(*newxattr);
 			return 0;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/cifs/cifssmb.c linux-libre-4.4.69-gnu/fs/cifs/cifssmb.c
--- linux-libre-4.4.68-gnu/fs/cifs/cifssmb.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/cifs/cifssmb.c	2017-05-20 08:27:22.000000000 -0400
@@ -717,6 +717,9 @@ CIFSSMBEcho(struct TCP_Server_Info *serv
 	if (rc)
 		return rc;
 
+	if (server->capabilities & CAP_UNICODE)
+		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
+
 	/* set up echo request */
 	smb->hdr.Tid = 0xffff;
 	smb->hdr.WordCount = 1;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/cifs/cifs_unicode.c linux-libre-4.4.69-gnu/fs/cifs/cifs_unicode.c
--- linux-libre-4.4.68-gnu/fs/cifs/cifs_unicode.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/cifs/cifs_unicode.c	2017-05-20 08:27:22.000000000 -0400
@@ -83,6 +83,9 @@ convert_sfm_char(const __u16 src_char, c
 	case SFM_COLON:
 		*target = ':';
 		break;
+	case SFM_DOUBLEQUOTE:
+		*target = '"';
+		break;
 	case SFM_ASTERISK:
 		*target = '*';
 		break;
@@ -418,6 +421,9 @@ static __le16 convert_to_sfm_char(char s
 	case ':':
 		dest_char = cpu_to_le16(SFM_COLON);
 		break;
+	case '"':
+		dest_char = cpu_to_le16(SFM_DOUBLEQUOTE);
+		break;
 	case '*':
 		dest_char = cpu_to_le16(SFM_ASTERISK);
 		break;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/cifs/cifs_unicode.h linux-libre-4.4.69-gnu/fs/cifs/cifs_unicode.h
--- linux-libre-4.4.68-gnu/fs/cifs/cifs_unicode.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/cifs/cifs_unicode.h	2017-05-20 08:27:22.000000000 -0400
@@ -57,6 +57,7 @@
  * not conflict (although almost does) with the mapping above.
  */
 
+#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
 #define SFM_ASTERISK    ((__u16) 0xF021)
 #define SFM_QUESTION    ((__u16) 0xF025)
 #define SFM_COLON       ((__u16) 0xF022)
@@ -64,8 +65,8 @@
 #define SFM_LESSTHAN    ((__u16) 0xF023)
 #define SFM_PIPE        ((__u16) 0xF027)
 #define SFM_SLASH       ((__u16) 0xF026)
-#define SFM_PERIOD	((__u16) 0xF028)
-#define SFM_SPACE	((__u16) 0xF029)
+#define SFM_SPACE	((__u16) 0xF028)
+#define SFM_PERIOD	((__u16) 0xF029)
 
 /*
  * Mapping mechanism to use when one of the seven reserved characters is
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/cifs/ioctl.c linux-libre-4.4.69-gnu/fs/cifs/ioctl.c
--- linux-libre-4.4.68-gnu/fs/cifs/ioctl.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/cifs/ioctl.c	2017-05-20 08:27:22.000000000 -0400
@@ -272,6 +272,8 @@ long cifs_ioctl(struct file *filep, unsi
 				rc = -EOPNOTSUPP;
 			break;
 		case CIFS_IOC_GET_MNT_INFO:
+			if (pSMBFile == NULL)
+				break;
 			tcon = tlink_tcon(pSMBFile->tlink);
 			rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
 			break;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/cifs/smb2pdu.c linux-libre-4.4.69-gnu/fs/cifs/smb2pdu.c
--- linux-libre-4.4.68-gnu/fs/cifs/smb2pdu.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/cifs/smb2pdu.c	2017-05-20 08:27:22.000000000 -0400
@@ -564,8 +564,12 @@ int smb3_validate_negotiate(const unsign
 	}
 
 	if (rsplen != sizeof(struct validate_negotiate_info_rsp)) {
-		cifs_dbg(VFS, "invalid size of protocol negotiate response\n");
-		return -EIO;
+		cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n",
+			 rsplen);
+
+		/* relax check since Mac returns max bufsize allowed on ioctl */
+		if (rsplen > CIFSMaxBufSize)
+			return -EIO;
 	}
 
 	/* check validate negotiate info response matches what we got earlier */
@@ -1518,8 +1522,12 @@ SMB2_ioctl(const unsigned int xid, struc
 	 * than one credit. Windows typically sets this smaller, but for some
 	 * ioctls it may be useful to allow server to send more. No point
 	 * limiting what the server can send as long as fits in one credit
+	 * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
+	 * (by default, note that it can be overridden to make max larger)
+	 * in responses (except for read responses which can be bigger.
+	 * We may want to bump this limit up
 	 */
-	req->MaxOutputResponse = cpu_to_le32(0xFF00); /* < 64K uses 1 credit */
+	req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize);
 
 	if (is_fsctl)
 		req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/ext4/inode.c linux-libre-4.4.69-gnu/fs/ext4/inode.c
--- linux-libre-4.4.68-gnu/fs/ext4/inode.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/ext4/inode.c	2017-05-20 08:27:22.000000000 -0400
@@ -5393,6 +5393,11 @@ int ext4_page_mkwrite(struct vm_area_str
 	file_update_time(vma->vm_file);
 
 	down_read(&EXT4_I(inode)->i_mmap_sem);
+
+	ret = ext4_convert_inline_data(inode);
+	if (ret)
+		goto out_ret;
+
 	/* Delalloc case is easy... */
 	if (test_opt(inode->i_sb, DELALLOC) &&
 	    !ext4_should_journal_data(inode) &&
diff -druNp --no-dereference linux-libre-4.4.68-gnu/fs/xattr.c linux-libre-4.4.69-gnu/fs/xattr.c
--- linux-libre-4.4.68-gnu/fs/xattr.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/fs/xattr.c	2017-05-20 08:27:22.000000000 -0400
@@ -442,7 +442,7 @@ getxattr(struct dentry *d, const char __
 			size = XATTR_SIZE_MAX;
 		kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
 		if (!kvalue) {
-			vvalue = vmalloc(size);
+			vvalue = vzalloc(size);
 			if (!vvalue)
 				return -ENOMEM;
 			kvalue = vvalue;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/include/net/mac80211.h linux-libre-4.4.69-gnu/include/net/mac80211.h
--- linux-libre-4.4.68-gnu/include/net/mac80211.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/include/net/mac80211.h	2017-05-20 08:27:22.000000000 -0400
@@ -1662,6 +1662,9 @@ struct ieee80211_sta_rates {
  * @supp_rates: Bitmap of supported rates (per band)
  * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
  * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
+ * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU
+ *	that this station is allowed to transmit to us.
+ *	Can be modified by driver.
  * @wme: indicates whether the STA supports QoS/WME (if local devices does,
  *	otherwise always false)
  * @drv_priv: data area for driver use, will always be aligned to
@@ -1688,6 +1691,7 @@ struct ieee80211_sta {
 	u16 aid;
 	struct ieee80211_sta_ht_cap ht_cap;
 	struct ieee80211_sta_vht_cap vht_cap;
+	u8 max_rx_aggregation_subframes;
 	bool wme;
 	u8 uapsd_queues;
 	u8 max_sp;
@@ -2674,6 +2678,33 @@ enum ieee80211_ampdu_mlme_action {
 };
 
 /**
+ * struct ieee80211_ampdu_params - AMPDU action parameters
+ *
+ * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action.
+ * @sta: peer of this AMPDU session
+ * @tid: tid of the BA session
+ * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When
+ *	action is set to %IEEE80211_AMPDU_RX_START the driver passes back the
+ *	actual ssn value used to start the session and writes the value here.
+ * @buf_size: reorder buffer size  (number of subframes). Valid only when the
+ *	action is set to %IEEE80211_AMPDU_RX_START or
+ *	%IEEE80211_AMPDU_TX_OPERATIONAL
+ * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU.
+ *	valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL
+ * @timeout: BA session timeout. Valid only when the action is set to
+ *	%IEEE80211_AMPDU_RX_START
+ */
+struct ieee80211_ampdu_params {
+	enum ieee80211_ampdu_mlme_action action;
+	struct ieee80211_sta *sta;
+	u16 tid;
+	u16 ssn;
+	u8 buf_size;
+	bool amsdu;
+	u16 timeout;
+};
+
+/**
  * enum ieee80211_frame_release_type - frame release reason
  * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
  * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
@@ -3017,13 +3048,9 @@ enum ieee80211_reconfig_type {
  * @ampdu_action: Perform a certain A-MPDU action
  * 	The RA/TID combination determines the destination and TID we want
  * 	the ampdu action to be performed for. The action is defined through
- * 	ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
- * 	is the first frame we expect to perform the action on. Notice
- * 	that TX/RX_STOP can pass NULL for this parameter.
- *	The @buf_size parameter is only valid when the action is set to
- *	%IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
- *	buffer size (number of subframes) for this session -- the driver
- *	may neither send aggregates containing more subframes than this
+ *	ieee80211_ampdu_mlme_action.
+ *	When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver
+ *	may neither send aggregates containing more subframes than @buf_size
  *	nor send aggregates in a way that lost frames would exceed the
  *	buffer size. If just limiting the aggregate size, this would be
  *	possible with a buf_size of 8:
@@ -3034,9 +3061,6 @@ enum ieee80211_reconfig_type {
  *	buffer size of 8. Correct ways to retransmit #1 would be:
  *	 - TX:       1 or 18 or 81
  *	Even "189" would be wrong since 1 could be lost again.
- *	The @amsdu parameter is valid when the action is set to
- *	%IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability
- *	to receive A-MSDU within A-MPDU.
  *
  *	Returns a negative error code on failure.
  *	The callback can sleep.
@@ -3378,9 +3402,7 @@ struct ieee80211_ops {
 	int (*tx_last_beacon)(struct ieee80211_hw *hw);
 	int (*ampdu_action)(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
-			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			    u8 buf_size, bool amsdu);
+			    struct ieee80211_ampdu_params *params);
 	int (*get_survey)(struct ieee80211_hw *hw, int idx,
 		struct survey_info *survey);
 	void (*rfkill_poll)(struct ieee80211_hw *hw);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/include/target/target_core_fabric.h linux-libre-4.4.69-gnu/include/target/target_core_fabric.h
--- linux-libre-4.4.68-gnu/include/target/target_core_fabric.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/include/target/target_core_fabric.h	2017-05-20 08:27:22.000000000 -0400
@@ -117,7 +117,7 @@ void	__transport_register_session(struct
 		struct se_node_acl *, struct se_session *, void *);
 void	transport_register_session(struct se_portal_group *,
 		struct se_node_acl *, struct se_session *, void *);
-void	target_get_session(struct se_session *);
+int	target_get_session(struct se_session *);
 void	target_put_session(struct se_session *);
 ssize_t	target_show_dynamic_sessions(struct se_portal_group *, char *);
 void	transport_free_session(struct se_session *);
@@ -172,8 +172,7 @@ bool	target_tpg_has_node_acl(struct se_p
 		const char *);
 struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
 		unsigned char *);
-int	core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
-		unsigned char *, u32, int);
+int	core_tpg_set_initiator_node_queue_depth(struct se_node_acl *, u32);
 int	core_tpg_set_initiator_node_tag(struct se_portal_group *,
 		struct se_node_acl *, const char *);
 int	core_tpg_register(struct se_wwn *, struct se_portal_group *, int);
diff -druNp --no-dereference linux-libre-4.4.68-gnu/kernel/padata.c linux-libre-4.4.69-gnu/kernel/padata.c
--- linux-libre-4.4.68-gnu/kernel/padata.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/kernel/padata.c	2017-05-20 08:27:22.000000000 -0400
@@ -357,7 +357,7 @@ static int padata_setup_cpumasks(struct
 
 	cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask);
 	if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) {
-		free_cpumask_var(pd->cpumask.cbcpu);
+		free_cpumask_var(pd->cpumask.pcpu);
 		return -ENOMEM;
 	}
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/Makefile linux-libre-4.4.69-gnu/Makefile
--- linux-libre-4.4.68-gnu/Makefile	2017-05-14 16:19:12.000000000 -0400
+++ linux-libre-4.4.69-gnu/Makefile	2017-05-20 10:53:32.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 4
-SUBLEVEL = 68
+SUBLEVEL = 69
 EXTRAVERSION = -gnu
 NAME = Blurry Fish Butt
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/bluetooth/hci_sock.c linux-libre-4.4.69-gnu/net/bluetooth/hci_sock.c
--- linux-libre-4.4.68-gnu/net/bluetooth/hci_sock.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/bluetooth/hci_sock.c	2017-05-20 08:27:22.000000000 -0400
@@ -1164,7 +1164,8 @@ static int hci_sock_sendmsg(struct socke
 	if (msg->msg_flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
-	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
+	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE|
+			       MSG_CMSG_COMPAT))
 		return -EINVAL;
 
 	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/mac80211/agg-rx.c linux-libre-4.4.69-gnu/net/mac80211/agg-rx.c
--- linux-libre-4.4.68-gnu/net/mac80211/agg-rx.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/mac80211/agg-rx.c	2017-05-20 08:27:22.000000000 -0400
@@ -7,6 +7,7 @@
  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -61,6 +62,14 @@ void ___ieee80211_stop_rx_ba_session(str
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_rx *tid_rx;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_RX_STOP,
+		.tid = tid,
+		.amsdu = false,
+		.timeout = 0,
+		.ssn = 0,
+	};
 
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
@@ -78,8 +87,7 @@ void ___ieee80211_stop_rx_ba_session(str
 	       initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
 	       (int)reason);
 
-	if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
-			     &sta->sta, tid, NULL, 0, false))
+	if (drv_ampdu_action(local, sta->sdata, &params))
 		sdata_info(sta->sdata,
 			   "HW problem - can not stop rx aggregation for %pM tid %d\n",
 			   sta->sta.addr, tid);
@@ -237,6 +245,15 @@ void __ieee80211_start_rx_ba_session(str
 {
 	struct ieee80211_local *local = sta->sdata->local;
 	struct tid_ampdu_rx *tid_agg_rx;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_RX_START,
+		.tid = tid,
+		.amsdu = false,
+		.timeout = timeout,
+		.ssn = start_seq_num,
+	};
+
 	int i, ret = -EOPNOTSUPP;
 	u16 status = WLAN_STATUS_REQUEST_DECLINED;
 
@@ -273,8 +290,12 @@ void __ieee80211_start_rx_ba_session(str
 		buf_size = IEEE80211_MAX_AMPDU_BUF;
 
 	/* make sure the size doesn't exceed the maximum supported by the hw */
-	if (buf_size > local->hw.max_rx_aggregation_subframes)
-		buf_size = local->hw.max_rx_aggregation_subframes;
+	if (buf_size > sta->sta.max_rx_aggregation_subframes)
+		buf_size = sta->sta.max_rx_aggregation_subframes;
+	params.buf_size = buf_size;
+
+	ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
+	       buf_size, sta->sta.addr);
 
 	/* examine state machine */
 	mutex_lock(&sta->ampdu_mlme.mtx);
@@ -322,8 +343,7 @@ void __ieee80211_start_rx_ba_session(str
 	for (i = 0; i < buf_size; i++)
 		__skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
 
-	ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
-			       &sta->sta, tid, &start_seq_num, 0, false);
+	ret = drv_ampdu_action(local, sta->sdata, &params);
 	ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
 	       sta->sta.addr, tid, ret);
 	if (ret) {
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/mac80211/agg-tx.c linux-libre-4.4.69-gnu/net/mac80211/agg-tx.c
--- linux-libre-4.4.68-gnu/net/mac80211/agg-tx.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/mac80211/agg-tx.c	2017-05-20 08:27:22.000000000 -0400
@@ -7,6 +7,7 @@
  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -295,7 +296,14 @@ int ___ieee80211_stop_tx_ba_session(stru
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_tx *tid_tx;
-	enum ieee80211_ampdu_mlme_action action;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.tid = tid,
+		.buf_size = 0,
+		.amsdu = false,
+		.timeout = 0,
+		.ssn = 0,
+	};
 	int ret;
 
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
@@ -304,10 +312,10 @@ int ___ieee80211_stop_tx_ba_session(stru
 	case AGG_STOP_DECLINED:
 	case AGG_STOP_LOCAL_REQUEST:
 	case AGG_STOP_PEER_REQUEST:
-		action = IEEE80211_AMPDU_TX_STOP_CONT;
+		params.action = IEEE80211_AMPDU_TX_STOP_CONT;
 		break;
 	case AGG_STOP_DESTROY_STA:
-		action = IEEE80211_AMPDU_TX_STOP_FLUSH;
+		params.action = IEEE80211_AMPDU_TX_STOP_FLUSH;
 		break;
 	default:
 		WARN_ON_ONCE(1);
@@ -330,9 +338,8 @@ int ___ieee80211_stop_tx_ba_session(stru
 		spin_unlock_bh(&sta->lock);
 		if (reason != AGG_STOP_DESTROY_STA)
 			return -EALREADY;
-		ret = drv_ampdu_action(local, sta->sdata,
-				       IEEE80211_AMPDU_TX_STOP_FLUSH_CONT,
-				       &sta->sta, tid, NULL, 0, false);
+		params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT;
+		ret = drv_ampdu_action(local, sta->sdata, &params);
 		WARN_ON_ONCE(ret);
 		return 0;
 	}
@@ -381,8 +388,7 @@ int ___ieee80211_stop_tx_ba_session(stru
 					WLAN_BACK_INITIATOR;
 	tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
 
-	ret = drv_ampdu_action(local, sta->sdata, action,
-			       &sta->sta, tid, NULL, 0, false);
+	ret = drv_ampdu_action(local, sta->sdata, &params);
 
 	/* HW shall not deny going back to legacy */
 	if (WARN_ON(ret)) {
@@ -445,7 +451,14 @@ void ieee80211_tx_ba_session_handle_star
 	struct tid_ampdu_tx *tid_tx;
 	struct ieee80211_local *local = sta->local;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	u16 start_seq_num;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_TX_START,
+		.tid = tid,
+		.buf_size = 0,
+		.amsdu = false,
+		.timeout = 0,
+	};
 	int ret;
 
 	tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
@@ -467,10 +480,8 @@ void ieee80211_tx_ba_session_handle_star
 	 */
 	synchronize_net();
 
-	start_seq_num = sta->tid_seq[tid] >> 4;
-
-	ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
-			       &sta->sta, tid, &start_seq_num, 0, false);
+	params.ssn = sta->tid_seq[tid] >> 4;
+	ret = drv_ampdu_action(local, sdata, &params);
 	if (ret) {
 		ht_dbg(sdata,
 		       "BA request denied - HW unavailable for %pM tid %d\n",
@@ -499,7 +510,7 @@ void ieee80211_tx_ba_session_handle_star
 
 	/* send AddBA request */
 	ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
-				     tid_tx->dialog_token, start_seq_num,
+				     tid_tx->dialog_token, params.ssn,
 				     IEEE80211_MAX_AMPDU_BUF,
 				     tid_tx->timeout);
 }
@@ -684,18 +695,24 @@ static void ieee80211_agg_tx_operational
 					 struct sta_info *sta, u16 tid)
 {
 	struct tid_ampdu_tx *tid_tx;
+	struct ieee80211_ampdu_params params = {
+		.sta = &sta->sta,
+		.action = IEEE80211_AMPDU_TX_OPERATIONAL,
+		.tid = tid,
+		.timeout = 0,
+		.ssn = 0,
+	};
 
 	lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
 	tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+	params.buf_size = tid_tx->buf_size;
+	params.amsdu = tid_tx->amsdu;
 
 	ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n",
 	       sta->sta.addr, tid);
 
-	drv_ampdu_action(local, sta->sdata,
-			 IEEE80211_AMPDU_TX_OPERATIONAL,
-			 &sta->sta, tid, NULL, tid_tx->buf_size,
-			 tid_tx->amsdu);
+	drv_ampdu_action(local, sta->sdata, &params);
 
 	/*
 	 * synchronize with TX path, while splicing the TX path
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/mac80211/driver-ops.c linux-libre-4.4.69-gnu/net/mac80211/driver-ops.c
--- linux-libre-4.4.68-gnu/net/mac80211/driver-ops.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/mac80211/driver-ops.c	2017-05-20 08:27:22.000000000 -0400
@@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80
 
 int drv_ampdu_action(struct ieee80211_local *local,
 		     struct ieee80211_sub_if_data *sdata,
-		     enum ieee80211_ampdu_mlme_action action,
-		     struct ieee80211_sta *sta, u16 tid,
-		     u16 *ssn, u8 buf_size, bool amsdu)
+		     struct ieee80211_ampdu_params *params)
 {
 	int ret = -EOPNOTSUPP;
 
@@ -296,12 +294,10 @@ int drv_ampdu_action(struct ieee80211_lo
 	if (!check_sdata_in_driver(sdata))
 		return -EIO;
 
-	trace_drv_ampdu_action(local, sdata, action, sta, tid,
-			       ssn, buf_size, amsdu);
+	trace_drv_ampdu_action(local, sdata, params);
 
 	if (local->ops->ampdu_action)
-		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
-					       sta, tid, ssn, buf_size, amsdu);
+		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params);
 
 	trace_drv_return_int(local, ret);
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/mac80211/driver-ops.h linux-libre-4.4.69-gnu/net/mac80211/driver-ops.h
--- linux-libre-4.4.68-gnu/net/mac80211/driver-ops.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/mac80211/driver-ops.h	2017-05-20 08:27:22.000000000 -0400
@@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(str
 
 int drv_ampdu_action(struct ieee80211_local *local,
 		     struct ieee80211_sub_if_data *sdata,
-		     enum ieee80211_ampdu_mlme_action action,
-		     struct ieee80211_sta *sta, u16 tid,
-		     u16 *ssn, u8 buf_size, bool amsdu);
+		     struct ieee80211_ampdu_params *params);
 
 static inline int drv_get_survey(struct ieee80211_local *local, int idx,
 				struct survey_info *survey)
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/mac80211/sta_info.c linux-libre-4.4.69-gnu/net/mac80211/sta_info.c
--- linux-libre-4.4.68-gnu/net/mac80211/sta_info.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/mac80211/sta_info.c	2017-05-20 08:27:22.000000000 -0400
@@ -329,6 +329,9 @@ struct sta_info *sta_info_alloc(struct i
 
 	memcpy(sta->addr, addr, ETH_ALEN);
 	memcpy(sta->sta.addr, addr, ETH_ALEN);
+	sta->sta.max_rx_aggregation_subframes =
+		local->hw.max_rx_aggregation_subframes;
+
 	sta->local = local;
 	sta->sdata = sdata;
 	sta->rx_stats.last_rx = jiffies;
diff -druNp --no-dereference linux-libre-4.4.68-gnu/net/mac80211/trace.h linux-libre-4.4.69-gnu/net/mac80211/trace.h
--- linux-libre-4.4.68-gnu/net/mac80211/trace.h	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/net/mac80211/trace.h	2017-05-20 08:27:22.000000000 -0400
@@ -80,7 +80,23 @@
 #define KEY_PR_FMT	" cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d"
 #define KEY_PR_ARG	__entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx
 
-
+#define AMPDU_ACTION_ENTRY	__field(enum ieee80211_ampdu_mlme_action,		\
+					ieee80211_ampdu_mlme_action)			\
+				STA_ENTRY						\
+				__field(u16, tid)					\
+				__field(u16, ssn)					\
+				__field(u8, buf_size)					\
+				__field(bool, amsdu)					\
+				__field(u16, timeout)
+#define AMPDU_ACTION_ASSIGN	STA_NAMED_ASSIGN(params->sta);				\
+				__entry->tid = params->tid;				\
+				__entry->ssn = params->ssn;				\
+				__entry->buf_size = params->buf_size;			\
+				__entry->amsdu = params->amsdu;				\
+				__entry->timeout = params->timeout;
+#define AMPDU_ACTION_PR_FMT	STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d"
+#define AMPDU_ACTION_PR_ARG	STA_PR_ARG, __entry->tid, __entry->ssn,			\
+				__entry->buf_size, __entry->amsdu, __entry->timeout
 
 /*
  * Tracing for driver callbacks.
@@ -970,38 +986,25 @@ DEFINE_EVENT(local_only_evt, drv_tx_last
 TRACE_EVENT(drv_ampdu_action,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
-		 enum ieee80211_ampdu_mlme_action action,
-		 struct ieee80211_sta *sta, u16 tid,
-		 u16 *ssn, u8 buf_size, bool amsdu),
+		 struct ieee80211_ampdu_params *params),
 
-	TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu),
+	TP_ARGS(local, sdata, params),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
-		STA_ENTRY
-		__field(u32, action)
-		__field(u16, tid)
-		__field(u16, ssn)
-		__field(u8, buf_size)
-		__field(bool, amsdu)
 		VIF_ENTRY
+		AMPDU_ACTION_ENTRY
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
-		STA_ASSIGN;
-		__entry->action = action;
-		__entry->tid = tid;
-		__entry->ssn = ssn ? *ssn : 0;
-		__entry->buf_size = buf_size;
-		__entry->amsdu = amsdu;
+		AMPDU_ACTION_ASSIGN;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
-		__entry->tid, __entry->buf_size, __entry->amsdu
+		LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT,
+		LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG
 	)
 );
 
diff -druNp --no-dereference linux-libre-4.4.68-gnu/tools/testing/selftests/x86/ldt_gdt.c linux-libre-4.4.69-gnu/tools/testing/selftests/x86/ldt_gdt.c
--- linux-libre-4.4.68-gnu/tools/testing/selftests/x86/ldt_gdt.c	2017-05-14 07:33:15.000000000 -0400
+++ linux-libre-4.4.69-gnu/tools/testing/selftests/x86/ldt_gdt.c	2017-05-20 08:27:22.000000000 -0400
@@ -394,6 +394,51 @@ static void *threadproc(void *ctx)
 	}
 }
 
+#ifdef __i386__
+
+#ifndef SA_RESTORE
+#define SA_RESTORER 0x04000000
+#endif
+
+/*
+ * The UAPI header calls this 'struct sigaction', which conflicts with
+ * glibc.  Sigh.
+ */
+struct fake_ksigaction {
+	void *handler;  /* the real type is nasty */
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	unsigned char sigset[8];
+};
+
+static void fix_sa_restorer(int sig)
+{
+	struct fake_ksigaction ksa;
+
+	if (syscall(SYS_rt_sigaction, sig, NULL, &ksa, 8) == 0) {
+		/*
+		 * glibc has a nasty bug: it sometimes writes garbage to
+		 * sa_restorer.  This interacts quite badly with anything
+		 * that fiddles with SS because it can trigger legacy
+		 * stack switching.  Patch it up.  See:
+		 *
+		 * https://sourceware.org/bugzilla/show_bug.cgi?id=21269
+		 */
+		if (!(ksa.sa_flags & SA_RESTORER) && ksa.sa_restorer) {
+			ksa.sa_restorer = NULL;
+			if (syscall(SYS_rt_sigaction, sig, &ksa, NULL,
+				    sizeof(ksa.sigset)) != 0)
+				err(1, "rt_sigaction");
+		}
+	}
+}
+#else
+static void fix_sa_restorer(int sig)
+{
+	/* 64-bit glibc works fine. */
+}
+#endif
+
 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 		       int flags)
 {
@@ -405,6 +450,7 @@ static void sethandler(int sig, void (*h
 	if (sigaction(sig, &sa, 0))
 		err(1, "sigaction");
 
+	fix_sa_restorer(sig);
 }
 
 static jmp_buf jmpbuf;
