diff options
author | Mike Pagano <mpagano@gentoo.org> | 2016-03-05 18:38:27 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2016-03-05 18:38:27 -0500 |
commit | 4a919eff2d079c34d6f84bf9073c32ef11af9864 (patch) | |
tree | e39d8117cf3958e7ab0d240f11455d54ebcf583d | |
parent | Linux patch 4.1.18 (diff) | |
download | linux-patches-4a919eff2d079c34d6f84bf9073c32ef11af9864.tar.gz linux-patches-4a919eff2d079c34d6f84bf9073c32ef11af9864.tar.bz2 linux-patches-4a919eff2d079c34d6f84bf9073c32ef11af9864.zip |
Linux patch 4.1.194.1-24
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1018_linux-4.1.19.patch | 7602 |
2 files changed, 7606 insertions, 0 deletions
diff --git a/0000_README b/0000_README index ed66531a..ad1d3727 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 00000000..449c63a4 --- /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; + } + |