forked from luck/tmp_suning_uos_patched
sound fixes for 4.14
The amount of the changes isn't as quite small as wished, nevertheless they are straight fixes that deserve merging to 4.14 final. Most of fixes are about ALSA core bugs spotted by fuzzer: a follow-up fix for the previous nested rwsem patch, a fix to avoid the resource hogs due to too many concurrent ALSA timer invocations, and a fix for a crash with SYSEX MIDI transfer over OSS sequencer emulation that is used by none but fuzzer. The rest are usual HD-audio and USB-audio device-specific quirks, which are safe to apply. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEECxfAB4MH3rD5mfB6bDGAVD0pKaQFAloEM2wOHHRpd2FpQHN1 c2UuZGUACgkQbDGAVD0pKaTBhA//RLxylDxyZ/OPOpvCIcF9pPhZdt5Ep16h5bFd fr/AmipflVkba6K7auT5JpcwBC+w+24VN2G8huUTZ+HAH1lVVqiSs+XZYw2sHlOi uL/DZ0pEVN8412UH/7Iu4vYeiz/XRzd1YtGQkFI4KKrwm10Vz2sR6JHgvLh30/Zz pyZrMSsu29yrT1R4l0zI5abEBs23n7vYpi9vsKInP44UkGZwi5iKPH0ThTrCJ92A uKOAhIJkGZk0q9GCWnVhe/NWF6t0YK7c4FWqTgXOmIdDpGfylwdjdAsFAFG/cs4x n4pZiwO3seFH+6fr4fc0esNqN/adj+15YEyzUmt12ctLKLEELFhJowT9Grnz1Zoq jswfkXMJIWdqHQ3YBxlhs4Q8ZM7fDXf/gYqsOIRolxy6dtrJ1SLVjJkhtYWx/T+V P++ftn9CQneji1/wqAqUw4HVyc+36rLYK60GKDVtrTCigyilCrq84Yj8W0qAqKJD /CK77d1NKdVZ4do+GpzXjwpwNs6LzjSjqkNH2hdDG4gBNoILxxo9GNYSnjOiLxm4 UCFA6SkD4vlq70VT3vn9YleFq2FzNADQ8jVgliyL1+4mF5baPXKHAdtGJA/HI7Nz 23wf/1zIoOXd+GymaI20ke2EaVvTVVLDyvQSwFVspmSfu6MA0faGy8AUFJWCR8Nh heXgbu0= =Q2mh -----END PGP SIGNATURE----- Merge tag 'sound-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "The amount of the changes isn't as quite small as wished, nevertheless they are straight fixes that deserve merging to 4.14 final. Most of fixes are about ALSA core bugs spotted by fuzzer: a follow-up fix for the previous nested rwsem patch, a fix to avoid the resource hogs due to too many concurrent ALSA timer invocations, and a fix for a crash with SYSEX MIDI transfer over OSS sequencer emulation that is used by none but fuzzer. The rest are usual HD-audio and USB-audio device-specific quirks, which are safe to apply" * tag 'sound-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda - fix headset mic problem for Dell machines with alc274 ALSA: seq: Fix OSS sysex delivery in OSS emulation ALSA: seq: Avoid invalid lockdep class warning ALSA: timer: Limit max instances per timer ALSA: usb-audio: support new Amanero Combo384 firmware version
This commit is contained in:
commit
d93d4ce103
|
@ -49,7 +49,8 @@ typedef union snd_seq_timestamp snd_seq_timestamp_t;
|
|||
#define SNDRV_SEQ_DEFAULT_CLIENT_EVENTS 200
|
||||
|
||||
/* max delivery path length */
|
||||
#define SNDRV_SEQ_MAX_HOPS 10
|
||||
/* NOTE: this shouldn't be greater than MAX_LOCKDEP_SUBCLASSES */
|
||||
#define SNDRV_SEQ_MAX_HOPS 8
|
||||
|
||||
/* max size of event size */
|
||||
#define SNDRV_SEQ_MAX_EVENT_LEN 0x3fffffff
|
||||
|
|
|
@ -90,6 +90,8 @@ struct snd_timer {
|
|||
struct list_head ack_list_head;
|
||||
struct list_head sack_list_head; /* slow ack list head */
|
||||
struct tasklet_struct task_queue;
|
||||
int max_instances; /* upper limit of timer instances */
|
||||
int num_instances; /* current number of timer instances */
|
||||
};
|
||||
|
||||
struct snd_timer_instance {
|
||||
|
|
|
@ -159,6 +159,7 @@ static int __init snd_hrtimer_init(void)
|
|||
timer->hw = hrtimer_hw;
|
||||
timer->hw.resolution = resolution;
|
||||
timer->hw.ticks = NANO_SEC / resolution;
|
||||
timer->max_instances = 100; /* lower the limit */
|
||||
|
||||
err = snd_timer_global_register(timer);
|
||||
if (err < 0) {
|
||||
|
|
|
@ -612,9 +612,7 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq
|
|||
if (!dp->timer->running)
|
||||
len = snd_seq_oss_timer_start(dp->timer);
|
||||
if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
|
||||
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
|
||||
snd_seq_oss_readq_puts(dp->readq, mdev->seq_device,
|
||||
ev->data.ext.ptr, ev->data.ext.len);
|
||||
snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev);
|
||||
} else {
|
||||
len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
|
||||
if (len > 0)
|
||||
|
|
|
@ -117,6 +117,35 @@ snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, in
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* put MIDI sysex bytes; the event buffer may be chained, thus it has
|
||||
* to be expanded via snd_seq_dump_var_event().
|
||||
*/
|
||||
struct readq_sysex_ctx {
|
||||
struct seq_oss_readq *readq;
|
||||
int dev;
|
||||
};
|
||||
|
||||
static int readq_dump_sysex(void *ptr, void *buf, int count)
|
||||
{
|
||||
struct readq_sysex_ctx *ctx = ptr;
|
||||
|
||||
return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count);
|
||||
}
|
||||
|
||||
int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
|
||||
struct snd_seq_event *ev)
|
||||
{
|
||||
struct readq_sysex_ctx ctx = {
|
||||
.readq = q,
|
||||
.dev = dev
|
||||
};
|
||||
|
||||
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
|
||||
return 0;
|
||||
return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an event to input queue:
|
||||
* return zero if enqueued
|
||||
|
|
|
@ -44,6 +44,8 @@ void snd_seq_oss_readq_delete(struct seq_oss_readq *q);
|
|||
void snd_seq_oss_readq_clear(struct seq_oss_readq *readq);
|
||||
unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait);
|
||||
int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len);
|
||||
int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
|
||||
struct snd_seq_event *ev);
|
||||
int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev);
|
||||
int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode);
|
||||
int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec);
|
||||
|
|
|
@ -180,7 +180,7 @@ static void snd_timer_request(struct snd_timer_id *tid)
|
|||
*
|
||||
* call this with register_mutex down.
|
||||
*/
|
||||
static void snd_timer_check_slave(struct snd_timer_instance *slave)
|
||||
static int snd_timer_check_slave(struct snd_timer_instance *slave)
|
||||
{
|
||||
struct snd_timer *timer;
|
||||
struct snd_timer_instance *master;
|
||||
|
@ -190,16 +190,21 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
|
|||
list_for_each_entry(master, &timer->open_list_head, open_list) {
|
||||
if (slave->slave_class == master->slave_class &&
|
||||
slave->slave_id == master->slave_id) {
|
||||
if (master->timer->num_instances >=
|
||||
master->timer->max_instances)
|
||||
return -EBUSY;
|
||||
list_move_tail(&slave->open_list,
|
||||
&master->slave_list_head);
|
||||
master->timer->num_instances++;
|
||||
spin_lock_irq(&slave_active_lock);
|
||||
slave->master = master;
|
||||
slave->timer = master->timer;
|
||||
spin_unlock_irq(&slave_active_lock);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -208,7 +213,7 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
|
|||
*
|
||||
* call this with register_mutex down.
|
||||
*/
|
||||
static void snd_timer_check_master(struct snd_timer_instance *master)
|
||||
static int snd_timer_check_master(struct snd_timer_instance *master)
|
||||
{
|
||||
struct snd_timer_instance *slave, *tmp;
|
||||
|
||||
|
@ -216,7 +221,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
|
|||
list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
|
||||
if (slave->slave_class == master->slave_class &&
|
||||
slave->slave_id == master->slave_id) {
|
||||
if (master->timer->num_instances >=
|
||||
master->timer->max_instances)
|
||||
return -EBUSY;
|
||||
list_move_tail(&slave->open_list, &master->slave_list_head);
|
||||
master->timer->num_instances++;
|
||||
spin_lock_irq(&slave_active_lock);
|
||||
spin_lock(&master->timer->lock);
|
||||
slave->master = master;
|
||||
|
@ -228,8 +237,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
|
|||
spin_unlock_irq(&slave_active_lock);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_timer_close_locked(struct snd_timer_instance *timeri);
|
||||
|
||||
/*
|
||||
* open a timer instance
|
||||
* when opening a master, the slave id must be here given.
|
||||
|
@ -240,6 +252,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
|
|||
{
|
||||
struct snd_timer *timer;
|
||||
struct snd_timer_instance *timeri = NULL;
|
||||
int err;
|
||||
|
||||
if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
|
||||
/* open a slave instance */
|
||||
|
@ -259,10 +272,14 @@ int snd_timer_open(struct snd_timer_instance **ti,
|
|||
timeri->slave_id = tid->device;
|
||||
timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
|
||||
list_add_tail(&timeri->open_list, &snd_timer_slave_list);
|
||||
snd_timer_check_slave(timeri);
|
||||
err = snd_timer_check_slave(timeri);
|
||||
if (err < 0) {
|
||||
snd_timer_close_locked(timeri);
|
||||
timeri = NULL;
|
||||
}
|
||||
mutex_unlock(®ister_mutex);
|
||||
*ti = timeri;
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* open a master instance */
|
||||
|
@ -288,6 +305,10 @@ int snd_timer_open(struct snd_timer_instance **ti,
|
|||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
if (timer->num_instances >= timer->max_instances) {
|
||||
mutex_unlock(®ister_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
timeri = snd_timer_instance_new(owner, timer);
|
||||
if (!timeri) {
|
||||
mutex_unlock(®ister_mutex);
|
||||
|
@ -314,25 +335,27 @@ int snd_timer_open(struct snd_timer_instance **ti,
|
|||
}
|
||||
|
||||
list_add_tail(&timeri->open_list, &timer->open_list_head);
|
||||
snd_timer_check_master(timeri);
|
||||
timer->num_instances++;
|
||||
err = snd_timer_check_master(timeri);
|
||||
if (err < 0) {
|
||||
snd_timer_close_locked(timeri);
|
||||
timeri = NULL;
|
||||
}
|
||||
mutex_unlock(®ister_mutex);
|
||||
*ti = timeri;
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_timer_open);
|
||||
|
||||
/*
|
||||
* close a timer instance
|
||||
* call this with register_mutex down.
|
||||
*/
|
||||
int snd_timer_close(struct snd_timer_instance *timeri)
|
||||
static int snd_timer_close_locked(struct snd_timer_instance *timeri)
|
||||
{
|
||||
struct snd_timer *timer = NULL;
|
||||
struct snd_timer_instance *slave, *tmp;
|
||||
|
||||
if (snd_BUG_ON(!timeri))
|
||||
return -ENXIO;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
list_del(&timeri->open_list);
|
||||
|
||||
/* force to stop the timer */
|
||||
|
@ -340,6 +363,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
|||
|
||||
timer = timeri->timer;
|
||||
if (timer) {
|
||||
timer->num_instances--;
|
||||
/* wait, until the active callback is finished */
|
||||
spin_lock_irq(&timer->lock);
|
||||
while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
|
||||
|
@ -355,6 +379,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
|||
list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
|
||||
open_list) {
|
||||
list_move_tail(&slave->open_list, &snd_timer_slave_list);
|
||||
timer->num_instances--;
|
||||
slave->master = NULL;
|
||||
slave->timer = NULL;
|
||||
list_del_init(&slave->ack_list);
|
||||
|
@ -382,9 +407,24 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
|||
module_put(timer->module);
|
||||
}
|
||||
|
||||
mutex_unlock(®ister_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* close a timer instance
|
||||
*/
|
||||
int snd_timer_close(struct snd_timer_instance *timeri)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (snd_BUG_ON(!timeri))
|
||||
return -ENXIO;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
err = snd_timer_close_locked(timeri);
|
||||
mutex_unlock(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_timer_close);
|
||||
|
||||
unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
|
||||
|
@ -856,6 +896,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
|
|||
spin_lock_init(&timer->lock);
|
||||
tasklet_init(&timer->task_queue, snd_timer_tasklet,
|
||||
(unsigned long)timer);
|
||||
timer->max_instances = 1000; /* default limit per timer */
|
||||
if (card != NULL) {
|
||||
timer->module = card->module;
|
||||
err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);
|
||||
|
|
|
@ -6544,6 +6544,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
|||
{0x14, 0x90170110},
|
||||
{0x1b, 0x90a70130},
|
||||
{0x21, 0x03211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
{0x12, 0xb7a60130},
|
||||
{0x13, 0xb8a61140},
|
||||
{0x16, 0x90170110},
|
||||
{0x21, 0x04211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
|
||||
{0x12, 0x90a60130},
|
||||
{0x14, 0x90170110},
|
||||
|
|
|
@ -1375,6 +1375,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
|
|||
case 0x199:
|
||||
return SNDRV_PCM_FMTBIT_DSD_U32_LE;
|
||||
case 0x19b:
|
||||
case 0x203:
|
||||
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue
Block a user