From: "Mike Pagano" <mpagano@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:4.1 commit in: /
Date: Sat, 5 Mar 2016 23:38:37 +0000 (UTC) [thread overview]
Message-ID: <1457221107.4a919eff2d079c34d6f84bf9073c32ef11af9864.mpagano@gentoo> (raw)
commit: 4a919eff2d079c34d6f84bf9073c32ef11af9864
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sat Mar 5 23:38:27 2016 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sat Mar 5 23:38:27 2016 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=4a919eff
Linux patch 4.1.19
0000_README | 4 +
1018_linux-4.1.19.patch | 7602 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 7606 insertions(+)
diff --git a/0000_README b/0000_README
index ed66531..ad1d372 100644
--- a/0000_README
+++ b/0000_README
@@ -115,6 +115,10 @@ Patch: 1017_linux-4.1.18.patch
From: http://www.kernel.org
Desc: Linux 4.1.18
+Patch: 1018_linux-4.1.19.patch
+From: http://www.kernel.org
+Desc: Linux 4.1.19
+
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/1018_linux-4.1.19.patch b/1018_linux-4.1.19.patch
new file mode 100644
index 0000000..449c63a
--- /dev/null
+++ b/1018_linux-4.1.19.patch
@@ -0,0 +1,7602 @@
+diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
+index 071fb18dc57c..07fad3d2fc56 100644
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -1321,6 +1321,14 @@ accept_ra_from_local - BOOLEAN
+ disabled if accept_ra_from_local is disabled
+ on a specific interface.
+
++accept_ra_min_hop_limit - INTEGER
++ Minimum hop limit Information in Router Advertisement.
++
++ Hop limit Information in Router Advertisement less than this
++ variable shall be ignored.
++
++ Default: 1
++
+ accept_ra_pinfo - BOOLEAN
+ Learn Prefix Information in Router Advertisement.
+
+diff --git a/Makefile b/Makefile
+index 001375cfd815..06107f683bbe 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 1
+-SUBLEVEL = 18
++SUBLEVEL = 19
+ EXTRAVERSION =
+ NAME = Series 4800
+
+diff --git a/arch/arm/common/icst.c b/arch/arm/common/icst.c
+index 2dc6da70ae59..d7ed252708c5 100644
+--- a/arch/arm/common/icst.c
++++ b/arch/arm/common/icst.c
+@@ -16,7 +16,7 @@
+ */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-
++#include <asm/div64.h>
+ #include <asm/hardware/icst.h>
+
+ /*
+@@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
+
+ unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
+ {
+- return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
++ u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
++ u32 divisor = (vco.r + 2) * p->s2div[vco.s];
++
++ do_div(dividend, divisor);
++ return (unsigned long)dividend;
+ }
+
+ EXPORT_SYMBOL(icst_hz);
+@@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params *p, unsigned long freq)
+
+ if (f > p->vco_min && f <= p->vco_max)
+ break;
++ i++;
+ } while (i < 8);
+
+ if (i >= 8)
+diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
+index 6499d93ae68d..47bc45a67e9b 100644
+--- a/arch/mips/include/asm/syscall.h
++++ b/arch/mips/include/asm/syscall.h
+@@ -101,10 +101,8 @@ static inline void syscall_get_arguments(struct task_struct *task,
+ /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
+ if ((config_enabled(CONFIG_32BIT) ||
+ test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
+- (regs->regs[2] == __NR_syscall)) {
++ (regs->regs[2] == __NR_syscall))
+ i++;
+- n++;
+- }
+
+ while (n--)
+ ret |= mips_get_syscall_arg(args++, task, regs, i++);
+diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
+index a52db28ecc1e..4457cb605356 100644
+--- a/arch/powerpc/include/asm/eeh.h
++++ b/arch/powerpc/include/asm/eeh.h
+@@ -79,6 +79,7 @@ struct pci_dn;
+ #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */
+ #define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */
+ #define EEH_PE_REMOVED (1 << 10) /* Removed permanently */
++#define EEH_PE_PRI_BUS (1 << 11) /* Cached primary bus */
+
+ struct eeh_pe {
+ int type; /* PE type: PHB/Bus/Device */
+@@ -336,19 +337,13 @@ static inline int eeh_check_failure(const volatile void __iomem *token)
+
+ #define eeh_dev_check_failure(x) (0)
+
+-static inline void eeh_addr_cache_build(void) { }
+-
+-static inline void eeh_add_device_early(struct pci_dn *pdn) { }
+-
+-static inline void eeh_add_device_tree_early(struct pci_dn *pdn) { }
+-
+-static inline void eeh_add_device_late(struct pci_dev *dev) { }
+-
+-static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
+-
+-static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
+-
+-static inline void eeh_remove_device(struct pci_dev *dev) { }
++#define eeh_addr_cache_build()
++#define eeh_add_device_early(pdn)
++#define eeh_add_device_tree_early(pdn)
++#define eeh_add_device_late(pdev)
++#define eeh_add_device_tree_late(pbus)
++#define eeh_add_sysfs_files(pbus)
++#define eeh_remove_device(pdev)
+
+ #define EEH_POSSIBLE_ERROR(val, type) (0)
+ #define EEH_IO_ERROR_VALUE(size) (-1UL)
+diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
+index 24768ff3cb73..90cc67904dc6 100644
+--- a/arch/powerpc/kernel/eeh_driver.c
++++ b/arch/powerpc/kernel/eeh_driver.c
+@@ -561,6 +561,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
+ */
+ eeh_pe_state_mark(pe, EEH_PE_KEEP);
+ if (bus) {
++ eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+ pci_lock_rescan_remove();
+ pcibios_remove_pci_devices(bus);
+ pci_unlock_rescan_remove();
+@@ -792,6 +793,7 @@ perm_error:
+ * the their PCI config any more.
+ */
+ if (frozen_bus) {
++ eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+ eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
+
+ pci_lock_rescan_remove();
+@@ -875,6 +877,7 @@ static void eeh_handle_special_event(void)
+ continue;
+
+ /* Notify all devices to be down */
++ eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+ bus = eeh_pe_bus_get(phb_pe);
+ eeh_pe_dev_traverse(pe,
+ eeh_report_failure, NULL);
+diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
+index 22f6d954ef89..c3e0420b8a42 100644
+--- a/arch/powerpc/kernel/eeh_pe.c
++++ b/arch/powerpc/kernel/eeh_pe.c
+@@ -906,7 +906,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
+ bus = pe->phb->bus;
+ } else if (pe->type & EEH_PE_BUS ||
+ pe->type & EEH_PE_DEVICE) {
+- if (pe->bus) {
++ if (pe->state & EEH_PE_PRI_BUS) {
+ bus = pe->bus;
+ goto out;
+ }
+diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
+index ce738ab3d5a9..abb396876b9a 100644
+--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
++++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
+@@ -455,9 +455,12 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)
+ * PCI devices of the PE are expected to be removed prior
+ * to PE reset.
+ */
+- if (!edev->pe->bus)
++ if (!(edev->pe->state & EEH_PE_PRI_BUS)) {
+ edev->pe->bus = pci_find_bus(hose->global_number,
+ pdn->busno);
++ if (edev->pe->bus)
++ edev->pe->state |= EEH_PE_PRI_BUS;
++ }
+
+ /*
+ * Enable EEH explicitly so that we will do EEH check
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index 181c53bac3a7..62855ac37ab7 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -285,6 +285,9 @@ static noinline int vmalloc_fault(unsigned long address)
+ if (!pmd_k)
+ return -1;
+
++ if (pmd_huge(*pmd_k))
++ return 0;
++
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ return -1;
+@@ -356,8 +359,6 @@ void vmalloc_sync_all(void)
+ * 64-bit:
+ *
+ * Handle a fault on the vmalloc area
+- *
+- * This assumes no large pages in there.
+ */
+ static noinline int vmalloc_fault(unsigned long address)
+ {
+@@ -399,17 +400,23 @@ static noinline int vmalloc_fault(unsigned long address)
+ if (pud_none(*pud_ref))
+ return -1;
+
+- if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
++ if (pud_none(*pud) || pud_pfn(*pud) != pud_pfn(*pud_ref))
+ BUG();
+
++ if (pud_huge(*pud))
++ return 0;
++
+ pmd = pmd_offset(pud, address);
+ pmd_ref = pmd_offset(pud_ref, address);
+ if (pmd_none(*pmd_ref))
+ return -1;
+
+- if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
++ if (pmd_none(*pmd) || pmd_pfn(*pmd) != pmd_pfn(*pmd_ref))
+ BUG();
+
++ if (pmd_huge(*pmd))
++ return 0;
++
+ pte_ref = pte_offset_kernel(pmd_ref, address);
+ if (!pte_present(*pte_ref))
+ return -1;
+diff --git a/block/bio.c b/block/bio.c
+index 4441522ca339..cbce3e2208f4 100644
+--- a/block/bio.c
++++ b/block/bio.c
+@@ -1122,9 +1122,12 @@ int bio_uncopy_user(struct bio *bio)
+ if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+ /*
+ * if we're in a workqueue, the request is orphaned, so
+- * don't copy into a random user address space, just free.
++ * don't copy into a random user address space, just free
++ * and return -EINTR so user space doesn't expect any data.
+ */
+- if (current->mm && bio_data_dir(bio) == READ)
++ if (!current->mm)
++ ret = -EINTR;
++ else if (bio_data_dir(bio) == READ)
+ ret = bio_copy_to_iter(bio, bmd->iter);
+ if (bmd->is_our_pages)
+ bio_free_pages(bio);
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index 5bc42f9b23f0..c0f03562a145 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -31,6 +31,11 @@ struct skcipher_sg_list {
+ struct scatterlist sg[0];
+ };
+
++struct skcipher_tfm {
++ struct crypto_ablkcipher *skcipher;
++ bool has_key;
++};
++
+ struct skcipher_ctx {
+ struct list_head tsgl;
+ struct af_alg_sgl rsgl;
+@@ -750,19 +755,139 @@ static struct proto_ops algif_skcipher_ops = {
+ .poll = skcipher_poll,
+ };
+
++static int skcipher_check_key(struct socket *sock)
++{
++ int err = 0;
++ struct sock *psk;
++ struct alg_sock *pask;
++ struct skcipher_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 skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t size)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_sendmsg(sock, msg, size);
++}
++
++static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
++ int offset, size_t size, int flags)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_sendpage(sock, page, offset, size, flags);
++}
++
++static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t ignored, int flags)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_recvmsg(sock, msg, ignored, flags);
++}
++
++static struct proto_ops algif_skcipher_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 = skcipher_sendmsg_nokey,
++ .sendpage = skcipher_sendpage_nokey,
++ .recvmsg = skcipher_recvmsg_nokey,
++ .poll = skcipher_poll,
++};
++
+ static void *skcipher_bind(const char *name, u32 type, u32 mask)
+ {
+- return crypto_alloc_ablkcipher(name, type, mask);
++ struct skcipher_tfm *tfm;
++ struct crypto_ablkcipher *skcipher;
++
++ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
++ if (!tfm)
++ return ERR_PTR(-ENOMEM);
++
++ skcipher = crypto_alloc_ablkcipher(name, type, mask);
++ if (IS_ERR(skcipher)) {
++ kfree(tfm);
++ return ERR_CAST(skcipher);
++ }
++
++ tfm->skcipher = skcipher;
++
++ return tfm;
+ }
+
+ static void skcipher_release(void *private)
+ {
+- crypto_free_ablkcipher(private);
++ struct skcipher_tfm *tfm = private;
++
++ crypto_free_ablkcipher(tfm->skcipher);
++ kfree(tfm);
+ }
+
+ static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
+ {
+- return crypto_ablkcipher_setkey(private, key, keylen);
++ struct skcipher_tfm *tfm = private;
++ int err;
++
++ err = crypto_ablkcipher_setkey(tfm->skcipher, key, keylen);
++ tfm->has_key = !err;
++
++ return err;
+ }
+
+ static void skcipher_wait(struct sock *sk)
+@@ -790,24 +915,26 @@ static void skcipher_sock_destruct(struct sock *sk)
+ af_alg_release_parent(sk);
+ }
+
+-static int skcipher_accept_parent(void *private, struct sock *sk)
++static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
+ {
+ struct skcipher_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+- unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private);
++ struct skcipher_tfm *tfm = private;
++ struct crypto_ablkcipher *skcipher = tfm->skcipher;
++ unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(skcipher);
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+- ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
++ ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(skcipher),
+ GFP_KERNEL);
+ if (!ctx->iv) {
+ sock_kfree_s(sk, ctx, len);
+ return -ENOMEM;
+ }
+
+- memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private));
++ memset(ctx->iv, 0, crypto_ablkcipher_ivsize(skcipher));
+
+ INIT_LIST_HEAD(&ctx->tsgl);
+ ctx->len = len;
+@@ -820,7 +947,7 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
+
+ ask->private = ctx;
+
+- ablkcipher_request_set_tfm(&ctx->req, private);
++ ablkcipher_request_set_tfm(&ctx->req, skcipher);
+ ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);
+
+@@ -829,12 +956,24 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
+ return 0;
+ }
+
++static int skcipher_accept_parent(void *private, struct sock *sk)
++{
++ struct skcipher_tfm *tfm = private;
++
++ if (!tfm->has_key)
++ return -ENOKEY;
++
++ return skcipher_accept_parent_nokey(private, sk);
++}
++
+ static const struct af_alg_type algif_type_skcipher = {
+ .bind = skcipher_bind,
+ .release = skcipher_release,
+ .setkey = skcipher_setkey,
+ .accept = skcipher_accept_parent,
++ .accept_nokey = skcipher_accept_parent_nokey,
+ .ops = &algif_skcipher_ops,
++ .ops_nokey = &algif_skcipher_ops_nokey,
+ .name = "skcipher",
+ .owner = THIS_MODULE
+ };
+diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
+index edf2e3ea1740..6a050e12fcdf 100644
+--- a/crypto/crypto_user.c
++++ b/crypto/crypto_user.c
+@@ -499,6 +499,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ if (link->dump == NULL)
+ return -EINVAL;
+
++ down_read(&crypto_alg_sem);
+ list_for_each_entry(alg, &crypto_alg_list, cra_list)
+ dump_alloc += CRYPTO_REPORT_MAXSIZE;
+
+@@ -508,8 +509,11 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ .done = link->done,
+ .min_dump_alloc = dump_alloc,
+ };
+- return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
++ err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
+ }
++ up_read(&crypto_alg_sem);
++
++ return err;
+ }
+
+ err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index e6ea912aee31..666fd8a1500a 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -262,6 +262,26 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index 287c4ba0219f..49840264dd57 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -495,8 +495,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
+ }
+ }
+
+- /* fabricate port_map from cap.nr_ports */
+- if (!port_map) {
++ /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
++ if (!port_map && vers < 0x10300) {
+ port_map = (1 << ahci_nr_ports(cap)) - 1;
+ dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
+
+diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
+index cdf6215a9a22..7dbba387d12a 100644
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap,
+ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+ struct ata_port *ap = qc->ap;
+- unsigned long flags;
+
+ if (ap->ops->error_handler) {
+ if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+-
+ /* EH might have kicked in while host lock is
+ * released.
+ */
+@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ } else
+ ata_port_freeze(ap);
+ }
+-
+- spin_unlock_irqrestore(ap->lock, flags);
+ } else {
+ if (likely(!(qc->err_mask & AC_ERR_HSM)))
+ ata_qc_complete(qc);
+@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ }
+ } else {
+ if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+ ata_sff_irq_on(ap);
+ ata_qc_complete(qc);
+- spin_unlock_irqrestore(ap->lock, flags);
+ } else
+ ata_qc_complete(qc);
+ }
+@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+ {
+ struct ata_link *link = qc->dev->link;
+ struct ata_eh_info *ehi = &link->eh_info;
+- unsigned long flags = 0;
+ int poll_next;
+
++ lockdep_assert_held(ap->lock);
++
+ WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+
+ /* Make sure ata_sff_qc_issue() does not throw things
+@@ -1112,14 +1106,6 @@ fsm_start:
+ }
+ }
+
+- /* Send the CDB (atapi) or the first data block (ata pio out).
+- * During the state transition, interrupt handler shouldn't
+- * be invoked before the data transfer is complete and
+- * hsm_task_state is changed. Hence, the following locking.
+- */
+- if (in_wq)
+- spin_lock_irqsave(ap->lock, flags);
+-
+ if (qc->tf.protocol == ATA_PROT_PIO) {
+ /* PIO data out protocol.
+ * send first data block.
+@@ -1135,9 +1121,6 @@ fsm_start:
+ /* send CDB */
+ atapi_send_cdb(ap, qc);
+
+- if (in_wq)
+- spin_unlock_irqrestore(ap->lock, flags);
+-
+ /* if polling, ata_sff_pio_task() handles the rest.
+ * otherwise, interrupt handler takes over from here.
+ */
+@@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work_struct *work)
+ u8 status;
+ int poll_next;
+
++ spin_lock_irq(ap->lock);
++
+ BUG_ON(ap->sff_pio_task_link == NULL);
+ /* qc can be NULL if timeout occurred */
+ qc = ata_qc_from_tag(ap, link->active_tag);
+ if (!qc) {
+ ap->sff_pio_task_link = NULL;
+- return;
++ goto out_unlock;
+ }
+
+ fsm_start:
+@@ -1381,11 +1366,14 @@ fsm_start:
+ */
+ status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
+ if (status & ATA_BUSY) {
++ spin_unlock_irq(ap->lock);
+ ata_msleep(ap, 2);
++ spin_lock_irq(ap->lock);
++
+ status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
+ if (status & ATA_BUSY) {
+ ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
+- return;
++ goto out_unlock;
+ }
+ }
+
+@@ -1402,6 +1390,8 @@ fsm_start:
+ */
+ if (poll_next)
+ goto fsm_start;
++out_unlock:
++ spin_unlock_irq(ap->lock);
+ }
+
+ /**
+diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
+index 0f9a9dc06a83..fb16d812c8f5 100644
+--- a/drivers/crypto/atmel-aes.c
++++ b/drivers/crypto/atmel-aes.c
+@@ -260,7 +260,11 @@ static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
+
+ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
+ {
+- clk_prepare_enable(dd->iclk);
++ int err;
++
++ err = clk_prepare_enable(dd->iclk);
++ if (err)
++ return err;
+
+ if (!(dd->flags & AES_FLAGS_INIT)) {
+ atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
+@@ -1320,7 +1324,6 @@ static int atmel_aes_probe(struct platform_device *pdev)
+ struct crypto_platform_data *pdata;
+ struct device *dev = &pdev->dev;
+ struct resource *aes_res;
+- unsigned long aes_phys_size;
+ int err;
+
+ pdata = pdev->dev.platform_data;
+@@ -1337,7 +1340,7 @@ static int atmel_aes_probe(struct platform_device *pdev)
+ goto aes_dd_err;
+ }
+
+- aes_dd = kzalloc(sizeof(struct atmel_aes_dev), GFP_KERNEL);
++ aes_dd = devm_kzalloc(&pdev->dev, sizeof(*aes_dd), GFP_KERNEL);
+ if (aes_dd == NULL) {
+ dev_err(dev, "unable to alloc data struct.\n");
+ err = -ENOMEM;
+@@ -1368,36 +1371,35 @@ static int atmel_aes_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+ aes_dd->phys_base = aes_res->start;
+- aes_phys_size = resource_size(aes_res);
+
+ /* Get the IRQ */
+ aes_dd->irq = platform_get_irq(pdev, 0);
+ if (aes_dd->irq < 0) {
+ dev_err(dev, "no IRQ resource info\n");
+ err = aes_dd->irq;
+- goto aes_irq_err;
++ goto res_err;
+ }
+
+- err = request_irq(aes_dd->irq, atmel_aes_irq, IRQF_SHARED, "atmel-aes",
+- aes_dd);
++ err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq,
++ IRQF_SHARED, "atmel-aes", aes_dd);
+ if (err) {
+ dev_err(dev, "unable to request aes irq.\n");
+- goto aes_irq_err;
++ goto res_err;
+ }
+
+ /* Initializing the clock */
+- aes_dd->iclk = clk_get(&pdev->dev, "aes_clk");
++ aes_dd->iclk = devm_clk_get(&pdev->dev, "aes_clk");
+ if (IS_ERR(aes_dd->iclk)) {
+ dev_err(dev, "clock initialization failed.\n");
+ err = PTR_ERR(aes_dd->iclk);
+- goto clk_err;
++ goto res_err;
+ }
+
+- aes_dd->io_base = ioremap(aes_dd->phys_base, aes_phys_size);
++ aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
+ if (!aes_dd->io_base) {
+ dev_err(dev, "can't ioremap\n");
+ err = -ENOMEM;
+- goto aes_io_err;
++ goto res_err;
+ }
+
+ atmel_aes_hw_version_init(aes_dd);
+@@ -1434,17 +1436,9 @@ err_algs:
+ err_aes_dma:
+ atmel_aes_buff_cleanup(aes_dd);
+ err_aes_buff:
+- iounmap(aes_dd->io_base);
+-aes_io_err:
+- clk_put(aes_dd->iclk);
+-clk_err:
+- free_irq(aes_dd->irq, aes_dd);
+-aes_irq_err:
+ res_err:
+ tasklet_kill(&aes_dd->done_task);
+ tasklet_kill(&aes_dd->queue_task);
+- kfree(aes_dd);
+- aes_dd = NULL;
+ aes_dd_err:
+ dev_err(dev, "initialization failed.\n");
+
+@@ -1469,16 +1463,6 @@ static int atmel_aes_remove(struct platform_device *pdev)
+
+ atmel_aes_dma_cleanup(aes_dd);
+
+- iounmap(aes_dd->io_base);
+-
+- clk_put(aes_dd->iclk);
+-
+- if (aes_dd->irq > 0)
+- free_irq(aes_dd->irq, aes_dd);
+-
+- kfree(aes_dd);
+- aes_dd = NULL;
+-
+ return 0;
+ }
+
+diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
+index 5b35433c5399..a71c97c03c39 100644
+--- a/drivers/crypto/atmel-sha.c
++++ b/drivers/crypto/atmel-sha.c
+@@ -783,7 +783,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err)
+ dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
+ SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+
+- clk_disable_unprepare(dd->iclk);
++ clk_disable(dd->iclk);
+
+ if (req->base.complete)
+ req->base.complete(&req->base, err);
+@@ -794,7 +794,11 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err)
+
+ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
+ {
+- clk_prepare_enable(dd->iclk);
++ int err;
++
++ err = clk_enable(dd->iclk);
++ if (err)
++ return err;
+
+ if (!(SHA_FLAGS_INIT & dd->flags)) {
+ atmel_sha_write(dd, SHA_CR, SHA_CR_SWRST);
+@@ -819,7 +823,7 @@ static void atmel_sha_hw_version_init(struct atmel_sha_dev *dd)
+ dev_info(dd->dev,
+ "version: 0x%x\n", dd->hw_version);
+
+- clk_disable_unprepare(dd->iclk);
++ clk_disable(dd->iclk);
+ }
+
+ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
+@@ -1345,11 +1349,9 @@ static int atmel_sha_probe(struct platform_device *pdev)
+ struct crypto_platform_data *pdata;
+ struct device *dev = &pdev->dev;
+ struct resource *sha_res;
+- unsigned long sha_phys_size;
+ int err;
+
+- sha_dd = devm_kzalloc(&pdev->dev, sizeof(struct atmel_sha_dev),
+- GFP_KERNEL);
++ sha_dd = devm_kzalloc(&pdev->dev, sizeof(*sha_dd), GFP_KERNEL);
+ if (sha_dd == NULL) {
+ dev_err(dev, "unable to alloc data struct.\n");
+ err = -ENOMEM;
+@@ -1378,7 +1380,6 @@ static int atmel_sha_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+ sha_dd->phys_base = sha_res->start;
+- sha_phys_size = resource_size(sha_res);
+
+ /* Get the IRQ */
+ sha_dd->irq = platform_get_irq(pdev, 0);
+@@ -1388,28 +1389,32 @@ static int atmel_sha_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+
+- err = request_irq(sha_dd->irq, atmel_sha_irq, IRQF_SHARED, "atmel-sha",
+- sha_dd);
++ err = devm_request_irq(&pdev->dev, sha_dd->irq, atmel_sha_irq,
++ IRQF_SHARED, "atmel-sha", sha_dd);
+ if (err) {
+ dev_err(dev, "unable to request sha irq.\n");
+ goto res_err;
+ }
+
+ /* Initializing the clock */
+- sha_dd->iclk = clk_get(&pdev->dev, "sha_clk");
++ sha_dd->iclk = devm_clk_get(&pdev->dev, "sha_clk");
+ if (IS_ERR(sha_dd->iclk)) {
+ dev_err(dev, "clock initialization failed.\n");
+ err = PTR_ERR(sha_dd->iclk);
+- goto clk_err;
++ goto res_err;
+ }
+
+- sha_dd->io_base = ioremap(sha_dd->phys_base, sha_phys_size);
++ sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res);
+ if (!sha_dd->io_base) {
+ dev_err(dev, "can't ioremap\n");
+ err = -ENOMEM;
+- goto sha_io_err;
++ goto res_err;
+ }
+
++ err = clk_prepare(sha_dd->iclk);
++ if (err)
++ goto res_err;
++
+ atmel_sha_hw_version_init(sha_dd);
+
+ atmel_sha_get_cap(sha_dd);
+@@ -1421,12 +1426,12 @@ static int atmel_sha_probe(struct platform_device *pdev)
+ if (IS_ERR(pdata)) {
+ dev_err(&pdev->dev, "platform data not available\n");
+ err = PTR_ERR(pdata);
+- goto err_pdata;
++ goto iclk_unprepare;
+ }
+ }
+ if (!pdata->dma_slave) {
+ err = -ENXIO;
+- goto err_pdata;
++ goto iclk_unprepare;
+ }
+ err = atmel_sha_dma_init(sha_dd, pdata);
+ if (err)
+@@ -1457,12 +1462,8 @@ err_algs:
+ if (sha_dd->caps.has_dma)
+ atmel_sha_dma_cleanup(sha_dd);
+ err_sha_dma:
+-err_pdata:
+- iounmap(sha_dd->io_base);
+-sha_io_err:
+- clk_put(sha_dd->iclk);
+-clk_err:
+- free_irq(sha_dd->irq, sha_dd);
++iclk_unprepare:
++ clk_unprepare(sha_dd->iclk);
+ res_err:
+ tasklet_kill(&sha_dd->done_task);
+ sha_dd_err:
+@@ -1489,6 +1490,8 @@ static int atmel_sha_remove(struct platform_device *pdev)
+ if (sha_dd->caps.has_dma)
+ atmel_sha_dma_cleanup(sha_dd);
+
++ clk_unprepare(sha_dd->iclk);
++
+ iounmap(sha_dd->io_base);
+
+ clk_put(sha_dd->iclk);
+diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
+index ca2999709eb4..2c7a628d0375 100644
+--- a/drivers/crypto/atmel-tdes.c
++++ b/drivers/crypto/atmel-tdes.c
+@@ -218,7 +218,11 @@ static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx)
+
+ static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
+ {
+- clk_prepare_enable(dd->iclk);
++ int err;
++
++ err = clk_prepare_enable(dd->iclk);
++ if (err)
++ return err;
+
+ if (!(dd->flags & TDES_FLAGS_INIT)) {
+ atmel_tdes_write(dd, TDES_CR, TDES_CR_SWRST);
+@@ -1355,7 +1359,6 @@ static int atmel_tdes_probe(struct platform_device *pdev)
+ struct crypto_platform_data *pdata;
+ struct device *dev = &pdev->dev;
+ struct resource *tdes_res;
+- unsigned long tdes_phys_size;
+ int err;
+
+ tdes_dd = devm_kmalloc(&pdev->dev, sizeof(*tdes_dd), GFP_KERNEL);
+@@ -1389,7 +1392,6 @@ static int atmel_tdes_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+ tdes_dd->phys_base = tdes_res->start;
+- tdes_phys_size = resource_size(tdes_res);
+
+ /* Get the IRQ */
+ tdes_dd->irq = platform_get_irq(pdev, 0);
+@@ -1399,26 +1401,26 @@ static int atmel_tdes_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+
+- err = request_irq(tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED,
+- "atmel-tdes", tdes_dd);
++ err = devm_request_irq(&pdev->dev, tdes_dd->irq, atmel_tdes_irq,
++ IRQF_SHARED, "atmel-tdes", tdes_dd);
+ if (err) {
+ dev_err(dev, "unable to request tdes irq.\n");
+- goto tdes_irq_err;
++ goto res_err;
+ }
+
+ /* Initializing the clock */
+- tdes_dd->iclk = clk_get(&pdev->dev, "tdes_clk");
++ tdes_dd->iclk = devm_clk_get(&pdev->dev, "tdes_clk");
+ if (IS_ERR(tdes_dd->iclk)) {
+ dev_err(dev, "clock initialization failed.\n");
+ err = PTR_ERR(tdes_dd->iclk);
+- goto clk_err;
++ goto res_err;
+ }
+
+- tdes_dd->io_base = ioremap(tdes_dd->phys_base, tdes_phys_size);
++ tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res);
+ if (!tdes_dd->io_base) {
+ dev_err(dev, "can't ioremap\n");
+ err = -ENOMEM;
+- goto tdes_io_err;
++ goto res_err;
+ }
+
+ atmel_tdes_hw_version_init(tdes_dd);
+@@ -1474,12 +1476,6 @@ err_tdes_dma:
+ err_pdata:
+ atmel_tdes_buff_cleanup(tdes_dd);
+ err_tdes_buff:
+- iounmap(tdes_dd->io_base);
+-tdes_io_err:
+- clk_put(tdes_dd->iclk);
+-clk_err:
+- free_irq(tdes_dd->irq, tdes_dd);
+-tdes_irq_err:
+ res_err:
+ tasklet_kill(&tdes_dd->done_task);
+ tasklet_kill(&tdes_dd->queue_task);
+@@ -1510,13 +1506,6 @@ static int atmel_tdes_remove(struct platform_device *pdev)
+
+ atmel_tdes_buff_cleanup(tdes_dd);
+
+- iounmap(tdes_dd->io_base);
+-
+- clk_put(tdes_dd->iclk);
+-
+- if (tdes_dd->irq >= 0)
+- free_irq(tdes_dd->irq, tdes_dd);
+-
+ return 0;
+ }
+
+diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
+index 303d937d63c7..ebffc744cb1b 100644
+--- a/drivers/dma/dw/core.c
++++ b/drivers/dma/dw/core.c
+@@ -156,7 +156,6 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
+
+ /* Enable interrupts */
+ channel_set_bit(dw, MASK.XFER, dwc->mask);
+- channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_set_bit(dw, MASK.ERROR, dwc->mask);
+
+ dwc->initialized = true;
+@@ -588,6 +587,9 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+ }
++
++ /* Re-enable interrupts */
++ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+ }
+
+ /* ------------------------------------------------------------------------- */
+@@ -618,11 +620,8 @@ static void dw_dma_tasklet(unsigned long data)
+ dwc_scan_descriptors(dw, dwc);
+ }
+
+- /*
+- * Re-enable interrupts.
+- */
++ /* Re-enable interrupts */
+ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
+- channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
+ }
+
+@@ -1256,6 +1255,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
+ int dw_dma_cyclic_start(struct dma_chan *chan)
+ {
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
++ struct dw_dma *dw = to_dw_dma(chan->device);
+ unsigned long flags;
+
+ if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) {
+@@ -1264,7 +1264,12 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
+ }
+
+ spin_lock_irqsave(&dwc->lock, flags);
++
++ /* Enable interrupts to perform cyclic transfer */
++ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
++
+ dwc_dostart(dwc, dwc->cdesc->desc[0]);
++
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ return 0;
+diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+index d2cd8d5b27a1..82f8e20cca74 100644
+--- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
++++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+@@ -207,7 +207,12 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
+ gpio = *data++;
+
+ /* pull up/down */
+- action = *data++;
++ action = *data++ & 1;
++
++ if (gpio >= ARRAY_SIZE(gtable)) {
++ DRM_DEBUG_KMS("unknown gpio %u\n", gpio);
++ goto out;
++ }
+
+ function = gtable[gpio].function_reg;
+ pad = gtable[gpio].pad_reg;
+@@ -226,6 +231,7 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
+ vlv_gpio_nc_write(dev_priv, pad, val);
+ mutex_unlock(&dev_priv->dpio_lock);
+
++out:
+ return data;
+ }
+
+diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
+index 7354a4cda59d..3aefaa058f0c 100644
+--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
++++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
+@@ -168,7 +168,8 @@ static int qxl_process_single_command(struct qxl_device *qdev,
+ cmd->command_size))
+ return -EFAULT;
+
+- reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL);
++ reloc_info = kmalloc_array(cmd->relocs_num,
++ sizeof(struct qxl_reloc_info), GFP_KERNEL);
+ if (!reloc_info)
+ return -ENOMEM;
+
+diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c
+index c507896aca45..197b157b73d0 100644
+--- a/drivers/gpu/drm/radeon/radeon_sa.c
++++ b/drivers/gpu/drm/radeon/radeon_sa.c
+@@ -349,8 +349,13 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
+ /* see if we can skip over some allocations */
+ } while (radeon_sa_bo_next_hole(sa_manager, fences, tries));
+
++ for (i = 0; i < RADEON_NUM_RINGS; ++i)
++ radeon_fence_ref(fences[i]);
++
+ spin_unlock(&sa_manager->wq.lock);
+ r = radeon_fence_wait_any(rdev, fences, false);
++ for (i = 0; i < RADEON_NUM_RINGS; ++i)
++ radeon_fence_unref(&fences[i]);
+ spin_lock(&sa_manager->wq.lock);
+ /* if we have nothing to wait for block */
+ if (r == -ENOENT) {
+diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
+index edafd3c2b170..f5c0590bbf73 100644
+--- a/drivers/gpu/drm/radeon/radeon_ttm.c
++++ b/drivers/gpu/drm/radeon/radeon_ttm.c
+@@ -758,7 +758,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
+ 0, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) {
+- while (--i) {
++ while (i--) {
+ pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i],
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ gtt->ttm.dma_address[i] = 0;
+diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
+index c32a934f7693..353e2ab090ee 100644
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -1349,7 +1349,7 @@ sequence_cmd:
+ if (!rc && dump_payload == false && unsol_data)
+ iscsit_set_unsoliticed_dataout(cmd);
+ else if (dump_payload && imm_data)
+- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
++ target_put_sess_cmd(&cmd->se_cmd);
+
+ return 0;
+ }
+@@ -1774,7 +1774,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
+ cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+- target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+ }
+ }
+
+@@ -1947,7 +1947,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
+ spin_unlock_bh(&cmd->istate_lock);
+
+ if (ret) {
+- target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+ transport_send_check_condition_and_sense(se_cmd,
+ se_cmd->pi_err, 0);
+ } else {
+diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
+index 9b84b4c0a000..6fbc7bc824d2 100644
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -1334,7 +1334,7 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
+
+ BUG_ON(ch->sess == NULL);
+
+- target_put_sess_cmd(ch->sess, &ioctx->cmd);
++ target_put_sess_cmd(&ioctx->cmd);
+ goto out;
+ }
+
+@@ -1365,11 +1365,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
+ * not been received in time.
+ */
+ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
+- target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
++ target_put_sess_cmd(&ioctx->cmd);
+ break;
+ case SRPT_STATE_MGMT_RSP_SENT:
+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+- target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
++ target_put_sess_cmd(&ioctx->cmd);
+ break;
+ default:
+ WARN(1, "Unexpected command state (%d)", state);
+@@ -1679,7 +1679,7 @@ static int srpt_check_stop_free(struct se_cmd *cmd)
+ struct srpt_send_ioctx *ioctx = container_of(cmd,
+ struct srpt_send_ioctx, cmd);
+
+- return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
++ return target_put_sess_cmd(&ioctx->cmd);
+ }
+
+ /**
+@@ -3074,7 +3074,7 @@ static void srpt_queue_response(struct se_cmd *cmd)
+ ioctx->tag);
+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+- target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
++ target_put_sess_cmd(&ioctx->cmd);
+ }
+ }
+
+diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
+index e272f06258ce..a3f0f5a47490 100644
+--- a/drivers/input/mouse/vmmouse.c
++++ b/drivers/input/mouse/vmmouse.c
+@@ -458,8 +458,6 @@ int vmmouse_init(struct psmouse *psmouse)
+ priv->abs_dev = abs_dev;
+ psmouse->private = priv;
+
+- input_set_capability(rel_dev, EV_REL, REL_WHEEL);
+-
+ /* Set up and register absolute device */
+ snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
+ psmouse->ps2dev.serio->phys);
+@@ -475,10 +473,6 @@ int vmmouse_init(struct psmouse *psmouse)
+ abs_dev->id.version = psmouse->model;
+ abs_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+
+- error = input_register_device(priv->abs_dev);
+- if (error)
+- goto init_fail;
+-
+ /* Set absolute device capabilities */
+ input_set_capability(abs_dev, EV_KEY, BTN_LEFT);
+ input_set_capability(abs_dev, EV_KEY, BTN_RIGHT);
+@@ -488,6 +482,13 @@ int vmmouse_init(struct psmouse *psmouse)
+ input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0);
+ input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0);
+
++ error = input_register_device(priv->abs_dev);
++ if (error)
++ goto init_fail;
++
++ /* Add wheel capability to the relative device */
++ input_set_capability(rel_dev, EV_REL, REL_WHEEL);
++
+ psmouse->protocol_handler = vmmouse_process_byte;
+ psmouse->disconnect = vmmouse_disconnect;
+ psmouse->reconnect = vmmouse_reconnect;
+diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
+index 9847613085e1..5a2ec39e1fd9 100644
+--- a/drivers/iommu/dmar.c
++++ b/drivers/iommu/dmar.c
+@@ -1342,7 +1342,7 @@ void dmar_disable_qi(struct intel_iommu *iommu)
+
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
+
+- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
++ sts = readl(iommu->reg + DMAR_GSTS_REG);
+ if (!(sts & DMA_GSTS_QIES))
+ goto end;
+
+diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
+index 5709ae9c3e77..04b39be8f1f3 100644
+--- a/drivers/iommu/intel_irq_remapping.c
++++ b/drivers/iommu/intel_irq_remapping.c
+@@ -544,7 +544,7 @@ static void iommu_disable_irq_remapping(struct intel_iommu *iommu)
+
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
+
+- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
++ sts = readl(iommu->reg + DMAR_GSTS_REG);
+ if (!(sts & DMA_GSTS_IRES))
+ goto end;
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 72ba774df7a7..bd744e31c434 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -214,6 +214,8 @@ static void bond_uninit(struct net_device *bond_dev);
+ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
+ struct rtnl_link_stats64 *stats);
+ static void bond_slave_arr_handler(struct work_struct *work);
++static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act,
++ int mod);
+
+ /*---------------------------- General routines -----------------------------*/
+
+@@ -2397,7 +2399,7 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
+ struct slave *slave)
+ {
+ struct arphdr *arp = (struct arphdr *)skb->data;
+- struct slave *curr_active_slave;
++ struct slave *curr_active_slave, *curr_arp_slave;
+ unsigned char *arp_ptr;
+ __be32 sip, tip;
+ int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
+@@ -2444,26 +2446,41 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
+ &sip, &tip);
+
+ curr_active_slave = rcu_dereference(bond->curr_active_slave);
++ curr_arp_slave = rcu_dereference(bond->current_arp_slave);
+
+- /* Backup slaves won't see the ARP reply, but do come through
+- * here for each ARP probe (so we swap the sip/tip to validate
+- * the probe). In a "redundant switch, common router" type of
+- * configuration, the ARP probe will (hopefully) travel from
+- * the active, through one switch, the router, then the other
+- * switch before reaching the backup.
++ /* We 'trust' the received ARP enough to validate it if:
++ *
++ * (a) the slave receiving the ARP is active (which includes the
++ * current ARP slave, if any), or
++ *
++ * (b) the receiving slave isn't active, but there is a currently
++ * active slave and it received valid arp reply(s) after it became
++ * the currently active slave, or
++ *
++ * (c) there is an ARP slave that sent an ARP during the prior ARP
++ * interval, and we receive an ARP reply on any slave. We accept
++ * these because switch FDB update delays may deliver the ARP
++ * reply to a slave other than the sender of the ARP request.
+ *
+- * We 'trust' the arp requests if there is an active slave and
+- * it received valid arp reply(s) after it became active. This
+- * is done to avoid endless looping when we can't reach the
++ * Note: for (b), backup slaves are receiving the broadcast ARP
++ * request, not a reply. This request passes from the sending
++ * slave through the L2 switch(es) to the receiving slave. Since
++ * this is checking the request, sip/tip are swapped for
++ * validation.
++ *
++ * This is done to avoid endless looping when we can't reach the
+ * arp_ip_target and fool ourselves with our own arp requests.
+ */
+-
+ if (bond_is_active_slave(slave))
+ bond_validate_arp(bond, slave, sip, tip);
+ else if (curr_active_slave &&
+ time_after(slave_last_rx(bond, curr_active_slave),
+ curr_active_slave->last_link_up))
+ bond_validate_arp(bond, slave, tip, sip);
++ else if (curr_arp_slave && (arp->ar_op == htons(ARPOP_REPLY)) &&
++ bond_time_in_interval(bond,
++ dev_trans_start(curr_arp_slave->dev), 1))
++ bond_validate_arp(bond, slave, sip, tip);
+
+ out_unlock:
+ if (arp != (struct arphdr *)skb->data)
+diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
+index 0d8af5bb5907..d5415205779f 100644
+--- a/drivers/net/ethernet/broadcom/tg3.c
++++ b/drivers/net/ethernet/broadcom/tg3.c
+@@ -7833,6 +7833,14 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
+ return ret;
+ }
+
++static bool tg3_tso_bug_gso_check(struct tg3_napi *tnapi, struct sk_buff *skb)
++{
++ /* Check if we will never have enough descriptors,
++ * as gso_segs can be more than current ring size
++ */
++ return skb_shinfo(skb)->gso_segs < tnapi->tx_pending / 3;
++}
++
+ static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
+
+ /* Use GSO to workaround all TSO packets that meet HW bug conditions
+@@ -7936,14 +7944,19 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ * vlan encapsulated.
+ */
+ if (skb->protocol == htons(ETH_P_8021Q) ||
+- skb->protocol == htons(ETH_P_8021AD))
+- return tg3_tso_bug(tp, tnapi, txq, skb);
++ skb->protocol == htons(ETH_P_8021AD)) {
++ if (tg3_tso_bug_gso_check(tnapi, skb))
++ return tg3_tso_bug(tp, tnapi, txq, skb);
++ goto drop;
++ }
+
+ if (!skb_is_gso_v6(skb)) {
+ if (unlikely((ETH_HLEN + hdr_len) > 80) &&
+- tg3_flag(tp, TSO_BUG))
+- return tg3_tso_bug(tp, tnapi, txq, skb);
+-
++ tg3_flag(tp, TSO_BUG)) {
++ if (tg3_tso_bug_gso_check(tnapi, skb))
++ return tg3_tso_bug(tp, tnapi, txq, skb);
++ goto drop;
++ }
+ ip_csum = iph->check;
+ ip_tot_len = iph->tot_len;
+ iph->check = 0;
+@@ -8075,7 +8088,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ if (would_hit_hwbug) {
+ tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
+
+- if (mss) {
++ if (mss && tg3_tso_bug_gso_check(tnapi, skb)) {
+ /* If it's a TSO packet, do GSO instead of
+ * allocating and copying to a large linear SKB
+ */
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+index 8a083d73efdb..dae2ebb53af7 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+@@ -236,6 +236,24 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = {
+ .enable = mlx4_en_phc_enable,
+ };
+
++#define MLX4_EN_WRAP_AROUND_SEC 10ULL
++
++/* This function calculates the max shift that enables the user range
++ * of MLX4_EN_WRAP_AROUND_SEC values in the cycles register.
++ */
++static u32 freq_to_shift(u16 freq)
++{
++ u32 freq_khz = freq * 1000;
++ u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC;
++ u64 max_val_cycles_rounded = is_power_of_2(max_val_cycles + 1) ?
++ max_val_cycles : roundup_pow_of_two(max_val_cycles) - 1;
++ /* calculate max possible multiplier in order to fit in 64bit */
++ u64 max_mul = div_u64(0xffffffffffffffffULL, max_val_cycles_rounded);
++
++ /* This comes from the reverse of clocksource_khz2mult */
++ return ilog2(div_u64(max_mul * freq_khz, 1000000));
++}
++
+ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
+ {
+ struct mlx4_dev *dev = mdev->dev;
+@@ -247,12 +265,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
+ memset(&mdev->cycles, 0, sizeof(mdev->cycles));
+ mdev->cycles.read = mlx4_en_read_clock;
+ mdev->cycles.mask = CLOCKSOURCE_MASK(48);
+- /* Using shift to make calculation more accurate. Since current HW
+- * clock frequency is 427 MHz, and cycles are given using a 48 bits
+- * register, the biggest shift when calculating using u64, is 14
+- * (max_cycles * multiplier < 2^64)
+- */
+- mdev->cycles.shift = 14;
++ mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock);
+ mdev->cycles.mult =
+ clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
+ mdev->nominal_c_mult = mdev->cycles.mult;
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index a5a0b8420d26..e9189597000d 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -2330,8 +2330,6 @@ out:
+ /* set offloads */
+ priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL;
+- priv->dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+- priv->dev->features |= NETIF_F_GSO_UDP_TUNNEL;
+ }
+
+ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
+@@ -2342,8 +2340,6 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
+ /* unset offloads */
+ priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL);
+- priv->dev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL;
+- priv->dev->features &= ~NETIF_F_GSO_UDP_TUNNEL;
+
+ ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
+ VXLAN_STEER_BY_OUTER_MAC, 0);
+@@ -2940,6 +2936,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ priv->rss_hash_fn = ETH_RSS_HASH_TOP;
+ }
+
++ if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
++ dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
++ dev->features |= NETIF_F_GSO_UDP_TUNNEL;
++ }
++
+ mdev->pndev[port] = dev;
+ mdev->upper[port] = NULL;
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c
+index 0a56f010c846..760a8b387912 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_port.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c
+@@ -223,11 +223,11 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
+ stats->collisions = 0;
+ stats->rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP);
+ stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
+- stats->rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
++ stats->rx_over_errors = 0;
+ stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
+ stats->rx_frame_errors = 0;
+ stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+- stats->rx_missed_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
++ stats->rx_missed_errors = 0;
+ stats->tx_aborted_errors = 0;
+ stats->tx_carrier_errors = 0;
+ stats->tx_fifo_errors = 0;
+diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
+index 73b6fc21ea00..4fedf7fa72c4 100644
+--- a/drivers/net/ethernet/rocker/rocker.c
++++ b/drivers/net/ethernet/rocker/rocker.c
+@@ -3384,12 +3384,14 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
+ info.addr = lw->addr;
+ info.vid = lw->vid;
+
++ rtnl_lock();
+ if (learned && removing)
+ call_netdev_switch_notifiers(NETDEV_SWITCH_FDB_DEL,
+ lw->dev, &info.info);
+ else if (learned && !removing)
+ call_netdev_switch_notifiers(NETDEV_SWITCH_FDB_ADD,
+ lw->dev, &info.info);
++ rtnl_unlock();
+
+ kfree(work);
+ }
+diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
+index 00cb41e71312..c56cf0b86f2c 100644
+--- a/drivers/net/phy/dp83640.c
++++ b/drivers/net/phy/dp83640.c
+@@ -833,6 +833,11 @@ static void decode_rxts(struct dp83640_private *dp83640,
+ struct skb_shared_hwtstamps *shhwtstamps = NULL;
+ struct sk_buff *skb;
+ unsigned long flags;
++ u8 overflow;
++
++ overflow = (phy_rxts->ns_hi >> 14) & 0x3;
++ if (overflow)
++ pr_debug("rx timestamp queue overflow, count %d\n", overflow);
+
+ spin_lock_irqsave(&dp83640->rx_lock, flags);
+
+@@ -875,6 +880,7 @@ static void decode_txts(struct dp83640_private *dp83640,
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sk_buff *skb;
+ u64 ns;
++ u8 overflow;
+
+ /* We must already have the skb that triggered this. */
+
+@@ -884,6 +890,17 @@ static void decode_txts(struct dp83640_private *dp83640,
+ pr_debug("have timestamp but tx_queue empty\n");
+ return;
+ }
++
++ overflow = (phy_txts->ns_hi >> 14) & 0x3;
++ if (overflow) {
++ pr_debug("tx timestamp queue overflow, count %d\n", overflow);
++ while (skb) {
++ skb_complete_tx_timestamp(skb, NULL);
++ skb = skb_dequeue(&dp83640->tx_queue);
++ }
++ return;
++ }
++
+ ns = phy2txts(phy_txts);
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
+index 9c8fabed4444..d1c4bc1c4df0 100644
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -395,6 +395,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
+
+ if (!__pppoe_xmit(sk_pppox(relay_po), skb))
+ goto abort_put;
++
++ sock_put(sk_pppox(relay_po));
+ } else {
+ if (sock_queue_rcv_skb(sk, skb))
+ goto abort_kfree;
+diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
+index 0bacabfa486e..b35199cc8f34 100644
+--- a/drivers/net/ppp/pptp.c
++++ b/drivers/net/ppp/pptp.c
+@@ -131,24 +131,27 @@ static int lookup_chan_dst(u16 call_id, __be32 d_addr)
+ return i < MAX_CALLID;
+ }
+
+-static int add_chan(struct pppox_sock *sock)
++static int add_chan(struct pppox_sock *sock,
++ struct pptp_addr *sa)
+ {
+ static int call_id;
+
+ spin_lock(&chan_lock);
+- if (!sock->proto.pptp.src_addr.call_id) {
++ if (!sa->call_id) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+ if (call_id == MAX_CALLID) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+ if (call_id == MAX_CALLID)
+ goto out_err;
+ }
+- sock->proto.pptp.src_addr.call_id = call_id;
+- } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
++ sa->call_id = call_id;
++ } else if (test_bit(sa->call_id, callid_bitmap)) {
+ goto out_err;
++ }
+
+- set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+- rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
++ sock->proto.pptp.src_addr = *sa;
++ set_bit(sa->call_id, callid_bitmap);
++ rcu_assign_pointer(callid_sock[sa->call_id], sock);
+ spin_unlock(&chan_lock);
+
+ return 0;
+@@ -417,7 +420,6 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+- struct pptp_opt *opt = &po->proto.pptp;
+ int error = 0;
+
+ if (sockaddr_len < sizeof(struct sockaddr_pppox))
+@@ -425,10 +427,22 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
+
+ lock_sock(sk);
+
+- opt->src_addr = sp->sa_addr.pptp;
+- if (add_chan(po))
++ if (sk->sk_state & PPPOX_DEAD) {
++ error = -EALREADY;
++ goto out;
++ }
++
++ if (sk->sk_state & PPPOX_BOUND) {
+ error = -EBUSY;
++ goto out;
++ }
++
++ if (add_chan(po, &sp->sa_addr.pptp))
++ error = -EBUSY;
++ else
++ sk->sk_state |= PPPOX_BOUND;
+
++out:
+ release_sock(sk);
+ return error;
+ }
+@@ -499,7 +513,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
+ }
+
+ opt->dst_addr = sp->sa_addr.pptp;
+- sk->sk_state = PPPOX_CONNECTED;
++ sk->sk_state |= PPPOX_CONNECTED;
+
+ end:
+ release_sock(sk);
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 71190dc1eacf..cffb25280a3b 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -542,6 +542,7 @@ static const struct usb_device_id products[] = {
+
+ /* 3. Combined interface devices matching on interface number */
+ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
++ {QMI_FIXED_INTF(0x05c6, 0x6001, 3)}, /* 4G LTE usb-modem U901 */
+ {QMI_FIXED_INTF(0x05c6, 0x7000, 0)},
+ {QMI_FIXED_INTF(0x05c6, 0x7001, 1)},
+ {QMI_FIXED_INTF(0x05c6, 0x7002, 1)},
+diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
+index 0bf82a20a0fb..48d21e0edd56 100644
+--- a/drivers/pci/pcie/aer/aerdrv.c
++++ b/drivers/pci/pcie/aer/aerdrv.c
+@@ -262,7 +262,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
+ rpc->rpd = dev;
+ INIT_WORK(&rpc->dpc_handler, aer_isr);
+ mutex_init(&rpc->rpc_mutex);
+- init_waitqueue_head(&rpc->wait_release);
+
+ /* Use PCIe bus function to store rpc into PCIe device */
+ set_service_data(dev, rpc);
+@@ -285,8 +284,7 @@ static void aer_remove(struct pcie_device *dev)
+ if (rpc->isr)
+ free_irq(dev->irq, dev);
+
+- wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+-
++ flush_work(&rpc->dpc_handler);
+ aer_disable_rootport(rpc);
+ kfree(rpc);
+ set_service_data(dev, NULL);
+diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
+index 84420b7c9456..945c939a86c5 100644
+--- a/drivers/pci/pcie/aer/aerdrv.h
++++ b/drivers/pci/pcie/aer/aerdrv.h
+@@ -72,7 +72,6 @@ struct aer_rpc {
+ * recovery on the same
+ * root port hierarchy
+ */
+- wait_queue_head_t wait_release;
+ };
+
+ struct aer_broadcast_data {
+diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
+index 5653ea94547f..b60a325234c5 100644
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -784,8 +784,6 @@ void aer_isr(struct work_struct *work)
+ while (get_e_source(rpc, &e_src))
+ aer_isr_one_error(p_device, &e_src);
+ mutex_unlock(&rpc->rpc_mutex);
+-
+- wake_up(&rpc->wait_release);
+ }
+
+ /**
+diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
+index 63bc12d7a73e..153e0a27c7ee 100644
+--- a/drivers/phy/phy-core.c
++++ b/drivers/phy/phy-core.c
+@@ -275,20 +275,21 @@ EXPORT_SYMBOL_GPL(phy_exit);
+
+ int phy_power_on(struct phy *phy)
+ {
+- int ret;
++ int ret = 0;
+
+ if (!phy)
+- return 0;
++ goto out;
+
+ if (phy->pwr) {
+ ret = regulator_enable(phy->pwr);
+ if (ret)
+- return ret;
++ goto out;
+ }
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+- return ret;
++ goto err_pm_sync;
++
+ ret = 0; /* Override possible ret == -ENOTSUPP */
+
+ mutex_lock(&phy->mutex);
+@@ -296,19 +297,20 @@ int phy_power_on(struct phy *phy)
+ ret = phy->ops->power_on(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
+- goto out;
++ goto err_pwr_on;
+ }
+ }
+ ++phy->power_count;
+ mutex_unlock(&phy->mutex);
+ return 0;
+
+-out:
++err_pwr_on:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put_sync(phy);
++err_pm_sync:
+ if (phy->pwr)
+ regulator_disable(phy->pwr);
+-
++out:
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(phy_power_on);
+diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
+index 6285f46f3ddb..fb9e30ed8018 100644
+--- a/drivers/phy/phy-twl4030-usb.c
++++ b/drivers/phy/phy-twl4030-usb.c
+@@ -719,6 +719,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+ pm_runtime_enable(&pdev->dev);
++ pm_runtime_get_sync(&pdev->dev);
+
+ /* Our job is to use irqs and status from the power module
+ * to keep the transceiver disabled when nothing's connected.
+@@ -754,6 +755,7 @@ static int twl4030_usb_remove(struct platform_device *pdev)
+ struct twl4030_usb *twl = platform_get_drvdata(pdev);
+ int val;
+
++ usb_remove_phy(&twl->phy);
+ pm_runtime_get_sync(twl->dev);
+ cancel_delayed_work(&twl->id_workaround_work);
+ device_remove_file(twl->dev, &dev_attr_vbus);
+@@ -761,6 +763,13 @@ static int twl4030_usb_remove(struct platform_device *pdev)
+ /* set transceiver mode to power on defaults */
+ twl4030_usb_set_mode(twl, -1);
+
++ /* idle ulpi before powering off */
++ if (cable_present(twl->linkstat))
++ pm_runtime_put_noidle(twl->dev);
++ pm_runtime_mark_last_busy(twl->dev);
++ pm_runtime_put_sync_suspend(twl->dev);
++ pm_runtime_disable(twl->dev);
++
+ /* autogate 60MHz ULPI clock,
+ * clear dpll clock request for i2c access,
+ * disable 32KHz
+@@ -775,11 +784,6 @@ static int twl4030_usb_remove(struct platform_device *pdev)
+ /* disable complete OTG block */
+ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+
+- if (cable_present(twl->linkstat))
+- pm_runtime_put_noidle(twl->dev);
+- pm_runtime_mark_last_busy(twl->dev);
+- pm_runtime_put(twl->dev);
+-
+ return 0;
+ }
+
+diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
+index 02bc5a6343c3..aa454241489c 100644
+--- a/drivers/platform/x86/intel_scu_ipcutil.c
++++ b/drivers/platform/x86/intel_scu_ipcutil.c
+@@ -49,7 +49,7 @@ struct scu_ipc_data {
+
+ static int scu_reg_access(u32 cmd, struct scu_ipc_data *data)
+ {
+- int count = data->count;
++ unsigned int count = data->count;
+
+ if (count == 0 || count == 3 || count > 4)
+ return -EINVAL;
+diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
+index a2597e683e79..6a64e86e8ccd 100644
+--- a/drivers/s390/block/dasd_alias.c
++++ b/drivers/s390/block/dasd_alias.c
+@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
+ spin_unlock_irqrestore(&lcu->lock, flags);
+ cancel_work_sync(&lcu->suc_data.worker);
+ spin_lock_irqsave(&lcu->lock, flags);
+- if (device == lcu->suc_data.device)
++ if (device == lcu->suc_data.device) {
++ dasd_put_device(device);
+ lcu->suc_data.device = NULL;
++ }
+ }
+ was_pending = 0;
+ if (device == lcu->ruac_data.device) {
+@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
+ was_pending = 1;
+ cancel_delayed_work_sync(&lcu->ruac_data.dwork);
+ spin_lock_irqsave(&lcu->lock, flags);
+- if (device == lcu->ruac_data.device)
++ if (device == lcu->ruac_data.device) {
++ dasd_put_device(device);
+ lcu->ruac_data.device = NULL;
++ }
+ }
+ private->lcu = NULL;
+ spin_unlock_irqrestore(&lcu->lock, flags);
+@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work)
+ if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
+ DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
+ " alias data in lcu (rc = %d), retry later", rc);
+- schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
++ if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ))
++ dasd_put_device(device);
+ } else {
++ dasd_put_device(device);
+ lcu->ruac_data.device = NULL;
+ lcu->flags &= ~UPDATE_PENDING;
+ }
+@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu,
+ */
+ if (!usedev)
+ return -EINVAL;
++ dasd_get_device(usedev);
+ lcu->ruac_data.device = usedev;
+- schedule_delayed_work(&lcu->ruac_data.dwork, 0);
++ if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0))
++ dasd_put_device(usedev);
+ return 0;
+ }
+
+@@ -722,7 +730,7 @@ static int reset_summary_unit_check(struct alias_lcu *lcu,
+ ASCEBC((char *) &cqr->magic, 4);
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = DASD_ECKD_CCW_RSCK;
+- ccw->flags = 0 ;
++ ccw->flags = CCW_FLAG_SLI;
+ ccw->count = 16;
+ ccw->cda = (__u32)(addr_t) cqr->data;
+ ((char *)cqr->data)[0] = reason;
+@@ -926,6 +934,7 @@ static void summary_unit_check_handling_work(struct work_struct *work)
+ /* 3. read new alias configuration */
+ _schedule_lcu_update(lcu, device);
+ lcu->suc_data.device = NULL;
++ dasd_put_device(device);
+ spin_unlock_irqrestore(&lcu->lock, flags);
+ }
+
+@@ -985,6 +994,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
+ }
+ lcu->suc_data.reason = reason;
+ lcu->suc_data.device = device;
++ dasd_get_device(device);
+ spin_unlock(&lcu->lock);
+- schedule_work(&lcu->suc_data.worker);
++ if (!schedule_work(&lcu->suc_data.worker))
++ dasd_put_device(device);
+ };
+diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
+index b46ace3d4bf0..dd0c133aa312 100644
+--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
++++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
+@@ -568,7 +568,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
+ /*
+ * Command Lock contention
+ */
+- err = SCSI_DH_RETRY;
++ err = SCSI_DH_IMM_RETRY;
+ break;
+ default:
+ break;
+@@ -618,6 +618,8 @@ retry:
+ err = mode_select_handle_sense(sdev, h->sense);
+ if (err == SCSI_DH_RETRY && retry_cnt--)
+ goto retry;
++ if (err == SCSI_DH_IMM_RETRY)
++ goto retry;
+ }
+ if (err == SCSI_DH_OK) {
+ h->state = RDAC_STATE_ACTIVE;
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
+index e9ae6b924c70..8b011aef12bd 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.c
++++ b/drivers/scsi/qla2xxx/qla_dbg.c
+@@ -67,10 +67,10 @@
+ * | | | 0xd031-0xd0ff |
+ * | | | 0xd101-0xd1fe |
+ * | | | 0xd214-0xd2fe |
+- * | Target Mode | 0xe079 | |
+- * | Target Mode Management | 0xf080 | 0xf002 |
++ * | Target Mode | 0xe080 | |
++ * | Target Mode Management | 0xf096 | 0xf002 |
+ * | | | 0xf046-0xf049 |
+- * | Target Mode Task Management | 0x1000b | |
++ * | Target Mode Task Management | 0x1000d | |
+ * ----------------------------------------------------------------------
+ */
+
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index e86201d3b8c6..90d926ca1200 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -274,6 +274,7 @@
+ #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
+
+ struct req_que;
++struct qla_tgt_sess;
+
+ /*
+ * (sd.h is not exported, hence local inclusion)
+@@ -2026,6 +2027,7 @@ typedef struct fc_port {
+ uint16_t port_id;
+
+ unsigned long retry_delay_timestamp;
++ struct qla_tgt_sess *tgt_session;
+ } fc_port_t;
+
+ #include "qla_mr.h"
+@@ -3579,6 +3581,16 @@ typedef struct scsi_qla_host {
+ uint16_t fcoe_fcf_idx;
+ uint8_t fcoe_vn_port_mac[6];
+
++ /* list of commands waiting on workqueue */
++ struct list_head qla_cmd_list;
++ struct list_head qla_sess_op_cmd_list;
++ spinlock_t cmd_list_lock;
++
++ /* Counter to detect races between ELS and RSCN events */
++ atomic_t generation_tick;
++ /* Time when global fcport update has been scheduled */
++ int total_fcport_update_gen;
++
+ uint32_t vp_abort_cnt;
+
+ struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 998498e2341b..60f9651f2643 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data)
+ QLA_LOGIO_LOGIN_RETRIED : 0;
+ qla2x00_post_async_login_done_work(fcport->vha, fcport,
+ lio->u.logio.data);
++ } else if (sp->type == SRB_LOGOUT_CMD) {
++ qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
+ }
+ }
+
+@@ -497,7 +499,10 @@ void
+ qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+ uint16_t *data)
+ {
+- qla2x00_mark_device_lost(vha, fcport, 1, 0);
++ /* Don't re-login in target mode */
++ if (!fcport->tgt_session)
++ qla2x00_mark_device_lost(vha, fcport, 1, 0);
++ qlt_logo_completion_handler(fcport, data[0]);
+ return;
+ }
+
+@@ -2189,7 +2194,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
+ /* Clear outstanding commands array. */
+ for (que = 0; que < ha->max_req_queues; que++) {
+ req = ha->req_q_map[que];
+- if (!req)
++ if (!req || !test_bit(que, ha->req_qid_map))
+ continue;
+ req->out_ptr = (void *)(req->ring + req->length);
+ *req->out_ptr = 0;
+@@ -2206,7 +2211,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
+
+ for (que = 0; que < ha->max_rsp_queues; que++) {
+ rsp = ha->rsp_q_map[que];
+- if (!rsp)
++ if (!rsp || !test_bit(que, ha->rsp_qid_map))
+ continue;
+ rsp->in_ptr = (void *)(rsp->ring + rsp->length);
+ *rsp->in_ptr = 0;
+@@ -2922,24 +2927,14 @@ qla2x00_rport_del(void *data)
+ {
+ fc_port_t *fcport = data;
+ struct fc_rport *rport;
+- scsi_qla_host_t *vha = fcport->vha;
+ unsigned long flags;
+- unsigned long vha_flags;
+
+ spin_lock_irqsave(fcport->vha->host->host_lock, flags);
+ rport = fcport->drport ? fcport->drport: fcport->rport;
+ fcport->drport = NULL;
+ spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
+- if (rport) {
++ if (rport)
+ fc_remote_port_delete(rport);
+- /*
+- * Release the target mode FC NEXUS in qla_target.c code
+- * if target mod is enabled.
+- */
+- spin_lock_irqsave(&vha->hw->hardware_lock, vha_flags);
+- qlt_fc_port_deleted(vha, fcport);
+- spin_unlock_irqrestore(&vha->hw->hardware_lock, vha_flags);
+- }
+ }
+
+ /**
+@@ -3379,6 +3374,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
+ LIST_HEAD(new_fcports);
+ struct qla_hw_data *ha = vha->hw;
+ struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
++ int discovery_gen;
+
+ /* If FL port exists, then SNS is present */
+ if (IS_FWI2_CAPABLE(ha))
+@@ -3449,6 +3445,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
+ fcport->scan_state = QLA_FCPORT_SCAN;
+ }
+
++ /* Mark the time right before querying FW for connected ports.
++ * This process is long, asynchronous and by the time it's done,
++ * collected information might not be accurate anymore. E.g.
++ * disconnected port might have re-connected and a brand new
++ * session has been created. In this case session's generation
++ * will be newer than discovery_gen. */
++ qlt_do_generation_tick(vha, &discovery_gen);
++
+ rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
+ if (rval != QLA_SUCCESS)
+ break;
+@@ -3500,7 +3504,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+- qlt_fc_port_deleted(vha, fcport);
++ qlt_fc_port_deleted(vha, fcport,
++ discovery_gen);
+ }
+ }
+ }
+@@ -4277,6 +4282,14 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
+ atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+ qla2x00_rport_del(fcport);
++
++ /*
++ * Release the target mode FC NEXUS in
++ * qla_target.c, if target mod is enabled.
++ */
++ qlt_fc_port_deleted(vha, fcport,
++ base_vha->total_fcport_update_gen);
++
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ }
+ }
+@@ -4944,7 +4957,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
+
+ for (i = 1; i < ha->max_rsp_queues; i++) {
+ rsp = ha->rsp_q_map[i];
+- if (rsp) {
++ if (rsp && test_bit(i, ha->rsp_qid_map)) {
+ rsp->options &= ~BIT_0;
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
+ if (ret != QLA_SUCCESS)
+@@ -4959,8 +4972,8 @@ qla25xx_init_queues(struct qla_hw_data *ha)
+ }
+ for (i = 1; i < ha->max_req_queues; i++) {
+ req = ha->req_q_map[i];
+- if (req) {
+- /* Clear outstanding commands array. */
++ if (req && test_bit(i, ha->req_qid_map)) {
++ /* Clear outstanding commands array. */
+ req->options &= ~BIT_0;
+ ret = qla25xx_init_req_que(base_vha, req);
+ if (ret != QLA_SUCCESS)
+diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
+index a1ab25fca874..dc96f31a8831 100644
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
+ logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+ logio->control_flags =
+ cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
++ if (!sp->fcport->tgt_session ||
++ !sp->fcport->tgt_session->keep_nport_handle)
++ logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
+ logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ logio->port_id[0] = sp->fcport->d_id.b.al_pa;
+ logio->port_id[1] = sp->fcport->d_id.b.area;
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index 6dc14cd782b2..1f3991ba7580 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -2992,9 +2992,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
+ "MSI-X: Failed to enable support "
+ "-- %d/%d\n Retry with %d vectors.\n",
+ ha->msix_count, ret, ret);
++ ha->msix_count = ret;
++ ha->max_rsp_queues = ha->msix_count - 1;
+ }
+- ha->msix_count = ret;
+- ha->max_rsp_queues = ha->msix_count - 1;
+ ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
+ ha->msix_count, GFP_KERNEL);
+ if (!ha->msix_entries) {
+diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
+index cc94192511cf..63abed122adf 100644
+--- a/drivers/scsi/qla2xxx/qla_mid.c
++++ b/drivers/scsi/qla2xxx/qla_mid.c
+@@ -601,7 +601,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
+ /* Delete request queues */
+ for (cnt = 1; cnt < ha->max_req_queues; cnt++) {
+ req = ha->req_q_map[cnt];
+- if (req) {
++ if (req && test_bit(cnt, ha->req_qid_map)) {
+ ret = qla25xx_delete_req_que(vha, req);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x00ea,
+@@ -615,7 +615,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
+ /* Delete response queues */
+ for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) {
+ rsp = ha->rsp_q_map[cnt];
+- if (rsp) {
++ if (rsp && test_bit(cnt, ha->rsp_qid_map)) {
+ ret = qla25xx_delete_rsp_que(vha, rsp);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x00eb,
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 7462dd70b150..d00725574577 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -398,6 +398,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
+ int cnt;
+
+ for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
++ if (!test_bit(cnt, ha->req_qid_map))
++ continue;
++
+ req = ha->req_q_map[cnt];
+ qla2x00_free_req_que(ha, req);
+ }
+@@ -405,6 +408,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
+ ha->req_q_map = NULL;
+
+ for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
++ if (!test_bit(cnt, ha->rsp_qid_map))
++ continue;
++
+ rsp = ha->rsp_q_map[cnt];
+ qla2x00_free_rsp_que(ha, rsp);
+ }
+@@ -3229,11 +3235,14 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
+ spin_lock_irqsave(vha->host->host_lock, flags);
+ fcport->drport = rport;
+ spin_unlock_irqrestore(vha->host->host_lock, flags);
++ qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen);
+ set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
+ qla2xxx_wake_dpc(base_vha);
+ } else {
++ int now;
+ fc_remote_port_delete(rport);
+- qlt_fc_port_deleted(vha, fcport);
++ qlt_do_generation_tick(vha, &now);
++ qlt_fc_port_deleted(vha, fcport, now);
+ }
+ }
+
+@@ -3763,8 +3772,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
+ INIT_LIST_HEAD(&vha->vp_fcports);
+ INIT_LIST_HEAD(&vha->work_list);
+ INIT_LIST_HEAD(&vha->list);
++ INIT_LIST_HEAD(&vha->qla_cmd_list);
++ INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
+
+ spin_lock_init(&vha->work_lock);
++ spin_lock_init(&vha->cmd_list_lock);
+
+ sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
+ ql_dbg(ql_dbg_init, vha, 0x0041,
+diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
+index 496a733d0ca3..df6193b48177 100644
+--- a/drivers/scsi/qla2xxx/qla_target.c
++++ b/drivers/scsi/qla2xxx/qla_target.c
+@@ -114,6 +114,10 @@ static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
+ struct atio_from_isp *atio, uint16_t status, int qfull);
+ static void qlt_disable_vha(struct scsi_qla_host *vha);
+ static void qlt_clear_tgt_db(struct qla_tgt *tgt);
++static void qlt_send_notify_ack(struct scsi_qla_host *vha,
++ struct imm_ntfy_from_isp *ntfy,
++ uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
++ uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan);
+ /*
+ * Global Variables
+ */
+@@ -123,6 +127,16 @@ static struct workqueue_struct *qla_tgt_wq;
+ static DEFINE_MUTEX(qla_tgt_mutex);
+ static LIST_HEAD(qla_tgt_glist);
+
++/* This API intentionally takes dest as a parameter, rather than returning
++ * int value to avoid caller forgetting to issue wmb() after the store */
++void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
++{
++ scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);
++ *dest = atomic_inc_return(&base_vha->generation_tick);
++ /* memory barrier */
++ wmb();
++}
++
+ /* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
+ static struct qla_tgt_sess *qlt_find_sess_by_port_name(
+ struct qla_tgt *tgt,
+@@ -382,14 +396,73 @@ static void qlt_free_session_done(struct work_struct *work)
+ struct qla_tgt *tgt = sess->tgt;
+ struct scsi_qla_host *vha = sess->vha;
+ struct qla_hw_data *ha = vha->hw;
++ unsigned long flags;
++ bool logout_started = false;
++ fc_port_t fcport;
++
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
++ "%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
++ " s_id %02x:%02x:%02x logout %d keep %d plogi %d\n",
++ __func__, sess->se_sess, sess, sess->port_name, sess->loop_id,
++ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
++ sess->logout_on_delete, sess->keep_nport_handle,
++ sess->plogi_ack_needed);
+
+ BUG_ON(!tgt);
++
++ if (sess->logout_on_delete) {
++ int rc;
++
++ memset(&fcport, 0, sizeof(fcport));
++ fcport.loop_id = sess->loop_id;
++ fcport.d_id = sess->s_id;
++ memcpy(fcport.port_name, sess->port_name, WWN_SIZE);
++ fcport.vha = vha;
++ fcport.tgt_session = sess;
++
++ rc = qla2x00_post_async_logout_work(vha, &fcport, NULL);
++ if (rc != QLA_SUCCESS)
++ ql_log(ql_log_warn, vha, 0xf085,
++ "Schedule logo failed sess %p rc %d\n",
++ sess, rc);
++ else
++ logout_started = true;
++ }
++
+ /*
+ * Release the target session for FC Nexus from fabric module code.
+ */
+ if (sess->se_sess != NULL)
+ ha->tgt.tgt_ops->free_session(sess);
+
++ if (logout_started) {
++ bool traced = false;
++
++ while (!ACCESS_ONCE(sess->logout_completed)) {
++ if (!traced) {
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086,
++ "%s: waiting for sess %p logout\n",
++ __func__, sess);
++ traced = true;
++ }
++ msleep(100);
++ }
++
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087,
++ "%s: sess %p logout completed\n",
++ __func__, sess);
++ }
++
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++
++ if (sess->plogi_ack_needed)
++ qlt_send_notify_ack(vha, &sess->tm_iocb,
++ 0, 0, 0, 0, 0, 0);
++
++ list_del(&sess->sess_list_entry);
++
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
+ "Unregistration of sess %p finished\n", sess);
+
+@@ -410,9 +483,9 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess)
+
+ vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
+
+- list_del(&sess->sess_list_entry);
+- if (sess->deleted)
+- list_del(&sess->del_list_entry);
++ if (!list_empty(&sess->del_list_entry))
++ list_del_init(&sess->del_list_entry);
++ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+
+ INIT_WORK(&sess->free_work, qlt_free_session_done);
+ schedule_work(&sess->free_work);
+@@ -490,27 +563,38 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
+ struct qla_tgt *tgt = sess->tgt;
+ uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5;
+
+- if (sess->deleted)
+- return;
++ if (sess->deleted) {
++ /* Upgrade to unconditional deletion in case it was temporary */
++ if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING)
++ list_del(&sess->del_list_entry);
++ else
++ return;
++ }
+
+ ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
+ "Scheduling sess %p for deletion\n", sess);
+- list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
+- sess->deleted = 1;
+
+- if (immediate)
++ if (immediate) {
+ dev_loss_tmo = 0;
++ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
++ list_add(&sess->del_list_entry, &tgt->del_sess_list);
++ } else {
++ sess->deleted = QLA_SESS_DELETION_PENDING;
++ list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
++ }
+
+ sess->expires = jiffies + dev_loss_tmo * HZ;
+
+ ql_dbg(ql_dbg_tgt, sess->vha, 0xe048,
+- "qla_target(%d): session for port %8phC (loop ID %d) scheduled for "
+- "deletion in %u secs (expires: %lu) immed: %d\n",
+- sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo,
+- sess->expires, immediate);
++ "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)"
++ " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n",
++ sess->vha->vp_idx, sess->port_name, sess->loop_id,
++ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
++ dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete,
++ sess->generation);
+
+ if (immediate)
+- schedule_delayed_work(&tgt->sess_del_work, 0);
++ mod_delayed_work(system_wq, &tgt->sess_del_work, 0);
+ else
+ schedule_delayed_work(&tgt->sess_del_work,
+ sess->expires - jiffies);
+@@ -579,9 +663,9 @@ out_free_id_list:
+ /* ha->hardware_lock supposed to be held on entry */
+ static void qlt_undelete_sess(struct qla_tgt_sess *sess)
+ {
+- BUG_ON(!sess->deleted);
++ BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
+
+- list_del(&sess->del_list_entry);
++ list_del_init(&sess->del_list_entry);
+ sess->deleted = 0;
+ }
+
+@@ -600,7 +684,9 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
+ del_list_entry);
+ elapsed = jiffies;
+ if (time_after_eq(elapsed, sess->expires)) {
+- qlt_undelete_sess(sess);
++ /* No turning back */
++ list_del_init(&sess->del_list_entry);
++ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
+ "Timeout: sess %p about to be deleted\n",
+@@ -644,6 +730,13 @@ static struct qla_tgt_sess *qlt_create_sess(
+ fcport->d_id.b.al_pa, fcport->d_id.b.area,
+ fcport->loop_id);
+
++ /* Cannot undelete at this point */
++ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ spin_unlock_irqrestore(&ha->hardware_lock,
++ flags);
++ return NULL;
++ }
++
+ if (sess->deleted)
+ qlt_undelete_sess(sess);
+
+@@ -653,6 +746,9 @@ static struct qla_tgt_sess *qlt_create_sess(
+
+ if (sess->local && !local)
+ sess->local = 0;
++
++ qlt_do_generation_tick(vha, &sess->generation);
++
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ return sess;
+@@ -674,6 +770,14 @@ static struct qla_tgt_sess *qlt_create_sess(
+ sess->s_id = fcport->d_id;
+ sess->loop_id = fcport->loop_id;
+ sess->local = local;
++ INIT_LIST_HEAD(&sess->del_list_entry);
++
++ /* Under normal circumstances we want to logout from firmware when
++ * session eventually ends and release corresponding nport handle.
++ * In the exception cases (e.g. when new PLOGI is waiting) corresponding
++ * code will adjust these flags as necessary. */
++ sess->logout_on_delete = 1;
++ sess->keep_nport_handle = 0;
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
+ "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n",
+@@ -706,6 +810,7 @@ static struct qla_tgt_sess *qlt_create_sess(
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list);
+ vha->vha_tgt.qla_tgt->sess_count++;
++ qlt_do_generation_tick(vha, &sess->generation);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
+@@ -719,7 +824,7 @@ static struct qla_tgt_sess *qlt_create_sess(
+ }
+
+ /*
+- * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port()
++ * Called from qla2x00_reg_remote_port()
+ */
+ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+@@ -751,6 +856,10 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
+ mutex_unlock(&vha->vha_tgt.tgt_mutex);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
++ } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ /* Point of no return */
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ return;
+ } else {
+ kref_get(&sess->se_sess->sess_kref);
+
+@@ -781,7 +890,12 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ }
+
+-void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
++/*
++ * max_gen - specifies maximum session generation
++ * at which this deletion requestion is still valid
++ */
++void
++qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
+ {
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_tgt_sess *sess;
+@@ -800,6 +914,15 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
+ return;
+ }
+
++ if (max_gen - sess->generation < 0) {
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
++ "Ignoring stale deletion request for se_sess %p / sess %p"
++ " for port %8phC, req_gen %d, sess_gen %d\n",
++ sess->se_sess, sess, sess->port_name, max_gen,
++ sess->generation);
++ return;
++ }
++
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess);
+
+ sess->local = 1;
+@@ -1170,6 +1293,70 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
+ FCP_TMF_CMPL, true);
+ }
+
++static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
++{
++ struct qla_tgt_sess_op *op;
++ struct qla_tgt_cmd *cmd;
++
++ spin_lock(&vha->cmd_list_lock);
++
++ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
++ if (tag == op->atio.u.isp24.exchange_addr) {
++ op->aborted = true;
++ spin_unlock(&vha->cmd_list_lock);
++ return 1;
++ }
++ }
++
++ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
++ if (tag == cmd->atio.u.isp24.exchange_addr) {
++ cmd->state = QLA_TGT_STATE_ABORTED;
++ spin_unlock(&vha->cmd_list_lock);
++ return 1;
++ }
++ }
++
++ spin_unlock(&vha->cmd_list_lock);
++ return 0;
++}
++
++/* drop cmds for the given lun
++ * XXX only looks for cmds on the port through which lun reset was recieved
++ * XXX does not go through the list of other port (which may have cmds
++ * for the same lun)
++ */
++static void abort_cmds_for_lun(struct scsi_qla_host *vha,
++ uint32_t lun, uint8_t *s_id)
++{
++ struct qla_tgt_sess_op *op;
++ struct qla_tgt_cmd *cmd;
++ uint32_t key;
++
++ key = sid_to_key(s_id);
++ spin_lock(&vha->cmd_list_lock);
++ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
++ uint32_t op_key;
++ uint32_t op_lun;
++
++ op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
++ op_lun = scsilun_to_int(
++ (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun);
++ if (op_key == key && op_lun == lun)
++ op->aborted = true;
++ }
++ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
++ uint32_t cmd_key;
++ uint32_t cmd_lun;
++
++ cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
++ cmd_lun = scsilun_to_int(
++ (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun);
++ if (cmd_key == key && cmd_lun == lun)
++ cmd->state = QLA_TGT_STATE_ABORTED;
++ }
++ spin_unlock(&vha->cmd_list_lock);
++}
++
+ /* ha->hardware_lock supposed to be held on entry */
+ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
+ struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess)
+@@ -1194,8 +1381,19 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
+ }
+ spin_unlock(&se_sess->sess_cmd_lock);
+
+- if (!found_lun)
+- return -ENOENT;
++ /* cmd not in LIO lists, look in qla list */
++ if (!found_lun) {
++ if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) {
++ /* send TASK_ABORT response immediately */
++ qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false);
++ return 0;
++ } else {
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
++ "unable to find cmd in driver or LIO for tag 0x%x\n",
++ abts->exchange_addr_to_abort);
++ return -ENOENT;
++ }
++ }
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f,
+ "qla_target(%d): task abort (tag=%d)\n",
+@@ -1279,6 +1477,11 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
+ return;
+ }
+
++ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
++ return;
++ }
++
+ rc = __qlt_24xx_handle_abts(vha, abts, sess);
+ if (rc != 0) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054,
+@@ -1721,21 +1924,6 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
+ struct qla_hw_data *ha = vha->hw;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+- if (unlikely(cmd->aborted)) {
+- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
+- "qla_target(%d): terminating exchange "
+- "for aborted cmd=%p (se_cmd=%p, tag=%d)", vha->vp_idx, cmd,
+- se_cmd, cmd->tag);
+-
+- cmd->state = QLA_TGT_STATE_ABORTED;
+- cmd->cmd_flags |= BIT_6;
+-
+- qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
+-
+- /* !! At this point cmd could be already freed !! */
+- return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED;
+- }
+-
+ prm->cmd = cmd;
+ prm->tgt = tgt;
+ prm->rq_result = scsi_status;
+@@ -2298,6 +2486,19 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
+ unsigned long flags = 0;
+ int res;
+
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ cmd->state = QLA_TGT_STATE_PROCESSED;
++ if (cmd->sess->logout_completed)
++ /* no need to terminate. FW already freed exchange. */
++ qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
++ else
++ qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ return 0;
++ }
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
+ memset(&prm, 0, sizeof(prm));
+ qlt_check_srr_debug(cmd, &xmit_type);
+
+@@ -2310,9 +2511,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
+ res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
+ &full_req_cnt);
+ if (unlikely(res != 0)) {
+- if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED)
+- return 0;
+-
+ return res;
+ }
+
+@@ -2459,7 +2657,8 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+- if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) {
++ if (qla2x00_reset_active(vha) || (cmd->reset_count != ha->chip_reset) ||
++ (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) {
+ /*
+ * Either a chip reset is active or this request was from
+ * previous life, just abort the processing.
+@@ -2652,6 +2851,89 @@ out:
+
+ /* If hardware_lock held on entry, might drop it, then reaquire */
+ /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
++static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
++ struct imm_ntfy_from_isp *ntfy)
++{
++ struct nack_to_isp *nack;
++ struct qla_hw_data *ha = vha->hw;
++ request_t *pkt;
++ int ret = 0;
++
++ ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c,
++ "Sending TERM ELS CTIO (ha=%p)\n", ha);
++
++ pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
++ if (pkt == NULL) {
++ ql_dbg(ql_dbg_tgt, vha, 0xe080,
++ "qla_target(%d): %s failed: unable to allocate "
++ "request packet\n", vha->vp_idx, __func__);
++ return -ENOMEM;
++ }
++
++ pkt->entry_type = NOTIFY_ACK_TYPE;
++ pkt->entry_count = 1;
++ pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++
++ nack = (struct nack_to_isp *)pkt;
++ nack->ox_id = ntfy->ox_id;
++
++ nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
++ if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
++ nack->u.isp24.flags = ntfy->u.isp24.flags &
++ __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
++ }
++
++ /* terminate */
++ nack->u.isp24.flags |=
++ __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE);
++
++ nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
++ nack->u.isp24.status = ntfy->u.isp24.status;
++ nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
++ nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
++ nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
++ nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
++ nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
++ nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
++
++ qla2x00_start_iocbs(vha, vha->req);
++ return ret;
++}
++
++static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
++ struct imm_ntfy_from_isp *imm, int ha_locked)
++{
++ unsigned long flags = 0;
++ int rc;
++
++ if (qlt_issue_marker(vha, ha_locked) < 0)
++ return;
++
++ if (ha_locked) {
++ rc = __qlt_send_term_imm_notif(vha, imm);
++
++#if 0 /* Todo */
++ if (rc == -ENOMEM)
++ qlt_alloc_qfull_cmd(vha, imm, 0, 0);
++#endif
++ goto done;
++ }
++
++ spin_lock_irqsave(&vha->hw->hardware_lock, flags);
++ rc = __qlt_send_term_imm_notif(vha, imm);
++
++#if 0 /* Todo */
++ if (rc == -ENOMEM)
++ qlt_alloc_qfull_cmd(vha, imm, 0, 0);
++#endif
++
++done:
++ if (!ha_locked)
++ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
++}
++
++/* If hardware_lock held on entry, might drop it, then reaquire */
++/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
+ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
+ struct qla_tgt_cmd *cmd,
+ struct atio_from_isp *atio)
+@@ -2794,6 +3076,24 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha)
+
+ }
+
++void qlt_abort_cmd(struct qla_tgt_cmd *cmd)
++{
++ struct qla_tgt *tgt = cmd->tgt;
++ struct scsi_qla_host *vha = tgt->vha;
++ struct se_cmd *se_cmd = &cmd->se_cmd;
++
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
++ "qla_target(%d): terminating exchange for aborted cmd=%p "
++ "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
++ cmd->tag);
++
++ cmd->state = QLA_TGT_STATE_ABORTED;
++ cmd->cmd_flags |= BIT_6;
++
++ qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
++}
++EXPORT_SYMBOL(qlt_abort_cmd);
++
+ void qlt_free_cmd(struct qla_tgt_cmd *cmd)
+ {
+ struct qla_tgt_sess *sess = cmd->sess;
+@@ -3265,6 +3565,13 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
+ if (tgt->tgt_stop)
+ goto out_term;
+
++ if (cmd->state == QLA_TGT_STATE_ABORTED) {
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082,
++ "cmd with tag %u is aborted\n",
++ cmd->atio.u.isp24.exchange_addr);
++ goto out_term;
++ }
++
+ cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
+ cmd->tag = atio->u.isp24.exchange_addr;
+ cmd->unpacked_lun = scsilun_to_int(
+@@ -3318,6 +3625,12 @@ out_term:
+ static void qlt_do_work(struct work_struct *work)
+ {
+ struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
++ scsi_qla_host_t *vha = cmd->vha;
++ unsigned long flags;
++
++ spin_lock_irqsave(&vha->cmd_list_lock, flags);
++ list_del(&cmd->cmd_list);
++ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
+
+ __qlt_do_work(cmd);
+ }
+@@ -3369,14 +3682,25 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
+ unsigned long flags;
+ uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
+
++ spin_lock_irqsave(&vha->cmd_list_lock, flags);
++ list_del(&op->cmd_list);
++ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
++
++ if (op->aborted) {
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
++ "sess_op with tag %u is aborted\n",
++ op->atio.u.isp24.exchange_addr);
++ goto out_term;
++ }
++
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
+- "qla_target(%d): Unable to find wwn login"
+- " (s_id %x:%x:%x), trying to create it manually\n",
+- vha->vp_idx, s_id[0], s_id[1], s_id[2]);
++ "qla_target(%d): Unable to find wwn login"
++ " (s_id %x:%x:%x), trying to create it manually\n",
++ vha->vp_idx, s_id[0], s_id[1], s_id[2]);
+
+ if (op->atio.u.raw.entry_count > 1) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
+- "Dropping multy entry atio %p\n", &op->atio);
++ "Dropping multy entry atio %p\n", &op->atio);
+ goto out_term;
+ }
+
+@@ -3441,10 +3765,25 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
+
+ memcpy(&op->atio, atio, sizeof(*atio));
+ op->vha = vha;
++
++ spin_lock(&vha->cmd_list_lock);
++ list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list);
++ spin_unlock(&vha->cmd_list_lock);
++
+ INIT_WORK(&op->work, qlt_create_sess_from_atio);
+ queue_work(qla_tgt_wq, &op->work);
+ return 0;
+ }
++
++ /* Another WWN used to have our s_id. Our PLOGI scheduled its
++ * session deletion, but it's still in sess_del_work wq */
++ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ ql_dbg(ql_dbg_io, vha, 0x3061,
++ "New command while old session %p is being deleted\n",
++ sess);
++ return -EFAULT;
++ }
++
+ /*
+ * Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
+ */
+@@ -3460,6 +3799,11 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
+
+ cmd->cmd_in_wq = 1;
+ cmd->cmd_flags |= BIT_0;
++
++ spin_lock(&vha->cmd_list_lock);
++ list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
++ spin_unlock(&vha->cmd_list_lock);
++
+ INIT_WORK(&cmd->work, qlt_do_work);
+ queue_work(qla_tgt_wq, &cmd->work);
+ return 0;
+@@ -3473,6 +3817,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
+ struct scsi_qla_host *vha = sess->vha;
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_tgt_mgmt_cmd *mcmd;
++ struct atio_from_isp *a = (struct atio_from_isp *)iocb;
+ int res;
+ uint8_t tmr_func;
+
+@@ -3513,6 +3858,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002,
+ "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx);
+ tmr_func = TMR_LUN_RESET;
++ abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
+ break;
+
+ case QLA_TGT_CLEAR_TS:
+@@ -3601,6 +3947,9 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
+ sizeof(struct atio_from_isp));
+ }
+
++ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)
++ return -EFAULT;
++
+ return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
+ }
+
+@@ -3666,22 +4015,280 @@ static int qlt_abort_task(struct scsi_qla_host *vha,
+ return __qlt_abort_task(vha, iocb, sess);
+ }
+
++void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
++{
++ if (fcport->tgt_session) {
++ if (rc != MBS_COMMAND_COMPLETE) {
++ ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093,
++ "%s: se_sess %p / sess %p from"
++ " port %8phC loop_id %#04x s_id %02x:%02x:%02x"
++ " LOGO failed: %#x\n",
++ __func__,
++ fcport->tgt_session->se_sess,
++ fcport->tgt_session,
++ fcport->port_name, fcport->loop_id,
++ fcport->d_id.b.domain, fcport->d_id.b.area,
++ fcport->d_id.b.al_pa, rc);
++ }
++
++ fcport->tgt_session->logout_completed = 1;
++ }
++}
++
++static void qlt_swap_imm_ntfy_iocb(struct imm_ntfy_from_isp *a,
++ struct imm_ntfy_from_isp *b)
++{
++ struct imm_ntfy_from_isp tmp;
++ memcpy(&tmp, a, sizeof(struct imm_ntfy_from_isp));
++ memcpy(a, b, sizeof(struct imm_ntfy_from_isp));
++ memcpy(b, &tmp, sizeof(struct imm_ntfy_from_isp));
++}
++
++/*
++* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list)
++*
++* Schedules sessions with matching port_id/loop_id but different wwn for
++* deletion. Returns existing session with matching wwn if present.
++* Null otherwise.
++*/
++static struct qla_tgt_sess *
++qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn,
++ port_id_t port_id, uint16_t loop_id)
++{
++ struct qla_tgt_sess *sess = NULL, *other_sess;
++ uint64_t other_wwn;
++
++ list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) {
++
++ other_wwn = wwn_to_u64(other_sess->port_name);
++
++ if (wwn == other_wwn) {
++ WARN_ON(sess);
++ sess = other_sess;
++ continue;
++ }
++
++ /* find other sess with nport_id collision */
++ if (port_id.b24 == other_sess->s_id.b24) {
++ if (loop_id != other_sess->loop_id) {
++ ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c,
++ "Invalidating sess %p loop_id %d wwn %llx.\n",
++ other_sess, other_sess->loop_id, other_wwn);
++
++ /*
++ * logout_on_delete is set by default, but another
++ * session that has the same s_id/loop_id combo
++ * might have cleared it when requested this session
++ * deletion, so don't touch it
++ */
++ qlt_schedule_sess_for_deletion(other_sess, true);
++ } else {
++ /*
++ * Another wwn used to have our s_id/loop_id
++ * combo - kill the session, but don't log out
++ */
++ sess->logout_on_delete = 0;
++ qlt_schedule_sess_for_deletion(other_sess,
++ true);
++ }
++ continue;
++ }
++
++ /* find other sess with nport handle collision */
++ if (loop_id == other_sess->loop_id) {
++ ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d,
++ "Invalidating sess %p loop_id %d wwn %llx.\n",
++ other_sess, other_sess->loop_id, other_wwn);
++
++ /* Same loop_id but different s_id
++ * Ok to kill and logout */
++ qlt_schedule_sess_for_deletion(other_sess, true);
++ }
++ }
++
++ return sess;
++}
++
++/* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */
++static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
++{
++ struct qla_tgt_sess_op *op;
++ struct qla_tgt_cmd *cmd;
++ uint32_t key;
++ int count = 0;
++
++ key = (((u32)s_id->b.domain << 16) |
++ ((u32)s_id->b.area << 8) |
++ ((u32)s_id->b.al_pa));
++
++ spin_lock(&vha->cmd_list_lock);
++ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
++ uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
++ if (op_key == key) {
++ op->aborted = true;
++ count++;
++ }
++ }
++ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
++ uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
++ if (cmd_key == key) {
++ cmd->state = QLA_TGT_STATE_ABORTED;
++ count++;
++ }
++ }
++ spin_unlock(&vha->cmd_list_lock);
++
++ return count;
++}
++
+ /*
+ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
+ */
+ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *iocb)
+ {
++ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
++ struct qla_hw_data *ha = vha->hw;
++ struct qla_tgt_sess *sess = NULL;
++ uint64_t wwn;
++ port_id_t port_id;
++ uint16_t loop_id;
++ uint16_t wd3_lo;
+ int res = 0;
+
++ wwn = wwn_to_u64(iocb->u.isp24.port_name);
++
++ port_id.b.domain = iocb->u.isp24.port_id[2];
++ port_id.b.area = iocb->u.isp24.port_id[1];
++ port_id.b.al_pa = iocb->u.isp24.port_id[0];
++ port_id.b.rsvd_1 = 0;
++
++ loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
++
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026,
+ "qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n",
+ vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode);
+
++ /* res = 1 means ack at the end of thread
++ * res = 0 means ack async/later.
++ */
+ switch (iocb->u.isp24.status_subcode) {
+ case ELS_PLOGI:
+- case ELS_FLOGI:
++
++ /* Mark all stale commands in qla_tgt_wq for deletion */
++ abort_cmds_for_s_id(vha, &port_id);
++
++ if (wwn)
++ sess = qlt_find_sess_invalidate_other(tgt, wwn,
++ port_id, loop_id);
++
++ if (!sess || IS_SW_RESV_ADDR(sess->s_id)) {
++ res = 1;
++ break;
++ }
++
++ if (sess->plogi_ack_needed) {
++ /*
++ * Initiator sent another PLOGI before last PLOGI could
++ * finish. Swap plogi iocbs and terminate old one
++ * without acking, new one will get acked when session
++ * deletion completes.
++ */
++ ql_log(ql_log_warn, sess->vha, 0xf094,
++ "sess %p received double plogi.\n", sess);
++
++ qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb);
++
++ qlt_send_term_imm_notif(vha, iocb, 1);
++
++ res = 0;
++ break;
++ }
++
++ res = 0;
++
++ /*
++ * Save immediate Notif IOCB for Ack when sess is done
++ * and being deleted.
++ */
++ memcpy(&sess->tm_iocb, iocb, sizeof(sess->tm_iocb));
++ sess->plogi_ack_needed = 1;
++
++ /*
++ * Under normal circumstances we want to release nport handle
++ * during LOGO process to avoid nport handle leaks inside FW.
++ * The exception is when LOGO is done while another PLOGI with
++ * the same nport handle is waiting as might be the case here.
++ * Note: there is always a possibily of a race where session
++ * deletion has already started for other reasons (e.g. ACL
++ * removal) and now PLOGI arrives:
++ * 1. if PLOGI arrived in FW after nport handle has been freed,
++ * FW must have assigned this PLOGI a new/same handle and we
++ * can proceed ACK'ing it as usual when session deletion
++ * completes.
++ * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
++ * bit reached it, the handle has now been released. We'll
++ * get an error when we ACK this PLOGI. Nothing will be sent
++ * back to initiator. Initiator should eventually retry
++ * PLOGI and situation will correct itself.
++ */
++ sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
++ (sess->s_id.b24 == port_id.b24));
++ qlt_schedule_sess_for_deletion(sess, true);
++ break;
++
+ case ELS_PRLI:
++ wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
++
++ if (wwn)
++ sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id,
++ loop_id);
++
++ if (sess != NULL) {
++ if (sess->deleted) {
++ /*
++ * Impatient initiator sent PRLI before last
++ * PLOGI could finish. Will force him to re-try,
++ * while last one finishes.
++ */
++ ql_log(ql_log_warn, sess->vha, 0xf095,
++ "sess %p PRLI received, before plogi ack.\n",
++ sess);
++ qlt_send_term_imm_notif(vha, iocb, 1);
++ res = 0;
++ break;
++ }
++
++ /*
++ * This shouldn't happen under normal circumstances,
++ * since we have deleted the old session during PLOGI
++ */
++ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096,
++ "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n",
++ sess->loop_id, sess, iocb->u.isp24.nport_handle);
++
++ sess->local = 0;
++ sess->loop_id = loop_id;
++ sess->s_id = port_id;
++
++ if (wd3_lo & BIT_7)
++ sess->conf_compl_supported = 1;
++
++ }
++ res = 1; /* send notify ack */
++
++ /* Make session global (not used in fabric mode) */
++ if (ha->current_topology != ISP_CFG_F) {
++ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
++ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
++ qla2xxx_wake_dpc(vha);
++ } else {
++ /* todo: else - create sess here. */
++ res = 1; /* send notify ack */
++ }
++
++ break;
++
+ case ELS_LOGO:
+ case ELS_PRLO:
+ res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
+@@ -3699,6 +4306,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
+ break;
+ }
+
++ case ELS_FLOGI: /* should never happen */
+ default:
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061,
+ "qla_target(%d): Unsupported ELS command %x "
+@@ -5016,6 +5624,11 @@ static void qlt_abort_work(struct qla_tgt *tgt,
+ if (!sess)
+ goto out_term;
+ } else {
++ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ sess = NULL;
++ goto out_term;
++ }
++
+ kref_get(&sess->se_sess->sess_kref);
+ }
+
+@@ -5070,6 +5683,11 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
+ if (!sess)
+ goto out_term;
+ } else {
++ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
++ sess = NULL;
++ goto out_term;
++ }
++
+ kref_get(&sess->se_sess->sess_kref);
+ }
+
+diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
+index 332086776dfe..d30c60a1d522 100644
+--- a/drivers/scsi/qla2xxx/qla_target.h
++++ b/drivers/scsi/qla2xxx/qla_target.h
+@@ -167,7 +167,24 @@ struct imm_ntfy_from_isp {
+ uint32_t srr_rel_offs;
+ uint16_t srr_ui;
+ uint16_t srr_ox_id;
+- uint8_t reserved_4[19];
++ union {
++ struct {
++ uint8_t node_name[8];
++ } plogi; /* PLOGI/ADISC/PDISC */
++ struct {
++ /* PRLI word 3 bit 0-15 */
++ uint16_t wd3_lo;
++ uint8_t resv0[6];
++ } prli;
++ struct {
++ uint8_t port_id[3];
++ uint8_t resv1;
++ uint16_t nport_handle;
++ uint16_t resv2;
++ } req_els;
++ } u;
++ uint8_t port_name[8];
++ uint8_t resv3[3];
+ uint8_t vp_index;
+ uint32_t reserved_5;
+ uint8_t port_id[3];
+@@ -234,6 +251,7 @@ struct nack_to_isp {
+ uint8_t reserved[2];
+ uint16_t ox_id;
+ } __packed;
++#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
+ #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
+ #define NOTIFY_ACK_SRR_FLAGS_REJECT 1
+
+@@ -790,13 +808,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
+ #define FC_TM_REJECT 4
+ #define FC_TM_FAILED 5
+
+-/*
+- * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was
+- * terminated, so no more actions is needed and success should be returned
+- * to target.
+- */
+-#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717
+-
+ #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
+ #define pci_dma_lo32(a) (a & 0xffffffff)
+ #define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
+@@ -874,6 +885,15 @@ struct qla_tgt_sess_op {
+ struct scsi_qla_host *vha;
+ struct atio_from_isp atio;
+ struct work_struct work;
++ struct list_head cmd_list;
++ bool aborted;
++};
++
++enum qla_sess_deletion {
++ QLA_SESS_DELETION_NONE = 0,
++ QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
++ * this one */
++ QLA_SESS_DELETION_IN_PROGRESS = 2,
+ };
+
+ /*
+@@ -884,8 +904,15 @@ struct qla_tgt_sess {
+ port_id_t s_id;
+
+ unsigned int conf_compl_supported:1;
+- unsigned int deleted:1;
++ unsigned int deleted:2;
+ unsigned int local:1;
++ unsigned int logout_on_delete:1;
++ unsigned int plogi_ack_needed:1;
++ unsigned int keep_nport_handle:1;
++
++ unsigned char logout_completed;
++
++ int generation;
+
+ struct se_session *se_sess;
+ struct scsi_qla_host *vha;
+@@ -897,6 +924,10 @@ struct qla_tgt_sess {
+
+ uint8_t port_name[WWN_SIZE];
+ struct work_struct free_work;
++
++ union {
++ struct imm_ntfy_from_isp tm_iocb;
++ };
+ };
+
+ struct qla_tgt_cmd {
+@@ -912,7 +943,6 @@ struct qla_tgt_cmd {
+ unsigned int conf_compl_supported:1;
+ unsigned int sg_mapped:1;
+ unsigned int free_sg:1;
+- unsigned int aborted:1; /* Needed in case of SRR */
+ unsigned int write_data_transferred:1;
+ unsigned int ctx_dsd_alloced:1;
+ unsigned int q_full:1;
+@@ -1027,6 +1057,10 @@ struct qla_tgt_srr_ctio {
+ struct qla_tgt_cmd *cmd;
+ };
+
++/* Check for Switch reserved address */
++#define IS_SW_RESV_ADDR(_s_id) \
++ ((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
++
+ #define QLA_TGT_XMIT_DATA 1
+ #define QLA_TGT_XMIT_STATUS 2
+ #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA)
+@@ -1044,7 +1078,7 @@ extern int qlt_lport_register(void *, u64, u64, u64,
+ extern void qlt_lport_deregister(struct scsi_qla_host *);
+ extern void qlt_unreg_sess(struct qla_tgt_sess *);
+ extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
+-extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *);
++extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
+ extern int __init qlt_init(void);
+ extern void qlt_exit(void);
+ extern void qlt_update_vp_map(struct scsi_qla_host *, int);
+@@ -1074,12 +1108,23 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
+ ha->host->active_mode |= MODE_INITIATOR;
+ }
+
++static inline uint32_t sid_to_key(const uint8_t *s_id)
++{
++ uint32_t key;
++
++ key = (((unsigned long)s_id[0] << 16) |
++ ((unsigned long)s_id[1] << 8) |
++ (unsigned long)s_id[2]);
++ return key;
++}
++
+ /*
+ * Exported symbols from qla_target.c LLD logic used by qla2xxx code..
+ */
+ extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
+ extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
+ extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
++extern void qlt_abort_cmd(struct qla_tgt_cmd *);
+ extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
+ extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
+ extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
+@@ -1110,5 +1155,7 @@ extern void qlt_stop_phase2(struct qla_tgt *);
+ extern irqreturn_t qla83xx_msix_atio_q(int, void *);
+ extern void qlt_83xx_iospace_config(struct qla_hw_data *);
+ extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
++extern void qlt_logo_completion_handler(fc_port_t *, int);
++extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
+
+ #endif /* __QLA_TARGET_H */
+diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
+index 962cb89fe0ae..af806fdb0dbc 100644
+--- a/drivers/scsi/qla2xxx/qla_tmpl.c
++++ b/drivers/scsi/qla2xxx/qla_tmpl.c
+@@ -395,6 +395,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
+ if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) {
+ for (i = 0; i < vha->hw->max_req_queues; i++) {
+ struct req_que *req = vha->hw->req_q_map[i];
++
++ if (!test_bit(i, vha->hw->req_qid_map))
++ continue;
++
+ if (req || !buf) {
+ length = req ?
+ req->length : REQUEST_ENTRY_CNT_24XX;
+@@ -408,6 +412,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
+ } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) {
+ for (i = 0; i < vha->hw->max_rsp_queues; i++) {
+ struct rsp_que *rsp = vha->hw->rsp_q_map[i];
++
++ if (!test_bit(i, vha->hw->rsp_qid_map))
++ continue;
++
+ if (rsp || !buf) {
+ length = rsp ?
+ rsp->length : RESPONSE_ENTRY_CNT_MQ;
+@@ -634,6 +642,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
+ if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) {
+ for (i = 0; i < vha->hw->max_req_queues; i++) {
+ struct req_que *req = vha->hw->req_q_map[i];
++
++ if (!test_bit(i, vha->hw->req_qid_map))
++ continue;
++
+ if (req || !buf) {
+ qla27xx_insert16(i, buf, len);
+ qla27xx_insert16(1, buf, len);
+@@ -645,6 +657,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
+ } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) {
+ for (i = 0; i < vha->hw->max_rsp_queues; i++) {
+ struct rsp_que *rsp = vha->hw->rsp_q_map[i];
++
++ if (!test_bit(i, vha->hw->rsp_qid_map))
++ continue;
++
+ if (rsp || !buf) {
+ qla27xx_insert16(i, buf, len);
+ qla27xx_insert16(1, buf, len);
+diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+index 5c9e680aa375..fdad875ca777 100644
+--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+@@ -429,7 +429,7 @@ static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd)
+ cmd->cmd_flags |= BIT_14;
+ }
+
+- return target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ return target_put_sess_cmd(se_cmd);
+ }
+
+ /* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying
+@@ -669,7 +669,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
+ cmd->cmd_flags |= BIT_4;
+ cmd->bufflen = se_cmd->data_length;
+ cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
+- cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
+
+ cmd->sg_cnt = se_cmd->t_data_nents;
+ cmd->sg = se_cmd->t_data_sg;
+@@ -699,7 +698,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
+ cmd->sg_cnt = 0;
+ cmd->offset = 0;
+ cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
+- cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
+ if (cmd->cmd_flags & BIT_5) {
+ pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
+ dump_stack();
+@@ -764,14 +762,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
+ {
+ struct qla_tgt_cmd *cmd = container_of(se_cmd,
+ struct qla_tgt_cmd, se_cmd);
+- struct scsi_qla_host *vha = cmd->vha;
+- struct qla_hw_data *ha = vha->hw;
+-
+- if (!cmd->sg_mapped)
+- return;
+-
+- pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
+- cmd->sg_mapped = 0;
++ qlt_abort_cmd(cmd);
+ }
+
+ static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
+@@ -1323,9 +1314,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
+ return NULL;
+ }
+
+- key = (((unsigned long)s_id[0] << 16) |
+- ((unsigned long)s_id[1] << 8) |
+- (unsigned long)s_id[2]);
++ key = sid_to_key(s_id);
+ pr_debug("find_sess_by_s_id: 0x%06x\n", key);
+
+ se_nacl = btree_lookup32(&lport->lport_fcport_map, key);
+@@ -1360,9 +1349,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
+ void *slot;
+ int rc;
+
+- key = (((unsigned long)s_id[0] << 16) |
+- ((unsigned long)s_id[1] << 8) |
+- (unsigned long)s_id[2]);
++ key = sid_to_key(s_id);
+ pr_debug("set_sess_by_s_id: %06x\n", key);
+
+ slot = btree_lookup32(&lport->lport_fcport_map, key);
+@@ -1718,6 +1705,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+ }
+
+ sess->conf_compl_supported = conf_compl_supported;
++
++ /* Reset logout parameters to default */
++ sess->logout_on_delete = 1;
++ sess->keep_nport_handle = 0;
+ }
+
+ /*
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index 64ed88a67e6e..ac418e73536d 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -205,6 +205,7 @@ static struct {
+ {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC},
+ {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+ {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
++ {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
+ {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+ {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
+index 330bbe831066..2e58279fab60 100644
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -712,7 +712,7 @@ static int iscsit_add_reject_from_cmd(
+ */
+ if (cmd->se_cmd.se_tfo != NULL) {
+ pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
+- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
++ target_put_sess_cmd(&cmd->se_cmd);
+ }
+ return -1;
+ }
+@@ -998,7 +998,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
+ conn->cid);
+
+- target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true);
++ target_get_sess_cmd(&cmd->se_cmd, true);
+
+ cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
+ scsilun_to_int(&hdr->lun));
+@@ -1064,7 +1064,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+ return -1;
+ else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
++ target_put_sess_cmd(&cmd->se_cmd);
+ return 0;
+ }
+ }
+@@ -1080,7 +1080,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ if (!cmd->sense_reason)
+ return 0;
+
+- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
++ target_put_sess_cmd(&cmd->se_cmd);
+ return 0;
+ }
+
+@@ -1111,7 +1111,6 @@ static int
+ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
+ bool dump_payload)
+ {
+- struct iscsi_conn *conn = cmd->conn;
+ int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
+ /*
+ * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
+@@ -1138,7 +1137,7 @@ after_immediate_data:
+
+ rc = iscsit_dump_data_payload(cmd->conn,
+ cmd->first_burst_len, 1);
+- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
++ target_put_sess_cmd(&cmd->se_cmd);
+ return rc;
+ } else if (cmd->unsolicited_data)
+ iscsit_set_unsoliticed_dataout(cmd);
+@@ -1807,7 +1806,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ conn->sess->se_sess, 0, DMA_NONE,
+ TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
+
+- target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true);
++ target_get_sess_cmd(&cmd->se_cmd, true);
+ sess_ref = true;
+
+ switch (function) {
+@@ -1949,7 +1948,7 @@ attach:
+ */
+ if (sess_ref) {
+ pr_debug("Handle TMR, using sess_ref=true check\n");
+- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
++ target_put_sess_cmd(&cmd->se_cmd);
+ }
+
+ iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
+index 5a8add721741..83bb55b94434 100644
+--- a/drivers/target/iscsi/iscsi_target_configfs.c
++++ b/drivers/target/iscsi/iscsi_target_configfs.c
+@@ -1981,7 +1981,7 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
+
+ static int lio_check_stop_free(struct se_cmd *se_cmd)
+ {
+- return target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ return target_put_sess_cmd(se_cmd);
+ }
+
+ static void lio_release_cmd(struct se_cmd *se_cmd)
+diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
+index b18edda3e8af..231e2e0e5894 100644
+--- a/drivers/target/iscsi/iscsi_target_util.c
++++ b/drivers/target/iscsi/iscsi_target_util.c
+@@ -746,7 +746,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
+ rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
+ if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
+ __iscsit_free_cmd(cmd, true, shutdown);
+- target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+ }
+ break;
+ case ISCSI_OP_REJECT:
+@@ -762,7 +762,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
+ rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
+ if (!rc && shutdown && se_cmd->se_sess) {
+ __iscsit_free_cmd(cmd, true, shutdown);
+- target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+ }
+ break;
+ }
+diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
+index 315ec3458eeb..adb8016955c4 100644
+--- a/drivers/target/target_core_tmr.c
++++ b/drivers/target/target_core_tmr.c
+@@ -71,7 +71,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr)
+
+ if (dev) {
+ spin_lock_irqsave(&dev->se_tmr_lock, flags);
+- list_del(&tmr->tmr_list);
++ list_del_init(&tmr->tmr_list);
+ spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
+ }
+
+@@ -153,7 +153,7 @@ void core_tmr_abort_task(
+ cancel_work_sync(&se_cmd->work);
+ transport_wait_for_tasks(se_cmd);
+
+- target_put_sess_cmd(se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+ transport_cmd_finish_abort(se_cmd, true);
+
+ printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
+@@ -175,9 +175,11 @@ static void core_tmr_drain_tmr_list(
+ struct list_head *preempt_and_abort_list)
+ {
+ LIST_HEAD(drain_tmr_list);
++ struct se_session *sess;
+ struct se_tmr_req *tmr_p, *tmr_pp;
+ struct se_cmd *cmd;
+ unsigned long flags;
++ bool rc;
+ /*
+ * Release all pending and outgoing TMRs aside from the received
+ * LUN_RESET tmr..
+@@ -203,17 +205,31 @@ static void core_tmr_drain_tmr_list(
+ if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
+ continue;
+
++ sess = cmd->se_sess;
++ if (WARN_ON_ONCE(!sess))
++ continue;
++
++ spin_lock(&sess->sess_cmd_lock);
+ spin_lock(&cmd->t_state_lock);
+ if (!(cmd->transport_state & CMD_T_ACTIVE)) {
+ spin_unlock(&cmd->t_state_lock);
++ spin_unlock(&sess->sess_cmd_lock);
+ continue;
+ }
+ if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) {
+ spin_unlock(&cmd->t_state_lock);
++ spin_unlock(&sess->sess_cmd_lock);
+ continue;
+ }
++ cmd->transport_state |= CMD_T_ABORTED;
+ spin_unlock(&cmd->t_state_lock);
+
++ rc = kref_get_unless_zero(&cmd->cmd_kref);
++ spin_unlock(&sess->sess_cmd_lock);
++ if (!rc) {
++ printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n");
++ continue;
++ }
+ list_move_tail(&tmr_p->tmr_list, &drain_tmr_list);
+ }
+ spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
+@@ -227,7 +243,11 @@ static void core_tmr_drain_tmr_list(
+ (preempt_and_abort_list) ? "Preempt" : "", tmr_p,
+ tmr_p->function, tmr_p->response, cmd->t_state);
+
++ cancel_work_sync(&cmd->work);
++ transport_wait_for_tasks(cmd);
++
+ transport_cmd_finish_abort(cmd, 1);
++ target_put_sess_cmd(cmd);
+ }
+ }
+
+diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
+index 675f2d9d1f14..3881504b40d8 100644
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -1419,7 +1419,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
+ * for fabrics using TARGET_SCF_ACK_KREF that expect a second
+ * kref_put() to happen during fabric packet acknowledgement.
+ */
+- ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
++ ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
+ if (ret)
+ return ret;
+ /*
+@@ -1433,7 +1433,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
+ rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun);
+ if (rc) {
+ transport_send_check_condition_and_sense(se_cmd, rc, 0);
+- target_put_sess_cmd(se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+ return 0;
+ }
+
+@@ -1584,7 +1584,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
+ se_cmd->se_tmr_req->ref_task_tag = tag;
+
+ /* See target_submit_cmd for commentary */
+- ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
++ ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
+ if (ret) {
+ core_tmr_release_req(se_cmd->se_tmr_req);
+ return ret;
+@@ -2227,7 +2227,7 @@ static int transport_release_cmd(struct se_cmd *cmd)
+ * If this cmd has been setup with target_get_sess_cmd(), drop
+ * the kref and call ->release_cmd() in kref callback.
+ */
+- return target_put_sess_cmd(cmd->se_sess, cmd);
++ return target_put_sess_cmd(cmd);
+ }
+
+ /**
+@@ -2471,13 +2471,12 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
+ EXPORT_SYMBOL(transport_generic_free_cmd);
+
+ /* target_get_sess_cmd - Add command to active ->sess_cmd_list
+- * @se_sess: session to reference
+ * @se_cmd: command descriptor to add
+ * @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd()
+ */
+-int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
+- bool ack_kref)
++int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
+ {
++ struct se_session *se_sess = se_cmd->se_sess;
+ unsigned long flags;
+ int ret = 0;
+
+@@ -2499,7 +2498,7 @@ out:
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+
+ if (ret && ack_kref)
+- target_put_sess_cmd(se_sess, se_cmd);
++ target_put_sess_cmd(se_cmd);
+
+ return ret;
+ }
+@@ -2528,11 +2527,12 @@ static void target_release_cmd_kref(struct kref *kref)
+ }
+
+ /* target_put_sess_cmd - Check for active I/O shutdown via kref_put
+- * @se_sess: session to reference
+ * @se_cmd: command descriptor to drop
+ */
+-int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
++int target_put_sess_cmd(struct se_cmd *se_cmd)
+ {
++ struct se_session *se_sess = se_cmd->se_sess;
++
+ if (!se_sess) {
+ se_cmd->se_tfo->release_cmd(se_cmd);
+ return 1;
+@@ -3025,8 +3025,17 @@ static void target_tmr_work(struct work_struct *work)
+ struct se_cmd *cmd = container_of(work, struct se_cmd, work);
+ struct se_device *dev = cmd->se_dev;
+ struct se_tmr_req *tmr = cmd->se_tmr_req;
++ unsigned long flags;
+ int ret;
+
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (cmd->transport_state & CMD_T_ABORTED) {
++ tmr->response = TMR_FUNCTION_REJECTED;
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ goto check_stop;
++ }
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
+ switch (tmr->function) {
+ case TMR_ABORT_TASK:
+ core_tmr_abort_task(dev, tmr, cmd->se_sess);
+@@ -3054,9 +3063,17 @@ static void target_tmr_work(struct work_struct *work)
+ break;
+ }
+
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (cmd->transport_state & CMD_T_ABORTED) {
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ goto check_stop;
++ }
+ cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
+ cmd->se_tfo->queue_tm_rsp(cmd);
+
++check_stop:
+ transport_cmd_check_stop_to_fabric(cmd);
+ }
+
+diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
+index 4d5e8409769c..254c183a5efe 100644
+--- a/drivers/tty/pty.c
++++ b/drivers/tty/pty.c
+@@ -672,7 +672,14 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+ /* this is called once with whichever end is closed last */
+ static void pty_unix98_shutdown(struct tty_struct *tty)
+ {
+- devpts_kill_index(tty->driver_data, tty->index);
++ struct inode *ptmx_inode;
++
++ if (tty->driver->subtype == PTY_TYPE_MASTER)
++ ptmx_inode = tty->driver_data;
++ else
++ ptmx_inode = tty->link->driver_data;
++ devpts_kill_index(ptmx_inode, tty->index);
++ devpts_del_ref(ptmx_inode);
+ }
+
+ static const struct tty_operations ptm_unix98_ops = {
+@@ -764,6 +771,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)
+ set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+ tty->driver_data = inode;
+
++ /*
++ * In the case where all references to ptmx inode are dropped and we
++ * still have /dev/tty opened pointing to the master/slave pair (ptmx
++ * is closed/released before /dev/tty), we must make sure that the inode
++ * is still valid when we call the final pty_unix98_shutdown, thus we
++ * hold an additional reference to the ptmx inode. For the same /dev/tty
++ * last close case, we also need to make sure the super_block isn't
++ * destroyed (devpts instance unmounted), before /dev/tty is closed and
++ * on its release devpts_kill_index is called.
++ */
++ devpts_add_ref(inode);
++
+ tty_add_file(tty, filp);
+
+ slave_inode = devpts_pty_new(inode,
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 2fd163b75665..b82b2a0f82a3 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -2002,6 +2002,7 @@ pci_wch_ch38x_setup(struct serial_private *priv,
+ #define PCIE_VENDOR_ID_WCH 0x1c00
+ #define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
+ #define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
++#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253
+
+ #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358
+ #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358
+@@ -2729,6 +2730,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
+ },
++ /* WCH CH382 2S card (16850 clone) */
++ {
++ .vendor = PCIE_VENDOR_ID_WCH,
++ .device = PCIE_DEVICE_ID_WCH_CH382_2S,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = pci_wch_ch38x_setup,
++ },
+ /* WCH CH382 2S1P card (16850 clone) */
+ {
+ .vendor = PCIE_VENDOR_ID_WCH,
+@@ -3049,6 +3058,7 @@ enum pci_board_num_t {
+ pbn_fintek_4,
+ pbn_fintek_8,
+ pbn_fintek_12,
++ pbn_wch382_2,
+ pbn_wch384_4,
+ pbn_pericom_PI7C9X7951,
+ pbn_pericom_PI7C9X7952,
+@@ -3879,6 +3889,13 @@ static struct pciserial_board pci_boards[] = {
+ .base_baud = 115200,
+ .first_offset = 0x40,
+ },
++ [pbn_wch382_2] = {
++ .flags = FL_BASE0,
++ .num_ports = 2,
++ .base_baud = 115200,
++ .uart_offset = 8,
++ .first_offset = 0xC0,
++ },
+ [pbn_wch384_4] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+@@ -5691,6 +5708,10 @@ static struct pci_device_id serial_pci_tbl[] = {
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_b0_bt_2_115200 },
+
++ { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0, pbn_wch382_2 },
++
+ { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_wch384_4 },
+diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
+index 7f49172ccd86..0a88693cd8ca 100644
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1368,7 +1368,7 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up)
+
+ /* Enable or disable the rs485 support */
+ static int
+-serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
++serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
+ {
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ unsigned int mode;
+@@ -1381,8 +1381,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
++ /* Clamp the delays to [0, 100ms] */
++ rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
++ rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
++
+ /* store new config */
+- port->rs485 = *rs485conf;
++ port->rs485 = *rs485;
+
+ /*
+ * Just as a precaution, only allow rs485
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index ea32b386797f..636435b41293 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -607,7 +607,7 @@ static void vhost_scsi_free_cmd(struct vhost_scsi_cmd *cmd)
+
+ static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd)
+ {
+- return target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++ return target_put_sess_cmd(se_cmd);
+ }
+
+ static void
+diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
+index 723470850b94..30bc9fa763bd 100644
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -1369,7 +1369,8 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+ read_extent_buffer(eb, dest + bytes_left,
+ name_off, name_len);
+ if (eb != eb_in) {
+- btrfs_tree_read_unlock_blocking(eb);
++ if (!path->skip_locking)
++ btrfs_tree_read_unlock_blocking(eb);
+ free_extent_buffer(eb);
+ }
+ ret = btrfs_find_item(fs_root, path, parent, 0,
+@@ -1389,9 +1390,10 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+ eb = path->nodes[0];
+ /* make sure we can use eb after releasing the path */
+ if (eb != eb_in) {
+- atomic_inc(&eb->refs);
+- btrfs_tree_read_lock(eb);
+- btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
++ if (!path->skip_locking)
++ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
++ path->nodes[0] = NULL;
++ path->locks[0] = 0;
+ }
+ btrfs_release_path(path);
+ iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
+diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
+index a2ae42720a6a..bc2d048a9eb9 100644
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -1690,7 +1690,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
+ *
+ */
+ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
+- struct list_head *ins_list)
++ struct list_head *ins_list, bool *emitted)
+ {
+ struct btrfs_dir_item *di;
+ struct btrfs_delayed_item *curr, *next;
+@@ -1734,6 +1734,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
+
+ if (over)
+ return 1;
++ *emitted = true;
+ }
+ return 0;
+ }
+diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
+index f70119f25421..0167853c84ae 100644
+--- a/fs/btrfs/delayed-inode.h
++++ b/fs/btrfs/delayed-inode.h
+@@ -144,7 +144,7 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
+ int btrfs_should_delete_dir_index(struct list_head *del_list,
+ u64 index);
+ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
+- struct list_head *ins_list);
++ struct list_head *ins_list, bool *emitted);
+
+ /* for init */
+ int __init btrfs_delayed_inode_init(void);
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index df4e0462976e..b114a0539d3d 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -5666,6 +5666,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
+ char *name_ptr;
+ int name_len;
+ int is_curr = 0; /* ctx->pos points to the current index? */
++ bool emitted;
+
+ /* FIXME, use a real flag for deciding about the key type */
+ if (root->fs_info->tree_root == root)
+@@ -5694,6 +5695,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
+ if (ret < 0)
+ goto err;
+
++ emitted = false;
+ while (1) {
+ leaf = path->nodes[0];
+ slot = path->slots[0];
+@@ -5773,6 +5775,7 @@ skip:
+
+ if (over)
+ goto nopos;
++ emitted = true;
+ di_len = btrfs_dir_name_len(leaf, di) +
+ btrfs_dir_data_len(leaf, di) + sizeof(*di);
+ di_cur += di_len;
+@@ -5785,11 +5788,20 @@ next:
+ if (key_type == BTRFS_DIR_INDEX_KEY) {
+ if (is_curr)
+ ctx->pos++;
+- ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
++ ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
+ if (ret)
+ goto nopos;
+ }
+
++ /*
++ * If we haven't emitted any dir entry, we must not touch ctx->pos as
++ * it was was set to the termination value in previous call. We assume
++ * that "." and ".." were emitted if we reach this point and set the
++ * termination value as well for an empty directory.
++ */
++ if (ctx->pos > 2 && !emitted)
++ goto nopos;
++
+ /* Reached end of directory/root. Bump pos past the last item. */
+ ctx->pos++;
+
+diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
+index afa09fce8151..e682b36a210f 100644
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -714,7 +714,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
+
+ ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
+ if (!ses->auth_key.response) {
+- rc = ENOMEM;
++ rc = -ENOMEM;
+ ses->auth_key.len = 0;
+ goto setup_ntlmv2_rsp_ret;
+ }
+diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
+index add566303c68..91360444adf5 100644
+--- a/fs/devpts/inode.c
++++ b/fs/devpts/inode.c
+@@ -569,6 +569,26 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
+ mutex_unlock(&allocated_ptys_lock);
+ }
+
++/*
++ * pty code needs to hold extra references in case of last /dev/tty close
++ */
++
++void devpts_add_ref(struct inode *ptmx_inode)
++{
++ struct super_block *sb = pts_sb_from_inode(ptmx_inode);
++
++ atomic_inc(&sb->s_active);
++ ihold(ptmx_inode);
++}
++
++void devpts_del_ref(struct inode *ptmx_inode)
++{
++ struct super_block *sb = pts_sb_from_inode(ptmx_inode);
++
++ iput(ptmx_inode);
++ deactivate_super(sb);
++}
++
+ /**
+ * devpts_pty_new -- create a new inode in /dev/pts/
+ * @ptmx_inode: inode of the master
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 966c614822cc..2b3a53a51582 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3133,29 +3133,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
+ * case, we allocate an io_end structure to hook to the iocb.
+ */
+ iocb->private = NULL;
+- ext4_inode_aio_set(inode, NULL);
+- if (!is_sync_kiocb(iocb)) {
+- io_end = ext4_init_io_end(inode, GFP_NOFS);
+- if (!io_end) {
+- ret = -ENOMEM;
+- goto retake_lock;
+- }
+- /*
+- * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
+- */
+- iocb->private = ext4_get_io_end(io_end);
+- /*
+- * we save the io structure for current async direct
+- * IO, so that later ext4_map_blocks() could flag the
+- * io structure whether there is a unwritten extents
+- * needs to be converted when IO is completed.
+- */
+- ext4_inode_aio_set(inode, io_end);
+- }
+-
+ if (overwrite) {
+ get_block_func = ext4_get_block_write_nolock;
+ } else {
++ ext4_inode_aio_set(inode, NULL);
++ if (!is_sync_kiocb(iocb)) {
++ io_end = ext4_init_io_end(inode, GFP_NOFS);
++ if (!io_end) {
++ ret = -ENOMEM;
++ goto retake_lock;
++ }
++ /*
++ * Grab reference for DIO. Will be dropped in
++ * ext4_end_io_dio()
++ */
++ iocb->private = ext4_get_io_end(io_end);
++ /*
++ * we save the io structure for current async direct
++ * IO, so that later ext4_map_blocks() could flag the
++ * io structure whether there is a unwritten extents
++ * needs to be converted when IO is completed.
++ */
++ ext4_inode_aio_set(inode, io_end);
++ }
+ get_block_func = ext4_get_block_write;
+ dio_flags = DIO_LOCKING;
+ }
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 370420bfae8d..7da8ac1047f8 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -268,11 +268,12 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
+ ext4_lblk_t orig_blk_offset, donor_blk_offset;
+ unsigned long blocksize = orig_inode->i_sb->s_blocksize;
+ unsigned int tmp_data_size, data_size, replaced_size;
+- int err2, jblocks, retries = 0;
++ int i, err2, jblocks, retries = 0;
+ int replaced_count = 0;
+ int from = data_offset_in_page << orig_inode->i_blkbits;
+ int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
+ struct super_block *sb = orig_inode->i_sb;
++ struct buffer_head *bh = NULL;
+
+ /*
+ * It needs twice the amount of ordinary journal buffers because
+@@ -383,8 +384,16 @@ data_copy:
+ }
+ /* Perform all necessary steps similar write_begin()/write_end()
+ * but keeping in mind that i_size will not change */
+- *err = __block_write_begin(pagep[0], from, replaced_size,
+- ext4_get_block);
++ if (!page_has_buffers(pagep[0]))
++ create_empty_buffers(pagep[0], 1 << orig_inode->i_blkbits, 0);
++ bh = page_buffers(pagep[0]);
++ for (i = 0; i < data_offset_in_page; i++)
++ bh = bh->b_this_page;
++ for (i = 0; i < block_len_in_page; i++) {
++ *err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0);
++ if (*err < 0)
++ break;
++ }
+ if (!*err)
+ *err = block_commit_write(pagep[0], from, from + replaced_size);
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index cf0c472047e3..0e783b9f7007 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -198,7 +198,7 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)
+ if (flex_gd == NULL)
+ goto out3;
+
+- if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data))
++ if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_group_data))
+ goto out2;
+ flex_gd->count = flexbg_size;
+
+diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h
+index 0419485891f2..0f1c6f315cdc 100644
+--- a/include/asm-generic/cputime_nsecs.h
++++ b/include/asm-generic/cputime_nsecs.h
+@@ -75,7 +75,7 @@ typedef u64 __nocast cputime64_t;
+ */
+ static inline cputime_t timespec_to_cputime(const struct timespec *val)
+ {
+- u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
++ u64 ret = (u64)val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
+ return (__force cputime_t) ret;
+ }
+ static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
+@@ -91,7 +91,8 @@ static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
+ */
+ static inline cputime_t timeval_to_cputime(const struct timeval *val)
+ {
+- u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_usec * NSEC_PER_USEC;
++ u64 ret = (u64)val->tv_sec * NSEC_PER_SEC +
++ val->tv_usec * NSEC_PER_USEC;
+ return (__force cputime_t) ret;
+ }
+ static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
+diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
+new file mode 100644
+index 000000000000..8d9c7e7a6432
+--- /dev/null
++++ b/include/linux/cgroup-defs.h
+@@ -0,0 +1,470 @@
++/*
++ * linux/cgroup-defs.h - basic definitions for cgroup
++ *
++ * This file provides basic type and interface. Include this file directly
++ * only if necessary to avoid cyclic dependencies.
++ */
++#ifndef _LINUX_CGROUP_DEFS_H
++#define _LINUX_CGROUP_DEFS_H
++
++#include <linux/limits.h>
++#include <linux/list.h>
++#include <linux/idr.h>
++#include <linux/wait.h>
++#include <linux/mutex.h>
++#include <linux/rcupdate.h>
++#include <linux/percpu-refcount.h>
++#include <linux/workqueue.h>
++
++#ifdef CONFIG_CGROUPS
++
++struct cgroup;
++struct cgroup_root;
++struct cgroup_subsys;
++struct cgroup_taskset;
++struct kernfs_node;
++struct kernfs_ops;
++struct kernfs_open_file;
++
++#define MAX_CGROUP_TYPE_NAMELEN 32
++#define MAX_CGROUP_ROOT_NAMELEN 64
++#define MAX_CFTYPE_NAME 64
++
++/* define the enumeration of all cgroup subsystems */
++#define SUBSYS(_x) _x ## _cgrp_id,
++enum cgroup_subsys_id {
++#include <linux/cgroup_subsys.h>
++ CGROUP_SUBSYS_COUNT,
++};
++#undef SUBSYS
++
++/* bits in struct cgroup_subsys_state flags field */
++enum {
++ CSS_NO_REF = (1 << 0), /* no reference counting for this css */
++ CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */
++ CSS_RELEASED = (1 << 2), /* refcnt reached zero, released */
++};
++
++/* bits in struct cgroup flags field */
++enum {
++ /* Control Group requires release notifications to userspace */
++ CGRP_NOTIFY_ON_RELEASE,
++ /*
++ * Clone the parent's configuration when creating a new child
++ * cpuset cgroup. For historical reasons, this option can be
++ * specified at mount time and thus is implemented here.
++ */
++ CGRP_CPUSET_CLONE_CHILDREN,
++};
++
++/* cgroup_root->flags */
++enum {
++ CGRP_ROOT_SANE_BEHAVIOR = (1 << 0), /* __DEVEL__sane_behavior specified */
++ CGRP_ROOT_NOPREFIX = (1 << 1), /* mounted subsystems have no named prefix */
++ CGRP_ROOT_XATTR = (1 << 2), /* supports extended attributes */
++};
++
++/* cftype->flags */
++enum {
++ CFTYPE_ONLY_ON_ROOT = (1 << 0), /* only create on root cgrp */
++ CFTYPE_NOT_ON_ROOT = (1 << 1), /* don't create on root cgrp */
++ CFTYPE_NO_PREFIX = (1 << 3), /* (DON'T USE FOR NEW FILES) no subsys prefix */
++
++ /* internal flags, do not use outside cgroup core proper */
++ __CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */
++ __CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */
++};
++
++/*
++ * Per-subsystem/per-cgroup state maintained by the system. This is the
++ * fundamental structural building block that controllers deal with.
++ *
++ * Fields marked with "PI:" are public and immutable and may be accessed
++ * directly without synchronization.
++ */
++struct cgroup_subsys_state {
++ /* PI: the cgroup that this css is attached to */
++ struct cgroup *cgroup;
++
++ /* PI: the cgroup subsystem that this css is attached to */
++ struct cgroup_subsys *ss;
++
++ /* reference count - access via css_[try]get() and css_put() */
++ struct percpu_ref refcnt;
++
++ /* PI: the parent css */
++ struct cgroup_subsys_state *parent;
++
++ /* siblings list anchored at the parent's ->children */
++ struct list_head sibling;
++ struct list_head children;
++
++ /*
++ * PI: Subsys-unique ID. 0 is unused and root is always 1. The
++ * matching css can be looked up using css_from_id().
++ */
++ int id;
++
++ unsigned int flags;
++
++ /*
++ * Monotonically increasing unique serial number which defines a
++ * uniform order among all csses. It's guaranteed that all
++ * ->children lists are in the ascending order of ->serial_nr and
++ * used to allow interrupting and resuming iterations.
++ */
++ u64 serial_nr;
++
++ /*
++ * Incremented by online self and children. Used to guarantee that
++ * parents are not offlined before their children.
++ */
++ atomic_t online_cnt;
++
++ /* percpu_ref killing and RCU release */
++ struct rcu_head rcu_head;
++ struct work_struct destroy_work;
++};
++
++/*
++ * A css_set is a structure holding pointers to a set of
++ * cgroup_subsys_state objects. This saves space in the task struct
++ * object and speeds up fork()/exit(), since a single inc/dec and a
++ * list_add()/del() can bump the reference count on the entire cgroup
++ * set for a task.
++ */
++struct css_set {
++ /* Reference count */
++ atomic_t refcount;
++
++ /*
++ * List running through all cgroup groups in the same hash
++ * slot. Protected by css_set_lock
++ */
++ struct hlist_node hlist;
++
++ /*
++ * Lists running through all tasks using this cgroup group.
++ * mg_tasks lists tasks which belong to this cset but are in the
++ * process of being migrated out or in. Protected by
++ * css_set_rwsem, but, during migration, once tasks are moved to
++ * mg_tasks, it can be read safely while holding cgroup_mutex.
++ */
++ struct list_head tasks;
++ struct list_head mg_tasks;
++
++ /*
++ * List of cgrp_cset_links pointing at cgroups referenced from this
++ * css_set. Protected by css_set_lock.
++ */
++ struct list_head cgrp_links;
++
++ /* the default cgroup associated with this css_set */
++ struct cgroup *dfl_cgrp;
++
++ /*
++ * Set of subsystem states, one for each subsystem. This array is
++ * immutable after creation apart from the init_css_set during
++ * subsystem registration (at boot time).
++ */
++ struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
++
++ /*
++ * List of csets participating in the on-going migration either as
++ * source or destination. Protected by cgroup_mutex.
++ */
++ struct list_head mg_preload_node;
++ struct list_head mg_node;
++
++ /*
++ * If this cset is acting as the source of migration the following
++ * two fields are set. mg_src_cgrp is the source cgroup of the
++ * on-going migration and mg_dst_cset is the destination cset the
++ * target tasks on this cset should be migrated to. Protected by
++ * cgroup_mutex.
++ */
++ struct cgroup *mg_src_cgrp;
++ struct css_set *mg_dst_cset;
++
++ /*
++ * On the default hierarhcy, ->subsys[ssid] may point to a css
++ * attached to an ancestor instead of the cgroup this css_set is
++ * associated with. The following node is anchored at
++ * ->subsys[ssid]->cgroup->e_csets[ssid] and provides a way to
++ * iterate through all css's attached to a given cgroup.
++ */
++ struct list_head e_cset_node[CGROUP_SUBSYS_COUNT];
++
++ /* For RCU-protected deletion */
++ struct rcu_head rcu_head;
++};
++
++struct cgroup {
++ /* self css with NULL ->ss, points back to this cgroup */
++ struct cgroup_subsys_state self;
++
++ unsigned long flags; /* "unsigned long" so bitops work */
++
++ /*
++ * idr allocated in-hierarchy ID.
++ *
++ * ID 0 is not used, the ID of the root cgroup is always 1, and a
++ * new cgroup will be assigned with a smallest available ID.
++ *
++ * Allocating/Removing ID must be protected by cgroup_mutex.
++ */
++ int id;
++
++ /*
++ * If this cgroup contains any tasks, it contributes one to
++ * populated_cnt. All children with non-zero popuplated_cnt of
++ * their own contribute one. The count is zero iff there's no task
++ * in this cgroup or its subtree.
++ */
++ int populated_cnt;
++
++ struct kernfs_node *kn; /* cgroup kernfs entry */
++ struct kernfs_node *populated_kn; /* kn for "cgroup.subtree_populated" */
++
++ /*
++ * The bitmask of subsystems enabled on the child cgroups.
++ * ->subtree_control is the one configured through
++ * "cgroup.subtree_control" while ->child_subsys_mask is the
++ * effective one which may have more subsystems enabled.
++ * Controller knobs are made available iff it's enabled in
++ * ->subtree_control.
++ */
++ unsigned int subtree_control;
++ unsigned int child_subsys_mask;
++
++ /* Private pointers for each registered subsystem */
++ struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT];
++
++ struct cgroup_root *root;
++
++ /*
++ * List of cgrp_cset_links pointing at css_sets with tasks in this
++ * cgroup. Protected by css_set_lock.
++ */
++ struct list_head cset_links;
++
++ /*
++ * On the default hierarchy, a css_set for a cgroup with some
++ * susbsys disabled will point to css's which are associated with
++ * the closest ancestor which has the subsys enabled. The
++ * following lists all css_sets which point to this cgroup's css
++ * for the given subsystem.
++ */
++ struct list_head e_csets[CGROUP_SUBSYS_COUNT];
++
++ /*
++ * list of pidlists, up to two for each namespace (one for procs, one
++ * for tasks); created on demand.
++ */
++ struct list_head pidlists;
++ struct mutex pidlist_mutex;
++
++ /* used to wait for offlining of csses */
++ wait_queue_head_t offline_waitq;
++
++ /* used to schedule release agent */
++ struct work_struct release_agent_work;
++};
++
++/*
++ * A cgroup_root represents the root of a cgroup hierarchy, and may be
++ * associated with a kernfs_root to form an active hierarchy. This is
++ * internal to cgroup core. Don't access directly from controllers.
++ */
++struct cgroup_root {
++ struct kernfs_root *kf_root;
++
++ /* The bitmask of subsystems attached to this hierarchy */
++ unsigned int subsys_mask;
++
++ /* Unique id for this hierarchy. */
++ int hierarchy_id;
++
++ /* The root cgroup. Root is destroyed on its release. */
++ struct cgroup cgrp;
++
++ /* Number of cgroups in the hierarchy, used only for /proc/cgroups */
++ atomic_t nr_cgrps;
++
++ /* A list running through the active hierarchies */
++ struct list_head root_list;
++
++ /* Hierarchy-specific flags */
++ unsigned int flags;
++
++ /* IDs for cgroups in this hierarchy */
++ struct idr cgroup_idr;
++
++ /* The path to use for release notifications. */
++ char release_agent_path[PATH_MAX];
++
++ /* The name for this hierarchy - may be empty */
++ char name[MAX_CGROUP_ROOT_NAMELEN];
++};
++
++/*
++ * struct cftype: handler definitions for cgroup control files
++ *
++ * When reading/writing to a file:
++ * - the cgroup to use is file->f_path.dentry->d_parent->d_fsdata
++ * - the 'cftype' of the file is file->f_path.dentry->d_fsdata
++ */
++struct cftype {
++ /*
++ * By convention, the name should begin with the name of the
++ * subsystem, followed by a period. Zero length string indicates
++ * end of cftype array.
++ */
++ char name[MAX_CFTYPE_NAME];
++ int private;
++ /*
++ * If not 0, file mode is set to this value, otherwise it will
++ * be figured out automatically
++ */
++ umode_t mode;
++
++ /*
++ * The maximum length of string, excluding trailing nul, that can
++ * be passed to write. If < PAGE_SIZE-1, PAGE_SIZE-1 is assumed.
++ */
++ size_t max_write_len;
++
++ /* CFTYPE_* flags */
++ unsigned int flags;
++
++ /*
++ * Fields used for internal bookkeeping. Initialized automatically
++ * during registration.
++ */
++ struct cgroup_subsys *ss; /* NULL for cgroup core files */
++ struct list_head node; /* anchored at ss->cfts */
++ struct kernfs_ops *kf_ops;
++
++ /*
++ * read_u64() is a shortcut for the common case of returning a
++ * single integer. Use it in place of read()
++ */
++ u64 (*read_u64)(struct cgroup_subsys_state *css, struct cftype *cft);
++ /*
++ * read_s64() is a signed version of read_u64()
++ */
++ s64 (*read_s64)(struct cgroup_subsys_state *css, struct cftype *cft);
++
++ /* generic seq_file read interface */
++ int (*seq_show)(struct seq_file *sf, void *v);
++
++ /* optional ops, implement all or none */
++ void *(*seq_start)(struct seq_file *sf, loff_t *ppos);
++ void *(*seq_next)(struct seq_file *sf, void *v, loff_t *ppos);
++ void (*seq_stop)(struct seq_file *sf, void *v);
++
++ /*
++ * write_u64() is a shortcut for the common case of accepting
++ * a single integer (as parsed by simple_strtoull) from
++ * userspace. Use in place of write(); return 0 or error.
++ */
++ int (*write_u64)(struct cgroup_subsys_state *css, struct cftype *cft,
++ u64 val);
++ /*
++ * write_s64() is a signed version of write_u64()
++ */
++ int (*write_s64)(struct cgroup_subsys_state *css, struct cftype *cft,
++ s64 val);
++
++ /*
++ * write() is the generic write callback which maps directly to
++ * kernfs write operation and overrides all other operations.
++ * Maximum write size is determined by ->max_write_len. Use
++ * of_css/cft() to access the associated css and cft.
++ */
++ ssize_t (*write)(struct kernfs_open_file *of,
++ char *buf, size_t nbytes, loff_t off);
++
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++ struct lock_class_key lockdep_key;
++#endif
++};
++
++/*
++ * Control Group subsystem type.
++ * See Documentation/cgroups/cgroups.txt for details
++ */
++struct cgroup_subsys {
++ struct cgroup_subsys_state *(*css_alloc)(struct cgroup_subsys_state *parent_css);
++ int (*css_online)(struct cgroup_subsys_state *css);
++ void (*css_offline)(struct cgroup_subsys_state *css);
++ void (*css_released)(struct cgroup_subsys_state *css);
++ void (*css_free)(struct cgroup_subsys_state *css);
++ void (*css_reset)(struct cgroup_subsys_state *css);
++ void (*css_e_css_changed)(struct cgroup_subsys_state *css);
++
++ int (*can_attach)(struct cgroup_subsys_state *css,
++ struct cgroup_taskset *tset);
++ void (*cancel_attach)(struct cgroup_subsys_state *css,
++ struct cgroup_taskset *tset);
++ void (*attach)(struct cgroup_subsys_state *css,
++ struct cgroup_taskset *tset);
++ void (*fork)(struct task_struct *task);
++ void (*exit)(struct cgroup_subsys_state *css,
++ struct cgroup_subsys_state *old_css,
++ struct task_struct *task);
++ void (*bind)(struct cgroup_subsys_state *root_css);
++
++ int disabled;
++ int early_init;
++
++ /*
++ * If %false, this subsystem is properly hierarchical -
++ * configuration, resource accounting and restriction on a parent
++ * cgroup cover those of its children. If %true, hierarchy support
++ * is broken in some ways - some subsystems ignore hierarchy
++ * completely while others are only implemented half-way.
++ *
++ * It's now disallowed to create nested cgroups if the subsystem is
++ * broken and cgroup core will emit a warning message on such
++ * cases. Eventually, all subsystems will be made properly
++ * hierarchical and this will go away.
++ */
++ bool broken_hierarchy;
++ bool warned_broken_hierarchy;
++
++ /* the following two fields are initialized automtically during boot */
++ int id;
++ const char *name;
++
++ /* link to parent, protected by cgroup_lock() */
++ struct cgroup_root *root;
++
++ /* idr for css->id */
++ struct idr css_idr;
++
++ /*
++ * List of cftypes. Each entry is the first entry of an array
++ * terminated by zero length name.
++ */
++ struct list_head cfts;
++
++ /*
++ * Base cftypes which are automatically registered. The two can
++ * point to the same array.
++ */
++ struct cftype *dfl_cftypes; /* for the default hierarchy */
++ struct cftype *legacy_cftypes; /* for the legacy hierarchies */
++
++ /*
++ * A subsystem may depend on other subsystems. When such subsystem
++ * is enabled on a cgroup, the depended-upon subsystems are enabled
++ * together if available. Subsystems enabled due to dependency are
++ * not visible to userland until explicitly enabled. The following
++ * specifies the mask of subsystems that this one depends on.
++ */
++ unsigned int depends_on;
++};
++
++#endif /* CONFIG_CGROUPS */
++#endif /* _LINUX_CGROUP_DEFS_H */
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index b9cb94c3102a..96a2ecd5aa69 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -11,23 +11,16 @@
+ #include <linux/sched.h>
+ #include <linux/cpumask.h>
+ #include <linux/nodemask.h>
+-#include <linux/rcupdate.h>
+ #include <linux/rculist.h>
+ #include <linux/cgroupstats.h>
+ #include <linux/rwsem.h>
+-#include <linux/idr.h>
+-#include <linux/workqueue.h>
+ #include <linux/fs.h>
+-#include <linux/percpu-refcount.h>
+ #include <linux/seq_file.h>
+ #include <linux/kernfs.h>
+-#include <linux/wait.h>
+
+-#ifdef CONFIG_CGROUPS
++#include <linux/cgroup-defs.h>
+
+-struct cgroup_root;
+-struct cgroup_subsys;
+-struct cgroup;
++#ifdef CONFIG_CGROUPS
+
+ extern int cgroup_init_early(void);
+ extern int cgroup_init(void);
+@@ -40,66 +33,6 @@ extern int cgroupstats_build(struct cgroupstats *stats,
+ extern int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *tsk);
+
+-/* define the enumeration of all cgroup subsystems */
+-#define SUBSYS(_x) _x ## _cgrp_id,
+-enum cgroup_subsys_id {
+-#include <linux/cgroup_subsys.h>
+- CGROUP_SUBSYS_COUNT,
+-};
+-#undef SUBSYS
+-
+-/*
+- * Per-subsystem/per-cgroup state maintained by the system. This is the
+- * fundamental structural building block that controllers deal with.
+- *
+- * Fields marked with "PI:" are public and immutable and may be accessed
+- * directly without synchronization.
+- */
+-struct cgroup_subsys_state {
+- /* PI: the cgroup that this css is attached to */
+- struct cgroup *cgroup;
+-
+- /* PI: the cgroup subsystem that this css is attached to */
+- struct cgroup_subsys *ss;
+-
+- /* reference count - access via css_[try]get() and css_put() */
+- struct percpu_ref refcnt;
+-
+- /* PI: the parent css */
+- struct cgroup_subsys_state *parent;
+-
+- /* siblings list anchored at the parent's ->children */
+- struct list_head sibling;
+- struct list_head children;
+-
+- /*
+- * PI: Subsys-unique ID. 0 is unused and root is always 1. The
+- * matching css can be looked up using css_from_id().
+- */
+- int id;
+-
+- unsigned int flags;
+-
+- /*
+- * Monotonically increasing unique serial number which defines a
+- * uniform order among all csses. It's guaranteed that all
+- * ->children lists are in the ascending order of ->serial_nr and
+- * used to allow interrupting and resuming iterations.
+- */
+- u64 serial_nr;
+-
+- /* percpu_ref killing and RCU release */
+- struct rcu_head rcu_head;
+- struct work_struct destroy_work;
+-};
+-
+-/* bits in struct cgroup_subsys_state flags field */
+-enum {
+- CSS_NO_REF = (1 << 0), /* no reference counting for this css */
+- CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */
+- CSS_RELEASED = (1 << 2), /* refcnt reached zero, released */
+-};
+-
+ /**
+ * css_get - obtain a reference on the specified css
+ * @css: target css
+@@ -185,307 +118,6 @@ static inline void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
+ percpu_ref_put_many(&css->refcnt, n);
+ }
+
+-/* bits in struct cgroup flags field */
+-enum {
+- /* Control Group requires release notifications to userspace */
+- CGRP_NOTIFY_ON_RELEASE,
+- /*
+- * Clone the parent's configuration when creating a new child
+- * cpuset cgroup. For historical reasons, this option can be
+- * specified at mount time and thus is implemented here.
+- */
+- CGRP_CPUSET_CLONE_CHILDREN,
+-};
+-
+-struct cgroup {
+- /* self css with NULL ->ss, points back to this cgroup */
+- struct cgroup_subsys_state self;
+-
+- unsigned long flags; /* "unsigned long" so bitops work */
+-
+- /*
+- * idr allocated in-hierarchy ID.
+- *
+- * ID 0 is not used, the ID of the root cgroup is always 1, and a
+- * new cgroup will be assigned with a smallest available ID.
+- *
+- * Allocating/Removing ID must be protected by cgroup_mutex.
+- */
+- int id;
+-
+- /*
+- * If this cgroup contains any tasks, it contributes one to
+- * populated_cnt. All children with non-zero popuplated_cnt of
+- * their own contribute one. The count is zero iff there's no task
+- * in this cgroup or its subtree.
+- */
+- int populated_cnt;
+-
+- struct kernfs_node *kn; /* cgroup kernfs entry */
+- struct kernfs_node *populated_kn; /* kn for "cgroup.subtree_populated" */
+-
+- /*
+- * The bitmask of subsystems enabled on the child cgroups.
+- * ->subtree_control is the one configured through
+- * "cgroup.subtree_control" while ->child_subsys_mask is the
+- * effective one which may have more subsystems enabled.
+- * Controller knobs are made available iff it's enabled in
+- * ->subtree_control.
+- */
+- unsigned int subtree_control;
+- unsigned int child_subsys_mask;
+-
+- /* Private pointers for each registered subsystem */
+- struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT];
+-
+- struct cgroup_root *root;
+-
+- /*
+- * List of cgrp_cset_links pointing at css_sets with tasks in this
+- * cgroup. Protected by css_set_lock.
+- */
+- struct list_head cset_links;
+-
+- /*
+- * On the default hierarchy, a css_set for a cgroup with some
+- * susbsys disabled will point to css's which are associated with
+- * the closest ancestor which has the subsys enabled. The
+- * following lists all css_sets which point to this cgroup's css
+- * for the given subsystem.
+- */
+- struct list_head e_csets[CGROUP_SUBSYS_COUNT];
+-
+- /*
+- * list of pidlists, up to two for each namespace (one for procs, one
+- * for tasks); created on demand.
+- */
+- struct list_head pidlists;
+- struct mutex pidlist_mutex;
+-
+- /* used to wait for offlining of csses */
+- wait_queue_head_t offline_waitq;
+-
+- /* used to schedule release agent */
+- struct work_struct release_agent_work;
+-};
+-
+-#define MAX_CGROUP_ROOT_NAMELEN 64
+-
+-/* cgroup_root->flags */
+-enum {
+- CGRP_ROOT_SANE_BEHAVIOR = (1 << 0), /* __DEVEL__sane_behavior specified */
+- CGRP_ROOT_NOPREFIX = (1 << 1), /* mounted subsystems have no named prefix */
+- CGRP_ROOT_XATTR = (1 << 2), /* supports extended attributes */
+-};
+-
+-/*
+- * A cgroup_root represents the root of a cgroup hierarchy, and may be
+- * associated with a kernfs_root to form an active hierarchy. This is
+- * internal to cgroup core. Don't access directly from controllers.
+- */
+-struct cgroup_root {
+- struct kernfs_root *kf_root;
+-
+- /* The bitmask of subsystems attached to this hierarchy */
+- unsigned int subsys_mask;
+-
+- /* Unique id for this hierarchy. */
+- int hierarchy_id;
+-
+- /* The root cgroup. Root is destroyed on its release. */
+- struct cgroup cgrp;
+-
+- /* Number of cgroups in the hierarchy, used only for /proc/cgroups */
+- atomic_t nr_cgrps;
+-
+- /* A list running through the active hierarchies */
+- struct list_head root_list;
+-
+- /* Hierarchy-specific flags */
+- unsigned int flags;
+-
+- /* IDs for cgroups in this hierarchy */
+- struct idr cgroup_idr;
+-
+- /* The path to use for release notifications. */
+- char release_agent_path[PATH_MAX];
+-
+- /* The name for this hierarchy - may be empty */
+- char name[MAX_CGROUP_ROOT_NAMELEN];
+-};
+-
+-/*
+- * A css_set is a structure holding pointers to a set of
+- * cgroup_subsys_state objects. This saves space in the task struct
+- * object and speeds up fork()/exit(), since a single inc/dec and a
+- * list_add()/del() can bump the reference count on the entire cgroup
+- * set for a task.
+- */
+-
+-struct css_set {
+-
+- /* Reference count */
+- atomic_t refcount;
+-
+- /*
+- * List running through all cgroup groups in the same hash
+- * slot. Protected by css_set_lock
+- */
+- struct hlist_node hlist;
+-
+- /*
+- * Lists running through all tasks using this cgroup group.
+- * mg_tasks lists tasks which belong to this cset but are in the
+- * process of being migrated out or in. Protected by
+- * css_set_rwsem, but, during migration, once tasks are moved to
+- * mg_tasks, it can be read safely while holding cgroup_mutex.
+- */
+- struct list_head tasks;
+- struct list_head mg_tasks;
+-
+- /*
+- * List of cgrp_cset_links pointing at cgroups referenced from this
+- * css_set. Protected by css_set_lock.
+- */
+- struct list_head cgrp_links;
+-
+- /* the default cgroup associated with this css_set */
+- struct cgroup *dfl_cgrp;
+-
+- /*
+- * Set of subsystem states, one for each subsystem. This array is
+- * immutable after creation apart from the init_css_set during
+- * subsystem registration (at boot time).
+- */
+- struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
+-
+- /*
+- * List of csets participating in the on-going migration either as
+- * source or destination. Protected by cgroup_mutex.
+- */
+- struct list_head mg_preload_node;
+- struct list_head mg_node;
+-
+- /*
+- * If this cset is acting as the source of migration the following
+- * two fields are set. mg_src_cgrp is the source cgroup of the
+- * on-going migration and mg_dst_cset is the destination cset the
+- * target tasks on this cset should be migrated to. Protected by
+- * cgroup_mutex.
+- */
+- struct cgroup *mg_src_cgrp;
+- struct css_set *mg_dst_cset;
+-
+- /*
+- * On the default hierarhcy, ->subsys[ssid] may point to a css
+- * attached to an ancestor instead of the cgroup this css_set is
+- * associated with. The following node is anchored at
+- * ->subsys[ssid]->cgroup->e_csets[ssid] and provides a way to
+- * iterate through all css's attached to a given cgroup.
+- */
+- struct list_head e_cset_node[CGROUP_SUBSYS_COUNT];
+-
+- /* For RCU-protected deletion */
+- struct rcu_head rcu_head;
+-};
+-
+-/*
+- * struct cftype: handler definitions for cgroup control files
+- *
+- * When reading/writing to a file:
+- * - the cgroup to use is file->f_path.dentry->d_parent->d_fsdata
+- * - the 'cftype' of the file is file->f_path.dentry->d_fsdata
+- */
+-
+-/* cftype->flags */
+-enum {
+- CFTYPE_ONLY_ON_ROOT = (1 << 0), /* only create on root cgrp */
+- CFTYPE_NOT_ON_ROOT = (1 << 1), /* don't create on root cgrp */
+- CFTYPE_NO_PREFIX = (1 << 3), /* (DON'T USE FOR NEW FILES) no subsys prefix */
+-
+- /* internal flags, do not use outside cgroup core proper */
+- __CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */
+- __CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */
+-};
+-
+-#define MAX_CFTYPE_NAME 64
+-
+-struct cftype {
+- /*
+- * By convention, the name should begin with the name of the
+- * subsystem, followed by a period. Zero length string indicates
+- * end of cftype array.
+- */
+- char name[MAX_CFTYPE_NAME];
+- int private;
+- /*
+- * If not 0, file mode is set to this value, otherwise it will
+- * be figured out automatically
+- */
+- umode_t mode;
+-
+- /*
+- * The maximum length of string, excluding trailing nul, that can
+- * be passed to write. If < PAGE_SIZE-1, PAGE_SIZE-1 is assumed.
+- */
+- size_t max_write_len;
+-
+- /* CFTYPE_* flags */
+- unsigned int flags;
+-
+- /*
+- * Fields used for internal bookkeeping. Initialized automatically
+- * during registration.
+- */
+- struct cgroup_subsys *ss; /* NULL for cgroup core files */
+- struct list_head node; /* anchored at ss->cfts */
+- struct kernfs_ops *kf_ops;
+-
+- /*
+- * read_u64() is a shortcut for the common case of returning a
+- * single integer. Use it in place of read()
+- */
+- u64 (*read_u64)(struct cgroup_subsys_state *css, struct cftype *cft);
+- /*
+- * read_s64() is a signed version of read_u64()
+- */
+- s64 (*read_s64)(struct cgroup_subsys_state *css, struct cftype *cft);
+-
+- /* generic seq_file read interface */
+- int (*seq_show)(struct seq_file *sf, void *v);
+-
+- /* optional ops, implement all or none */
+- void *(*seq_start)(struct seq_file *sf, loff_t *ppos);
+- void *(*seq_next)(struct seq_file *sf, void *v, loff_t *ppos);
+- void (*seq_stop)(struct seq_file *sf, void *v);
+-
+- /*
+- * write_u64() is a shortcut for the common case of accepting
+- * a single integer (as parsed by simple_strtoull) from
+- * userspace. Use in place of write(); return 0 or error.
+- */
+- int (*write_u64)(struct cgroup_subsys_state *css, struct cftype *cft,
+- u64 val);
+- /*
+- * write_s64() is a signed version of write_u64()
+- */
+- int (*write_s64)(struct cgroup_subsys_state *css, struct cftype *cft,
+- s64 val);
+-
+- /*
+- * write() is the generic write callback which maps directly to
+- * kernfs write operation and overrides all other operations.
+- * Maximum write size is determined by ->max_write_len. Use
+- * of_css/cft() to access the associated css and cft.
+- */
+- ssize_t (*write)(struct kernfs_open_file *of,
+- char *buf, size_t nbytes, loff_t off);
+-
+-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+- struct lock_class_key lockdep_key;
+-#endif
+-};
+-
+ extern struct cgroup_root cgrp_dfl_root;
+ extern struct css_set init_css_set;
+
+@@ -612,11 +244,6 @@ int cgroup_rm_cftypes(struct cftype *cfts);
+
+ bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
+
+-/*
+- * Control Group taskset, used to pass around set of tasks to cgroup_subsys
+- * methods.
+- */
+-struct cgroup_taskset;
+ struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset);
+ struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset);
+
+@@ -629,84 +256,6 @@ struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset);
+ for ((task) = cgroup_taskset_first((tset)); (task); \
+ (task) = cgroup_taskset_next((tset)))
+
+-/*
+- * Control Group subsystem type.
+- * See Documentation/cgroups/cgroups.txt for details
+- */
+-
+-struct cgroup_subsys {
+- struct cgroup_subsys_state *(*css_alloc)(struct cgroup_subsys_state *parent_css);
+- int (*css_online)(struct cgroup_subsys_state *css);
+- void (*css_offline)(struct cgroup_subsys_state *css);
+- void (*css_released)(struct cgroup_subsys_state *css);
+- void (*css_free)(struct cgroup_subsys_state *css);
+- void (*css_reset)(struct cgroup_subsys_state *css);
+- void (*css_e_css_changed)(struct cgroup_subsys_state *css);
+-
+- int (*can_attach)(struct cgroup_subsys_state *css,
+- struct cgroup_taskset *tset);
+- void (*cancel_attach)(struct cgroup_subsys_state *css,
+- struct cgroup_taskset *tset);
+- void (*attach)(struct cgroup_subsys_state *css,
+- struct cgroup_taskset *tset);
+- void (*fork)(struct task_struct *task);
+- void (*exit)(struct cgroup_subsys_state *css,
+- struct cgroup_subsys_state *old_css,
+- struct task_struct *task);
+- void (*bind)(struct cgroup_subsys_state *root_css);
+-
+- int disabled;
+- int early_init;
+-
+- /*
+- * If %false, this subsystem is properly hierarchical -
+- * configuration, resource accounting and restriction on a parent
+- * cgroup cover those of its children. If %true, hierarchy support
+- * is broken in some ways - some subsystems ignore hierarchy
+- * completely while others are only implemented half-way.
+- *
+- * It's now disallowed to create nested cgroups if the subsystem is
+- * broken and cgroup core will emit a warning message on such
+- * cases. Eventually, all subsystems will be made properly
+- * hierarchical and this will go away.
+- */
+- bool broken_hierarchy;
+- bool warned_broken_hierarchy;
+-
+- /* the following two fields are initialized automtically during boot */
+- int id;
+-#define MAX_CGROUP_TYPE_NAMELEN 32
+- const char *name;
+-
+- /* link to parent, protected by cgroup_lock() */
+- struct cgroup_root *root;
+-
+- /* idr for css->id */
+- struct idr css_idr;
+-
+- /*
+- * List of cftypes. Each entry is the first entry of an array
+- * terminated by zero length name.
+- */
+- struct list_head cfts;
+-
+- /*
+- * Base cftypes which are automatically registered. The two can
+- * point to the same array.
+- */
+- struct cftype *dfl_cftypes; /* for the default hierarchy */
+- struct cftype *legacy_cftypes; /* for the legacy hierarchies */
+-
+- /*
+- * A subsystem may depend on other subsystems. When such subsystem
+- * is enabled on a cgroup, the depended-upon subsystems are enabled
+- * together if available. Subsystems enabled due to dependency are
+- * not visible to userland until explicitly enabled. The following
+- * specifies the mask of subsystems that this one depends on.
+- */
+- unsigned int depends_on;
+-};
+-
+ #define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
+ #include <linux/cgroup_subsys.h>
+ #undef SUBSYS
+diff --git a/include/linux/compiler.h b/include/linux/compiler.h
+index 867722591be2..99728072e536 100644
+--- a/include/linux/compiler.h
++++ b/include/linux/compiler.h
+@@ -142,7 +142,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
+ */
+ #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
+ #define __trace_if(cond) \
+- if (__builtin_constant_p((cond)) ? !!(cond) : \
++ if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
+ ({ \
+ int ______r; \
+ static struct ftrace_branch_data \
+diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
+index 251a2090a554..e0ee0b3000b2 100644
+--- a/include/linux/devpts_fs.h
++++ b/include/linux/devpts_fs.h
+@@ -19,6 +19,8 @@
+
+ int devpts_new_index(struct inode *ptmx_inode);
+ void devpts_kill_index(struct inode *ptmx_inode, int idx);
++void devpts_add_ref(struct inode *ptmx_inode);
++void devpts_del_ref(struct inode *ptmx_inode);
+ /* mknod in devpts */
+ struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+ void *priv);
+@@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode);
+ /* Dummy stubs in the no-pty case */
+ static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
+ static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
++static inline void devpts_add_ref(struct inode *ptmx_inode) { }
++static inline void devpts_del_ref(struct inode *ptmx_inode) { }
+ static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
+ dev_t device, int index, void *priv)
+ {
+diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
+index e4b464983322..01c25923675b 100644
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -29,6 +29,7 @@ struct ipv6_devconf {
+ __s32 max_desync_factor;
+ __s32 max_addresses;
+ __s32 accept_ra_defrtr;
++ __s32 accept_ra_min_hop_limit;
+ __s32 accept_ra_pinfo;
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+ __s32 accept_ra_rtr_pref;
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 1f17abe23725..6633b0cd3fb9 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -203,6 +203,7 @@ struct sk_buff;
+ #else
+ #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1)
+ #endif
++extern int sysctl_max_skb_frags;
+
+ typedef struct skb_frag_struct skb_frag_t;
+
+diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
+index a5f7f3ecafa3..a6e1bca88cc6 100644
+--- a/include/linux/tracepoint.h
++++ b/include/linux/tracepoint.h
+@@ -14,8 +14,10 @@
+ * See the file COPYING for more details.
+ */
+
++#include <linux/smp.h>
+ #include <linux/errno.h>
+ #include <linux/types.h>
++#include <linux/cpumask.h>
+ #include <linux/rcupdate.h>
+ #include <linux/static_key.h>
+
+@@ -129,6 +131,9 @@ extern void syscall_unregfunc(void);
+ void *it_func; \
+ void *__data; \
+ \
++ if (!cpu_online(raw_smp_processor_id())) \
++ return; \
++ \
+ if (!(cond)) \
+ return; \
+ prercu; \
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index e830c3dff61a..7bb69c9c3c43 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -6,8 +6,8 @@
+ #include <linux/mutex.h>
+ #include <net/sock.h>
+
+-void unix_inflight(struct file *fp);
+-void unix_notinflight(struct file *fp);
++void unix_inflight(struct user_struct *user, struct file *fp);
++void unix_notinflight(struct user_struct *user, struct file *fp);
+ void unix_gc(void);
+ void wait_for_unix_gc(void);
+ struct sock *unix_get_socket(struct file *filp);
+diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
+index 5e192068e6cb..388dea4da083 100644
+--- a/include/net/ip6_route.h
++++ b/include/net/ip6_route.h
+@@ -64,8 +64,16 @@ static inline bool rt6_need_strict(const struct in6_addr *daddr)
+
+ void ip6_route_input(struct sk_buff *skb);
+
+-struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
+- struct flowi6 *fl6);
++struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
++ struct flowi6 *fl6, int flags);
++
++static inline struct dst_entry *ip6_route_output(struct net *net,
++ const struct sock *sk,
++ struct flowi6 *fl6)
++{
++ return ip6_route_output_flags(net, sk, fl6, 0);
++}
++
+ struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
+ int flags);
+
+diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
+index 54271ed0ed45..13f1a97f6b2b 100644
+--- a/include/net/ip_fib.h
++++ b/include/net/ip_fib.h
+@@ -59,6 +59,7 @@ struct fib_nh_exception {
+ struct rtable __rcu *fnhe_rth_input;
+ struct rtable __rcu *fnhe_rth_output;
+ unsigned long fnhe_stamp;
++ struct rcu_head rcu;
+ };
+
+ struct fnhe_hash_bucket {
+diff --git a/include/net/scm.h b/include/net/scm.h
+index 262532d111f5..59fa93c01d2a 100644
+--- a/include/net/scm.h
++++ b/include/net/scm.h
+@@ -21,6 +21,7 @@ struct scm_creds {
+ struct scm_fp_list {
+ short count;
+ short max;
++ struct user_struct *user;
+ struct file *fp[SCM_MAX_FD];
+ };
+
+diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
+index 0f4dc3768587..24c8d9d0d946 100644
+--- a/include/target/target_core_fabric.h
++++ b/include/target/target_core_fabric.h
+@@ -155,8 +155,8 @@ bool transport_wait_for_tasks(struct se_cmd *);
+ int transport_check_aborted_status(struct se_cmd *, int);
+ int transport_send_check_condition_and_sense(struct se_cmd *,
+ sense_reason_t, int);
+-int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
+-int target_put_sess_cmd(struct se_session *, struct se_cmd *);
++int target_get_sess_cmd(struct se_cmd *, bool);
++int target_put_sess_cmd(struct se_cmd *);
+ void target_sess_cmd_list_set_waiting(struct se_session *);
+ void target_wait_for_sess_cmds(struct se_session *);
+
+diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
+index 5efa54ae567c..80f3b74446a1 100644
+--- a/include/uapi/linux/ipv6.h
++++ b/include/uapi/linux/ipv6.h
+@@ -171,6 +171,8 @@ enum {
+ DEVCONF_USE_OPTIMISTIC,
+ DEVCONF_ACCEPT_RA_MTU,
+ DEVCONF_STABLE_SECRET,
++ DEVCONF_USE_OIF_ADDRS_ONLY,
++ DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
+ DEVCONF_MAX
+ };
+
+diff --git a/ipc/msgutil.c b/ipc/msgutil.c
+index 2b491590ebab..71f448e5e927 100644
+--- a/ipc/msgutil.c
++++ b/ipc/msgutil.c
+@@ -123,7 +123,7 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
+ size_t len = src->m_ts;
+ size_t alen;
+
+- BUG_ON(dst == NULL);
++ WARN_ON(dst == NULL);
+ if (src->m_ts > dst->m_ts)
+ return ERR_PTR(-EINVAL);
+
+diff --git a/ipc/shm.c b/ipc/shm.c
+index 499a8bd22fad..bbe5f62f2b12 100644
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -155,9 +155,13 @@ static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
+ {
+ struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
+
++ /*
++ * Callers of shm_lock() must validate the status of the returned ipc
++ * object pointer (as returned by ipc_lock()), and error out as
++ * appropriate.
++ */
+ if (IS_ERR(ipcp))
+- return (struct shmid_kernel *)ipcp;
+-
++ return (void *)ipcp;
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
+ }
+
+@@ -183,19 +187,33 @@ static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
+ }
+
+
+-/* This is called by fork, once for every shm attach. */
+-static void shm_open(struct vm_area_struct *vma)
++static int __shm_open(struct vm_area_struct *vma)
+ {
+ struct file *file = vma->vm_file;
+ struct shm_file_data *sfd = shm_file_data(file);
+ struct shmid_kernel *shp;
+
+ shp = shm_lock(sfd->ns, sfd->id);
+- BUG_ON(IS_ERR(shp));
++
++ if (IS_ERR(shp))
++ return PTR_ERR(shp);
++
+ shp->shm_atim = get_seconds();
+ shp->shm_lprid = task_tgid_vnr(current);
+ shp->shm_nattch++;
+ shm_unlock(shp);
++ return 0;
++}
++
++/* This is called by fork, once for every shm attach. */
++static void shm_open(struct vm_area_struct *vma)
++{
++ int err = __shm_open(vma);
++ /*
++ * We raced in the idr lookup or with shm_destroy().
++ * Either way, the ID is busted.
++ */
++ WARN_ON_ONCE(err);
+ }
+
+ /*
+@@ -258,7 +276,14 @@ static void shm_close(struct vm_area_struct *vma)
+ down_write(&shm_ids(ns).rwsem);
+ /* remove from the list of attaches of the shm segment */
+ shp = shm_lock(ns, sfd->id);
+- BUG_ON(IS_ERR(shp));
++
++ /*
++ * We raced in the idr lookup or with shm_destroy().
++ * Either way, the ID is busted.
++ */
++ if (WARN_ON_ONCE(IS_ERR(shp)))
++ goto done; /* no-op */
++
+ shp->shm_lprid = task_tgid_vnr(current);
+ shp->shm_dtim = get_seconds();
+ shp->shm_nattch--;
+@@ -266,6 +291,7 @@ static void shm_close(struct vm_area_struct *vma)
+ shm_destroy(ns, shp);
+ else
+ shm_unlock(shp);
++done:
+ up_write(&shm_ids(ns).rwsem);
+ }
+
+@@ -387,17 +413,25 @@ static int shm_mmap(struct file *file, struct vm_area_struct *vma)
+ struct shm_file_data *sfd = shm_file_data(file);
+ int ret;
+
++ /*
++ * In case of remap_file_pages() emulation, the file can represent
++ * removed IPC ID: propogate shm_lock() error to caller.
++ */
++ ret =__shm_open(vma);
++ if (ret)
++ return ret;
++
+ ret = sfd->file->f_op->mmap(sfd->file, vma);
+- if (ret != 0)
++ if (ret) {
++ shm_close(vma);
+ return ret;
++ }
+ sfd->vm_ops = vma->vm_ops;
+ #ifdef CONFIG_MMU
+- BUG_ON(!sfd->vm_ops->fault);
++ WARN_ON(!sfd->vm_ops->fault);
+ #endif
+ vma->vm_ops = &shm_vm_ops;
+- shm_open(vma);
+-
+- return ret;
++ return 0;
+ }
+
+ static int shm_release(struct inode *ino, struct file *file)
+@@ -1192,7 +1226,6 @@ out_fput:
+ out_nattch:
+ down_write(&shm_ids(ns).rwsem);
+ shp = shm_lock(ns, shmid);
+- BUG_ON(IS_ERR(shp));
+ shp->shm_nattch--;
+ if (shm_may_destroy(ns, shp))
+ shm_destroy(ns, shp);
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 141d562064a7..6582410a71c7 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -1944,7 +1944,7 @@ static void adjust_branches(struct bpf_prog *prog, int pos, int delta)
+ /* adjust offset of jmps if necessary */
+ if (i < pos && i + insn->off + 1 > pos)
+ insn->off += delta;
+- else if (i > pos && i + insn->off + 1 < pos)
++ else if (i > pos + delta && i + insn->off + 1 <= pos + delta)
+ insn->off -= delta;
+ }
+ }
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 4d65b66ae60d..359da3abb004 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -4481,6 +4481,7 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
+ INIT_LIST_HEAD(&css->sibling);
+ INIT_LIST_HEAD(&css->children);
+ css->serial_nr = css_serial_nr_next++;
++ atomic_set(&css->online_cnt, 0);
+
+ if (cgroup_parent(cgrp)) {
+ css->parent = cgroup_css(cgroup_parent(cgrp), ss);
+@@ -4503,6 +4504,10 @@ static int online_css(struct cgroup_subsys_state *css)
+ if (!ret) {
+ css->flags |= CSS_ONLINE;
+ rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
++
++ atomic_inc(&css->online_cnt);
++ if (css->parent)
++ atomic_inc(&css->parent->online_cnt);
+ }
+ return ret;
+ }
+@@ -4740,10 +4745,15 @@ static void css_killed_work_fn(struct work_struct *work)
+ container_of(work, struct cgroup_subsys_state, destroy_work);
+
+ mutex_lock(&cgroup_mutex);
+- offline_css(css);
+- mutex_unlock(&cgroup_mutex);
+
+- css_put(css);
++ do {
++ offline_css(css);
++ css_put(css);
++ /* @css can't go away while we're holding cgroup_mutex */
++ css = css->parent;
++ } while (css && atomic_dec_and_test(&css->online_cnt));
++
++ mutex_unlock(&cgroup_mutex);
+ }
+
+ /* css kill confirmation processing requires process context, bounce */
+@@ -4752,8 +4762,10 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
+ struct cgroup_subsys_state *css =
+ container_of(ref, struct cgroup_subsys_state, refcnt);
+
+- INIT_WORK(&css->destroy_work, css_killed_work_fn);
+- queue_work(cgroup_destroy_wq, &css->destroy_work);
++ if (atomic_dec_and_test(&css->online_cnt)) {
++ INIT_WORK(&css->destroy_work, css_killed_work_fn);
++ queue_work(cgroup_destroy_wq, &css->destroy_work);
++ }
+ }
+
+ /**
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 5c01664c26e2..6d631161705c 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -127,6 +127,11 @@ enum {
+ *
+ * PR: wq_pool_mutex protected for writes. Sched-RCU protected for reads.
+ *
++ * PW: wq_pool_mutex and wq->mutex protected for writes. Either for reads.
++ *
++ * PWR: wq_pool_mutex and wq->mutex protected for writes. Either or
++ * sched-RCU for reads.
++ *
+ * WQ: wq->mutex protected.
+ *
+ * WR: wq->mutex protected for writes. Sched-RCU protected for reads.
+@@ -247,8 +252,8 @@ struct workqueue_struct {
+ int nr_drainers; /* WQ: drain in progress */
+ int saved_max_active; /* WQ: saved pwq max_active */
+
+- struct workqueue_attrs *unbound_attrs; /* WQ: only for unbound wqs */
+- struct pool_workqueue *dfl_pwq; /* WQ: only for unbound wqs */
++ struct workqueue_attrs *unbound_attrs; /* PW: only for unbound wqs */
++ struct pool_workqueue *dfl_pwq; /* PW: only for unbound wqs */
+
+ #ifdef CONFIG_SYSFS
+ struct wq_device *wq_dev; /* I: for sysfs interface */
+@@ -268,7 +273,7 @@ struct workqueue_struct {
+ /* hot fields used during command issue, aligned to cacheline */
+ unsigned int flags ____cacheline_aligned; /* WQ: WQ_* flags */
+ struct pool_workqueue __percpu *cpu_pwqs; /* I: per-cpu pwqs */
+- struct pool_workqueue __rcu *numa_pwq_tbl[]; /* FR: unbound pwqs indexed by node */
++ struct pool_workqueue __rcu *numa_pwq_tbl[]; /* PWR: unbound pwqs indexed by node */
+ };
+
+ static struct kmem_cache *pwq_cache;
+@@ -347,6 +352,12 @@ static void workqueue_sysfs_unregister(struct workqueue_struct *wq);
+ lockdep_is_held(&wq->mutex), \
+ "sched RCU or wq->mutex should be held")
+
++#define assert_rcu_or_wq_mutex_or_pool_mutex(wq) \
++ rcu_lockdep_assert(rcu_read_lock_sched_held() || \
++ lockdep_is_held(&wq->mutex) || \
++ lockdep_is_held(&wq_pool_mutex), \
++ "sched RCU, wq->mutex or wq_pool_mutex should be held")
++
+ #define for_each_cpu_worker_pool(pool, cpu) \
+ for ((pool) = &per_cpu(cpu_worker_pools, cpu)[0]; \
+ (pool) < &per_cpu(cpu_worker_pools, cpu)[NR_STD_WORKER_POOLS]; \
+@@ -551,7 +562,8 @@ static int worker_pool_assign_id(struct worker_pool *pool)
+ * @wq: the target workqueue
+ * @node: the node ID
+ *
+- * This must be called either with pwq_lock held or sched RCU read locked.
++ * This must be called with any of wq_pool_mutex, wq->mutex or sched RCU
++ * read locked.
+ * If the pwq needs to be used beyond the locking in effect, the caller is
+ * responsible for guaranteeing that the pwq stays online.
+ *
+@@ -560,7 +572,17 @@ static int worker_pool_assign_id(struct worker_pool *pool)
+ static struct pool_workqueue *unbound_pwq_by_node(struct workqueue_struct *wq,
+ int node)
+ {
+- assert_rcu_or_wq_mutex(wq);
++ assert_rcu_or_wq_mutex_or_pool_mutex(wq);
++
++ /*
++ * XXX: @node can be NUMA_NO_NODE if CPU goes offline while a
++ * delayed item is pending. The plan is to keep CPU -> NODE
++ * mapping valid and stable across CPU on/offlines. Once that
++ * happens, this workaround can be removed.
++ */
++ if (unlikely(node == NUMA_NO_NODE))
++ return wq->dfl_pwq;
++
+ return rcu_dereference_raw(wq->numa_pwq_tbl[node]);
+ }
+
+@@ -1451,13 +1473,13 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
+ timer_stats_timer_set_start_info(&dwork->timer);
+
+ dwork->wq = wq;
+- /* timer isn't guaranteed to run in this cpu, record earlier */
+- if (cpu == WORK_CPU_UNBOUND)
+- cpu = raw_smp_processor_id();
+ dwork->cpu = cpu;
+ timer->expires = jiffies + delay;
+
+- add_timer_on(timer, cpu);
++ if (unlikely(cpu != WORK_CPU_UNBOUND))
++ add_timer_on(timer, cpu);
++ else
++ add_timer(timer);
+ }
+
+ /**
+@@ -3425,17 +3447,6 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq,
+ return pwq;
+ }
+
+-/* undo alloc_unbound_pwq(), used only in the error path */
+-static void free_unbound_pwq(struct pool_workqueue *pwq)
+-{
+- lockdep_assert_held(&wq_pool_mutex);
+-
+- if (pwq) {
+- put_unbound_pool(pwq->pool);
+- kmem_cache_free(pwq_cache, pwq);
+- }
+-}
+-
+ /**
+ * wq_calc_node_mask - calculate a wq_attrs' cpumask for the specified node
+ * @attrs: the wq_attrs of interest
+@@ -3488,6 +3499,7 @@ static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq,
+ {
+ struct pool_workqueue *old_pwq;
+
++ lockdep_assert_held(&wq_pool_mutex);
+ lockdep_assert_held(&wq->mutex);
+
+ /* link_pwq() can handle duplicate calls */
+@@ -3498,42 +3510,48 @@ static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq,
+ return old_pwq;
+ }
+
+-/**
+- * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue
+- * @wq: the target workqueue
+- * @attrs: the workqueue_attrs to apply, allocated with alloc_workqueue_attrs()
+- *
+- * Apply @attrs to an unbound workqueue @wq. Unless disabled, on NUMA
+- * machines, this function maps a separate pwq to each NUMA node with
+- * possibles CPUs in @attrs->cpumask so that work items are affine to the
+- * NUMA node it was issued on. Older pwqs are released as in-flight work
+- * items finish. Note that a work item which repeatedly requeues itself
+- * back-to-back will stay on its current pwq.
+- *
+- * Performs GFP_KERNEL allocations.
+- *
+- * Return: 0 on success and -errno on failure.
+- */
+-int apply_workqueue_attrs(struct workqueue_struct *wq,
+- const struct workqueue_attrs *attrs)
++/* context to store the prepared attrs & pwqs before applying */
++struct apply_wqattrs_ctx {
++ struct workqueue_struct *wq; /* target workqueue */
++ struct workqueue_attrs *attrs; /* attrs to apply */
++ struct pool_workqueue *dfl_pwq;
++ struct pool_workqueue *pwq_tbl[];
++};
++
++/* free the resources after success or abort */
++static void apply_wqattrs_cleanup(struct apply_wqattrs_ctx *ctx)
+ {
++ if (ctx) {
++ int node;
++
++ for_each_node(node)
++ put_pwq_unlocked(ctx->pwq_tbl[node]);
++ put_pwq_unlocked(ctx->dfl_pwq);
++
++ free_workqueue_attrs(ctx->attrs);
++
++ kfree(ctx);
++ }
++}
++
++/* allocate the attrs and pwqs for later installation */
++static struct apply_wqattrs_ctx *
++apply_wqattrs_prepare(struct workqueue_struct *wq,
++ const struct workqueue_attrs *attrs)
++{
++ struct apply_wqattrs_ctx *ctx;
+ struct workqueue_attrs *new_attrs, *tmp_attrs;
+- struct pool_workqueue **pwq_tbl, *dfl_pwq;
+- int node, ret;
++ int node;
+
+- /* only unbound workqueues can change attributes */
+- if (WARN_ON(!(wq->flags & WQ_UNBOUND)))
+- return -EINVAL;
++ lockdep_assert_held(&wq_pool_mutex);
+
+- /* creating multiple pwqs breaks ordering guarantee */
+- if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs)))
+- return -EINVAL;
++ ctx = kzalloc(sizeof(*ctx) + nr_node_ids * sizeof(ctx->pwq_tbl[0]),
++ GFP_KERNEL);
+
+- pwq_tbl = kzalloc(nr_node_ids * sizeof(pwq_tbl[0]), GFP_KERNEL);
+ new_attrs = alloc_workqueue_attrs(GFP_KERNEL);
+ tmp_attrs = alloc_workqueue_attrs(GFP_KERNEL);
+- if (!pwq_tbl || !new_attrs || !tmp_attrs)
+- goto enomem;
++ if (!ctx || !new_attrs || !tmp_attrs)
++ goto out_free;
+
+ /* make a copy of @attrs and sanitize it */
+ copy_workqueue_attrs(new_attrs, attrs);
+@@ -3547,75 +3565,111 @@ int apply_workqueue_attrs(struct workqueue_struct *wq,
+ copy_workqueue_attrs(tmp_attrs, new_attrs);
+
+ /*
+- * CPUs should stay stable across pwq creations and installations.
+- * Pin CPUs, determine the target cpumask for each node and create
+- * pwqs accordingly.
+- */
+- get_online_cpus();
+-
+- mutex_lock(&wq_pool_mutex);
+-
+- /*
+ * If something goes wrong during CPU up/down, we'll fall back to
+ * the default pwq covering whole @attrs->cpumask. Always create
+ * it even if we don't use it immediately.
+ */
+- dfl_pwq = alloc_unbound_pwq(wq, new_attrs);
+- if (!dfl_pwq)
+- goto enomem_pwq;
++ ctx->dfl_pwq = alloc_unbound_pwq(wq, new_attrs);
++ if (!ctx->dfl_pwq)
++ goto out_free;
+
+ for_each_node(node) {
+ if (wq_calc_node_cpumask(attrs, node, -1, tmp_attrs->cpumask)) {
+- pwq_tbl[node] = alloc_unbound_pwq(wq, tmp_attrs);
+- if (!pwq_tbl[node])
+- goto enomem_pwq;
++ ctx->pwq_tbl[node] = alloc_unbound_pwq(wq, tmp_attrs);
++ if (!ctx->pwq_tbl[node])
++ goto out_free;
+ } else {
+- dfl_pwq->refcnt++;
+- pwq_tbl[node] = dfl_pwq;
++ ctx->dfl_pwq->refcnt++;
++ ctx->pwq_tbl[node] = ctx->dfl_pwq;
+ }
+ }
+
+- mutex_unlock(&wq_pool_mutex);
++ ctx->attrs = new_attrs;
++ ctx->wq = wq;
++ free_workqueue_attrs(tmp_attrs);
++ return ctx;
++
++out_free:
++ free_workqueue_attrs(tmp_attrs);
++ free_workqueue_attrs(new_attrs);
++ apply_wqattrs_cleanup(ctx);
++ return NULL;
++}
++
++/* set attrs and install prepared pwqs, @ctx points to old pwqs on return */
++static void apply_wqattrs_commit(struct apply_wqattrs_ctx *ctx)
++{
++ int node;
+
+ /* all pwqs have been created successfully, let's install'em */
+- mutex_lock(&wq->mutex);
++ mutex_lock(&ctx->wq->mutex);
+
+- copy_workqueue_attrs(wq->unbound_attrs, new_attrs);
++ copy_workqueue_attrs(ctx->wq->unbound_attrs, ctx->attrs);
+
+ /* save the previous pwq and install the new one */
+ for_each_node(node)
+- pwq_tbl[node] = numa_pwq_tbl_install(wq, node, pwq_tbl[node]);
++ ctx->pwq_tbl[node] = numa_pwq_tbl_install(ctx->wq, node,
++ ctx->pwq_tbl[node]);
+
+ /* @dfl_pwq might not have been used, ensure it's linked */
+- link_pwq(dfl_pwq);
+- swap(wq->dfl_pwq, dfl_pwq);
++ link_pwq(ctx->dfl_pwq);
++ swap(ctx->wq->dfl_pwq, ctx->dfl_pwq);
+
+- mutex_unlock(&wq->mutex);
++ mutex_unlock(&ctx->wq->mutex);
++}
+
+- /* put the old pwqs */
+- for_each_node(node)
+- put_pwq_unlocked(pwq_tbl[node]);
+- put_pwq_unlocked(dfl_pwq);
++/**
++ * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue
++ * @wq: the target workqueue
++ * @attrs: the workqueue_attrs to apply, allocated with alloc_workqueue_attrs()
++ *
++ * Apply @attrs to an unbound workqueue @wq. Unless disabled, on NUMA
++ * machines, this function maps a separate pwq to each NUMA node with
++ * possibles CPUs in @attrs->cpumask so that work items are affine to the
++ * NUMA node it was issued on. Older pwqs are released as in-flight work
++ * items finish. Note that a work item which repeatedly requeues itself
++ * back-to-back will stay on its current pwq.
++ *
++ * Performs GFP_KERNEL allocations.
++ *
++ * Return: 0 on success and -errno on failure.
++ */
++int apply_workqueue_attrs(struct workqueue_struct *wq,
++ const struct workqueue_attrs *attrs)
++{
++ struct apply_wqattrs_ctx *ctx;
++ int ret = -ENOMEM;
+
+- put_online_cpus();
+- ret = 0;
+- /* fall through */
+-out_free:
+- free_workqueue_attrs(tmp_attrs);
+- free_workqueue_attrs(new_attrs);
+- kfree(pwq_tbl);
+- return ret;
++ /* only unbound workqueues can change attributes */
++ if (WARN_ON(!(wq->flags & WQ_UNBOUND)))
++ return -EINVAL;
++
++ /* creating multiple pwqs breaks ordering guarantee */
++ if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs)))
++ return -EINVAL;
++
++ /*
++ * CPUs should stay stable across pwq creations and installations.
++ * Pin CPUs, determine the target cpumask for each node and create
++ * pwqs accordingly.
++ */
++ get_online_cpus();
++ mutex_lock(&wq_pool_mutex);
++
++ ctx = apply_wqattrs_prepare(wq, attrs);
++
++ /* the ctx has been prepared successfully, let's commit it */
++ if (ctx) {
++ apply_wqattrs_commit(ctx);
++ ret = 0;
++ }
+
+-enomem_pwq:
+- free_unbound_pwq(dfl_pwq);
+- for_each_node(node)
+- if (pwq_tbl && pwq_tbl[node] != dfl_pwq)
+- free_unbound_pwq(pwq_tbl[node]);
+ mutex_unlock(&wq_pool_mutex);
+ put_online_cpus();
+-enomem:
+- ret = -ENOMEM;
+- goto out_free;
++
++ apply_wqattrs_cleanup(ctx);
++
++ return ret;
+ }
+
+ /**
+diff --git a/lib/klist.c b/lib/klist.c
+index 89b485a2a58d..2a072bfaeace 100644
+--- a/lib/klist.c
++++ b/lib/klist.c
+@@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *k, struct klist_iter *i,
+ struct klist_node *n)
+ {
+ i->i_klist = k;
+- i->i_cur = n;
+- if (n)
+- kref_get(&n->n_ref);
++ i->i_cur = NULL;
++ if (n && kref_get_unless_zero(&n->n_ref))
++ i->i_cur = n;
+ }
+ EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+diff --git a/mm/mmap.c b/mm/mmap.c
+index b639fa2721d8..d30b8f8f02b1 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -2654,12 +2654,29 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
+ if (!vma || !(vma->vm_flags & VM_SHARED))
+ goto out;
+
+- if (start < vma->vm_start || start + size > vma->vm_end)
++ if (start < vma->vm_start)
+ goto out;
+
+- if (pgoff == linear_page_index(vma, start)) {
+- ret = 0;
+- goto out;
++ if (start + size > vma->vm_end) {
++ struct vm_area_struct *next;
++
++ for (next = vma->vm_next; next; next = next->vm_next) {
++ /* hole between vmas ? */
++ if (next->vm_start != next->vm_prev->vm_end)
++ goto out;
++
++ if (next->vm_file != vma->vm_file)
++ goto out;
++
++ if (next->vm_flags != vma->vm_flags)
++ goto out;
++
++ if (start + size <= next->vm_end)
++ break;
++ }
++
++ if (!next)
++ goto out;
+ }
+
+ prot |= vma->vm_flags & VM_READ ? PROT_READ : 0;
+@@ -2669,9 +2686,16 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
+ flags &= MAP_NONBLOCK;
+ flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE;
+ if (vma->vm_flags & VM_LOCKED) {
++ struct vm_area_struct *tmp;
+ flags |= MAP_LOCKED;
++
+ /* drop PG_Mlocked flag for over-mapped range */
+- munlock_vma_pages_range(vma, start, start + size);
++ for (tmp = vma; tmp->vm_start >= start + size;
++ tmp = tmp->vm_next) {
++ munlock_vma_pages_range(tmp,
++ max(tmp->vm_start, start),
++ min(tmp->vm_end, start + size));
++ }
+ }
+
+ file = get_file(vma->vm_file);
+diff --git a/net/bridge/br.c b/net/bridge/br.c
+index 02c24cf63c34..c72e01cf09d0 100644
+--- a/net/bridge/br.c
++++ b/net/bridge/br.c
+@@ -121,6 +121,7 @@ static struct notifier_block br_device_notifier = {
+ .notifier_call = br_device_event
+ };
+
++/* called with RTNL */
+ static int br_netdev_switch_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+ {
+@@ -130,7 +131,6 @@ static int br_netdev_switch_event(struct notifier_block *unused,
+ struct netdev_switch_notifier_fdb_info *fdb_info;
+ int err = NOTIFY_DONE;
+
+- rtnl_lock();
+ p = br_port_get_rtnl(dev);
+ if (!p)
+ goto out;
+@@ -155,7 +155,6 @@ static int br_netdev_switch_event(struct notifier_block *unused,
+ }
+
+ out:
+- rtnl_unlock();
+ return err;
+ }
+
+diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
+index 2c35c02a931e..3556791fdc6e 100644
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -113,7 +113,6 @@ ip:
+ case htons(ETH_P_IPV6): {
+ const struct ipv6hdr *iph;
+ struct ipv6hdr _iph;
+- __be32 flow_label;
+
+ ipv6:
+ iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
+@@ -130,8 +129,9 @@ ipv6:
+ flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr);
+ flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr);
+
+- flow_label = ip6_flowlabel(iph);
+- if (flow_label) {
++ if (skb && ip6_flowlabel(iph)) {
++ __be32 flow_label = ip6_flowlabel(iph);
++
+ /* Awesome, IPv6 packet has a flow label so we can
+ * use that to represent the ports without any
+ * further dissection.
+@@ -233,6 +233,13 @@ ipv6:
+ return false;
+ proto = eth->h_proto;
+ nhoff += sizeof(*eth);
++
++ /* Cap headers that we access via pointers at the
++ * end of the Ethernet header as our maximum alignment
++ * at that point is only 2 bytes.
++ */
++ if (NET_IP_ALIGN)
++ hlen = nhoff;
+ }
+ goto again;
+ }
+diff --git a/net/core/scm.c b/net/core/scm.c
+index 8a1741b14302..dce0acb929f1 100644
+--- a/net/core/scm.c
++++ b/net/core/scm.c
+@@ -87,6 +87,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
+ *fplp = fpl;
+ fpl->count = 0;
+ fpl->max = SCM_MAX_FD;
++ fpl->user = NULL;
+ }
+ fpp = &fpl->fp[fpl->count];
+
+@@ -107,6 +108,10 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
+ *fpp++ = file;
+ fpl->count++;
+ }
++
++ if (!fpl->user)
++ fpl->user = get_uid(current_user());
++
+ return num;
+ }
+
+@@ -119,6 +124,7 @@ void __scm_destroy(struct scm_cookie *scm)
+ scm->fp = NULL;
+ for (i=fpl->count-1; i>=0; i--)
+ fput(fpl->fp[i]);
++ free_uid(fpl->user);
+ kfree(fpl);
+ }
+ }
+@@ -336,6 +342,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
+ for (i = 0; i < fpl->count; i++)
+ get_file(fpl->fp[i]);
+ new_fpl->max = new_fpl->count;
++ new_fpl->user = get_uid(fpl->user);
+ }
+ return new_fpl;
+ }
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 2e5fcda16570..c9793c6c5005 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -79,6 +79,8 @@
+
+ struct kmem_cache *skbuff_head_cache __read_mostly;
+ static struct kmem_cache *skbuff_fclone_cache __read_mostly;
++int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
++EXPORT_SYMBOL(sysctl_max_skb_frags);
+
+ /**
+ * skb_panic - private function for out-of-line support
+diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
+index 95b6139d710c..a6beb7b6ae55 100644
+--- a/net/core/sysctl_net_core.c
++++ b/net/core/sysctl_net_core.c
+@@ -26,6 +26,7 @@ static int zero = 0;
+ static int one = 1;
+ static int min_sndbuf = SOCK_MIN_SNDBUF;
+ static int min_rcvbuf = SOCK_MIN_RCVBUF;
++static int max_skb_frags = MAX_SKB_FRAGS;
+
+ static int net_msg_warn; /* Unused, but still a sysctl */
+
+@@ -392,6 +393,15 @@ static struct ctl_table net_core_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
++ {
++ .procname = "max_skb_frags",
++ .data = &sysctl_max_skb_frags,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = &one,
++ .extra2 = &max_skb_frags,
++ },
+ { }
+ };
+
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index 419d23c53ec7..280d46f947ea 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -1839,7 +1839,7 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
+ if (err < 0)
+ goto errout;
+
+- err = EINVAL;
++ err = -EINVAL;
+ if (!tb[NETCONFA_IFINDEX])
+ goto errout;
+
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index 6ddde89996f4..b6c7bdea4853 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -249,6 +249,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
+ switch (cmsg->cmsg_type) {
+ case IP_RETOPTS:
+ err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
++
++ /* Our caller is responsible for freeing ipc->opt */
+ err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg),
+ err < 40 ? err : 40);
+ if (err)
+diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
+index 05ff44b758df..f6ee0d561aab 100644
+--- a/net/ipv4/ping.c
++++ b/net/ipv4/ping.c
+@@ -745,8 +745,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(sock_net(sk), msg, &ipc, false);
+- if (err)
++ if (unlikely(err)) {
++ kfree(ipc.opt);
+ return err;
++ }
+ if (ipc.opt)
+ free = 1;
+ }
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index 561cd4b8fc6e..c77aac75759d 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -543,8 +543,10 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(sock_net(sk), msg, &ipc, false);
+- if (err)
++ if (unlikely(err)) {
++ kfree(ipc.opt);
+ goto out;
++ }
+ if (ipc.opt)
+ free = 1;
+ }
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index f45f2a12f37b..1d3cdb4d4ebc 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -125,6 +125,7 @@ static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ;
+ static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20;
+ static int ip_rt_min_advmss __read_mostly = 256;
+
++static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT;
+ /*
+ * Interface to generic destination cache.
+ */
+@@ -753,7 +754,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
+ struct fib_nh *nh = &FIB_RES_NH(res);
+
+ update_or_create_fnhe(nh, fl4->daddr, new_gw,
+- 0, 0);
++ 0, jiffies + ip_rt_gc_timeout);
+ }
+ if (kill_route)
+ rt->dst.obsolete = DST_OBSOLETE_KILL;
+@@ -1538,6 +1539,36 @@ static void ip_handle_martian_source(struct net_device *dev,
+ #endif
+ }
+
++static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
++{
++ struct fnhe_hash_bucket *hash;
++ struct fib_nh_exception *fnhe, __rcu **fnhe_p;
++ u32 hval = fnhe_hashfun(daddr);
++
++ spin_lock_bh(&fnhe_lock);
++
++ hash = rcu_dereference_protected(nh->nh_exceptions,
++ lockdep_is_held(&fnhe_lock));
++ hash += hval;
++
++ fnhe_p = &hash->chain;
++ fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock));
++ while (fnhe) {
++ if (fnhe->fnhe_daddr == daddr) {
++ rcu_assign_pointer(*fnhe_p, rcu_dereference_protected(
++ fnhe->fnhe_next, lockdep_is_held(&fnhe_lock)));
++ fnhe_flush_routes(fnhe);
++ kfree_rcu(fnhe, rcu);
++ break;
++ }
++ fnhe_p = &fnhe->fnhe_next;
++ fnhe = rcu_dereference_protected(fnhe->fnhe_next,
++ lockdep_is_held(&fnhe_lock));
++ }
++
++ spin_unlock_bh(&fnhe_lock);
++}
++
+ /* called in rcu_read_lock() section */
+ static int __mkroute_input(struct sk_buff *skb,
+ const struct fib_result *res,
+@@ -1592,11 +1623,20 @@ static int __mkroute_input(struct sk_buff *skb,
+
+ fnhe = find_exception(&FIB_RES_NH(*res), daddr);
+ if (do_cache) {
+- if (fnhe)
++ if (fnhe) {
+ rth = rcu_dereference(fnhe->fnhe_rth_input);
+- else
+- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
++ if (rth && rth->dst.expires &&
++ time_after(jiffies, rth->dst.expires)) {
++ ip_del_fnhe(&FIB_RES_NH(*res), daddr);
++ fnhe = NULL;
++ } else {
++ goto rt_cache;
++ }
++ }
++
++ rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+
++rt_cache:
+ if (rt_cache_valid(rth)) {
+ skb_dst_set_noref(skb, &rth->dst);
+ goto out;
+@@ -1945,19 +1985,29 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
+ struct fib_nh *nh = &FIB_RES_NH(*res);
+
+ fnhe = find_exception(nh, fl4->daddr);
+- if (fnhe)
++ if (fnhe) {
+ prth = &fnhe->fnhe_rth_output;
+- else {
+- if (unlikely(fl4->flowi4_flags &
+- FLOWI_FLAG_KNOWN_NH &&
+- !(nh->nh_gw &&
+- nh->nh_scope == RT_SCOPE_LINK))) {
+- do_cache = false;
+- goto add;
++ rth = rcu_dereference(*prth);
++ if (rth && rth->dst.expires &&
++ time_after(jiffies, rth->dst.expires)) {
++ ip_del_fnhe(nh, fl4->daddr);
++ fnhe = NULL;
++ } else {
++ goto rt_cache;
+ }
+- prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ }
++
++ if (unlikely(fl4->flowi4_flags &
++ FLOWI_FLAG_KNOWN_NH &&
++ !(nh->nh_gw &&
++ nh->nh_scope == RT_SCOPE_LINK))) {
++ do_cache = false;
++ goto add;
++ }
++ prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ rth = rcu_dereference(*prth);
++
++rt_cache:
+ if (rt_cache_valid(rth)) {
+ dst_hold(&rth->dst);
+ return rth;
+@@ -2504,7 +2554,6 @@ void ip_rt_multicast_event(struct in_device *in_dev)
+ }
+
+ #ifdef CONFIG_SYSCTL
+-static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT;
+ static int ip_rt_gc_interval __read_mostly = 60 * HZ;
+ static int ip_rt_gc_min_interval __read_mostly = HZ / 2;
+ static int ip_rt_gc_elasticity __read_mostly = 8;
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index bb2ce74f6004..19d385a0f02d 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -279,6 +279,7 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/ioctls.h>
++#include <asm/unaligned.h>
+ #include <net/busy_poll.h>
+
+ int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
+@@ -921,7 +922,7 @@ new_segment:
+
+ i = skb_shinfo(skb)->nr_frags;
+ can_coalesce = skb_can_coalesce(skb, i, page, offset);
+- if (!can_coalesce && i >= MAX_SKB_FRAGS) {
++ if (!can_coalesce && i >= sysctl_max_skb_frags) {
+ tcp_mark_push(tp, skb);
+ goto new_segment;
+ }
+@@ -1187,7 +1188,7 @@ new_segment:
+
+ if (!skb_can_coalesce(skb, i, pfrag->page,
+ pfrag->offset)) {
+- if (i == MAX_SKB_FRAGS || !sg) {
++ if (i == sysctl_max_skb_frags || !sg) {
+ tcp_mark_push(tp, skb);
+ goto new_segment;
+ }
+@@ -2603,6 +2604,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ u32 now = tcp_time_stamp;
+ unsigned int start;
++ u64 rate64;
+ u32 rate;
+
+ memset(info, 0, sizeof(*info));
+@@ -2665,15 +2667,17 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
+ info->tcpi_total_retrans = tp->total_retrans;
+
+ rate = READ_ONCE(sk->sk_pacing_rate);
+- info->tcpi_pacing_rate = rate != ~0U ? rate : ~0ULL;
++ rate64 = rate != ~0U ? rate : ~0ULL;
++ put_unaligned(rate64, &info->tcpi_pacing_rate);
+
+ rate = READ_ONCE(sk->sk_max_pacing_rate);
+- info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL;
++ rate64 = rate != ~0U ? rate : ~0ULL;
++ put_unaligned(rate64, &info->tcpi_max_pacing_rate);
+
+ do {
+ start = u64_stats_fetch_begin_irq(&tp->syncp);
+- info->tcpi_bytes_acked = tp->bytes_acked;
+- info->tcpi_bytes_received = tp->bytes_received;
++ put_unaligned(tp->bytes_acked, &info->tcpi_bytes_acked);
++ put_unaligned(tp->bytes_received, &info->tcpi_bytes_received);
+ } while (u64_stats_fetch_retry_irq(&tp->syncp, start));
+ }
+ EXPORT_SYMBOL_GPL(tcp_get_info);
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index cd18c3d3251e..13b92d595138 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -705,7 +705,8 @@ release_sk1:
+ outside socket context is ugly, certainly. What can I do?
+ */
+
+-static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
++static void tcp_v4_send_ack(struct net *net,
++ struct sk_buff *skb, u32 seq, u32 ack,
+ u32 win, u32 tsval, u32 tsecr, int oif,
+ struct tcp_md5sig_key *key,
+ int reply_flags, u8 tos)
+@@ -720,7 +721,6 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+ ];
+ } rep;
+ struct ip_reply_arg arg;
+- struct net *net = dev_net(skb_dst(skb)->dev);
+
+ memset(&rep.th, 0, sizeof(struct tcphdr));
+ memset(&arg, 0, sizeof(arg));
+@@ -782,7 +782,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
+ struct inet_timewait_sock *tw = inet_twsk(sk);
+ struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
+
+- tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
++ tcp_v4_send_ack(sock_net(sk), skb,
++ tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+ tcp_time_stamp + tcptw->tw_ts_offset,
+ tcptw->tw_ts_recent,
+@@ -801,8 +802,10 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
+ /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
+ * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
+ */
+- tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
+- tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
++ u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
++ tcp_sk(sk)->snd_nxt;
++
++ tcp_v4_send_ack(sock_net(sk), skb, seq,
+ tcp_rsk(req)->rcv_nxt, req->rcv_wnd,
+ tcp_time_stamp,
+ req->ts_recent,
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 1b8c5ba7d5f7..a390174b96de 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -963,8 +963,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(sock_net(sk), msg, &ipc,
+ sk->sk_family == AF_INET6);
+- if (err)
++ if (unlikely(err)) {
++ kfree(ipc.opt);
+ return err;
++ }
+ if (ipc.opt)
+ free = 1;
+ connected = 0;
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index f4795b0d6e6e..f555f4fc1d62 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -195,6 +195,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
+ .max_addresses = IPV6_MAX_ADDRESSES,
+ .accept_ra_defrtr = 1,
+ .accept_ra_from_local = 0,
++ .accept_ra_min_hop_limit= 1,
+ .accept_ra_pinfo = 1,
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+ .accept_ra_rtr_pref = 1,
+@@ -236,6 +237,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
+ .max_addresses = IPV6_MAX_ADDRESSES,
+ .accept_ra_defrtr = 1,
+ .accept_ra_from_local = 0,
++ .accept_ra_min_hop_limit= 1,
+ .accept_ra_pinfo = 1,
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+ .accept_ra_rtr_pref = 1,
+@@ -567,7 +569,7 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
+ if (err < 0)
+ goto errout;
+
+- err = EINVAL;
++ err = -EINVAL;
+ if (!tb[NETCONFA_IFINDEX])
+ goto errout;
+
+@@ -3421,6 +3423,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
+ {
+ struct inet6_dev *idev = ifp->idev;
+ struct net_device *dev = idev->dev;
++ bool notify = false;
+
+ addrconf_join_solict(dev, &ifp->addr);
+
+@@ -3466,7 +3469,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
+ /* Because optimistic nodes can use this address,
+ * notify listeners. If DAD fails, RTM_DELADDR is sent.
+ */
+- ipv6_ifa_notify(RTM_NEWADDR, ifp);
++ notify = true;
+ }
+ }
+
+@@ -3474,6 +3477,8 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
+ out:
+ spin_unlock(&ifp->lock);
+ read_unlock_bh(&idev->lock);
++ if (notify)
++ ipv6_ifa_notify(RTM_NEWADDR, ifp);
+ }
+
+ static void addrconf_dad_start(struct inet6_ifaddr *ifp)
+@@ -4565,6 +4570,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+ array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
+ array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
+ array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
++ array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit;
+ array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+ array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
+@@ -5458,6 +5464,13 @@ static struct addrconf_sysctl_table
+ .proc_handler = proc_dointvec,
+ },
+ {
++ .procname = "accept_ra_min_hop_limit",
++ .data = &ipv6_devconf.accept_ra_min_hop_limit,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec,
++ },
++ {
+ .procname = "accept_ra_pinfo",
+ .data = &ipv6_devconf.accept_ra_pinfo,
+ .maxlen = sizeof(int),
+diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
+index 13ca4cf5616f..8e6cb3f14326 100644
+--- a/net/ipv6/datagram.c
++++ b/net/ipv6/datagram.c
+@@ -162,6 +162,9 @@ ipv4_connected:
+ fl6.fl6_dport = inet->inet_dport;
+ fl6.fl6_sport = inet->inet_sport;
+
++ if (!fl6.flowi6_oif)
++ fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
++
+ if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
+ fl6.flowi6_oif = np->mcast_oif;
+
+diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
+index d491125011c4..db939e4ac68a 100644
+--- a/net/ipv6/ip6_flowlabel.c
++++ b/net/ipv6/ip6_flowlabel.c
+@@ -540,12 +540,13 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ }
+ spin_lock_bh(&ip6_sk_fl_lock);
+ for (sflp = &np->ipv6_fl_list;
+- (sfl = rcu_dereference(*sflp)) != NULL;
++ (sfl = rcu_dereference_protected(*sflp,
++ lockdep_is_held(&ip6_sk_fl_lock))) != NULL;
+ sflp = &sfl->next) {
+ if (sfl->fl->label == freq.flr_label) {
+ if (freq.flr_label == (np->flow_label&IPV6_FLOWLABEL_MASK))
+ np->flow_label &= ~IPV6_FLOWLABEL_MASK;
+- *sflp = rcu_dereference(sfl->next);
++ *sflp = sfl->next;
+ spin_unlock_bh(&ip6_sk_fl_lock);
+ fl_release(sfl->fl);
+ kfree_rcu(sfl, rcu);
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index f50228b0abe5..36b9ac48b8fb 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -885,6 +885,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ struct rt6_info *rt;
+ #endif
+ int err;
++ int flags = 0;
+
+ /* The correct way to handle this would be to do
+ * ip6_route_get_saddr, and then ip6_route_output; however,
+@@ -916,10 +917,13 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ dst_release(*dst);
+ *dst = NULL;
+ }
++
++ if (fl6->flowi6_oif)
++ flags |= RT6_LOOKUP_F_IFACE;
+ }
+
+ if (!*dst)
+- *dst = ip6_route_output(net, sk, fl6);
++ *dst = ip6_route_output_flags(net, sk, fl6, flags);
+
+ err = (*dst)->error;
+ if (err)
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 96f153c0846b..abb0bdda759a 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -1225,18 +1225,16 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+
+ if (rt)
+ rt6_set_expires(rt, jiffies + (HZ * lifetime));
+- if (ra_msg->icmph.icmp6_hop_limit) {
+- /* Only set hop_limit on the interface if it is higher than
+- * the current hop_limit.
+- */
+- if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
++ if (in6_dev->cnf.accept_ra_min_hop_limit < 256 &&
++ ra_msg->icmph.icmp6_hop_limit) {
++ if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) {
+ in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
++ if (rt)
++ dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
++ ra_msg->icmph.icmp6_hop_limit);
+ } else {
+- ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
++ ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than minimum\n");
+ }
+- if (rt)
+- dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
+- ra_msg->icmph.icmp6_hop_limit);
+ }
+
+ skip_defrtr:
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index f371fefa7fdc..fe70bd6a7516 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -1030,11 +1030,9 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table
+ return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
+ }
+
+-struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
+- struct flowi6 *fl6)
++struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
++ struct flowi6 *fl6, int flags)
+ {
+- int flags = 0;
+-
+ fl6->flowi6_iif = LOOPBACK_IFINDEX;
+
+ if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
+@@ -1047,7 +1045,7 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
+
+ return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
+ }
+-EXPORT_SYMBOL(ip6_route_output);
++EXPORT_SYMBOL_GPL(ip6_route_output_flags);
+
+ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
+ {
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 6daa52a18d40..123f6f9f854c 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -709,6 +709,9 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
+ if (!addr || addr->sa_family != AF_IUCV)
+ return -EINVAL;
+
++ if (addr_len < sizeof(struct sockaddr_iucv))
++ return -EINVAL;
++
+ lock_sock(sk);
+ if (sk->sk_state != IUCV_OPEN) {
+ err = -EBADFD;
+diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
+index 9e13c2ff8789..fe92a08b3cd5 100644
+--- a/net/l2tp/l2tp_netlink.c
++++ b/net/l2tp/l2tp_netlink.c
+@@ -124,8 +124,13 @@ static int l2tp_tunnel_notify(struct genl_family *family,
+ ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq,
+ NLM_F_ACK, tunnel, cmd);
+
+- if (ret >= 0)
+- return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ if (ret >= 0) {
++ ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ /* We don't care if no one is listening */
++ if (ret == -ESRCH)
++ ret = 0;
++ return ret;
++ }
+
+ nlmsg_free(msg);
+
+@@ -147,8 +152,13 @@ static int l2tp_session_notify(struct genl_family *family,
+ ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
+ NLM_F_ACK, session, cmd);
+
+- if (ret >= 0)
+- return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ if (ret >= 0) {
++ ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ /* We don't care if no one is listening */
++ if (ret == -ESRCH)
++ ret = 0;
++ return ret;
++ }
+
+ nlmsg_free(msg);
+
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index e13c3c3ea4ac..9d134ab3351f 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -60,6 +60,8 @@
+ #include <net/inet_common.h>
+ #include <net/inet_ecn.h>
+
++#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
++
+ /* Global data structures. */
+ struct sctp_globals sctp_globals __read_mostly;
+
+@@ -1332,6 +1334,8 @@ static __init int sctp_init(void)
+ unsigned long limit;
+ int max_share;
+ int order;
++ int num_entries;
++ int max_entry_order;
+
+ sock_skb_cb_check_size(sizeof(struct sctp_ulpevent));
+
+@@ -1384,14 +1388,24 @@ static __init int sctp_init(void)
+
+ /* Size and allocate the association hash table.
+ * The methodology is similar to that of the tcp hash tables.
++ * Though not identical. Start by getting a goal size
+ */
+ if (totalram_pages >= (128 * 1024))
+ goal = totalram_pages >> (22 - PAGE_SHIFT);
+ else
+ goal = totalram_pages >> (24 - PAGE_SHIFT);
+
+- for (order = 0; (1UL << order) < goal; order++)
+- ;
++ /* Then compute the page order for said goal */
++ order = get_order(goal);
++
++ /* Now compute the required page order for the maximum sized table we
++ * want to create
++ */
++ max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES *
++ sizeof(struct sctp_bind_hashbucket));
++
++ /* Limit the page order by that maximum hash table size */
++ order = min(order, max_entry_order);
+
+ do {
+ sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE /
+@@ -1425,27 +1439,42 @@ static __init int sctp_init(void)
+ INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
+ }
+
+- /* Allocate and initialize the SCTP port hash table. */
++ /* Allocate and initialize the SCTP port hash table.
++ * Note that order is initalized to start at the max sized
++ * table we want to support. If we can't get that many pages
++ * reduce the order and try again
++ */
+ do {
+- sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
+- sizeof(struct sctp_bind_hashbucket);
+- if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
+- continue;
+ sctp_port_hashtable = (struct sctp_bind_hashbucket *)
+ __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order);
+ } while (!sctp_port_hashtable && --order > 0);
++
+ if (!sctp_port_hashtable) {
+ pr_err("Failed bind hash alloc\n");
+ status = -ENOMEM;
+ goto err_bhash_alloc;
+ }
++
++ /* Now compute the number of entries that will fit in the
++ * port hash space we allocated
++ */
++ num_entries = (1UL << order) * PAGE_SIZE /
++ sizeof(struct sctp_bind_hashbucket);
++
++ /* And finish by rounding it down to the nearest power of two
++ * this wastes some memory of course, but its needed because
++ * the hash function operates based on the assumption that
++ * that the number of entries is a power of two
++ */
++ sctp_port_hashsize = rounddown_pow_of_two(num_entries);
++
+ for (i = 0; i < sctp_port_hashsize; i++) {
+ spin_lock_init(&sctp_port_hashtable[i].lock);
+ INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
+ }
+
+- pr_info("Hash tables configured (established %d bind %d)\n",
+- sctp_assoc_hashsize, sctp_port_hashsize);
++ pr_info("Hash tables configured (established %d bind %d/%d)\n",
++ sctp_assoc_hashsize, sctp_port_hashsize, num_entries);
+
+ sctp_sysctl_register();
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 76e6ec62cf92..3c5833058b03 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -5555,6 +5555,7 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
+ struct sctp_hmac_algo_param *hmacs;
+ __u16 data_len = 0;
+ u32 num_idents;
++ int i;
+
+ if (!ep->auth_enable)
+ return -EACCES;
+@@ -5572,8 +5573,12 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
+ return -EFAULT;
+ if (put_user(num_idents, &p->shmac_num_idents))
+ return -EFAULT;
+- if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
+- return -EFAULT;
++ for (i = 0; i < num_idents; i++) {
++ __u16 hmacid = ntohs(hmacs->hmac_ids[i]);
++
++ if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
++ return -EFAULT;
++ }
+ return 0;
+ }
+
+@@ -6653,6 +6658,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
+
+ if (cmsgs->srinfo->sinfo_flags &
+ ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
++ SCTP_SACK_IMMEDIATELY |
+ SCTP_ABORT | SCTP_EOF))
+ return -EINVAL;
+ break;
+@@ -6676,6 +6682,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
+
+ if (cmsgs->sinfo->snd_flags &
+ ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
++ SCTP_SACK_IMMEDIATELY |
+ SCTP_ABORT | SCTP_EOF))
+ return -EINVAL;
+ break;
+diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
+index 055453d48668..a8dbe8001e46 100644
+--- a/net/switchdev/switchdev.c
++++ b/net/switchdev/switchdev.c
+@@ -15,6 +15,7 @@
+ #include <linux/mutex.h>
+ #include <linux/notifier.h>
+ #include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
+ #include <net/ip_fib.h>
+ #include <net/switchdev.h>
+
+@@ -64,7 +65,6 @@ int netdev_switch_port_stp_update(struct net_device *dev, u8 state)
+ }
+ EXPORT_SYMBOL_GPL(netdev_switch_port_stp_update);
+
+-static DEFINE_MUTEX(netdev_switch_mutex);
+ static RAW_NOTIFIER_HEAD(netdev_switch_notif_chain);
+
+ /**
+@@ -79,9 +79,9 @@ int register_netdev_switch_notifier(struct notifier_block *nb)
+ {
+ int err;
+
+- mutex_lock(&netdev_switch_mutex);
++ rtnl_lock();
+ err = raw_notifier_chain_register(&netdev_switch_notif_chain, nb);
+- mutex_unlock(&netdev_switch_mutex);
++ rtnl_unlock();
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(register_netdev_switch_notifier);
+@@ -97,9 +97,9 @@ int unregister_netdev_switch_notifier(struct notifier_block *nb)
+ {
+ int err;
+
+- mutex_lock(&netdev_switch_mutex);
++ rtnl_lock();
+ err = raw_notifier_chain_unregister(&netdev_switch_notif_chain, nb);
+- mutex_unlock(&netdev_switch_mutex);
++ rtnl_unlock();
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(unregister_netdev_switch_notifier);
+@@ -113,16 +113,17 @@ EXPORT_SYMBOL_GPL(unregister_netdev_switch_notifier);
+ * Call all network notifier blocks. This should be called by driver
+ * when it needs to propagate hardware event.
+ * Return values are same as for atomic_notifier_call_chain().
++ * rtnl_lock must be held.
+ */
+ int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
+ struct netdev_switch_notifier_info *info)
+ {
+ int err;
+
++ ASSERT_RTNL();
++
+ info->dev = dev;
+- mutex_lock(&netdev_switch_mutex);
+ err = raw_notifier_call_chain(&netdev_switch_notif_chain, val, info);
+- mutex_unlock(&netdev_switch_mutex);
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(call_netdev_switch_notifiers);
+diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
+index 1c147c869c2e..948f316019d7 100644
+--- a/net/tipc/subscr.c
++++ b/net/tipc/subscr.c
+@@ -302,11 +302,10 @@ static void subscr_conn_msg_event(struct net *net, int conid,
+ struct tipc_net *tn = net_generic(net, tipc_net_id);
+
+ spin_lock_bh(&subscriber->lock);
+- subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, &sub);
+- if (sub)
+- tipc_nametbl_subscribe(sub);
+- else
++ if (subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, &sub))
+ tipc_conn_terminate(tn->topsrv, subscriber->conid);
++ else
++ tipc_nametbl_subscribe(sub);
+ spin_unlock_bh(&subscriber->lock);
+ }
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index cb3a01a9ed38..535a642a1688 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1464,7 +1464,7 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
+ UNIXCB(skb).fp = NULL;
+
+ for (i = scm->fp->count-1; i >= 0; i--)
+- unix_notinflight(scm->fp->fp[i]);
++ unix_notinflight(scm->fp->user, scm->fp->fp[i]);
+ }
+
+ static void unix_destruct_scm(struct sk_buff *skb)
+@@ -1529,7 +1529,7 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
+ return -ENOMEM;
+
+ for (i = scm->fp->count - 1; i >= 0; i--)
+- unix_inflight(scm->fp->fp[i]);
++ unix_inflight(scm->fp->user, scm->fp->fp[i]);
+ return max_level;
+ }
+
+@@ -1714,7 +1714,12 @@ restart_locked:
+ goto out_unlock;
+ }
+
+- if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
++ /* other == sk && unix_peer(other) != sk if
++ * - unix_peer(sk) == NULL, destination address bound to sk
++ * - unix_peer(sk) == sk by time of get but disconnected before lock
++ */
++ if (other != sk &&
++ unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
+ if (timeo) {
+ timeo = unix_wait_for_peer(other, timeo);
+
+@@ -2131,6 +2136,7 @@ again:
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
++ scm_destroy(&scm);
+ goto out;
+ }
+
+diff --git a/net/unix/diag.c b/net/unix/diag.c
+index c512f64d5287..4d9679701a6d 100644
+--- a/net/unix/diag.c
++++ b/net/unix/diag.c
+@@ -220,7 +220,7 @@ done:
+ return skb->len;
+ }
+
+-static struct sock *unix_lookup_by_ino(int ino)
++static struct sock *unix_lookup_by_ino(unsigned int ino)
+ {
+ int i;
+ struct sock *sk;
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 8fcdc2283af5..6a0d48525fcf 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -116,7 +116,7 @@ struct sock *unix_get_socket(struct file *filp)
+ * descriptor if it is for an AF_UNIX socket.
+ */
+
+-void unix_inflight(struct file *fp)
++void unix_inflight(struct user_struct *user, struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
+
+@@ -133,11 +133,11 @@ void unix_inflight(struct file *fp)
+ }
+ unix_tot_inflight++;
+ }
+- fp->f_cred->user->unix_inflight++;
++ user->unix_inflight++;
+ spin_unlock(&unix_gc_lock);
+ }
+
+-void unix_notinflight(struct file *fp)
++void unix_notinflight(struct user_struct *user, struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
+
+@@ -152,7 +152,7 @@ void unix_notinflight(struct file *fp)
+ list_del_init(&u->link);
+ unix_tot_inflight--;
+ }
+- fp->f_cred->user->unix_inflight--;
++ user->unix_inflight--;
+ spin_unlock(&unix_gc_lock);
+ }
+
+diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
+index 582091498819..d6bc2b3af9ef 100644
+--- a/security/integrity/evm/evm_main.c
++++ b/security/integrity/evm/evm_main.c
+@@ -23,6 +23,7 @@
+ #include <linux/integrity.h>
+ #include <linux/evm.h>
+ #include <crypto/hash.h>
++#include <crypto/algapi.h>
+ #include "evm.h"
+
+ int evm_initialized;
+@@ -148,7 +149,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
+ xattr_value_len, calc.digest);
+ if (rc)
+ break;
+- rc = memcmp(xattr_data->digest, calc.digest,
++ rc = crypto_memneq(xattr_data->digest, calc.digest,
+ sizeof(calc.digest));
+ if (rc)
+ rc = -EINVAL;
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 75888dd38a7f..aa999e747c94 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -74,6 +74,18 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
+ static DEFINE_RWLOCK(snd_pcm_link_rwlock);
+ static DECLARE_RWSEM(snd_pcm_link_rwsem);
+
++/* Writer in rwsem may block readers even during its waiting in queue,
++ * and this may lead to a deadlock when the code path takes read sem
++ * twice (e.g. one in snd_pcm_action_nonatomic() and another in
++ * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
++ * spin until it gets the lock.
++ */
++static inline void down_write_nonblock(struct rw_semaphore *lock)
++{
++ while (!down_write_trylock(lock))
++ cond_resched();
++}
++
+ /**
+ * snd_pcm_stream_lock - Lock the PCM stream
+ * @substream: PCM substream
+@@ -1816,7 +1828,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
+ res = -ENOMEM;
+ goto _nolock;
+ }
+- down_write(&snd_pcm_link_rwsem);
++ down_write_nonblock(&snd_pcm_link_rwsem);
+ write_lock_irq(&snd_pcm_link_rwlock);
+ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
+ substream->runtime->status->state != substream1->runtime->status->state ||
+@@ -1863,7 +1875,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
+ struct snd_pcm_substream *s;
+ int res = 0;
+
+- down_write(&snd_pcm_link_rwsem);
++ down_write_nonblock(&snd_pcm_link_rwsem);
+ write_lock_irq(&snd_pcm_link_rwlock);
+ if (!snd_pcm_stream_linked(substream)) {
+ res = -EALREADY;
+diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
+index 801076687bb1..c850345c43b5 100644
+--- a/sound/core/seq/seq_memory.c
++++ b/sound/core/seq/seq_memory.c
+@@ -383,15 +383,20 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
+
+ if (snd_BUG_ON(!pool))
+ return -EINVAL;
+- if (pool->ptr) /* should be atomic? */
+- return 0;
+
+- pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
+- if (!pool->ptr)
++ cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
++ if (!cellptr)
+ return -ENOMEM;
+
+ /* add new cells to the free cell list */
+ spin_lock_irqsave(&pool->lock, flags);
++ if (pool->ptr) {
++ spin_unlock_irqrestore(&pool->lock, flags);
++ vfree(cellptr);
++ return 0;
++ }
++
++ pool->ptr = cellptr;
+ pool->free = NULL;
+
+ for (cell = 0; cell < pool->size; cell++) {
+diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
+index 921fb2bd8fad..fe686ee41c6d 100644
+--- a/sound/core/seq/seq_ports.c
++++ b/sound/core/seq/seq_ports.c
+@@ -535,19 +535,22 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+ bool is_src, bool ack)
+ {
+ struct snd_seq_port_subs_info *grp;
++ struct list_head *list;
++ bool empty;
+
+ grp = is_src ? &port->c_src : &port->c_dest;
++ list = is_src ? &subs->src_list : &subs->dest_list;
+ down_write(&grp->list_mutex);
+ write_lock_irq(&grp->list_lock);
+- if (is_src)
+- list_del(&subs->src_list);
+- else
+- list_del(&subs->dest_list);
++ empty = list_empty(list);
++ if (!empty)
++ list_del_init(list);
+ grp->exclusive = 0;
+ write_unlock_irq(&grp->list_lock);
+ up_write(&grp->list_mutex);
+
+- unsubscribe_port(client, port, grp, &subs->info, ack);
++ if (!empty)
++ unsubscribe_port(client, port, grp, &subs->info, ack);
+ }
+
+ /* connect two ports */
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index 00e8c5f4de17..bf48e71f73cd 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -422,7 +422,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
+ spin_lock_irqsave(&timer->lock, flags);
+ list_for_each_entry(ts, &ti->slave_active_head, active_list)
+ if (ts->ccallback)
+- ts->ccallback(ti, event + 100, &tstamp, resolution);
++ ts->ccallback(ts, event + 100, &tstamp, resolution);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ }
+
+@@ -518,9 +518,13 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
+ spin_unlock_irqrestore(&slave_active_lock, flags);
+ return -EBUSY;
+ }
++ if (timeri->timer)
++ spin_lock(&timeri->timer->lock);
+ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
++ if (timeri->timer)
++ spin_unlock(&timeri->timer->lock);
+ spin_unlock_irqrestore(&slave_active_lock, flags);
+ goto __end;
+ }
+@@ -1920,6 +1924,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
+ {
+ struct snd_timer_user *tu;
+ long result = 0, unit;
++ int qhead;
+ int err = 0;
+
+ tu = file->private_data;
+@@ -1931,7 +1936,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
+
+ if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
+ err = -EAGAIN;
+- break;
++ goto _error;
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -1946,42 +1951,37 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
+
+ if (tu->disconnected) {
+ err = -ENODEV;
+- break;
++ goto _error;
+ }
+ if (signal_pending(current)) {
+ err = -ERESTARTSYS;
+- break;
++ goto _error;
+ }
+ }
+
++ qhead = tu->qhead++;
++ tu->qhead %= tu->queue_size;
+ spin_unlock_irq(&tu->qlock);
+- if (err < 0)
+- goto _error;
+
+ if (tu->tread) {
+- if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
+- sizeof(struct snd_timer_tread))) {
++ if (copy_to_user(buffer, &tu->tqueue[qhead],
++ sizeof(struct snd_timer_tread)))
+ err = -EFAULT;
+- goto _error;
+- }
+ } else {
+- if (copy_to_user(buffer, &tu->queue[tu->qhead++],
+- sizeof(struct snd_timer_read))) {
++ if (copy_to_user(buffer, &tu->queue[qhead],
++ sizeof(struct snd_timer_read)))
+ err = -EFAULT;
+- goto _error;
+- }
+ }
+
+- tu->qhead %= tu->queue_size;
+-
+- result += unit;
+- buffer += unit;
+-
+ spin_lock_irq(&tu->qlock);
+ tu->qused--;
++ if (err < 0)
++ goto _error;
++ result += unit;
++ buffer += unit;
+ }
+- spin_unlock_irq(&tu->qlock);
+ _error:
++ spin_unlock_irq(&tu->qlock);
+ return result > 0 ? result : err;
+ }
+
+diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
+index 96592d5ba7bf..c5d5217a4180 100644
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
+ module_param(fake_buffer, bool, 0444);
+ MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
+ #ifdef CONFIG_HIGH_RES_TIMERS
+-module_param(hrtimer, bool, 0444);
++module_param(hrtimer, bool, 0644);
+ MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
+ #endif
+
+@@ -109,6 +109,9 @@ struct dummy_timer_ops {
+ snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
+ };
+
++#define get_dummy_ops(substream) \
++ (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
++
+ struct dummy_model {
+ const char *name;
+ int (*playback_constraints)(struct snd_pcm_runtime *runtime);
+@@ -137,7 +140,6 @@ struct snd_dummy {
+ int iobox;
+ struct snd_kcontrol *cd_volume_ctl;
+ struct snd_kcontrol *cd_switch_ctl;
+- const struct dummy_timer_ops *timer_ops;
+ };
+
+ /*
+@@ -231,6 +233,8 @@ struct dummy_model *dummy_models[] = {
+ */
+
+ struct dummy_systimer_pcm {
++ /* ops must be the first item */
++ const struct dummy_timer_ops *timer_ops;
+ spinlock_t lock;
+ struct timer_list timer;
+ unsigned long base_time;
+@@ -366,6 +370,8 @@ static struct dummy_timer_ops dummy_systimer_ops = {
+ */
+
+ struct dummy_hrtimer_pcm {
++ /* ops must be the first item */
++ const struct dummy_timer_ops *timer_ops;
+ ktime_t base_time;
+ ktime_t period_time;
+ atomic_t running;
+@@ -492,31 +498,25 @@ static struct dummy_timer_ops dummy_hrtimer_ops = {
+
+ static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+- return dummy->timer_ops->start(substream);
++ return get_dummy_ops(substream)->start(substream);
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+- return dummy->timer_ops->stop(substream);
++ return get_dummy_ops(substream)->stop(substream);
+ }
+ return -EINVAL;
+ }
+
+ static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+- return dummy->timer_ops->prepare(substream);
++ return get_dummy_ops(substream)->prepare(substream);
+ }
+
+ static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+- return dummy->timer_ops->pointer(substream);
++ return get_dummy_ops(substream)->pointer(substream);
+ }
+
+ static struct snd_pcm_hardware dummy_pcm_hardware = {
+@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
+ struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+ struct dummy_model *model = dummy->model;
+ struct snd_pcm_runtime *runtime = substream->runtime;
++ const struct dummy_timer_ops *ops;
+ int err;
+
+- dummy->timer_ops = &dummy_systimer_ops;
++ ops = &dummy_systimer_ops;
+ #ifdef CONFIG_HIGH_RES_TIMERS
+ if (hrtimer)
+- dummy->timer_ops = &dummy_hrtimer_ops;
++ ops = &dummy_hrtimer_ops;
+ #endif
+
+- err = dummy->timer_ops->create(substream);
++ err = ops->create(substream);
+ if (err < 0)
+ return err;
++ get_dummy_ops(substream) = ops;
+
+ runtime->hw = dummy->pcm_hw;
+ if (substream->pcm->device & 1) {
+@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
+ err = model->capture_constraints(substream->runtime);
+ }
+ if (err < 0) {
+- dummy->timer_ops->free(substream);
++ get_dummy_ops(substream)->free(substream);
+ return err;
+ }
+ return 0;
+@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
+
+ static int dummy_pcm_close(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+- dummy->timer_ops->free(substream);
++ get_dummy_ops(substream)->free(substream);
+ return 0;
+ }
+
+diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
+index 5bc7f2e2715c..194627c6c42b 100644
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -3998,9 +3998,9 @@ static void pin_power_callback(struct hda_codec *codec,
+ struct hda_jack_callback *jack,
+ bool on)
+ {
+- if (jack && jack->tbl->nid)
++ if (jack && jack->nid)
+ sync_power_state_change(codec,
+- set_pin_power_jack(codec, jack->tbl->nid, on));
++ set_pin_power_jack(codec, jack->nid, on));
+ }
+
+ /* callback only doing power up -- called at first */
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index 09920ba55ba1..69093ce34231 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -1976,10 +1976,10 @@ static void azx_remove(struct pci_dev *pci)
+ struct hda_intel *hda;
+
+ if (card) {
+- /* flush the pending probing work */
++ /* cancel the pending probing work */
+ chip = card->private_data;
+ hda = container_of(chip, struct hda_intel, chip);
+- flush_work(&hda->probe_work);
++ cancel_work_sync(&hda->probe_work);
+
+ snd_card_free(card);
+ }
+diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
+index d7cfe7b8c32b..52cc36758dd4 100644
+--- a/sound/pci/hda/hda_jack.c
++++ b/sound/pci/hda/hda_jack.c
+@@ -259,7 +259,7 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
+ if (!callback)
+ return ERR_PTR(-ENOMEM);
+ callback->func = func;
+- callback->tbl = jack;
++ callback->nid = jack->nid;
+ callback->next = jack->callback;
+ jack->callback = callback;
+ }
+diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
+index b279e327a23b..a13c11c3ddbb 100644
+--- a/sound/pci/hda/hda_jack.h
++++ b/sound/pci/hda/hda_jack.h
+@@ -21,7 +21,7 @@ struct hda_jack_callback;
+ typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
+
+ struct hda_jack_callback {
+- struct hda_jack_tbl *tbl;
++ hda_nid_t nid;
+ hda_jack_callback_fn func;
+ unsigned int private_data; /* arbitrary data */
+ struct hda_jack_callback *next;
+diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
+index 4a4e7b282e4f..0374bd5b61c8 100644
+--- a/sound/pci/hda/patch_ca0132.c
++++ b/sound/pci/hda/patch_ca0132.c
+@@ -4401,13 +4401,16 @@ static void ca0132_process_dsp_response(struct hda_codec *codec,
+ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
+ {
+ struct ca0132_spec *spec = codec->spec;
++ struct hda_jack_tbl *tbl;
+
+ /* Delay enabling the HP amp, to let the mic-detection
+ * state machine run.
+ */
+ cancel_delayed_work_sync(&spec->unsol_hp_work);
+ schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
+- cb->tbl->block_report = 1;
++ tbl = snd_hda_jack_tbl_get(codec, cb->nid);
++ if (tbl)
++ tbl->block_report = 1;
+ }
+
+ static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
+diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
+index d02eccd51f6e..51d519554744 100644
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -433,7 +433,8 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
+ eld = &per_pin->sink_eld;
+
+ mutex_lock(&per_pin->lock);
+- if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
++ if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
++ eld->eld_size > ELD_MAX_SIZE) {
+ mutex_unlock(&per_pin->lock);
+ snd_BUG();
+ return -EINVAL;
+@@ -1178,7 +1179,7 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid)
+ static void jack_callback(struct hda_codec *codec,
+ struct hda_jack_callback *jack)
+ {
+- check_presence_and_report(codec, jack->tbl->nid);
++ check_presence_and_report(codec, jack->nid);
+ }
+
+ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 8189f02f8446..df34c78a6ced 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -277,7 +277,7 @@ static void alc_update_knob_master(struct hda_codec *codec,
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (!uctl)
+ return;
+- val = snd_hda_codec_read(codec, jack->tbl->nid, 0,
++ val = snd_hda_codec_read(codec, jack->nid, 0,
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+ val &= HDA_AMP_VOLMASK;
+ uctl->value.integer.value[0] = val;
+@@ -1792,7 +1792,6 @@ enum {
+ ALC882_FIXUP_NO_PRIMARY_HP,
+ ALC887_FIXUP_ASUS_BASS,
+ ALC887_FIXUP_BASS_CHMAP,
+- ALC882_FIXUP_DISABLE_AAMIX,
+ };
+
+ static void alc889_fixup_coef(struct hda_codec *codec,
+@@ -1954,8 +1953,6 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
+
+ static void alc_fixup_bass_chmap(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action);
+-static void alc_fixup_disable_aamix(struct hda_codec *codec,
+- const struct hda_fixup *fix, int action);
+
+ static const struct hda_fixup alc882_fixups[] = {
+ [ALC882_FIXUP_ABIT_AW9D_MAX] = {
+@@ -2193,10 +2190,6 @@ static const struct hda_fixup alc882_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_bass_chmap,
+ },
+- [ALC882_FIXUP_DISABLE_AAMIX] = {
+- .type = HDA_FIXUP_FUNC,
+- .v.func = alc_fixup_disable_aamix,
+- },
+ };
+
+ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+@@ -2235,6 +2228,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
+ SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
+ SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
++ SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
+
+ /* All Apple entries are in codec SSIDs */
+ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
+@@ -2264,7 +2258,6 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+ SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
+- SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
+ SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index 8e7d4c087a7a..840178a26a6b 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -493,9 +493,9 @@ static void jack_update_power(struct hda_codec *codec,
+ if (!spec->num_pwrs)
+ return;
+
+- if (jack && jack->tbl->nid) {
+- stac_toggle_power_map(codec, jack->tbl->nid,
+- snd_hda_jack_detect(codec, jack->tbl->nid),
++ if (jack && jack->nid) {
++ stac_toggle_power_map(codec, jack->nid,
++ snd_hda_jack_detect(codec, jack->nid),
+ true);
+ return;
+ }
+diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
+index 2ee44abd56a6..6cbd03a5e53d 100644
+--- a/sound/soc/codecs/rt5645.c
++++ b/sound/soc/codecs/rt5645.c
+@@ -487,7 +487,7 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = {
+
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
+- RT5645_BST_SFT1, 8, 0, bst_tlv),
++ RT5645_BST_SFT1, 12, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
+ RT5645_BST_SFT2, 8, 0, bst_tlv),
+
+diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
+index 35fe58f4fa86..52fe7eb2dea1 100644
+--- a/sound/soc/soc-pcm.c
++++ b/sound/soc/soc-pcm.c
+@@ -1661,7 +1661,8 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
+- (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
+ continue;
+
+ dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
+diff --git a/sound/usb/midi.c b/sound/usb/midi.c
+index bec63e0d2605..f059326a4914 100644
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -2451,7 +2451,6 @@ int snd_usbmidi_create(struct snd_card *card,
+ else
+ err = snd_usbmidi_create_endpoints(umidi, endpoints);
+ if (err < 0) {
+- snd_usbmidi_free(umidi);
+ return err;
+ }
+
next reply other threads:[~2016-03-06 12:02 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-05 23:38 Mike Pagano [this message]
-- strict thread matches above, loose matches on Subject: below --
2018-05-29 10:34 [gentoo-commits] proj/linux-patches:4.1 commit in: / Mike Pagano
2018-01-23 9:37 Alice Ferrazzi
2017-12-15 20:22 Alice Ferrazzi
2017-12-08 14:48 Mike Pagano
2017-12-07 18:53 Mike Pagano
2017-10-18 11:51 Mike Pagano
2017-09-13 19:38 Mike Pagano
2017-08-06 18:01 Mike Pagano
2017-04-14 19:17 Mike Pagano
2017-03-14 11:39 Mike Pagano
2017-03-02 16:31 Mike Pagano
2017-03-02 16:31 Mike Pagano
2017-02-24 16:11 Mike Pagano
2017-01-18 23:50 Alice Ferrazzi
2017-01-10 4:02 Alice Ferrazzi
2016-12-08 0:43 Mike Pagano
2016-11-30 11:45 Mike Pagano
2016-11-23 11:25 Mike Pagano
2016-10-28 10:19 Mike Pagano
2016-10-12 19:52 Mike Pagano
2016-09-18 12:47 Mike Pagano
2016-08-22 23:29 Mike Pagano
2016-08-10 12:55 Mike Pagano
2016-07-31 16:01 Mike Pagano
2016-07-15 14:18 Mike Pagano
2016-07-13 23:38 Mike Pagano
2016-07-02 15:31 Mike Pagano
2016-07-01 19:56 Mike Pagano
2016-06-23 11:45 Mike Pagano
2016-06-08 11:17 Mike Pagano
2016-05-24 12:39 Mike Pagano
2016-05-12 0:12 Mike Pagano
2016-04-28 18:56 Mike Pagano
2016-04-22 18:06 Mike Pagano
2016-04-20 11:23 Mike Pagano
2016-04-06 11:23 Mike Pagano
2016-03-22 22:47 Mike Pagano
2016-03-17 22:52 Mike Pagano
2016-02-16 15:28 Mike Pagano
2016-01-31 23:29 Mike Pagano
2016-01-23 18:30 Mike Pagano
2016-01-20 13:54 Mike Pagano
2015-12-15 11:17 Mike Pagano
2015-12-10 13:54 Mike Pagano
2015-11-10 0:30 Mike Pagano
2015-11-05 23:29 Mike Pagano
2015-11-05 23:29 Mike Pagano
2015-10-27 13:19 Mike Pagano
2015-10-26 20:51 Mike Pagano
2015-10-26 20:49 Mike Pagano
2015-10-03 16:07 Mike Pagano
2015-10-02 12:08 Mike Pagano
2015-09-29 17:50 Mike Pagano
2015-09-28 23:57 Mike Pagano
2015-09-21 22:16 Mike Pagano
2015-09-14 15:20 Mike Pagano
2015-08-17 15:38 Mike Pagano
2015-08-12 14:17 Mike Pagano
2015-08-10 23:42 Mike Pagano
2015-08-03 19:01 Mike Pagano
2015-07-22 10:31 Mike Pagano
2015-07-22 10:09 Mike Pagano
2015-07-19 18:55 Mike Pagano
2015-07-17 15:24 Mike Pagano
2015-07-10 23:47 Mike Pagano
2015-07-01 15:33 Mike Pagano
2015-06-27 19:50 Mike Pagano
2015-06-26 22:36 Mike Pagano
2015-06-20 17:37 Mike Pagano
2015-06-08 17:59 Mike Pagano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1457221107.4a919eff2d079c34d6f84bf9073c32ef11af9864.mpagano@gentoo \
--to=mpagano@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox