diff options
author | Mike Pagano <mpagano@gentoo.org> | 2016-02-17 18:59:04 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2016-02-17 18:59:04 -0500 |
commit | 785c46db0215ad62c979861e60bdeccd37f198ce (patch) | |
tree | 060993f01889b6e5b4ac06a4ea41984b3d8e116e | |
parent | Linux patch 3.14.60 (diff) | |
download | linux-patches-785c46db0215ad62c979861e60bdeccd37f198ce.tar.gz linux-patches-785c46db0215ad62c979861e60bdeccd37f198ce.tar.bz2 linux-patches-785c46db0215ad62c979861e60bdeccd37f198ce.zip |
Linux patch 3.14.613.14-68
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1060_linux-3.14.61.patch | 2765 |
2 files changed, 2769 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 03a61a1b..d9cdf768 100644 --- a/0000_README +++ b/0000_README @@ -282,6 +282,10 @@ Patch: 1059_linux-3.14.60.patch From: http://www.kernel.org Desc: Linux 3.14.60 +Patch: 1060_linux-3.14.61.patch +From: http://www.kernel.org +Desc: Linux 3.14.61 + 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/1060_linux-3.14.61.patch b/1060_linux-3.14.61.patch new file mode 100644 index 00000000..9b42d080 --- /dev/null +++ b/1060_linux-3.14.61.patch @@ -0,0 +1,2765 @@ +diff --git a/Makefile b/Makefile +index 502255cebc9a..fbf4ec689957 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 60 ++SUBLEVEL = 61 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h +index 294d251ca7b2..2ae13ce592e8 100644 +--- a/arch/parisc/include/uapi/asm/mman.h ++++ b/arch/parisc/include/uapi/asm/mman.h +@@ -46,16 +46,6 @@ + #define MADV_DONTFORK 10 /* don't inherit across fork */ + #define MADV_DOFORK 11 /* do inherit across fork */ + +-/* The range 12-64 is reserved for page size specification. */ +-#define MADV_4K_PAGES 12 /* Use 4K pages */ +-#define MADV_16K_PAGES 14 /* Use 16K pages */ +-#define MADV_64K_PAGES 16 /* Use 64K pages */ +-#define MADV_256K_PAGES 18 /* Use 256K pages */ +-#define MADV_1M_PAGES 20 /* Use 1 Megabyte pages */ +-#define MADV_4M_PAGES 22 /* Use 4 Megabyte pages */ +-#define MADV_16M_PAGES 24 /* Use 16 Megabyte pages */ +-#define MADV_64M_PAGES 26 /* Use 64 Megabyte pages */ +- + #define MADV_MERGEABLE 65 /* KSM may merge identical pages */ + #define MADV_UNMERGEABLE 66 /* KSM may not merge identical pages */ + +diff --git a/arch/parisc/include/uapi/asm/siginfo.h b/arch/parisc/include/uapi/asm/siginfo.h +index d7034728f377..1c75565d984b 100644 +--- a/arch/parisc/include/uapi/asm/siginfo.h ++++ b/arch/parisc/include/uapi/asm/siginfo.h +@@ -1,6 +1,10 @@ + #ifndef _PARISC_SIGINFO_H + #define _PARISC_SIGINFO_H + ++#if defined(__LP64__) ++#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) ++#endif ++ + #include <asm-generic/siginfo.h> + + #undef NSIGTRAP +diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c +index 1cba8f29bb49..78bb6dd88e03 100644 +--- a/arch/parisc/kernel/signal.c ++++ b/arch/parisc/kernel/signal.c +@@ -442,6 +442,55 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + regs->gr[28]); + } + ++/* ++ * Check how the syscall number gets loaded into %r20 within ++ * the delay branch in userspace and adjust as needed. ++ */ ++ ++static void check_syscallno_in_delay_branch(struct pt_regs *regs) ++{ ++ u32 opcode, source_reg; ++ u32 __user *uaddr; ++ int err; ++ ++ /* Usually we don't have to restore %r20 (the system call number) ++ * because it gets loaded in the delay slot of the branch external ++ * instruction via the ldi instruction. ++ * In some cases a register-to-register copy instruction might have ++ * been used instead, in which case we need to copy the syscall ++ * number into the source register before returning to userspace. ++ */ ++ ++ /* A syscall is just a branch, so all we have to do is fiddle the ++ * return pointer so that the ble instruction gets executed again. ++ */ ++ regs->gr[31] -= 8; /* delayed branching */ ++ ++ /* Get assembler opcode of code in delay branch */ ++ uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4); ++ err = get_user(opcode, uaddr); ++ if (err) ++ return; ++ ++ /* Check if delay branch uses "ldi int,%r20" */ ++ if ((opcode & 0xffff0000) == 0x34140000) ++ return; /* everything ok, just return */ ++ ++ /* Check if delay branch uses "nop" */ ++ if (opcode == INSN_NOP) ++ return; ++ ++ /* Check if delay branch uses "copy %rX,%r20" */ ++ if ((opcode & 0xffe0ffff) == 0x08000254) { ++ source_reg = (opcode >> 16) & 31; ++ regs->gr[source_reg] = regs->gr[20]; ++ return; ++ } ++ ++ pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n", ++ current->comm, task_pid_nr(current), opcode); ++} ++ + static inline void + syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) + { +@@ -464,10 +513,7 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) + } + /* fallthrough */ + case -ERESTARTNOINTR: +- /* A syscall is just a branch, so all +- * we have to do is fiddle the return pointer. +- */ +- regs->gr[31] -= 8; /* delayed branching */ ++ check_syscallno_in_delay_branch(regs); + break; + } + } +@@ -516,15 +562,9 @@ insert_restart_trampoline(struct pt_regs *regs) + } + case -ERESTARTNOHAND: + case -ERESTARTSYS: +- case -ERESTARTNOINTR: { +- /* Hooray for delayed branching. We don't +- * have to restore %r20 (the system call +- * number) because it gets loaded in the delay +- * slot of the branch external instruction. +- */ +- regs->gr[31] -= 8; ++ case -ERESTARTNOINTR: ++ check_syscallno_in_delay_branch(regs); + return; +- } + default: + break; + } +diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h +index e6820c86e8c7..47ebd5b5ed55 100644 +--- a/arch/sh/include/uapi/asm/unistd_64.h ++++ b/arch/sh/include/uapi/asm/unistd_64.h +@@ -278,7 +278,7 @@ + #define __NR_fsetxattr 256 + #define __NR_getxattr 257 + #define __NR_lgetxattr 258 +-#define __NR_fgetxattr 269 ++#define __NR_fgetxattr 259 + #define __NR_listxattr 260 + #define __NR_llistxattr 261 + #define __NR_flistxattr 262 +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 1de4beeb25f8..1971f3ccb09a 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -125,6 +125,23 @@ int af_alg_release(struct socket *sock) + } + EXPORT_SYMBOL_GPL(af_alg_release); + ++void af_alg_release_parent(struct sock *sk) ++{ ++ struct alg_sock *ask = alg_sk(sk); ++ bool last; ++ ++ sk = ask->parent; ++ ask = alg_sk(sk); ++ ++ lock_sock(sk); ++ last = !--ask->refcnt; ++ release_sock(sk); ++ ++ if (last) ++ sock_put(sk); ++} ++EXPORT_SYMBOL_GPL(af_alg_release_parent); ++ + static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + { + struct sock *sk = sock->sk; +@@ -132,6 +149,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + struct sockaddr_alg *sa = (void *)uaddr; + const struct af_alg_type *type; + void *private; ++ int err; + + if (sock->state == SS_CONNECTED) + return -EINVAL; +@@ -157,16 +175,22 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + return PTR_ERR(private); + } + ++ err = -EBUSY; + lock_sock(sk); ++ if (ask->refcnt) ++ goto unlock; + + swap(ask->type, type); + swap(ask->private, private); + ++ err = 0; ++ ++unlock: + release_sock(sk); + + alg_do_release(type, private); + +- return 0; ++ return err; + } + + static int alg_setkey(struct sock *sk, char __user *ukey, +@@ -199,11 +223,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + const struct af_alg_type *type; +- int err = -ENOPROTOOPT; ++ int err = -EBUSY; + + lock_sock(sk); ++ if (ask->refcnt) ++ goto unlock; ++ + type = ask->type; + ++ err = -ENOPROTOOPT; + if (level != SOL_ALG || !type) + goto unlock; + +@@ -247,14 +275,13 @@ int af_alg_accept(struct sock *sk, struct socket *newsock) + security_sk_clone(sk, sk2); + + err = type->accept(ask->private, sk2); +- if (err) { +- sk_free(sk2); ++ if (err) + goto unlock; +- } + + sk2->sk_family = PF_ALG; + +- sock_hold(sk); ++ if (!ask->refcnt++) ++ sock_hold(sk); + alg_sk(sk2)->parent = sk; + alg_sk(sk2)->type = type; + +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index 850246206b12..c542c0d88afd 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -51,7 +51,8 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock, + + lock_sock(sk); + if (!ctx->more) { +- err = crypto_ahash_init(&ctx->req); ++ err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req), ++ &ctx->completion); + if (err) + goto unlock; + } +@@ -131,6 +132,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, + } else { + if (!ctx->more) { + err = crypto_ahash_init(&ctx->req); ++ err = af_alg_wait_for_completion(err, &ctx->completion); + if (err) + goto unlock; + } +@@ -192,9 +194,14 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags) + struct sock *sk2; + struct alg_sock *ask2; + struct hash_ctx *ctx2; ++ bool more; + int err; + +- err = crypto_ahash_export(req, state); ++ lock_sock(sk); ++ more = ctx->more; ++ err = more ? crypto_ahash_export(req, state) : 0; ++ release_sock(sk); ++ + if (err) + return err; + +@@ -205,7 +212,10 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags) + sk2 = newsock->sk; + ask2 = alg_sk(sk2); + ctx2 = ask2->private; +- ctx2->more = 1; ++ ctx2->more = more; ++ ++ if (!more) ++ return err; + + err = crypto_ahash_import(&ctx2->req, state); + if (err) { +diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c +index c7666f401381..a3dfc0d83107 100644 +--- a/crypto/crypto_user.c ++++ b/crypto/crypto_user.c +@@ -477,6 +477,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; + +@@ -486,8 +487,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 cc5f102bebf3..111614b48f96 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -249,6 +249,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 b65d79cd43d5..8b24a7bb573b 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -487,8 +487,8 @@ void ahci_save_initial_config(struct device *dev, + } + } + +- /* 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); + +@@ -1253,6 +1253,15 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, + ata_tf_to_fis(tf, pmp, is_cmd, fis); + ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12)); + ++ /* set port value for softreset of Port Multiplier */ ++ if (pp->fbs_enabled && pp->fbs_last_dev != pmp) { ++ tmp = readl(port_mmio + PORT_FBS); ++ tmp &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC); ++ tmp |= pmp << PORT_FBS_DEV_OFFSET; ++ writel(tmp, port_mmio + PORT_FBS); ++ pp->fbs_last_dev = pmp; ++ } ++ + /* issue & wait */ + writel(1, port_mmio + PORT_CMD_ISSUE); + +diff --git a/drivers/base/memory.c b/drivers/base/memory.c +index bece691cb5d9..3e2a3059b1f8 100644 +--- a/drivers/base/memory.c ++++ b/drivers/base/memory.c +@@ -311,6 +311,10 @@ static int memory_subsys_offline(struct device *dev) + if (mem->state == MEM_OFFLINE) + return 0; + ++ /* Can't offline block with non-present sections */ ++ if (mem->section_count != sections_per_block) ++ return -EINVAL; ++ + return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); + } + +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index 643bba7d6f81..9eab751efeea 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -490,7 +490,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, + } + ibmvtpm->rtce_size = be16_to_cpu(crq->len); + ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, +- GFP_KERNEL); ++ GFP_ATOMIC); + if (!ibmvtpm->rtce_buf) { + dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n"); + return; +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index deabd2c8772d..ced6d61c1787 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -492,8 +492,6 @@ static void hid_ctrl(struct urb *urb) + struct usbhid_device *usbhid = hid->driver_data; + int unplug = 0, status = urb->status; + +- spin_lock(&usbhid->lock); +- + switch (status) { + case 0: /* success */ + if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) +@@ -513,6 +511,8 @@ static void hid_ctrl(struct urb *urb) + hid_warn(urb->dev, "ctrl urb status %d received\n", status); + } + ++ spin_lock(&usbhid->lock); ++ + if (unplug) { + usbhid->ctrltail = usbhid->ctrlhead; + } else { +diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c +index 422a9fdeb53e..6eb9dc9ef8f3 100644 +--- a/drivers/md/dm-mpath.c ++++ b/drivers/md/dm-mpath.c +@@ -1626,11 +1626,8 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, + /* + * Only pass ioctls through if the device sizes match exactly. + */ +- if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) { +- int err = scsi_verify_blk_ioctl(NULL, cmd); +- if (err) +- r = err; +- } ++ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); + + if (r == -ENOTCONN && !fatal_signal_pending(current)) + queue_work(kmultipathd, &m->process_queued_ios); +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index d6e47033b5e0..7ba85e2b146b 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -471,8 +471,10 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root, + + r = insert_at(sizeof(__le64), pn, parent_index + 1, + le64_to_cpu(rn->keys[0]), &location); +- if (r) ++ if (r) { ++ unlock_block(s->info, right); + return r; ++ } + + if (key < le64_to_cpu(rn->keys[0])) { + unlock_block(s->info, right); +diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c +index dd67c8a400cc..6bac4a53da1d 100644 +--- a/drivers/media/pci/saa7134/saa7134-alsa.c ++++ b/drivers/media/pci/saa7134/saa7134-alsa.c +@@ -1145,6 +1145,8 @@ static int alsa_device_init(struct saa7134_dev *dev) + + static int alsa_device_exit(struct saa7134_dev *dev) + { ++ if (!snd_saa7134_cards[dev->nr]) ++ return 1; + + snd_card_free(snd_saa7134_cards[dev->nr]); + snd_saa7134_cards[dev->nr] = NULL; +@@ -1194,7 +1196,8 @@ static void saa7134_alsa_exit(void) + int idx; + + for (idx = 0; idx < SNDRV_CARDS; idx++) { +- snd_card_free(snd_saa7134_cards[idx]); ++ if (snd_saa7134_cards[idx]) ++ snd_card_free(snd_saa7134_cards[idx]); + } + + saa7134_dmasound_init = NULL; +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index fca336b65351..2bece37d0228 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -264,7 +264,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_ + + struct v4l2_standard32 { + __u32 index; +- __u32 id[2]; /* __u64 would get the alignment wrong */ ++ compat_u64 id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; +@@ -284,7 +284,7 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 + { + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || + put_user(kp->index, &up->index) || +- copy_to_user(up->id, &kp->id, sizeof(__u64)) || ++ put_user(kp->id, &up->id) || + copy_to_user(up->name, kp->name, 24) || + copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || + put_user(kp->framelines, &up->framelines) || +@@ -576,10 +576,10 @@ struct v4l2_input32 { + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ +- v4l2_std_id std; ++ compat_u64 std; + __u32 status; + __u32 reserved[4]; +-} __attribute__ ((packed)); ++}; + + /* The 64-bit v4l2_input struct has extra padding at the end of the struct. + Otherwise it is identical to the 32-bit version. */ +@@ -719,6 +719,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext + struct v4l2_event32 { + __u32 type; + union { ++ compat_s64 value64; + __u8 data[64]; + } u; + __u32 pending; +diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c +index 33d3871d1e13..63aeac93a95e 100644 +--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c ++++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c +@@ -117,7 +117,8 @@ static void vb2_dc_prepare(void *buf_priv) + if (!sgt || buf->db_attach) + return; + +- dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir); ++ dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents, ++ buf->dma_dir); + } + + static void vb2_dc_finish(void *buf_priv) +@@ -129,7 +130,7 @@ static void vb2_dc_finish(void *buf_priv) + if (!sgt || buf->db_attach) + return; + +- dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir); ++ dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir); + } + + /*********************************************/ +diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c +index 3c7d6d7623c1..e638993ac626 100644 +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -635,8 +635,10 @@ int add_mtd_partitions(struct mtd_info *master, + + for (i = 0; i < nbparts; i++) { + slave = allocate_partition(master, parts + i, i, cur_offset); +- if (IS_ERR(slave)) ++ if (IS_ERR(slave)) { ++ del_mtd_partitions(master); + return PTR_ERR(slave); ++ } + + mutex_lock(&mtd_partitions_mutex); + list_add(&slave->list, &mtd_partitions); +diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h +index 07e3d6a049ad..e11c1adf2aad 100644 +--- a/drivers/net/wireless/ti/wlcore/io.h ++++ b/drivers/net/wireless/ti/wlcore/io.h +@@ -203,19 +203,23 @@ static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg, + + static inline void wl1271_power_off(struct wl1271 *wl) + { +- int ret; ++ int ret = 0; + + if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags)) + return; + +- ret = wl->if_ops->power(wl->dev, false); ++ if (wl->if_ops->power) ++ ret = wl->if_ops->power(wl->dev, false); + if (!ret) + clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); + } + + static inline int wl1271_power_on(struct wl1271 *wl) + { +- int ret = wl->if_ops->power(wl->dev, true); ++ int ret = 0; ++ ++ if (wl->if_ops->power) ++ ret = wl->if_ops->power(wl->dev, true); + if (ret == 0) + set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); + +diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c +index b2c018dccf18..c675163b0d40 100644 +--- a/drivers/net/wireless/ti/wlcore/spi.c ++++ b/drivers/net/wireless/ti/wlcore/spi.c +@@ -72,7 +72,10 @@ + */ + #define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) + +-#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) ++/* Maximum number of SPI write chunks */ ++#define WSPI_MAX_NUM_OF_CHUNKS \ ++ ((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1) ++ + + struct wl12xx_spi_glue { + struct device *dev; +@@ -270,9 +273,10 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, + void *buf, size_t len, bool fixed) + { + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); +- struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)]; ++ /* SPI write buffers - 2 for each chunk */ ++ struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; + struct spi_message m; +- u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; ++ u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */ + u32 *cmd; + u32 chunk_len; + int i; +diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c +index 38901665c770..f16c43dd6d04 100644 +--- a/drivers/pci/bus.c ++++ b/drivers/pci/bus.c +@@ -147,6 +147,8 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, + type_mask |= IORESOURCE_IO | IORESOURCE_MEM; + + pci_bus_for_each_resource(bus, r, i) { ++ resource_size_t min_used = min; ++ + if (!r) + continue; + +@@ -170,12 +172,12 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, + * overrides "min". + */ + if (avail.start) +- min = avail.start; ++ min_used = avail.start; + + max = avail.end; + + /* Ok, try it out.. */ +- ret = allocate_resource(r, res, size, min, max, ++ ret = allocate_resource(r, res, size, min_used, max, + align, alignf, alignf_data); + if (ret == 0) + return 0; +diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c +index 9d30809bb407..916af5096f57 100644 +--- a/drivers/remoteproc/remoteproc_debugfs.c ++++ b/drivers/remoteproc/remoteproc_debugfs.c +@@ -156,7 +156,7 @@ rproc_recovery_write(struct file *filp, const char __user *user_buf, + char buf[10]; + int ret; + +- if (count > sizeof(buf)) ++ if (count < 1 || count > sizeof(buf)) + return count; + + ret = copy_from_user(buf, user_buf, count); +diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c +index 5f8c6d2f4df7..0e46e8d1d7bc 100644 +--- a/drivers/spi/spi-atmel.c ++++ b/drivers/spi/spi-atmel.c +@@ -593,7 +593,8 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, + + *plen = len; + +- if (atmel_spi_dma_slave_config(as, &slave_config, 8)) ++ if (atmel_spi_dma_slave_config(as, &slave_config, ++ xfer->bits_per_word)) + goto err_exit; + + /* Send both scatterlists */ +diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c +index 3d09265b5133..1454a0c42aac 100644 +--- a/drivers/spi/spi-ti-qspi.c ++++ b/drivers/spi/spi-ti-qspi.c +@@ -364,11 +364,10 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, + + mutex_unlock(&qspi->list_lock); + ++ ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG); + m->status = status; + spi_finalize_current_message(master); + +- ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG); +- + return status; + } + +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index d88492152be1..72ed3d147687 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -1268,7 +1268,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) + master->bus_num = -1; + master->num_chipselect = 1; + master->dev.class = &spi_master_class; +- master->dev.parent = get_device(dev); ++ master->dev.parent = dev; + spi_master_set_devdata(master, &master[1]); + + return master; +diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c +index 143deb62467d..12446e9a4435 100644 +--- a/drivers/tty/tty_buffer.c ++++ b/drivers/tty/tty_buffer.c +@@ -411,7 +411,7 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) + count = disc->ops->receive_buf2(tty, p, f, count); + else { + count = min_t(int, count, tty->receive_room); +- if (count) ++ if (count && disc->ops->receive_buf) + disc->ops->receive_buf(tty, p, f, count); + } + head->read += count; +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 39988fa91294..b17df1000250 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -2581,6 +2581,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) + } + + /** ++ * tiocgetd - get line discipline ++ * @tty: tty device ++ * @p: pointer to user data ++ * ++ * Retrieves the line discipline id directly from the ldisc. ++ * ++ * Locking: waits for ldisc reference (in case the line discipline ++ * is changing or the tty is being hungup) ++ */ ++ ++static int tiocgetd(struct tty_struct *tty, int __user *p) ++{ ++ struct tty_ldisc *ld; ++ int ret; ++ ++ ld = tty_ldisc_ref_wait(tty); ++ ret = put_user(ld->ops->num, p); ++ tty_ldisc_deref(ld); ++ return ret; ++} ++ ++/** + * send_break - performed time break + * @tty: device to break on + * @duration: timeout in mS +@@ -2794,7 +2816,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case TIOCGSID: + return tiocgsid(tty, real_tty, p); + case TIOCGETD: +- return put_user(tty->ldisc->ops->num, (int __user *)p); ++ return tiocgetd(tty, p); + case TIOCSETD: + return tiocsetd(tty, p); + case TIOCVHANGUP: +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index fa114bcedabf..648e7eccdde9 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -5225,7 +5225,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + usb_set_usb2_hardware_lpm(udev, 0); + + bos = udev->bos; +- udev->bos = NULL; + + /* Disable LPM and LTM while we reset the device and reinstall the alt + * settings. Device-initiated LPM settings, and system exit latency +@@ -5334,8 +5333,11 @@ done: + usb_set_usb2_hardware_lpm(udev, 1); + usb_unlocked_enable_lpm(udev); + usb_enable_ltm(udev); +- usb_release_bos_descriptor(udev); +- udev->bos = bos; ++ /* release the new BOS descriptor allocated by hub_port_init() */ ++ if (udev->bos != bos) { ++ usb_release_bos_descriptor(udev); ++ udev->bos = bos; ++ } + return 0; + + re_enumerate: +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 5c957658a04a..7f01f165e77b 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -612,8 +612,30 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + if ((raw_port_status & PORT_RESET) || + !(raw_port_status & PORT_PE)) + return 0xffffffff; +- if (time_after_eq(jiffies, +- bus_state->resume_done[wIndex])) { ++ /* did port event handler already start resume timing? */ ++ if (!bus_state->resume_done[wIndex]) { ++ /* If not, maybe we are in a host initated resume? */ ++ if (test_bit(wIndex, &bus_state->resuming_ports)) { ++ /* Host initated resume doesn't time the resume ++ * signalling using resume_done[]. ++ * It manually sets RESUME state, sleeps 20ms ++ * and sets U0 state. This should probably be ++ * changed, but not right now. ++ */ ++ } else { ++ /* port resume was discovered now and here, ++ * start resume timing ++ */ ++ unsigned long timeout = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); ++ ++ set_bit(wIndex, &bus_state->resuming_ports); ++ bus_state->resume_done[wIndex] = timeout; ++ mod_timer(&hcd->rh_timer, timeout); ++ } ++ /* Has resume been signalled for USB_RESUME_TIME yet? */ ++ } else if (time_after_eq(jiffies, ++ bus_state->resume_done[wIndex])) { + int time_left; + + xhci_dbg(xhci, "Resume USB2 port %d\n", +@@ -654,13 +676,24 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + } else { + /* + * The resume has been signaling for less than +- * 20ms. Report the port status as SUSPEND, +- * let the usbcore check port status again +- * and clear resume signaling later. ++ * USB_RESUME_TIME. Report the port status as SUSPEND, ++ * let the usbcore check port status again and clear ++ * resume signaling later. + */ + status |= USB_PORT_STAT_SUSPEND; + } + } ++ /* ++ * Clear stale usb2 resume signalling variables in case port changed ++ * state during resume signalling. For example on error ++ */ ++ if ((bus_state->resume_done[wIndex] || ++ test_bit(wIndex, &bus_state->resuming_ports)) && ++ (raw_port_status & PORT_PLS_MASK) != XDEV_U3 && ++ (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) { ++ bus_state->resume_done[wIndex] = 0; ++ clear_bit(wIndex, &bus_state->resuming_ports); ++ } + if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 + && (raw_port_status & PORT_POWER) + && (bus_state->suspended_ports & (1 << wIndex))) { +@@ -989,6 +1022,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + if ((temp & PORT_PE) == 0) + goto error; + ++ set_bit(wIndex, &bus_state->resuming_ports); + xhci_set_link_state(xhci, port_array, wIndex, + XDEV_RESUME); + spin_unlock_irqrestore(&xhci->lock, flags); +@@ -996,6 +1030,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + spin_lock_irqsave(&xhci->lock, flags); + xhci_set_link_state(xhci, port_array, wIndex, + XDEV_U0); ++ clear_bit(wIndex, &bus_state->resuming_ports); + } + bus_state->port_c_suspend |= 1 << wIndex; + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index bd993fe00e0c..3bfe81c6229a 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1768,7 +1768,8 @@ static void handle_port_status(struct xhci_hcd *xhci, + */ + bogus_port_status = true; + goto cleanup; +- } else { ++ } else if (!test_bit(faked_port_index, ++ &bus_state->resuming_ports)) { + xhci_dbg(xhci, "resume HS port %d\n", port_id); + bus_state->resume_done[faked_port_index] = jiffies + + msecs_to_jiffies(USB_RESUME_TIMEOUT); +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index c8e693c22014..27688e3b0a4c 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -4866,6 +4866,9 @@ static int __init xhci_hcd_init(void) + { + int retval; + ++ if (usb_disabled()) ++ return -ENODEV; ++ + retval = xhci_register_pci(); + if (retval < 0) { + pr_debug("Problem registering PCI driver.\n"); +@@ -4894,9 +4897,6 @@ static int __init xhci_hcd_init(void) + /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */ + BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8); + +- if (usb_disabled()) +- return -ENODEV; +- + return 0; + unreg_pci: + xhci_unregister_pci(); +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index b4fc4091e3f8..02e6fe228a63 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -98,6 +98,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ + { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ + { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ ++ { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */ + { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ + { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 7fb81dbbdc8d..b5d8e2544b8f 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -837,6 +837,7 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, ++ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) }, + { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, + + /* Papouch devices based on FTDI chip */ +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 2943b97b2a83..7850071c0ae1 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -615,6 +615,7 @@ + */ + #define RATOC_VENDOR_ID 0x0584 + #define RATOC_PRODUCT_ID_USB60F 0xb020 ++#define RATOC_PRODUCT_ID_SCU18 0xb03a + + /* + * Infineon Technologies +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index bdbe642e6569..81f6a572f016 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -269,6 +269,8 @@ static void option_instat_callback(struct urb *urb); + #define TELIT_PRODUCT_CC864_SINGLE 0x1006 + #define TELIT_PRODUCT_DE910_DUAL 0x1010 + #define TELIT_PRODUCT_UE910_V2 0x1012 ++#define TELIT_PRODUCT_LE922_USBCFG0 0x1042 ++#define TELIT_PRODUCT_LE922_USBCFG3 0x1043 + #define TELIT_PRODUCT_LE920 0x1200 + #define TELIT_PRODUCT_LE910 0x1201 + +@@ -623,6 +625,16 @@ static const struct option_blacklist_info telit_le920_blacklist = { + .reserved = BIT(1) | BIT(5), + }; + ++static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = { ++ .sendsetup = BIT(2), ++ .reserved = BIT(0) | BIT(1) | BIT(3), ++}; ++ ++static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = { ++ .sendsetup = BIT(0), ++ .reserved = BIT(1) | BIT(2) | BIT(3), ++}; ++ + static const struct usb_device_id option_ids[] = { + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, +@@ -1168,6 +1180,10 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, ++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), ++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, ++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3), ++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), + .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), +@@ -1679,7 +1695,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +- { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, ++ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, +diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c +index 60afb39eb73c..337a0be89fcf 100644 +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -544,6 +544,11 @@ static int treo_attach(struct usb_serial *serial) + (serial->num_interrupt_in == 0)) + return 0; + ++ if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ + /* + * It appears that Treos and Kyoceras want to use the + * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, +@@ -597,8 +602,10 @@ static int clie_5_attach(struct usb_serial *serial) + */ + + /* some sanity check */ +- if (serial->num_ports < 2) +- return -1; ++ if (serial->num_bulk_out < 2) { ++ dev_err(&serial->interface->dev, "missing bulk out endpoints\n"); ++ return -ENODEV; ++ } + + /* port 0 now uses the modified endpoint Address */ + port = serial->port[0]; +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 35240a704413..6eb8df76e17c 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -679,16 +679,16 @@ static int load_elf_binary(struct linux_binprm *bprm) + */ + would_dump(bprm, interpreter); + +- retval = kernel_read(interpreter, 0, bprm->buf, +- BINPRM_BUF_SIZE); +- if (retval != BINPRM_BUF_SIZE) { ++ /* Get the exec headers */ ++ retval = kernel_read(interpreter, 0, ++ (void *)&loc->interp_elf_ex, ++ sizeof(loc->interp_elf_ex)); ++ if (retval != sizeof(loc->interp_elf_ex)) { + if (retval >= 0) + retval = -EIO; + goto out_free_dentry; + } + +- /* Get the exec headers */ +- loc->interp_elf_ex = *((struct elfhdr *)bprm->buf); + break; + } + elf_ppnt++; +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 2a6830a7af33..96fe2c175a73 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -26,6 +26,7 @@ + #include <linux/seqlock.h> + #include <linux/mutex.h> + #include <linux/timer.h> ++#include <linux/version.h> + #include <linux/wait.h> + #include <linux/blockgroup_lock.h> + #include <linux/percpu_counter.h> +@@ -724,19 +725,55 @@ struct move_extent { + <= (EXT4_GOOD_OLD_INODE_SIZE + \ + (einode)->i_extra_isize)) \ + ++/* ++ * We use an encoding that preserves the times for extra epoch "00": ++ * ++ * extra msb of adjust for signed ++ * epoch 32-bit 32-bit tv_sec to ++ * bits time decoded 64-bit tv_sec 64-bit tv_sec valid time range ++ * 0 0 1 -0x80000000..-0x00000001 0x000000000 1901-12-13..1969-12-31 ++ * 0 0 0 0x000000000..0x07fffffff 0x000000000 1970-01-01..2038-01-19 ++ * 0 1 1 0x080000000..0x0ffffffff 0x100000000 2038-01-19..2106-02-07 ++ * 0 1 0 0x100000000..0x17fffffff 0x100000000 2106-02-07..2174-02-25 ++ * 1 0 1 0x180000000..0x1ffffffff 0x200000000 2174-02-25..2242-03-16 ++ * 1 0 0 0x200000000..0x27fffffff 0x200000000 2242-03-16..2310-04-04 ++ * 1 1 1 0x280000000..0x2ffffffff 0x300000000 2310-04-04..2378-04-22 ++ * 1 1 0 0x300000000..0x37fffffff 0x300000000 2378-04-22..2446-05-10 ++ * ++ * Note that previous versions of the kernel on 64-bit systems would ++ * incorrectly use extra epoch bits 1,1 for dates between 1901 and ++ * 1970. e2fsck will correct this, assuming that it is run on the ++ * affected filesystem before 2242. ++ */ ++ + static inline __le32 ext4_encode_extra_time(struct timespec *time) + { +- return cpu_to_le32((sizeof(time->tv_sec) > 4 ? +- (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) | +- ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK)); ++ u32 extra = sizeof(time->tv_sec) > 4 ? ++ ((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0; ++ return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS)); + } + + static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra) + { +- if (sizeof(time->tv_sec) > 4) +- time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) +- << 32; +- time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; ++ if (unlikely(sizeof(time->tv_sec) > 4 && ++ (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0) ++ /* Handle legacy encoding of pre-1970 dates with epoch ++ * bits 1,1. We assume that by kernel version 4.20, ++ * everyone will have run fsck over the affected ++ * filesystems to correct the problem. (This ++ * backwards compatibility may be removed before this ++ * time, at the discretion of the ext4 developers.) ++ */ ++ u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK; ++ if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0) ++ extra_bits = 0; ++ time->tv_sec += extra_bits << 32; ++#else ++ time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32; ++#endif ++ } ++ time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; + } + + #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \ +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index 2400ad1c3d12..831cb305c63f 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1030,7 +1030,7 @@ exit_free: + * do not copy the full number of backups at this time. The resize + * which changed s_groups_count will backup again. + */ +-static void update_backups(struct super_block *sb, int blk_off, char *data, ++static void update_backups(struct super_block *sb, sector_t blk_off, char *data, + int size, int meta_bg) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +@@ -1055,7 +1055,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data, + group = ext4_list_backups(sb, &three, &five, &seven); + last = sbi->s_groups_count; + } else { +- group = ext4_meta_bg_first_group(sb, group) + 1; ++ group = ext4_get_group_number(sb, blk_off) + 1; + last = (ext4_group_t)(group + EXT4_DESC_PER_BLOCK(sb) - 2); + } + +diff --git a/fs/fat/dir.c b/fs/fat/dir.c +index 3963ede84eb0..75bf5e717ed8 100644 +--- a/fs/fat/dir.c ++++ b/fs/fat/dir.c +@@ -614,9 +614,9 @@ parse_record: + int status = fat_parse_long(inode, &cpos, &bh, &de, + &unicode, &nr_slots); + if (status < 0) { +- ctx->pos = cpos; ++ bh = NULL; + ret = status; +- goto out; ++ goto end_of_dir; + } else if (status == PARSE_INVALID) + goto record_end; + else if (status == PARSE_NOT_LONGNAME) +@@ -658,8 +658,9 @@ parse_record: + fill_len = short_len; + + start_filldir: +- if (!fake_offset) +- ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); ++ ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); ++ if (fake_offset && ctx->pos < 2) ++ ctx->pos = 2; + + if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) { + if (!dir_emit_dot(file, ctx)) +@@ -685,14 +686,19 @@ record_end: + fake_offset = 0; + ctx->pos = cpos; + goto get_new; ++ + end_of_dir: +- ctx->pos = cpos; ++ if (fake_offset && cpos < 2) ++ ctx->pos = 2; ++ else ++ ctx->pos = cpos; + fill_failed: + brelse(bh); + if (unicode) + __putname(unicode); + out: + mutex_unlock(&sbi->s_lock); ++ + return ret; + } + +diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c +index 989f39401547..96e48c67271b 100644 +--- a/fs/fscache/netfs.c ++++ b/fs/fscache/netfs.c +@@ -22,6 +22,7 @@ static LIST_HEAD(fscache_netfs_list); + int __fscache_register_netfs(struct fscache_netfs *netfs) + { + struct fscache_netfs *ptr; ++ struct fscache_cookie *cookie; + int ret; + + _enter("{%s}", netfs->name); +@@ -29,29 +30,25 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) + INIT_LIST_HEAD(&netfs->link); + + /* allocate a cookie for the primary index */ +- netfs->primary_index = +- kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL); ++ cookie = kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL); + +- if (!netfs->primary_index) { ++ if (!cookie) { + _leave(" = -ENOMEM"); + return -ENOMEM; + } + + /* initialise the primary index cookie */ +- atomic_set(&netfs->primary_index->usage, 1); +- atomic_set(&netfs->primary_index->n_children, 0); +- atomic_set(&netfs->primary_index->n_active, 1); ++ atomic_set(&cookie->usage, 1); ++ atomic_set(&cookie->n_children, 0); ++ atomic_set(&cookie->n_active, 1); + +- netfs->primary_index->def = &fscache_fsdef_netfs_def; +- netfs->primary_index->parent = &fscache_fsdef_index; +- netfs->primary_index->netfs_data = netfs; +- netfs->primary_index->flags = 1 << FSCACHE_COOKIE_ENABLED; ++ cookie->def = &fscache_fsdef_netfs_def; ++ cookie->parent = &fscache_fsdef_index; ++ cookie->netfs_data = netfs; ++ cookie->flags = 1 << FSCACHE_COOKIE_ENABLED; + +- atomic_inc(&netfs->primary_index->parent->usage); +- atomic_inc(&netfs->primary_index->parent->n_children); +- +- spin_lock_init(&netfs->primary_index->lock); +- INIT_HLIST_HEAD(&netfs->primary_index->backing_objects); ++ spin_lock_init(&cookie->lock); ++ INIT_HLIST_HEAD(&cookie->backing_objects); + + /* check the netfs type is not already present */ + down_write(&fscache_addremove_sem); +@@ -62,6 +59,10 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) + goto already_registered; + } + ++ atomic_inc(&cookie->parent->usage); ++ atomic_inc(&cookie->parent->n_children); ++ ++ netfs->primary_index = cookie; + list_add(&netfs->link, &fscache_netfs_list); + ret = 0; + +@@ -71,11 +72,8 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) + already_registered: + up_write(&fscache_addremove_sem); + +- if (ret < 0) { +- netfs->primary_index->parent = NULL; +- __fscache_cookie_put(netfs->primary_index); +- netfs->primary_index = NULL; +- } ++ if (ret < 0) ++ kmem_cache_free(fscache_cookie_jar, cookie); + + _leave(" = %d", ret); + return ret; +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index ecc57071a1a9..a8c65539fbd2 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -2066,6 +2066,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, + + if (!buffer_dirty(bh)) { + /* bdflush has written it. We can drop it now */ ++ __jbd2_journal_remove_checkpoint(jh); + goto zap_buffer; + } + +@@ -2095,6 +2096,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, + /* The orphan record's transaction has + * committed. We can cleanse this buffer */ + clear_buffer_jbddirty(bh); ++ __jbd2_journal_remove_checkpoint(jh); + goto zap_buffer; + } + } +diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c +index 1dd0bcc75536..96cbbe9e7030 100644 +--- a/fs/ocfs2/dlm/dlmmaster.c ++++ b/fs/ocfs2/dlm/dlmmaster.c +@@ -2459,6 +2459,11 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, + spin_lock(&dlm->master_lock); + ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name, + namelen, target, dlm->node_num); ++ /* get an extra reference on the mle. ++ * otherwise the assert_master from the new ++ * master will destroy this. ++ */ ++ dlm_get_mle_inuse(mle); + spin_unlock(&dlm->master_lock); + spin_unlock(&dlm->spinlock); + +@@ -2494,6 +2499,7 @@ fail: + if (mle_added) { + dlm_mle_detach_hb_events(dlm, mle); + dlm_put_mle(mle); ++ dlm_put_mle_inuse(mle); + } else if (mle) { + kmem_cache_free(dlm_mle_cache, mle); + mle = NULL; +@@ -2511,17 +2517,6 @@ fail: + * ensure that all assert_master work is flushed. */ + flush_workqueue(dlm->dlm_worker); + +- /* get an extra reference on the mle. +- * otherwise the assert_master from the new +- * master will destroy this. +- * also, make sure that all callers of dlm_get_mle +- * take both dlm->spinlock and dlm->master_lock */ +- spin_lock(&dlm->spinlock); +- spin_lock(&dlm->master_lock); +- dlm_get_mle_inuse(mle); +- spin_unlock(&dlm->master_lock); +- spin_unlock(&dlm->spinlock); +- + /* notify new node and send all lock state */ + /* call send_one_lockres with migration flag. + * this serves as notice to the target node that a +@@ -3246,6 +3241,15 @@ top: + mle->new_master != dead_node) + continue; + ++ if (mle->new_master == dead_node && mle->inuse) { ++ mlog(ML_NOTICE, "%s: target %u died during " ++ "migration from %u, the MLE is " ++ "still keep used, ignore it!\n", ++ dlm->name, dead_node, ++ mle->master); ++ continue; ++ } ++ + /* If we have reached this point, this mle needs to be + * removed from the list and freed. */ + dlm_clean_migration_mle(dlm, mle); +diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c +index fe29f7978f81..4b93d96d244f 100644 +--- a/fs/ocfs2/dlm/dlmrecovery.c ++++ b/fs/ocfs2/dlm/dlmrecovery.c +@@ -2332,6 +2332,8 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) + break; + } + } ++ dlm_lockres_clear_refmap_bit(dlm, res, ++ dead_node); + spin_unlock(&res->spinlock); + continue; + } +diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c +index cc0aeb9e81a2..5e260e14cdd6 100644 +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -340,13 +340,11 @@ static int ocfs2_mknod(struct inode *dir, + goto leave; + } + +- status = posix_acl_create(dir, &mode, &default_acl, &acl); ++ status = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); + if (status) { + mlog_errno(status); + goto leave; + } +- /* update inode->i_mode after mask with "umask". */ +- inode->i_mode = mode; + + handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, + S_ISDIR(mode), +diff --git a/fs/proc/fd.c b/fs/proc/fd.c +index 985ea881b5bc..c06a1f97ac22 100644 +--- a/fs/proc/fd.c ++++ b/fs/proc/fd.c +@@ -283,11 +283,19 @@ static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry, + */ + int proc_fd_permission(struct inode *inode, int mask) + { +- int rv = generic_permission(inode, mask); ++ struct task_struct *p; ++ int rv; ++ ++ rv = generic_permission(inode, mask); + if (rv == 0) +- return 0; +- if (task_tgid(current) == proc_pid(inode)) ++ return rv; ++ ++ rcu_read_lock(); ++ p = pid_task(proc_pid(inode), PIDTYPE_PID); ++ if (p && same_thread_group(p, current)) + rv = 0; ++ rcu_read_unlock(); ++ + return rv; + } + +diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c +index c327d4ee1235..7b3792e5844a 100644 +--- a/fs/sysv/inode.c ++++ b/fs/sysv/inode.c +@@ -161,14 +161,8 @@ void sysv_set_inode(struct inode *inode, dev_t rdev) + inode->i_fop = &sysv_dir_operations; + inode->i_mapping->a_ops = &sysv_aops; + } else if (S_ISLNK(inode->i_mode)) { +- if (inode->i_blocks) { +- inode->i_op = &sysv_symlink_inode_operations; +- inode->i_mapping->a_ops = &sysv_aops; +- } else { +- inode->i_op = &sysv_fast_symlink_inode_operations; +- nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size, +- sizeof(SYSV_I(inode)->i_data) - 1); +- } ++ inode->i_op = &sysv_symlink_inode_operations; ++ inode->i_mapping->a_ops = &sysv_aops; + } else + init_special_inode(inode, inode->i_mode, rdev); + } +diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h +index d61c11170213..2f38daaab3d7 100644 +--- a/include/crypto/if_alg.h ++++ b/include/crypto/if_alg.h +@@ -30,6 +30,8 @@ struct alg_sock { + + struct sock *parent; + ++ unsigned int refcnt; ++ + const struct af_alg_type *type; + void *private; + }; +@@ -64,6 +66,7 @@ int af_alg_register_type(const struct af_alg_type *type); + int af_alg_unregister_type(const struct af_alg_type *type); + + int af_alg_release(struct socket *sock); ++void af_alg_release_parent(struct sock *sk); + int af_alg_accept(struct sock *sk, struct socket *newsock); + + int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, +@@ -80,11 +83,6 @@ static inline struct alg_sock *alg_sk(struct sock *sk) + return (struct alg_sock *)sk; + } + +-static inline void af_alg_release_parent(struct sock *sk) +-{ +- sock_put(alg_sk(sk)->parent); +-} +- + static inline void af_alg_init_completion(struct af_alg_completion *completion) + { + init_completion(&completion->completion); +diff --git a/include/linux/signal.h b/include/linux/signal.h +index 2ac423bdb676..53944e50e421 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -247,7 +247,6 @@ extern int sigprocmask(int, sigset_t *, sigset_t *); + extern void set_current_blocked(sigset_t *); + extern void __set_current_blocked(const sigset_t *); + extern int show_unhandled_signals; +-extern int sigsuspend(sigset_t *); + + struct sigaction { + #ifndef __ARCH_HAS_IRIX_SIGACTION +diff --git a/kernel/signal.c b/kernel/signal.c +index 15c22ee11156..d8db156e5f5c 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -3550,7 +3550,7 @@ SYSCALL_DEFINE0(pause) + + #endif + +-int sigsuspend(sigset_t *set) ++static int sigsuspend(sigset_t *set) + { + current->saved_sigmask = current->blocked; + set_current_blocked(set); +diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c +index 2900817ba65c..7c8cef653166 100644 +--- a/kernel/trace/trace_printk.c ++++ b/kernel/trace/trace_printk.c +@@ -269,6 +269,7 @@ static const char **find_next(void *v, loff_t *pos) + if (*pos < last_index + start_index) + return __start___tracepoint_str + (*pos - last_index); + ++ start_index += last_index; + return find_next_mod_format(start_index, v, fmt, pos); + } + +diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h +index 49b582a225b0..b9897e2be404 100644 +--- a/scripts/recordmcount.h ++++ b/scripts/recordmcount.h +@@ -377,7 +377,7 @@ static void nop_mcount(Elf_Shdr const *const relhdr, + + if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { + if (make_nop) +- ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset); ++ ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset)); + if (warn_on_notrace_sect && !once) { + printf("Section %s has mcount callers being ignored\n", + txtname); +diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c +index 048550aacffc..596a2020fe2c 100644 +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -22,6 +22,7 @@ + #include <linux/evm.h> + #include <linux/magic.h> + #include <crypto/hash.h> ++#include <crypto/algapi.h> + #include "evm.h" + + int evm_initialized; +@@ -133,7 +134,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/compress_offload.c b/sound/core/compress_offload.c +index 7403f348ed14..91525fafe73b 100644 +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -44,6 +44,13 @@ + #include <sound/compress_offload.h> + #include <sound/compress_driver.h> + ++/* struct snd_compr_codec_caps overflows the ioctl bit size for some ++ * architectures, so we need to disable the relevant ioctls. ++ */ ++#if _IOC_SIZEBITS < 14 ++#define COMPR_CODEC_CAPS_OVERFLOW ++#endif ++ + /* TODO: + * - add substream support for multiple devices in case of + * SND_DYNAMIC_MINORS is not used +@@ -438,6 +445,7 @@ out: + return retval; + } + ++#ifndef COMPR_CODEC_CAPS_OVERFLOW + static int + snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg) + { +@@ -461,6 +469,7 @@ out: + kfree(caps); + return retval; + } ++#endif /* !COMPR_CODEC_CAPS_OVERFLOW */ + + /* revisit this with snd_pcm_preallocate_xxx */ + static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, +@@ -799,9 +808,11 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) + case _IOC_NR(SNDRV_COMPRESS_GET_CAPS): + retval = snd_compr_get_caps(stream, arg); + break; ++#ifndef COMPR_CODEC_CAPS_OVERFLOW + case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS): + retval = snd_compr_get_codec_caps(stream, arg); + break; ++#endif + case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS): + retval = snd_compr_set_params(stream, arg); + break; +diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c +index 4c1cc51772e6..7417f96cea6e 100644 +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_substream *substream, + return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); + } + +-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) ++static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, ++ bool trylock) + { + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hw_params *params, *sparams; +@@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) + struct snd_mask sformat_mask; + struct snd_mask mask; + +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ if (trylock) { ++ if (!(mutex_trylock(&runtime->oss.params_lock))) ++ return -EAGAIN; ++ } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) + return -EINTR; + sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); + params = kmalloc(sizeof(*params), GFP_KERNEL); +@@ -1091,7 +1095,7 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil + if (asubstream == NULL) + asubstream = substream; + if (substream->runtime->oss.params) { +- err = snd_pcm_oss_change_params(substream); ++ err = snd_pcm_oss_change_params(substream, false); + if (err < 0) + return err; + } +@@ -1130,7 +1134,7 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) + return 0; + runtime = substream->runtime; + if (runtime->oss.params) { +- err = snd_pcm_oss_change_params(substream); ++ err = snd_pcm_oss_change_params(substream, false); + if (err < 0) + return err; + } +@@ -2168,7 +2172,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre + runtime = substream->runtime; + + if (runtime->oss.params && +- (err = snd_pcm_oss_change_params(substream)) < 0) ++ (err = snd_pcm_oss_change_params(substream, false)) < 0) + return err; + + info.fragsize = runtime->oss.period_bytes; +@@ -2804,7 +2808,12 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) + return -EIO; + + if (runtime->oss.params) { +- if ((err = snd_pcm_oss_change_params(substream)) < 0) ++ /* use mutex_trylock() for params_lock for avoiding a deadlock ++ * between mmap_sem and params_lock taken by ++ * copy_from/to_user() in snd_pcm_oss_write/read() ++ */ ++ err = snd_pcm_oss_change_params(substream, true); ++ if (err < 0) + return err; + } + #ifdef CONFIG_SND_PCM_OSS_PLUGINS +diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c +index 7b596b5751db..500765f20843 100644 +--- a/sound/core/rawmidi.c ++++ b/sound/core/rawmidi.c +@@ -934,31 +934,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, + unsigned long flags; + long result = 0, count1; + struct snd_rawmidi_runtime *runtime = substream->runtime; ++ unsigned long appl_ptr; + ++ spin_lock_irqsave(&runtime->lock, flags); + while (count > 0 && runtime->avail) { + count1 = runtime->buffer_size - runtime->appl_ptr; + if (count1 > count) + count1 = count; +- spin_lock_irqsave(&runtime->lock, flags); + if (count1 > (int)runtime->avail) + count1 = runtime->avail; ++ ++ /* update runtime->appl_ptr before unlocking for userbuf */ ++ appl_ptr = runtime->appl_ptr; ++ runtime->appl_ptr += count1; ++ runtime->appl_ptr %= runtime->buffer_size; ++ runtime->avail -= count1; ++ + if (kernelbuf) +- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1); ++ memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1); + if (userbuf) { + spin_unlock_irqrestore(&runtime->lock, flags); + if (copy_to_user(userbuf + result, +- runtime->buffer + runtime->appl_ptr, count1)) { ++ runtime->buffer + appl_ptr, count1)) { + return result > 0 ? result : -EFAULT; + } + spin_lock_irqsave(&runtime->lock, flags); + } +- runtime->appl_ptr += count1; +- runtime->appl_ptr %= runtime->buffer_size; +- runtime->avail -= count1; +- spin_unlock_irqrestore(&runtime->lock, flags); + result += count1; + count -= count1; + } ++ spin_unlock_irqrestore(&runtime->lock, flags); + return result; + } + +@@ -1161,8 +1166,9 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, + unsigned long flags; + long count1, result; + struct snd_rawmidi_runtime *runtime = substream->runtime; ++ unsigned long appl_ptr; + +- if (snd_BUG_ON(!kernelbuf && !userbuf)) ++ if (!kernelbuf && !userbuf) + return -EINVAL; + if (snd_BUG_ON(!runtime->buffer)) + return -EINVAL; +@@ -1181,12 +1187,19 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, + count1 = count; + if (count1 > (long)runtime->avail) + count1 = runtime->avail; ++ ++ /* update runtime->appl_ptr before unlocking for userbuf */ ++ appl_ptr = runtime->appl_ptr; ++ runtime->appl_ptr += count1; ++ runtime->appl_ptr %= runtime->buffer_size; ++ runtime->avail -= count1; ++ + if (kernelbuf) +- memcpy(runtime->buffer + runtime->appl_ptr, ++ memcpy(runtime->buffer + appl_ptr, + kernelbuf + result, count1); + else if (userbuf) { + spin_unlock_irqrestore(&runtime->lock, flags); +- if (copy_from_user(runtime->buffer + runtime->appl_ptr, ++ if (copy_from_user(runtime->buffer + appl_ptr, + userbuf + result, count1)) { + spin_lock_irqsave(&runtime->lock, flags); + result = result > 0 ? result : -EFAULT; +@@ -1194,9 +1207,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, + } + spin_lock_irqsave(&runtime->lock, flags); + } +- runtime->appl_ptr += count1; +- runtime->appl_ptr %= runtime->buffer_size; +- runtime->avail -= count1; + result += count1; + count -= count1; + } +diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c +index c5b773a1eea9..4a09c3085ca4 100644 +--- a/sound/core/seq/oss/seq_oss_synth.c ++++ b/sound/core/seq/oss/seq_oss_synth.c +@@ -310,7 +310,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) + struct seq_oss_synth *rec; + struct seq_oss_synthinfo *info; + +- if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) ++ if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) + return; + for (i = 0; i < dp->max_synthdev; i++) { + info = &dp->synths[i]; +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index ecfbf5f39d38..08865dcbf5f1 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct snd_seq_client *client, + else + down_read(&grp->list_mutex); + list_for_each_entry(subs, &grp->list_head, src_list) { ++ /* both ports ready? */ ++ if (atomic_read(&subs->ref_count) != 2) ++ continue; + event->dest = subs->info.dest; + if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) + /* convert time according to flag with subscription */ +diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c +index 9516e5ce3aad..67c91d226552 100644 +--- a/sound/core/seq/seq_ports.c ++++ b/sound/core/seq/seq_ports.c +@@ -175,10 +175,6 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + } + + /* */ +-enum group_type { +- SRC_LIST, DEST_LIST +-}; +- + static int subscribe_port(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_port_subs_info *grp, +@@ -205,6 +201,20 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr, + return NULL; + } + ++static void delete_and_unsubscribe_port(struct snd_seq_client *client, ++ struct snd_seq_client_port *port, ++ struct snd_seq_subscribers *subs, ++ bool is_src, bool ack); ++ ++static inline struct snd_seq_subscribers * ++get_subscriber(struct list_head *p, bool is_src) ++{ ++ if (is_src) ++ return list_entry(p, struct snd_seq_subscribers, src_list); ++ else ++ return list_entry(p, struct snd_seq_subscribers, dest_list); ++} ++ + /* + * remove all subscribers on the list + * this is called from port_delete, for each src and dest list. +@@ -212,7 +222,7 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr, + static void clear_subscriber_list(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_port_subs_info *grp, +- int grptype) ++ int is_src) + { + struct list_head *p, *n; + +@@ -221,15 +231,13 @@ static void clear_subscriber_list(struct snd_seq_client *client, + struct snd_seq_client *c; + struct snd_seq_client_port *aport; + +- if (grptype == SRC_LIST) { +- subs = list_entry(p, struct snd_seq_subscribers, src_list); ++ subs = get_subscriber(p, is_src); ++ if (is_src) + aport = get_client_port(&subs->info.dest, &c); +- } else { +- subs = list_entry(p, struct snd_seq_subscribers, dest_list); ++ else + aport = get_client_port(&subs->info.sender, &c); +- } +- list_del(p); +- unsubscribe_port(client, port, grp, &subs->info, 0); ++ delete_and_unsubscribe_port(client, port, subs, is_src, false); ++ + if (!aport) { + /* looks like the connected port is being deleted. + * we decrease the counter, and when both ports are deleted +@@ -237,21 +245,14 @@ static void clear_subscriber_list(struct snd_seq_client *client, + */ + if (atomic_dec_and_test(&subs->ref_count)) + kfree(subs); +- } else { +- /* ok we got the connected port */ +- struct snd_seq_port_subs_info *agrp; +- agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src; +- down_write(&agrp->list_mutex); +- if (grptype == SRC_LIST) +- list_del(&subs->dest_list); +- else +- list_del(&subs->src_list); +- up_write(&agrp->list_mutex); +- unsubscribe_port(c, aport, agrp, &subs->info, 1); +- kfree(subs); +- snd_seq_port_unlock(aport); +- snd_seq_client_unlock(c); ++ continue; + } ++ ++ /* ok we got the connected port */ ++ delete_and_unsubscribe_port(c, aport, subs, !is_src, true); ++ kfree(subs); ++ snd_seq_port_unlock(aport); ++ snd_seq_client_unlock(c); + } + } + +@@ -264,8 +265,8 @@ static int port_delete(struct snd_seq_client *client, + snd_use_lock_sync(&port->use_lock); + + /* clear subscribers info */ +- clear_subscriber_list(client, port, &port->c_src, SRC_LIST); +- clear_subscriber_list(client, port, &port->c_dest, DEST_LIST); ++ clear_subscriber_list(client, port, &port->c_src, true); ++ clear_subscriber_list(client, port, &port->c_dest, false); + + if (port->private_free) + port->private_free(port->private_data); +@@ -484,85 +485,120 @@ static int match_subs_info(struct snd_seq_port_subscribe *r, + return 0; + } + +- +-/* connect two ports */ +-int snd_seq_port_connect(struct snd_seq_client *connector, +- struct snd_seq_client *src_client, +- struct snd_seq_client_port *src_port, +- struct snd_seq_client *dest_client, +- struct snd_seq_client_port *dest_port, +- struct snd_seq_port_subscribe *info) ++static int check_and_subscribe_port(struct snd_seq_client *client, ++ struct snd_seq_client_port *port, ++ struct snd_seq_subscribers *subs, ++ bool is_src, bool exclusive, bool ack) + { +- struct snd_seq_port_subs_info *src = &src_port->c_src; +- struct snd_seq_port_subs_info *dest = &dest_port->c_dest; +- struct snd_seq_subscribers *subs, *s; +- int err, src_called = 0; +- unsigned long flags; +- int exclusive; ++ struct snd_seq_port_subs_info *grp; ++ struct list_head *p; ++ struct snd_seq_subscribers *s; ++ int err; + +- subs = kzalloc(sizeof(*subs), GFP_KERNEL); +- if (! subs) +- return -ENOMEM; +- +- subs->info = *info; +- atomic_set(&subs->ref_count, 2); +- +- down_write(&src->list_mutex); +- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); +- +- exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0; ++ grp = is_src ? &port->c_src : &port->c_dest; + err = -EBUSY; ++ down_write(&grp->list_mutex); + if (exclusive) { +- if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head)) ++ if (!list_empty(&grp->list_head)) + goto __error; + } else { +- if (src->exclusive || dest->exclusive) ++ if (grp->exclusive) + goto __error; + /* check whether already exists */ +- list_for_each_entry(s, &src->list_head, src_list) { +- if (match_subs_info(info, &s->info)) +- goto __error; +- } +- list_for_each_entry(s, &dest->list_head, dest_list) { +- if (match_subs_info(info, &s->info)) ++ list_for_each(p, &grp->list_head) { ++ s = get_subscriber(p, is_src); ++ if (match_subs_info(&subs->info, &s->info)) + goto __error; + } + } + +- if ((err = subscribe_port(src_client, src_port, src, info, +- connector->number != src_client->number)) < 0) +- goto __error; +- src_called = 1; +- +- if ((err = subscribe_port(dest_client, dest_port, dest, info, +- connector->number != dest_client->number)) < 0) ++ err = subscribe_port(client, port, grp, &subs->info, ack); ++ if (err < 0) { ++ grp->exclusive = 0; + goto __error; ++ } + + /* add to list */ +- write_lock_irqsave(&src->list_lock, flags); +- // write_lock(&dest->list_lock); // no other lock yet +- list_add_tail(&subs->src_list, &src->list_head); +- list_add_tail(&subs->dest_list, &dest->list_head); +- // write_unlock(&dest->list_lock); // no other lock yet +- write_unlock_irqrestore(&src->list_lock, flags); ++ write_lock_irq(&grp->list_lock); ++ if (is_src) ++ list_add_tail(&subs->src_list, &grp->list_head); ++ else ++ list_add_tail(&subs->dest_list, &grp->list_head); ++ grp->exclusive = exclusive; ++ atomic_inc(&subs->ref_count); ++ write_unlock_irq(&grp->list_lock); ++ err = 0; ++ ++ __error: ++ up_write(&grp->list_mutex); ++ return err; ++} + +- src->exclusive = dest->exclusive = exclusive; ++static void delete_and_unsubscribe_port(struct snd_seq_client *client, ++ struct snd_seq_client_port *port, ++ struct snd_seq_subscribers *subs, ++ bool is_src, bool ack) ++{ ++ struct snd_seq_port_subs_info *grp; ++ ++ grp = is_src ? &port->c_src : &port->c_dest; ++ 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); ++ grp->exclusive = 0; ++ write_unlock_irq(&grp->list_lock); ++ up_write(&grp->list_mutex); ++ ++ unsubscribe_port(client, port, grp, &subs->info, ack); ++} ++ ++/* connect two ports */ ++int snd_seq_port_connect(struct snd_seq_client *connector, ++ struct snd_seq_client *src_client, ++ struct snd_seq_client_port *src_port, ++ struct snd_seq_client *dest_client, ++ struct snd_seq_client_port *dest_port, ++ struct snd_seq_port_subscribe *info) ++{ ++ struct snd_seq_subscribers *subs; ++ bool exclusive; ++ int err; ++ ++ subs = kzalloc(sizeof(*subs), GFP_KERNEL); ++ if (!subs) ++ return -ENOMEM; ++ ++ subs->info = *info; ++ atomic_set(&subs->ref_count, 0); ++ INIT_LIST_HEAD(&subs->src_list); ++ INIT_LIST_HEAD(&subs->dest_list); ++ ++ exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE); ++ ++ err = check_and_subscribe_port(src_client, src_port, subs, true, ++ exclusive, ++ connector->number != src_client->number); ++ if (err < 0) ++ goto error; ++ err = check_and_subscribe_port(dest_client, dest_port, subs, false, ++ exclusive, ++ connector->number != dest_client->number); ++ if (err < 0) ++ goto error_dest; + +- up_write(&dest->list_mutex); +- up_write(&src->list_mutex); + return 0; + +- __error: +- if (src_called) +- unsubscribe_port(src_client, src_port, src, info, +- connector->number != src_client->number); ++ error_dest: ++ delete_and_unsubscribe_port(src_client, src_port, subs, true, ++ connector->number != src_client->number); ++ error: + kfree(subs); +- up_write(&dest->list_mutex); +- up_write(&src->list_mutex); + return err; + } + +- + /* remove the connection */ + int snd_seq_port_disconnect(struct snd_seq_client *connector, + struct snd_seq_client *src_client, +@@ -572,37 +608,28 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector, + struct snd_seq_port_subscribe *info) + { + struct snd_seq_port_subs_info *src = &src_port->c_src; +- struct snd_seq_port_subs_info *dest = &dest_port->c_dest; + struct snd_seq_subscribers *subs; + int err = -ENOENT; +- unsigned long flags; + + down_write(&src->list_mutex); +- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); +- + /* look for the connection */ + list_for_each_entry(subs, &src->list_head, src_list) { + if (match_subs_info(info, &subs->info)) { +- write_lock_irqsave(&src->list_lock, flags); +- // write_lock(&dest->list_lock); // no lock yet +- list_del(&subs->src_list); +- list_del(&subs->dest_list); +- // write_unlock(&dest->list_lock); +- write_unlock_irqrestore(&src->list_lock, flags); +- src->exclusive = dest->exclusive = 0; +- unsubscribe_port(src_client, src_port, src, info, +- connector->number != src_client->number); +- unsubscribe_port(dest_client, dest_port, dest, info, +- connector->number != dest_client->number); +- kfree(subs); ++ atomic_dec(&subs->ref_count); /* mark as not ready */ + err = 0; + break; + } + } +- +- up_write(&dest->list_mutex); + up_write(&src->list_mutex); +- return err; ++ if (err < 0) ++ return err; ++ ++ delete_and_unsubscribe_port(src_client, src_port, subs, true, ++ connector->number != src_client->number); ++ delete_and_unsubscribe_port(dest_client, dest_port, subs, false, ++ connector->number != dest_client->number); ++ kfree(subs); ++ return 0; + } + + +diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c +index 24d44b2f61ac..6ec30a98a92a 100644 +--- a/sound/core/seq/seq_timer.c ++++ b/sound/core/seq/seq_timer.c +@@ -92,6 +92,9 @@ void snd_seq_timer_delete(struct snd_seq_timer **tmr) + + void snd_seq_timer_defaults(struct snd_seq_timer * tmr) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tmr->lock, flags); + /* setup defaults */ + tmr->ppq = 96; /* 96 PPQ */ + tmr->tempo = 500000; /* 120 BPM */ +@@ -107,21 +110,25 @@ void snd_seq_timer_defaults(struct snd_seq_timer * tmr) + tmr->preferred_resolution = seq_default_timer_resolution; + + tmr->skew = tmr->skew_base = SKEW_BASE; ++ spin_unlock_irqrestore(&tmr->lock, flags); + } + +-void snd_seq_timer_reset(struct snd_seq_timer * tmr) ++static void seq_timer_reset(struct snd_seq_timer *tmr) + { +- unsigned long flags; +- +- spin_lock_irqsave(&tmr->lock, flags); +- + /* reset time & songposition */ + tmr->cur_time.tv_sec = 0; + tmr->cur_time.tv_nsec = 0; + + tmr->tick.cur_tick = 0; + tmr->tick.fraction = 0; ++} ++ ++void snd_seq_timer_reset(struct snd_seq_timer *tmr) ++{ ++ unsigned long flags; + ++ spin_lock_irqsave(&tmr->lock, flags); ++ seq_timer_reset(tmr); + spin_unlock_irqrestore(&tmr->lock, flags); + } + +@@ -140,8 +147,11 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri, + tmr = q->timer; + if (tmr == NULL) + return; +- if (!tmr->running) ++ spin_lock_irqsave(&tmr->lock, flags); ++ if (!tmr->running) { ++ spin_unlock_irqrestore(&tmr->lock, flags); + return; ++ } + + resolution *= ticks; + if (tmr->skew != tmr->skew_base) { +@@ -150,8 +160,6 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri, + (((resolution & 0xffff) * tmr->skew) >> 16); + } + +- spin_lock_irqsave(&tmr->lock, flags); +- + /* update timer */ + snd_seq_inc_time_nsec(&tmr->cur_time, resolution); + +@@ -298,26 +306,30 @@ int snd_seq_timer_open(struct snd_seq_queue *q) + t->callback = snd_seq_timer_interrupt; + t->callback_data = q; + t->flags |= SNDRV_TIMER_IFLG_AUTO; ++ spin_lock_irq(&tmr->lock); + tmr->timeri = t; ++ spin_unlock_irq(&tmr->lock); + return 0; + } + + int snd_seq_timer_close(struct snd_seq_queue *q) + { + struct snd_seq_timer *tmr; ++ struct snd_timer_instance *t; + + tmr = q->timer; + if (snd_BUG_ON(!tmr)) + return -EINVAL; +- if (tmr->timeri) { +- snd_timer_stop(tmr->timeri); +- snd_timer_close(tmr->timeri); +- tmr->timeri = NULL; +- } ++ spin_lock_irq(&tmr->lock); ++ t = tmr->timeri; ++ tmr->timeri = NULL; ++ spin_unlock_irq(&tmr->lock); ++ if (t) ++ snd_timer_close(t); + return 0; + } + +-int snd_seq_timer_stop(struct snd_seq_timer * tmr) ++static int seq_timer_stop(struct snd_seq_timer *tmr) + { + if (! tmr->timeri) + return -EINVAL; +@@ -328,6 +340,17 @@ int snd_seq_timer_stop(struct snd_seq_timer * tmr) + return 0; + } + ++int snd_seq_timer_stop(struct snd_seq_timer *tmr) ++{ ++ unsigned long flags; ++ int err; ++ ++ spin_lock_irqsave(&tmr->lock, flags); ++ err = seq_timer_stop(tmr); ++ spin_unlock_irqrestore(&tmr->lock, flags); ++ return err; ++} ++ + static int initialize_timer(struct snd_seq_timer *tmr) + { + struct snd_timer *t; +@@ -360,13 +383,13 @@ static int initialize_timer(struct snd_seq_timer *tmr) + return 0; + } + +-int snd_seq_timer_start(struct snd_seq_timer * tmr) ++static int seq_timer_start(struct snd_seq_timer *tmr) + { + if (! tmr->timeri) + return -EINVAL; + if (tmr->running) +- snd_seq_timer_stop(tmr); +- snd_seq_timer_reset(tmr); ++ seq_timer_stop(tmr); ++ seq_timer_reset(tmr); + if (initialize_timer(tmr) < 0) + return -EINVAL; + snd_timer_start(tmr->timeri, tmr->ticks); +@@ -375,14 +398,25 @@ int snd_seq_timer_start(struct snd_seq_timer * tmr) + return 0; + } + +-int snd_seq_timer_continue(struct snd_seq_timer * tmr) ++int snd_seq_timer_start(struct snd_seq_timer *tmr) ++{ ++ unsigned long flags; ++ int err; ++ ++ spin_lock_irqsave(&tmr->lock, flags); ++ err = seq_timer_start(tmr); ++ spin_unlock_irqrestore(&tmr->lock, flags); ++ return err; ++} ++ ++static int seq_timer_continue(struct snd_seq_timer *tmr) + { + if (! tmr->timeri) + return -EINVAL; + if (tmr->running) + return -EBUSY; + if (! tmr->initialized) { +- snd_seq_timer_reset(tmr); ++ seq_timer_reset(tmr); + if (initialize_timer(tmr) < 0) + return -EINVAL; + } +@@ -392,11 +426,24 @@ int snd_seq_timer_continue(struct snd_seq_timer * tmr) + return 0; + } + ++int snd_seq_timer_continue(struct snd_seq_timer *tmr) ++{ ++ unsigned long flags; ++ int err; ++ ++ spin_lock_irqsave(&tmr->lock, flags); ++ err = seq_timer_continue(tmr); ++ spin_unlock_irqrestore(&tmr->lock, flags); ++ return err; ++} ++ + /* return current 'real' time. use timeofday() to get better granularity. */ + snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) + { + snd_seq_real_time_t cur_time; ++ unsigned long flags; + ++ spin_lock_irqsave(&tmr->lock, flags); + cur_time = tmr->cur_time; + if (tmr->running) { + struct timeval tm; +@@ -412,7 +459,7 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) + } + snd_seq_sanity_real_time(&cur_time); + } +- ++ spin_unlock_irqrestore(&tmr->lock, flags); + return cur_time; + } + +diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c +index 4b50e604276d..0fa691e01384 100644 +--- a/sound/core/seq/seq_virmidi.c ++++ b/sound/core/seq/seq_virmidi.c +@@ -254,9 +254,13 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream) + */ + static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) + { ++ struct snd_virmidi_dev *rdev = substream->rmidi->private_data; + struct snd_virmidi *vmidi = substream->runtime->private_data; +- snd_midi_event_free(vmidi->parser); ++ ++ write_lock_irq(&rdev->filelist_lock); + list_del(&vmidi->list); ++ write_unlock_irq(&rdev->filelist_lock); ++ snd_midi_event_free(vmidi->parser); + substream->runtime->private_data = NULL; + kfree(vmidi); + return 0; +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 4e436fe53afa..d90d8f4b85fe 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -300,8 +300,7 @@ int snd_timer_open(struct snd_timer_instance **ti, + return 0; + } + +-static int _snd_timer_stop(struct snd_timer_instance *timeri, +- int keep_flag, int event); ++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event); + + /* + * close a timer instance +@@ -343,7 +342,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) + spin_unlock_irq(&timer->lock); + mutex_lock(®ister_mutex); + list_del(&timeri->open_list); +- if (timer && list_empty(&timer->open_list_head) && ++ if (list_empty(&timer->open_list_head) && + timer->hw.close) + timer->hw.close(timer); + /* remove slave links */ +@@ -415,7 +414,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); + } + +@@ -444,6 +443,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri) + unsigned long flags; + + spin_lock_irqsave(&slave_active_lock, flags); ++ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { ++ spin_unlock_irqrestore(&slave_active_lock, flags); ++ return -EBUSY; ++ } + timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; + if (timeri->master && timeri->timer) { + spin_lock(&timeri->timer->lock); +@@ -468,23 +471,30 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) + return -EINVAL; + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { + result = snd_timer_start_slave(timeri); +- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); ++ if (result >= 0) ++ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); + return result; + } + timer = timeri->timer; + if (timer == NULL) + return -EINVAL; + spin_lock_irqsave(&timer->lock, flags); ++ if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | ++ SNDRV_TIMER_IFLG_START)) { ++ result = -EBUSY; ++ goto unlock; ++ } + timeri->ticks = timeri->cticks = ticks; + timeri->pticks = 0; + result = snd_timer_start1(timer, timeri, ticks); ++ unlock: + spin_unlock_irqrestore(&timer->lock, flags); +- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); ++ if (result >= 0) ++ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); + return result; + } + +-static int _snd_timer_stop(struct snd_timer_instance * timeri, +- int keep_flag, int event) ++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) + { + struct snd_timer *timer; + unsigned long flags; +@@ -493,19 +503,30 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, + return -ENXIO; + + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { +- if (!keep_flag) { +- spin_lock_irqsave(&slave_active_lock, flags); +- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; +- list_del_init(&timeri->ack_list); +- list_del_init(&timeri->active_list); ++ spin_lock_irqsave(&slave_active_lock, flags); ++ if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { + 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; + } + timer = timeri->timer; + if (!timer) + return -EINVAL; + spin_lock_irqsave(&timer->lock, flags); ++ if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | ++ SNDRV_TIMER_IFLG_START))) { ++ spin_unlock_irqrestore(&timer->lock, flags); ++ return -EBUSY; ++ } + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); + if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && +@@ -520,9 +541,7 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, + } + } + } +- if (!keep_flag) +- timeri->flags &= +- ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); ++ timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); + spin_unlock_irqrestore(&timer->lock, flags); + __end: + if (event != SNDRV_TIMER_EVENT_RESOLUTION) +@@ -541,7 +560,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri) + unsigned long flags; + int err; + +- err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP); ++ err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP); + if (err < 0) + return err; + timer = timeri->timer; +@@ -571,10 +590,15 @@ int snd_timer_continue(struct snd_timer_instance *timeri) + if (! timer) + return -EINVAL; + spin_lock_irqsave(&timer->lock, flags); ++ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { ++ result = -EBUSY; ++ goto unlock; ++ } + if (!timeri->cticks) + timeri->cticks = 1; + timeri->pticks = 0; + result = snd_timer_start1(timer, timeri, timer->sticks); ++ unlock: + spin_unlock_irqrestore(&timer->lock, flags); + snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE); + return result; +@@ -585,7 +609,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri) + */ + int snd_timer_pause(struct snd_timer_instance * timeri) + { +- return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE); ++ return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE); + } + + /* +@@ -702,8 +726,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) + ti->cticks = ti->ticks; + } else { + ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; +- if (--timer->running) +- list_del_init(&ti->active_list); ++ --timer->running; ++ list_del_init(&ti->active_list); + } + if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || + (ti->flags & SNDRV_TIMER_IFLG_FAST)) +diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c +index 915b4d7fbb23..8946cef245fc 100644 +--- a/sound/drivers/dummy.c ++++ b/sound/drivers/dummy.c +@@ -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; +@@ -368,6 +372,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; +@@ -494,31 +500,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 = { +@@ -564,17 +564,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) { +@@ -596,7 +598,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; +@@ -604,8 +606,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/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index 3c90743fa50b..eef182bea2ad 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -617,6 +617,7 @@ enum { + CS4208_MAC_AUTO, + CS4208_MBA6, + CS4208_MBP11, ++ CS4208_MACMINI, + CS4208_GPIO0, + }; + +@@ -624,6 +625,7 @@ static const struct hda_model_fixup cs4208_models[] = { + { .id = CS4208_GPIO0, .name = "gpio0" }, + { .id = CS4208_MBA6, .name = "mba6" }, + { .id = CS4208_MBP11, .name = "mbp11" }, ++ { .id = CS4208_MACMINI, .name = "macmini" }, + {} + }; + +@@ -635,6 +637,7 @@ static const struct snd_pci_quirk cs4208_fixup_tbl[] = { + /* codec SSID matching */ + static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11), ++ SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI), + SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6), + SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6), + SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11), +@@ -667,6 +670,24 @@ static void cs4208_fixup_mac(struct hda_codec *codec, + snd_hda_apply_fixup(codec, action); + } + ++/* MacMini 7,1 has the inverted jack detection */ ++static void cs4208_fixup_macmini(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ static const struct hda_pintbl pincfgs[] = { ++ { 0x18, 0x00ab9150 }, /* mic (audio-in) jack: disable detect */ ++ { 0x21, 0x004be140 }, /* SPDIF: disable detect */ ++ { } ++ }; ++ ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) { ++ /* HP pin (0x10) has an inverted detection */ ++ codec->inv_jack_detect = 1; ++ /* disable the bogus Mic and SPDIF jack detections */ ++ snd_hda_apply_pincfgs(codec, pincfgs); ++ } ++} ++ + static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +@@ -710,6 +731,12 @@ static const struct hda_fixup cs4208_fixups[] = { + .chained = true, + .chain_id = CS4208_GPIO0, + }, ++ [CS4208_MACMINI] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = cs4208_fixup_macmini, ++ .chained = true, ++ .chain_id = CS4208_GPIO0, ++ }, + [CS4208_GPIO0] = { + .type = HDA_FIXUP_FUNC, + .v.func = cs4208_fixup_gpio0, +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 611110a3f1a4..55ce39df9cd7 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -426,7 +426,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; +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index bd0b986f7d50..eeb5b68e9e3e 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2266,6 +2266,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), +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index e28704e1274a..431a89b75ff3 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1404,7 +1404,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 9123fc518f07..424c1e874bd3 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -2365,7 +2365,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; + } + +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 901f87dea827..9a599b1bc6ba 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1128,8 +1128,12 @@ void snd_usb_set_interface_quirk(struct usb_device *dev) + * "Playback Design" products need a 50ms delay after setting the + * USB interface. + */ +- if (le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) ++ switch (le16_to_cpu(dev->descriptor.idVendor)) { ++ case 0x23ba: /* Playback Design */ ++ case 0x0644: /* TEAC Corp. */ + mdelay(50); ++ break; ++ } + } + + void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, +@@ -1144,6 +1148,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + mdelay(20); + ++ /* ++ * "TEAC Corp." products need a 20ms delay after each ++ * class compliant request ++ */ ++ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) && ++ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) ++ mdelay(20); ++ + /* Marantz/Denon devices with USB DAC functionality need a delay + * after each class compliant request + */ |