This is the 3.10.94 stable release

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJWaHZOAAoJEDjbvchgkmk+my0P/jsD1AGpZ5MFfMAktU9icsRe
 vW4jp81LEsjkhNQiQ7jbSztUh5tLPnBjXH7qyK9UggzRnhuucHLqn488GTSTrg0n
 1kXAhnwOdZeFSw/eTInDZ9jEWD3f9w+ZKJeissK0Q0gBNocBgsd4iidjyxlOXTMd
 7P19EH0ys4YL42KfvRm/3t+cT09/2VGk+Y0rDqU0xpQM7ZhRPdmdewRMtk6L0YiX
 +Ijypv+3C5Zv1JE4Y7+V7EG535jhYHnlnXnsnpSMmUHHusAGnPHl6rwk2o/7zwJZ
 /aDRCqTqAnncGS3+e/5/0AIvLbdqKbbnp0P8vXOFZ8RDZU3z7TxlO29j1R9tjceT
 80kQDAwWN/1UXUsjny0W+1ozTf5KkH6VibgBbZRrbcZ9NkiurMayXeMbfysCy3An
 OAyHxVv2gwQ/QYJp54UBAmT5fyKq6AhO9C7l+Iedt9/yuT17E69+QTkMaUc9BCZ7
 OG5Sf1H2umcRraWSc//bxyjzXkLm4kgginNuNSCa6xkVJBW+EzAssovJqV53w62U
 aZu/gRtbVP88m6Ay+QhwHkeyO1yJiVO+0ssyo4gj+tBsKnf66u/c3i9QExn3fepk
 3nr61ooKgm4wdBVOArFwLxY2PjkpGG+hR9L/sHvxTf6ULTauWD5kwdsv0LP2mJhw
 wKgrcBhfo+1LGJnJoowF
 =pOAT
 -----END PGP SIGNATURE-----

Merge tag 'v3.10.94' into HEAD

This is the 3.10.94 stable release
This commit is contained in:
Luca Stefani 2017-04-18 17:12:56 +02:00
commit 7492d477e6
32 changed files with 176 additions and 47 deletions

View File

@ -1,6 +1,6 @@
VERSION = 3
PATCHLEVEL = 10
SUBLEVEL = 93
SUBLEVEL = 94
EXTRAVERSION =
NAME = TOSSUG Baby Fish

View File

@ -1487,12 +1487,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) {

View File

@ -498,7 +498,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);

View File

@ -85,14 +85,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]

View File

@ -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)) {

View File

@ -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

View File

@ -1159,6 +1159,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();

View File

@ -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

View File

@ -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);
}

View File

@ -910,7 +910,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));

View File

@ -1836,7 +1836,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);

View File

@ -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();

View File

@ -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)

View File

@ -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;
}

View File

@ -1545,9 +1545,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

View File

@ -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;
}

View File

@ -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)},

View File

@ -870,11 +870,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)

View File

@ -133,7 +133,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;
@ -152,7 +152,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);
@ -177,7 +177,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;
@ -192,8 +192,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)

View File

@ -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) },

View File

@ -40,7 +40,8 @@ extern 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

View File

@ -396,6 +396,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);
}

View File

@ -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);
}
}

View File

@ -1672,8 +1672,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);
@ -1735,7 +1735,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;
}

View File

@ -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;
}

View File

@ -3074,7 +3074,7 @@ 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;
/*

View File

@ -177,6 +177,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);

View File

@ -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 -> "

View File

@ -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;
};
@ -464,6 +466,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 */
@ -2214,6 +2256,10 @@ int snd_usbmidi_create(struct snd_card *card,
if (err < 0)
break;
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:

View File

@ -3041,6 +3041,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),

View File

@ -318,6 +318,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,

View File

@ -83,6 +83,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,