aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-09 12:58:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-09 12:58:11 -0500
commitd93d4ce103fdd6c6689e94cfbd0316b027d6ead2 (patch)
tree7d28acab8905fc77005b0d09ef4c8bcb0ff45a29
parentd1041cdc60bc122aac09f822aad1ff6c5cb84406 (diff)
parent75ee94b20b46459e3d29f5ac2c3af3cebdeef777 (diff)
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
-rw-r--r--include/sound/seq_kernel.h3
-rw-r--r--include/sound/timer.h2
-rw-r--r--sound/core/hrtimer.c1
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c4
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c29
-rw-r--r--sound/core/seq/oss/seq_oss_readq.h2
-rw-r--r--sound/core/timer.c67
-rw-r--r--sound/pci/hda/patch_realtek.c5
-rw-r--r--sound/usb/quirks.c1
9 files changed, 97 insertions, 17 deletions
diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
index feb58d455560..4b9ee3009aa0 100644
--- a/include/sound/seq_kernel.h
+++ b/include/sound/seq_kernel.h
@@ -49,7 +49,8 @@ typedef union snd_seq_timestamp snd_seq_timestamp_t;
49#define SNDRV_SEQ_DEFAULT_CLIENT_EVENTS 200 49#define SNDRV_SEQ_DEFAULT_CLIENT_EVENTS 200
50 50
51/* max delivery path length */ 51/* max delivery path length */
52#define SNDRV_SEQ_MAX_HOPS 10 52/* NOTE: this shouldn't be greater than MAX_LOCKDEP_SUBCLASSES */
53#define SNDRV_SEQ_MAX_HOPS 8
53 54
54/* max size of event size */ 55/* max size of event size */
55#define SNDRV_SEQ_MAX_EVENT_LEN 0x3fffffff 56#define SNDRV_SEQ_MAX_EVENT_LEN 0x3fffffff
diff --git a/include/sound/timer.h b/include/sound/timer.h
index c4d76ff056c6..7ae226ab6990 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -90,6 +90,8 @@ struct snd_timer {
90 struct list_head ack_list_head; 90 struct list_head ack_list_head;
91 struct list_head sack_list_head; /* slow ack list head */ 91 struct list_head sack_list_head; /* slow ack list head */
92 struct tasklet_struct task_queue; 92 struct tasklet_struct task_queue;
93 int max_instances; /* upper limit of timer instances */
94 int num_instances; /* current number of timer instances */
93}; 95};
94 96
95struct snd_timer_instance { 97struct snd_timer_instance {
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
index 1ac0c423903e..6e47b823bcaa 100644
--- a/sound/core/hrtimer.c
+++ b/sound/core/hrtimer.c
@@ -159,6 +159,7 @@ static int __init snd_hrtimer_init(void)
159 timer->hw = hrtimer_hw; 159 timer->hw = hrtimer_hw;
160 timer->hw.resolution = resolution; 160 timer->hw.resolution = resolution;
161 timer->hw.ticks = NANO_SEC / resolution; 161 timer->hw.ticks = NANO_SEC / resolution;
162 timer->max_instances = 100; /* lower the limit */
162 163
163 err = snd_timer_global_register(timer); 164 err = snd_timer_global_register(timer);
164 if (err < 0) { 165 if (err < 0) {
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index aaff9ee32695..b30b2139e3f0 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -612,9 +612,7 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq
612 if (!dp->timer->running) 612 if (!dp->timer->running)
613 len = snd_seq_oss_timer_start(dp->timer); 613 len = snd_seq_oss_timer_start(dp->timer);
614 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { 614 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
615 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) 615 snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev);
616 snd_seq_oss_readq_puts(dp->readq, mdev->seq_device,
617 ev->data.ext.ptr, ev->data.ext.len);
618 } else { 616 } else {
619 len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev); 617 len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev);
620 if (len > 0) 618 if (len > 0)
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 046cb586fb2f..06b21226b4e7 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -118,6 +118,35 @@ snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, in
118} 118}
119 119
120/* 120/*
121 * put MIDI sysex bytes; the event buffer may be chained, thus it has
122 * to be expanded via snd_seq_dump_var_event().
123 */
124struct readq_sysex_ctx {
125 struct seq_oss_readq *readq;
126 int dev;
127};
128
129static int readq_dump_sysex(void *ptr, void *buf, int count)
130{
131 struct readq_sysex_ctx *ctx = ptr;
132
133 return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count);
134}
135
136int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
137 struct snd_seq_event *ev)
138{
139 struct readq_sysex_ctx ctx = {
140 .readq = q,
141 .dev = dev
142 };
143
144 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
145 return 0;
146 return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx);
147}
148
149/*
121 * copy an event to input queue: 150 * copy an event to input queue:
122 * return zero if enqueued 151 * return zero if enqueued
123 */ 152 */
diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h
index f1463f1f449e..8d033ca2d23f 100644
--- a/sound/core/seq/oss/seq_oss_readq.h
+++ b/sound/core/seq/oss/seq_oss_readq.h
@@ -44,6 +44,8 @@ void snd_seq_oss_readq_delete(struct seq_oss_readq *q);
44void snd_seq_oss_readq_clear(struct seq_oss_readq *readq); 44void snd_seq_oss_readq_clear(struct seq_oss_readq *readq);
45unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait); 45unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait);
46int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len); 46int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len);
47int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
48 struct snd_seq_event *ev);
47int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev); 49int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev);
48int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode); 50int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode);
49int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec); 51int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 6cdd04a45962..15e82a656d96 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -180,7 +180,7 @@ static void snd_timer_request(struct snd_timer_id *tid)
180 * 180 *
181 * call this with register_mutex down. 181 * call this with register_mutex down.
182 */ 182 */
183static void snd_timer_check_slave(struct snd_timer_instance *slave) 183static int snd_timer_check_slave(struct snd_timer_instance *slave)
184{ 184{
185 struct snd_timer *timer; 185 struct snd_timer *timer;
186 struct snd_timer_instance *master; 186 struct snd_timer_instance *master;
@@ -190,16 +190,21 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
190 list_for_each_entry(master, &timer->open_list_head, open_list) { 190 list_for_each_entry(master, &timer->open_list_head, open_list) {
191 if (slave->slave_class == master->slave_class && 191 if (slave->slave_class == master->slave_class &&
192 slave->slave_id == master->slave_id) { 192 slave->slave_id == master->slave_id) {
193 if (master->timer->num_instances >=
194 master->timer->max_instances)
195 return -EBUSY;
193 list_move_tail(&slave->open_list, 196 list_move_tail(&slave->open_list,
194 &master->slave_list_head); 197 &master->slave_list_head);
198 master->timer->num_instances++;
195 spin_lock_irq(&slave_active_lock); 199 spin_lock_irq(&slave_active_lock);
196 slave->master = master; 200 slave->master = master;
197 slave->timer = master->timer; 201 slave->timer = master->timer;
198 spin_unlock_irq(&slave_active_lock); 202 spin_unlock_irq(&slave_active_lock);
199 return; 203 return 0;
200 } 204 }
201 } 205 }
202 } 206 }
207 return 0;
203} 208}
204 209
205/* 210/*
@@ -208,7 +213,7 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
208 * 213 *
209 * call this with register_mutex down. 214 * call this with register_mutex down.
210 */ 215 */
211static void snd_timer_check_master(struct snd_timer_instance *master) 216static int snd_timer_check_master(struct snd_timer_instance *master)
212{ 217{
213 struct snd_timer_instance *slave, *tmp; 218 struct snd_timer_instance *slave, *tmp;
214 219
@@ -216,7 +221,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
216 list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) { 221 list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
217 if (slave->slave_class == master->slave_class && 222 if (slave->slave_class == master->slave_class &&
218 slave->slave_id == master->slave_id) { 223 slave->slave_id == master->slave_id) {
224 if (master->timer->num_instances >=
225 master->timer->max_instances)
226 return -EBUSY;
219 list_move_tail(&slave->open_list, &master->slave_list_head); 227 list_move_tail(&slave->open_list, &master->slave_list_head);
228 master->timer->num_instances++;
220 spin_lock_irq(&slave_active_lock); 229 spin_lock_irq(&slave_active_lock);
221 spin_lock(&master->timer->lock); 230 spin_lock(&master->timer->lock);
222 slave->master = master; 231 slave->master = master;
@@ -228,8 +237,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
228 spin_unlock_irq(&slave_active_lock); 237 spin_unlock_irq(&slave_active_lock);
229 } 238 }
230 } 239 }
240 return 0;