summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2017-05-20 16:21:19 -0400
committerMike Pagano <mpagano@gentoo.org>2017-05-20 16:21:19 -0400
commit3cbf1ac5e192cdc5c01c23ee73adbd0ae05c383e (patch)
treedcd80a243d0f94b95db8eb179a4713f8227886b6
parentLinux patch 4.4.68 (diff)
downloadlinux-patches-3cbf1ac5e192cdc5c01c23ee73adbd0ae05c383e.tar.gz
linux-patches-3cbf1ac5e192cdc5c01c23ee73adbd0ae05c383e.tar.bz2
linux-patches-3cbf1ac5e192cdc5c01c23ee73adbd0ae05c383e.zip
Linux patch 4.4.694.4-72
-rw-r--r--0000_README4
-rw-r--r--1068_linux-4.4.69.patch2955
2 files changed, 2959 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 2efc5994..ccd90a89 100644
--- a/0000_README
+++ b/0000_README
@@ -315,6 +315,10 @@ Patch: 1067_linux-4.4.68.patch
From: http://www.kernel.org
Desc: Linux 4.4.68
+Patch: 1068_linux-4.4.69.patch
+From: http://www.kernel.org
+Desc: Linux 4.4.69
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1068_linux-4.4.69.patch b/1068_linux-4.4.69.patch
new file mode 100644
index 00000000..0fde812a
--- /dev/null
+++ b/1068_linux-4.4.69.patch
@@ -0,0 +1,2955 @@
+diff --git a/Makefile b/Makefile
+index e6c7990497e7..dc5df61ea4be 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 4
+-SUBLEVEL = 68
++SUBLEVEL = 69
+ EXTRAVERSION =
+ NAME = Blurry Fish Butt
+
+diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
+index a9b3b905e661..443db0c43d7c 100644
+--- a/arch/arm/kvm/psci.c
++++ b/arch/arm/kvm/psci.c
+@@ -208,9 +208,10 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
+
+ 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_vcpu *vcpu)
+ 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_vcpu *vcpu)
+
+ 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_vcpu *vcpu)
+ 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 --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
+index d2650e84faf2..c2489f62c4fb 100644
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -1054,8 +1054,8 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
+ {
+ 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_vcpu *vcpu,
+ {
+ 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 --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
+index 9011a88353de..ed1e9206f830 100644
+--- a/arch/x86/boot/boot.h
++++ b/arch/x86/boot/boot.h
+@@ -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 --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h
+index bd8ce6bcdfc9..6503526d7b24 100644
+--- a/arch/x86/include/asm/pmem.h
++++ b/arch/x86/include/asm/pmem.h
+@@ -122,7 +122,7 @@ static inline size_t arch_copy_from_iter_pmem(void __pmem *addr, size_t bytes,
+
+ 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 --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index e75095fa414e..281899da19d4 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2960,6 +2960,12 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
+ | 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(struct kvm_vcpu *vcpu,
+ 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 --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
+index a629694ee750..e14c43a2d187 100644
+--- a/arch/x86/um/ptrace_64.c
++++ b/arch/x86/um/ptrace_64.c
+@@ -121,7 +121,7 @@ int poke_user(struct task_struct *child, long addr, long data)
+ 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 --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index 1e56ff583459..63146c378f1e 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -2038,7 +2038,8 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
+
+ /*
+ * 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_to_phys(unsigned long vaddr)
+ 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_to_phys(unsigned long vaddr)
+ 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 --git a/block/blk-integrity.c b/block/blk-integrity.c
+index 319f2e4f4a8b..478f572cb1e7 100644
+--- a/block/blk-integrity.c
++++ b/block/blk-integrity.c
+@@ -412,7 +412,8 @@ void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template
+
+ 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 --git a/crypto/algif_aead.c b/crypto/algif_aead.c
+index 6d4d4569447e..faea9d728fd2 100644
+--- a/crypto/algif_aead.c
++++ b/crypto/algif_aead.c
+@@ -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 sock *sk)
+ 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 *private, struct sock *sk)
+
+ 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 *private, struct sock *sk)
+ 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 --git a/drivers/Makefile b/drivers/Makefile
+index 795d0ca714bf..098997f2cc3a 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -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 --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
+index cb852cc750b7..f9b569ef3dd7 100644
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -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 --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
+index b9065506a847..0c63fce0c1e0 100644
+--- a/drivers/bluetooth/hci_intel.c
++++ b/drivers/bluetooth/hci_intel.c
+@@ -307,6 +307,9 @@ static int intel_set_power(struct hci_uart *hu, bool powered)
+ 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 *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 *hu, struct sk_buff *skb)
+
+ 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 *hu, struct sk_buff *skb)
+ }
+ }
+ mutex_unlock(&intel_device_list_lock);
+-
++out_enqueue:
+ skb_queue_tail(&intel->txq, skb);
+
+ return 0;
+diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
+index 90e624662257..0d83cfb9708f 100644
+--- a/drivers/char/ipmi/ipmi_ssif.c
++++ b/drivers/char/ipmi/ipmi_ssif.c
+@@ -888,6 +888,7 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
+ * 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 ssif_info *ssif_info, int result,
+ 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 ssif_info *ssif_info, int result,
+ 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 --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
+index b1f37d4095fa..e76d52a203a7 100644
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -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 --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
+index 77ddf2fa8625..8763fb832b01 100644
+--- a/drivers/infiniband/hw/mlx4/main.c
++++ b/drivers/infiniband/hw/mlx4/main.c
+@@ -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 --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
+index 36ec8aa048aa..0b5bb0cee6f9 100644
+--- a/drivers/infiniband/hw/mlx4/mcg.c
++++ b/drivers/infiniband/hw/mlx4/mcg.c
+@@ -1105,7 +1105,8 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
+ 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 --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+index 6bd5740e2691..09396bd7b02d 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+@@ -281,8 +281,11 @@ void ipoib_delete_debug_files(struct net_device *dev)
+ {
+ 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 --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+index 8efcff1beb8f..6699ecd855f0 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -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 *dev)
+
+ 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(const char *format,
+ 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(const char *format,
+ 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_device *device, void *client_data)
+ 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 --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+index fca1a882de27..57a34f87dedf 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+@@ -85,8 +85,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
+ 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_priv *ppriv, struct ipoib_dev_priv *priv,
+
+ sysfs_failed:
+ result = -ENOMEM;
+- ipoib_delete_debug_files(priv->dev);
+ unregister_netdevice(priv->dev);
+
+ register_failed:
+diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
+index 665bf3285618..32e76c5ee741 100644
+--- a/drivers/md/dm-era-target.c
++++ b/drivers/md/dm-era-target.c
+@@ -961,15 +961,15 @@ static int metadata_commit(struct era_metadata *md)
+ }
+ }
+
+- 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 --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
+index 1e1bef349487..6decf4a95ce1 100644
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -6351,12 +6351,13 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+
+ 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 --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+index a680a970b7f7..e4281438c04f 100644
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
+
+ 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 --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
+index b114e57a823f..3abc64574116 100644
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1855,14 +1855,16 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+
+ 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 --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
+index 19d3d64416bf..4d1527a2e292 100644
+--- a/drivers/net/wireless/ath/carl9170/main.c
++++ b/drivers/net/wireless/ath/carl9170/main.c
+@@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct work_struct *work)
+
+ 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 --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
+index 7c169abdbafe..a27279c2c695 100644
+--- a/drivers/net/wireless/ath/wcn36xx/main.c
++++ b/drivers/net/wireless/ath/wcn36xx/main.c
+@@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee80211_hw *hw)
+
+ 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 --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+index bec2dc1ca2e4..61ae2768132a 100644
+--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+@@ -818,13 +818,15 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 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 --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c
+index 95a7fdb3cc1c..c602a1e674ca 100644
+--- a/drivers/net/wireless/cw1200/sta.c
++++ b/drivers/net/wireless/cw1200/sta.c
+@@ -2135,9 +2135,7 @@ void cw1200_mcast_timeout(unsigned long arg)
+
+ 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 --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h
+index bebb3379017f..a0bacaa39b31 100644
+--- a/drivers/net/wireless/cw1200/sta.h
++++ b/drivers/net/wireless/cw1200/sta.h
+@@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
+ 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 --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
+index 6656215a13a9..04b0349a6ad9 100644
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
+@@ -5982,12 +5982,14 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+
+ 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 --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
+index 8ab8706f9422..e432715e02d8 100644
+--- a/drivers/net/wireless/iwlegacy/4965.h
++++ b/drivers/net/wireless/iwlegacy/4965.h
+@@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+ 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 --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+index b3ad34e8bf5a..1eb1a823a111 100644
+--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
++++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+@@ -729,12 +729,15 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+
+ 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 --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+index ce12717e656a..1a8ea775de08 100644
+--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+@@ -826,13 +826,16 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+
+ 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 --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
+index 0cd95120bc78..d59769e858f4 100644
+--- a/drivers/net/wireless/mac80211_hwsim.c
++++ b/drivers/net/wireless/mac80211_hwsim.c
+@@ -1817,10 +1817,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
+
+ 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 --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
+index f715eee39851..e70dd9523911 100644
+--- a/drivers/net/wireless/mediatek/mt7601u/main.c
++++ b/drivers/net/wireless/mediatek/mt7601u/main.c
+@@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+
+ 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 --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
+index 30e3aaae32e2..088429d0a634 100644
+--- a/drivers/net/wireless/mwl8k.c
++++ b/drivers/net/wireless/mwl8k.c
+@@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
+
+ 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 --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
+index 6aed923a709a..7d820c395375 100644
+--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
+@@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+
+ 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 --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
+index e36d8c456275..8b537a5a4b01 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/core.c
++++ b/drivers/net/wireless/realtek/rtlwifi/core.c
+@@ -1369,11 +1369,13 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw,
+
+ 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 --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+index b5bcc933a2a6..4df992de7d07 100644
+--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
++++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+@@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
+ * 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 --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
+index 9733b31a780d..69c1c09687a3 100644
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+ 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 --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
+index 440790b92b19..83f1a44fb9b4 100644
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *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 --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
+index 09c7e098f460..085ef5c87262 100644
+--- a/drivers/net/wireless/ti/wl18xx/event.c
++++ b/drivers/net/wireless/ti/wl18xx/event.c
+@@ -206,5 +206,33 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
+ 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 --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
+index f3d4f13379cb..9495fadc8093 100644
+--- a/drivers/net/wireless/ti/wl18xx/event.h
++++ b/drivers/net/wireless/ti/wl18xx/event.h
+@@ -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 --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
+index 50cce42089a5..47f355e92193 100644
+--- a/drivers/net/wireless/ti/wl18xx/main.c
++++ b/drivers/net/wireless/ti/wl18xx/main.c
+@@ -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 --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
+index f28fa3b5029d..0646c9b6f8d7 100644
+--- a/drivers/net/wireless/ti/wlcore/acx.c
++++ b/drivers/net/wireless/ti/wlcore/acx.c
+@@ -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(struct wl1271 *wl, u8 tid_index,
+ 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 --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
+index 954d57ec98f4..524aea495dff 100644
+--- a/drivers/net/wireless/ti/wlcore/acx.h
++++ b/drivers/net/wireless/ti/wlcore/acx.h
+@@ -1112,7 +1112,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
+ 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 --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
+index ec7f6af3fab2..7b27c7e23af2 100644
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -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 ieee80211_hw *hw,
+ }
+
+ 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 ieee80211_hw *hw,
+ }
+
+ 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 --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index b87192e0f9aa..109becdabc24 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -610,7 +610,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 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);
+@@ -726,11 +726,12 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
+ 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 --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
+index 445f83615575..fb4f3fea6c66 100644
+--- a/drivers/staging/gdm724x/gdm_mux.c
++++ b/drivers/staging/gdm724x/gdm_mux.c
+@@ -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 --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
+index c975c3b87093..cfc3017fd64a 100644
+--- a/drivers/staging/vt6656/usbpipe.c
++++ b/drivers/staging/vt6656/usbpipe.c
+@@ -50,15 +50,25 @@ int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
+ 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 *priv, u8 request, u16 value,
+ 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 --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
+index 6ed80b05d674..200d3de8bc1e 100644
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -4821,6 +4821,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
+ 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 --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
+index b4bfd706ac94..dc1bd1f1bdfe 100644
+--- a/drivers/target/iscsi/iscsi_target_configfs.c
++++ b/drivers/target/iscsi/iscsi_target_configfs.c
+@@ -725,11 +725,8 @@ static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item,
+
+ 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_only(
+ }
+
+ /*
+- * 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 --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
+index 316f66172335..4a137b0ae3dc 100644
+--- a/drivers/target/iscsi/iscsi_target_login.c
++++ b/drivers/target/iscsi/iscsi_target_login.c
+@@ -195,6 +195,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
+ 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 --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
+index 68261b7dcefe..205a509b0dfb 100644
+--- a/drivers/target/iscsi/iscsi_target_tpg.c
++++ b/drivers/target/iscsi/iscsi_target_tpg.c
+@@ -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 --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
+index 9db32bd24cd4..2da211920c18 100644
+--- a/drivers/target/iscsi/iscsi_target_tpg.h
++++ b/drivers/target/iscsi/iscsi_target_tpg.h
+@@ -26,8 +26,6 @@ extern struct iscsi_tpg_np *iscsit_tpg_add_network_portal(struct iscsi_portal_gr
+ 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 --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
+index 79291869bce6..041a56987845 100644
+--- a/drivers/target/target_core_file.c
++++ b/drivers/target/target_core_file.c
+@@ -594,8 +594,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
+ 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 --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
+index 90c5dffc9fa4..608117819366 100644
+--- a/drivers/target/target_core_sbc.c
++++ b/drivers/target/target_core_sbc.c
+@@ -498,8 +498,11 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
+ * 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 --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
+index 2794c6ec5c3c..899c33b3c734 100644
+--- a/drivers/target/target_core_tpg.c
++++ b/drivers/target/target_core_tpg.c
+@@ -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_node_acl(struct se_portal_group *tpg,
+ 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(struct se_node_acl *acl)
+ 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(struct se_node_acl *acl)
+ *
+ */
+ 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 --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
+index df2059984e14..af301414a9f3 100644
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -383,9 +383,9 @@ static void target_release_session(struct kref *kref)
+ 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 --git a/drivers/tty/pty.c b/drivers/tty/pty.c
+index 807d80145686..96aa0ad32497 100644
+--- a/drivers/tty/pty.c
++++ b/drivers/tty/pty.c
+@@ -216,16 +216,11 @@ static int pty_signal(struct tty_struct *tty, int sig)
+ 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 --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
+index 24280d9a05e9..de1c143b475f 100644
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1712,7 +1712,8 @@ static int serial_omap_probe(struct platform_device *pdev)
+ 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 platform_device *dev)
+ {
+ 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 --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
+index 6deb06147202..e6bc1a6be4a4 100644
+--- a/drivers/tty/serial/samsung.c
++++ b/drivers/tty/serial/samsung.c
+@@ -900,14 +900,13 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
+ 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(struct s3c24xx_uart_port *p)
+
+ 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(struct s3c24xx_uart_port *p)
+
+ 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 --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index dadd1e8dfe09..0bb380a9fcf7 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1328,6 +1328,24 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ */
+ 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_device *udev)
+ 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 --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
+index ea337a718cc1..b3de806085f0 100644
+--- a/drivers/usb/core/file.c
++++ b/drivers/usb/core/file.c
+@@ -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 kref *kref)
+
+ 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_interface *intf,
+ 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 --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7c2d87befb51..67961231cbbd 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1048,6 +1048,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+
+ 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 *hub, enum hub_activation_type type)
+
+ /* 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 **pdev)
+ 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 --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 998a738e6359..5d70d46239bb 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -2493,7 +2493,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+ (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 --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 1624b09d9748..2e947dc94e32 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -135,6 +135,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
+ 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 --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index b3a21fcbbaf9..dbd441c1c2ad 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -873,6 +873,7 @@ static const struct usb_device_id id_table_combined[] = {
+ { 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 --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
+index 48ee04c94a75..71fb9e59db71 100644
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -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 --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
+index ecb826eefe02..2fa280671c1e 100644
+--- a/drivers/vfio/vfio_iommu_type1.c
++++ b/drivers/vfio/vfio_iommu_type1.c
+@@ -130,57 +130,34 @@ static void vfio_unlink_dma(struct vfio_iommu *iommu, struct vfio_dma *old)
+ 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;
+-
+- mm = vwork->mm;
+- down_write(&mm->mmap_sem);
+- mm->locked_vm += vwork->npage;
+- up_write(&mm->mmap_sem);
+- mmput(mm);
+- kfree(vwork);
+-}
++ int ret = 0;
+
+-static void vfio_lock_acct(long npage)
+-{
+- struct vwork *vwork;
+- struct mm_struct *mm;
++ if (!npage)
++ return 0;
+
+- if (!current->mm || !npage)
+- return; /* process exited or nothing to do */
++ if (!current->mm)
++ return -ESRCH; /* process exited */
+
+- if (down_write_trylock(&current->mm->mmap_sem)) {
+- current->mm->locked_vm += npage;
+- up_write(&current->mm->mmap_sem);
+- return;
+- }
++ down_write(&current->mm->mmap_sem);
++ if (npage > 0) {
++ if (lock_cap ? !*lock_cap : !capable(CAP_IPC_LOCK)) {
++ unsigned long limit;
+
+- /*
+- * 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;
++ limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
++
++ 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 vaddr, int prot, unsigned long *pfn)
+ 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 vaddr, long npage,
+ 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 vaddr, long npage,
+ 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 long pfn, long npage,
+ 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_iommu *iommu, struct vfio_dma *dma)
+ 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 --git a/fs/block_dev.c b/fs/block_dev.c
+index e5733bb537c9..26bbaaefdff4 100644
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -88,12 +88,11 @@ void invalidate_bdev(struct block_device *bdev)
+ {
+ 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 --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
+index 819163d8313b..b24275ef97f7 100644
+--- a/fs/ceph/xattr.c
++++ b/fs/ceph/xattr.c
+@@ -369,6 +369,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
+
+ 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_info *ci,
+ 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 --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
+index 02b071bf3732..a0b3e7d1be48 100644
+--- a/fs/cifs/cifs_unicode.c
++++ b/fs/cifs/cifs_unicode.c
+@@ -83,6 +83,9 @@ convert_sfm_char(const __u16 src_char, char *target)
+ 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 src_char, bool end_of_string)
+ 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 --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
+index 479bc0a941f3..07ade707fa60 100644
+--- a/fs/cifs/cifs_unicode.h
++++ b/fs/cifs/cifs_unicode.h
+@@ -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 --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
+index 5e2f8b8ca08a..b60150e5b5ce 100644
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -717,6 +717,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
+ 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 --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
+index 35cf990f87d3..a8f5b31636dc 100644
+--- a/fs/cifs/ioctl.c
++++ b/fs/cifs/ioctl.c
+@@ -272,6 +272,8 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
+ 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 --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
+index 6cb2603f8a5c..f4afa3b1cc56 100644
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -564,8 +564,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
+ }
+
+ 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, struct cifs_tcon *tcon, u64 persistent_fid,
+ * 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 --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 817a937de733..ccae64dad40c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5393,6 +5393,11 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 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 --git a/fs/xattr.c b/fs/xattr.c
+index 9b932b95d74e..f0da9d24e9ca 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -442,7 +442,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
+ 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 --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 760bc4d5a2cf..4e51f9a5a177 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -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 --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
+index 97069ecabe49..5f9b62c129fc 100644
+--- a/include/target/target_core_fabric.h
++++ b/include/target/target_core_fabric.h
+@@ -117,7 +117,7 @@ void __transport_register_session(struct se_portal_group *,
+ 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_portal_group *tpg,
+ 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 --git a/kernel/padata.c b/kernel/padata.c
+index 401227e3967c..ecc7b3f452c7 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -357,7 +357,7 @@ static int padata_setup_cpumasks(struct parallel_data *pd,
+
+ 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 --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index b1eb8c09a660..c842f40c1173 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -1164,7 +1164,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
+ 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 --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
+index 367784be5df2..a830356b94ac 100644
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -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(struct sta_info *sta, u16 tid,
+ {
+ 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(struct sta_info *sta, u16 tid,
+ 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(struct sta_info *sta,
+ {
+ 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(struct sta_info *sta,
+ 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(struct sta_info *sta,
+ 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 --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index ff757181b0a8..4932e9f243a2 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -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(struct sta_info *sta, u16 tid,
+ {
+ 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(struct sta_info *sta, u16 tid,
+ 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(struct sta_info *sta, u16 tid,
+ 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(struct sta_info *sta, u16 tid,
+ 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_start(struct sta_info *sta, int tid)
+ 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_start(struct sta_info *sta, int tid)
+ */
+ 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_start(struct sta_info *sta, int tid)
+
+ /* 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 ieee80211_local *local,
+ 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 --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
+index ca1fe5576103..c258f1041d33 100644
+--- a/net/mac80211/driver-ops.c
++++ b/net/mac80211/driver-ops.c
+@@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local,
+
+ 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_local *local,
+ 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 --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
+index 154ce4b13406..18b0d65baff0 100644
+--- a/net/mac80211/driver-ops.h
++++ b/net/mac80211/driver-ops.h
+@@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local)
+
+ 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 --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 67066d048e6f..63ea6cbac5ad 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -329,6 +329,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
+
+ 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 --git a/net/mac80211/trace.h b/net/mac80211/trace.h
+index 56c6d6cfa5a1..913e959b03cf 100644
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -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_beacon,
+ 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 --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
+index 31a3035cd4eb..923e59eb82c7 100644
+--- a/tools/testing/selftests/x86/ldt_gdt.c
++++ b/tools/testing/selftests/x86/ldt_gdt.c
+@@ -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 (*handler)(int, siginfo_t *, void *),
+ if (sigaction(sig, &sa, 0))
+ err(1, "sigaction");
+
++ fix_sa_restorer(sig);
+ }
+
+ static jmp_buf jmpbuf;