diff options
author | Mike Pagano <mpagano@gentoo.org> | 2015-12-10 08:52:12 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2015-12-10 08:52:12 -0500 |
commit | 74a5efb4942d8b7803a6d350358ce71f06b1db7d (patch) | |
tree | 83a7f78a90d9e9ae683b1c06e884861a9ea7cf7b | |
parent | Linux patch 3.14.57 (diff) | |
download | linux-patches-3.14-64.tar.gz linux-patches-3.14-64.tar.bz2 linux-patches-3.14-64.zip |
Linux patch 3.14.583.14-64
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1057_linux-3.14.58.patch | 1007 |
2 files changed, 1011 insertions, 0 deletions
diff --git a/0000_README b/0000_README index e6c3b6c2..240d7481 100644 --- a/0000_README +++ b/0000_README @@ -270,6 +270,10 @@ Patch: 1056_linux-3.14.57.patch From: http://www.kernel.org Desc: Linux 3.14.57 +Patch: 1057_linux-3.14.58.patch +From: http://www.kernel.org +Desc: Linux 3.14.58 + 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/1057_linux-3.14.58.patch b/1057_linux-3.14.58.patch new file mode 100644 index 00000000..56aed0cc --- /dev/null +++ b/1057_linux-3.14.58.patch @@ -0,0 +1,1007 @@ +diff --git a/Makefile b/Makefile +index 51ee14329c47..48a4d0b37c10 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 57 ++SUBLEVEL = 58 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c +index 5339009b3c0c..4873697b0958 100644 +--- a/arch/arm/common/edma.c ++++ b/arch/arm/common/edma.c +@@ -404,7 +404,8 @@ static irqreturn_t dma_irq_handler(int irq, void *data) + BIT(slot)); + if (edma_cc[ctlr]->intr_data[channel].callback) + edma_cc[ctlr]->intr_data[channel].callback( +- channel, EDMA_DMA_COMPLETE, ++ EDMA_CTLR_CHAN(ctlr, channel), ++ EDMA_DMA_COMPLETE, + edma_cc[ctlr]->intr_data[channel].data); + } + } while (sh_ipr); +@@ -458,7 +459,8 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) + if (edma_cc[ctlr]->intr_data[k]. + callback) { + edma_cc[ctlr]->intr_data[k]. +- callback(k, ++ callback( ++ EDMA_CTLR_CHAN(ctlr, k), + EDMA_DMA_CC_ERROR, + edma_cc[ctlr]->intr_data + [k].data); +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index 42f2fb8c5a00..887b19e915ee 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -1411,12 +1411,19 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, + unsigned long uaddr = vma->vm_start; + unsigned long usize = vma->vm_end - vma->vm_start; + struct page **pages = __iommu_get_pages(cpu_addr, attrs); ++ unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; ++ unsigned long off = vma->vm_pgoff; + + vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot); + + if (!pages) + return -ENXIO; + ++ if (off >= nr_pages || (usize >> PAGE_SHIFT) > nr_pages - off) ++ return -ENXIO; ++ ++ pages += off; ++ + do { + int ret = vm_insert_page(vma, uaddr, *pages++); + if (ret) { +diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c +index 830ff07f3385..410e60e0e6de 100644 +--- a/arch/arm/plat-orion/common.c ++++ b/arch/arm/plat-orion/common.c +@@ -499,7 +499,7 @@ void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq) + + d->netdev = &orion_ge00.dev; + for (i = 0; i < d->nr_chips; i++) +- d->chip[i].mii_bus = &orion_ge00_shared.dev; ++ d->chip[i].mii_bus = &orion_ge_mvmdio.dev; + orion_switch_device.dev.platform_data = d; + + platform_device_register(&orion_switch_device); +diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h +index 0e7fa4963735..428ae6f7a23b 100644 +--- a/arch/arm64/include/asm/ptrace.h ++++ b/arch/arm64/include/asm/ptrace.h +@@ -71,14 +71,14 @@ + #define compat_sp regs[13] + #define compat_lr regs[14] + #define compat_sp_hyp regs[15] +-#define compat_sp_irq regs[16] +-#define compat_lr_irq regs[17] +-#define compat_sp_svc regs[18] +-#define compat_lr_svc regs[19] +-#define compat_sp_abt regs[20] +-#define compat_lr_abt regs[21] +-#define compat_sp_und regs[22] +-#define compat_lr_und regs[23] ++#define compat_lr_irq regs[16] ++#define compat_sp_irq regs[17] ++#define compat_lr_svc regs[18] ++#define compat_sp_svc regs[19] ++#define compat_lr_abt regs[20] ++#define compat_sp_abt regs[21] ++#define compat_lr_und regs[22] ++#define compat_sp_und regs[23] + #define compat_r8_fiq regs[24] + #define compat_r9_fiq regs[25] + #define compat_r10_fiq regs[26] +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index e6bddd5b9da3..e5194f3028ba 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -280,10 +280,9 @@ __setup("nosmap", setup_disable_smap); + + static __always_inline void setup_smap(struct cpuinfo_x86 *c) + { +- unsigned long eflags; ++ unsigned long eflags = native_save_fl(); + + /* This should have been cleared long ago */ +- raw_local_save_flags(eflags); + BUG_ON(eflags & X86_EFLAGS_AC); + + if (cpu_has(c, X86_FEATURE_SMAP)) { +diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S +index a2dc0add72ed..761fd69df6d9 100644 +--- a/arch/x86/kernel/head_64.S ++++ b/arch/x86/kernel/head_64.S +@@ -65,6 +65,9 @@ startup_64: + * tables and then reload them. + */ + ++ /* Sanitize CPU configuration */ ++ call verify_cpu ++ + /* + * Compute the delta between the address I am compiled to run at and the + * address I am actually running at. +@@ -174,6 +177,9 @@ ENTRY(secondary_startup_64) + * after the boot processor executes this code. + */ + ++ /* Sanitize CPU configuration */ ++ call verify_cpu ++ + movq $(init_level4_pgt - __START_KERNEL_map), %rax + 1: + +@@ -288,6 +294,8 @@ ENTRY(secondary_startup_64) + pushq %rax # target address in negative space + lretq + ++#include "verify_cpu.S" ++ + #ifdef CONFIG_HOTPLUG_CPU + /* + * Boot CPU0 entry point. It's called from play_dead(). Everything has been set +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index ce72964b2f46..040718106629 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1178,6 +1178,14 @@ void __init setup_arch(char **cmdline_p) + clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); ++ ++ /* ++ * sync back low identity map too. It is used for example ++ * in the 32-bit EFI stub. ++ */ ++ clone_pgd_range(initial_page_table, ++ swapper_pg_dir + KERNEL_PGD_BOUNDARY, ++ min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); + #endif + + tboot_probe(); +diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S +index b9242bacbe59..4cf401f581e7 100644 +--- a/arch/x86/kernel/verify_cpu.S ++++ b/arch/x86/kernel/verify_cpu.S +@@ -34,10 +34,11 @@ + #include <asm/msr-index.h> + + verify_cpu: +- pushfl # Save caller passed flags +- pushl $0 # Kill any dangerous flags +- popfl ++ pushf # Save caller passed flags ++ push $0 # Kill any dangerous flags ++ popf + ++#ifndef __x86_64__ + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx +@@ -48,6 +49,7 @@ verify_cpu: + popl %eax + cmpl %eax,%ebx + jz verify_cpu_no_longmode # cpu has no cpuid ++#endif + + movl $0x0,%eax # See if cpuid 1 is implemented + cpuid +@@ -130,10 +132,10 @@ verify_cpu_sse_test: + jmp verify_cpu_sse_test # try again + + verify_cpu_no_longmode: +- popfl # Restore caller passed flags ++ popf # Restore caller passed flags + movl $1,%eax + ret + verify_cpu_sse_ok: +- popfl # Restore caller passed flags ++ popf # Restore caller passed flags + xorl %eax, %eax + ret +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 8ff2b3ca7ee9..2a09de8d6d71 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -90,6 +90,7 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x04CA, 0x300b) }, + { USB_DEVICE(0x04CA, 0x3010) }, + { USB_DEVICE(0x0930, 0x0219) }, ++ { USB_DEVICE(0x0930, 0x021c) }, + { USB_DEVICE(0x0930, 0x0220) }, + { USB_DEVICE(0x0930, 0x0227) }, + { USB_DEVICE(0x0b05, 0x17d0) }, +@@ -101,6 +102,7 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0CF3, 0x311F) }, + { USB_DEVICE(0x0cf3, 0x3121) }, + { USB_DEVICE(0x0CF3, 0x817a) }, ++ { USB_DEVICE(0x0CF3, 0x817b) }, + { USB_DEVICE(0x0cf3, 0xe003) }, + { USB_DEVICE(0x0CF3, 0xE004) }, + { USB_DEVICE(0x0CF3, 0xE005) }, +@@ -146,6 +148,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, +@@ -157,6 +160,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0CF3, 0x817b), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index c23658e42fc3..5d5e99902475 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -168,6 +168,7 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, +@@ -179,6 +180,7 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, +diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c +index f17c3018b7c7..c2d0559115d3 100644 +--- a/drivers/net/can/sja1000/sja1000.c ++++ b/drivers/net/can/sja1000/sja1000.c +@@ -184,6 +184,9 @@ static void sja1000_start(struct net_device *dev) + priv->write_reg(priv, SJA1000_RXERR, 0x0); + priv->read_reg(priv, SJA1000_ECC); + ++ /* clear interrupt flags */ ++ priv->read_reg(priv, SJA1000_IR); ++ + /* leave reset mode */ + set_normal_mode(dev); + } +diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c +index 96fc7fe8519f..c089fa1ceea9 100644 +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -950,7 +950,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp) + /* Set CPU queue access map - all CPUs have access to all RX + * queues and to all TX queues + */ +- for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) ++ for_each_present_cpu(cpu) + mvreg_write(pp, MVNETA_CPU_MAP(cpu), + (MVNETA_CPU_RXQ_ACCESS_ALL_MASK | + MVNETA_CPU_TXQ_ACCESS_ALL_MASK)); +diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c +index 0d02fba94536..54004a6e2820 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c +@@ -1987,7 +1987,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) + spin_lock_init(&s_state->lock); + } + +- memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size); ++ memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe)); + priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD; + INIT_WORK(&priv->mfunc.master.comm_work, + mlx4_master_comm_channel); +diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c +index e8a1baa87c95..44c2df923fa3 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx4/eq.c +@@ -183,7 +183,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe) + return; + } + +- memcpy(s_eqe, eqe, dev->caps.eqe_size - 1); ++ memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1); + s_eqe->slave_id = slave; + /* ensure all information is written before setting the ownersip bit */ + wmb(); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +index c5f9cb85c8ef..ff08be535a4d 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +@@ -731,10 +731,13 @@ static int stmmac_get_ts_info(struct net_device *dev, + { + struct stmmac_priv *priv = netdev_priv(dev); + +- if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) { ++ if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) { + +- info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | ++ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | ++ SOF_TIMESTAMPING_TX_HARDWARE | ++ SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | ++ SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + if (priv->ptp_clock) +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index e8c21f911b6f..6185874a088e 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -68,7 +68,7 @@ static const struct proto_ops macvtap_socket_ops; + #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ + NETIF_F_TSO6 | NETIF_F_UFO) + #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) +-#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) ++#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST) + + static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev) + { +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index f606b5ba611f..5aa563136373 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -569,7 +569,7 @@ static int pppoe_release(struct socket *sock) + + po = pppox_sk(sk); + +- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { ++ if (po->pppoe_dev) { + dev_put(po->pppoe_dev); + po->pppoe_dev = NULL; + } +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 841b60831df1..5c150a0c5ee2 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1652,9 +1652,9 @@ static int virtnet_probe(struct virtio_device *vdev) + /* Do we support "hardware" checksums? */ + if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { + /* This opens up the world of extra features. */ +- dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; ++ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG; + if (csum) +- dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; ++ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { + dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO +diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c +index a5f9875cfd6e..f84e5d7e8bbe 100644 +--- a/drivers/net/wireless/mwifiex/debugfs.c ++++ b/drivers/net/wireless/mwifiex/debugfs.c +@@ -637,7 +637,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, + (struct mwifiex_private *) file->private_data; + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *) addr; +- int pos = 0, ret = 0, i; ++ int pos, ret, i; + u8 value[MAX_EEPROM_DATA]; + + if (!buf) +@@ -645,7 +645,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, + + if (saved_offset == -1) { + /* No command has been given */ +- pos += snprintf(buf, PAGE_SIZE, "0"); ++ pos = snprintf(buf, PAGE_SIZE, "0"); + goto done; + } + +@@ -654,17 +654,17 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, + (u16) saved_bytes, value); + if (ret) { + ret = -EINVAL; +- goto done; ++ goto out_free; + } + +- pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); ++ pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); + + for (i = 0; i < saved_bytes; i++) +- pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]); +- +- ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); ++ pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]); + + done: ++ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); ++out_free: + free_page(addr); + return ret; + } +diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c +index bbd5888e316b..11c7fcc1048f 100644 +--- a/drivers/staging/rtl8712/usb_intf.c ++++ b/drivers/staging/rtl8712/usb_intf.c +@@ -144,6 +144,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { + {USB_DEVICE(0x0DF6, 0x0058)}, + {USB_DEVICE(0x0DF6, 0x0049)}, + {USB_DEVICE(0x0DF6, 0x004C)}, ++ {USB_DEVICE(0x0DF6, 0x006C)}, + {USB_DEVICE(0x0DF6, 0x0064)}, + /* Skyworth */ + {USB_DEVICE(0x14b2, 0x3300)}, +diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c +index 0924ee40a966..b9adc2ec49dd 100644 +--- a/drivers/usb/class/usblp.c ++++ b/drivers/usb/class/usblp.c +@@ -869,11 +869,11 @@ static int usblp_wwait(struct usblp *usblp, int nonblock) + + add_wait_queue(&usblp->wwait, &waita); + for (;;) { +- set_current_state(TASK_INTERRUPTIBLE); + if (mutex_lock_interruptible(&usblp->mut)) { + rc = -EINTR; + break; + } ++ set_current_state(TASK_INTERRUPTIBLE); + rc = usblp_wtest(usblp, nonblock); + mutex_unlock(&usblp->mut); + if (rc <= 0) +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index ec69b90475c7..d7e0b3651907 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -132,7 +132,7 @@ static inline struct musb *dev_to_musb(struct device *dev) + /*-------------------------------------------------------------------------*/ + + #ifndef CONFIG_BLACKFIN +-static int musb_ulpi_read(struct usb_phy *phy, u32 offset) ++static int musb_ulpi_read(struct usb_phy *phy, u32 reg) + { + void __iomem *addr = phy->io_priv; + int i = 0; +@@ -151,7 +151,7 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) + * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM. + */ + +- musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); ++ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg); + musb_writeb(addr, MUSB_ULPI_REG_CONTROL, + MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR); + +@@ -176,7 +176,7 @@ out: + return ret; + } + +-static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) ++static int musb_ulpi_write(struct usb_phy *phy, u32 val, u32 reg) + { + void __iomem *addr = phy->io_priv; + int i = 0; +@@ -191,8 +191,8 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) + power &= ~MUSB_POWER_SUSPENDM; + musb_writeb(addr, MUSB_POWER, power); + +- musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); +- musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data); ++ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg); ++ musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)val); + musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ); + + while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index c918075e5eae..bdbe642e6569 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -162,6 +162,7 @@ static void option_instat_callback(struct urb *urb); + #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 + #define NOVATELWIRELESS_PRODUCT_E362 0x9010 + #define NOVATELWIRELESS_PRODUCT_E371 0x9011 ++#define NOVATELWIRELESS_PRODUCT_U620L 0x9022 + #define NOVATELWIRELESS_PRODUCT_G2 0xA010 + #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 + +@@ -354,6 +355,7 @@ static void option_instat_callback(struct urb *urb); + /* This is the 4G XS Stick W14 a.k.a. Mobilcom Debitel Surf-Stick * + * It seems to contain a Qualcomm QSC6240/6290 chipset */ + #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603 ++#define FOUR_G_SYSTEMS_PRODUCT_W100 0x9b01 + + /* iBall 3.5G connect wireless modem */ + #define IBALL_3_5G_CONNECT 0x9605 +@@ -527,6 +529,11 @@ static const struct option_blacklist_info four_g_w14_blacklist = { + .sendsetup = BIT(0) | BIT(1), + }; + ++static const struct option_blacklist_info four_g_w100_blacklist = { ++ .sendsetup = BIT(1) | BIT(2), ++ .reserved = BIT(3), ++}; ++ + static const struct option_blacklist_info alcatel_x200_blacklist = { + .sendsetup = BIT(0) | BIT(1), + .reserved = BIT(4), +@@ -1060,6 +1067,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U620L, 0xff, 0x00, 0x00) }, + + { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, + { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, +@@ -1641,6 +1649,9 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), + .driver_info = (kernel_ulong_t)&four_g_w14_blacklist + }, ++ { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W100), ++ .driver_info = (kernel_ulong_t)&four_g_w100_blacklist ++ }, + { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, +diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c +index ec7cea585663..113913823ff3 100644 +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -159,6 +159,7 @@ static const struct usb_device_id ti_id_table_3410[] = { + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, + { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, ++ { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) }, + { } /* terminator */ + }; + +@@ -191,6 +192,7 @@ static const struct usb_device_id ti_id_table_combined[] = { + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, + { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, ++ { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) }, + { } /* terminator */ + }; + +diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h +index 4a2423e84d55..98f35c656c02 100644 +--- a/drivers/usb/serial/ti_usb_3410_5052.h ++++ b/drivers/usb/serial/ti_usb_3410_5052.h +@@ -56,6 +56,10 @@ + #define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID + #define ABBOTT_STRIP_PORT_ID 0x3420 + ++/* Honeywell vendor and product IDs */ ++#define HONEYWELL_VENDOR_ID 0x10ac ++#define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */ ++ + /* Commands */ + #define TI_GET_VERSION 0x01 + #define TI_GET_PORT_STATUS 0x02 +diff --git a/include/net/inet_common.h b/include/net/inet_common.h +index fe7994c48b75..fd1da045dabc 100644 +--- a/include/net/inet_common.h ++++ b/include/net/inet_common.h +@@ -40,7 +40,8 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family, + + static inline void inet_ctl_sock_destroy(struct sock *sk) + { +- sk_release_kernel(sk); ++ if (sk) ++ sk_release_kernel(sk); + } + + #endif +diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c +index d9fb93451442..eda534f61acf 100644 +--- a/net/bluetooth/hidp/core.c ++++ b/net/bluetooth/hidp/core.c +@@ -415,6 +415,20 @@ static void hidp_idle_timeout(unsigned long arg) + { + struct hidp_session *session = (struct hidp_session *) arg; + ++ /* The HIDP user-space API only contains calls to add and remove ++ * devices. There is no way to forward events of any kind. Therefore, ++ * we have to forcefully disconnect a device on idle-timeouts. This is ++ * unfortunate and weird API design, but it is spec-compliant and ++ * required for backwards-compatibility. Hence, on idle-timeout, we ++ * signal driver-detach events, so poll() will be woken up with an ++ * error-condition on both sockets. ++ */ ++ ++ session->intr_sock->sk->sk_err = EUNATCH; ++ session->ctrl_sock->sk->sk_err = EUNATCH; ++ wake_up_interruptible(sk_sleep(session->intr_sock->sk)); ++ wake_up_interruptible(sk_sleep(session->ctrl_sock->sk)); ++ + hidp_session_terminate(session); + } + +diff --git a/net/core/dst.c b/net/core/dst.c +index 15b6792e6ebb..c07070544e3f 100644 +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -283,7 +283,7 @@ void dst_release(struct dst_entry *dst) + + newrefcnt = atomic_dec_return(&dst->__refcnt); + WARN_ON(newrefcnt < 0); +- if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) ++ if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) + call_rcu(&dst->rcu_head, dst_destroy_rcu); + } + } +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 1149fc2290e2..a3d7ccfe154d 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -1674,8 +1674,8 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) + { + struct ip_options *opt = &(IPCB(skb)->opt); + +- IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); +- IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); ++ IP_INC_STATS(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); ++ IP_ADD_STATS(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); + + if (unlikely(opt->optlen)) + ip_forward_options(skb); +@@ -1737,7 +1737,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, + * to blackhole. + */ + +- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS); ++ IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS); + ip_rt_put(rt); + goto out_free; + } +diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c +index 98ad6ec4bd3c..8ad149478e19 100644 +--- a/net/irda/irlmp.c ++++ b/net/irda/irlmp.c +@@ -1876,7 +1876,7 @@ static void *irlmp_seq_hb_idx(struct irlmp_iter_state *iter, loff_t *off) + for (element = hashbin_get_first(iter->hashbin); + element != NULL; + element = hashbin_get_next(iter->hashbin)) { +- if (!off || *off-- == 0) { ++ if (!off || (*off)-- == 0) { + /* NB: hashbin left locked */ + return element; + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index c9535a976b56..fcb2b171b897 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2869,7 +2869,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + + if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold && + ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { +- int sig = ifmgd->ave_beacon_signal; ++ int sig = ifmgd->ave_beacon_signal / 16; + int last_sig = ifmgd->last_ave_beacon_signal; + + /* +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index fee7dcc28abd..c53684eeddb3 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2642,22 +2642,40 @@ static int packet_release(struct socket *sock) + * Attach a packet hook. + */ + +-static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) ++static int packet_do_bind(struct sock *sk, const char *name, int ifindex, ++ __be16 proto) + { + struct packet_sock *po = pkt_sk(sk); + struct net_device *dev_curr; + __be16 proto_curr; + bool need_rehook; ++ struct net_device *dev = NULL; ++ int ret = 0; ++ bool unlisted = false; + +- if (po->fanout) { +- if (dev) +- dev_put(dev); +- ++ if (po->fanout) + return -EINVAL; +- } + + lock_sock(sk); + spin_lock(&po->bind_lock); ++ rcu_read_lock(); ++ ++ if (name) { ++ dev = dev_get_by_name_rcu(sock_net(sk), name); ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ } else if (ifindex) { ++ dev = dev_get_by_index_rcu(sock_net(sk), ifindex); ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ } ++ ++ if (dev) ++ dev_hold(dev); + + proto_curr = po->prot_hook.type; + dev_curr = po->prot_hook.dev; +@@ -2665,14 +2683,29 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + need_rehook = proto_curr != proto || dev_curr != dev; + + if (need_rehook) { +- unregister_prot_hook(sk, true); ++ if (po->running) { ++ rcu_read_unlock(); ++ __unregister_prot_hook(sk, true); ++ rcu_read_lock(); ++ dev_curr = po->prot_hook.dev; ++ if (dev) ++ unlisted = !dev_get_by_index_rcu(sock_net(sk), ++ dev->ifindex); ++ } + + po->num = proto; + po->prot_hook.type = proto; +- po->prot_hook.dev = dev; + +- po->ifindex = dev ? dev->ifindex : 0; +- packet_cached_dev_assign(po, dev); ++ if (unlikely(unlisted)) { ++ dev_put(dev); ++ po->prot_hook.dev = NULL; ++ po->ifindex = -1; ++ packet_cached_dev_reset(po); ++ } else { ++ po->prot_hook.dev = dev; ++ po->ifindex = dev ? dev->ifindex : 0; ++ packet_cached_dev_assign(po, dev); ++ } + } + if (dev_curr) + dev_put(dev_curr); +@@ -2680,7 +2713,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + if (proto == 0 || !need_rehook) + goto out_unlock; + +- if (!dev || (dev->flags & IFF_UP)) { ++ if (!unlisted && (!dev || (dev->flags & IFF_UP))) { + register_prot_hook(sk); + } else { + sk->sk_err = ENETDOWN; +@@ -2689,9 +2722,10 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + } + + out_unlock: ++ rcu_read_unlock(); + spin_unlock(&po->bind_lock); + release_sock(sk); +- return 0; ++ return ret; + } + + /* +@@ -2703,8 +2737,6 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, + { + struct sock *sk = sock->sk; + char name[15]; +- struct net_device *dev; +- int err = -ENODEV; + + /* + * Check legality +@@ -2714,19 +2746,13 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, + return -EINVAL; + strlcpy(name, uaddr->sa_data, sizeof(name)); + +- dev = dev_get_by_name(sock_net(sk), name); +- if (dev) +- err = packet_do_bind(sk, dev, pkt_sk(sk)->num); +- return err; ++ return packet_do_bind(sk, name, 0, pkt_sk(sk)->num); + } + + static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + { + struct sockaddr_ll *sll = (struct sockaddr_ll *)uaddr; + struct sock *sk = sock->sk; +- struct net_device *dev = NULL; +- int err; +- + + /* + * Check legality +@@ -2737,16 +2763,8 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len + if (sll->sll_family != AF_PACKET) + return -EINVAL; + +- if (sll->sll_ifindex) { +- err = -ENODEV; +- dev = dev_get_by_index(sock_net(sk), sll->sll_ifindex); +- if (dev == NULL) +- goto out; +- } +- err = packet_do_bind(sk, dev, sll->sll_protocol ? : pkt_sk(sk)->num); +- +-out: +- return err; ++ return packet_do_bind(sk, NULL, sll->sll_ifindex, ++ sll->sll_protocol ? : pkt_sk(sk)->num); + } + + static struct proto packet_proto = { +diff --git a/net/rds/connection.c b/net/rds/connection.c +index 378c3a6acf84..f5fb7d6b7c41 100644 +--- a/net/rds/connection.c ++++ b/net/rds/connection.c +@@ -183,6 +183,12 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, + } + } + ++ if (trans == NULL) { ++ kmem_cache_free(rds_conn_slab, conn); ++ conn = ERR_PTR(-ENODEV); ++ goto out; ++ } ++ + conn->c_trans = trans; + + ret = trans->conn_alloc(conn, gfp); +diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c +index 4fac4f2bb9dc..8b33d9967b56 100644 +--- a/net/rds/tcp_recv.c ++++ b/net/rds/tcp_recv.c +@@ -234,8 +234,15 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb, + } + + to_copy = min(tc->t_tinc_data_rem, left); +- pskb_pull(clone, offset); +- pskb_trim(clone, to_copy); ++ if (!pskb_pull(clone, offset) || ++ pskb_trim(clone, to_copy)) { ++ pr_warn("rds_tcp_data_recv: pull/trim failed " ++ "left %zu data_rem %zu skb_len %d\n", ++ left, tc->t_tinc_data_rem, skb->len); ++ kfree_skb(clone); ++ desc->error = -ENOMEM; ++ goto out; ++ } + skb_queue_tail(&tinc->ti_skb_list, clone); + + rdsdebug("skb %p data %p len %d off %u to_copy %zu -> " +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index c7aa71ee775b..9123fc518f07 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -174,6 +174,8 @@ struct snd_usb_midi_in_endpoint { + u8 running_status_length; + } ports[0x10]; + u8 seen_f5; ++ bool in_sysex; ++ u8 last_cin; + u8 error_resubmit; + int current_port; + }; +@@ -465,6 +467,39 @@ static void snd_usbmidi_maudio_broken_running_status_input( + } + + /* ++ * QinHeng CH345 is buggy: every second packet inside a SysEx has not CIN 4 ++ * but the previously seen CIN, but still with three data bytes. ++ */ ++static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep, ++ uint8_t *buffer, int buffer_length) ++{ ++ unsigned int i, cin, length; ++ ++ for (i = 0; i + 3 < buffer_length; i += 4) { ++ if (buffer[i] == 0 && i > 0) ++ break; ++ cin = buffer[i] & 0x0f; ++ if (ep->in_sysex && ++ cin == ep->last_cin && ++ (buffer[i + 1 + (cin == 0x6)] & 0x80) == 0) ++ cin = 0x4; ++#if 0 ++ if (buffer[i + 1] == 0x90) { ++ /* ++ * Either a corrupted running status or a real note-on ++ * message; impossible to detect reliably. ++ */ ++ } ++#endif ++ length = snd_usbmidi_cin_length[cin]; ++ snd_usbmidi_input_data(ep, 0, &buffer[i + 1], length); ++ ep->in_sysex = cin == 0x4; ++ if (!ep->in_sysex) ++ ep->last_cin = cin; ++ } ++} ++ ++/* + * CME protocol: like the standard protocol, but SysEx commands are sent as a + * single USB packet preceded by a 0x0F byte. + */ +@@ -650,6 +685,12 @@ static struct usb_protocol_ops snd_usbmidi_cme_ops = { + .output_packet = snd_usbmidi_output_standard_packet, + }; + ++static struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = { ++ .input = ch345_broken_sysex_input, ++ .output = snd_usbmidi_standard_output, ++ .output_packet = snd_usbmidi_output_standard_packet, ++}; ++ + /* + * AKAI MPD16 protocol: + * +@@ -1326,6 +1367,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, + * Various chips declare a packet size larger than 4 bytes, but + * do not actually work with larger packets: + */ ++ case USB_ID(0x0a67, 0x5011): /* Medeli DD305 */ + case USB_ID(0x0a92, 0x1020): /* ESI M4U */ + case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */ + case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */ +@@ -2290,6 +2332,10 @@ int snd_usbmidi_create(struct snd_card *card, + + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; ++ case QUIRK_MIDI_CH345: ++ umidi->usb_protocol_ops = &snd_usbmidi_ch345_broken_sysex_ops; ++ err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); ++ break; + default: + snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); + err = -ENXIO; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 7c24088bcaa4..c600d4277974 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -2875,6 +2875,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), + .idProduct = 0x1020, + }, + ++/* QinHeng devices */ ++{ ++ USB_DEVICE(0x1a86, 0x752d), ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { ++ .vendor_name = "QinHeng", ++ .product_name = "CH345", ++ .ifnum = 1, ++ .type = QUIRK_MIDI_CH345 ++ } ++}, ++ + /* KeithMcMillen Stringport */ + { + USB_DEVICE(0x1f38, 0x0001), +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 827d40441ec7..901f87dea827 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -526,6 +526,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, + [QUIRK_MIDI_CME] = create_any_midi_quirk, + [QUIRK_MIDI_AKAI] = create_any_midi_quirk, + [QUIRK_MIDI_FTDI] = create_any_midi_quirk, ++ [QUIRK_MIDI_CH345] = create_any_midi_quirk, + [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, + [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, + [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, +diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h +index 5d2fe0530745..e5b2c30a8e90 100644 +--- a/sound/usb/usbaudio.h ++++ b/sound/usb/usbaudio.h +@@ -84,6 +84,7 @@ enum quirk_type { + QUIRK_MIDI_AKAI, + QUIRK_MIDI_US122L, + QUIRK_MIDI_FTDI, ++ QUIRK_MIDI_CH345, + QUIRK_AUDIO_STANDARD_INTERFACE, + QUIRK_AUDIO_FIXED_ENDPOINT, + QUIRK_AUDIO_EDIROL_UAXX, |