commit:     b9305a6beafce412577420e88ff20213fd71c7f0
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun Jan 31 23:15:32 2016 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun Jan 31 23:15:32 2016 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b9305a6b

Linux Patch 3.10.96

 0000_README              |    4 +
 1095_linux-3.10.96.patch | 1497 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1501 insertions(+)

diff --git a/0000_README b/0000_README
index 0edba9c..19931f8 100644
--- a/0000_README
+++ b/0000_README
@@ -422,6 +422,10 @@ Patch:  1094_linux-3.10.95.patch
 From:   http://www.kernel.org
 Desc:   Linux 3.10.95
 
+Patch:  1095_linux-3.10.96.patch
+From:   http://www.kernel.org
+Desc:   Linux 3.10.96
+
 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/1095_linux-3.10.96.patch b/1095_linux-3.10.96.patch
new file mode 100644
index 0000000..6c35ece
--- /dev/null
+++ b/1095_linux-3.10.96.patch
@@ -0,0 +1,1497 @@
+diff --git a/Makefile b/Makefile
+index eb120001bc12..c88ea5d8d19c 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 3
+ PATCHLEVEL = 10
+-SUBLEVEL = 95
++SUBLEVEL = 96
+ EXTRAVERSION =
+ NAME = TOSSUG Baby Fish
+ 
+diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
+index 33a74fc45959..dfad98fda4f8 100644
+--- a/arch/arm64/kernel/ptrace.c
++++ b/arch/arm64/kernel/ptrace.c
+@@ -51,6 +51,12 @@
+  */
+ void ptrace_disable(struct task_struct *child)
+ {
++      /*
++       * This would be better off in core code, but PTRACE_DETACH has
++       * grown its fair share of arch-specific worts and changing it
++       * is likely to cause regressions on obscure architectures.
++       */
++      user_disable_single_step(child);
+ }
+ 
+ /*
+diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
+index ba7477efad5c..5b77586ef0af 100644
+--- a/arch/arm64/mm/mmu.c
++++ b/arch/arm64/mm/mmu.c
+@@ -348,6 +348,9 @@ void __init paging_init(void)
+ 
+       empty_zero_page = virt_to_page(zero_page);
+ 
++      /* Ensure the zero page is visible to the page table walker */
++      dsb();
++
+       /*
+        * TTBR0 is only used for the identity mapping at this stage. Make it
+        * point to zero page to avoid speculatively fetching new entries.
+diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
+index 428da175d073..31b91602f055 100644
+--- a/arch/mn10300/Kconfig
++++ b/arch/mn10300/Kconfig
+@@ -2,6 +2,7 @@ config MN10300
+       def_bool y
+       select HAVE_OPROFILE
+       select HAVE_GENERIC_HARDIRQS
++      select HAVE_UID16
+       select GENERIC_IRQ_SHOW
+       select ARCH_WANT_IPC_PARSE_VERSION
+       select HAVE_ARCH_TRACEHOOK
+@@ -37,9 +38,6 @@ config HIGHMEM
+ config NUMA
+       def_bool n
+ 
+-config UID16
+-      def_bool y
+-
+ config RWSEM_GENERIC_SPINLOCK
+       def_bool y
+ 
+diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
+index 1072bfd18c50..f4dd44a7118f 100644
+--- a/arch/openrisc/Kconfig
++++ b/arch/openrisc/Kconfig
+@@ -17,6 +17,7 @@ config OPENRISC
+       select GENERIC_IRQ_SHOW
+       select GENERIC_IOMAP
+       select GENERIC_CPU_DEVICES
++      select HAVE_UID16
+       select GENERIC_ATOMIC64
+       select GENERIC_CLOCKEVENTS
+       select GENERIC_STRNCPY_FROM_USER
+@@ -29,9 +30,6 @@ config MMU
+ config HAVE_DMA_ATTRS
+       def_bool y
+ 
+-config UID16
+-      def_bool y
+-
+ config RWSEM_GENERIC_SPINLOCK
+       def_bool y
+ 
+diff --git a/arch/powerpc/include/asm/cmpxchg.h 
b/arch/powerpc/include/asm/cmpxchg.h
+index e245aab7f191..95b515113186 100644
+--- a/arch/powerpc/include/asm/cmpxchg.h
++++ b/arch/powerpc/include/asm/cmpxchg.h
+@@ -18,12 +18,12 @@ __xchg_u32(volatile void *p, unsigned long val)
+       unsigned long prev;
+ 
+       __asm__ __volatile__(
+-      PPC_RELEASE_BARRIER
++      PPC_ATOMIC_ENTRY_BARRIER
+ "1:   lwarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+ "     stwcx.  %3,0,%2 \n\
+       bne-    1b"
+-      PPC_ACQUIRE_BARRIER
++      PPC_ATOMIC_EXIT_BARRIER
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+@@ -61,12 +61,12 @@ __xchg_u64(volatile void *p, unsigned long val)
+       unsigned long prev;
+ 
+       __asm__ __volatile__(
+-      PPC_RELEASE_BARRIER
++      PPC_ATOMIC_ENTRY_BARRIER
+ "1:   ldarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+ "     stdcx.  %3,0,%2 \n\
+       bne-    1b"
+-      PPC_ACQUIRE_BARRIER
++      PPC_ATOMIC_EXIT_BARRIER
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+@@ -152,14 +152,14 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long 
old, unsigned long new)
+       unsigned int prev;
+ 
+       __asm__ __volatile__ (
+-      PPC_RELEASE_BARRIER
++      PPC_ATOMIC_ENTRY_BARRIER
+ "1:   lwarx   %0,0,%2         # __cmpxchg_u32\n\
+       cmpw    0,%0,%3\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%2)
+ "     stwcx.  %4,0,%2\n\
+       bne-    1b"
+-      PPC_ACQUIRE_BARRIER
++      PPC_ATOMIC_EXIT_BARRIER
+       "\n\
+ 2:"
+       : "=&r" (prev), "+m" (*p)
+@@ -198,13 +198,13 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long 
old, unsigned long new)
+       unsigned long prev;
+ 
+       __asm__ __volatile__ (
+-      PPC_RELEASE_BARRIER
++      PPC_ATOMIC_ENTRY_BARRIER
+ "1:   ldarx   %0,0,%2         # __cmpxchg_u64\n\
+       cmpd    0,%0,%3\n\
+       bne-    2f\n\
+       stdcx.  %4,0,%2\n\
+       bne-    1b"
+-      PPC_ACQUIRE_BARRIER
++      PPC_ATOMIC_EXIT_BARRIER
+       "\n\
+ 2:"
+       : "=&r" (prev), "+m" (*p)
+diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
+index 795f67792ea9..60c31698f7d5 100644
+--- a/arch/powerpc/include/asm/reg.h
++++ b/arch/powerpc/include/asm/reg.h
+@@ -108,6 +108,7 @@
+ #define MSR_TS_T      __MASK(MSR_TS_T_LG)     /*  Transaction Transactional */
+ #define MSR_TS_MASK   (MSR_TS_T | MSR_TS_S)   /* Transaction State bits */
+ #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */
++#define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */
+ #define MSR_TM_TRANSACTIONAL(x)       (((x) & MSR_TS_MASK) == MSR_TS_T)
+ #define MSR_TM_SUSPENDED(x)   (((x) & MSR_TS_MASK) == MSR_TS_S)
+ 
+diff --git a/arch/powerpc/include/asm/synch.h 
b/arch/powerpc/include/asm/synch.h
+index e682a7143edb..c50868681f9e 100644
+--- a/arch/powerpc/include/asm/synch.h
++++ b/arch/powerpc/include/asm/synch.h
+@@ -44,7 +44,7 @@ static inline void isync(void)
+       MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
+ #define PPC_ACQUIRE_BARRIER    "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
+ #define PPC_RELEASE_BARRIER    stringify_in_c(LWSYNC) "\n"
+-#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
++#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(sync) "\n"
+ #define PPC_ATOMIC_EXIT_BARRIER        "\n" stringify_in_c(sync) "\n"
+ #else
+ #define PPC_ACQUIRE_BARRIER
+diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
+index d9b673b06757..8220ae86252c 100644
+--- a/arch/powerpc/kernel/signal_32.c
++++ b/arch/powerpc/kernel/signal_32.c
+@@ -858,6 +858,15 @@ static long restore_tm_user_regs(struct pt_regs *regs,
+               return 1;
+ #endif /* CONFIG_SPE */
+ 
++      /* Get the top half of the MSR from the user context */
++      if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
++              return 1;
++      msr_hi <<= 32;
++      /* If TM bits are set to the reserved value, it's an invalid context */
++      if (MSR_TM_RESV(msr_hi))
++              return 1;
++      /* Pull in the MSR TM bits from the user context */
++      regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK);
+       /* Now, recheckpoint.  This loads up all of the checkpointed (older)
+        * registers, including FP and V[S]Rs.  After recheckpointing, the
+        * transactional versions should be loaded.
+@@ -867,11 +876,6 @@ static long restore_tm_user_regs(struct pt_regs *regs,
+       current->thread.tm_texasr |= TEXASR_FS;
+       /* This loads the checkpointed FP/VEC state, if used */
+       tm_recheckpoint(&current->thread, msr);
+-      /* Get the top half of the MSR */
+-      if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
+-              return 1;
+-      /* Pull in MSR TM from user context */
+-      regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK);
+ 
+       /* This loads the speculative FP/VEC state, if used */
+       if (msr & MSR_FP) {
+diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
+index 74d9615a6bb6..2419c17538e2 100644
+--- a/arch/powerpc/kernel/signal_64.c
++++ b/arch/powerpc/kernel/signal_64.c
+@@ -416,6 +416,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
+ 
+       /* get MSR separately, transfer the LE bit if doing signal return */
+       err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
++      /* Don't allow reserved mode. */
++      if (MSR_TM_RESV(msr))
++              return -EINVAL;
++
+       /* pull in MSR TM from user context */
+       regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
+ 
+diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
+index 102ad8a255f3..466fbd54e7f8 100644
+--- a/arch/powerpc/kvm/book3s_hv.c
++++ b/arch/powerpc/kvm/book3s_hv.c
+@@ -160,6 +160,12 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
+ 
+ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
+ {
++      /*
++       * Check for illegal transactional state bit combination
++       * and if we find it, force the TS field to a safe state.
++       */
++      if ((msr & MSR_TS_MASK) == MSR_TS_MASK)
++              msr &= ~MSR_TS_MASK;
+       vcpu->arch.shregs.msr = msr;
+       kvmppc_end_cede(vcpu);
+ }
+diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
+index 4fa687a47a62..6b8d6e8cd449 100644
+--- a/arch/x86/include/asm/boot.h
++++ b/arch/x86/include/asm/boot.h
+@@ -27,7 +27,7 @@
+ #define BOOT_HEAP_SIZE             0x400000
+ #else /* !CONFIG_KERNEL_BZIP2 */
+ 
+-#define BOOT_HEAP_SIZE        0x8000
++#define BOOT_HEAP_SIZE        0x10000
+ 
+ #endif /* !CONFIG_KERNEL_BZIP2 */
+ 
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index 90fd1195f276..abfc89b3b55a 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -366,6 +366,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] 
= {
+                       DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
+               },
+       },
++      {       /* Handle problems with rebooting on the iMac10,1. */
++              .callback = set_pci_reboot,
++              .ident = "Apple iMac10,1",
++              .matches = {
++                  DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++                  DMI_MATCH(DMI_PRODUCT_NAME, "iMac10,1"),
++              },
++      },
+ 
+       {       /* Handle reboot issue on Acer Aspire one */
+               .callback = set_kbd_reboot,
+diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
+index 66deef41512f..f11fd597c5b6 100644
+--- a/arch/x86/kernel/signal.c
++++ b/arch/x86/kernel/signal.c
+@@ -686,12 +686,15 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
+       signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP));
+ }
+ 
+-#ifdef CONFIG_X86_32
+-#define NR_restart_syscall    __NR_restart_syscall
+-#else /* !CONFIG_X86_32 */
+-#define NR_restart_syscall    \
+-      test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : 
__NR_restart_syscall
+-#endif /* CONFIG_X86_32 */
++static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
++{
++#if defined(CONFIG_X86_32) || !defined(CONFIG_X86_64)
++      return __NR_restart_syscall;
++#else /* !CONFIG_X86_32 && CONFIG_X86_64 */
++      return test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall :
++              __NR_restart_syscall | (regs->orig_ax & __X32_SYSCALL_BIT);
++#endif /* CONFIG_X86_32 || !CONFIG_X86_64 */
++}
+ 
+ /*
+  * Note that 'init' is a special process: it doesn't get signals it doesn't
+@@ -720,7 +723,7 @@ static void do_signal(struct pt_regs *regs)
+                       break;
+ 
+               case -ERESTART_RESTARTBLOCK:
+-                      regs->ax = NR_restart_syscall;
++                      regs->ax = get_nr_restart_syscall(regs);
+                       regs->ip -= 2;
+                       break;
+               }
+diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
+index 45329c8c226e..39e12c10b931 100644
+--- a/arch/x86/xen/suspend.c
++++ b/arch/x86/xen/suspend.c
+@@ -30,7 +30,8 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
+ {
+ #ifdef CONFIG_XEN_PVHVM
+       int cpu;
+-      xen_hvm_init_shared_info();
++      if (!suspend_cancelled)
++          xen_hvm_init_shared_info();
+       xen_callback_vector();
+       xen_unplug_emulated_devices();
+       if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c 
b/drivers/char/ipmi/ipmi_si_intf.c
+index 02cc352d8bcc..a67ac2a71155 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -1144,14 +1144,14 @@ static int smi_start_processing(void       *send_info,
+ 
+       new_smi->intf = intf;
+ 
+-      /* Try to claim any interrupts. */
+-      if (new_smi->irq_setup)
+-              new_smi->irq_setup(new_smi);
+-
+       /* Set up the timer that drives the interface. */
+       setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
+       smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
+ 
++      /* Try to claim any interrupts. */
++      if (new_smi->irq_setup)
++              new_smi->irq_setup(new_smi);
++
+       /*
+        * Check if the user forcefully enabled the daemon.
+        */
+diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
+index 0daa11e418b1..bdbd80415908 100644
+--- a/drivers/connector/connector.c
++++ b/drivers/connector/connector.c
+@@ -154,26 +154,21 @@ static int cn_call_callback(struct sk_buff *skb)
+  *
+  * It checks skb, netlink header and msg sizes, and calls callback helper.
+  */
+-static void cn_rx_skb(struct sk_buff *__skb)
++static void cn_rx_skb(struct sk_buff *skb)
+ {
+       struct nlmsghdr *nlh;
+-      struct sk_buff *skb;
+       int len, err;
+ 
+-      skb = skb_get(__skb);
+-
+       if (skb->len >= NLMSG_HDRLEN) {
+               nlh = nlmsg_hdr(skb);
+               len = nlmsg_len(nlh);
+ 
+               if (len < (int)sizeof(struct cn_msg) ||
+                   skb->len < nlh->nlmsg_len ||
+-                  len > CONNECTOR_MAX_MSG_SIZE) {
+-                      kfree_skb(skb);
++                  len > CONNECTOR_MAX_MSG_SIZE)
+                       return;
+-              }
+ 
+-              err = cn_call_callback(skb);
++              err = cn_call_callback(skb_get(skb));
+               if (err < 0)
+                       kfree_skb(skb);
+       }
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 2bd798a7d9aa..c1a8cf2d490b 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1462,7 +1462,7 @@ int hid_connect(struct hid_device *hdev, unsigned int 
connect_mask)
+               "Multi-Axis Controller"
+       };
+       const char *type, *bus;
+-      char buf[64];
++      char buf[64] = "";
+       unsigned int i;
+       int len;
+       int ret;
+diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
+index 38ceac5053a0..0ed6731396ef 100644
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -301,6 +301,8 @@ isdn_ppp_open(int min, struct file *file)
+       is->compflags = 0;
+ 
+       is->reset = isdn_ppp_ccp_reset_alloc(is);
++      if (!is->reset)
++              return -ENOMEM;
+ 
+       is->lp = NULL;
+       is->mp_seqno = 0;       /* MP sequence number */
+@@ -320,6 +322,10 @@ isdn_ppp_open(int min, struct file *file)
+        * VJ header compression init
+        */
+       is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle 
*/
++      if (IS_ERR(is->slcomp)) {
++              isdn_ppp_ccp_reset_free(is);
++              return PTR_ERR(is->slcomp);
++      }
+ #endif
+ #ifdef CONFIG_IPPP_FILTER
+       is->pass_filter = NULL;
+@@ -568,10 +574,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int 
cmd, unsigned long arg)
+                       is->maxcid = val;
+ #ifdef CONFIG_ISDN_PPP_VJ
+                       sltmp = slhc_init(16, val);
+-                      if (!sltmp) {
+-                              printk(KERN_ERR "ippp, can't realloc slhc 
struct\n");
+-                              return -ENOMEM;
+-                      }
++                      if (IS_ERR(sltmp))
++                              return PTR_ERR(sltmp);
+                       if (is->slcomp)
+                               slhc_free(is->slcomp);
+                       is->slcomp = sltmp;
+diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
+index 5a1897d86e94..a2d7d5f066f1 100644
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -716,10 +716,8 @@ static long ppp_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
+                       val &= 0xffff;
+               }
+               vj = slhc_init(val2+1, val+1);
+-              if (!vj) {
+-                      netdev_err(ppp->dev,
+-                                 "PPP: no memory (VJ compressor)\n");
+-                      err = -ENOMEM;
++              if (IS_ERR(vj)) {
++                      err = PTR_ERR(vj);
+                       break;
+               }
+               ppp_lock(ppp);
+diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
+index 1252d9c726a7..b52eabc168a0 100644
+--- a/drivers/net/slip/slhc.c
++++ b/drivers/net/slip/slhc.c
+@@ -84,8 +84,9 @@ static long decode(unsigned char **cpp);
+ static unsigned char * put16(unsigned char *cp, unsigned short x);
+ static unsigned short pull16(unsigned char **cpp);
+ 
+-/* Initialize compression data structure
++/* Allocate compression data structure
+  *    slots must be in range 0 to 255 (zero meaning no compression)
++ * Returns pointer to structure or ERR_PTR() on error.
+  */
+ struct slcompress *
+ slhc_init(int rslots, int tslots)
+@@ -94,11 +95,14 @@ slhc_init(int rslots, int tslots)
+       register struct cstate *ts;
+       struct slcompress *comp;
+ 
++      if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255)
++              return ERR_PTR(-EINVAL);
++
+       comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
+       if (! comp)
+               goto out_fail;
+ 
+-      if ( rslots > 0  &&  rslots < 256 ) {
++      if (rslots > 0) {
+               size_t rsize = rslots * sizeof(struct cstate);
+               comp->rstate = kzalloc(rsize, GFP_KERNEL);
+               if (! comp->rstate)
+@@ -106,7 +110,7 @@ slhc_init(int rslots, int tslots)
+               comp->rslot_limit = rslots - 1;
+       }
+ 
+-      if ( tslots > 0  &&  tslots < 256 ) {
++      if (tslots > 0) {
+               size_t tsize = tslots * sizeof(struct cstate);
+               comp->tstate = kzalloc(tsize, GFP_KERNEL);
+               if (! comp->tstate)
+@@ -141,7 +145,7 @@ out_free2:
+ out_free:
+       kfree(comp);
+ out_fail:
+-      return NULL;
++      return ERR_PTR(-ENOMEM);
+ }
+ 
+ 
+diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
+index a34d6bf5e43b..ca3e73753fb8 100644
+--- a/drivers/net/slip/slip.c
++++ b/drivers/net/slip/slip.c
+@@ -163,7 +163,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu)
+       if (cbuff == NULL)
+               goto err_exit;
+       slcomp = slhc_init(16, 16);
+-      if (slcomp == NULL)
++      if (IS_ERR(slcomp))
+               goto err_exit;
+ #endif
+       spin_lock_bh(&sl->lock);
+diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
+index 14179a6593ef..5225d4321e7c 100644
+--- a/drivers/net/team/team.c
++++ b/drivers/net/team/team.c
+@@ -1636,10 +1636,10 @@ static int team_vlan_rx_kill_vid(struct net_device 
*dev, __be16 proto, u16 vid)
+       struct team *team = netdev_priv(dev);
+       struct team_port *port;
+ 
+-      rcu_read_lock();
+-      list_for_each_entry_rcu(port, &team->port_list, list)
++      mutex_lock(&team->lock);
++      list_for_each_entry(port, &team->port_list, list)
+               vlan_vid_del(port->dev, proto, vid);
+-      rcu_read_unlock();
++      mutex_unlock(&team->lock);
+ 
+       return 0;
+ }
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index 177f911f5946..cc6d3f987436 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -116,12 +116,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct 
net_device *dev)
+               kfree_skb(skb);
+               goto drop;
+       }
+-      /* don't change ip_summed == CHECKSUM_PARTIAL, as that
+-       * will cause bad checksum on forwarded packets
+-       */
+-      if (skb->ip_summed == CHECKSUM_NONE &&
+-          rcv->features & NETIF_F_RXCSUM)
+-              skb->ip_summed = CHECKSUM_UNNECESSARY;
+ 
+       if (likely(dev_forward_skb(rcv, skb) == NET_RX_SUCCESS)) {
+               struct pcpu_vstats *stats = this_cpu_ptr(dev->vstats);
+diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
+index 8c33491b21fe..c6aa38883466 100644
+--- a/drivers/parisc/iommu-helpers.h
++++ b/drivers/parisc/iommu-helpers.h
+@@ -104,7 +104,11 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
+       struct scatterlist *contig_sg;     /* contig chunk head */
+       unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+       unsigned int n_mappings = 0;
+-      unsigned int max_seg_size = dma_get_max_seg_size(dev);
++      unsigned int max_seg_size = min(dma_get_max_seg_size(dev),
++                                      (unsigned)DMA_CHUNK_SIZE);
++      unsigned int max_seg_boundary = dma_get_seg_boundary(dev) + 1;
++      if (max_seg_boundary)   /* check if the addition above didn't overflow 
*/
++              max_seg_size = min(max_seg_size, max_seg_boundary);
+ 
+       while (nents > 0) {
+ 
+@@ -139,14 +143,11 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device 
*dev,
+ 
+                       /*
+                       ** First make sure current dma stream won't
+-                      ** exceed DMA_CHUNK_SIZE if we coalesce the
++                      ** exceed max_seg_size if we coalesce the
+                       ** next entry.
+                       */   
+-                      if(unlikely(ALIGN(dma_len + dma_offset + 
startsg->length,
+-                                          IOVP_SIZE) > DMA_CHUNK_SIZE))
+-                              break;
+-
+-                      if (startsg->length + dma_len > max_seg_size)
++                      if (unlikely(ALIGN(dma_len + dma_offset + 
startsg->length, IOVP_SIZE) >
++                                   max_seg_size))
+                               break;
+ 
+                       /*
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index a3431e90345f..4dc18615cd0f 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -4615,8 +4615,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct 
usb_device *hdev,
+       ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
+       slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
+       slot_ctx->dev_info |= cpu_to_le32(DEV_HUB);
++      /*
++       * refer to section 6.2.2: MTT should be 0 for full speed hub,
++       * but it may be already set to 1 when setup an xHCI virtual
++       * device, so clear it anyway.
++       */
+       if (tt->multi)
+               slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
++      else if (hdev->speed == USB_SPEED_FULL)
++              slot_ctx->dev_info &= cpu_to_le32(~DEV_MTT);
++
+       if (xhci->hci_version > 0x95) {
+               xhci_dbg(xhci, "xHCI version %x needs hub "
+                               "TT think time and number of ports\n",
+@@ -4807,6 +4815,10 @@ static int __init xhci_hcd_init(void)
+       BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
+       /* 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 25522e98602e..72c14d7d604f 100644
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -160,6 +160,7 @@ static const struct usb_device_id id_table[] = {
+       { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
+       { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
+       { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
++      { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+       { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
+       { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
+       { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index 76c9a847da5d..e03900e8c667 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -532,7 +532,8 @@ static int ipaq_open(struct tty_struct *tty,
+        * through. Since this has a reasonably high failure rate, we retry
+        * several times.
+        */
+-      while (retries--) {
++      while (retries) {
++              retries--;
+               result = usb_control_msg(serial->dev,
+                               usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+                               0x1, 0, NULL, 0, 100);
+diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
+index e68205cbc46e..3d8e6098cd40 100644
+--- a/drivers/xen/gntdev.c
++++ b/drivers/xen/gntdev.c
+@@ -770,7 +770,7 @@ static int gntdev_mmap(struct file *flip, struct 
vm_area_struct *vma)
+ 
+       vma->vm_ops = &gntdev_vmops;
+ 
+-      vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
++      vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
+ 
+       if (use_ptemod)
+               vma->vm_flags |= VM_DONTCOPY;
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 7cf305d036db..4781332f2e11 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -670,6 +670,7 @@ struct user_struct {
+       unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
+ #endif
+       unsigned long locked_shm; /* How many pages of mlocked shm ? */
++      unsigned long unix_inflight;    /* How many files in flight in unix 
sockets */
+ 
+ #ifdef CONFIG_KEYS
+       struct key *uid_keyring;        /* UID specific keyring */
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 84662ecc7b51..e1bc430133f4 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -498,7 +498,7 @@ asmlinkage long sys_chown(const char __user *filename,
+ asmlinkage long sys_lchown(const char __user *filename,
+                               uid_t user, gid_t group);
+ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);
+-#ifdef CONFIG_UID16
++#ifdef CONFIG_HAVE_UID16
+ asmlinkage long sys_chown16(const char __user *filename,
+                               old_uid_t user, old_gid_t group);
+ asmlinkage long sys_lchown16(const char __user *filename,
+diff --git a/include/linux/types.h b/include/linux/types.h
+index 4d118ba11349..83db8e5974dc 100644
+--- a/include/linux/types.h
++++ b/include/linux/types.h
+@@ -35,7 +35,7 @@ typedef __kernel_gid16_t        gid16_t;
+ 
+ typedef unsigned long         uintptr_t;
+ 
+-#ifdef CONFIG_UID16
++#ifdef CONFIG_HAVE_UID16
+ /* This is defined by include/asm-{arch}/posix_types.h */
+ typedef __kernel_old_uid_t    old_uid_t;
+ typedef __kernel_old_gid_t    old_gid_t;
+diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
+index 886f6d6dc48a..3995a66c3e4e 100644
+--- a/net/bridge/br_stp_if.c
++++ b/net/bridge/br_stp_if.c
+@@ -128,7 +128,10 @@ static void br_stp_start(struct net_bridge *br)
+       char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
+       char *envp[] = { NULL };
+ 
+-      r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
++      if (net_eq(dev_net(br->dev), &init_net))
++              r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
++      else
++              r = -ENOENT;
+ 
+       spin_lock_bh(&br->lock);
+ 
+diff --git a/net/core/dst.c b/net/core/dst.c
+index 01f9980af86e..1bf6842b89b8 100644
+--- a/net/core/dst.c
++++ b/net/core/dst.c
+@@ -280,10 +280,11 @@ void dst_release(struct dst_entry *dst)
+ {
+       if (dst) {
+               int newrefcnt;
++              unsigned short nocache = dst->flags & DST_NOCACHE;
+ 
+               newrefcnt = atomic_dec_return(&dst->__refcnt);
+               WARN_ON(newrefcnt < 0);
+-              if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE))
++              if (!newrefcnt && unlikely(nocache))
+                       call_rcu(&dst->rcu_head, dst_destroy_rcu);
+       }
+ }
+diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c
+index 05c3b6f0e8e1..bf8321d6f2ef 100644
+--- a/net/ipv4/tcp_yeah.c
++++ b/net/ipv4/tcp_yeah.c
+@@ -222,7 +222,7 @@ static u32 tcp_yeah_ssthresh(struct sock *sk) {
+       yeah->fast_count = 0;
+       yeah->reno_count = max(yeah->reno_count>>1, 2U);
+ 
+-      return tp->snd_cwnd - reduction;
++      return max_t(int, tp->snd_cwnd - reduction, 2);
+ }
+ 
+ static struct tcp_congestion_ops tcp_yeah __read_mostly = {
+diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
+index b30ad3741b46..d5c918975c8c 100644
+--- a/net/ipv6/addrlabel.c
++++ b/net/ipv6/addrlabel.c
+@@ -558,7 +558,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct 
nlmsghdr* nlh)
+ 
+       rcu_read_lock();
+       p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), 
ifal->ifal_index);
+-      if (p && ip6addrlbl_hold(p))
++      if (p && !ip6addrlbl_hold(p))
+               p = NULL;
+       lseq = ip6addrlbl_table.seq;
+       rcu_read_unlock();
+diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
+index 5a940dbd74a3..f0229223bf91 100644
+--- a/net/phonet/af_phonet.c
++++ b/net/phonet/af_phonet.c
+@@ -377,6 +377,10 @@ static int phonet_rcv(struct sk_buff *skb, struct 
net_device *dev,
+       struct sockaddr_pn sa;
+       u16 len;
+ 
++      skb = skb_share_check(skb, GFP_ATOMIC);
++      if (!skb)
++              return NET_RX_DROP;
++
+       /* check we have at least a full Phonet header */
+       if (!pskb_pull(skb, sizeof(struct phonethdr)))
+               goto out;
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index c52763a26297..d9cbecb62aca 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -4835,7 +4835,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
+ 
+       retval = SCTP_DISPOSITION_CONSUME;
+ 
+-      sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
++      if (abort)
++              sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+ 
+       /* Even if we can't send the ABORT due to low memory delete the
+        * TCB.  This is a departure from our typical NOMEM handling.
+@@ -4972,7 +4973,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
+                       SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+       retval = SCTP_DISPOSITION_CONSUME;
+ 
+-      sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
++      if (abort)
++              sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+ 
+       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+                       SCTP_STATE(SCTP_STATE_CLOSED));
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 80bd61ae5945..bdc3fb66717d 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -1533,8 +1533,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long 
timeout)
+                       struct sctp_chunk *chunk;
+ 
+                       chunk = sctp_make_abort_user(asoc, NULL, 0);
+-                      if (chunk)
+-                              sctp_primitive_ABORT(net, asoc, chunk);
++                      sctp_primitive_ABORT(net, asoc, chunk);
+               } else
+                       sctp_primitive_SHUTDOWN(net, asoc, NULL);
+       }
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index f934e7ba5eb8..a673c1f4f638 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1483,6 +1483,21 @@ static void unix_destruct_scm(struct sk_buff *skb)
+       sock_wfree(skb);
+ }
+ 
++/*
++ * The "user->unix_inflight" variable is protected by the garbage
++ * collection lock, and we just read it locklessly here. If you go
++ * over the limit, there might be a tiny race in actually noticing
++ * it across threads. Tough.
++ */
++static inline bool too_many_unix_fds(struct task_struct *p)
++{
++      struct user_struct *user = current_user();
++
++      if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)))
++              return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
++      return false;
++}
++
+ #define MAX_RECURSION_LEVEL 4
+ 
+ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
+@@ -1491,6 +1506,9 @@ static int unix_attach_fds(struct scm_cookie *scm, 
struct sk_buff *skb)
+       unsigned char max_level = 0;
+       int unix_sock_count = 0;
+ 
++      if (too_many_unix_fds(current))
++              return -ETOOMANYREFS;
++
+       for (i = scm->fp->count - 1; i >= 0; i--) {
+               struct sock *sk = unix_get_socket(scm->fp->fp[i]);
+ 
+@@ -1512,10 +1530,8 @@ static int unix_attach_fds(struct scm_cookie *scm, 
struct sk_buff *skb)
+       if (!UNIXCB(skb).fp)
+               return -ENOMEM;
+ 
+-      if (unix_sock_count) {
+-              for (i = scm->fp->count - 1; i >= 0; i--)
+-                      unix_inflight(scm->fp->fp[i]);
+-      }
++      for (i = scm->fp->count - 1; i >= 0; i--)
++              unix_inflight(scm->fp->fp[i]);
+       return max_level;
+ }
+ 
+@@ -1934,7 +1950,14 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, 
struct socket *sock,
+       if (flags&MSG_OOB)
+               goto out;
+ 
+-      mutex_lock(&u->readlock);
++      err = mutex_lock_interruptible(&u->readlock);
++      if (unlikely(err)) {
++              /* recvmsg() in non blocking mode is supposed to return -EAGAIN
++               * sk_rcvtimeo is not honored by mutex_lock_interruptible()
++               */
++              err = noblock ? -EAGAIN : -ERESTARTSYS;
++              goto out;
++      }
+ 
+       skip = sk_peek_offset(sk, flags);
+ 
+@@ -2083,14 +2106,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, 
struct socket *sock,
+               memset(&tmp_scm, 0, sizeof(tmp_scm));
+       }
+ 
+-      err = mutex_lock_interruptible(&u->readlock);
+-      if (unlikely(err)) {
+-              /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+-               * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+-               */
+-              err = noblock ? -EAGAIN : -ERESTARTSYS;
+-              goto out;
+-      }
++      mutex_lock(&u->readlock);
+ 
+       do {
+               int chunk;
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 9bc73f87f64a..06730fe6ad9d 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -125,9 +125,12 @@ struct sock *unix_get_socket(struct file *filp)
+ void unix_inflight(struct file *fp)
+ {
+       struct sock *s = unix_get_socket(fp);
++
++      spin_lock(&unix_gc_lock);
++
+       if (s) {
+               struct unix_sock *u = unix_sk(s);
+-              spin_lock(&unix_gc_lock);
++
+               if (atomic_long_inc_return(&u->inflight) == 1) {
+                       BUG_ON(!list_empty(&u->link));
+                       list_add_tail(&u->link, &gc_inflight_list);
+@@ -135,22 +138,27 @@ void unix_inflight(struct file *fp)
+                       BUG_ON(list_empty(&u->link));
+               }
+               unix_tot_inflight++;
+-              spin_unlock(&unix_gc_lock);
+       }
++      fp->f_cred->user->unix_inflight++;
++      spin_unlock(&unix_gc_lock);
+ }
+ 
+ void unix_notinflight(struct file *fp)
+ {
+       struct sock *s = unix_get_socket(fp);
++
++      spin_lock(&unix_gc_lock);
++
+       if (s) {
+               struct unix_sock *u = unix_sk(s);
+-              spin_lock(&unix_gc_lock);
++
+               BUG_ON(list_empty(&u->link));
+               if (atomic_long_dec_and_test(&u->inflight))
+                       list_del_init(&u->link);
+               unix_tot_inflight--;
+-              spin_unlock(&unix_gc_lock);
+       }
++      fp->f_cred->user->unix_inflight--;
++      spin_unlock(&unix_gc_lock);
+ }
+ 
+ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
+diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
+index 679218b56ede..f94f6a2d6988 100755
+--- a/scripts/recordmcount.pl
++++ b/scripts/recordmcount.pl
+@@ -265,7 +265,8 @@ if ($arch eq "x86_64") {
+ 
+ } elsif ($arch eq "powerpc") {
+     $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
+-    $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";
++    # See comment in the sparc64 section for why we use '\w'.
++    $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?\\w*?)>:";
+     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";
+ 
+     if ($bits == 64) {
+diff --git a/sound/core/control.c b/sound/core/control.c
+index f2082a35b890..3fcead61f0ef 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1325,6 +1325,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+               return -EFAULT;
+       if (tlv.length < sizeof(unsigned int) * 2)
+               return -EINVAL;
++      if (!tlv.numid)
++              return -EINVAL;
+       down_read(&card->controls_rwsem);
+       kctl = snd_ctl_find_numid(card, tlv.numid);
+       if (kctl == NULL) {
+diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
+index b8b31c433d64..14d483d6b3b0 100644
+--- a/sound/core/hrtimer.c
++++ b/sound/core/hrtimer.c
+@@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_timer *t)
+       struct snd_hrtimer *stime = t->private_data;
+ 
+       atomic_set(&stime->running, 0);
+-      hrtimer_cancel(&stime->hrt);
++      hrtimer_try_to_cancel(&stime->hrt);
+       hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
+                     HRTIMER_MODE_REL);
+       atomic_set(&stime->running, 1);
+@@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
+ {
+       struct snd_hrtimer *stime = t->private_data;
+       atomic_set(&stime->running, 0);
++      hrtimer_try_to_cancel(&stime->hrt);
+       return 0;
+ }
+ 
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index c4ac3c1e19af..1bb1a43c7d03 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -236,10 +236,15 @@ static int snd_pcm_ioctl_hw_params_compat(struct 
snd_pcm_substream *substream,
+       if (! (runtime = substream->runtime))
+               return -ENOTTY;
+ 
+-      /* only fifo_size is different, so just copy all */
+-      data = memdup_user(data32, sizeof(*data32));
+-      if (IS_ERR(data))
+-              return PTR_ERR(data);
++      data = kmalloc(sizeof(*data), GFP_KERNEL);
++      if (!data)
++              return -ENOMEM;
++
++      /* only fifo_size (RO from userspace) is different, so just copy all */
++      if (copy_from_user(data, data32, sizeof(*data32))) {
++              err = -EFAULT;
++              goto error;
++      }
+ 
+       if (refine)
+               err = snd_pcm_hw_refine(substream, data);
+diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
+index 4dc6bae80e15..ecfbf5f39d38 100644
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -1950,7 +1950,7 @@ static int snd_seq_ioctl_remove_events(struct 
snd_seq_client *client,
+                * No restrictions so for a user client we can clear
+                * the whole fifo
+                */
+-              if (client->type == USER_CLIENT)
++              if (client->type == USER_CLIENT && client->data.user.fifo)
+                       snd_seq_fifo_clear(client->data.user.fifo);
+       }
+ 
+diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
+index 81f7c109dc46..65175902a68a 100644
+--- a/sound/core/seq/seq_compat.c
++++ b/sound/core/seq/seq_compat.c
+@@ -49,11 +49,12 @@ static int snd_seq_call_port_info_ioctl(struct 
snd_seq_client *client, unsigned
+       struct snd_seq_port_info *data;
+       mm_segment_t fs;
+ 
+-      data = memdup_user(data32, sizeof(*data32));
+-      if (IS_ERR(data))
+-              return PTR_ERR(data);
++      data = kmalloc(sizeof(*data), GFP_KERNEL);
++      if (!data)
++              return -ENOMEM;
+ 
+-      if (get_user(data->flags, &data32->flags) ||
++      if (copy_from_user(data, data32, sizeof(*data32)) ||
++          get_user(data->flags, &data32->flags) ||
+           get_user(data->time_queue, &data32->time_queue))
+               goto error;
+       data->kernel = NULL;
+diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
+index f9077361c119..4c9aa462de9b 100644
+--- a/sound/core/seq/seq_queue.c
++++ b/sound/core/seq/seq_queue.c
+@@ -144,8 +144,10 @@ static struct snd_seq_queue *queue_new(int owner, int 
locked)
+ static void queue_delete(struct snd_seq_queue *q)
+ {
+       /* stop and release the timer */
++      mutex_lock(&q->timer_mutex);
+       snd_seq_timer_stop(q->timer);
+       snd_seq_timer_close(q);
++      mutex_unlock(&q->timer_mutex);
+       /* wait until access free */
+       snd_use_lock_sync(&q->use_lock);
+       /* release resources... */
+diff --git a/sound/core/timer.c b/sound/core/timer.c
+index 6ddcf06f52f9..4e436fe53afa 100644
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -73,7 +73,7 @@ struct snd_timer_user {
+       struct timespec tstamp;         /* trigger tstamp */
+       wait_queue_head_t qchange_sleep;
+       struct fasync_struct *fasync;
+-      struct mutex tread_sem;
++      struct mutex ioctl_lock;
+ };
+ 
+ /* list of timers */
+@@ -215,11 +215,13 @@ static void snd_timer_check_master(struct 
snd_timer_instance *master)
+                   slave->slave_id == master->slave_id) {
+                       list_move_tail(&slave->open_list, 
&master->slave_list_head);
+                       spin_lock_irq(&slave_active_lock);
++                      spin_lock(&master->timer->lock);
+                       slave->master = master;
+                       slave->timer = master->timer;
+                       if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
+                               list_add_tail(&slave->active_list,
+                                             &master->slave_active_head);
++                      spin_unlock(&master->timer->lock);
+                       spin_unlock_irq(&slave_active_lock);
+               }
+       }
+@@ -345,15 +347,18 @@ int snd_timer_close(struct snd_timer_instance *timeri)
+                   timer->hw.close)
+                       timer->hw.close(timer);
+               /* remove slave links */
++              spin_lock_irq(&slave_active_lock);
++              spin_lock(&timer->lock);
+               list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
+                                        open_list) {
+-                      spin_lock_irq(&slave_active_lock);
+-                      _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
+                       list_move_tail(&slave->open_list, 
&snd_timer_slave_list);
+                       slave->master = NULL;
+                       slave->timer = NULL;
+-                      spin_unlock_irq(&slave_active_lock);
++                      list_del_init(&slave->ack_list);
++                      list_del_init(&slave->active_list);
+               }
++              spin_unlock(&timer->lock);
++              spin_unlock_irq(&slave_active_lock);
+               mutex_unlock(&register_mutex);
+       }
+  out:
+@@ -440,9 +445,12 @@ static int snd_timer_start_slave(struct 
snd_timer_instance *timeri)
+ 
+       spin_lock_irqsave(&slave_active_lock, flags);
+       timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
+-      if (timeri->master)
++      if (timeri->master && timeri->timer) {
++              spin_lock(&timeri->timer->lock);
+               list_add_tail(&timeri->active_list,
+                             &timeri->master->slave_active_head);
++              spin_unlock(&timeri->timer->lock);
++      }
+       spin_unlock_irqrestore(&slave_active_lock, flags);
+       return 1; /* delayed start */
+ }
+@@ -488,6 +496,8 @@ static int _snd_timer_stop(struct snd_timer_instance * 
timeri,
+               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_unlock_irqrestore(&slave_active_lock, flags);
+               }
+               goto __end;
+@@ -693,7 +703,7 @@ void snd_timer_interrupt(struct snd_timer * timer, 
unsigned long ticks_left)
+               } else {
+                       ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+                       if (--timer->running)
+-                              list_del(&ti->active_list);
++                              list_del_init(&ti->active_list);
+               }
+               if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
+                   (ti->flags & SNDRV_TIMER_IFLG_FAST))
+@@ -1256,7 +1266,7 @@ static int snd_timer_user_open(struct inode *inode, 
struct file *file)
+               return -ENOMEM;
+       spin_lock_init(&tu->qlock);
+       init_waitqueue_head(&tu->qchange_sleep);
+-      mutex_init(&tu->tread_sem);
++      mutex_init(&tu->ioctl_lock);
+       tu->ticks = 1;
+       tu->queue_size = 128;
+       tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
+@@ -1276,8 +1286,10 @@ static int snd_timer_user_release(struct inode *inode, 
struct file *file)
+       if (file->private_data) {
+               tu = file->private_data;
+               file->private_data = NULL;
++              mutex_lock(&tu->ioctl_lock);
+               if (tu->timeri)
+                       snd_timer_close(tu->timeri);
++              mutex_unlock(&tu->ioctl_lock);
+               kfree(tu->queue);
+               kfree(tu->tqueue);
+               kfree(tu);
+@@ -1515,7 +1527,6 @@ static int snd_timer_user_tselect(struct file *file,
+       int err = 0;
+ 
+       tu = file->private_data;
+-      mutex_lock(&tu->tread_sem);
+       if (tu->timeri) {
+               snd_timer_close(tu->timeri);
+               tu->timeri = NULL;
+@@ -1559,7 +1570,6 @@ static int snd_timer_user_tselect(struct file *file,
+       }
+ 
+       __err:
+-              mutex_unlock(&tu->tread_sem);
+       return err;
+ }
+ 
+@@ -1772,7 +1782,7 @@ enum {
+       SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
+ };
+ 
+-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
++static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+ {
+       struct snd_timer_user *tu;
+@@ -1789,17 +1799,11 @@ static long snd_timer_user_ioctl(struct file *file, 
unsigned int cmd,
+       {
+               int xarg;
+ 
+-              mutex_lock(&tu->tread_sem);
+-              if (tu->timeri) {       /* too late */
+-                      mutex_unlock(&tu->tread_sem);
++              if (tu->timeri) /* too late */
+                       return -EBUSY;
+-              }
+-              if (get_user(xarg, p)) {
+-                      mutex_unlock(&tu->tread_sem);
++              if (get_user(xarg, p))
+                       return -EFAULT;
+-              }
+               tu->tread = xarg ? 1 : 0;
+-              mutex_unlock(&tu->tread_sem);
+               return 0;
+       }
+       case SNDRV_TIMER_IOCTL_GINFO:
+@@ -1832,6 +1836,18 @@ static long snd_timer_user_ioctl(struct file *file, 
unsigned int cmd,
+       return -ENOTTY;
+ }
+ 
++static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
++                               unsigned long arg)
++{
++      struct snd_timer_user *tu = file->private_data;
++      long ret;
++
++      mutex_lock(&tu->ioctl_lock);
++      ret = __snd_timer_user_ioctl(file, cmd, arg);
++      mutex_unlock(&tu->ioctl_lock);
++      return ret;
++}
++
+ static int snd_timer_user_fasync(int fd, struct file * file, int on)
+ {
+       struct snd_timer_user *tu;
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index 1800db643a16..57d01f101b04 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -1104,6 +1104,36 @@ static unsigned int azx_get_response(struct hda_bus 
*bus,
+               return azx_rirb_get_response(bus, addr);
+ }
+ 
++#ifdef CONFIG_PM_SLEEP
++/* put codec down to D3 at hibernation for Intel SKL+;
++ * otherwise BIOS may still access the codec and screw up the driver
++ */
++#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
++#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
++#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
++#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
++
++static int azx_freeze_noirq(struct device *dev)
++{
++      struct pci_dev *pci = to_pci_dev(dev);
++
++      if (IS_SKL_PLUS(pci))
++              pci_set_power_state(pci, PCI_D3hot);
++
++      return 0;
++}
++
++static int azx_thaw_noirq(struct device *dev)
++{
++      struct pci_dev *pci = to_pci_dev(dev);
++
++      if (IS_SKL_PLUS(pci))
++              pci_set_power_state(pci, PCI_D0);
++
++      return 0;
++}
++#endif /* CONFIG_PM_SLEEP */
++
+ #ifdef CONFIG_PM
+ static void azx_power_notify(struct hda_bus *bus, bool power_up);
+ #endif
+@@ -2974,6 +3004,10 @@ static int azx_runtime_idle(struct device *dev)
+ #ifdef CONFIG_PM
+ static const struct dev_pm_ops azx_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
++#ifdef CONFIG_PM_SLEEP
++      .freeze_noirq = azx_freeze_noirq,
++      .thaw_noirq = azx_thaw_noirq,
++#endif
+       SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, 
azx_runtime_idle)
+ };
+ 
+@@ -3864,6 +3898,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+       { PCI_DEVICE(0x8086, 0x8d21),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
++      /* Lewisburg */
++      { PCI_DEVICE(0x8086, 0xa1f0),
++        .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
++      { PCI_DEVICE(0x8086, 0xa270),
++        .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+       /* Lynx Point-LP */
+       { PCI_DEVICE(0x8086, 0x9c20),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 183a96ab2533..69a2aafb0b0f 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -1768,6 +1768,7 @@ enum {
+       ALC889_FIXUP_MBA11_VREF,
+       ALC889_FIXUP_MBA21_VREF,
+       ALC889_FIXUP_MP11_VREF,
++      ALC889_FIXUP_MP41_VREF,
+       ALC882_FIXUP_INV_DMIC,
+       ALC882_FIXUP_NO_PRIMARY_HP,
+       ALC887_FIXUP_ASUS_BASS,
+@@ -1854,7 +1855,7 @@ static void alc889_fixup_mbp_vref(struct hda_codec 
*codec,
+                                 const struct hda_fixup *fix, int action)
+ {
+       struct alc_spec *spec = codec->spec;
+-      static hda_nid_t nids[2] = { 0x14, 0x15 };
++      static hda_nid_t nids[3] = { 0x14, 0x15, 0x19 };
+       int i;
+ 
+       if (action != HDA_FIXUP_ACT_INIT)
+@@ -2128,6 +2129,12 @@ static const struct hda_fixup alc882_fixups[] = {
+               .chained = true,
+               .chain_id = ALC885_FIXUP_MACPRO_GPIO,
+       },
++      [ALC889_FIXUP_MP41_VREF] = {
++              .type = HDA_FIXUP_FUNC,
++              .v.func = alc889_fixup_mbp_vref,
++              .chained = true,
++              .chain_id = ALC885_FIXUP_MACPRO_GPIO,
++      },
+       [ALC882_FIXUP_INV_DMIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_inv_dmic_0x12,
+@@ -2200,7 +2207,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
+       SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", 
ALC889_FIXUP_IMAC91_VREF),
+       SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
+-      SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
++      SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 4,1/5,1", 
ALC889_FIXUP_MP41_VREF),
+       SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
+       SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", 
ALC889_FIXUP_IMAC91_VREF),
+       SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", 
ALC889_FIXUP_IMAC91_VREF),
+@@ -4446,6 +4453,7 @@ static const struct hda_fixup alc662_fixups[] = {
+ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
++      SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", 
ALC662_FIXUP_INV_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
+       SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index 44d3fb95ebba..5ffe7992aaed 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -703,6 +703,7 @@ static bool hp_bnb2011_with_dock(struct hda_codec *codec)
+ static bool hp_blike_system(u32 subsystem_id)
+ {
+       switch (subsystem_id) {
++      case 0x103c1473: /* HP ProBook 6550b */
+       case 0x103c1520:
+       case 0x103c1521:
+       case 0x103c1523:
+diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
+index 5fb88ac82aa9..4fdb234d74b4 100644
+--- a/sound/pci/rme96.c
++++ b/sound/pci/rme96.c
+@@ -703,10 +703,11 @@ snd_rme96_playback_setrate(struct rme96 *rme96,
+       {
+               /* change to/from double-speed: reset the DAC (if available) */
+               snd_rme96_reset_dac(rme96);
++              return 1; /* need to restore volume */
+       } else {
+               writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
++              return 0;
+       }
+-      return 0;
+ }
+ 
+ static int
+@@ -944,6 +945,7 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream 
*substream,
+       struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err, rate, dummy;
++      bool apply_dac_volume = false;
+ 
+       runtime->dma_area = (void __force *)(rme96->iobase +
+                                            RME96_IO_PLAY_BUFFER);
+@@ -957,24 +959,26 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream 
*substream,
+       {
+                 /* slave clock */
+                 if ((int)params_rate(params) != rate) {
+-                      spin_unlock_irq(&rme96->lock);
+-                      return -EIO;                    
+-                }
+-      } else if ((err = snd_rme96_playback_setrate(rme96, 
params_rate(params))) < 0) {
+-              spin_unlock_irq(&rme96->lock);
+-              return err;
+-      }
+-      if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) 
< 0) {
+-              spin_unlock_irq(&rme96->lock);
+-              return err;
++                      err = -EIO;
++                      goto error;
++              }
++      } else {
++              err = snd_rme96_playback_setrate(rme96, params_rate(params));
++              if (err < 0)
++                      goto error;
++              apply_dac_volume = err > 0; /* need to restore volume later? */
+       }
++
++      err = snd_rme96_playback_setformat(rme96, params_format(params));
++      if (err < 0)
++              goto error;
+       snd_rme96_setframelog(rme96, params_channels(params), 1);
+       if (rme96->capture_periodsize != 0) {
+               if (params_period_size(params) << rme96->playback_frlog !=
+                   rme96->capture_periodsize)
+               {
+-                      spin_unlock_irq(&rme96->lock);
+-                      return -EBUSY;
++                      err = -EBUSY;
++                      goto error;
+               }
+       }
+       rme96->playback_periodsize =
+@@ -985,9 +989,16 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream 
*substream,
+               rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | 
RME96_WCR_EMP);
+               writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase 
+ RME96_IO_CONTROL_REGISTER);
+       }
++
++      err = 0;
++ error:
+       spin_unlock_irq(&rme96->lock);
+-              
+-      return 0;
++      if (apply_dac_volume) {
++              usleep_range(3000, 10000);
++              snd_rme96_apply_dac_volume(rme96);
++      }
++
++      return err;
+ }
+ 
+ static int
+diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
+index 663a2a748626..56815af4e00b 100644
+--- a/sound/soc/codecs/arizona.c
++++ b/sound/soc/codecs/arizona.c
+@@ -1057,7 +1057,7 @@ static int arizona_hw_params(struct snd_pcm_substream 
*substream,
+       int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
+       int bclk, lrclk, wl, frame, bclk_target;
+ 
+-      if (params_rate(params) % 8000)
++      if (params_rate(params) % 4000)
+               rates = &arizona_44k1_bclk_rates[0];
+       else
+               rates = &arizona_48k_bclk_rates[0];
+diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
+index 1ae1f8bd9c36..305d28dec668 100644
+--- a/sound/soc/codecs/wm8962.c
++++ b/sound/soc/codecs/wm8962.c
+@@ -363,8 +363,8 @@ static struct reg_default wm8962_reg[] = {
+       { 16924, 0x0059 },   /* R16924 - HDBASS_PG_1 */
+       { 16925, 0x999A },   /* R16925 - HDBASS_PG_0 */
+ 
+-      { 17048, 0x0083 },   /* R17408 - HPF_C_1 */
+-      { 17049, 0x98AD },   /* R17409 - HPF_C_0 */
++      { 17408, 0x0083 },   /* R17408 - HPF_C_1 */
++      { 17409, 0x98AD },   /* R17409 - HPF_C_0 */
+ 
+       { 17920, 0x007F },   /* R17920 - ADCL_RETUNE_C1_1 */
+       { 17921, 0xFFFF },   /* R17921 - ADCL_RETUNE_C1_0 */
+diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
+index 06a8000aa07b..2340554981d6 100644
+--- a/sound/soc/soc-compress.c
++++ b/sound/soc/soc-compress.c
+@@ -384,17 +384,34 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, 
int num)
+       struct snd_compr *compr;
+       char new_name[64];
+       int ret = 0, direction = 0;
++      int playback = 0, capture = 0;
+ 
+       /* check client and interface hw capabilities */
+       snprintf(new_name, sizeof(new_name), "%s %s-%d",
+                       rtd->dai_link->stream_name, codec_dai->name, num);
+ 
+       if (codec_dai->driver->playback.channels_min)
++              playback = 1;
++      if (codec_dai->driver->capture.channels_min)
++              capture = 1;
++
++      capture = capture && cpu_dai->driver->capture.channels_min;
++      playback = playback && cpu_dai->driver->playback.channels_min;
++
++      /*
++       * Compress devices are unidirectional so only one of the directions
++       * should be set, check for that (xor)
++       */
++      if (playback + capture != 1) {
++              dev_err(rtd->card->dev, "Invalid direction for compress P %d, C 
%d\n",
++                              playback, capture);
++              return -EINVAL;
++      }
++
++      if(playback)
+               direction = SND_COMPRESS_PLAYBACK;
+-      else if (codec_dai->driver->capture.channels_min)
+-              direction = SND_COMPRESS_CAPTURE;
+       else
+-              return -EINVAL;
++              direction = SND_COMPRESS_CAPTURE;
+ 
+       compr = kzalloc(sizeof(*compr), GFP_KERNEL);
+       if (compr == NULL) {

Reply via email to