From 9cd641ed31f576d08f7b784850ba93eef050f32f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Jul 2018 14:46:27 +0200 Subject: ALSA: pcm: trace XRUN event at injection, too The PCM xrun injection triggers directly snd_pcm_stop() without the standard xrun handler, hence it's not recorded on the event buffer. Ditto for snd_pcm_stop_xrun() call and SNDRV_PCM_IOCTL_XRUN ioctl. They are inconvenient from the debugging POV. Let's make them to trigger XRUN via the standard helper more consistently. Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 2 +- sound/core/pcm_lib.c | 7 ++++--- sound/core/pcm_local.h | 2 ++ sound/core/pcm_native.c | 8 ++++---- 4 files changed, 11 insertions(+), 8 deletions(-) (limited to 'sound/core') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index c352bfb973cc..6f037a4b8b52 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -497,7 +497,7 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry, snd_pcm_stream_lock_irq(substream); runtime = substream->runtime; if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + __snd_pcm_xrun(substream); snd_pcm_stream_unlock_irq(substream); } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 44b5ae833082..c1d2e8e1fc6b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -153,7 +153,8 @@ EXPORT_SYMBOL(snd_pcm_debug_name); dump_stack(); \ } while (0) -static void xrun(struct snd_pcm_substream *substream) +/* call with stream lock held */ +void __snd_pcm_xrun(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -201,7 +202,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, } } else { if (avail >= runtime->stop_threshold) { - xrun(substream); + __snd_pcm_xrun(substream); return -EPIPE; } } @@ -297,7 +298,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, } if (pos == SNDRV_PCM_POS_XRUN) { - xrun(substream); + __snd_pcm_xrun(substream); return -EPIPE; } if (pos >= runtime->buffer_size) { diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h index 7a499d02df6c..c515612969a4 100644 --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h @@ -65,4 +65,6 @@ static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {} static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {} #endif +void __snd_pcm_xrun(struct snd_pcm_substream *substream); + #endif /* __SOUND_CORE_PCM_LOCAL_H */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index cecc79772c94..20174d0c0527 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1337,13 +1337,12 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream) int snd_pcm_stop_xrun(struct snd_pcm_substream *substream) { unsigned long flags; - int ret = 0; snd_pcm_stream_lock_irqsave(substream, flags); if (snd_pcm_running(substream)) - ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + __snd_pcm_xrun(substream); snd_pcm_stream_unlock_irqrestore(substream, flags); - return ret; + return 0; } EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun); @@ -1591,7 +1590,8 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) result = 0; /* already there */ break; case SNDRV_PCM_STATE_RUNNING: - result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + __snd_pcm_xrun(substream); + result = 0; break; default: result = -EBADFD; -- cgit v1.2.1 From e647f5a5c5d165c87750e8c0dcbe341b5a378ffd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Jul 2018 15:08:05 +0200 Subject: ALSA: pcm: Use snd_pcm_stop_xrun() for xrun injection Basically the xrun injection routine can simply call the standard helper snd_pcm_stop_xrun(), but with one exception: it may be called even when the stream is closed. Make snd_pcm_stop_xrun() more robust and check the NULL runtime state, and simplify xrun injection code by calling it. Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 7 +------ sound/core/pcm_native.c | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'sound/core') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 6f037a4b8b52..fdb9b92fc8d6 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -492,13 +492,8 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime; - snd_pcm_stream_lock_irq(substream); - runtime = substream->runtime; - if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING) - __snd_pcm_xrun(substream); - snd_pcm_stream_unlock_irq(substream); + snd_pcm_stop_xrun(substream); } static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 20174d0c0527..66c90f486af9 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1339,7 +1339,7 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream) unsigned long flags; snd_pcm_stream_lock_irqsave(substream, flags); - if (snd_pcm_running(substream)) + if (substream->runtime && snd_pcm_running(substream)) __snd_pcm_xrun(substream); snd_pcm_stream_unlock_irqrestore(substream, flags); return 0; -- cgit v1.2.1 From d64c5cf8e89d124355924c513a42b16f0d7d3a03 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 6 Jul 2018 13:50:36 +0100 Subject: ALSA: pcm: Allow drivers to set R/W wait time. Currently ALSA core blocks userspace for about 10 seconds for PCM R/W IO. This needs to be configurable for modern hardware like DSPs where no pointer update in milliseconds can indicate terminal DSP errors. Add a substream variable to set the wait time in ms. This allows userspace and drivers to recover more quickly from terminal DSP errors. Signed-off-by: Liam Girdwood Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'sound/core') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index c1d2e8e1fc6b..5736860f325b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1833,12 +1833,19 @@ static int wait_for_avail(struct snd_pcm_substream *substream, if (runtime->no_period_wakeup) wait_time = MAX_SCHEDULE_TIMEOUT; else { - wait_time = 10; - if (runtime->rate) { - long t = runtime->period_size * 2 / runtime->rate; - wait_time = max(t, wait_time); + /* use wait time from substream if available */ + if (substream->wait_time) { + wait_time = substream->wait_time; + } else { + wait_time = 10; + + if (runtime->rate) { + long t = runtime->period_size * 2 / + runtime->rate; + wait_time = max(t, wait_time); + } + wait_time = msecs_to_jiffies(wait_time * 1000); } - wait_time = msecs_to_jiffies(wait_time * 1000); } for (;;) { -- cgit v1.2.1 From ff2d6acdf6f13d9f8fdcd890844c6d7535ac1f10 Mon Sep 17 00:00:00 2001 From: Timo Wischer Date: Tue, 10 Jul 2018 17:28:45 +0200 Subject: ALSA: pcm: Fix snd_interval_refine first/last with open min/max Without this commit the following intervals [x y), (x y) were be replaced to (y-1 y) by snd_interval_refine_last(). This was also done if y-1 is part of the previous interval. With this changes it will be replaced with [y-1 y) in case of y-1 is part of the previous interval. A similar behavior will be used for snd_interval_refine_first(). This commit adapts the changes for alsa-lib of commit 9bb985c ("pcm: snd_interval_refine_first/last: exclude value only if also excluded before") Signed-off-by: Timo Wischer Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'sound/core') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 5736860f325b..4e6110d778bd 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -627,27 +627,33 @@ EXPORT_SYMBOL(snd_interval_refine); static int snd_interval_refine_first(struct snd_interval *i) { + const unsigned int last_max = i->max; + if (snd_BUG_ON(snd_interval_empty(i))) return -EINVAL; if (snd_interval_single(i)) return 0; i->max = i->min; - i->openmax = i->openmin; - if (i->openmax) + if (i->openmin) i->max++; + /* only exclude max value if also excluded before refine */ + i->openmax = (i->openmax && i->max >= last_max); return 1; } static int snd_interval_refine_last(struct snd_interval *i) { + const unsigned int last_min = i->min; + if (snd_BUG_ON(snd_interval_empty(i))) return -EINVAL; if (snd_interval_single(i)) return 0; i->min = i->max; - i->openmin = i->openmax; - if (i->openmin) + if (i->openmax) i->min--; + /* only exclude min value if also excluded before refine */ + i->openmin = (i->openmin && i->min <= last_min); return 1; } -- cgit v1.2.1 From 5bed9139727f3bad06c9444bd092336a59397e9d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 22:32:52 +0200 Subject: ALSA: rawmidi: Tidy up coding styles Just minor coding style fixes like removal of superfluous white space, adding missing blank lines, etc. No actual code changes at all. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 101 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 42 deletions(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index b53026a72e73..14dec13ecde9 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -88,6 +88,7 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file) static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime = substream->runtime; + return runtime->avail >= runtime->avail_min; } @@ -95,6 +96,7 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre size_t count) { struct snd_rawmidi_runtime *runtime = substream->runtime; + return runtime->avail >= runtime->avail_min && (!substream->append || runtime->avail >= count); } @@ -103,6 +105,7 @@ static void snd_rawmidi_input_event_work(struct work_struct *work) { struct snd_rawmidi_runtime *runtime = container_of(work, struct snd_rawmidi_runtime, event_work); + if (runtime->event) runtime->event(runtime->substream); } @@ -111,7 +114,8 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime; - if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL) + runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); + if (!runtime) return -ENOMEM; runtime->substream = substream; spin_lock_init(&runtime->lock); @@ -124,7 +128,8 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) runtime->avail = 0; else runtime->avail = runtime->buffer_size; - if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) { + runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL); + if (!runtime->buffer) { kfree(runtime); return -ENOMEM; } @@ -143,7 +148,7 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) return 0; } -static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) +static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) { if (!substream->opened) return; @@ -330,7 +335,7 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, /* called from sound/core/seq/seq_midi.c */ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, - int mode, struct snd_rawmidi_file * rfile) + int mode, struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; int err; @@ -370,7 +375,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) struct snd_rawmidi_file *rawmidi_file = NULL; wait_queue_entry_t wait; - if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) + if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ err = nonseekable_open(inode, file); @@ -520,7 +525,7 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) if (snd_BUG_ON(!rfile)) return -ENXIO; - + rmidi = rfile->rmidi; rawmidi_release_priv(rfile); module_put(rmidi->card->module); @@ -548,7 +553,7 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, struct snd_rawmidi_info *info) { struct snd_rawmidi *rmidi; - + if (substream == NULL) return -ENODEV; rmidi = substream->rmidi; @@ -568,11 +573,13 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, } static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_info __user * _info) + struct snd_rawmidi_info __user *_info) { struct snd_rawmidi_info info; int err; - if ((err = snd_rawmidi_info(substream, &info)) < 0) + + err = snd_rawmidi_info(substream, &info); + if (err < 0) return err; if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info))) return -EFAULT; @@ -619,13 +626,15 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, { int err; struct snd_rawmidi_info info; + if (get_user(info.device, &_info->device)) return -EFAULT; if (get_user(info.stream, &_info->stream)) return -EFAULT; if (get_user(info.subdevice, &_info->subdevice)) return -EFAULT; - if ((err = snd_rawmidi_info_select(card, &info)) < 0) + err = snd_rawmidi_info_select(card, &info); + if (err < 0) return err; if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info))) return -EFAULT; @@ -633,20 +642,18 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, } int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params * params) + struct snd_rawmidi_params *params) { char *newbuf, *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; - + if (substream->append && substream->use_count > 1) return -EBUSY; snd_rawmidi_drain_output(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; - } - if (params->avail_min < 1 || params->avail_min > params->buffer_size) { + if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; - } if (params->buffer_size != runtime->buffer_size) { newbuf = kmalloc(params->buffer_size, GFP_KERNEL); if (!newbuf) @@ -667,18 +674,16 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, EXPORT_SYMBOL(snd_rawmidi_output_params); int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params * params) + struct snd_rawmidi_params *params) { char *newbuf, *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; snd_rawmidi_drain_input(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; - } - if (params->avail_min < 1 || params->avail_min > params->buffer_size) { + if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; - } if (params->buffer_size != runtime->buffer_size) { newbuf = kmalloc(params->buffer_size, GFP_KERNEL); if (!newbuf) @@ -697,7 +702,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, EXPORT_SYMBOL(snd_rawmidi_input_params); static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) + struct snd_rawmidi_status *status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -710,7 +715,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, } static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) + struct snd_rawmidi_status *status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -739,6 +744,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long { int stream; struct snd_rawmidi_info __user *info = argp; + if (get_user(stream, &info->stream)) return -EFAULT; switch (stream) { @@ -753,6 +759,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDRV_RAWMIDI_IOCTL_PARAMS: { struct snd_rawmidi_params params; + if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) return -EFAULT; switch (params.stream) { @@ -772,6 +779,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long { int err = 0; struct snd_rawmidi_status status; + if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status))) return -EFAULT; switch (status.stream) { @@ -797,6 +805,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDRV_RAWMIDI_IOCTL_DROP: { int val; + if (get_user(val, (int __user *) argp)) return -EFAULT; switch (val) { @@ -811,6 +820,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDRV_RAWMIDI_IOCTL_DRAIN: { int val; + if (get_user(val, (int __user *) argp)) return -EFAULT; switch (val) { @@ -844,7 +854,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: { int device; - + if (get_user(device, (int __user *)argp)) return -EFAULT; if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */ @@ -866,7 +876,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE: { int val; - + if (get_user(val, (int __user *)argp)) return -EFAULT; control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val; @@ -1020,6 +1030,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_lock_irq(&runtime->lock); while (!snd_rawmidi_ready(substream)) { wait_queue_entry_t wait; + if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { spin_unlock_irq(&runtime->lock); return result > 0 ? result : -EAGAIN; @@ -1072,7 +1083,7 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream) spin_lock_irqsave(&runtime->lock, flags); result = runtime->avail >= runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); - return result; + return result; } EXPORT_SYMBOL(snd_rawmidi_transmit_empty); @@ -1210,7 +1221,7 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack); * @substream: the rawmidi substream * @buffer: the buffer pointer * @count: the data size to transfer - * + * * Copies data from the buffer to the device and advances the pointer. * * Return: The copied size if successful, or a negative error code on failure. @@ -1324,6 +1335,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_lock_irq(&runtime->lock); while (!snd_rawmidi_ready_append(substream, count)) { wait_queue_entry_t wait; + if (file->f_flags & O_NONBLOCK) { spin_unlock_irq(&runtime->lock); return result > 0 ? result : -EAGAIN; @@ -1357,6 +1369,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, while (runtime->avail != runtime->buffer_size) { wait_queue_entry_t wait; unsigned int last_avail = runtime->avail; + init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -1374,7 +1387,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, return result; } -static __poll_t snd_rawmidi_poll(struct file *file, poll_table * wait) +static __poll_t snd_rawmidi_poll(struct file *file, poll_table *wait) { struct snd_rawmidi_file *rfile; struct snd_rawmidi_runtime *runtime; @@ -1411,7 +1424,6 @@ static __poll_t snd_rawmidi_poll(struct file *file, poll_table * wait) #endif /* - */ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, @@ -1479,8 +1491,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, * Register functions */ -static const struct file_operations snd_rawmidi_f_ops = -{ +static const struct file_operations snd_rawmidi_f_ops = { .owner = THIS_MODULE, .read = snd_rawmidi_read, .write = snd_rawmidi_write, @@ -1535,7 +1546,7 @@ static void release_rawmidi_device(struct device *dev) */ int snd_rawmidi_new(struct snd_card *card, char *id, int device, int output_count, int input_count, - struct snd_rawmidi ** rrawmidi) + struct snd_rawmidi **rrawmidi) { struct snd_rawmidi *rmidi; int err; @@ -1566,21 +1577,24 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, rmidi->dev.release = release_rawmidi_device; dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device); - if ((err = snd_rawmidi_alloc_substreams(rmidi, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], - SNDRV_RAWMIDI_STREAM_INPUT, - input_count)) < 0) { + err = snd_rawmidi_alloc_substreams(rmidi, + &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], + SNDRV_RAWMIDI_STREAM_INPUT, + input_count); + if (err < 0) { snd_rawmidi_free(rmidi); return err; } - if ((err = snd_rawmidi_alloc_substreams(rmidi, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], - SNDRV_RAWMIDI_STREAM_OUTPUT, - output_count)) < 0) { + err = snd_rawmidi_alloc_substreams(rmidi, + &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], + SNDRV_RAWMIDI_STREAM_OUTPUT, + output_count); + if (err < 0) { snd_rawmidi_free(rmidi); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops); + if (err < 0) { snd_rawmidi_free(rmidi); return err; } @@ -1624,6 +1638,7 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi) static int snd_rawmidi_dev_free(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; + return snd_rawmidi_free(rmidi); } @@ -1631,6 +1646,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device) static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) { struct snd_rawmidi *rmidi = device->private_data; + rmidi->seq_dev = NULL; } #endif @@ -1732,6 +1748,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) list_del_init(&rmidi->list); for (dir = 0; dir < 2; dir++) { struct snd_rawmidi_substream *s; + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { if (s->runtime) wake_up(&s->runtime->sleep); @@ -1769,7 +1786,7 @@ void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, const struct snd_rawmidi_ops *ops) { struct snd_rawmidi_substream *substream; - + list_for_each_entry(substream, &rmidi->streams[stream].substreams, list) substream->ops = ops; } -- cgit v1.2.1 From 7fdc9b08071b6a3fc85bf90b79e13f6e973a7e5e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 22:45:50 +0200 Subject: ALSA: rawmidi: Simplify error paths Apply the standard idiom: rewrite the multiple unlocks in error paths in the goto-error-and-single-unlock way. Just a code refactoring, and no functional changes. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 76 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 14dec13ecde9..6b24c2d2dae6 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -338,22 +338,20 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, int mode, struct snd_rawmidi_file *rfile) { struct snd_rawmidi *rmidi; - int err; + int err = 0; if (snd_BUG_ON(!rfile)) return -EINVAL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); - if (rmidi == NULL) { - mutex_unlock(®ister_mutex); - return -ENODEV; - } - if (!try_module_get(rmidi->card->module)) { - mutex_unlock(®ister_mutex); - return -ENXIO; - } + if (!rmidi) + err = -ENODEV; + else if (!try_module_get(rmidi->card->module)) + err = -ENXIO; mutex_unlock(®ister_mutex); + if (err < 0) + return err; mutex_lock(&rmidi->open_mutex); err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); @@ -1581,26 +1579,25 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], SNDRV_RAWMIDI_STREAM_INPUT, input_count); - if (err < 0) { - snd_rawmidi_free(rmidi); - return err; - } + if (err < 0) + goto error; err = snd_rawmidi_alloc_substreams(rmidi, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], SNDRV_RAWMIDI_STREAM_OUTPUT, output_count); - if (err < 0) { - snd_rawmidi_free(rmidi); - return err; - } + if (err < 0) + goto error; err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops); - if (err < 0) { - snd_rawmidi_free(rmidi); - return err; - } + if (err < 0) + goto error; + if (rrawmidi) *rrawmidi = rmidi; return 0; + + error: + snd_rawmidi_free(rmidi); + return err; } EXPORT_SYMBOL(snd_rawmidi_new); @@ -1660,30 +1657,27 @@ static int snd_rawmidi_dev_register(struct snd_device *device) if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) return -ENOMEM; + err = 0; mutex_lock(®ister_mutex); - if (snd_rawmidi_search(rmidi->card, rmidi->device)) { - mutex_unlock(®ister_mutex); - return -EBUSY; - } - list_add_tail(&rmidi->list, &snd_rawmidi_devices); + if (snd_rawmidi_search(rmidi->card, rmidi->device)) + err = -EBUSY; + else + list_add_tail(&rmidi->list, &snd_rawmidi_devices); mutex_unlock(®ister_mutex); + if (err < 0) + return err; + err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device, &snd_rawmidi_f_ops, rmidi, &rmidi->dev); if (err < 0) { rmidi_err(rmidi, "unable to register\n"); - mutex_lock(®ister_mutex); - list_del(&rmidi->list); - mutex_unlock(®ister_mutex); - return err; + goto error; } - if (rmidi->ops && rmidi->ops->dev_register && - (err = rmidi->ops->dev_register(rmidi)) < 0) { - snd_unregister_device(&rmidi->dev); - mutex_lock(®ister_mutex); - list_del(&rmidi->list); - mutex_unlock(®ister_mutex); - return err; + if (rmidi->ops && rmidi->ops->dev_register) { + err = rmidi->ops->dev_register(rmidi); + if (err < 0) + goto error_unregister; } #ifdef CONFIG_SND_OSSEMUL rmidi->ossreg = 0; @@ -1735,6 +1729,14 @@ static int snd_rawmidi_dev_register(struct snd_device *device) } #endif return 0; + + error_unregister: + snd_unregister_device(&rmidi->dev); + error: + mutex_lock(®ister_mutex); + list_del(&rmidi->list); + mutex_unlock(®ister_mutex); + return err; } static int snd_rawmidi_dev_disconnect(struct snd_device *device) -- cgit v1.2.1 From f5beb598b0c4dd023833ae1a7c188ecd987b7125 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 23:07:29 +0200 Subject: ALSA: rawmidi: Minor code refactoring Unify a few open codes with helper functions to improve the readability. Minor behavior changes (rather fixes) are: - runtime->drain clearance is done within lock - active_sensing is updated before resizing buffer in SNDRV_RAWMIDI_IOCTL_PARAMS ioctl. Other than that, simply code cleanups. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 77 ++++++++++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 44 deletions(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6b24c2d2dae6..cc944a3637a2 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -164,17 +164,28 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i cancel_work_sync(&substream->runtime->event_work); } -int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) +static void __reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime, + bool is_input) +{ + runtime->drain = 0; + runtime->appl_ptr = runtime->hw_ptr = 0; + runtime->avail = is_input ? 0 : runtime->buffer_size; +} + +static void reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime, + bool is_input) { unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_rawmidi_output_trigger(substream, 0); - runtime->drain = 0; spin_lock_irqsave(&runtime->lock, flags); - runtime->appl_ptr = runtime->hw_ptr = 0; - runtime->avail = runtime->buffer_size; + __reset_runtime_ptrs(runtime, is_input); spin_unlock_irqrestore(&runtime->lock, flags); +} + +int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) +{ + snd_rawmidi_output_trigger(substream, 0); + reset_runtime_ptrs(substream->runtime, false); return 0; } EXPORT_SYMBOL(snd_rawmidi_drop_output); @@ -213,15 +224,8 @@ EXPORT_SYMBOL(snd_rawmidi_drain_output); int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) { - unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_rawmidi_input_trigger(substream, 0); - runtime->drain = 0; - spin_lock_irqsave(&runtime->lock, flags); - runtime->appl_ptr = runtime->hw_ptr = 0; - runtime->avail = 0; - spin_unlock_irqrestore(&runtime->lock, flags); + reset_runtime_ptrs(substream->runtime, true); return 0; } EXPORT_SYMBOL(snd_rawmidi_drain_input); @@ -639,15 +643,12 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, return 0; } -int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params *params) +static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, + struct snd_rawmidi_params *params, + bool is_input) { char *newbuf, *oldbuf; - struct snd_rawmidi_runtime *runtime = substream->runtime; - if (substream->append && substream->use_count > 1) - return -EBUSY; - snd_rawmidi_drain_output(substream); if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; if (params->avail_min < 1 || params->avail_min > params->buffer_size) @@ -660,42 +661,30 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; - runtime->avail = runtime->buffer_size; - runtime->appl_ptr = runtime->hw_ptr = 0; + __reset_runtime_ptrs(runtime, is_input); spin_unlock_irq(&runtime->lock); kfree(oldbuf); } runtime->avail_min = params->avail_min; - substream->active_sensing = !params->no_active_sensing; return 0; } + +int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, + struct snd_rawmidi_params *params) +{ + if (substream->append && substream->use_count > 1) + return -EBUSY; + snd_rawmidi_drain_output(substream); + substream->active_sensing = !params->no_active_sensing; + return resize_runtime_buffer(substream->runtime, params, false); +} EXPORT_SYMBOL(snd_rawmidi_output_params); int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params *params) { - char *newbuf, *oldbuf; - struct snd_rawmidi_runtime *runtime = substream->runtime; - snd_rawmidi_drain_input(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) - return -EINVAL; - if (params->avail_min < 1 || params->avail_min > params->buffer_size) - return -EINVAL; - if (params->buffer_size != runtime->buffer_size) { - newbuf = kmalloc(params->buffer_size, GFP_KERNEL); - if (!newbuf) - return -ENOMEM; - spin_lock_irq(&runtime->lock); - oldbuf = runtime->buffer; - runtime->buffer = newbuf; - runtime->buffer_size = params->buffer_size; - runtime->appl_ptr = runtime->hw_ptr = 0; - spin_unlock_irq(&runtime->lock); - kfree(oldbuf); - } - runtime->avail_min = params->avail_min; - return 0; + return resize_runtime_buffer(substream->runtime, params, true); } EXPORT_SYMBOL(snd_rawmidi_input_params); -- cgit v1.2.1 From ef4db239cda2d74f53120e223643b0f5bbf947c1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2018 23:12:33 +0200 Subject: ALSA: rawmidi: Use kvmalloc() for buffers The size of in-kernel rawmidi buffers may be big up to 1MB, and it can be specified freely by user-space; which implies that user-space may trigger kmalloc() errors frequently. This patch replaces the buffer allocation via kvmalloc() for dealing with bigger buffers gracefully. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index cc944a3637a2..69517e18ef07 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -128,7 +129,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) runtime->avail = 0; else runtime->avail = runtime->buffer_size; - runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL); + runtime->buffer = kvmalloc(runtime->buffer_size, GFP_KERNEL); if (!runtime->buffer) { kfree(runtime); return -ENOMEM; @@ -142,7 +143,7 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime = substream->runtime; - kfree(runtime->buffer); + kvfree(runtime->buffer); kfree(runtime); substream->runtime = NULL; return 0; @@ -654,7 +655,7 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; if (params->buffer_size != runtime->buffer_size) { - newbuf = kmalloc(params->buffer_size, GFP_KERNEL); + newbuf = kvmalloc(params->buffer_size, GFP_KERNEL); if (!newbuf) return -ENOMEM; spin_lock_irq(&runtime->lock); @@ -663,7 +664,7 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, runtime->buffer_size = params->buffer_size; __reset_runtime_ptrs(runtime, is_input); spin_unlock_irq(&runtime->lock); - kfree(oldbuf); + kvfree(oldbuf); } runtime->avail_min = params->avail_min; return 0; -- cgit v1.2.1 From d10ee9c542365bdc0a7497306e21ff6c7f2172b0 Mon Sep 17 00:00:00 2001 From: Srikanth K H Date: Fri, 20 Jul 2018 11:13:51 +0530 Subject: ALSA: timer: catch invalid timer object creation A timer object for the classes SNDRV_TIMER_CLASS_CARD and SNDRV_TIMER_CLASS_PCM has to be associated with a card object, but we have no check at creation time. Such a timer object with NULL card causes various unexpected problems, e.g. NULL dereference at reading the sound timer proc file. So as preventive measure while the creating the sound timer object is created the card information availability is checked for the mentioned entries and returned error if its NULL. Signed-off-by: Srikanth K H Signed-off-by: Takashi Iwai --- sound/core/timer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound/core') diff --git a/sound/core/timer.c b/sound/core/timer.c index b6f076bbc72d..61a0cec6e1f6 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -883,6 +883,11 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, if (snd_BUG_ON(!tid)) return -EINVAL; + if (tid->dev_class == SNDRV_TIMER_CLASS_CARD || + tid->dev_class == SNDRV_TIMER_CLASS_PCM) { + if (WARN_ON(!card)) + return -EINVAL; + } if (rtimer) *rtimer = NULL; timer = kzalloc(sizeof(*timer), GFP_KERNEL); -- cgit v1.2.1 From 191bb51e72c3b2b1ed1b2bd7ac30dd9f7ccea306 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:00:55 +0200 Subject: ALSA: pcm: Use standard lower_32_bits() and upper_32_bits() Instead of open codes, use the standard macros for obtaining the lower and upper 32bit values. Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_plugin.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/core') diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 85a56af104bd..85bab922ce69 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -281,10 +281,10 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask, SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW); - if (formats.bits[0] & (u32)linfmts) - formats.bits[0] |= (u32)linfmts; - if (formats.bits[1] & (u32)(linfmts >> 32)) - formats.bits[1] |= (u32)(linfmts >> 32); + if (formats.bits[0] & lower_32_bits(linfmts)) + formats.bits[0] |= lower_32_bits(linfmts); + if (formats.bits[1] & upper_32_bits(linfmts)) + formats.bits[1] |= upper_32_bits(linfmts); return snd_mask_test(&formats, (__force int)format); } -- cgit v1.2.1 From f8b6c0cfbdd7359db9bb4da38dd54217296f9264 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2018 23:19:38 +0200 Subject: ALSA: pcm: Fix sparse warning wrt PCM format type The PCM format type is with __bitwise, hence it needs the explicit cast with __force. It's ugly, but there is a reason for that cost... This fixes the sparse warning: sound/core/oss/pcm_oss.c:1854:55: warning: incorrect type in argument 1 (different base types) Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/core') diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 905a53c1cde5..f8d4a419f3af 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1851,7 +1851,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); for (fmt = 0; fmt < 32; ++fmt) { if (snd_mask_test(format_mask, fmt)) { - int f = snd_pcm_oss_format_to(fmt); + int f = snd_pcm_oss_format_to((__force snd_pcm_format_t)fmt); if (f >= 0) formats |= f; } -- cgit v1.2.1 From f7debfe54090d1a1c38e1f070be20d83bb70a8e0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 29 Jul 2018 23:03:05 +0200 Subject: ALSA: seq: virmidi: Offload the output event processing The virmidi sequencer stuff tries to translate the rawmidi bytes to sequencer events and deliver the packets at trigger callback. The amount of the whole process of these translations and deliveries depends on the incoming rawmidi bytes, and we have no limit for that; this was the cause of a CPU soft lockup that had been reported and fixed recently. Although we've fixed the soft lockup by putting the temporary unlock and cond_resched(), it's rather a quick band aid. In this patch, meanwhile, the event parsing and delivery process is offloaded to a dedicated work, and the trigger callback just kicks it off. It has three merits, at least: - The processing is always done in a sleepable context, which can assure the event delivery with non-atomic flag without hackish is_atomic() usage. - Other relevant codes can be simplified, reducing the lines - It makes me happier Signed-off-by: Takashi Iwai --- sound/core/seq/seq_virmidi.c | 100 ++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 54 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 8ebbca554e99..67ea5d62cebc 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -154,70 +154,58 @@ static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, i } } -/* - * trigger rawmidi stream for output +/* process rawmidi bytes and send events; + * we need no lock here for vmidi->event since it's handled only in this work */ -static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) +static void snd_vmidi_output_work(struct work_struct *work) { - struct snd_virmidi *vmidi = substream->runtime->private_data; - int count, res; - unsigned char buf[32], *pbuf; - unsigned long flags; - bool check_resched = !in_atomic(); + struct snd_virmidi *vmidi; + struct snd_rawmidi_substream *substream; + unsigned char input; + int ret; + + vmidi = container_of(work, struct snd_virmidi, output_work); + substream = vmidi->substream; + + /* discard the outputs in dispatch mode unless subscribed */ + if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && + !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { + while (!snd_rawmidi_transmit_empty(substream)) + snd_rawmidi_transmit_ack(substream, 1); + return; + } - if (up) { - vmidi->trigger = 1; - if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && - !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { - while (snd_rawmidi_transmit(substream, buf, - sizeof(buf)) > 0) { - /* ignored */ - } - return; - } - spin_lock_irqsave(&substream->runtime->lock, flags); + while (vmidi->trigger) { + if (snd_rawmidi_transmit(substream, &input, 1) != 1) + break; + if (snd_midi_event_encode_byte(vmidi->parser, input, + &vmidi->event) <= 0) + continue; if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { - if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) - goto out; + ret = snd_seq_kernel_client_dispatch(vmidi->client, + &vmidi->event, + false, 0); vmidi->event.type = SNDRV_SEQ_EVENT_NONE; - } - while (1) { - count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf)); - if (count <= 0) + if (ret < 0) break; - pbuf = buf; - while (count > 0) { - res = snd_midi_event_encode(vmidi->parser, pbuf, count, &vmidi->event); - if (res < 0) { - snd_midi_event_reset_encode(vmidi->parser); - continue; - } - __snd_rawmidi_transmit_ack(substream, res); - pbuf += res; - count -= res; - if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { - if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) - goto out; - vmidi->event.type = SNDRV_SEQ_EVENT_NONE; - } - } - if (!check_resched) - continue; - /* do temporary unlock & cond_resched() for avoiding - * CPU soft lockup, which may happen via a write from - * a huge rawmidi buffer - */ - spin_unlock_irqrestore(&substream->runtime->lock, flags); - cond_resched(); - spin_lock_irqsave(&substream->runtime->lock, flags); } - out: - spin_unlock_irqrestore(&substream->runtime->lock, flags); - } else { - vmidi->trigger = 0; + /* rawmidi input might be huge, allow to have a break */ + cond_resched(); } } +/* + * trigger rawmidi stream for output + */ +static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) +{ + struct snd_virmidi *vmidi = substream->runtime->private_data; + + vmidi->trigger = !!up; + if (up) + queue_work(system_highpri_wq, &vmidi->output_work); +} + /* * open rawmidi handle for input */ @@ -270,6 +258,7 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream) vmidi->port = rdev->port; snd_virmidi_init_event(vmidi, &vmidi->event); vmidi->rdev = rdev; + INIT_WORK(&vmidi->output_work, snd_vmidi_output_work); runtime->private_data = vmidi; return 0; } @@ -299,6 +288,9 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_virmidi *vmidi = substream->runtime->private_data; + + vmidi->trigger = 0; /* to be sure */ + cancel_work_sync(&vmidi->output_work); snd_midi_event_free(vmidi->parser); substream->runtime->private_data = NULL; kfree(vmidi); -- cgit v1.2.1 From 89b4ab213feb11a5bece544cfa12374f66c2c47c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Jul 2018 14:48:29 +0200 Subject: ALSA: seq: virmidi: Use READ_ONCE/WRITE_ONCE() macros The trigger flag in vmidi object can be referred in different contexts concurrently, hence it's better to be put with READ_ONCE() and WRITE_ONCE() macros to assure the accesses. Signed-off-by: Takashi Iwai --- sound/core/seq/seq_virmidi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 67ea5d62cebc..03ac5e72dbe6 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -89,7 +89,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, else down_read(&rdev->filelist_sem); list_for_each_entry(vmidi, &rdev->filelist, list) { - if (!vmidi->trigger) + if (!READ_ONCE(vmidi->trigger)) continue; if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) @@ -147,11 +147,7 @@ static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, i { struct snd_virmidi *vmidi = substream->runtime->private_data; - if (up) { - vmidi->trigger = 1; - } else { - vmidi->trigger = 0; - } + WRITE_ONCE(vmidi->trigger, !!up); } /* process rawmidi bytes and send events; @@ -175,7 +171,7 @@ static void snd_vmidi_output_work(struct work_struct *work) return; } - while (vmidi->trigger) { + while (READ_ONCE(vmidi->trigger)) { if (snd_rawmidi_transmit(substream, &input, 1) != 1) break; if (snd_midi_event_encode_byte(vmidi->parser, input, @@ -201,7 +197,7 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, { struct snd_virmidi *vmidi = substream->runtime->private_data; - vmidi->trigger = !!up; + WRITE_ONCE(vmidi->trigger, !!up); if (up) queue_work(system_highpri_wq, &vmidi->output_work); } @@ -289,7 +285,7 @@ static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_virmidi *vmidi = substream->runtime->private_data; - vmidi->trigger = 0; /* to be sure */ + WRITE_ONCE(vmidi->trigger, false); /* to be sure */ cancel_work_sync(&vmidi->output_work); snd_midi_event_free(vmidi->parser); substream->runtime->private_data = NULL; -- cgit v1.2.1 From 5a6cd13d4faef48bdcb7ae9c1e98175332ced7cd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 1 Aug 2018 10:58:25 -0500 Subject: ALSA: pcm: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Addresses-Coverity-ID: 1357375 ("Missing break in switch") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_plugin.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/core') diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 85bab922ce69..0391cb1a4f19 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -353,6 +353,7 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, if (snd_mask_test(format_mask, (__force int)format1)) return format1; } + /* fall through */ default: return (__force snd_pcm_format_t)-EINVAL; } -- cgit v1.2.1 From ef965ad5a7697ff16e3be01954f5c57208e36c22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 14:38:18 +0200 Subject: ALSA: seq: Minor cleanup of MIDI event parser helpers snd_midi_event_encode_byte() can never fail, and it can return rather true/false. Change the return type to bool, adjust the argument to receive a MIDI byte as unsigned char, and adjust the comment accordingly. This allows callers to drop error checks, which simplifies the code. Meanwhile, snd_midi_event_encode() helper is used only in seq_midi.c, and it can be better folded into it. This will reduce the total amount of lines in the end. Signed-off-by: Takashi Iwai --- sound/core/seq/oss/seq_oss_midi.c | 2 +- sound/core/seq/seq_midi.c | 24 ++++++++++------------ sound/core/seq/seq_midi_event.c | 42 +++++++-------------------------------- sound/core/seq/seq_virmidi.c | 4 ++-- 4 files changed, 20 insertions(+), 52 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 9debd1b8fd28..0d5f8b16d057 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -637,7 +637,7 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru if ((mdev = get_mididev(dp, dev)) == NULL) return -ENODEV; - if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) { + if (snd_midi_event_encode_byte(mdev->coder, c, ev)) { snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); snd_use_lock_free(&mdev->use_lock); return 0; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 5dd0ee258359..9e0dabd3ce5f 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -78,7 +78,7 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream) struct seq_midisynth *msynth; struct snd_seq_event ev; char buf[16], *pbuf; - long res, count; + long res; if (substream == NULL) return; @@ -94,19 +94,15 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream) if (msynth->parser == NULL) continue; pbuf = buf; - while (res > 0) { - count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev); - if (count < 0) - break; - pbuf += count; - res -= count; - if (ev.type != SNDRV_SEQ_EVENT_NONE) { - ev.source.port = msynth->seq_port; - ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0); - /* clear event and reset header */ - memset(&ev, 0, sizeof(ev)); - } + while (res-- > 0) { + if (!snd_midi_event_encode_byte(msynth->parser, + *pbuf++, &ev)) + continue; + ev.source.port = msynth->seq_port; + ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; + snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0); + /* clear event and reset header */ + memset(&ev, 0, sizeof(ev)); } } } diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 90bbbdbeba03..53c0dfab90d6 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -214,45 +214,17 @@ int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize) } #endif /* 0 */ -/* - * read bytes and encode to sequencer event if finished - * return the size of encoded bytes - */ -long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count, - struct snd_seq_event *ev) -{ - long result = 0; - int rc; - - ev->type = SNDRV_SEQ_EVENT_NONE; - - while (count-- > 0) { - rc = snd_midi_event_encode_byte(dev, *buf++, ev); - result++; - if (rc < 0) - return rc; - else if (rc > 0) - return result; - } - - return result; -} -EXPORT_SYMBOL(snd_midi_event_encode); - /* * read one byte and encode to sequencer event: - * return 1 if MIDI bytes are encoded to an event - * 0 data is not finished - * negative for error + * return true if MIDI bytes are encoded to an event + * false data is not finished */ -int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, - struct snd_seq_event *ev) +bool snd_midi_event_encode_byte(struct snd_midi_event *dev, unsigned char c, + struct snd_seq_event *ev) { - int rc = 0; + bool rc = false; unsigned long flags; - c &= 0xff; - if (c >= MIDI_CMD_COMMON_CLOCK) { /* real-time event */ ev->type = status_event[ST_SPECIAL + c - 0xf0].event; @@ -293,7 +265,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, status_event[dev->type].encode(dev, ev); if (dev->type >= ST_SPECIAL) dev->type = ST_INVALID; - rc = 1; + rc = true; } else if (dev->type == ST_SYSEX) { if (c == MIDI_CMD_COMMON_SYSEX_END || dev->read >= dev->bufsize) { @@ -306,7 +278,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, dev->read = 0; /* continue to parse */ else reset_encode(dev); /* all parsed */ - rc = 1; + rc = true; } } diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 03ac5e72dbe6..0c84926eb726 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -174,8 +174,8 @@ static void snd_vmidi_output_work(struct work_struct *work) while (READ_ONCE(vmidi->trigger)) { if (snd_rawmidi_transmit(substream, &input, 1) != 1) break; - if (snd_midi_event_encode_byte(vmidi->parser, input, - &vmidi->event) <= 0) + if (!snd_midi_event_encode_byte(vmidi->parser, input, + &vmidi->event)) continue; if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { ret = snd_seq_kernel_client_dispatch(vmidi->client, -- cgit v1.2.1 From fc4bfd9a35f3d9cbf5ad6a20faedca71d1d9ed52 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 14:59:07 +0200 Subject: ALSA: seq: Remove dead codes There are a few functions that have been commented out for ages. And also there are functions that do nothing but placeholders. Let's kill them. Signed-off-by: Takashi Iwai --- sound/core/seq/seq.c | 7 ------- sound/core/seq/seq_memory.c | 12 ----------- sound/core/seq/seq_memory.h | 6 ------ sound/core/seq/seq_midi_emul.c | 12 ----------- sound/core/seq/seq_midi_event.c | 45 ----------------------------------------- sound/core/seq/seq_virmidi.c | 33 ------------------------------ 6 files changed, 115 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 639544b4fb04..e685eccdc741 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -87,10 +87,6 @@ static int __init alsa_seq_init(void) if ((err = client_init_data()) < 0) goto error; - /* init memory, room for selected events */ - if ((err = snd_sequencer_memory_init()) < 0) - goto error; - /* init event queues */ if ((err = snd_seq_queues_init()) < 0) goto error; @@ -126,9 +122,6 @@ static void __exit alsa_seq_exit(void) /* unregister sequencer device */ snd_sequencer_device_done(); - /* release event memory */ - snd_sequencer_memory_done(); - snd_seq_autoload_exit(); } diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index a4c8543176b2..5b0388202bac 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -504,18 +504,6 @@ int snd_seq_pool_delete(struct snd_seq_pool **ppool) return 0; } -/* initialize sequencer memory */ -int __init snd_sequencer_memory_init(void) -{ - return 0; -} - -/* release sequencer memory */ -void __exit snd_sequencer_memory_done(void) -{ -} - - /* exported to seq_clientmgr.c */ void snd_seq_info_pool(struct snd_info_buffer *buffer, struct snd_seq_pool *pool, char *space) diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h index 3abe306c394a..1292fe91f02e 100644 --- a/sound/core/seq/seq_memory.h +++ b/sound/core/seq/seq_memory.h @@ -94,12 +94,6 @@ struct snd_seq_pool *snd_seq_pool_new(int poolsize); /* remove pool */ int snd_seq_pool_delete(struct snd_seq_pool **pool); -/* init memory */ -int snd_sequencer_memory_init(void); - -/* release event memory */ -void snd_sequencer_memory_done(void); - /* polling */ int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait); diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 288f839a554b..f9f21331aeea 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -728,15 +728,3 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) kfree(chset); } EXPORT_SYMBOL(snd_midi_channel_free_set); - -static int __init alsa_seq_midi_emul_init(void) -{ - return 0; -} - -static void __exit alsa_seq_midi_emul_exit(void) -{ -} - -module_init(alsa_seq_midi_emul_init) -module_exit(alsa_seq_midi_emul_exit) diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 53c0dfab90d6..b11419537062 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -175,45 +175,12 @@ void snd_midi_event_reset_decode(struct snd_midi_event *dev) } EXPORT_SYMBOL(snd_midi_event_reset_decode); -#if 0 -void snd_midi_event_init(struct snd_midi_event *dev) -{ - snd_midi_event_reset_encode(dev); - snd_midi_event_reset_decode(dev); -} -#endif /* 0 */ - void snd_midi_event_no_status(struct snd_midi_event *dev, int on) { dev->nostat = on ? 1 : 0; } EXPORT_SYMBOL(snd_midi_event_no_status); -/* - * resize buffer - */ -#if 0 -int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize) -{ - unsigned char *new_buf, *old_buf; - unsigned long flags; - - if (bufsize == dev->bufsize) - return 0; - new_buf = kmalloc(bufsize, GFP_KERNEL); - if (new_buf == NULL) - return -ENOMEM; - spin_lock_irqsave(&dev->lock, flags); - old_buf = dev->buf; - dev->buf = new_buf; - dev->bufsize = bufsize; - reset_encode(dev); - spin_unlock_irqrestore(&dev->lock, flags); - kfree(old_buf); - return 0; -} -#endif /* 0 */ - /* * read one byte and encode to sequencer event: * return true if MIDI bytes are encoded to an event @@ -503,15 +470,3 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, } return idx; } - -static int __init alsa_seq_midi_event_init(void) -{ - return 0; -} - -static void __exit alsa_seq_midi_event_exit(void) -{ -} - -module_init(alsa_seq_midi_event_init) -module_exit(alsa_seq_midi_event_exit) diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 0c84926eb726..a2f1c6b58693 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -109,23 +109,6 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, return 0; } -/* - * receive an event from the remote virmidi port - * - * for rawmidi inputs, you can call this function from the event - * handler of a remote port which is attached to the virmidi via - * SNDRV_VIRMIDI_SEQ_ATTACH. - */ -#if 0 -int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev) -{ - struct snd_virmidi_dev *rdev; - - rdev = rmidi->private_data; - return snd_virmidi_dev_receive_event(rdev, ev, true); -} -#endif /* 0 */ - /* * event handler of virmidi port */ @@ -544,19 +527,3 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi return 0; } EXPORT_SYMBOL(snd_virmidi_new); - -/* - * ENTRY functions - */ - -static int __init alsa_virmidi_init(void) -{ - return 0; -} - -static void __exit alsa_virmidi_exit(void) -{ -} - -module_init(alsa_virmidi_init) -module_exit(alsa_virmidi_exit) -- cgit v1.2.1 From 00976ad5271999ba06d24319fd1031b178aff832 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 16:37:02 +0200 Subject: ALSA: seq: Fix leftovers at probe error path The sequencer core module doesn't call some destructors in the error path of the init code, which may leave some resources. This patch mainly fix these leaks by calling the destructors appropriately at alsa_seq_init(). Also the patch brings a few cleanups along with it, namely: - Expand the old "if ((err = xxx) < 0)" coding style - Get rid of empty seq_queue_init() and its caller - Change snd_seq_info_done() to void Last but not least, a couple of functions lose __exit annotation since they are called also in alsa_seq_init(). No functional changes but minor code cleanups. Signed-off-by: Takashi Iwai --- sound/core/seq/seq.c | 26 ++++++++++++++++---------- sound/core/seq/seq_clientmgr.c | 2 +- sound/core/seq/seq_info.c | 10 ++-------- sound/core/seq/seq_info.h | 6 +++--- sound/core/seq/seq_queue.c | 12 +----------- sound/core/seq/seq_queue.h | 3 --- 6 files changed, 23 insertions(+), 36 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index e685eccdc741..7de98d71f2aa 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -84,26 +84,32 @@ static int __init alsa_seq_init(void) { int err; - if ((err = client_init_data()) < 0) - goto error; - - /* init event queues */ - if ((err = snd_seq_queues_init()) < 0) + err = client_init_data(); + if (err < 0) goto error; /* register sequencer device */ - if ((err = snd_sequencer_device_init()) < 0) + err = snd_sequencer_device_init(); + if (err < 0) goto error; /* register proc interface */ - if ((err = snd_seq_info_init()) < 0) - goto error; + err = snd_seq_info_init(); + if (err < 0) + goto error_device; /* register our internal client */ - if ((err = snd_seq_system_client_init()) < 0) - goto error; + err = snd_seq_system_client_init(); + if (err < 0) + goto error_info; snd_seq_autoload_init(); + return 0; + + error_info: + snd_seq_info_done(); + error_device: + snd_sequencer_device_done(); error: return err; } diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 6fd4b074b206..a0b768e2f697 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2543,7 +2543,7 @@ int __init snd_sequencer_device_init(void) /* * unregister sequencer device */ -void __exit snd_sequencer_device_done(void) +void snd_sequencer_device_done(void) { snd_unregister_device(&seq_dev); put_device(&seq_dev); diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c index 97015447b9b3..b27fedd435b6 100644 --- a/sound/core/seq/seq_info.c +++ b/sound/core/seq/seq_info.c @@ -50,7 +50,7 @@ create_info_entry(char *name, void (*read)(struct snd_info_entry *, return entry; } -static void free_info_entries(void) +void snd_seq_info_done(void) { snd_info_free_entry(queues_entry); snd_info_free_entry(clients_entry); @@ -70,12 +70,6 @@ int __init snd_seq_info_init(void) return 0; error: - free_info_entries(); + snd_seq_info_done(); return -ENOMEM; } - -int __exit snd_seq_info_done(void) -{ - free_info_entries(); - return 0; -} diff --git a/sound/core/seq/seq_info.h b/sound/core/seq/seq_info.h index f8549f81a645..2cdf8f6e63f5 100644 --- a/sound/core/seq/seq_info.h +++ b/sound/core/seq/seq_info.h @@ -30,11 +30,11 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buff #ifdef CONFIG_SND_PROC_FS -int snd_seq_info_init( void ); -int snd_seq_info_done( void ); +int snd_seq_info_init(void); +void snd_seq_info_done(void); #else static inline int snd_seq_info_init(void) { return 0; } -static inline int snd_seq_info_done(void) { return 0; } +static inline void snd_seq_info_done(void) {} #endif #endif diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index b377f5048352..3b3ac96f1f5f 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -159,18 +159,8 @@ static void queue_delete(struct snd_seq_queue *q) /*----------------------------------------------------------------*/ -/* setup queues */ -int __init snd_seq_queues_init(void) -{ - /* - memset(queue_list, 0, sizeof(queue_list)); - num_queues = 0; - */ - return 0; -} - /* delete all existing queues */ -void __exit snd_seq_queues_delete(void) +void snd_seq_queues_delete(void) { int i; diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index 719093489a2c..76db43b79a2b 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -63,9 +63,6 @@ struct snd_seq_queue { /* get the number of current queues */ int snd_seq_queue_get_cur_queues(void); -/* init queues structure */ -int snd_seq_queues_init(void); - /* delete queues */ void snd_seq_queues_delete(void); -- cgit v1.2.1 From 04702e8d0092832eaeeacc6b1bfbf81a66f242c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 16:42:29 +0200 Subject: ALSA: seq: Use no intrruptible mutex_lock All usages of mutex in ALSA sequencer core would take too long, hence we don't have to care about the user interruption that makes things complicated. Let's replace them with simpler mutex_lock(). Signed-off-by: Takashi Iwai --- sound/core/seq/seq_clientmgr.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index a0b768e2f697..92e6524a3a9d 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -311,10 +311,9 @@ static int snd_seq_open(struct inode *inode, struct file *file) if (err < 0) return err; - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; + mutex_lock(®ister_mutex); client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); - if (client == NULL) { + if (!client) { mutex_unlock(®ister_mutex); return -ENOMEM; /* failure code */ } @@ -1704,10 +1703,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, if (queue == NULL) return -EINVAL; - if (mutex_lock_interruptible(&queue->timer_mutex)) { - queuefree(queue); - return -ERESTARTSYS; - } + mutex_lock(&queue->timer_mutex); tmr = queue->timer; memset(timer, 0, sizeof(*timer)); timer->queue = queue->queue; @@ -1741,10 +1737,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, q = queueptr(timer->queue); if (q == NULL) return -ENXIO; - if (mutex_lock_interruptible(&q->timer_mutex)) { - queuefree(q); - return -ERESTARTSYS; - } + mutex_lock(&q->timer_mutex); tmr = q->timer; snd_seq_queue_timer_close(timer->queue); tmr->type = timer->type; @@ -2180,8 +2173,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS) return -EINVAL; - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; + mutex_lock(®ister_mutex); if (card) { client_index += SNDRV_SEQ_GLOBAL_CLIENTS @@ -2522,19 +2514,15 @@ int __init snd_sequencer_device_init(void) snd_device_initialize(&seq_dev, NULL); dev_set_name(&seq_dev, "seq"); - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; - + mutex_lock(®ister_mutex); err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, &snd_seq_f_ops, NULL, &seq_dev); + mutex_unlock(®ister_mutex); if (err < 0) { - mutex_unlock(®ister_mutex); put_device(&seq_dev); return err; } - mutex_unlock(®ister_mutex); - return 0; } -- cgit v1.2.1 From 93ce1b12966d9d60ee5583ffbde822a22909568e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Aug 2018 16:43:56 +0200 Subject: ALSA: seq: Drop unused 64bit division macros The old ugly macros remained in the code without usage. Rip them off. Signed-off-by: Takashi Iwai --- sound/core/seq/seq_queue.h | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index 76db43b79a2b..e006fc8e3a36 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -109,28 +109,4 @@ int snd_seq_queue_is_used(int queueid, int client); int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop); -/* - * 64bit division - for sync stuff.. - */ -#if defined(i386) || defined(i486) - -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divl %4" \ - : "=a" ((u32)(q)), \ - "=d" ((u32)(r)) \ - : "0" ((u32)(n0)), \ - "1" ((u32)(n1)), \ - "rm" ((u32)(d))) - -#define u64_div(x,y,q) do {u32 __tmp; udiv_qrnnd(q, __tmp, (x)>>32, x, y);} while (0) -#define u64_mod(x,y,r) do {u32 __tmp; udiv_qrnnd(__tmp, q, (x)>>32, x, y);} while (0) -#define u64_divmod(x,y,q,r) udiv_qrnnd(q, r, (x)>>32, x, y) - -#else -#define u64_div(x,y,q) ((q) = (u32)((u64)(x) / (u64)(y))) -#define u64_mod(x,y,r) ((r) = (u32)((u64)(x) % (u64)(y))) -#define u64_divmod(x,y,q,r) (u64_div(x,y,q), u64_mod(x,y,r)) -#endif - - #endif -- cgit v1.2.1 From a6403299893982a2c0b0a6f43261976c43e1598e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Aug 2018 15:40:25 +0200 Subject: ALSA: compress: Remove empty init and exit For a sake of code simplification, remove the init and the exit entries that do nothing. Notes for readers: actually it's OK to remove *both* init and exit, but not OK to remove the exit entry. By removing only the exit while keeping init, the module becomes permanently loaded; i.e. you cannot unload it any longer! Signed-off-by: Takashi Iwai --- sound/core/compress_offload.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'sound/core') diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 4b01a37c836e..26b5e245b074 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1160,18 +1160,6 @@ int snd_compress_deregister(struct snd_compr *device) } EXPORT_SYMBOL_GPL(snd_compress_deregister); -static int __init snd_compress_init(void) -{ - return 0; -} - -static void __exit snd_compress_exit(void) -{ -} - -module_init(snd_compress_init); -module_exit(snd_compress_exit); - MODULE_DESCRIPTION("ALSA Compressed offload framework"); MODULE_AUTHOR("Vinod Koul "); MODULE_LICENSE("GPL v2"); -- cgit v1.2.1 From 2f3b94e539a46052f8eba1f295ff5646e227578a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 3 Aug 2018 15:52:33 -0500 Subject: ALSA: seq: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Notice that in this particular case, I replaced the code comment with a proper "fall through" annotation, which is what GCC is expecting to find. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/seq/seq_midi_emul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index f9f21331aeea..c1975dd31871 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -318,7 +318,7 @@ do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chse break; case MIDI_CTL_MSB_DATA_ENTRY: chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0; - /* go through here */ + /* fall through */ case MIDI_CTL_LSB_DATA_ENTRY: if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED) rpn(ops, drv, chan, chset); -- cgit v1.2.1 From eb2caeb88c181904110f8e74995c7b0bb7fd39f6 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 3 Aug 2018 15:53:54 -0500 Subject: ALSA: seq_oss: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 2 was used: -Wimplicit-fallthrough=2 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Takashi Iwai --- sound/core/seq/oss/seq_oss_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/core') diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index 4f24ea9fad93..ba127c22539a 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c @@ -92,7 +92,7 @@ snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev) case TMR_WAIT_REL: parm += rec->cur_tick; rec->realtime = 0; - /* continue to next */ + /* fall through and continue to next */ case TMR_WAIT_ABS: if (parm == 0) { rec->realtime = 1; -- cgit v1.2.1