summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/Kconfig2
-rw-r--r--sound/core/Makefile1
-rw-r--r--sound/core/compress_offload.c199
-rw-r--r--sound/core/control.c112
-rw-r--r--sound/core/control_compat.c21
-rw-r--r--sound/core/control_led.c14
-rw-r--r--sound/core/control_trace.h55
-rw-r--r--sound/core/ctljack.c18
-rw-r--r--sound/core/device.c25
-rw-r--r--sound/core/hrtimer.c7
-rw-r--r--sound/core/hwdep.c2
-rw-r--r--sound/core/info.c8
-rw-r--r--sound/core/init.c28
-rw-r--r--sound/core/jack.c29
-rw-r--r--sound/core/memalloc.c4
-rw-r--r--sound/core/misc.c38
-rw-r--r--sound/core/oss/copy.c17
-rw-r--r--sound/core/oss/io.c17
-rw-r--r--sound/core/oss/linear.c17
-rw-r--r--sound/core/oss/mixer_oss.c96
-rw-r--r--sound/core/oss/mulaw.c16
-rw-r--r--sound/core/oss/pcm_oss.c81
-rw-r--r--sound/core/oss/pcm_plugin.c19
-rw-r--r--sound/core/oss/rate.c17
-rw-r--r--sound/core/oss/route.c17
-rw-r--r--sound/core/pcm.c10
-rw-r--r--sound/core/pcm_compat.c39
-rw-r--r--sound/core/pcm_dmaengine.c25
-rw-r--r--sound/core/pcm_drm_eld.c2
-rw-r--r--sound/core/pcm_lib.c2
-rw-r--r--sound/core/pcm_memory.c4
-rw-r--r--sound/core/pcm_misc.c49
-rw-r--r--sound/core/pcm_native.c250
-rw-r--r--sound/core/rawmidi.c19
-rw-r--r--sound/core/seq/oss/seq_oss.c28
-rw-r--r--sound/core/seq/oss/seq_oss_device.h7
-rw-r--r--sound/core/seq/oss/seq_oss_init.c10
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c143
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c14
-rw-r--r--sound/core/seq/oss/seq_oss_rw.c6
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c149
-rw-r--r--sound/core/seq/oss/seq_oss_synth.h4
-rw-r--r--sound/core/seq/oss/seq_oss_timer.c2
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.c7
-rw-r--r--sound/core/seq/seq_clientmgr.c880
-rw-r--r--sound/core/seq/seq_clientmgr.h17
-rw-r--r--sound/core/seq/seq_compat.c4
-rw-r--r--sound/core/seq/seq_dummy.c2
-rw-r--r--sound/core/seq/seq_fifo.c18
-rw-r--r--sound/core/seq/seq_fifo.h1
-rw-r--r--sound/core/seq/seq_memory.c6
-rw-r--r--sound/core/seq/seq_midi.c31
-rw-r--r--sound/core/seq/seq_midi_emul.c4
-rw-r--r--sound/core/seq/seq_midi_event.c2
-rw-r--r--sound/core/seq/seq_ports.c30
-rw-r--r--sound/core/seq/seq_ports.h2
-rw-r--r--sound/core/seq/seq_prioq.c2
-rw-r--r--sound/core/seq/seq_queue.c112
-rw-r--r--sound/core/seq/seq_queue.h3
-rw-r--r--sound/core/seq/seq_system.c6
-rw-r--r--sound/core/seq/seq_timer.c7
-rw-r--r--sound/core/seq/seq_ump_client.c31
-rw-r--r--sound/core/seq/seq_ump_convert.c53
-rw-r--r--sound/core/seq/seq_ump_convert.h1
-rw-r--r--sound/core/seq/seq_virmidi.c10
-rw-r--r--sound/core/seq_device.c28
-rw-r--r--sound/core/sound.c9
-rw-r--r--sound/core/sound_oss.c2
-rw-r--r--sound/core/timer.c65
-rw-r--r--sound/core/ump.c7
-rw-r--r--sound/core/vmaster.c17
71 files changed, 1440 insertions, 1540 deletions
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 48db44fa56fe..4e7bc370ffd7 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -155,7 +155,7 @@ config SND_MAX_CARDS
config SND_SUPPORT_OLD_API
bool "Support old ALSA API"
- default y
+ default n
help
Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3
or older).
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 31a0623cc89d..fdd3bb6e81a9 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -23,6 +23,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
# for trace-points
CFLAGS_pcm_lib.o := -I$(src)
CFLAGS_pcm_native.o := -I$(src)
+CFLAGS_control.o := -I$(src)
snd-pcm-dmaengine-y := pcm_dmaengine.o
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 840bb9cfe789..fd63d219bf86 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -41,13 +41,6 @@
#define COMPR_CODEC_CAPS_OVERFLOW
#endif
-/* TODO:
- * - add substream support for multiple devices in case of
- * SND_DYNAMIC_MINORS is not used
- * - Multiple node representation
- * driver should be able to register multiple nodes
- */
-
struct snd_compr_file {
unsigned long caps;
struct snd_compr_stream stream;
@@ -176,14 +169,37 @@ static int snd_compr_free(struct inode *inode, struct file *f)
return 0;
}
+static void
+snd_compr_tstamp32_from_64(struct snd_compr_tstamp *tstamp32,
+ const struct snd_compr_tstamp64 *tstamp64)
+{
+ tstamp32->byte_offset = tstamp64->byte_offset;
+ tstamp32->copied_total = (u32)tstamp64->copied_total;
+ tstamp32->pcm_frames = (u32)tstamp64->pcm_frames;
+ tstamp32->pcm_io_frames = (u32)tstamp64->pcm_io_frames;
+ tstamp32->sampling_rate = tstamp64->sampling_rate;
+}
+
static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
- struct snd_compr_tstamp *tstamp)
+ struct snd_compr_tstamp64 *tstamp)
{
+ int ret;
+
if (!stream->ops->pointer)
return -ENOTSUPP;
- stream->ops->pointer(stream, tstamp);
- pr_debug("dsp consumed till %d total %d bytes\n",
- tstamp->byte_offset, tstamp->copied_total);
+
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_OPEN:
+ return -EBADFD;
+ default:
+ break;
+ }
+
+ ret = stream->ops->pointer(stream, tstamp);
+ if (ret != 0)
+ return ret;
+ pr_debug("dsp consumed till %u total %llu bytes\n", tstamp->byte_offset,
+ tstamp->copied_total);
if (stream->direction == SND_COMPRESS_PLAYBACK)
stream->runtime->total_bytes_transferred = tstamp->copied_total;
else
@@ -192,7 +208,7 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
}
static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
- struct snd_compr_avail *avail)
+ struct snd_compr_avail64 *avail)
{
memset(avail, 0, sizeof(*avail));
snd_compr_update_tstamp(stream, &avail->tstamp);
@@ -204,9 +220,9 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
pr_debug("detected init and someone forgot to do a write\n");
return stream->runtime->buffer_size;
}
- pr_debug("app wrote %lld, DSP consumed %lld\n",
- stream->runtime->total_bytes_available,
- stream->runtime->total_bytes_transferred);
+ pr_debug("app wrote %llu, DSP consumed %llu\n",
+ stream->runtime->total_bytes_available,
+ stream->runtime->total_bytes_transferred);
if (stream->runtime->total_bytes_available ==
stream->runtime->total_bytes_transferred) {
if (stream->direction == SND_COMPRESS_PLAYBACK) {
@@ -223,28 +239,43 @@ static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
if (stream->direction == SND_COMPRESS_PLAYBACK)
avail->avail = stream->runtime->buffer_size - avail->avail;
- pr_debug("ret avail as %lld\n", avail->avail);
+ pr_debug("ret avail as %zu\n", (size_t)avail->avail);
return avail->avail;
}
static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
{
- struct snd_compr_avail avail;
+ struct snd_compr_avail64 avail;
return snd_compr_calc_avail(stream, &avail);
}
-static int
-snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+static void snd_compr_avail32_from_64(struct snd_compr_avail *avail32,
+ const struct snd_compr_avail64 *avail64)
{
- struct snd_compr_avail ioctl_avail;
+ avail32->avail = avail64->avail;
+ snd_compr_tstamp32_from_64(&avail32->tstamp, &avail64->tstamp);
+}
+
+static int snd_compr_ioctl_avail(struct snd_compr_stream *stream,
+ unsigned long arg, bool is_32bit)
+{
+ struct snd_compr_avail64 ioctl_avail64;
+ struct snd_compr_avail ioctl_avail32;
size_t avail;
+ const void *copy_from = &ioctl_avail64;
+ size_t copy_size = sizeof(ioctl_avail64);
if (stream->direction == SND_COMPRESS_ACCEL)
return -EBADFD;
- avail = snd_compr_calc_avail(stream, &ioctl_avail);
- ioctl_avail.avail = avail;
+ avail = snd_compr_calc_avail(stream, &ioctl_avail64);
+ ioctl_avail64.avail = avail;
+ if (is_32bit) {
+ snd_compr_avail32_from_64(&ioctl_avail32, &ioctl_avail64);
+ copy_from = &ioctl_avail32;
+ copy_size = sizeof(ioctl_avail32);
+ }
switch (stream->runtime->state) {
case SNDRV_PCM_STATE_OPEN:
@@ -255,8 +286,7 @@ snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
break;
}
- if (copy_to_user((__u64 __user *)arg,
- &ioctl_avail, sizeof(ioctl_avail)))
+ if (copy_to_user((__u64 __user *)arg, copy_from, copy_size))
return -EFAULT;
return 0;
}
@@ -274,8 +304,7 @@ static int snd_compr_write_data(struct snd_compr_stream *stream,
(app_pointer * runtime->buffer_size);
dstn = runtime->buffer + app_pointer;
- pr_debug("copying %ld at %lld\n",
- (unsigned long)count, app_pointer);
+ pr_debug("copying %lu at %llu\n", (unsigned long)count, app_pointer);
if (count < runtime->buffer_size - app_pointer) {
if (copy_from_user(dstn, buf, count))
return -EFAULT;
@@ -318,7 +347,7 @@ static ssize_t snd_compr_write(struct file *f, const char __user *buf,
}
avail = snd_compr_get_avail(stream);
- pr_debug("avail returned %ld\n", (unsigned long)avail);
+ pr_debug("avail returned %lu\n", (unsigned long)avail);
/* calculate how much we can write to buffer */
if (avail > count)
avail = count;
@@ -374,7 +403,7 @@ static ssize_t snd_compr_read(struct file *f, char __user *buf,
}
avail = snd_compr_get_avail(stream);
- pr_debug("avail returned %ld\n", (unsigned long)avail);
+ pr_debug("avail returned %lu\n", (unsigned long)avail);
/* calculate how much we can read from buffer */
if (avail > count)
avail = count;
@@ -443,7 +472,7 @@ static __poll_t snd_compr_poll(struct file *f, poll_table *wait)
#endif
avail = snd_compr_get_avail(stream);
- pr_debug("avail is %ld\n", (unsigned long)avail);
+ pr_debug("avail is %lu\n", (unsigned long)avail);
/* check if we have at least one fragment to fill */
switch (runtime->state) {
case SNDRV_PCM_STATE_DRAINING:
@@ -490,12 +519,12 @@ static int
snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
{
int retval;
- struct snd_compr_codec_caps *caps __free(kfree) = NULL;
if (!stream->ops->get_codec_caps)
return -ENXIO;
- caps = kzalloc(sizeof(*caps), GFP_KERNEL);
+ struct snd_compr_codec_caps *caps __free(kfree) =
+ kzalloc_obj(*caps);
if (!caps)
return -ENOMEM;
@@ -515,7 +544,7 @@ int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size)
if (snd_BUG_ON(!(stream) || !(stream)->runtime))
return -EINVAL;
- dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
+ dmab = kzalloc_obj(*dmab);
if (!dmab)
return -ENOMEM;
dmab->dev = stream->dma_buffer.dev;
@@ -623,7 +652,6 @@ snd_compress_check_input(struct snd_compr_stream *stream, struct snd_compr_param
static int
snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
{
- struct snd_compr_params *params __free(kfree) = NULL;
int retval;
if (stream->runtime->state == SNDRV_PCM_STATE_OPEN || stream->next_track) {
@@ -631,7 +659,9 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
* we should allow parameter change only when stream has been
* opened not in other cases
*/
- params = memdup_user((void __user *)arg, sizeof(*params));
+ struct snd_compr_params *params __free(kfree) =
+ memdup_user((void __user *)arg, sizeof(*params));
+
if (IS_ERR(params))
return PTR_ERR(params);
@@ -663,13 +693,13 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
static int
snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
{
- struct snd_codec *params __free(kfree) = NULL;
int retval;
if (!stream->ops->get_params)
return -EBADFD;
- params = kzalloc(sizeof(*params), GFP_KERNEL);
+ struct snd_codec *params __free(kfree) =
+ kzalloc_obj(*params);
if (!params)
return -ENOMEM;
retval = stream->ops->get_params(stream, params);
@@ -723,16 +753,26 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg)
return retval;
}
-static inline int
-snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+static inline int snd_compr_tstamp(struct snd_compr_stream *stream,
+ unsigned long arg, bool is_32bit)
{
- struct snd_compr_tstamp tstamp = {0};
+ struct snd_compr_tstamp64 tstamp64 = { 0 };
+ struct snd_compr_tstamp tstamp32 = { 0 };
+ const void *copy_from = &tstamp64;
+ size_t copy_size = sizeof(tstamp64);
int ret;
- ret = snd_compr_update_tstamp(stream, &tstamp);
- if (ret == 0)
- ret = copy_to_user((struct snd_compr_tstamp __user *)arg,
- &tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+ ret = snd_compr_update_tstamp(stream, &tstamp64);
+ if (ret == 0) {
+ if (is_32bit) {
+ snd_compr_tstamp32_from_64(&tstamp32, &tstamp64);
+ copy_from = &tstamp32;
+ copy_size = sizeof(tstamp32);
+ }
+ ret = copy_to_user((void __user *)arg, copy_from, copy_size) ?
+ -EFAULT :
+ 0;
+ }
return ret;
}
@@ -1031,7 +1071,7 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
return -EBUSY;
if (utask->origin_seqno != 0 || utask->input_size != 0)
return -EINVAL;
- task = kzalloc(sizeof(*task), GFP_KERNEL);
+ task = kzalloc_obj(*task);
if (task == NULL)
return -ENOMEM;
task->seqno = utask->seqno = snd_compr_seqno_next(stream);
@@ -1070,12 +1110,13 @@ cleanup:
static int snd_compr_task_create(struct snd_compr_stream *stream, unsigned long arg)
{
- struct snd_compr_task *task __free(kfree) = NULL;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
- task = memdup_user((void __user *)arg, sizeof(*task));
+
+ struct snd_compr_task *task __free(kfree) =
+ memdup_user((void __user *)arg, sizeof(*task));
if (IS_ERR(task))
return PTR_ERR(task);
retval = snd_compr_task_new(stream, task);
@@ -1131,12 +1172,13 @@ static int snd_compr_task_start(struct snd_compr_stream *stream, struct snd_comp
static int snd_compr_task_start_ioctl(struct snd_compr_stream *stream, unsigned long arg)
{
- struct snd_compr_task *task __free(kfree) = NULL;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
- task = memdup_user((void __user *)arg, sizeof(*task));
+
+ struct snd_compr_task *task __free(kfree) =
+ memdup_user((void __user *)arg, sizeof(*task));
if (IS_ERR(task))
return PTR_ERR(task);
retval = snd_compr_task_start(stream, task);
@@ -1222,12 +1264,13 @@ static int snd_compr_task_status(struct snd_compr_stream *stream,
static int snd_compr_task_status_ioctl(struct snd_compr_stream *stream, unsigned long arg)
{
- struct snd_compr_task_status *status __free(kfree) = NULL;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
- status = memdup_user((void __user *)arg, sizeof(*status));
+
+ struct snd_compr_task_status *status __free(kfree) =
+ memdup_user((void __user *)arg, sizeof(*status));
if (IS_ERR(status))
return PTR_ERR(status);
retval = snd_compr_task_status(stream, status);
@@ -1269,62 +1312,66 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
stream = &data->stream;
guard(mutex)(&stream->device->lock);
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
+ switch (cmd) {
+ case SNDRV_COMPRESS_IOCTL_VERSION:
return put_user(SNDRV_COMPRESS_VERSION,
(int __user *)arg) ? -EFAULT : 0;
- case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+ case SNDRV_COMPRESS_GET_CAPS:
return snd_compr_get_caps(stream, arg);
#ifndef COMPR_CODEC_CAPS_OVERFLOW
- case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+ case SNDRV_COMPRESS_GET_CODEC_CAPS:
return snd_compr_get_codec_caps(stream, arg);
#endif
- case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+ case SNDRV_COMPRESS_SET_PARAMS:
return snd_compr_set_params(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+ case SNDRV_COMPRESS_GET_PARAMS:
return snd_compr_get_params(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_SET_METADATA):
+ case SNDRV_COMPRESS_SET_METADATA:
return snd_compr_set_metadata(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_GET_METADATA):
+ case SNDRV_COMPRESS_GET_METADATA:
return snd_compr_get_metadata(stream, arg);
}
if (stream->direction == SND_COMPRESS_ACCEL) {
#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL)
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(SNDRV_COMPRESS_TASK_CREATE):
+ switch (cmd) {
+ case SNDRV_COMPRESS_TASK_CREATE:
return snd_compr_task_create(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_TASK_FREE):
+ case SNDRV_COMPRESS_TASK_FREE:
return snd_compr_task_seq(stream, arg, snd_compr_task_free_one);
- case _IOC_NR(SNDRV_COMPRESS_TASK_START):
+ case SNDRV_COMPRESS_TASK_START:
return snd_compr_task_start_ioctl(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_TASK_STOP):
+ case SNDRV_COMPRESS_TASK_STOP:
return snd_compr_task_seq(stream, arg, snd_compr_task_stop_one);
- case _IOC_NR(SNDRV_COMPRESS_TASK_STATUS):
+ case SNDRV_COMPRESS_TASK_STATUS:
return snd_compr_task_status_ioctl(stream, arg);
}
#endif
return -ENOTTY;
}
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
- return snd_compr_tstamp(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_AVAIL):
- return snd_compr_ioctl_avail(stream, arg);
- case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+ switch (cmd) {
+ case SNDRV_COMPRESS_TSTAMP:
+ return snd_compr_tstamp(stream, arg, true);
+ case SNDRV_COMPRESS_TSTAMP64:
+ return snd_compr_tstamp(stream, arg, false);
+ case SNDRV_COMPRESS_AVAIL:
+ return snd_compr_ioctl_avail(stream, arg, true);
+ case SNDRV_COMPRESS_AVAIL64:
+ return snd_compr_ioctl_avail(stream, arg, false);
+ case SNDRV_COMPRESS_PAUSE:
return snd_compr_pause(stream);
- case _IOC_NR(SNDRV_COMPRESS_RESUME):
+ case SNDRV_COMPRESS_RESUME:
return snd_compr_resume(stream);
- case _IOC_NR(SNDRV_COMPRESS_START):
+ case SNDRV_COMPRESS_START:
return snd_compr_start(stream);
- case _IOC_NR(SNDRV_COMPRESS_STOP):
+ case SNDRV_COMPRESS_STOP:
return snd_compr_stop(stream);
- case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+ case SNDRV_COMPRESS_DRAIN:
return snd_compr_drain(stream);
- case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN):
+ case SNDRV_COMPRESS_PARTIAL_DRAIN:
return snd_compr_partial_drain(stream);
- case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK):
+ case SNDRV_COMPRESS_NEXT_TRACK:
return snd_compr_next_track(stream);
}
diff --git a/sound/core/control.c b/sound/core/control.c
index 0ddade871b52..5e51857635e6 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -19,6 +19,13 @@
#include <sound/info.h>
#include <sound/control.h>
+#ifdef CONFIG_SND_CTL_DEBUG
+#define CREATE_TRACE_POINTS
+#include "control_trace.h"
+#else
+#define trace_snd_ctl_put(card, kctl, iname, expected, actual)
+#endif
+
// Max allocation size for user controls.
static int max_user_ctl_alloc_size = 8 * 1024 * 1024;
module_param_named(max_user_ctl_alloc_size, max_user_ctl_alloc_size, int, 0444);
@@ -233,7 +240,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
if (count == 0 || count > MAX_CONTROL_COUNT)
return -EINVAL;
- *kctl = kzalloc(struct_size(*kctl, vd, count), GFP_KERNEL);
+ *kctl = kzalloc_flex(**kctl, vd, count);
if (!*kctl)
return -ENOMEM;
@@ -867,9 +874,9 @@ EXPORT_SYMBOL(snd_ctl_find_id);
static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
unsigned int cmd, void __user *arg)
{
- struct snd_ctl_card_info *info __free(kfree) = NULL;
+ struct snd_ctl_card_info *info __free(kfree) =
+ kzalloc(sizeof(*info), GFP_KERNEL);
- info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
scoped_guard(rwsem_read, &snd_ioctl_rwsem) {
@@ -1244,10 +1251,10 @@ static int snd_ctl_elem_read(struct snd_card *card,
static int snd_ctl_elem_read_user(struct snd_card *card,
struct snd_ctl_elem_value __user *_control)
{
- struct snd_ctl_elem_value *control __free(kfree) = NULL;
int result;
+ struct snd_ctl_elem_value *control __free(kfree) =
+ memdup_user(_control, sizeof(*control));
- control = memdup_user(_control, sizeof(*control));
if (IS_ERR(control))
return PTR_ERR(control);
@@ -1264,6 +1271,72 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
return result;
}
+#if IS_ENABLED(CONFIG_SND_CTL_DEBUG)
+
+static const char *const snd_ctl_elem_iface_names[] = {
+ [SNDRV_CTL_ELEM_IFACE_CARD] = "CARD",
+ [SNDRV_CTL_ELEM_IFACE_HWDEP] = "HWDEP",
+ [SNDRV_CTL_ELEM_IFACE_MIXER] = "MIXER",
+ [SNDRV_CTL_ELEM_IFACE_PCM] = "PCM",
+ [SNDRV_CTL_ELEM_IFACE_RAWMIDI] = "RAWMIDI",
+ [SNDRV_CTL_ELEM_IFACE_TIMER] = "TIMER",
+ [SNDRV_CTL_ELEM_IFACE_SEQUENCER] = "SEQUENCER",
+};
+
+static int snd_ctl_put_verify(struct snd_card *card, struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *control)
+{
+ struct snd_ctl_elem_value *original = card->value_buf;
+ struct snd_ctl_elem_info info;
+ const char *iname;
+ int ret, retcmp;
+
+ memset(original, 0, sizeof(*original));
+ memset(&info, 0, sizeof(info));
+
+ ret = kctl->info(kctl, &info);
+ if (ret)
+ return ret;
+
+ ret = kctl->get(kctl, original);
+ if (ret)
+ return ret;
+
+ ret = kctl->put(kctl, control);
+ if (ret < 0)
+ return ret;
+
+ /* Sanitize the new value (control->value) before comparing. */
+ fill_remaining_elem_value(control, &info, 0);
+
+ /* With known state for both new and original, do the comparison. */
+ retcmp = memcmp(&original->value, &control->value, sizeof(original->value));
+ if (retcmp)
+ retcmp = 1;
+
+ iname = snd_ctl_elem_iface_names[kctl->id.iface];
+ trace_snd_ctl_put(&kctl->id, iname, card->number, ret, retcmp);
+
+ return ret;
+}
+
+static int snd_ctl_put(struct snd_card *card, struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *control, unsigned int access)
+{
+ if ((access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK) ||
+ (access & SNDRV_CTL_ELEM_ACCESS_VOLATILE))
+ return kctl->put(kctl, control);
+
+ return snd_ctl_put_verify(card, kctl, control);
+}
+#else
+static inline int snd_ctl_put(struct snd_card *card, struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *control, unsigned int access)
+{
+ return kctl->put(kctl, control);
+}
+#endif
+
static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
struct snd_ctl_elem_value *control)
{
@@ -1300,7 +1373,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
false);
}
if (!result)
- result = kctl->put(kctl, control);
+ result = snd_ctl_put(card, kctl, control, vd->access);
+
if (result < 0) {
up_write(&card->controls_rwsem);
return result;
@@ -1320,11 +1394,11 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
struct snd_ctl_elem_value __user *_control)
{
- struct snd_ctl_elem_value *control __free(kfree) = NULL;
struct snd_card *card;
int result;
+ struct snd_ctl_elem_value *control __free(kfree) =
+ memdup_user(_control, sizeof(*control));
- control = memdup_user(_control, sizeof(*control));
if (IS_ERR(control))
return PTR_ERR(control);
@@ -1405,7 +1479,7 @@ static bool check_user_elem_overflow(struct snd_card *card, ssize_t add)
static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
unsigned int offset;
offset = snd_ctl_get_ioff(kcontrol, &uinfo->id);
@@ -1418,7 +1492,7 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
const char *names;
unsigned int item;
unsigned int offset;
@@ -1435,7 +1509,7 @@ static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
names = ue->priv_data;
for (; item > 0; --item)
names += strlen(names) + 1;
- strcpy(uinfo->value.enumerated.name, names);
+ strscpy(uinfo->value.enumerated.name, names);
return 0;
}
@@ -1443,7 +1517,7 @@ static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
unsigned int size = ue->elem_data_size;
char *src = ue->elem_data +
snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
@@ -1456,7 +1530,7 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int err, change;
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
unsigned int size = ue->elem_data_size;
char *dst = ue->elem_data +
snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
@@ -1475,7 +1549,7 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
unsigned int size)
{
- struct user_element *ue = kctl->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kctl);
unsigned int *container;
unsigned int mask = 0;
int i;
@@ -1528,7 +1602,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
static int read_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
unsigned int size)
{
- struct user_element *ue = kctl->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kctl);
if (ue->tlv_data_size == 0 || ue->tlv_data == NULL)
return -ENXIO;
@@ -1574,6 +1648,10 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
/* check that there are enough valid names */
p = names;
for (i = 0; i < ue->info.value.enumerated.items; ++i) {
+ if (buf_len == 0) {
+ kvfree(names);
+ return -EINVAL;
+ }
name_len = strnlen(p, buf_len);
if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
kvfree(names);
@@ -1598,7 +1676,7 @@ static size_t compute_user_elem_size(size_t size, unsigned int count)
static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
// decrement the allocation size.
ue->card->user_ctl_alloc_size -= compute_user_elem_size(ue->elem_data_size, kcontrol->count);
@@ -2057,7 +2135,7 @@ static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *
{
struct snd_kctl_ioctl *pn;
- pn = kzalloc(sizeof(struct snd_kctl_ioctl), GFP_KERNEL);
+ pn = kzalloc_obj(struct snd_kctl_ioctl);
if (pn == NULL)
return -ENOMEM;
pn->fioctl = fcn;
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 6459809ed364..16bc80555f26 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -80,10 +80,10 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
struct snd_ctl_elem_info32 __user *data32)
{
struct snd_card *card = ctl->card;
- struct snd_ctl_elem_info *data __free(kfree) = NULL;
int err;
+ struct snd_ctl_elem_info *data __free(kfree) =
+ kzalloc_obj(*data);
- data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
@@ -169,14 +169,15 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
int *countp)
{
struct snd_kcontrol *kctl;
- struct snd_ctl_elem_info *info __free(kfree) = NULL;
int err;
guard(rwsem_read)(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, id);
if (!kctl)
return -ENOENT;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+ struct snd_ctl_elem_info *info __free(kfree) =
+ kzalloc_obj(*info);
if (info == NULL)
return -ENOMEM;
info->id = *id;
@@ -280,10 +281,10 @@ static int copy_ctl_value_to_user(void __user *userdata,
static int __ctl_elem_read_user(struct snd_card *card,
void __user *userdata, void __user *valuep)
{
- struct snd_ctl_elem_value *data __free(kfree) = NULL;
int err, type, count;
+ struct snd_ctl_elem_value *data __free(kfree) =
+ kzalloc_obj(*data);
- data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -314,11 +315,11 @@ static int ctl_elem_read_user(struct snd_card *card,
static int __ctl_elem_write_user(struct snd_ctl_file *file,
void __user *userdata, void __user *valuep)
{
- struct snd_ctl_elem_value *data __free(kfree) = NULL;
struct snd_card *card = file->card;
int err, type, count;
+ struct snd_ctl_elem_value *data __free(kfree) =
+ kzalloc_obj(*data);
- data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -378,9 +379,9 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
struct snd_ctl_elem_info32 __user *data32,
int replace)
{
- struct snd_ctl_elem_info *data __free(kfree) = NULL;
+ struct snd_ctl_elem_info *data __free(kfree) =
+ kzalloc_obj(*data);
- data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index e33dfcf863cf..d92b36ab5ec6 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -245,12 +245,12 @@ DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T))
static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
unsigned int group, bool set)
{
- struct snd_card *card __free(snd_card_unref) = NULL;
struct snd_kcontrol *kctl;
struct snd_kcontrol_volatile *vd;
unsigned int ioff, access, new_access;
+ struct snd_card *card __free(snd_card_unref) =
+ snd_card_ref(card_number);
- card = snd_card_ref(card_number);
if (!card)
return -ENXIO;
guard(rwsem_write)(&card->controls_rwsem);
@@ -302,13 +302,13 @@ static void snd_ctl_led_clean(struct snd_card *card)
static int snd_ctl_led_reset(int card_number, unsigned int group)
{
- struct snd_card *card __free(snd_card_unref) = NULL;
struct snd_ctl_led_ctl *lctl, *_lctl;
struct snd_ctl_led *led;
struct snd_kcontrol_volatile *vd;
bool change = false;
+ struct snd_card *card __free(snd_card_unref) =
+ snd_card_ref(card_number);
- card = snd_card_ref(card_number);
if (!card)
return -ENXIO;
@@ -598,11 +598,11 @@ static ssize_t list_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
- struct snd_card *card __free(snd_card_unref) = NULL;
struct snd_ctl_led_ctl *lctl;
size_t l = 0;
+ struct snd_card *card __free(snd_card_unref) =
+ snd_card_ref(led_card->number);
- card = snd_card_ref(led_card->number);
if (!card)
return -ENXIO;
guard(rwsem_read)(&card->controls_rwsem);
@@ -653,7 +653,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
for (group = 0; group < MAX_LED; group++) {
led = &snd_ctl_leds[group];
- led_card = kzalloc(sizeof(*led_card), GFP_KERNEL);
+ led_card = kzalloc_obj(*led_card);
if (!led_card)
goto cerr2;
led_card->number = card->number;
diff --git a/sound/core/control_trace.h b/sound/core/control_trace.h
new file mode 100644
index 000000000000..d30e654b0860
--- /dev/null
+++ b/sound/core/control_trace.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM snd_ctl
+
+#if !defined(_TRACE_SND_CTL_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SND_CTL_H
+
+#include <linux/tracepoint.h>
+#include <uapi/sound/asound.h>
+
+TRACE_EVENT(snd_ctl_put,
+
+ TP_PROTO(struct snd_ctl_elem_id *id, const char *iname, unsigned int card,
+ int expected, int actual),
+
+ TP_ARGS(id, iname, card, expected, actual),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, numid)
+ __string(iname, iname)
+ __string(kname, id->name)
+ __field(unsigned int, index)
+ __field(unsigned int, device)
+ __field(unsigned int, subdevice)
+ __field(unsigned int, card)
+ __field(int, expected)
+ __field(int, actual)
+ ),
+
+ TP_fast_assign(
+ __entry->numid = id->numid;
+ __assign_str(iname);
+ __assign_str(kname);
+ __entry->index = id->index;
+ __entry->device = id->device;
+ __entry->subdevice = id->subdevice;
+ __entry->card = card;
+ __entry->expected = expected;
+ __entry->actual = actual;
+ ),
+
+ TP_printk("%s: expected=%d, actual=%d for ctl numid=%d, iface=%s, name='%s', index=%d, device=%d, subdevice=%d, card=%d\n",
+ __entry->expected == __entry->actual ? "success" : "fail",
+ __entry->expected, __entry->actual, __entry->numid,
+ __get_str(iname), __get_str(kname), __entry->index,
+ __entry->device, __entry->subdevice, __entry->card)
+);
+
+#endif /* _TRACE_SND_CTL_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE control_trace
+#include <trace/define_trace.h>
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
index 709b1a9c2caa..6b6ab34fbde8 100644
--- a/sound/core/ctljack.c
+++ b/sound/core/ctljack.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/export.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -46,17 +47,20 @@ static int get_available_index(struct snd_card *card, const char *name)
return sid.index;
}
-static void jack_kctl_name_gen(char *name, const char *src_name, int size)
+static void jack_kctl_name_gen(char *name, const char *src_name, size_t size)
{
size_t count = strlen(src_name);
- bool need_cat = true;
+ const char *suf = " Jack";
+ size_t suf_len = strlen(suf);
+ bool append_suf = true;
- /* remove redundant " Jack" from src_name */
- if (count >= 5)
- need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false;
-
- snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name);
+ if (count >= suf_len)
+ append_suf = strncmp(&src_name[count - suf_len], suf, suf_len) != 0;
+ if (append_suf)
+ snprintf(name, size, "%s%s", src_name, suf);
+ else
+ strscpy(name, src_name, size);
}
struct snd_kcontrol *
diff --git a/sound/core/device.c b/sound/core/device.c
index b57d80a17052..5f2aa476d89b 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -34,7 +34,7 @@ int snd_device_new(struct snd_card *card, enum snd_device_type type,
if (snd_BUG_ON(!card || !device_data || !ops))
return -ENXIO;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc_obj(*dev);
if (!dev)
return -ENOMEM;
INIT_LIST_HEAD(&dev->list);
@@ -237,26 +237,3 @@ void snd_device_free_all(struct snd_card *card)
list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
__snd_device_free(dev);
}
-
-/**
- * snd_device_get_state - Get the current state of the given device
- * @card: the card instance
- * @device_data: the data pointer to release
- *
- * Returns the current state of the given device object. For the valid
- * device, either @SNDRV_DEV_BUILD, @SNDRV_DEV_REGISTERED or
- * @SNDRV_DEV_DISCONNECTED is returned.
- * Or for a non-existing device, -1 is returned as an error.
- *
- * Return: the current state, or -1 if not found
- */
-int snd_device_get_state(struct snd_card *card, void *device_data)
-{
- struct snd_device *dev;
-
- dev = look_for_dev(card, device_data);
- if (dev)
- return dev->state;
- return -1;
-}
-EXPORT_SYMBOL_GPL(snd_device_get_state);
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
index e9c60dce59fb..9fcd1c03dc5b 100644
--- a/sound/core/hrtimer.c
+++ b/sound/core/hrtimer.c
@@ -6,6 +6,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/hrtimer.h>
@@ -43,7 +44,7 @@ static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
}
/* calculate the drift */
- delta = ktime_sub(hrt->base->get_time(), hrtimer_get_expires(hrt));
+ delta = ktime_sub(hrtimer_cb_get_time(hrt), hrtimer_get_expires(hrt));
if (delta > 0)
ticks += ktime_divns(delta, ticks * resolution);
@@ -63,7 +64,7 @@ static int snd_hrtimer_open(struct snd_timer *t)
{
struct snd_hrtimer *stime;
- stime = kzalloc(sizeof(*stime), GFP_KERNEL);
+ stime = kzalloc_obj(*stime);
if (!stime)
return -ENOMEM;
stime->timer = t;
@@ -138,7 +139,7 @@ static int __init snd_hrtimer_init(void)
return err;
timer->module = THIS_MODULE;
- strcpy(timer->name, "HR timer");
+ strscpy(timer->name, "HR timer");
timer->hw = hrtimer_hw;
timer->hw.resolution = resolution;
timer->hw.ticks = NANO_SEC / resolution;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 09200df2932c..973d11732bfd 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -375,7 +375,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
return -ENXIO;
if (rhwdep)
*rhwdep = NULL;
- hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
+ hwdep = kzalloc_obj(*hwdep);
if (!hwdep)
return -ENOMEM;
diff --git a/sound/core/info.c b/sound/core/info.c
index 1f5b8a3d9e3b..54834dbe6b59 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -79,7 +79,7 @@ static int alloc_info_private(struct snd_info_entry *entry,
return -ENODEV;
if (!try_module_get(entry->module))
return -EFAULT;
- data = kzalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc_obj(*data);
if (!data) {
module_put(entry->module);
return -ENOMEM;
@@ -311,7 +311,7 @@ static ssize_t snd_info_text_entry_write(struct file *file,
guard(mutex)(&entry->access);
buf = data->wbuffer;
if (!buf) {
- data->wbuffer = buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ data->wbuffer = buf = kzalloc_obj(*buf);
if (!buf)
return -ENOMEM;
}
@@ -355,7 +355,7 @@ static int snd_info_text_entry_open(struct inode *inode, struct file *file)
if (err < 0)
return err;
- data->rbuffer = kzalloc(sizeof(*data->rbuffer), GFP_KERNEL);
+ data->rbuffer = kzalloc_obj(*data->rbuffer);
if (!data->rbuffer) {
err = -ENOMEM;
goto error;
@@ -663,7 +663,7 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent,
struct module *module)
{
struct snd_info_entry *entry;
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc_obj(*entry);
if (entry == NULL)
return NULL;
entry->name = kstrdup(name, GFP_KERNEL);
diff --git a/sound/core/init.c b/sound/core/init.c
index 114fb87de990..0c316189e947 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -129,7 +129,7 @@ int snd_device_alloc(struct device **dev_p, struct snd_card *card)
struct device *dev;
*dev_p = NULL;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc_obj(*dev);
if (!dev)
return -ENOMEM;
device_initialize(dev);
@@ -363,6 +363,11 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
card->debugfs_root = debugfs_create_dir(dev_name(&card->card_dev),
sound_debugfs_root);
#endif
+#ifdef CONFIG_SND_CTL_DEBUG
+ card->value_buf = kmalloc(sizeof(*card->value_buf), GFP_KERNEL);
+ if (!card->value_buf)
+ return -ENOMEM;
+#endif
return 0;
__error_ctl:
@@ -587,6 +592,9 @@ static int snd_card_do_free(struct snd_card *card)
snd_device_free_all(card);
if (card->private_free)
card->private_free(card);
+#ifdef CONFIG_SND_CTL_DEBUG
+ kfree(card->value_buf);
+#endif
if (snd_info_card_free(card) < 0) {
dev_warn(card->dev, "unable to free card info\n");
/* Not fatal error */
@@ -723,27 +731,25 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
* ("card" conflicts with proc directories)
*/
if (!*id || !strncmp(id, "card", 4)) {
- strcpy(id, "Default");
+ strscpy(card->id, "Default");
is_default = true;
}
len = strlen(id);
for (loops = 0; loops < SNDRV_CARDS; loops++) {
- char *spos;
char sfxstr[5]; /* "_012" */
- int sfxlen;
+ int sfxlen, slen;
if (card_id_ok(card, id))
return; /* OK */
/* Add _XYZ suffix */
- sprintf(sfxstr, "_%X", loops + 1);
- sfxlen = strlen(sfxstr);
+ sfxlen = scnprintf(sfxstr, sizeof(sfxstr), "_%X", loops + 1);
if (len + sfxlen >= sizeof(card->id))
- spos = id + sizeof(card->id) - sfxlen - 1;
+ slen = sizeof(card->id) - sfxlen - 1;
else
- spos = id + len;
- strcpy(spos, sfxstr);
+ slen = len;
+ strscpy(id + slen, sfxstr, sizeof(card->id) - slen);
}
/* fallback to the default id */
if (!is_default) {
@@ -801,7 +807,7 @@ static ssize_t id_store(struct device *dev, struct device_attribute *attr,
guard(mutex)(&snd_card_mutex);
if (!card_id_ok(NULL, buf1))
return -EEXIST;
- strcpy(card->id, buf1);
+ strscpy(card->id, buf1);
snd_info_card_id_change(card);
return count;
@@ -1062,7 +1068,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
{
struct snd_monitor_file *mfile;
- mfile = kmalloc(sizeof(*mfile), GFP_KERNEL);
+ mfile = kmalloc_obj(*mfile);
if (mfile == NULL)
return -ENOMEM;
mfile->file = file;
diff --git a/sound/core/jack.c b/sound/core/jack.c
index e4bcecdf89b7..5e8a2f3f4196 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -34,6 +34,7 @@ static const int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
SW_JACK_PHYSICAL_INSERT,
SW_VIDEOOUT_INSERT,
SW_LINEIN_INSERT,
+ SW_USB_INSERT,
};
#endif /* CONFIG_SND_JACK_INPUT_DEV */
@@ -241,8 +242,9 @@ static ssize_t jack_kctl_id_read(struct file *file,
static const char * const jack_events_name[] = {
"HEADPHONE(0x0001)", "MICROPHONE(0x0002)", "LINEOUT(0x0004)",
"MECHANICAL(0x0008)", "VIDEOOUT(0x0010)", "LINEIN(0x0020)",
- "", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)", "BTN_3(0x0800)",
- "BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)", "",
+ "USB(0x0040)", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)",
+ "BTN_3(0x0800)", "BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)",
+ "",
};
/* the recommended buffer size is 256 */
@@ -438,7 +440,7 @@ static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const cha
if (err < 0)
return NULL;
- jack_kctl = kzalloc(sizeof(*jack_kctl), GFP_KERNEL);
+ jack_kctl = kzalloc_obj(*jack_kctl);
if (!jack_kctl)
goto error;
@@ -514,7 +516,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
return -ENOMEM;
}
- jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL);
+ jack = kzalloc_obj(struct snd_jack);
if (jack == NULL)
return -ENOMEM;
@@ -575,25 +577,6 @@ EXPORT_SYMBOL(snd_jack_new);
#ifdef CONFIG_SND_JACK_INPUT_DEV
/**
- * snd_jack_set_parent - Set the parent device for a jack
- *
- * @jack: The jack to configure
- * @parent: The device to set as parent for the jack.
- *
- * Set the parent for the jack devices in the device tree. This
- * function is only valid prior to registration of the jack. If no
- * parent is configured then the parent device will be the sound card.
- */
-void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
-{
- WARN_ON(jack->registered);
- guard(mutex)(&jack->input_dev_lock);
- if (jack->input_dev)
- jack->input_dev->dev.parent = parent;
-}
-EXPORT_SYMBOL(snd_jack_set_parent);
-
-/**
* snd_jack_set_key - Set a key mapping on a jack
*
* @jack: The jack to configure
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index b3853583d2ae..9320671dfcc8 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -719,12 +719,12 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
unsigned int idx, npages;
void *p;
- sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
+ sgbuf = kzalloc_obj(*sgbuf);
if (!sgbuf)
return NULL;
size = PAGE_ALIGN(size);
sgbuf->count = size >> PAGE_SHIFT;
- sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
+ sgbuf->pages = kvzalloc_objs(*sgbuf->pages, sgbuf->count);
sgbuf->npages = kvcalloc(sgbuf->count, sizeof(*sgbuf->npages), GFP_KERNEL);
if (!sgbuf->pages || !sgbuf->npages)
goto error;
diff --git a/sound/core/misc.c b/sound/core/misc.c
index c2fda3bd90a0..5aca09edf971 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -100,14 +100,18 @@ static LIST_HEAD(snd_fasync_list);
static void snd_fasync_work_fn(struct work_struct *work)
{
struct snd_fasync *fasync;
+ int signal, poll;
spin_lock_irq(&snd_fasync_lock);
while (!list_empty(&snd_fasync_list)) {
fasync = list_first_entry(&snd_fasync_list, struct snd_fasync, list);
list_del_init(&fasync->list);
+ if (!fasync->on)
+ continue;
+ signal = fasync->signal;
+ poll = fasync->poll;
spin_unlock_irq(&snd_fasync_lock);
- if (fasync->on)
- kill_fasync(&fasync->fasync, fasync->signal, fasync->poll);
+ kill_fasync(&fasync->fasync, signal, poll);
spin_lock_irq(&snd_fasync_lock);
}
spin_unlock_irq(&snd_fasync_lock);
@@ -127,35 +131,30 @@ int snd_fasync_helper(int fd, struct file *file, int on,
INIT_LIST_HEAD(&fasync->list);
}
- spin_lock_irq(&snd_fasync_lock);
- if (*fasyncp) {
- kfree(fasync);
- fasync = *fasyncp;
- } else {
- if (!fasync) {
- spin_unlock_irq(&snd_fasync_lock);
- return 0;
+ scoped_guard(spinlock_irq, &snd_fasync_lock) {
+ if (*fasyncp) {
+ kfree(fasync);
+ fasync = *fasyncp;
+ } else {
+ if (!fasync)
+ return 0;
+ *fasyncp = fasync;
}
- *fasyncp = fasync;
+ fasync->on = on;
}
- fasync->on = on;
- spin_unlock_irq(&snd_fasync_lock);
return fasync_helper(fd, file, on, &fasync->fasync);
}
EXPORT_SYMBOL_GPL(snd_fasync_helper);
void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll)
{
- unsigned long flags;
-
if (!fasync || !fasync->on)
return;
- spin_lock_irqsave(&snd_fasync_lock, flags);
+ guard(spinlock_irqsave)(&snd_fasync_lock);
fasync->signal = signal;
fasync->poll = poll;
list_move(&fasync->list, &snd_fasync_list);
schedule_work(&snd_fasync_work);
- spin_unlock_irqrestore(&snd_fasync_lock, flags);
}
EXPORT_SYMBOL_GPL(snd_kill_fasync);
@@ -163,7 +162,10 @@ void snd_fasync_free(struct snd_fasync *fasync)
{
if (!fasync)
return;
- fasync->on = 0;
+
+ scoped_guard(spinlock_irq, &snd_fasync_lock)
+ list_del_init(&fasync->list);
+
flush_work(&snd_fasync_work);
kfree(fasync);
}
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c
index 05b58d4fc2b7..467fc6847bc9 100644
--- a/sound/core/oss/copy.c
+++ b/sound/core/oss/copy.c
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* Linear conversion Plug-In
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/time.h>
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index d870b2d93135..9317f971a0d3 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* PCM I/O Plug-In Interface
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/time.h>
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 797d838a2f9e..6e51cfdca238 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -1,23 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* Linear conversion Plug-In
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>,
* Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/time.h>
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 05fc8911479c..591cff800329 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -47,7 +47,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
snd_card_unref(card);
return err;
}
- fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
+ fmixer = kzalloc_obj(*fmixer);
if (fmixer == NULL) {
snd_card_file_remove(card, file);
snd_card_unref(card);
@@ -517,19 +517,22 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
unsigned int numid,
int *left, int *right)
{
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@@ -550,19 +553,22 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
int *left, int *right,
int route)
{
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@@ -609,8 +615,6 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
unsigned int numid,
int left, int right)
{
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
int res;
@@ -618,11 +622,16 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@@ -646,8 +655,6 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
int left, int right,
int route)
{
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
struct snd_kcontrol *kctl;
struct snd_card *card = fmixer->card;
int res;
@@ -655,11 +662,16 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
if (uinfo == NULL || uctl == NULL)
return;
if (kctl->info(kctl, uinfo))
@@ -783,15 +795,17 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
struct snd_kcontrol *kctl;
struct snd_mixer_oss_slot *pslot;
struct slot *slot;
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
int err, idx;
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
if (uinfo == NULL || uctl == NULL)
return -ENOMEM;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return -ENODEV;
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (!kctl)
return -ENOENT;
@@ -825,16 +839,18 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
struct snd_kcontrol *kctl;
struct snd_mixer_oss_slot *pslot;
struct slot *slot = NULL;
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
int err;
unsigned int idx;
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
if (uinfo == NULL || uctl == NULL)
return -ENOMEM;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return -ENODEV;
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (!kctl)
return -ENOENT;
@@ -872,18 +888,20 @@ struct snd_mixer_oss_assign_table {
static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *slot, const char *name, int index, int item)
{
- struct snd_ctl_elem_info *info __free(kfree) = NULL;
struct snd_kcontrol *kcontrol;
struct snd_card *card = mixer->card;
int err;
+ struct snd_ctl_elem_info *info __free(kfree) =
+ kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
scoped_guard(rwsem_read, &card->controls_rwsem) {
+ if (card->shutdown)
+ return -ENODEV;
kcontrol = snd_mixer_oss_test_id(mixer, name, index);
if (kcontrol == NULL)
return 0;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
err = kcontrol->info(kcontrol, info);
if (err < 0)
return err;
@@ -991,7 +1009,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
struct slot *pslot;
struct snd_kcontrol *kctl;
struct snd_mixer_oss_slot *rslot;
- char str[64];
+ const char *str;
/* check if already assigned */
if (mixer->slots[ptr->oss_id].get_volume && ! replace_old)
@@ -1002,23 +1020,25 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
return 0;
guard(rwsem_read)(&mixer->card->controls_rwsem);
+ if (mixer->card->shutdown)
+ return -ENODEV;
kctl = NULL;
if (!ptr->index)
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (kctl) {
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kzalloc_obj(*uinfo);
- uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
if (!uinfo)
return -ENOMEM;
if (kctl->info(kctl, uinfo))
return 0;
- strcpy(str, ptr->name);
+ str = ptr->name;
if (!strcmp(str, "Master"))
- strcpy(str, "Mix");
- if (!strcmp(str, "Master Mono"))
- strcpy(str, "Mix Mono");
+ str = "Mix";
+ else if (!strcmp(str, "Master Mono"))
+ str = "Mix Mono";
slot.capture_item = 0;
if (!strcmp(uinfo->value.enumerated.name, str)) {
slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
@@ -1035,7 +1055,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
}
}
if (slot.present != 0) {
- pslot = kmalloc(sizeof(slot), GFP_KERNEL);
+ pslot = kmalloc_obj(slot);
if (! pslot)
return -ENOMEM;
*pslot = slot;
@@ -1295,7 +1315,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) {
int idx, err;
- mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
+ mixer = kzalloc_objs(*mixer, 2);
if (mixer == NULL)
return -ENOMEM;
mutex_init(&mixer->reg_mutex);
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index fe27034f2846..a95386e55fa1 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* Mu-Law conversion Plug-In Interface
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
* Uros Bizjak <uros@kss-loka.si>
*
* Based on reference implementation by Sun Microsystems, Inc.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/time.h>
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 4683b9139c56..a140a0d9abb8 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -377,7 +377,6 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
snd_pcm_hw_param_t var, unsigned int best,
int *dir)
{
- struct snd_pcm_hw_params *save __free(kfree) = NULL;
int v;
unsigned int saved_min;
int last = 0;
@@ -397,19 +396,22 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
maxdir = 1;
max--;
}
- save = kmalloc(sizeof(*save), GFP_KERNEL);
+
+ struct snd_pcm_hw_params *save __free(kfree) =
+ kmalloc_obj(*save);
if (save == NULL)
return -ENOMEM;
*save = *params;
saved_min = min;
min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
if (min >= 0) {
- struct snd_pcm_hw_params *params1 __free(kfree) = NULL;
if (max < 0)
goto _end;
if ((unsigned int)min == saved_min && mindir == valdir)
goto _end;
- params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
+
+ struct snd_pcm_hw_params *params1 __free(kfree) =
+ kmalloc_obj(*params1);
if (params1 == NULL)
return -ENOMEM;
*params1 = *save;
@@ -781,10 +783,10 @@ static int choose_rate(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, unsigned int best_rate)
{
const struct snd_interval *it;
- struct snd_pcm_hw_params *save __free(kfree) = NULL;
unsigned int rate, prev;
- save = kmalloc(sizeof(*save), GFP_KERNEL);
+ struct snd_pcm_hw_params *save __free(kfree) =
+ kmalloc_obj(*save);
if (save == NULL)
return -ENOMEM;
*save = *params;
@@ -859,9 +861,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
if (!runtime->oss.params)
return 0;
- sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL);
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
+ sw_params = kzalloc_obj(*sw_params);
+ params = kmalloc_obj(*params);
+ sparams = kmalloc_obj(*sparams);
if (!sw_params || !params || !sparams) {
err = -ENOMEM;
goto failure;
@@ -1074,8 +1076,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
runtime->oss.params = 0;
runtime->oss.prepare = 1;
runtime->oss.buffer_used = 0;
- if (runtime->dma_area)
- snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
+ err = snd_pcm_runtime_buffer_set_silence(runtime);
+ if (err < 0)
+ goto failure;
runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
@@ -1224,14 +1227,16 @@ static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substrea
snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_state_t state;
int ret;
while (1) {
- if (runtime->state == SNDRV_PCM_STATE_XRUN ||
- runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
+ state = snd_pcm_get_state(substream);
+ if (state == SNDRV_PCM_STATE_XRUN ||
+ state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: write: recovering from %s\n",
- runtime->state == SNDRV_PCM_STATE_XRUN ?
+ state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_oss_prepare(substream);
@@ -1246,7 +1251,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
break;
/* test, if we can't store new data, because the stream */
/* has not been started */
- if (runtime->state == SNDRV_PCM_STATE_PREPARED)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_PREPARED)
return -EAGAIN;
}
return ret;
@@ -1256,20 +1261,22 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t delay;
+ snd_pcm_state_t state;
int ret;
while (1) {
- if (runtime->state == SNDRV_PCM_STATE_XRUN ||
- runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
+ state = snd_pcm_get_state(substream);
+ if (state == SNDRV_PCM_STATE_XRUN ||
+ state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: read: recovering from %s\n",
- runtime->state == SNDRV_PCM_STATE_XRUN ?
+ state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
if (ret < 0)
break;
- } else if (runtime->state == SNDRV_PCM_STATE_SETUP) {
+ } else if (state == SNDRV_PCM_STATE_SETUP) {
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
break;
@@ -1282,7 +1289,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
frames, in_kernel);
mutex_lock(&runtime->oss.params_lock);
if (ret == -EPIPE) {
- if (runtime->state == SNDRV_PCM_STATE_DRAINING) {
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_DRAINING) {
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
if (ret < 0)
break;
@@ -1298,15 +1305,16 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_state_t state;
int ret;
while (1) {
- if (runtime->state == SNDRV_PCM_STATE_XRUN ||
- runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
+ state = snd_pcm_get_state(substream);
+ if (state == SNDRV_PCM_STATE_XRUN ||
+ state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: writev: recovering from %s\n",
- runtime->state == SNDRV_PCM_STATE_XRUN ?
+ state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_oss_prepare(substream);
@@ -1319,7 +1327,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
/* test, if we can't store new data, because the stream */
/* has not been started */
- if (runtime->state == SNDRV_PCM_STATE_PREPARED)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_PREPARED)
return -EAGAIN;
}
return ret;
@@ -1327,21 +1335,22 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_state_t state;
int ret;
while (1) {
- if (runtime->state == SNDRV_PCM_STATE_XRUN ||
- runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
+ state = snd_pcm_get_state(substream);
+ if (state == SNDRV_PCM_STATE_XRUN ||
+ state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: readv: recovering from %s\n",
- runtime->state == SNDRV_PCM_STATE_XRUN ?
+ state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
if (ret < 0)
break;
- } else if (runtime->state == SNDRV_PCM_STATE_SETUP) {
+ } else if (state == SNDRV_PCM_STATE_SETUP) {
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
break;
@@ -1835,7 +1844,6 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
struct snd_pcm_substream *substream;
int err;
int direct;
- struct snd_pcm_hw_params *params __free(kfree) = NULL;
unsigned int formats = 0;
const struct snd_mask *format_mask;
int fmt;
@@ -1855,7 +1863,9 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
AFMT_S32_LE | AFMT_S32_BE |
AFMT_S24_LE | AFMT_S24_BE |
AFMT_S24_PACKED;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
+
+ struct snd_pcm_hw_params *params __free(kfree) =
+ kmalloc_obj(*params);
if (!params)
return -ENOMEM;
_snd_pcm_hw_params_any(params);
@@ -2003,9 +2013,8 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig
static int snd_pcm_oss_nonblock(struct file * file)
{
- spin_lock(&file->f_lock);
+ guard(spinlock)(&file->f_lock);
file->f_flags |= O_NONBLOCK;
- spin_unlock(&file->f_lock);
return 0;
}
@@ -2415,7 +2424,7 @@ static int snd_pcm_oss_open_file(struct file *file,
if (rpcm_oss_file)
*rpcm_oss_file = NULL;
- pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
+ pcm_oss_file = kzalloc_obj(*pcm_oss_file);
if (pcm_oss_file == NULL)
return -ENOMEM;
@@ -3029,7 +3038,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
}
} while (*str);
if (setup == NULL) {
- setup = kmalloc(sizeof(*setup), GFP_KERNEL);
+ setup = kmalloc_obj(*setup);
if (! setup) {
buffer->error = -ENOMEM;
return;
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 82e180c776ae..14b4a390a219 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -1,23 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* PCM Plug-In shared (kernel/library) code
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#if 0
@@ -178,7 +163,7 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
channels = src_format->channels;
else
channels = dst_format->channels;
- plugin->buf_channels = kcalloc(channels, sizeof(*plugin->buf_channels), GFP_KERNEL);
+ plugin->buf_channels = kzalloc_objs(*plugin->buf_channels, channels);
if (plugin->buf_channels == NULL) {
snd_pcm_plugin_free(plugin);
return -ENOMEM;
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index b56eeda5e30e..68711ad251ee 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* Rate conversion Plug-In
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/time.h>
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index 72dea04197ef..20f7032d12bb 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* Route Plug-In
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <linux/time.h>
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 283aac441fa0..bfedf571e021 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -328,13 +328,13 @@ static const char *snd_pcm_oss_format_name(int format)
static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
struct snd_info_buffer *buffer)
{
- struct snd_pcm_info *info __free(kfree) = NULL;
int err;
if (! substream)
return;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ struct snd_pcm_info *info __free(kfree) =
+ kmalloc_obj(*info);
if (!info)
return;
@@ -657,7 +657,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
}
prev = NULL;
for (idx = 0, prev = NULL; idx < substream_count; idx++) {
- substream = kzalloc(sizeof(*substream), GFP_KERNEL);
+ substream = kzalloc_obj(*substream);
if (!substream)
return -ENOMEM;
substream->pcm = pcm;
@@ -713,7 +713,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
return -ENXIO;
if (rpcm)
*rpcm = NULL;
- pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+ pcm = kzalloc_obj(*pcm);
if (!pcm)
return -ENOMEM;
pcm->card = card;
@@ -935,7 +935,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
if (substream == NULL)
return -EAGAIN;
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+ runtime = kzalloc_obj(*runtime);
if (runtime == NULL)
return -ENOMEM;
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index a42ec7f5a1da..5313f50f17da 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -235,7 +235,6 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
int refine,
struct snd_pcm_hw_params32 __user *data32)
{
- struct snd_pcm_hw_params *data __free(kfree) = NULL;
struct snd_pcm_runtime *runtime;
int err;
@@ -243,7 +242,8 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
if (!runtime)
return -ENOTTY;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ struct snd_pcm_hw_params *data __free(kfree) =
+ kmalloc_obj(*data);
if (!data)
return -ENOMEM;
@@ -332,7 +332,6 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
compat_caddr_t buf;
compat_caddr_t __user *bufptr;
u32 frames;
- void __user **bufs __free(kfree) = NULL;
int err, ch, i;
if (! substream->runtime)
@@ -349,7 +348,9 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
get_user(frames, &data32->frames))
return -EFAULT;
bufptr = compat_ptr(buf);
- bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL);
+
+ void __user **bufs __free(kfree) =
+ kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < ch; i++) {
@@ -377,12 +378,10 @@ struct snd_pcm_mmap_status_x32 {
s32 pad1;
u32 hw_ptr;
u32 pad2; /* alignment */
- s64 tstamp_sec;
- s64 tstamp_nsec;
+ struct __snd_timespec64 tstamp;
snd_pcm_state_t suspended_state;
s32 pad3;
- s64 audio_tstamp_sec;
- s64 audio_tstamp_nsec;
+ struct __snd_timespec64 audio_tstamp;
} __packed;
struct snd_pcm_mmap_control_x32 {
@@ -418,9 +417,7 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
if (snd_BUG_ON(!runtime))
return -EINVAL;
- if (get_user(sflags, &src->flags) ||
- get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
- get_user(scontrol.avail_min, &src->c.control.avail_min))
+ if (snd_pcm_sync_ptr_get_user(sflags, scontrol, src))
return -EFAULT;
if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
err = snd_pcm_hwsync(substream);
@@ -433,11 +430,13 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
if (!boundary)
boundary = 0x7fffffff;
scoped_guard(pcm_stream_lock_irq, substream) {
- /* FIXME: we should consider the boundary for the sync from app */
- if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
- control->appl_ptr = scontrol.appl_ptr;
- else
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) {
+ err = pcm_lib_apply_appl_ptr(substream, scontrol.appl_ptr);
+ if (err < 0)
+ return err;
+ } else {
scontrol.appl_ptr = control->appl_ptr % boundary;
+ }
if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
control->avail_min = scontrol.avail_min;
else
@@ -450,15 +449,7 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
}
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
- if (put_user(sstatus.state, &src->s.status.state) ||
- put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
- put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
- put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
- put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
- put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
- put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
- put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
- put_user(scontrol.avail_min, &src->c.control.avail_min))
+ if (snd_pcm_sync_ptr_put_user(sstatus, scontrol, src))
return -EFAULT;
return 0;
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index b134a51b3fd5..1306b04be171 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -111,6 +111,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->dst_addr = dma_data->addr;
slave_config->dst_maxburst = dma_data->maxburst;
+ slave_config->dst_port_window_size = dma_data->port_window_size;
if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)
slave_config->dst_addr_width =
DMA_SLAVE_BUSWIDTH_UNDEFINED;
@@ -119,6 +120,7 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
} else {
slave_config->src_addr = dma_data->addr;
slave_config->src_maxburst = dma_data->maxburst;
+ slave_config->src_port_window_size = dma_data->port_window_size;
if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)
slave_config->src_addr_width =
DMA_SLAVE_BUSWIDTH_UNDEFINED;
@@ -316,7 +318,7 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+ prtd = kzalloc_obj(*prtd);
if (!prtd)
return -ENOMEM;
@@ -328,27 +330,6 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
-/**
- * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
- * @substream: PCM substream
- * @filter_fn: Filter function used to request the DMA channel
- * @filter_data: Data passed to the DMA filter function
- *
- * This function will request a DMA channel using the passed filter function and
- * data. The function should usually be called from the pcm open callback. Note
- * that this function will use private_data field of the substream's runtime. So
- * it is not available to your pcm driver implementation.
- *
- * Return: 0 on success, a negative error code otherwise
- */
-int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
- dma_filter_fn filter_fn, void *filter_data)
-{
- return snd_dmaengine_pcm_open(substream,
- snd_dmaengine_pcm_request_channel(filter_fn, filter_data));
-}
-EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
-
int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 688eefce82fa..cb2eebaac85f 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -379,7 +379,7 @@ int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
* in console or for audio devices. Assume the highest speakers
* configuration, to _not_ prohibit multi-channel audio playback.
*/
- if (!e->spk_alloc)
+ if (!e->spk_alloc && e->sad_count)
e->spk_alloc = 0xffff;
return 0;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 6eaa950504cf..09c421cd9319 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2601,7 +2601,7 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
if (WARN_ON(pcm->streams[stream].chmap_kctl))
return -EBUSY;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc_obj(*info);
if (!info)
return -ENOMEM;
info->pcm = pcm;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ea3941f8666b..cfe9f10e7359 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -448,7 +448,7 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
/* dma_max=0 means the fixed size preallocation */
if (substream->dma_buffer.area && !substream->dma_max)
return -ENOMEM;
- dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
+ dmab = kzalloc_obj(*dmab);
if (! dmab)
return -ENOMEM;
dmab->dev = substream->dma_buffer.dev;
@@ -458,7 +458,7 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
substream->stream,
size, dmab) < 0) {
kfree(dmab);
- pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
+ pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot allocate for size %zu\n",
substream->pcm->card->number, substream->pcm->device,
substream->stream ? 'c' : 'p', substream->number,
substream->pcm->name, size);
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index d3a08e292072..180b6b64a448 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -1,24 +1,9 @@
+// SPDX-License-Identifier: LGPL-2.0+
/*
* PCM Interface - misc routines
* Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
-
+
#include <linux/time.h>
#include <linux/export.h>
#include <sound/core.h>
@@ -586,33 +571,3 @@ unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
return rates_a & rates_b;
}
EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);
-
-/**
- * snd_pcm_rate_range_to_bits - converts rate range to SNDRV_PCM_RATE_xxx bit
- * @rate_min: the minimum sample rate
- * @rate_max: the maximum sample rate
- *
- * This function has an implicit assumption: the rates in the given range have
- * only the pre-defined rates like 44100 or 16000.
- *
- * Return: The SNDRV_PCM_RATE_xxx flag that corresponds to the given rate range,
- * or SNDRV_PCM_RATE_KNOT for an unknown range.
- */
-unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min,
- unsigned int rate_max)
-{
- unsigned int rates = 0;
- int i;
-
- for (i = 0; i < snd_pcm_known_rates.count; i++) {
- if (snd_pcm_known_rates.list[i] >= rate_min
- && snd_pcm_known_rates.list[i] <= rate_max)
- rates |= 1 << i;
- }
-
- if (!rates)
- rates = SNDRV_PCM_RATE_KNOT;
-
- return rates;
-}
-EXPORT_SYMBOL_GPL(snd_pcm_rate_range_to_bits);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 6c2b6a62d9d2..a541bb235cfa 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -24,6 +24,7 @@
#include <sound/minors.h>
#include <linux/uio.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
#include "pcm_local.h"
@@ -83,19 +84,24 @@ void snd_pcm_group_init(struct snd_pcm_group *group)
}
/* define group lock helpers */
-#define DEFINE_PCM_GROUP_LOCK(action, mutex_action) \
+#define DEFINE_PCM_GROUP_LOCK(action, bh_lock, bh_unlock, mutex_action) \
static void snd_pcm_group_ ## action(struct snd_pcm_group *group, bool nonatomic) \
{ \
- if (nonatomic) \
+ if (nonatomic) { \
mutex_ ## mutex_action(&group->mutex); \
- else \
- spin_ ## action(&group->lock); \
+ } else { \
+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && bh_lock) \
+ local_bh_disable(); \
+ spin_ ## action(&group->lock); \
+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && bh_unlock) \
+ local_bh_enable(); \
+ } \
}
-DEFINE_PCM_GROUP_LOCK(lock, lock);
-DEFINE_PCM_GROUP_LOCK(unlock, unlock);
-DEFINE_PCM_GROUP_LOCK(lock_irq, lock);
-DEFINE_PCM_GROUP_LOCK(unlock_irq, unlock);
+DEFINE_PCM_GROUP_LOCK(lock, false, false, lock);
+DEFINE_PCM_GROUP_LOCK(unlock, false, false, unlock);
+DEFINE_PCM_GROUP_LOCK(lock_irq, true, false, lock);
+DEFINE_PCM_GROUP_LOCK(unlock_irq, false, true, unlock);
/**
* snd_pcm_stream_lock - Lock the PCM stream
@@ -236,10 +242,10 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
int snd_pcm_info_user(struct snd_pcm_substream *substream,
struct snd_pcm_info __user * _info)
{
- struct snd_pcm_info *info __free(kfree) = NULL;
int err;
+ struct snd_pcm_info *info __free(kfree) =
+ kmalloc_obj(*info);
- info = kmalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
err = snd_pcm_info(substream, info);
@@ -358,7 +364,6 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
struct snd_pcm_hw_constraints *constrs =
&substream->runtime->hw_constraints;
unsigned int k;
- unsigned int *rstamps __free(kfree) = NULL;
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp;
struct snd_pcm_hw_rule *r;
@@ -374,7 +379,8 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
* Each member of 'rstamps' array represents the sequence number of
* recent application of corresponding rule.
*/
- rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
+ unsigned int *rstamps __free(kfree) =
+ kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
if (!rstamps)
return -ENOMEM;
@@ -577,10 +583,10 @@ EXPORT_SYMBOL(snd_pcm_hw_refine);
static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
- struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err;
+ struct snd_pcm_hw_params *params __free(kfree) =
+ memdup_user(_params, sizeof(*params));
- params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
@@ -612,13 +618,32 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
return usecs;
}
-static void snd_pcm_set_state(struct snd_pcm_substream *substream,
- snd_pcm_state_t state)
+/**
+ * snd_pcm_set_state - Set the PCM runtime state with stream lock
+ * @substream: PCM substream
+ * @state: state to set
+ */
+void snd_pcm_set_state(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
{
guard(pcm_stream_lock_irq)(substream);
if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED)
__snd_pcm_set_state(substream->runtime, state);
}
+EXPORT_SYMBOL_GPL(snd_pcm_set_state);
+
+/**
+ * snd_pcm_get_state - Read the PCM runtime state with stream lock
+ * @substream: PCM substream
+ *
+ * Return: the current PCM state
+ */
+snd_pcm_state_t snd_pcm_get_state(struct snd_pcm_substream *substream)
+{
+ guard(pcm_stream_lock_irqsave)(substream);
+ return substream->runtime->state;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_get_state);
static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
int event)
@@ -723,6 +748,22 @@ static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime)
atomic_inc(&runtime->buffer_accessing);
}
+/* fill the PCM buffer with the current silence format; called from pcm_oss.c */
+int snd_pcm_runtime_buffer_set_silence(struct snd_pcm_runtime *runtime)
+{
+ int err;
+
+ err = snd_pcm_buffer_access_lock(runtime);
+ if (err < 0)
+ return err;
+ if (runtime->dma_area)
+ snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
+ bytes_to_samples(runtime, runtime->dma_bytes));
+ snd_pcm_buffer_access_unlock(runtime);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_runtime_buffer_set_silence);
+
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
#define is_oss_stream(substream) ((substream)->oss.oss)
#else
@@ -867,10 +908,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
- struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err;
+ struct snd_pcm_hw_params *params __free(kfree) =
+ memdup_user(_params, sizeof(*params));
- params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
@@ -1739,6 +1780,9 @@ static int snd_pcm_suspend(struct snd_pcm_substream *substream)
* snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
* @pcm: the PCM instance
*
+ * Takes and releases pcm->open_mutex to serialize against
+ * concurrent open/close while walking the substreams.
+ *
* After this call, all streams are changed to SUSPENDED state.
*
* Return: Zero if successful (or @pcm is %NULL), or a negative error code.
@@ -1751,8 +1795,9 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
if (! pcm)
return 0;
+ guard(mutex)(&pcm->open_mutex);
+
for_each_pcm_substream(pcm, stream, substream) {
- /* FIXME: the open/close code should lock this as well */
if (!substream->runtime)
continue;
@@ -2122,6 +2167,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
for (;;) {
long tout;
struct snd_pcm_runtime *to_check;
+ unsigned int drain_rate;
+ snd_pcm_uframes_t drain_bufsz;
+ bool drain_no_period_wakeup;
+
if (signal_pending(current)) {
result = -ERESTARTSYS;
break;
@@ -2141,16 +2190,25 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
snd_pcm_group_unref(group, substream);
if (!to_check)
break; /* all drained */
+ /*
+ * Cache the runtime fields needed after unlock.
+ * A concurrent close() on the linked stream may free
+ * its runtime via snd_pcm_detach_substream() once we
+ * release the stream lock below.
+ */
+ drain_no_period_wakeup = to_check->no_period_wakeup;
+ drain_rate = to_check->rate;
+ drain_bufsz = to_check->buffer_size;
init_waitqueue_entry(&wait, current);
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&to_check->sleep, &wait);
snd_pcm_stream_unlock_irq(substream);
- if (runtime->no_period_wakeup)
+ if (drain_no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
else {
tout = 100;
- if (runtime->rate) {
- long t = runtime->buffer_size * 1100 / runtime->rate;
+ if (drain_rate) {
+ long t = drain_bufsz * 1100 / drain_rate;
tout = max(t, tout);
}
tout = msecs_to_jiffies(tout);
@@ -2245,7 +2303,6 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
- struct snd_pcm_group *group __free(kfree) = NULL;
struct snd_pcm_group *target_group;
bool nonatomic = substream->pcm->nonatomic;
CLASS(fd, f)(fd);
@@ -2261,7 +2318,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
if (substream == substream1)
return -EINVAL;
- group = kzalloc(sizeof(*group), GFP_KERNEL);
+ struct snd_pcm_group *group __free(kfree) =
+ kzalloc(sizeof(*group), GFP_KERNEL);
if (!group)
return -ENOMEM;
snd_pcm_group_init(group);
@@ -2790,7 +2848,7 @@ static int snd_pcm_open_file(struct file *file,
if (err < 0)
return err;
- pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
+ pcm_file = kzalloc_obj(*pcm_file);
if (pcm_file == NULL) {
snd_pcm_release_substream(substream);
return -ENOMEM;
@@ -3040,49 +3098,87 @@ static inline int snd_pcm_hwsync(struct snd_pcm_substream *substream)
return snd_pcm_delay(substream, NULL);
}
+#define snd_pcm_sync_ptr_get_user(__f, __c, __ptr) ({ \
+ __label__ failed, failed_begin; \
+ int __err = -EFAULT; \
+ typeof(*(__ptr)) __user *__src = (__ptr); \
+ \
+ if (!user_read_access_begin(__src, sizeof(*__src))) \
+ goto failed_begin; \
+ unsafe_get_user(__f, &__src->flags, failed); \
+ unsafe_get_user(__c.appl_ptr, &__src->c.control.appl_ptr, failed); \
+ unsafe_get_user(__c.avail_min, &__src->c.control.avail_min, failed); \
+ __err = 0; \
+failed: \
+ user_read_access_end(); \
+failed_begin: \
+ __err; \
+})
+
+#define snd_pcm_sync_ptr_put_user(__s, __c, __ptr) ({ \
+ __label__ failed, failed_begin; \
+ int __err = -EFAULT; \
+ typeof(*(__ptr)) __user *__src = (__ptr); \
+ \
+ if (!user_write_access_begin(__src, sizeof(*__src))) \
+ goto failed_begin; \
+ unsafe_put_user(__s.state, &__src->s.status.state, failed); \
+ unsafe_put_user(__s.hw_ptr, &__src->s.status.hw_ptr, failed); \
+ unsafe_put_user(__s.tstamp.tv_sec, &__src->s.status.tstamp.tv_sec, failed); \
+ unsafe_put_user(__s.tstamp.tv_nsec, &__src->s.status.tstamp.tv_nsec, failed); \
+ unsafe_put_user(__s.suspended_state, &__src->s.status.suspended_state, failed); \
+ unsafe_put_user(__s.audio_tstamp.tv_sec, &__src->s.status.audio_tstamp.tv_sec, failed); \
+ unsafe_put_user(__s.audio_tstamp.tv_nsec, &__src->s.status.audio_tstamp.tv_nsec, failed);\
+ unsafe_put_user(__c.appl_ptr, &__src->c.control.appl_ptr, failed); \
+ unsafe_put_user(__c.avail_min, &__src->c.control.avail_min, failed); \
+ __err = 0; \
+failed: \
+ user_write_access_end(); \
+failed_begin: \
+ __err; \
+})
+
static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
struct snd_pcm_sync_ptr __user *_sync_ptr)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_pcm_sync_ptr sync_ptr;
volatile struct snd_pcm_mmap_status *status;
volatile struct snd_pcm_mmap_control *control;
+ u32 sflags;
+ struct snd_pcm_mmap_control scontrol;
+ struct snd_pcm_mmap_status sstatus;
int err;
- memset(&sync_ptr, 0, sizeof(sync_ptr));
- if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
+ if (snd_pcm_sync_ptr_get_user(sflags, scontrol, _sync_ptr))
return -EFAULT;
- if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control)))
- return -EFAULT;
status = runtime->status;
control = runtime->control;
- if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
+ if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
err = snd_pcm_hwsync(substream);
if (err < 0)
return err;
}
scoped_guard(pcm_stream_lock_irq, substream) {
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
- err = pcm_lib_apply_appl_ptr(substream,
- sync_ptr.c.control.appl_ptr);
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) {
+ err = pcm_lib_apply_appl_ptr(substream, scontrol.appl_ptr);
if (err < 0)
return err;
} else {
- sync_ptr.c.control.appl_ptr = control->appl_ptr;
+ scontrol.appl_ptr = control->appl_ptr;
}
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
- control->avail_min = sync_ptr.c.control.avail_min;
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+ control->avail_min = scontrol.avail_min;
else
- sync_ptr.c.control.avail_min = control->avail_min;
- sync_ptr.s.status.state = status->state;
- sync_ptr.s.status.hw_ptr = status->hw_ptr;
- sync_ptr.s.status.tstamp = status->tstamp;
- sync_ptr.s.status.suspended_state = status->suspended_state;
- sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
+ scontrol.avail_min = control->avail_min;
+ sstatus.state = status->state;
+ sstatus.hw_ptr = status->hw_ptr;
+ sstatus.tstamp = status->tstamp;
+ sstatus.suspended_state = status->suspended_state;
+ sstatus.audio_tstamp = status->audio_tstamp;
}
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
- if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
+ if (snd_pcm_sync_ptr_put_user(sstatus, scontrol, _sync_ptr))
return -EFAULT;
return 0;
}
@@ -3091,11 +3187,9 @@ struct snd_pcm_mmap_status32 {
snd_pcm_state_t state;
s32 pad1;
u32 hw_ptr;
- s32 tstamp_sec;
- s32 tstamp_nsec;
+ struct __snd_timespec tstamp;
snd_pcm_state_t suspended_state;
- s32 audio_tstamp_sec;
- s32 audio_tstamp_nsec;
+ struct __snd_timespec audio_tstamp;
} __packed;
struct snd_pcm_mmap_control32 {
@@ -3119,13 +3213,23 @@ struct snd_pcm_sync_ptr32 {
static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t boundary;
+ snd_pcm_uframes_t border;
+ int order;
if (! runtime->buffer_size)
return 0;
- boundary = runtime->buffer_size;
- while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
- boundary *= 2;
- return boundary;
+
+ border = 0x7fffffffUL - runtime->buffer_size;
+ if (runtime->buffer_size > border)
+ return runtime->buffer_size;
+
+ order = __fls(border) - __fls(runtime->buffer_size);
+ boundary = runtime->buffer_size << order;
+
+ if (boundary <= border)
+ return boundary;
+ else
+ return boundary / 2;
}
static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
@@ -3143,9 +3247,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
if (snd_BUG_ON(!runtime))
return -EINVAL;
- if (get_user(sflags, &src->flags) ||
- get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
- get_user(scontrol.avail_min, &src->c.control.avail_min))
+ if (snd_pcm_sync_ptr_get_user(sflags, scontrol, src))
return -EFAULT;
if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
err = snd_pcm_hwsync(substream);
@@ -3178,15 +3280,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
}
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
- if (put_user(sstatus.state, &src->s.status.state) ||
- put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
- put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
- put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
- put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
- put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
- put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
- put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
- put_user(scontrol.avail_min, &src->c.control.avail_min))
+ if (snd_pcm_sync_ptr_put_user(sstatus, scontrol, src))
return -EFAULT;
return 0;
@@ -3519,7 +3613,6 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
- void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(to);
@@ -3538,7 +3631,9 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
if (!frame_aligned(runtime, iov->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, iov->iov_len);
- bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
+
+ void __user **bufs __free(kfree) =
+ kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < to->nr_segs; ++i) {
@@ -3558,7 +3653,6 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
- void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(from);
@@ -3576,7 +3670,9 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
!frame_aligned(runtime, iov->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, iov->iov_len);
- bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
+
+ void __user **bufs __free(kfree) =
+ kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < from->nr_segs; ++i) {
@@ -4048,15 +4144,15 @@ static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *opara
static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams)
{
- struct snd_pcm_hw_params *params __free(kfree) = NULL;
- struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
+ struct snd_pcm_hw_params *params __free(kfree) =
+ kmalloc_obj(*params);
if (!params)
return -ENOMEM;
- oparams = memdup_user(_oparams, sizeof(*oparams));
+ struct snd_pcm_hw_params_old *oparams __free(kfree) =
+ memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams))
return PTR_ERR(oparams);
snd_pcm_hw_convert_from_old_params(params, oparams);
@@ -4077,15 +4173,15 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams)
{
- struct snd_pcm_hw_params *params __free(kfree) = NULL;
- struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
+ struct snd_pcm_hw_params *params __free(kfree) =
+ kmalloc_obj(*params);
if (!params)
return -ENOMEM;
- oparams = memdup_user(_oparams, sizeof(*oparams));
+ struct snd_pcm_hw_params_old *oparams __free(kfree) =
+ memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams))
return PTR_ERR(oparams);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 70a958ac1112..3b1034a44938 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -159,7 +159,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
{
struct snd_rawmidi_runtime *runtime;
- runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+ runtime = kzalloc_obj(*runtime);
if (!runtime)
return -ENOMEM;
runtime->substream = substream;
@@ -472,7 +472,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
fflags = snd_rawmidi_file_flags(file);
if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */
fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
- rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
+ rawmidi_file = kmalloc_obj(*rawmidi_file);
if (rawmidi_file == NULL) {
err = -ENOMEM;
goto __error;
@@ -631,9 +631,9 @@ static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
info->flags = rmidi->info_flags;
if (substream->inactive)
info->flags |= SNDRV_RAWMIDI_INFO_STREAM_INACTIVE;
- strcpy(info->id, rmidi->id);
- strcpy(info->name, rmidi->name);
- strcpy(info->subname, substream->name);
+ strscpy(info->id, rmidi->id);
+ strscpy(info->name, rmidi->name);
+ strscpy(info->subname, substream->name);
info->subdevices_count = substream->pstr->substream_count;
info->subdevices_avail = (substream->pstr->substream_count -
substream->pstr->substream_opened);
@@ -1803,7 +1803,7 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
int idx;
for (idx = 0; idx < count; idx++) {
- substream = kzalloc(sizeof(*substream), GFP_KERNEL);
+ substream = kzalloc_obj(*substream);
if (!substream)
return -ENOMEM;
substream->stream = direction;
@@ -1891,7 +1891,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
if (rrawmidi)
*rrawmidi = NULL;
- rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
+ rmidi = kzalloc_obj(*rmidi);
if (!rmidi)
return -ENOMEM;
err = snd_rawmidi_init(rmidi, card, id, device,
@@ -2106,13 +2106,11 @@ EXPORT_SYMBOL(snd_rawmidi_set_ops);
static int __init alsa_rawmidi_init(void)
{
-
snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);
snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);
#ifdef CONFIG_SND_OSSEMUL
- { int i;
/* check device map table */
- for (i = 0; i < SNDRV_CARDS; i++) {
+ for (int i = 0; i < SNDRV_CARDS; i++) {
if (midi_map[i] < 0 || midi_map[i] >= SNDRV_RAWMIDI_DEVICES) {
pr_err("ALSA: rawmidi: invalid midi_map[%d] = %d\n",
i, midi_map[i]);
@@ -2124,7 +2122,6 @@ static int __init alsa_rawmidi_init(void)
amidi_map[i] = 1;
}
}
- }
#endif /* CONFIG_SND_OSSEMUL */
return 0;
}
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 77c1214acd90..021cd70f90db 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -54,10 +54,10 @@ static __poll_t odev_poll(struct file *file, poll_table * wait);
*/
static struct snd_seq_driver seq_oss_synth_driver = {
+ .probe = snd_seq_oss_synth_probe,
+ .remove = snd_seq_oss_synth_remove,
.driver = {
.name = KBUILD_MODNAME,
- .probe = snd_seq_oss_synth_probe,
- .remove = snd_seq_oss_synth_remove,
},
.id = SNDRV_SEQ_DEV_ID_OSS,
.argsize = sizeof(struct snd_seq_oss_reg),
@@ -117,18 +117,15 @@ static DEFINE_MUTEX(register_mutex);
static int
odev_open(struct inode *inode, struct file *file)
{
- int level, rc;
+ int level;
if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC)
level = SNDRV_SEQ_OSS_MODE_MUSIC;
else
level = SNDRV_SEQ_OSS_MODE_SYNTH;
- mutex_lock(&register_mutex);
- rc = snd_seq_oss_open(file, level);
- mutex_unlock(&register_mutex);
-
- return rc;
+ guard(mutex)(&register_mutex);
+ return snd_seq_oss_open(file, level);
}
static int
@@ -140,10 +137,8 @@ odev_release(struct inode *inode, struct file *file)
if (!dp)
return 0;
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
snd_seq_oss_release(dp);
- mutex_unlock(&register_mutex);
-
return 0;
}
@@ -229,13 +224,12 @@ register_device(void)
{
int rc;
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
NULL, 0,
&seq_oss_f_ops, NULL);
if (rc < 0) {
pr_err("ALSA: seq_oss: can't register device seq\n");
- mutex_unlock(&register_mutex);
return rc;
}
rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
@@ -244,22 +238,19 @@ register_device(void)
if (rc < 0) {
pr_err("ALSA: seq_oss: can't register device music\n");
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
- mutex_unlock(&register_mutex);
return rc;
}
- mutex_unlock(&register_mutex);
return 0;
}
static void
unregister_device(void)
{
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
pr_err("ALSA: seq_oss: error unregister device music\n");
if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
pr_err("ALSA: seq_oss: error unregister device seq\n");
- mutex_unlock(&register_mutex);
}
/*
@@ -273,12 +264,11 @@ static struct snd_info_entry *info_entry;
static void
info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
{
- mutex_lock(&register_mutex);
+ guard(mutex)(&register_mutex);
snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
snd_seq_oss_system_info_read(buf);
snd_seq_oss_synth_info_read(buf);
snd_seq_oss_midi_info_read(buf);
- mutex_unlock(&register_mutex);
}
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h
index 6163a00bc8de..935cf3df0b30 100644
--- a/sound/core/seq/oss/seq_oss_device.h
+++ b/sound/core/seq/oss/seq_oss_device.h
@@ -137,12 +137,7 @@ snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int a
static inline int
snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg)
{
- int err;
-
- snd_seq_client_ioctl_lock(dp->cseq);
- err = snd_seq_kernel_client_ctl(dp->cseq, type, arg);
- snd_seq_client_ioctl_unlock(dp->cseq);
- return err;
+ return snd_seq_kernel_client_ioctl(dp->cseq, type, arg);
}
/* fill the addresses in header */
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index e6d7d83ed0e7..d3e6a8a8d823 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -63,10 +63,10 @@ int __init
snd_seq_oss_create_client(void)
{
int rc;
- struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback port_callback;
+ struct snd_seq_port_info *port __free(kfree) =
+ kzalloc_obj(*port);
- port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
@@ -79,7 +79,7 @@ snd_seq_oss_create_client(void)
system_client = rc;
/* create announcement receiver port */
- strcpy(port->name, "Receiver");
+ strscpy(port->name, "Receiver");
port->addr.client = system_client;
port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
port->type = 0;
@@ -168,7 +168,7 @@ snd_seq_oss_open(struct file *file, int level)
int i, rc;
struct seq_oss_devinfo *dp;
- dp = kzalloc(sizeof(*dp), GFP_KERNEL);
+ dp = kzalloc_obj(*dp);
if (!dp)
return -ENOMEM;
@@ -347,7 +347,7 @@ alloc_seq_queue(struct seq_oss_devinfo *dp)
memset(&qinfo, 0, sizeof(qinfo));
qinfo.owner = system_client;
qinfo.locked = 1;
- strcpy(qinfo.name, "OSS Sequencer Emulation");
+ strscpy(qinfo.name, "OSS Sequencer Emulation");
rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo);
if (rc < 0)
return rc;
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index f8e247d9e5c9..b50a49ca42ff 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -40,6 +40,7 @@ struct seq_oss_midi {
struct mutex open_mutex;
};
+DEFINE_FREE(seq_oss_midi, struct seq_oss_midi *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock))
/*
* midi device table
@@ -64,11 +65,11 @@ static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev,
int
snd_seq_oss_midi_lookup_ports(int client)
{
- struct snd_seq_client_info *clinfo __free(kfree) = NULL;
- struct snd_seq_port_info *pinfo __free(kfree) = NULL;
+ struct snd_seq_client_info *clinfo __free(kfree) =
+ kzalloc_obj(*clinfo);
+ struct snd_seq_port_info *pinfo __free(kfree) =
+ kzalloc_obj(*pinfo);
- clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
- pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
if (!clinfo || !pinfo)
return -ENOMEM;
clinfo->client = -1;
@@ -90,13 +91,11 @@ static struct seq_oss_midi *
get_mdev(int dev)
{
struct seq_oss_midi *mdev;
- unsigned long flags;
- spin_lock_irqsave(&register_lock, flags);
+ guard(spinlock_irqsave)(&register_lock);
mdev = midi_devs[dev];
if (mdev)
snd_use_lock_use(&mdev->use_lock);
- spin_unlock_irqrestore(&register_lock, flags);
return mdev;
}
@@ -108,19 +107,16 @@ find_slot(int client, int port)
{
int i;
struct seq_oss_midi *mdev;
- unsigned long flags;
- spin_lock_irqsave(&register_lock, flags);
+ guard(spinlock_irqsave)(&register_lock);
for (i = 0; i < max_midi_devs; i++) {
mdev = midi_devs[i];
if (mdev && mdev->client == client && mdev->port == port) {
/* found! */
snd_use_lock_use(&mdev->use_lock);
- spin_unlock_irqrestore(&register_lock, flags);
return mdev;
}
}
- spin_unlock_irqrestore(&register_lock, flags);
return NULL;
}
@@ -135,7 +131,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
{
int i;
struct seq_oss_midi *mdev;
- unsigned long flags;
/* the port must include generic midi */
if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
@@ -158,7 +153,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
/*
* allocate midi info record
*/
- mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ mdev = kzalloc_obj(*mdev);
if (!mdev)
return -ENOMEM;
@@ -185,14 +180,13 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
/*
* look for en empty slot
*/
- spin_lock_irqsave(&register_lock, flags);
+ guard(spinlock_irqsave)(&register_lock);
for (i = 0; i < max_midi_devs; i++) {
if (midi_devs[i] == NULL)
break;
}
if (i >= max_midi_devs) {
if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
- spin_unlock_irqrestore(&register_lock, flags);
snd_midi_event_free(mdev->coder);
kfree(mdev);
return -ENOMEM;
@@ -201,7 +195,6 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
}
mdev->seq_device = i;
midi_devs[mdev->seq_device] = mdev;
- spin_unlock_irqrestore(&register_lock, flags);
return 0;
}
@@ -213,26 +206,24 @@ int
snd_seq_oss_midi_check_exit_port(int client, int port)
{
struct seq_oss_midi *mdev;
- unsigned long flags;
int index;
mdev = find_slot(client, port);
if (mdev) {
- spin_lock_irqsave(&register_lock, flags);
- midi_devs[mdev->seq_device] = NULL;
- spin_unlock_irqrestore(&register_lock, flags);
+ scoped_guard(spinlock_irqsave, &register_lock) {
+ midi_devs[mdev->seq_device] = NULL;
+ }
snd_use_lock_free(&mdev->use_lock);
snd_use_lock_sync(&mdev->use_lock);
snd_midi_event_free(mdev->coder);
kfree(mdev);
}
- spin_lock_irqsave(&register_lock, flags);
+ guard(spinlock_irqsave)(&register_lock);
for (index = max_midi_devs - 1; index >= 0; index--) {
if (midi_devs[index])
break;
}
max_midi_devs = index + 1;
- spin_unlock_irqrestore(&register_lock, flags);
return 0;
}
@@ -245,9 +236,8 @@ snd_seq_oss_midi_clear_all(void)
{
int i;
struct seq_oss_midi *mdev;
- unsigned long flags;
- spin_lock_irqsave(&register_lock, flags);
+ guard(spinlock_irqsave)(&register_lock);
for (i = 0; i < max_midi_devs; i++) {
mdev = midi_devs[i];
if (mdev) {
@@ -257,7 +247,6 @@ snd_seq_oss_midi_clear_all(void)
}
}
max_midi_devs = 0;
- spin_unlock_irqrestore(&register_lock, flags);
}
@@ -267,9 +256,8 @@ snd_seq_oss_midi_clear_all(void)
void
snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
{
- spin_lock_irq(&register_lock);
+ guard(spinlock_irq)(&register_lock);
dp->max_mididev = max_midi_devs;
- spin_unlock_irq(&register_lock);
}
/*
@@ -317,20 +305,17 @@ int
snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
{
int perm;
- struct seq_oss_midi *mdev;
struct snd_seq_port_subscribe subs;
- int err;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
- mutex_lock(&mdev->open_mutex);
+ guard(mutex)(&mdev->open_mutex);
/* already used? */
- if (mdev->opened && mdev->devinfo != dp) {
- err = -EBUSY;
- goto unlock;
- }
+ if (mdev->opened && mdev->devinfo != dp)
+ return -EBUSY;
perm = 0;
if (is_write_mode(fmode))
@@ -338,16 +323,12 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
if (is_read_mode(fmode))
perm |= PERM_READ;
perm &= mdev->flags;
- if (perm == 0) {
- err = -ENXIO;
- goto unlock;
- }
+ if (perm == 0)
+ return -ENXIO;
/* already opened? */
- if ((mdev->opened & perm) == perm) {
- err = 0;
- goto unlock;
- }
+ if ((mdev->opened & perm) == perm)
+ return 0;
perm &= ~mdev->opened;
@@ -370,18 +351,11 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
mdev->opened |= PERM_READ;
}
- if (! mdev->opened) {
- err = -ENXIO;
- goto unlock;
- }
+ if (!mdev->opened)
+ return -ENXIO;
mdev->devinfo = dp;
- err = 0;
-
- unlock:
- mutex_unlock(&mdev->open_mutex);
- snd_use_lock_free(&mdev->use_lock);
- return err;
+ return 0;
}
/*
@@ -390,15 +364,15 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
int
snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{
- struct seq_oss_midi *mdev;
struct snd_seq_port_subscribe subs;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
- mutex_lock(&mdev->open_mutex);
+ guard(mutex)(&mdev->open_mutex);
if (!mdev->opened || mdev->devinfo != dp)
- goto unlock;
+ return 0;
memset(&subs, 0, sizeof(subs));
if (mdev->opened & PERM_WRITE) {
@@ -416,10 +390,6 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
mdev->opened = 0;
mdev->devinfo = NULL;
-
- unlock:
- mutex_unlock(&mdev->open_mutex);
- snd_use_lock_free(&mdev->use_lock);
return 0;
}
@@ -429,10 +399,10 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
int
snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
{
- struct seq_oss_midi *mdev;
int mode;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return 0;
@@ -442,7 +412,6 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
if (mdev->opened & PERM_READ)
mode |= SNDRV_SEQ_OSS_FILE_READ;
- snd_use_lock_free(&mdev->use_lock);
return mode;
}
@@ -453,15 +422,13 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
void
snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{
- struct seq_oss_midi *mdev;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return;
- if (! mdev->opened) {
- snd_use_lock_free(&mdev->use_lock);
+ if (!mdev->opened)
return;
- }
if (mdev->opened & PERM_WRITE) {
struct snd_seq_event ev;
@@ -492,7 +459,6 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
}
}
// snd_seq_oss_midi_close(dp, dev);
- snd_use_lock_free(&mdev->use_lock);
}
@@ -502,14 +468,13 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
void
snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
{
- struct seq_oss_midi *mdev;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return;
addr->client = mdev->client;
addr->port = mdev->port;
- snd_use_lock_free(&mdev->use_lock);
}
@@ -520,26 +485,20 @@ int
snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
{
struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
- struct seq_oss_midi *mdev;
- int rc;
if (dp->readq == NULL)
return 0;
- mdev = find_slot(ev->source.client, ev->source.port);
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ find_slot(ev->source.client, ev->source.port);
if (!mdev)
return 0;
- if (! (mdev->opened & PERM_READ)) {
- snd_use_lock_free(&mdev->use_lock);
+ if (!(mdev->opened & PERM_READ))
return 0;
- }
if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
- rc = send_synth_event(dp, ev, mdev->seq_device);
+ return send_synth_event(dp, ev, mdev->seq_device);
else
- rc = send_midi_event(dp, ev, mdev);
-
- snd_use_lock_free(&mdev->use_lock);
- return rc;
+ return send_midi_event(dp, ev, mdev);
}
/*
@@ -636,17 +595,15 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq
int
snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
{
- struct seq_oss_midi *mdev;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return -ENODEV;
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;
}
- snd_use_lock_free(&mdev->use_lock);
return -EINVAL;
}
@@ -656,16 +613,15 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru
int
snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
{
- struct seq_oss_midi *mdev;
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mididev(dp, dev);
- mdev = get_mididev(dp, dev);
if (!mdev)
return -ENXIO;
inf->device = dev;
inf->dev_type = 0; /* FIXME: ?? */
inf->capabilities = 0; /* FIXME: ?? */
strscpy(inf->name, mdev->name, sizeof(inf->name));
- snd_use_lock_free(&mdev->use_lock);
return 0;
}
@@ -692,12 +648,12 @@ void
snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
{
int i;
- struct seq_oss_midi *mdev;
snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
for (i = 0; i < max_midi_devs; i++) {
snd_iprintf(buf, "\nmidi %d: ", i);
- mdev = get_mdev(i);
+ struct seq_oss_midi *mdev __free(seq_oss_midi) =
+ get_mdev(i);
if (mdev == NULL) {
snd_iprintf(buf, "*empty*\n");
continue;
@@ -707,7 +663,6 @@ snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, " capability %s / opened %s\n",
capmode_str(mdev->flags),
capmode_str(mdev->opened));
- snd_use_lock_free(&mdev->use_lock);
}
}
#endif /* CONFIG_SND_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index f0db5d3dcba4..c880d4771169 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -34,11 +34,11 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
{
struct seq_oss_readq *q;
- q = kzalloc(sizeof(*q), GFP_KERNEL);
+ q = kzalloc_obj(*q);
if (!q)
return NULL;
- q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL);
+ q->q = kzalloc_objs(union evrec, maxlen);
if (!q->q) {
kfree(q);
return NULL;
@@ -140,13 +140,9 @@ int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
int
snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
{
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
- if (q->qlen >= q->maxlen - 1) {
- spin_unlock_irqrestore(&q->lock, flags);
+ guard(spinlock_irqsave)(&q->lock);
+ if (q->qlen >= q->maxlen - 1)
return -ENOMEM;
- }
memcpy(&q->q[q->tail], ev, sizeof(*ev));
q->tail = (q->tail + 1) % q->maxlen;
@@ -155,8 +151,6 @@ snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
/* wake up sleeper */
wake_up(&q->midi_sleep);
- spin_unlock_irqrestore(&q->lock, flags);
-
return 0;
}
diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c
index 8a142fd54a19..307ef98c44c7 100644
--- a/sound/core/seq/oss/seq_oss_rw.c
+++ b/sound/core/seq/oss/seq_oss_rw.c
@@ -101,9 +101,9 @@ snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count,
break;
}
fmt = (*(unsigned short *)rec.c) & 0xffff;
- /* FIXME the return value isn't correct */
- return snd_seq_oss_synth_load_patch(dp, rec.s.dev,
- fmt, buf, 0, count);
+ err = snd_seq_oss_synth_load_patch(dp, rec.s.dev,
+ fmt, buf, 0, count);
+ return err < 0 ? err : count;
}
if (ev_is_long(&rec)) {
/* extended code */
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 9de47e098b29..c4b82e29ab05 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -44,6 +44,7 @@ struct seq_oss_synth {
snd_use_lock_t use_lock;
};
+DEFINE_FREE(seq_oss_synth, struct seq_oss_synth *, if (!IS_ERR_OR_NULL(_T)) snd_use_lock_free(&(_T)->use_lock))
/*
* device table
@@ -79,13 +80,11 @@ snd_seq_oss_synth_init(void)
* registration of the synth device
*/
int
-snd_seq_oss_synth_probe(struct device *_dev)
+snd_seq_oss_synth_probe(struct snd_seq_device *dev)
{
- struct snd_seq_device *dev = to_seq_dev(_dev);
int i;
struct seq_oss_synth *rec;
struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
- unsigned long flags;
rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (!rec)
@@ -103,23 +102,22 @@ snd_seq_oss_synth_probe(struct device *_dev)
strscpy(rec->name, dev->name, sizeof(rec->name));
/* registration */
- spin_lock_irqsave(&register_lock, flags);
- for (i = 0; i < max_synth_devs; i++) {
- if (synth_devs[i] == NULL)
- break;
- }
- if (i >= max_synth_devs) {
- if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
- spin_unlock_irqrestore(&register_lock, flags);
- pr_err("ALSA: seq_oss: no more synth slot\n");
- kfree(rec);
- return -ENOMEM;
+ scoped_guard(spinlock_irqsave, &register_lock) {
+ for (i = 0; i < max_synth_devs; i++) {
+ if (synth_devs[i] == NULL)
+ break;
+ }
+ if (i >= max_synth_devs) {
+ if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
+ pr_err("ALSA: seq_oss: no more synth slot\n");
+ kfree(rec);
+ return -ENOMEM;
+ }
+ max_synth_devs++;
}
- max_synth_devs++;
+ rec->seq_device = i;
+ synth_devs[i] = rec;
}
- rec->seq_device = i;
- synth_devs[i] = rec;
- spin_unlock_irqrestore(&register_lock, flags);
dev->driver_data = rec;
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (i < SNDRV_CARDS)
@@ -129,33 +127,30 @@ snd_seq_oss_synth_probe(struct device *_dev)
}
-int
-snd_seq_oss_synth_remove(struct device *_dev)
+void
+snd_seq_oss_synth_remove(struct snd_seq_device *dev)
{
- struct snd_seq_device *dev = to_seq_dev(_dev);
int index;
struct seq_oss_synth *rec = dev->driver_data;
- unsigned long flags;
- spin_lock_irqsave(&register_lock, flags);
- for (index = 0; index < max_synth_devs; index++) {
- if (synth_devs[index] == rec)
- break;
- }
- if (index >= max_synth_devs) {
- spin_unlock_irqrestore(&register_lock, flags);
- pr_err("ALSA: seq_oss: can't unregister synth\n");
- return -EINVAL;
- }
- synth_devs[index] = NULL;
- if (index == max_synth_devs - 1) {
- for (index--; index >= 0; index--) {
- if (synth_devs[index])
+ scoped_guard(spinlock_irqsave, &register_lock) {
+ for (index = 0; index < max_synth_devs; index++) {
+ if (synth_devs[index] == rec)
break;
}
- max_synth_devs = index + 1;
+ if (index >= max_synth_devs) {
+ pr_err("ALSA: seq_oss: can't unregister synth\n");
+ return;
+ }
+ synth_devs[index] = NULL;
+ if (index == max_synth_devs - 1) {
+ for (index--; index >= 0; index--) {
+ if (synth_devs[index])
+ break;
+ }
+ max_synth_devs = index + 1;
+ }
}
- spin_unlock_irqrestore(&register_lock, flags);
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (rec->seq_device < SNDRV_CARDS)
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
@@ -163,8 +158,6 @@ snd_seq_oss_synth_remove(struct device *_dev)
snd_use_lock_sync(&rec->use_lock);
kfree(rec);
-
- return 0;
}
@@ -174,13 +167,11 @@ static struct seq_oss_synth *
get_sdev(int dev)
{
struct seq_oss_synth *rec;
- unsigned long flags;
- spin_lock_irqsave(&register_lock, flags);
+ guard(spinlock_irqsave)(&register_lock);
rec = synth_devs[dev];
if (rec)
snd_use_lock_use(&rec->use_lock);
- spin_unlock_irqrestore(&register_lock, flags);
return rec;
}
@@ -193,20 +184,18 @@ void
snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
{
int i;
- struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
dp->max_synthdev = max_synth_devs;
dp->synth_opened = 0;
memset(dp->synths, 0, sizeof(dp->synths));
for (i = 0; i < dp->max_synthdev; i++) {
- rec = get_sdev(i);
+ struct seq_oss_synth *rec __free(seq_oss_synth) = get_sdev(i);
+
if (rec == NULL)
continue;
- if (rec->oper.open == NULL || rec->oper.close == NULL) {
- snd_use_lock_free(&rec->use_lock);
+ if (rec->oper.open == NULL || rec->oper.close == NULL)
continue;
- }
info = &dp->synths[i];
info->arg.app_index = dp->port;
info->arg.file_mode = dp->file_mode;
@@ -216,22 +205,19 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
else
info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
info->opened = 0;
- if (!try_module_get(rec->oper.owner)) {
- snd_use_lock_free(&rec->use_lock);
+ if (!try_module_get(rec->oper.owner))
continue;
- }
if (rec->oper.open(&info->arg, rec->private_data) < 0) {
module_put(rec->oper.owner);
- snd_use_lock_free(&rec->use_lock);
continue;
}
info->nr_voices = rec->nr_voices;
if (info->nr_voices > 0) {
- info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
+ info->ch = kzalloc_objs(struct seq_oss_chinfo,
+ info->nr_voices);
if (!info->ch) {
rec->oper.close(&info->arg);
module_put(rec->oper.owner);
- snd_use_lock_free(&rec->use_lock);
continue;
}
reset_channels(info);
@@ -239,7 +225,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
info->opened++;
rec->opened++;
dp->synth_opened++;
- snd_use_lock_free(&rec->use_lock);
}
}
@@ -286,7 +271,6 @@ void
snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
{
int i;
- struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
@@ -301,7 +285,9 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
midi_synth_dev.opened--;
}
} else {
- rec = get_sdev(i);
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_sdev(i);
+
if (rec == NULL)
continue;
if (rec->opened > 0) {
@@ -309,7 +295,6 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
module_put(rec->oper.owner);
rec->opened = 0;
}
- snd_use_lock_free(&rec->use_lock);
}
kfree(info->ch);
info->ch = NULL;
@@ -380,7 +365,6 @@ reset_channels(struct seq_oss_synthinfo *info)
void
snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
{
- struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
info = get_synthinfo_nospec(dp, dev);
@@ -403,7 +387,8 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
return;
}
- rec = get_sdev(dev);
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_sdev(dev);
if (rec == NULL)
return;
if (rec->oper.reset) {
@@ -416,7 +401,6 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
ev.type = SNDRV_SEQ_EVENT_RESET;
snd_seq_oss_dispatch(dp, &ev, 0, 0);
}
- snd_use_lock_free(&rec->use_lock);
}
@@ -428,9 +412,7 @@ int
snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
const char __user *buf, int p, int c)
{
- struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
- int rc;
info = get_synthinfo_nospec(dp, dev);
if (!info)
@@ -438,16 +420,16 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
if (info->is_midi)
return 0;
- rec = get_synthdev(dp, dev);
+
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_synthdev(dp, dev);
if (!rec)
return -ENXIO;
if (rec->oper.load_patch == NULL)
- rc = -ENXIO;
+ return -ENXIO;
else
- rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c);
- snd_use_lock_free(&rec->use_lock);
- return rc;
+ return rec->oper.load_patch(&info->arg, fmt, buf, p, c);
}
/*
@@ -456,13 +438,11 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
struct seq_oss_synthinfo *
snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
{
- struct seq_oss_synth *rec;
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_synthdev(dp, dev);
- rec = get_synthdev(dp, dev);
- if (rec) {
- snd_use_lock_free(&rec->use_lock);
+ if (rec)
return get_synthinfo_nospec(dp, dev);
- }
return NULL;
}
@@ -513,22 +493,20 @@ snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event
int
snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
{
- struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
- int rc;
info = get_synthinfo_nospec(dp, dev);
if (!info || info->is_midi)
return -ENXIO;
- rec = get_synthdev(dp, dev);
+
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_synthdev(dp, dev);
if (!rec)
return -ENXIO;
if (rec->oper.ioctl == NULL)
- rc = -ENXIO;
+ return -ENXIO;
else
- rc = rec->oper.ioctl(&info->arg, cmd, addr);
- snd_use_lock_free(&rec->use_lock);
- return rc;
+ return rec->oper.ioctl(&info->arg, cmd, addr);
}
@@ -555,7 +533,6 @@ snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *
int
snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
{
- struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
if (!info)
@@ -571,7 +548,9 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->device = dev;
strscpy(inf->name, minf.name, sizeof(inf->name));
} else {
- rec = get_synthdev(dp, dev);
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_synthdev(dp, dev);
+
if (!rec)
return -ENXIO;
inf->synth_type = rec->synth_type;
@@ -579,7 +558,6 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
inf->nr_voices = rec->nr_voices;
inf->device = dev;
strscpy(inf->name, rec->name, sizeof(inf->name));
- snd_use_lock_free(&rec->use_lock);
}
return 0;
}
@@ -593,12 +571,12 @@ void
snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
{
int i;
- struct seq_oss_synth *rec;
snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
for (i = 0; i < max_synth_devs; i++) {
snd_iprintf(buf, "\nsynth %d: ", i);
- rec = get_sdev(i);
+ struct seq_oss_synth *rec __free(seq_oss_synth) =
+ get_sdev(i);
if (rec == NULL) {
snd_iprintf(buf, "*empty*\n");
continue;
@@ -610,7 +588,6 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n",
str_enabled_disabled((long)rec->oper.ioctl),
str_enabled_disabled((long)rec->oper.load_patch));
- snd_use_lock_free(&rec->use_lock);
}
}
#endif /* CONFIG_SND_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_synth.h b/sound/core/seq/oss/seq_oss_synth.h
index ffc40d8a7ef1..f52283904cba 100644
--- a/sound/core/seq/oss/seq_oss_synth.h
+++ b/sound/core/seq/oss/seq_oss_synth.h
@@ -15,8 +15,8 @@
#include <sound/seq_device.h>
void snd_seq_oss_synth_init(void);
-int snd_seq_oss_synth_probe(struct device *dev);
-int snd_seq_oss_synth_remove(struct device *dev);
+int snd_seq_oss_synth_probe(struct snd_seq_device *dev);
+void snd_seq_oss_synth_remove(struct snd_seq_device *dev);
void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index f9f57232a83f..44c04795204e 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -34,7 +34,7 @@ snd_seq_oss_timer_new(struct seq_oss_devinfo *dp)
{
struct seq_oss_timer *rec;
- rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+ rec = kzalloc_obj(*rec);
if (rec == NULL)
return NULL;
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 3e3209ce53b1..09239ea4b5ea 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -27,7 +27,7 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen)
struct seq_oss_writeq *q;
struct snd_seq_client_pool pool;
- q = kzalloc(sizeof(*q), GFP_KERNEL);
+ q = kzalloc_obj(*q);
if (!q)
return NULL;
q->dp = dp;
@@ -122,13 +122,10 @@ snd_seq_oss_writeq_sync(struct seq_oss_writeq *q)
void
snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time)
{
- unsigned long flags;
-
- spin_lock_irqsave(&q->sync_lock, flags);
+ guard(spinlock_irqsave)(&q->sync_lock);
q->sync_time = time;
q->sync_event_put = 0;
wake_up(&q->sync_sleep);
- spin_unlock_irqrestore(&q->sync_lock, flags);
}
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 198c598a5393..75a7a2af9d8c 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -108,7 +108,6 @@ static struct snd_seq_client *clientptr(int clientid)
static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
{
- unsigned long flags;
struct snd_seq_client *client;
if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {
@@ -116,15 +115,13 @@ static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
clientid);
return NULL;
}
- spin_lock_irqsave(&clients_lock, flags);
- client = clientptr(clientid);
- if (client)
- goto __lock;
- if (clienttablock[clientid]) {
- spin_unlock_irqrestore(&clients_lock, flags);
- return NULL;
+ scoped_guard(spinlock_irqsave, &clients_lock) {
+ client = clientptr(clientid);
+ if (client)
+ return snd_seq_client_ref(client);
+ if (clienttablock[clientid])
+ return NULL;
}
- spin_unlock_irqrestore(&clients_lock, flags);
#ifdef CONFIG_MODULES
if (load_module) {
static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);
@@ -153,19 +150,14 @@ static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
snd_seq_device_load_drivers();
}
}
- spin_lock_irqsave(&clients_lock, flags);
- client = clientptr(clientid);
- if (client)
- goto __lock;
- spin_unlock_irqrestore(&clients_lock, flags);
+ scoped_guard(spinlock_irqsave, &clients_lock) {
+ client = clientptr(clientid);
+ if (client)
+ return snd_seq_client_ref(client);
+ }
}
#endif
return NULL;
-
- __lock:
- snd_use_lock_use(&client->use_lock);
- spin_unlock_irqrestore(&clients_lock, flags);
- return client;
}
/* get snd_seq_client object for the given id quickly */
@@ -182,41 +174,6 @@ static struct snd_seq_client *client_load_and_use_ptr(int clientid)
return client_use_ptr(clientid, IS_ENABLED(CONFIG_MODULES));
}
-/* Take refcount and perform ioctl_mutex lock on the given client;
- * used only for OSS sequencer
- * Unlock via snd_seq_client_ioctl_unlock() below
- */
-bool snd_seq_client_ioctl_lock(int clientid)
-{
- struct snd_seq_client *client;
-
- client = client_load_and_use_ptr(clientid);
- if (!client)
- return false;
- mutex_lock(&client->ioctl_mutex);
- /* The client isn't unrefed here; see snd_seq_client_ioctl_unlock() */
- return true;
-}
-EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock);
-
-/* Unlock and unref the given client; for OSS sequencer use only */
-void snd_seq_client_ioctl_unlock(int clientid)
-{
- struct snd_seq_client *client;
-
- client = snd_seq_client_use_ptr(clientid);
- if (WARN_ON(!client))
- return;
- mutex_unlock(&client->ioctl_mutex);
- /* The doubly unrefs below are intentional; the first one releases the
- * leftover from snd_seq_client_ioctl_lock() above, and the second one
- * is for releasing snd_seq_client_use_ptr() in this function
- */
- snd_seq_client_unlock(client);
- snd_seq_client_unlock(client);
-}
-EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock);
-
static void usage_alloc(struct snd_seq_usage *res, int num)
{
res->cur += num;
@@ -262,25 +219,24 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
client->ump_endpoint_port = -1;
/* find free slot in the client table */
- spin_lock_irq(&clients_lock);
- if (client_index < 0) {
- for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
- c < SNDRV_SEQ_MAX_CLIENTS;
- c++) {
- if (clienttab[c] || clienttablock[c])
- continue;
- clienttab[client->number = c] = client;
- spin_unlock_irq(&clients_lock);
- return client;
- }
- } else {
- if (clienttab[client_index] == NULL && !clienttablock[client_index]) {
- clienttab[client->number = client_index] = client;
- spin_unlock_irq(&clients_lock);
- return client;
+ scoped_guard(spinlock_irq, &clients_lock) {
+ if (client_index < 0) {
+ for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
+ c < SNDRV_SEQ_MAX_CLIENTS;
+ c++) {
+ if (clienttab[c] || clienttablock[c])
+ continue;
+ clienttab[client->number = c] = client;
+ return client;
+ }
+ } else {
+ if (clienttab[client_index] == NULL && !clienttablock[client_index]) {
+ clienttab[client->number = client_index] = client;
+ return client;
+ }
}
}
- spin_unlock_irq(&clients_lock);
+
snd_seq_pool_delete(&client->pool);
kfree(client);
return NULL; /* no free slot found or busy, return failure code */
@@ -291,41 +247,41 @@ static int seq_free_client1(struct snd_seq_client *client)
{
if (!client)
return 0;
- spin_lock_irq(&clients_lock);
- clienttablock[client->number] = 1;
- clienttab[client->number] = NULL;
- spin_unlock_irq(&clients_lock);
+ scoped_guard(spinlock_irq, &clients_lock) {
+ clienttablock[client->number] = 1;
+ clienttab[client->number] = NULL;
+ }
snd_seq_delete_all_ports(client);
snd_seq_queue_client_leave(client->number);
snd_use_lock_sync(&client->use_lock);
if (client->pool)
snd_seq_pool_delete(&client->pool);
- spin_lock_irq(&clients_lock);
- clienttablock[client->number] = 0;
- spin_unlock_irq(&clients_lock);
+ scoped_guard(spinlock_irq, &clients_lock) {
+ clienttablock[client->number] = 0;
+ }
return 0;
}
static void seq_free_client(struct snd_seq_client * client)
{
- mutex_lock(&register_mutex);
- switch (client->type) {
- case NO_CLIENT:
- pr_warn("ALSA: seq: Trying to free unused client %d\n",
- client->number);
- break;
- case USER_CLIENT:
- case KERNEL_CLIENT:
- seq_free_client1(client);
- usage_free(&client_usage, 1);
- break;
+ scoped_guard(mutex, &register_mutex) {
+ switch (client->type) {
+ case NO_CLIENT:
+ pr_warn("ALSA: seq: Trying to free unused client %d\n",
+ client->number);
+ break;
+ case USER_CLIENT:
+ case KERNEL_CLIENT:
+ seq_free_client1(client);
+ usage_free(&client_usage, 1);
+ break;
- default:
- pr_err("ALSA: seq: Trying to free client %d with undefined type = %d\n",
- client->number, client->type);
+ default:
+ pr_err("ALSA: seq: Trying to free client %d with undefined type = %d\n",
+ client->number, client->type);
+ }
}
- mutex_unlock(&register_mutex);
snd_seq_system_client_ev_client_exit(client->number);
}
@@ -346,37 +302,34 @@ static int snd_seq_open(struct inode *inode, struct file *file)
if (err < 0)
return err;
- mutex_lock(&register_mutex);
- client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
- if (!client) {
- mutex_unlock(&register_mutex);
- return -ENOMEM; /* failure code */
- }
-
- mode = snd_seq_file_flags(file);
- if (mode & SNDRV_SEQ_LFLG_INPUT)
- client->accept_input = 1;
- if (mode & SNDRV_SEQ_LFLG_OUTPUT)
- client->accept_output = 1;
-
- user = &client->data.user;
- user->fifo = NULL;
- user->fifo_pool_size = 0;
-
- if (mode & SNDRV_SEQ_LFLG_INPUT) {
- user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS;
- user->fifo = snd_seq_fifo_new(user->fifo_pool_size);
- if (user->fifo == NULL) {
- seq_free_client1(client);
- kfree(client);
- mutex_unlock(&register_mutex);
- return -ENOMEM;
+ scoped_guard(mutex, &register_mutex) {
+ client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
+ if (!client)
+ return -ENOMEM; /* failure code */
+
+ mode = snd_seq_file_flags(file);
+ if (mode & SNDRV_SEQ_LFLG_INPUT)
+ client->accept_input = 1;
+ if (mode & SNDRV_SEQ_LFLG_OUTPUT)
+ client->accept_output = 1;
+
+ user = &client->data.user;
+ user->fifo = NULL;
+ user->fifo_pool_size = 0;
+
+ if (mode & SNDRV_SEQ_LFLG_INPUT) {
+ user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS;
+ user->fifo = snd_seq_fifo_new(user->fifo_pool_size);
+ if (user->fifo == NULL) {
+ seq_free_client1(client);
+ kfree(client);
+ return -ENOMEM;
+ }
}
- }
- usage_alloc(&client_usage, 1);
- client->type = USER_CLIENT;
- mutex_unlock(&register_mutex);
+ usage_alloc(&client_usage, 1);
+ client->type = USER_CLIENT;
+ }
c = client->number;
file->private_data = client;
@@ -463,7 +416,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
cell = NULL;
err = 0;
- snd_seq_fifo_lock(fifo);
+ guard(snd_seq_fifo)(fifo);
if (IS_ENABLED(CONFIG_SND_SEQ_UMP) && client->midi_version > 0)
aligned_size = sizeof(struct snd_seq_ump_event);
@@ -521,7 +474,6 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
if (err == -EAGAIN && result > 0)
err = 0;
}
- snd_seq_fifo_unlock(fifo);
return (err < 0) ? err : result;
}
@@ -542,24 +494,21 @@ static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)
*/
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
{
- struct snd_seq_client *dest;
+ struct snd_seq_client *dest __free(snd_seq_client) =
+ snd_seq_client_use_ptr(event->dest.client);
- dest = snd_seq_client_use_ptr(event->dest.client);
if (dest == NULL)
return NULL;
if (! dest->accept_input)
- goto __not_avail;
+ return NULL;
if (snd_seq_ev_is_ump(event))
- return dest; /* ok - no filter checks */
+ return no_free_ptr(dest); /* ok - no filter checks */
if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
! test_bit(event->type, dest->event_filter))
- goto __not_avail;
+ return NULL;
- return dest; /* ok - accessible */
-__not_avail:
- snd_seq_client_unlock(dest);
- return NULL;
+ return no_free_ptr(dest); /* ok - accessible */
}
@@ -616,9 +565,9 @@ static int bounce_error_event(struct snd_seq_client *client,
static int update_timestamp_of_queue(struct snd_seq_event *event,
int queue, int real_time)
{
- struct snd_seq_queue *q;
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(queue);
- q = queueptr(queue);
if (! q)
return 0;
event->queue = queue;
@@ -630,7 +579,6 @@ static int update_timestamp_of_queue(struct snd_seq_event *event,
event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;
}
- queuefree(q);
return 1;
}
@@ -656,73 +604,63 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
return 0;
}
-/*
- * deliver an event to the specified destination.
- * if filter is non-zero, client filter bitmap is tested.
- *
- * RETURN VALUE: 0 : if succeeded
- * <0 : error
- */
-static int snd_seq_deliver_single_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int atomic, int hop)
+/* deliver a single event; called from snd_seq_deliver_single_event() */
+static int _snd_seq_deliver_single_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
+ int atomic, int hop)
{
- struct snd_seq_client *dest = NULL;
- struct snd_seq_client_port *dest_port = NULL;
- int result = -ENOENT;
- int direct;
-
- direct = snd_seq_ev_is_direct(event);
-
- dest = get_event_dest_client(event);
+ struct snd_seq_client *dest __free(snd_seq_client) =
+ get_event_dest_client(event);
if (dest == NULL)
- goto __skip;
- dest_port = snd_seq_port_use_ptr(dest, event->dest.port);
+ return -ENOENT;
+
+ struct snd_seq_client_port *dest_port __free(snd_seq_port) =
+ snd_seq_port_use_ptr(dest, event->dest.port);
if (dest_port == NULL)
- goto __skip;
+ return -ENOENT;
/* check permission */
- if (! check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE)) {
- result = -EPERM;
- goto __skip;
- }
-
+ if (!check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE))
+ return -EPERM;
+
if (dest_port->timestamping)
update_timestamp_of_queue(event, dest_port->time_queue,
dest_port->time_real);
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
if (snd_seq_ev_is_ump(event)) {
- if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) {
- result = snd_seq_deliver_from_ump(client, dest, dest_port,
- event, atomic, hop);
- goto __skip;
- } else if (dest->type == USER_CLIENT &&
- !snd_seq_client_is_ump(dest)) {
- result = 0; // drop the event
- goto __skip;
- }
- } else if (snd_seq_client_is_ump(dest)) {
- if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) {
- result = snd_seq_deliver_to_ump(client, dest, dest_port,
+ if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT))
+ return snd_seq_deliver_from_ump(client, dest, dest_port,
event, atomic, hop);
- goto __skip;
- }
+ else if (dest->type == USER_CLIENT &&
+ !snd_seq_client_is_ump(dest))
+ return 0; // drop the event
+ } else if (snd_seq_client_is_ump(dest)) {
+ if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT))
+ return snd_seq_deliver_to_ump(client, dest, dest_port,
+ event, atomic, hop);
}
#endif /* CONFIG_SND_SEQ_UMP */
- result = __snd_seq_deliver_single_event(dest, dest_port, event,
- atomic, hop);
+ return __snd_seq_deliver_single_event(dest, dest_port, event,
+ atomic, hop);
+}
- __skip:
- if (dest_port)
- snd_seq_port_unlock(dest_port);
- if (dest)
- snd_seq_client_unlock(dest);
+/*
+ * deliver an event to the specified destination.
+ * if filter is non-zero, client filter bitmap is tested.
+ *
+ * RETURN VALUE: 0 : if succeeded
+ * <0 : error
+ */
+static int snd_seq_deliver_single_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
+ int atomic, int hop)
+{
+ int result = _snd_seq_deliver_single_event(client, event, atomic, hop);
- if (result < 0 && !direct) {
- result = bounce_error_event(client, event, result, atomic, hop);
- }
+ if (result < 0 && !snd_seq_ev_is_direct(event))
+ return bounce_error_event(client, event, result, atomic, hop);
return result;
}
@@ -732,8 +670,7 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
*/
static int __deliver_to_subscribers(struct snd_seq_client *client,
struct snd_seq_event *event,
- struct snd_seq_client_port *src_port,
- int atomic, int hop)
+ int port, int atomic, int hop)
{
struct snd_seq_subscribers *subs;
int err, result = 0, num_ev = 0;
@@ -741,6 +678,14 @@ static int __deliver_to_subscribers(struct snd_seq_client *client,
size_t saved_size;
struct snd_seq_port_subs_info *grp;
+ if (port < 0)
+ return 0;
+
+ struct snd_seq_client_port *src_port __free(snd_seq_port) =
+ snd_seq_port_use_ptr(client, port);
+ if (!src_port)
+ return 0;
+
/* save original event record */
saved_size = snd_seq_event_packet_size(event);
memcpy(&event_saved, event, saved_size);
@@ -783,25 +728,32 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
struct snd_seq_event *event,
int atomic, int hop)
{
- struct snd_seq_client_port *src_port;
- int ret = 0, ret2;
-
- src_port = snd_seq_port_use_ptr(client, event->source.port);
- if (src_port) {
- ret = __deliver_to_subscribers(client, event, src_port, atomic, hop);
- snd_seq_port_unlock(src_port);
- }
-
- if (client->ump_endpoint_port < 0 ||
- event->source.port == client->ump_endpoint_port)
- return ret;
+ int ret;
+#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+ int ret2;
+#endif
- src_port = snd_seq_port_use_ptr(client, client->ump_endpoint_port);
- if (!src_port)
+ ret = __deliver_to_subscribers(client, event,
+ event->source.port, atomic, hop);
+#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+ if (!snd_seq_client_is_ump(client) || client->ump_endpoint_port < 0)
return ret;
- ret2 = __deliver_to_subscribers(client, event, src_port, atomic, hop);
- snd_seq_port_unlock(src_port);
- return ret2 < 0 ? ret2 : ret;
+ /* If it's an event from EP port (and with a UMP group),
+ * deliver to subscribers of the corresponding UMP group port, too.
+ * Or, if it's from non-EP port, deliver to subscribers of EP port, too.
+ */
+ if (event->source.port == client->ump_endpoint_port)
+ ret2 = __deliver_to_subscribers(client, event,
+ snd_seq_ump_group_port(event),
+ atomic, hop);
+ else
+ ret2 = __deliver_to_subscribers(client, event,
+ client->ump_endpoint_port,
+ atomic, hop);
+ if (ret2 < 0)
+ return ret2;
+#endif
+ return ret;
}
/* deliver an event to the destination port(s).
@@ -850,13 +802,13 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e
*/
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
- struct snd_seq_client *client;
int result;
if (snd_BUG_ON(!cell))
return -EINVAL;
- client = snd_seq_client_use_ptr(cell->event.source.client);
+ struct snd_seq_client *client __free(snd_seq_client) =
+ snd_seq_client_use_ptr(cell->event.source.client);
if (client == NULL) {
snd_seq_cell_free(cell); /* release this cell */
return -EINVAL;
@@ -912,7 +864,6 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
snd_seq_cell_free(cell);
}
- snd_seq_client_unlock(client);
return result;
}
@@ -936,10 +887,10 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
event->queue = SNDRV_SEQ_QUEUE_DIRECT;
} else if (event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) {
/* check presence of source port */
- struct snd_seq_client_port *src_port = snd_seq_port_use_ptr(client, event->source.port);
- if (src_port == NULL)
+ struct snd_seq_client_port *src_port __free(snd_seq_port) =
+ snd_seq_port_use_ptr(client, event->source.port);
+ if (!src_port)
return -EINVAL;
- snd_seq_port_unlock(src_port);
}
/* direct event processing without enqueued */
@@ -1204,34 +1155,24 @@ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)
static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
{
struct snd_seq_running_info *info = arg;
- struct snd_seq_client *cptr;
- int err = 0;
-
/* requested client number */
- cptr = client_load_and_use_ptr(info->client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(info->client);
+
if (cptr == NULL)
return -ENOENT; /* don't change !!! */
#ifdef SNDRV_BIG_ENDIAN
- if (!info->big_endian) {
- err = -EINVAL;
- goto __err;
- }
+ if (!info->big_endian)
+ return -EINVAL;
#else
- if (info->big_endian) {
- err = -EINVAL;
- goto __err;
- }
-
+ if (info->big_endian)
+ return -EINVAL;
#endif
- if (info->cpu_mode > sizeof(long)) {
- err = -EINVAL;
- goto __err;
- }
+ if (info->cpu_mode > sizeof(long))
+ return -EINVAL;
cptr->convert32 = (info->cpu_mode < sizeof(long));
- __err:
- snd_seq_client_unlock(cptr);
- return err;
+ return 0;
}
/* CLIENT_INFO ioctl() */
@@ -1242,7 +1183,7 @@ static void get_client_info(struct snd_seq_client *cptr,
/* fill the info fields */
info->type = cptr->type;
- strcpy(info->name, cptr->name);
+ strscpy(info->name, cptr->name);
info->filter = cptr->filter;
info->event_lost = cptr->event_lost;
memcpy(info->event_filter, cptr->event_filter, 32);
@@ -1267,16 +1208,14 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_client_info *client_info = arg;
- struct snd_seq_client *cptr;
-
/* requested client number */
- cptr = client_load_and_use_ptr(client_info->client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(client_info->client);
+
if (cptr == NULL)
return -ENOENT; /* don't change !!! */
get_client_info(cptr, client_info);
- snd_seq_client_unlock(cptr);
-
return 0;
}
@@ -1406,24 +1345,19 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg)
static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
{
struct snd_seq_port_info *info = arg;
- struct snd_seq_client *cptr;
- struct snd_seq_client_port *port;
- cptr = client_load_and_use_ptr(info->addr.client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(info->addr.client);
if (cptr == NULL)
return -ENXIO;
- port = snd_seq_port_use_ptr(cptr, info->addr.port);
- if (port == NULL) {
- snd_seq_client_unlock(cptr);
+ struct snd_seq_client_port *port __free(snd_seq_port) =
+ snd_seq_port_use_ptr(cptr, info->addr.port);
+ if (port == NULL)
return -ENOENT; /* don't change */
- }
/* get port info */
snd_seq_get_port_info(port, info);
- snd_seq_port_unlock(port);
- snd_seq_client_unlock(cptr);
-
return 0;
}
@@ -1434,14 +1368,14 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg)
{
struct snd_seq_port_info *info = arg;
- struct snd_seq_client_port *port;
if (info->addr.client != client->number) /* only set our own ports ! */
return -EPERM;
- port = snd_seq_port_use_ptr(client, info->addr.port);
+
+ struct snd_seq_client_port *port __free(snd_seq_port) =
+ snd_seq_port_use_ptr(client, info->addr.port);
if (port) {
snd_seq_set_port_info(port, info);
- snd_seq_port_unlock(port);
/* notify the change */
snd_seq_system_client_ev_port_change(info->addr.client,
info->addr.port);
@@ -1512,41 +1446,34 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_subscribe *subs = arg;
- int result = -EINVAL;
- struct snd_seq_client *receiver = NULL, *sender = NULL;
- struct snd_seq_client_port *sport = NULL, *dport = NULL;
+ int result;
- receiver = client_load_and_use_ptr(subs->dest.client);
+ struct snd_seq_client *receiver __free(snd_seq_client) =
+ client_load_and_use_ptr(subs->dest.client);
if (!receiver)
- goto __end;
- sender = client_load_and_use_ptr(subs->sender.client);
+ return -EINVAL;
+ struct snd_seq_client *sender __free(snd_seq_client) =
+ client_load_and_use_ptr(subs->sender.client);
if (!sender)
- goto __end;
- sport = snd_seq_port_use_ptr(sender, subs->sender.port);
+ return -EINVAL;
+ struct snd_seq_client_port *sport __free(snd_seq_port) =
+ snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
- goto __end;
- dport = snd_seq_port_use_ptr(receiver, subs->dest.port);
+ return -EINVAL;
+ struct snd_seq_client_port *dport __free(snd_seq_port) =
+ snd_seq_port_use_ptr(receiver, subs->dest.port);
if (!dport)
- goto __end;
+ return -EINVAL;
result = check_subscription_permission(client, sport, dport, subs);
if (result < 0)
- goto __end;
+ return result;
/* connect them */
result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs);
if (! result) /* broadcast announce */
snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
- __end:
- if (sport)
- snd_seq_port_unlock(sport);
- if (dport)
- snd_seq_port_unlock(dport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (receiver)
- snd_seq_client_unlock(receiver);
return result;
}
@@ -1558,40 +1485,33 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_subscribe *subs = arg;
- int result = -ENXIO;
- struct snd_seq_client *receiver = NULL, *sender = NULL;
- struct snd_seq_client_port *sport = NULL, *dport = NULL;
+ int result;
- receiver = snd_seq_client_use_ptr(subs->dest.client);
+ struct snd_seq_client *receiver __free(snd_seq_client) =
+ snd_seq_client_use_ptr(subs->dest.client);
if (!receiver)
- goto __end;
- sender = snd_seq_client_use_ptr(subs->sender.client);
+ return -ENXIO;
+ struct snd_seq_client *sender __free(snd_seq_client) =
+ snd_seq_client_use_ptr(subs->sender.client);
if (!sender)
- goto __end;
- sport = snd_seq_port_use_ptr(sender, subs->sender.port);
+ return -ENXIO;
+ struct snd_seq_client_port *sport __free(snd_seq_port) =
+ snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
- goto __end;
- dport = snd_seq_port_use_ptr(receiver, subs->dest.port);
+ return -ENXIO;
+ struct snd_seq_client_port *dport __free(snd_seq_port) =
+ snd_seq_port_use_ptr(receiver, subs->dest.port);
if (!dport)
- goto __end;
+ return -ENXIO;
result = check_subscription_permission(client, sport, dport, subs);
if (result < 0)
- goto __end;
+ return result;
result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs);
if (! result) /* broadcast announce */
snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
- __end:
- if (sport)
- snd_seq_port_unlock(sport);
- if (dport)
- snd_seq_port_unlock(dport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (receiver)
- snd_seq_client_unlock(receiver);
return result;
}
@@ -1600,9 +1520,9 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
{
struct snd_seq_queue_info *info = arg;
- struct snd_seq_queue *q;
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ snd_seq_queue_alloc(client->number, info->locked, info->flags);
- q = snd_seq_queue_alloc(client->number, info->locked, info->flags);
if (IS_ERR(q))
return PTR_ERR(q);
@@ -1614,7 +1534,6 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
if (!info->name[0])
snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue);
strscpy(q->name, info->name, sizeof(q->name));
- snd_use_lock_free(&q->use_lock);
return 0;
}
@@ -1632,9 +1551,9 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_info *info = arg;
- struct snd_seq_queue *q;
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(info->queue);
- q = queueptr(info->queue);
if (q == NULL)
return -EINVAL;
@@ -1643,7 +1562,6 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
info->owner = q->owner;
info->locked = q->locked;
strscpy(info->name, q->name, sizeof(info->name));
- queuefree(q);
return 0;
}
@@ -1653,7 +1571,6 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_info *info = arg;
- struct snd_seq_queue *q;
if (info->owner != client->number)
return -EINVAL;
@@ -1668,15 +1585,13 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
return -EPERM;
}
- q = queueptr(info->queue);
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(info->queue);
if (! q)
return -EINVAL;
- if (q->owner != client->number) {
- queuefree(q);
+ if (q->owner != client->number)
return -EPERM;
- }
strscpy(q->name, info->name, sizeof(q->name));
- queuefree(q);
return 0;
}
@@ -1686,15 +1601,14 @@ static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_info *info = arg;
- struct snd_seq_queue *q;
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ snd_seq_queue_find_name(info->name);
- q = snd_seq_queue_find_name(info->name);
if (q == NULL)
return -EINVAL;
info->queue = q->queue;
info->owner = q->owner;
info->locked = q->locked;
- queuefree(q);
return 0;
}
@@ -1704,10 +1618,10 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_status *status = arg;
- struct snd_seq_queue *queue;
struct snd_seq_timer *tmr;
+ struct snd_seq_queue *queue __free(snd_seq_queue) =
+ queueptr(status->queue);
- queue = queueptr(status->queue);
if (queue == NULL)
return -EINVAL;
memset(status, 0, sizeof(*status));
@@ -1722,7 +1636,6 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
status->running = tmr->running;
status->flags = queue->flags;
- queuefree(queue);
return 0;
}
@@ -1733,10 +1646,10 @@ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_tempo *tempo = arg;
- struct snd_seq_queue *queue;
struct snd_seq_timer *tmr;
+ struct snd_seq_queue *queue __free(snd_seq_queue) =
+ queueptr(tempo->queue);
- queue = queueptr(tempo->queue);
if (queue == NULL)
return -EINVAL;
memset(tempo, 0, sizeof(*tempo));
@@ -1750,7 +1663,6 @@ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
tempo->skew_base = tmr->skew_base;
if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 4))
tempo->tempo_base = tmr->tempo_base;
- queuefree(queue);
return 0;
}
@@ -1783,14 +1695,14 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_queue_timer *timer = arg;
- struct snd_seq_queue *queue;
struct snd_seq_timer *tmr;
+ struct snd_seq_queue *queue __free(snd_seq_queue) =
+ queueptr(timer->queue);
- queue = queueptr(timer->queue);
if (queue == NULL)
return -EINVAL;
- mutex_lock(&queue->timer_mutex);
+ guard(mutex)(&queue->timer_mutex);
tmr = queue->timer;
memset(timer, 0, sizeof(*timer));
timer->queue = queue->queue;
@@ -1800,8 +1712,6 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
timer->u.alsa.id = tmr->alsa_id;
timer->u.alsa.resolution = tmr->preferred_resolution;
}
- mutex_unlock(&queue->timer_mutex);
- queuefree(queue);
return 0;
}
@@ -1818,13 +1728,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
return -EINVAL;
if (snd_seq_queue_check_access(timer->queue, client->number)) {
- struct snd_seq_queue *q;
struct snd_seq_timer *tmr;
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(timer->queue);
- q = queueptr(timer->queue);
if (q == NULL)
return -ENXIO;
- mutex_lock(&q->timer_mutex);
+ guard(mutex)(&q->timer_mutex);
tmr = q->timer;
snd_seq_queue_timer_close(timer->queue);
tmr->type = timer->type;
@@ -1833,8 +1743,6 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
tmr->preferred_resolution = timer->u.alsa.resolution;
}
result = snd_seq_queue_timer_open(timer->queue);
- mutex_unlock(&q->timer_mutex);
- queuefree(q);
} else {
return -EPERM;
}
@@ -1882,9 +1790,9 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_client_pool *info = arg;
- struct snd_seq_client *cptr;
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(info->client);
- cptr = client_load_and_use_ptr(info->client);
if (cptr == NULL)
return -ENOENT;
memset(info, 0, sizeof(*info));
@@ -1901,7 +1809,6 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
info->input_pool = 0;
info->input_free = 0;
}
- snd_seq_client_unlock(cptr);
return 0;
}
@@ -1983,26 +1890,16 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_subscribe *subs = arg;
- int result;
- struct snd_seq_client *sender = NULL;
- struct snd_seq_client_port *sport = NULL;
- result = -EINVAL;
- sender = client_load_and_use_ptr(subs->sender.client);
+ struct snd_seq_client *sender __free(snd_seq_client) =
+ client_load_and_use_ptr(subs->sender.client);
if (!sender)
- goto __end;
- sport = snd_seq_port_use_ptr(sender, subs->sender.port);
+ return -EINVAL;
+ struct snd_seq_client_port *sport __free(snd_seq_port) =
+ snd_seq_port_use_ptr(sender, subs->sender.port);
if (!sport)
- goto __end;
- result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest,
- subs);
- __end:
- if (sport)
- snd_seq_port_unlock(sport);
- if (sender)
- snd_seq_client_unlock(sender);
-
- return result;
+ return -EINVAL;
+ return snd_seq_port_get_subscription(&sport->c_src, &subs->dest, subs);
}
@@ -2012,19 +1909,18 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
{
struct snd_seq_query_subs *subs = arg;
- int result = -ENXIO;
- struct snd_seq_client *cptr = NULL;
- struct snd_seq_client_port *port = NULL;
struct snd_seq_port_subs_info *group;
struct list_head *p;
int i;
- cptr = client_load_and_use_ptr(subs->root.client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(subs->root.client);
if (!cptr)
- goto __end;
- port = snd_seq_port_use_ptr(cptr, subs->root.port);
+ return -ENXIO;
+ struct snd_seq_client_port *port __free(snd_seq_port) =
+ snd_seq_port_use_ptr(cptr, subs->root.port);
if (!port)
- goto __end;
+ return -ENXIO;
switch (subs->type) {
case SNDRV_SEQ_QUERY_SUBS_READ:
@@ -2034,14 +1930,13 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
group = &port->c_dest;
break;
default:
- goto __end;
+ return -ENXIO;
}
- down_read(&group->list_mutex);
+ guard(rwsem_read)(&group->list_mutex);
/* search for the subscriber */
subs->num_subs = group->count;
i = 0;
- result = -ENOENT;
list_for_each(p, &group->list_head) {
if (i++ == subs->index) {
/* found! */
@@ -2055,19 +1950,11 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
}
subs->flags = s->info.flags;
subs->queue = s->info.queue;
- result = 0;
- break;
+ return 0;
}
}
- up_read(&group->list_mutex);
-
- __end:
- if (port)
- snd_seq_port_unlock(port);
- if (cptr)
- snd_seq_client_unlock(cptr);
- return result;
+ return -ENOENT;
}
@@ -2078,7 +1965,6 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_client_info *info = arg;
- struct snd_seq_client *cptr = NULL;
/* search for next client */
if (info->client < INT_MAX)
@@ -2086,17 +1972,14 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
if (info->client < 0)
info->client = 0;
for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
- cptr = client_load_and_use_ptr(info->client);
- if (cptr)
- break; /* found */
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(info->client);
+ if (cptr) {
+ get_client_info(cptr, info);
+ return 0; /* found */
+ }
}
- if (cptr == NULL)
- return -ENOENT;
-
- get_client_info(cptr, info);
- snd_seq_client_unlock(cptr);
-
- return 0;
+ return -ENOENT;
}
/*
@@ -2106,26 +1989,22 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
void *arg)
{
struct snd_seq_port_info *info = arg;
- struct snd_seq_client *cptr;
- struct snd_seq_client_port *port = NULL;
- cptr = client_load_and_use_ptr(info->addr.client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(info->addr.client);
if (cptr == NULL)
return -ENXIO;
/* search for next port */
info->addr.port++;
- port = snd_seq_port_query_nearest(cptr, info);
- if (port == NULL) {
- snd_seq_client_unlock(cptr);
+ struct snd_seq_client_port *port __free(snd_seq_port) =
+ snd_seq_port_query_nearest(cptr, info);
+ if (port == NULL)
return -ENOENT;
- }
/* get port info */
info->addr = port->addr;
snd_seq_get_port_info(port, info);
- snd_seq_port_unlock(port);
- snd_seq_client_unlock(cptr);
return 0;
}
@@ -2190,7 +2069,6 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
{
struct snd_seq_client_ump_info __user *argp =
(struct snd_seq_client_ump_info __user *)arg;
- struct snd_seq_client *cptr;
int client, type, err = 0;
size_t size;
void *p;
@@ -2206,55 +2084,55 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
size = sizeof(struct snd_ump_endpoint_info);
else
size = sizeof(struct snd_ump_block_info);
- cptr = client_load_and_use_ptr(client);
+
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(client);
if (!cptr)
return -ENOENT;
- mutex_lock(&cptr->ioctl_mutex);
- if (!cptr->midi_version) {
- err = -EBADFD;
- goto error;
- }
-
- if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {
- if (!cptr->ump_info)
- p = NULL;
- else
- p = cptr->ump_info[type];
- if (!p) {
- err = -ENODEV;
- goto error;
- }
- if (copy_to_user(argp->info, p, size)) {
- err = -EFAULT;
- goto error;
- }
- } else {
- if (cptr->type != USER_CLIENT) {
+ scoped_guard(mutex, &cptr->ioctl_mutex) {
+ if (!cptr->midi_version) {
err = -EBADFD;
- goto error;
+ break;
}
- if (!cptr->ump_info) {
- cptr->ump_info = kcalloc(NUM_UMP_INFOS,
- sizeof(void *), GFP_KERNEL);
+
+ if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {
+ if (!cptr->ump_info)
+ p = NULL;
+ else
+ p = cptr->ump_info[type];
+ if (!p) {
+ err = -ENODEV;
+ break;
+ }
+ if (copy_to_user(argp->info, p, size)) {
+ err = -EFAULT;
+ break;
+ }
+ } else {
+ if (cptr->type != USER_CLIENT) {
+ err = -EBADFD;
+ break;
+ }
if (!cptr->ump_info) {
- err = -ENOMEM;
- goto error;
+ cptr->ump_info = kcalloc(NUM_UMP_INFOS,
+ sizeof(void *), GFP_KERNEL);
+ if (!cptr->ump_info) {
+ err = -ENOMEM;
+ break;
+ }
}
+ p = memdup_user(argp->info, size);
+ if (IS_ERR(p)) {
+ err = PTR_ERR(p);
+ break;
+ }
+ kfree(cptr->ump_info[type]);
+ terminate_ump_info_strings(p, type);
+ cptr->ump_info[type] = p;
}
- p = memdup_user(argp->info, size);
- if (IS_ERR(p)) {
- err = PTR_ERR(p);
- goto error;
- }
- kfree(cptr->ump_info[type]);
- terminate_ump_info_strings(p, type);
- cptr->ump_info[type] = p;
- }
- error:
- mutex_unlock(&cptr->ioctl_mutex);
- snd_seq_client_unlock(cptr);
+ }
if (!err && cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO) {
if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)
snd_seq_system_ump_notify(client, 0,
@@ -2367,9 +2245,9 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd,
return -EFAULT;
}
- mutex_lock(&client->ioctl_mutex);
- err = handler->func(client, &buf);
- mutex_unlock(&client->ioctl_mutex);
+ scoped_guard(mutex, &client->ioctl_mutex) {
+ err = handler->func(client, &buf);
+ }
if (err >= 0) {
/* Some commands includes a bug in 'dir' field. */
if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT ||
@@ -2406,34 +2284,32 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS)
return -EINVAL;
- mutex_lock(&register_mutex);
+ scoped_guard(mutex, &register_mutex) {
- if (card) {
- client_index += SNDRV_SEQ_GLOBAL_CLIENTS
- + card->number * SNDRV_SEQ_CLIENTS_PER_CARD;
- if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN)
- client_index = -1;
- }
+ if (card) {
+ client_index += SNDRV_SEQ_GLOBAL_CLIENTS
+ + card->number * SNDRV_SEQ_CLIENTS_PER_CARD;
+ if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN)
+ client_index = -1;
+ }
- /* empty write queue as default */
- client = seq_create_client1(client_index, 0);
- if (client == NULL) {
- mutex_unlock(&register_mutex);
- return -EBUSY; /* failure code */
- }
- usage_alloc(&client_usage, 1);
+ /* empty write queue as default */
+ client = seq_create_client1(client_index, 0);
+ if (client == NULL)
+ return -EBUSY; /* failure code */
+ usage_alloc(&client_usage, 1);
- client->accept_input = 1;
- client->accept_output = 1;
- client->data.kernel.card = card;
- client->user_pversion = SNDRV_SEQ_VERSION;
+ client->accept_input = 1;
+ client->accept_output = 1;
+ client->data.kernel.card = card;
+ client->user_pversion = SNDRV_SEQ_VERSION;
- va_start(args, name_fmt);
- vsnprintf(client->name, sizeof(client->name), name_fmt, args);
- va_end(args);
+ va_start(args, name_fmt);
+ vsnprintf(client->name, sizeof(client->name), name_fmt, args);
+ va_end(args);
- client->type = KERNEL_CLIENT;
- mutex_unlock(&register_mutex);
+ client->type = KERNEL_CLIENT;
+ }
/* make others aware this new client */
snd_seq_system_client_ev_client_start(client->number);
@@ -2469,9 +2345,6 @@ EXPORT_SYMBOL(snd_seq_delete_kernel_client);
int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
struct file *file, bool blocking)
{
- struct snd_seq_client *cptr;
- int result;
-
if (snd_BUG_ON(!ev))
return -EINVAL;
@@ -2488,22 +2361,19 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
if (check_event_type_and_length(ev))
return -EINVAL;
- cptr = client_load_and_use_ptr(client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ client_load_and_use_ptr(client);
if (cptr == NULL)
return -EINVAL;
if (!cptr->accept_output) {
- result = -EPERM;
+ return -EPERM;
} else { /* send it */
- mutex_lock(&cptr->ioctl_mutex);
- result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
- false, 0,
- &cptr->ioctl_mutex);
- mutex_unlock(&cptr->ioctl_mutex);
+ guard(mutex)(&cptr->ioctl_mutex);
+ return snd_seq_client_enqueue_event(cptr, ev, file, blocking,
+ false, 0,
+ &cptr->ioctl_mutex);
}
-
- snd_seq_client_unlock(cptr);
- return result;
}
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
@@ -2517,9 +2387,6 @@ EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
int atomic, int hop)
{
- struct snd_seq_client *cptr;
- int result;
-
if (snd_BUG_ON(!ev))
return -EINVAL;
@@ -2530,20 +2397,33 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
if (check_event_type_and_length(ev))
return -EINVAL;
- cptr = snd_seq_client_use_ptr(client);
+ struct snd_seq_client *cptr __free(snd_seq_client) =
+ snd_seq_client_use_ptr(client);
if (cptr == NULL)
return -EINVAL;
if (!cptr->accept_output)
- result = -EPERM;
+ return -EPERM;
else
- result = snd_seq_deliver_event(cptr, ev, atomic, hop);
-
- snd_seq_client_unlock(cptr);
- return result;
+ return snd_seq_deliver_event(cptr, ev, atomic, hop);
}
EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
+static int call_seq_client_ctl(struct snd_seq_client *client,
+ unsigned int cmd, void *arg)
+{
+ const struct ioctl_handler *handler;
+
+ for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {
+ if (handler->cmd == cmd)
+ return handler->func(client, arg);
+ }
+
+ pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+ return -ENOTTY;
+}
+
/**
* snd_seq_kernel_client_ctl - operate a command for a client with data in
* kernel space.
@@ -2558,24 +2438,29 @@ EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
*/
int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
{
- const struct ioctl_handler *handler;
struct snd_seq_client *client;
client = clientptr(clientid);
if (client == NULL)
return -ENXIO;
- for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {
- if (handler->cmd == cmd)
- return handler->func(client, arg);
- }
-
- pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
- cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
- return -ENOTTY;
+ return call_seq_client_ctl(client, cmd, arg);
}
EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
+/* a similar like above but taking locks; used only from OSS sequencer layer */
+int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg)
+{
+ struct snd_seq_client *client __free(snd_seq_client) =
+ client_load_and_use_ptr(clientid);
+
+ if (!client)
+ return -ENXIO;
+ guard(mutex)(&client->ioctl_mutex);
+ return call_seq_client_ctl(client, cmd, arg);
+}
+EXPORT_SYMBOL_GPL(snd_seq_kernel_client_ioctl);
+
/* exported (for OSS emulator) */
int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait)
{
@@ -2602,7 +2487,7 @@ EXPORT_SYMBOL_GPL(snd_seq_kernel_client_get);
void snd_seq_kernel_client_put(struct snd_seq_client *cptr)
{
if (cptr)
- snd_seq_client_unlock(cptr);
+ snd_seq_client_unref(cptr);
}
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_put);
@@ -2620,11 +2505,9 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,
struct snd_seq_subscribers *s;
int count = 0;
- down_read(&group->list_mutex);
- if (list_empty(&group->list_head)) {
- up_read(&group->list_mutex);
+ guard(rwsem_read)(&group->list_mutex);
+ if (list_empty(&group->list_head))
return;
- }
snd_iprintf(buffer, msg);
list_for_each(p, &group->list_head) {
if (is_src)
@@ -2641,7 +2524,6 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,
if (group->exclusive)
snd_iprintf(buffer, "[ex]");
}
- up_read(&group->list_mutex);
snd_iprintf(buffer, "\n");
}
@@ -2667,7 +2549,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
{
struct snd_seq_client_port *p;
- mutex_lock(&client->ports_mutex);
+ guard(mutex)(&client->ports_mutex);
list_for_each_entry(p, &client->ports_list_head, list) {
if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE)
continue;
@@ -2686,7 +2568,6 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: ");
snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: ");
}
- mutex_unlock(&client->ports_mutex);
}
static const char *midi_version_string(unsigned int version)
@@ -2708,7 +2589,6 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
int c;
- struct snd_seq_client *client;
snd_iprintf(buffer, "Client info\n");
snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur);
@@ -2718,15 +2598,15 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
/* list the client table */
for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
- client = client_load_and_use_ptr(c);
+ struct snd_seq_client *client __free(snd_seq_client) =
+ client_load_and_use_ptr(c);
+
if (client == NULL)
continue;
- if (client->type == NO_CLIENT) {
- snd_seq_client_unlock(client);
+ if (client->type == NO_CLIENT)
continue;
- }
- mutex_lock(&client->ioctl_mutex);
+ guard(mutex)(&client->ioctl_mutex);
snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n",
c, client->name,
client->type == USER_CLIENT ? "User" : "Kernel",
@@ -2744,8 +2624,6 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
snd_iprintf(buffer, " Input pool :\n");
snd_seq_info_pool(buffer, client->data.user.fifo->pool, " ");
}
- mutex_unlock(&client->ioctl_mutex);
- snd_seq_client_unlock(client);
}
}
#endif /* CONFIG_SND_PROC_FS */
@@ -2783,10 +2661,10 @@ int __init snd_sequencer_device_init(void)
return err;
dev_set_name(seq_dev, "seq");
- mutex_lock(&register_mutex);
- err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
- &snd_seq_f_ops, NULL, seq_dev);
- mutex_unlock(&register_mutex);
+ scoped_guard(mutex, &register_mutex) {
+ err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
+ &snd_seq_f_ops, NULL, seq_dev);
+ }
if (err < 0) {
put_device(seq_dev);
return err;
diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h
index 915b1017286e..ece02c58db70 100644
--- a/sound/core/seq/seq_clientmgr.h
+++ b/sound/core/seq/seq_clientmgr.h
@@ -78,8 +78,20 @@ void snd_sequencer_device_done(void);
/* get locked pointer to client */
struct snd_seq_client *snd_seq_client_use_ptr(int clientid);
+static inline struct snd_seq_client *
+snd_seq_client_ref(struct snd_seq_client *client)
+{
+ snd_use_lock_use(&client->use_lock);
+ return client;
+}
+
/* unlock pointer to client */
-#define snd_seq_client_unlock(client) snd_use_lock_free(&(client)->use_lock)
+static inline void snd_seq_client_unref(struct snd_seq_client *client)
+{
+ snd_use_lock_free(&client->use_lock);
+}
+
+DEFINE_FREE(snd_seq_client, struct snd_seq_client *, if (!IS_ERR_OR_NULL(_T)) snd_seq_client_unref(_T))
/* dispatch event to client(s) */
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop);
@@ -94,8 +106,7 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
int atomic, int hop);
/* only for OSS sequencer */
-bool snd_seq_client_ioctl_lock(int clientid);
-void snd_seq_client_ioctl_unlock(int clientid);
+int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg);
extern int seq_client_load[15];
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index 643af4c1e838..22679dca9aae 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -31,10 +31,10 @@ struct snd_seq_port_info32 {
static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd,
struct snd_seq_port_info32 __user *data32)
{
- struct snd_seq_port_info *data __free(kfree) = NULL;
int err;
+ struct snd_seq_port_info *data __free(kfree) =
+ kmalloc_obj(*data);
- data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 783fc72c2ef6..af45f328ae99 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -115,7 +115,7 @@ create_port(int idx, int type)
struct snd_seq_port_callback pcb;
struct snd_seq_dummy_port *rec;
- rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+ rec = kzalloc_obj(*rec);
if (!rec)
return NULL;
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 3a10b081f129..ebe1394c18a9 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -19,7 +19,7 @@ struct snd_seq_fifo *snd_seq_fifo_new(int poolsize)
{
struct snd_seq_fifo *f;
- f = kzalloc(sizeof(*f), GFP_KERNEL);
+ f = kzalloc_obj(*f);
if (!f)
return NULL;
@@ -106,12 +106,11 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
if (snd_BUG_ON(!f))
return -EINVAL;
- snd_use_lock_use(&f->use_lock);
+ guard(snd_seq_fifo)(f);
err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL, NULL); /* always non-blocking */
if (err < 0) {
if ((err == -ENOMEM) || (err == -EAGAIN))
atomic_inc(&f->overflow);
- snd_use_lock_free(&f->use_lock);
return err;
}
@@ -130,8 +129,6 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
if (waitqueue_active(&f->input_sleep))
wake_up(&f->input_sleep);
- snd_use_lock_free(&f->use_lock);
-
return 0; /* success */
}
@@ -213,6 +210,7 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file,
poll_table *wait)
{
poll_wait(file, &f->input_sleep, wait);
+ guard(spinlock_irq)(&f->lock);
return (f->cells > 0);
}
@@ -263,14 +261,10 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
/* get the number of unused cells safely */
int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f)
{
- int cells;
-
if (!f)
return 0;
- snd_use_lock_use(&f->use_lock);
- scoped_guard(spinlock_irqsave, &f->lock)
- cells = snd_seq_unused_cells(f->pool);
- snd_use_lock_free(&f->use_lock);
- return cells;
+ guard(snd_seq_fifo)(f);
+ guard(spinlock_irqsave)(&f->lock);
+ return snd_seq_unused_cells(f->pool);
}
diff --git a/sound/core/seq/seq_fifo.h b/sound/core/seq/seq_fifo.h
index b56a7b897c9c..4c9c49127746 100644
--- a/sound/core/seq/seq_fifo.h
+++ b/sound/core/seq/seq_fifo.h
@@ -37,6 +37,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event);
/* lock fifo from release */
#define snd_seq_fifo_lock(fifo) snd_use_lock_use(&(fifo)->use_lock)
#define snd_seq_fifo_unlock(fifo) snd_use_lock_free(&(fifo)->use_lock)
+DEFINE_GUARD(snd_seq_fifo, struct snd_seq_fifo *, snd_seq_fifo_lock(_T), snd_seq_fifo_unlock(_T))
/* get a cell from fifo - fifo should be locked */
int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index ccde0ca3d208..aaf808316c30 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -441,9 +441,7 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
if (snd_BUG_ON(!pool))
return -EINVAL;
- cellptr = kvmalloc_array(pool->size,
- sizeof(struct snd_seq_event_cell),
- GFP_KERNEL);
+ cellptr = kvmalloc_objs(struct snd_seq_event_cell, pool->size);
if (!cellptr)
return -ENOMEM;
@@ -518,7 +516,7 @@ struct snd_seq_pool *snd_seq_pool_new(int poolsize)
struct snd_seq_pool *pool;
/* create pool block */
- pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+ pool = kzalloc_obj(*pool);
if (!pool)
return NULL;
spin_lock_init(&pool->lock);
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index ba52a77eda38..ca3f5fc30992 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -265,13 +265,10 @@ static void snd_seq_midisynth_delete(struct seq_midisynth *msynth)
/* register new midi synth port */
static int
-snd_seq_midisynth_probe(struct device *_dev)
+snd_seq_midisynth_probe(struct snd_seq_device *dev)
{
- struct snd_seq_device *dev = to_seq_dev(_dev);
struct seq_midisynth_client *client;
struct seq_midisynth *msynth, *ms;
- struct snd_seq_port_info *port __free(kfree) = NULL;
- struct snd_rawmidi_info *info __free(kfree) = NULL;
struct snd_rawmidi *rmidi = dev->private_data;
int newclient = 0;
unsigned int p, ports;
@@ -282,7 +279,9 @@ snd_seq_midisynth_probe(struct device *_dev)
if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES))
return -EINVAL;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+
+ struct snd_rawmidi_info *info __free(kfree) =
+ kmalloc_obj(*info);
if (! info)
return -ENOMEM;
info->device = device;
@@ -306,7 +305,7 @@ snd_seq_midisynth_probe(struct device *_dev)
client = synths[card->number];
if (client == NULL) {
newclient = 1;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
+ client = kzalloc_obj(*client);
if (client == NULL)
return -ENOMEM;
client->seq_client =
@@ -319,8 +318,10 @@ snd_seq_midisynth_probe(struct device *_dev)
}
}
- msynth = kcalloc(ports, sizeof(struct seq_midisynth), GFP_KERNEL);
- port = kmalloc(sizeof(*port), GFP_KERNEL);
+ msynth = kzalloc_objs(struct seq_midisynth, ports);
+
+ struct snd_seq_port_info *port __free(kfree) =
+ kmalloc_obj(*port);
if (msynth == NULL || port == NULL)
goto __nomem;
@@ -344,7 +345,7 @@ snd_seq_midisynth_probe(struct device *_dev)
info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
info->subdevice = p;
if (snd_rawmidi_info_select(card, info) >= 0)
- strcpy(port->name, info->subname);
+ strscpy(port->name, info->subname);
if (! port->name[0]) {
if (info->name[0]) {
if (ports > 1)
@@ -411,10 +412,9 @@ snd_seq_midisynth_probe(struct device *_dev)
}
/* release midi synth port */
-static int
-snd_seq_midisynth_remove(struct device *_dev)
+static void
+snd_seq_midisynth_remove(struct snd_seq_device *dev)
{
- struct snd_seq_device *dev = to_seq_dev(_dev);
struct seq_midisynth_client *client;
struct seq_midisynth *msynth;
struct snd_card *card = dev->card;
@@ -423,7 +423,7 @@ snd_seq_midisynth_remove(struct device *_dev)
guard(mutex)(&register_mutex);
client = synths[card->number];
if (client == NULL || client->ports[device] == NULL)
- return -ENODEV;
+ return;
ports = client->ports_per_device[device];
client->ports_per_device[device] = 0;
msynth = client->ports[device];
@@ -437,14 +437,13 @@ snd_seq_midisynth_remove(struct device *_dev)
synths[card->number] = NULL;
kfree(client);
}
- return 0;
}
static struct snd_seq_driver seq_midisynth_driver = {
+ .probe = snd_seq_midisynth_probe,
+ .remove = snd_seq_midisynth_remove,
.driver = {
.name = KBUILD_MODNAME,
- .probe = snd_seq_midisynth_probe,
- .remove = snd_seq_midisynth_remove,
},
.id = SNDRV_SEQ_DEV_ID_MIDISYNTH,
.argsize = 0,
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 81d2ef5e5811..fd067c85c524 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -650,7 +650,7 @@ static struct snd_midi_channel *snd_midi_channel_init_set(int n)
struct snd_midi_channel *chan;
int i;
- chan = kmalloc_array(n, sizeof(struct snd_midi_channel), GFP_KERNEL);
+ chan = kmalloc_objs(struct snd_midi_channel, n);
if (chan) {
for (i = 0; i < n; i++)
snd_midi_channel_init(chan+i, i);
@@ -688,7 +688,7 @@ struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
{
struct snd_midi_channel_set *chset;
- chset = kmalloc(sizeof(*chset), GFP_KERNEL);
+ chset = kmalloc_obj(*chset);
if (chset) {
chset->channels = snd_midi_channel_init_set(n);
chset->private_data = NULL;
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index fa9dfc53c3fc..0d9269b47b59 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -104,7 +104,7 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
struct snd_midi_event *dev;
*rdev = NULL;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc_obj(*dev);
if (dev == NULL)
return -ENOMEM;
if (bufsize > 0) {
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index cc2f8e846584..da8d358958f1 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -129,7 +129,7 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
}
/* create a new port */
- new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
+ new_port = kzalloc_obj(*new_port);
if (!new_port)
return -ENOMEM; /* failure, out of memory */
/* init port data */
@@ -178,17 +178,10 @@ static int unsubscribe_port(struct snd_seq_client *client,
static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
struct snd_seq_client **cp)
{
- struct snd_seq_client_port *p;
*cp = snd_seq_client_use_ptr(addr->client);
- if (*cp) {
- p = snd_seq_port_use_ptr(*cp, addr->port);
- if (! p) {
- snd_seq_client_unlock(*cp);
- *cp = NULL;
- }
- return p;
- }
- return NULL;
+ if (!*cp)
+ return NULL;
+ return snd_seq_port_use_ptr(*cp, addr->port);
}
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
@@ -218,14 +211,13 @@ static void clear_subscriber_list(struct snd_seq_client *client,
list_for_each_safe(p, n, &grp->list_head) {
struct snd_seq_subscribers *subs;
- struct snd_seq_client *c;
- struct snd_seq_client_port *aport;
subs = get_subscriber(p, is_src);
- if (is_src)
- aport = get_client_port(&subs->info.dest, &c);
- else
- aport = get_client_port(&subs->info.sender, &c);
+ struct snd_seq_client *c __free(snd_seq_client) = NULL;
+ struct snd_seq_client_port *aport __free(snd_seq_port) =
+ is_src ?
+ get_client_port(&subs->info.dest, &c) :
+ get_client_port(&subs->info.sender, &c);
delete_and_unsubscribe_port(client, port, subs, is_src, false);
if (!aport) {
@@ -241,8 +233,6 @@ static void clear_subscriber_list(struct snd_seq_client *client,
/* ok we got the connected port */
delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
kfree(subs);
- snd_seq_port_unlock(aport);
- snd_seq_client_unlock(c);
}
}
@@ -582,7 +572,7 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
bool exclusive;
int err;
- subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+ subs = kzalloc_obj(*subs);
if (!subs)
return -ENOMEM;
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
index b3b35018cb82..40ed6cf7cb90 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -96,6 +96,8 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
/* unlock the port */
#define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock)
+DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T))
+
/* create a port, port number or a negative error code is returned */
int snd_seq_create_port(struct snd_seq_client *client, int port_index,
struct snd_seq_client_port **port_ret);
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index e649485a8772..25c0ed8f9f0f 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -43,7 +43,7 @@ struct snd_seq_prioq *snd_seq_prioq_new(void)
{
struct snd_seq_prioq *f;
- f = kzalloc(sizeof(*f), GFP_KERNEL);
+ f = kzalloc_obj(*f);
if (!f)
return NULL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 5df26788dda4..2c420d249c96 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -89,7 +89,7 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
{
struct snd_seq_queue *q;
- q = kzalloc(sizeof(*q), GFP_KERNEL);
+ q = kzalloc_obj(*q);
if (!q)
return NULL;
@@ -209,14 +209,14 @@ struct snd_seq_queue *queueptr(int queueid)
struct snd_seq_queue *snd_seq_queue_find_name(char *name)
{
int i;
- struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queueptr(i);
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(i);
+
if (q) {
if (strncmp(q->name, name, sizeof(q->name)) == 0)
- return q;
- queuefree(q);
+ return no_free_ptr(q);
}
}
return NULL;
@@ -286,12 +286,13 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
int dest, err;
- struct snd_seq_queue *q;
if (snd_BUG_ON(!cell))
return -EINVAL;
dest = cell->event.queue; /* destination queue */
- q = queueptr(dest);
+
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(dest);
if (q == NULL)
return -EINVAL;
/* handle relative time stamps, convert them into absolute */
@@ -321,16 +322,12 @@ int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
break;
}
- if (err < 0) {
- queuefree(q); /* unlock */
+ if (err < 0)
return err;
- }
/* trigger dispatching */
snd_seq_check_queue(q, atomic, hop);
- queuefree(q); /* unlock */
-
return 0;
}
@@ -366,15 +363,12 @@ static inline void queue_access_unlock(struct snd_seq_queue *q)
/* exported - only checking permission */
int snd_seq_queue_check_access(int queueid, int client)
{
- struct snd_seq_queue *q = queueptr(queueid);
- int access_ok;
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid);
if (! q)
return 0;
- scoped_guard(spinlock_irqsave, &q->owner_lock)
- access_ok = check_access(q, client);
- queuefree(q);
- return access_ok;
+ guard(spinlock_irqsave)(&q->owner_lock);
+ return check_access(q, client);
}
/*----------------------------------------------------------------*/
@@ -384,22 +378,19 @@ int snd_seq_queue_check_access(int queueid, int client)
*/
int snd_seq_queue_set_owner(int queueid, int client, int locked)
{
- struct snd_seq_queue *q = queueptr(queueid);
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid);
if (q == NULL)
return -EINVAL;
- if (! queue_access_lock(q, client)) {
- queuefree(q);
+ if (!queue_access_lock(q, client))
return -EPERM;
- }
scoped_guard(spinlock_irqsave, &q->owner_lock) {
q->locked = locked ? 1 : 0;
q->owner = client;
}
queue_access_unlock(q);
- queuefree(q);
return 0;
}
@@ -414,10 +405,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
int snd_seq_queue_timer_open(int queueid)
{
int result = 0;
- struct snd_seq_queue *queue;
struct snd_seq_timer *tmr;
+ struct snd_seq_queue *queue __free(snd_seq_queue) =
+ queueptr(queueid);
- queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
tmr = queue->timer;
@@ -426,7 +417,6 @@ int snd_seq_queue_timer_open(int queueid)
snd_seq_timer_defaults(tmr);
result = snd_seq_timer_open(queue);
}
- queuefree(queue);
return result;
}
@@ -435,14 +425,13 @@ int snd_seq_queue_timer_open(int queueid)
*/
int snd_seq_queue_timer_close(int queueid)
{
- struct snd_seq_queue *queue;
int result = 0;
+ struct snd_seq_queue *queue __free(snd_seq_queue) =
+ queueptr(queueid);
- queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
snd_seq_timer_close(queue);
- queuefree(queue);
return result;
}
@@ -450,15 +439,13 @@ int snd_seq_queue_timer_close(int queueid)
int snd_seq_queue_timer_set_tempo(int queueid, int client,
struct snd_seq_queue_tempo *info)
{
- struct snd_seq_queue *q = queueptr(queueid);
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(queueid);
int result;
if (q == NULL)
return -EINVAL;
- if (! queue_access_lock(q, client)) {
- queuefree(q);
+ if (!queue_access_lock(q, client))
return -EPERM;
- }
result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq,
info->tempo_base);
@@ -466,7 +453,6 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
result = snd_seq_timer_set_skew(q->timer, info->skew_value,
info->skew_base);
queue_access_unlock(q);
- queuefree(q);
return result;
}
@@ -495,15 +481,13 @@ static void queue_use(struct snd_seq_queue *queue, int client, int use)
*/
int snd_seq_queue_use(int queueid, int client, int use)
{
- struct snd_seq_queue *queue;
+ struct snd_seq_queue *queue __free(snd_seq_queue) =
+ queueptr(queueid);
- queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
- mutex_lock(&queue->timer_mutex);
+ guard(mutex)(&queue->timer_mutex);
queue_use(queue, client, use);
- mutex_unlock(&queue->timer_mutex);
- queuefree(queue);
return 0;
}
@@ -514,15 +498,12 @@ int snd_seq_queue_use(int queueid, int client, int use)
*/
int snd_seq_queue_is_used(int queueid, int client)
{
- struct snd_seq_queue *q;
- int result;
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(queueid);
- q = queueptr(queueid);
if (q == NULL)
return -EINVAL; /* invalid queue */
- result = test_bit(client, q->clients_bitmap) ? 1 : 0;
- queuefree(q);
- return result;
+ return test_bit(client, q->clients_bitmap) ? 1 : 0;
}
@@ -535,11 +516,10 @@ int snd_seq_queue_is_used(int queueid, int client)
void snd_seq_queue_client_leave(int client)
{
int i;
- struct snd_seq_queue *q;
/* delete own queues from queue list */
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queue_list_remove(i, client);
+ struct snd_seq_queue *q = queue_list_remove(i, client);
if (q)
queue_delete(q);
}
@@ -548,7 +528,7 @@ void snd_seq_queue_client_leave(int client)
* they are not owned by this client
*/
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queueptr(i);
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i);
if (!q)
continue;
if (test_bit(client, q->clients_bitmap)) {
@@ -556,7 +536,6 @@ void snd_seq_queue_client_leave(int client)
snd_seq_prioq_leave(q->timeq, client, 0);
snd_seq_queue_use(q->queue, client, 0);
}
- queuefree(q);
}
}
@@ -564,30 +543,13 @@ void snd_seq_queue_client_leave(int client)
/*----------------------------------------------------------------*/
-/* remove cells from all queues */
-void snd_seq_queue_client_leave_cells(int client)
-{
- int i;
- struct snd_seq_queue *q;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queueptr(i);
- if (!q)
- continue;
- snd_seq_prioq_leave(q->tickq, client, 0);
- snd_seq_prioq_leave(q->timeq, client, 0);
- queuefree(q);
- }
-}
-
/* remove cells based on flush criteria */
void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
{
int i;
- struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queueptr(i);
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i);
if (!q)
continue;
if (test_bit(client, q->clients_bitmap) &&
@@ -596,7 +558,6 @@ void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
snd_seq_prioq_remove_events(q->tickq, client, info);
snd_seq_prioq_remove_events(q->timeq, client, info);
}
- queuefree(q);
}
}
@@ -683,24 +644,21 @@ static void snd_seq_queue_process_event(struct snd_seq_queue *q,
*/
int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
{
- struct snd_seq_queue *q;
-
if (snd_BUG_ON(!ev))
return -EINVAL;
- q = queueptr(ev->data.queue.queue);
+
+ struct snd_seq_queue *q __free(snd_seq_queue) =
+ queueptr(ev->data.queue.queue);
if (q == NULL)
return -EINVAL;
- if (! queue_access_lock(q, ev->source.client)) {
- queuefree(q);
+ if (!queue_access_lock(q, ev->source.client))
return -EPERM;
- }
snd_seq_queue_process_event(q, ev, atomic, hop);
queue_access_unlock(q);
- queuefree(q);
return 0;
}
@@ -713,13 +671,12 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
int i, bpm;
- struct snd_seq_queue *q;
struct snd_seq_timer *tmr;
bool locked;
int owner;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queueptr(i);
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(i);
if (!q)
continue;
@@ -747,7 +704,6 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "current time : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec);
snd_iprintf(buffer, "current tick : %d\n", tmr->tick.cur_tick);
snd_iprintf(buffer, "\n");
- queuefree(q);
}
}
#endif /* CONFIG_SND_PROC_FS */
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index 74cc31aacdac..afcd3c5484a6 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -66,7 +66,6 @@ void snd_seq_queue_client_leave(int client);
int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop);
/* Remove events */
-void snd_seq_queue_client_leave_cells(int client);
void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info);
/* return pointer to queue structure for specified id */
@@ -74,6 +73,8 @@ struct snd_seq_queue *queueptr(int queueid);
/* unlock */
#define queuefree(q) snd_use_lock_free(&(q)->use_lock)
+DEFINE_FREE(snd_seq_queue, struct snd_seq_queue *, if (!IS_ERR_OR_NULL(_T)) queuefree(_T))
+
/* return the (first) queue matching with the specified name */
struct snd_seq_queue *snd_seq_queue_find_name(char *name);
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index 853920f79016..f6132a120048 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -130,7 +130,7 @@ int __init snd_seq_system_client_init(void)
struct snd_seq_port_info *port;
int err;
- port = kzalloc(sizeof(*port), GFP_KERNEL);
+ port = kzalloc_obj(*port);
if (!port)
return -ENOMEM;
@@ -146,7 +146,7 @@ int __init snd_seq_system_client_init(void)
}
/* register timer */
- strcpy(port->name, "Timer");
+ strscpy(port->name, "Timer");
port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */
port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */
port->kernel = &pcallbacks;
@@ -160,7 +160,7 @@ int __init snd_seq_system_client_init(void)
goto error_port;
/* register announcement port */
- strcpy(port->name, "Announce");
+ strscpy(port->name, "Announce");
port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */
pcallbacks.event_input = NULL;
pcallbacks.subscribe = sys_announce_subscribe;
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index c9f0392ac7f1..9bef2f792498 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -43,7 +43,7 @@ struct snd_seq_timer *snd_seq_timer_new(void)
{
struct snd_seq_timer *tmr;
- tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
+ tmr = kzalloc_obj(*tmr);
if (!tmr)
return NULL;
spin_lock_init(&tmr->lock);
@@ -440,13 +440,13 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
int idx;
- struct snd_seq_queue *q;
struct snd_seq_timer *tmr;
struct snd_timer_instance *ti;
unsigned long resolution;
for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
- q = queueptr(idx);
+ struct snd_seq_queue *q __free(snd_seq_queue) = queueptr(idx);
+
if (q == NULL)
continue;
scoped_guard(mutex, &q->timer_mutex) {
@@ -461,7 +461,6 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base);
}
- queuefree(q);
}
}
#endif /* CONFIG_SND_PROC_FS */
diff --git a/sound/core/seq/seq_ump_client.c b/sound/core/seq/seq_ump_client.c
index 1255351b59ce..fdc76f23e03f 100644
--- a/sound/core/seq/seq_ump_client.c
+++ b/sound/core/seq/seq_ump_client.c
@@ -214,13 +214,13 @@ static bool skip_group(struct seq_ump_client *client, struct snd_ump_group *grou
static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
{
struct snd_ump_group *group = &client->ump->groups[group_index];
- struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback pcallbacks;
if (skip_group(client, group))
return 0;
- port = kzalloc(sizeof(*port), GFP_KERNEL);
+ struct snd_seq_port_info *port __free(kfree) =
+ kzalloc_obj(*port);
if (!port)
return -ENOMEM;
@@ -243,12 +243,12 @@ static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
/* update the sequencer ports; called from notify_fb_change callback */
static void update_port_infos(struct seq_ump_client *client)
{
- struct snd_seq_port_info *old __free(kfree) = NULL;
- struct snd_seq_port_info *new __free(kfree) = NULL;
int i, err;
- old = kzalloc(sizeof(*old), GFP_KERNEL);
- new = kzalloc(sizeof(*new), GFP_KERNEL);
+ struct snd_seq_port_info *old __free(kfree) =
+ kzalloc_obj(*old);
+ struct snd_seq_port_info *new __free(kfree) =
+ kzalloc_obj(*new);
if (!old || !new)
return;
@@ -278,12 +278,12 @@ static void update_port_infos(struct seq_ump_client *client)
/* create a UMP Endpoint port */
static int create_ump_endpoint_port(struct seq_ump_client *client)
{
- struct snd_seq_port_info *port __free(kfree) = NULL;
struct snd_seq_port_callback pcallbacks;
unsigned int rawmidi_info = client->ump->core.info_flags;
int err;
- port = kzalloc(sizeof(*port), GFP_KERNEL);
+ struct snd_seq_port_info *port __free(kfree) =
+ kzalloc_obj(*port);
if (!port)
return -ENOMEM;
@@ -310,7 +310,7 @@ static int create_ump_endpoint_port(struct seq_ump_client *client)
SNDRV_SEQ_PORT_TYPE_HARDWARE |
SNDRV_SEQ_PORT_TYPE_PORT;
port->midi_channels = 16;
- strcpy(port->name, "MIDI 2.0");
+ strscpy(port->name, "MIDI 2.0");
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.private_data = client;
@@ -452,9 +452,8 @@ static const struct snd_seq_ump_ops seq_ump_ops = {
};
/* create a sequencer client and ports for the given UMP endpoint */
-static int snd_seq_ump_probe(struct device *_dev)
+static int snd_seq_ump_probe(struct snd_seq_device *dev)
{
- struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_ump_endpoint *ump = dev->private_data;
struct snd_card *card = dev->card;
struct seq_ump_client *client;
@@ -462,7 +461,7 @@ static int snd_seq_ump_probe(struct device *_dev)
struct snd_seq_client *cptr;
int p, err;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
+ client = kzalloc_obj(*client);
if (!client)
return -ENOMEM;
@@ -513,21 +512,19 @@ static int snd_seq_ump_probe(struct device *_dev)
}
/* remove a sequencer client */
-static int snd_seq_ump_remove(struct device *_dev)
+static void snd_seq_ump_remove(struct snd_seq_device *dev)
{
- struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_ump_endpoint *ump = dev->private_data;
if (ump->seq_client)
seq_ump_client_free(ump->seq_client);
- return 0;
}
static struct snd_seq_driver seq_ump_driver = {
+ .probe = snd_seq_ump_probe,
+ .remove = snd_seq_ump_remove,
.driver = {
.name = KBUILD_MODNAME,
- .probe = snd_seq_ump_probe,
- .remove = snd_seq_ump_remove,
},
.id = SNDRV_SEQ_DEV_ID_UMP,
.argsize = 0,
diff --git a/sound/core/seq/seq_ump_convert.c b/sound/core/seq/seq_ump_convert.c
index ff7e558b4d51..ff4ee26adad1 100644
--- a/sound/core/seq/seq_ump_convert.c
+++ b/sound/core/seq/seq_ump_convert.c
@@ -841,7 +841,7 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
unsigned char index = event->data.control.param & 0x7f;
unsigned char val = event->data.control.value & 0x7f;
struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel];
- int ret;
+ int ret = 0;
/* process special CC's (bank/rpn/nrpn) */
switch (index) {
@@ -851,47 +851,54 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
cc->cc_rpn_msb = val;
if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f)
reset_rpn(cc);
- return ret;
+ break;
case UMP_CC_RPN_LSB:
ret = fill_rpn(cc, data, channel, true);
cc->rpn_set = 1;
cc->cc_rpn_lsb = val;
if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f)
reset_rpn(cc);
- return ret;
+ break;
case UMP_CC_NRPN_MSB:
ret = fill_rpn(cc, data, channel, true);
cc->nrpn_set = 1;
cc->cc_nrpn_msb = val;
- return ret;
+ break;
case UMP_CC_NRPN_LSB:
ret = fill_rpn(cc, data, channel, true);
cc->nrpn_set = 1;
cc->cc_nrpn_lsb = val;
- return ret;
+ break;
case UMP_CC_DATA:
cc->cc_data_msb_set = 1;
cc->cc_data_msb = val;
- return fill_rpn(cc, data, channel, false);
+ ret = fill_rpn(cc, data, channel, false);
+ break;
case UMP_CC_BANK_SELECT:
cc->bank_set = 1;
cc->cc_bank_msb = val;
- return 0; // skip
+ ret = 0; // skip
+ break;
case UMP_CC_BANK_SELECT_LSB:
cc->bank_set = 1;
cc->cc_bank_lsb = val;
- return 0; // skip
+ ret = 0; // skip
+ break;
case UMP_CC_DATA_LSB:
cc->cc_data_lsb_set = 1;
cc->cc_data_lsb = val;
- return fill_rpn(cc, data, channel, false);
+ ret = fill_rpn(cc, data, channel, false);
+ break;
+ default:
+ data->cc.status = status;
+ data->cc.channel = channel;
+ data->cc.index = index;
+ data->cc.data = upscale_7_to_32bit(event->data.control.value & 0x7f);
+ ret = 1;
+ break;
}
- data->cc.status = status;
- data->cc.channel = channel;
- data->cc.index = index;
- data->cc.data = upscale_7_to_32bit(event->data.control.value & 0x7f);
- return 1;
+ return ret;
}
/* convert one-parameter control event to MIDI 2.0 UMP */
@@ -1285,3 +1292,21 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source,
else
return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop);
}
+
+/* return the UMP group-port number of the event;
+ * return -1 if groupless or non-UMP event
+ */
+int snd_seq_ump_group_port(const struct snd_seq_event *event)
+{
+ const struct snd_seq_ump_event *ump_ev =
+ (const struct snd_seq_ump_event *)event;
+ unsigned char type;
+
+ if (!snd_seq_ev_is_ump(event))
+ return -1;
+ type = ump_message_type(ump_ev->ump[0]);
+ if (ump_is_groupless_msg(type))
+ return -1;
+ /* group-port number starts from 1 */
+ return ump_message_group(ump_ev->ump[0]) + 1;
+}
diff --git a/sound/core/seq/seq_ump_convert.h b/sound/core/seq/seq_ump_convert.h
index 6c146d803280..4abf0a7637d7 100644
--- a/sound/core/seq/seq_ump_convert.h
+++ b/sound/core/seq/seq_ump_convert.h
@@ -18,5 +18,6 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source,
struct snd_seq_client_port *dest_port,
struct snd_seq_event *event,
int atomic, int hop);
+int snd_seq_ump_group_port(const struct snd_seq_event *event);
#endif /* __SEQ_UMP_CONVERT_H */
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index b4672613c261..982828650d41 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -216,7 +216,7 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
struct snd_rawmidi_runtime *runtime = substream->runtime;
struct snd_virmidi *vmidi;
- vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
+ vmidi = kzalloc_obj(*vmidi);
if (vmidi == NULL)
return -ENOMEM;
vmidi->substream = substream;
@@ -361,13 +361,13 @@ static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev)
{
int client;
struct snd_seq_port_callback pcallbacks;
- struct snd_seq_port_info *pinfo __free(kfree) = NULL;
int err;
if (rdev->client >= 0)
return 0;
- pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
+ struct snd_seq_port_info *pinfo __free(kfree) =
+ kzalloc_obj(*pinfo);
if (!pinfo)
return -ENOMEM;
@@ -497,8 +497,8 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
&rmidi);
if (err < 0)
return err;
- strcpy(rmidi->name, rmidi->id);
- rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
+ strscpy(rmidi->name, rmidi->id);
+ rdev = kzalloc_obj(*rdev);
if (rdev == NULL) {
snd_device_free(card, rmidi);
return -ENOMEM;
diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c
index 4492be5d2317..1b062d6b17ea 100644
--- a/sound/core/seq_device.c
+++ b/sound/core/seq_device.c
@@ -43,15 +43,37 @@ MODULE_LICENSE("GPL");
static int snd_seq_bus_match(struct device *dev, const struct device_driver *drv)
{
struct snd_seq_device *sdev = to_seq_dev(dev);
- struct snd_seq_driver *sdrv = to_seq_drv(drv);
+ const struct snd_seq_driver *sdrv = to_seq_drv(drv);
return strcmp(sdrv->id, sdev->id) == 0 &&
sdrv->argsize == sdev->argsize;
}
+static int snd_seq_bus_probe(struct device *dev)
+{
+ struct snd_seq_device *sdev = to_seq_dev(dev);
+ const struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
+
+ if (sdrv->probe)
+ return sdrv->probe(sdev);
+ else
+ return 0;
+}
+
+static void snd_seq_bus_remove(struct device *dev)
+{
+ struct snd_seq_device *sdev = to_seq_dev(dev);
+ const struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
+
+ if (sdrv->remove)
+ sdrv->remove(sdev);
+}
+
static const struct bus_type snd_seq_bus_type = {
.name = "snd_seq",
.match = snd_seq_bus_match,
+ .probe = snd_seq_bus_probe,
+ .remove = snd_seq_bus_remove,
};
/*
@@ -247,10 +269,12 @@ EXPORT_SYMBOL(snd_seq_device_new);
*/
int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod)
{
- if (WARN_ON(!drv->driver.name || !drv->id))
+ if (WARN_ON(!drv->driver.name || !drv->id || drv->driver.probe || drv->driver.remove))
return -EINVAL;
+
drv->driver.bus = &snd_seq_bus_type;
drv->driver.owner = mod;
+
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(__snd_seq_driver_register);
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 6531a67f13b3..8d05fe0d263b 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -216,9 +216,16 @@ static int snd_find_free_minor(int type, struct snd_card *card, int dev)
case SNDRV_DEVICE_TYPE_RAWMIDI:
case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
+ minor = SNDRV_MINOR(card->number, type + dev);
+ break;
case SNDRV_DEVICE_TYPE_COMPRESS:
if (snd_BUG_ON(!card))
return -EINVAL;
+ if (dev < 0 ||
+ dev >= SNDRV_MINOR_HWDEP - SNDRV_MINOR_COMPRESS)
+ return -EINVAL;
minor = SNDRV_MINOR(card->number, type + dev);
break;
default:
@@ -257,7 +264,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
if (snd_BUG_ON(!device))
return -EINVAL;
- preg = kmalloc(sizeof *preg, GFP_KERNEL);
+ preg = kmalloc_obj(*preg);
if (preg == NULL)
return -ENOMEM;
preg->type = type;
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index d65cc6fee2e6..7eb49f2cada5 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -96,7 +96,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
return 0; /* ignore silently */
if (minor < 0)
return minor;
- preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
+ preg = kmalloc_obj(struct snd_minor);
if (preg == NULL)
return -ENOMEM;
preg->type = type;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 1de4b90fd4d1..820901d503af 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -129,6 +129,9 @@ static LIST_HEAD(snd_timer_list);
/* list of slave instances */
static LIST_HEAD(snd_timer_slave_list);
+/* list of open master instances that can accept slave links */
+static LIST_HEAD(snd_timer_master_list);
+
/* lock for slave active lists */
static DEFINE_SPINLOCK(slave_active_lock);
@@ -151,7 +154,7 @@ struct snd_timer_instance *snd_timer_instance_new(const char *owner)
{
struct snd_timer_instance *timeri;
- timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
+ timeri = kzalloc_obj(*timeri);
if (timeri == NULL)
return NULL;
timeri->owner = kstrdup(owner, GFP_KERNEL);
@@ -161,6 +164,7 @@ struct snd_timer_instance *snd_timer_instance_new(const char *owner)
}
INIT_LIST_HEAD(&timeri->open_list);
INIT_LIST_HEAD(&timeri->active_list);
+ INIT_LIST_HEAD(&timeri->master_list);
INIT_LIST_HEAD(&timeri->ack_list);
INIT_LIST_HEAD(&timeri->slave_list_head);
INIT_LIST_HEAD(&timeri->slave_active_head);
@@ -245,6 +249,12 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
return 1;
}
+static bool snd_timer_has_slave_key(const struct snd_timer_instance *timeri)
+{
+ return !(timeri->flags & SNDRV_TIMER_IFLG_SLAVE) &&
+ timeri->slave_class > SNDRV_TIMER_SCLASS_NONE;
+}
+
/*
* look for a master instance matching with the slave id of the given slave.
* when found, relink the open_link of the slave.
@@ -253,19 +263,15 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
*/
static int snd_timer_check_slave(struct snd_timer_instance *slave)
{
- struct snd_timer *timer;
struct snd_timer_instance *master;
int err = 0;
- /* FIXME: it's really dumb to look up all entries.. */
- list_for_each_entry(timer, &snd_timer_list, device_list) {
- list_for_each_entry(master, &timer->open_list_head, open_list) {
- err = check_matching_master_slave(master, slave);
- if (err != 0) /* match found or error */
- goto out;
- }
+ list_for_each_entry(master, &snd_timer_master_list, master_list) {
+ err = check_matching_master_slave(master, slave);
+ if (err != 0) /* match found or error */
+ goto out;
}
- out:
+out:
return err < 0 ? err : 0;
}
@@ -377,6 +383,8 @@ int snd_timer_open(struct snd_timer_instance *timeri,
timeri->slave_id = slave_id;
list_add_tail(&timeri->open_list, &timer->open_list_head);
+ if (snd_timer_has_slave_key(timeri))
+ list_add_tail(&timeri->master_list, &snd_timer_master_list);
timer->num_instances++;
err = snd_timer_check_master(timeri);
list_added:
@@ -431,6 +439,9 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
num_slaves--;
}
+ if (!list_empty(&timeri->master_list))
+ list_del_init(&timeri->master_list);
+
/* force to stop the timer */
snd_timer_stop(timeri);
@@ -930,7 +941,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
}
if (rtimer)
*rtimer = NULL;
- timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+ timer = kzalloc_obj(*timer);
if (!timer)
return -ENOMEM;
timer->tmr_class = tid->dev_class;
@@ -1118,8 +1129,8 @@ struct snd_timer_system_private {
static void snd_timer_s_function(struct timer_list *t)
{
- struct snd_timer_system_private *priv = from_timer(priv, t,
- tlist);
+ struct snd_timer_system_private *priv = timer_container_of(priv, t,
+ tlist);
struct snd_timer *timer = priv->snd_timer;
unsigned long jiff = jiffies;
if (time_after(jiff, priv->last_expires))
@@ -1195,9 +1206,9 @@ static int snd_timer_register_system(void)
err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer);
if (err < 0)
return err;
- strcpy(timer->name, "system timer");
+ strscpy(timer->name, "system timer");
timer->hw = snd_timer_system;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc_obj(*priv);
if (priv == NULL) {
snd_timer_free(timer);
return -ENOMEM;
@@ -1432,11 +1443,11 @@ static int realloc_user_queue(struct snd_timer_user *tu, int size)
struct snd_timer_tread64 *tqueue = NULL;
if (tu->tread) {
- tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL);
+ tqueue = kzalloc_objs(*tqueue, size);
if (!tqueue)
return -ENOMEM;
} else {
- queue = kcalloc(size, sizeof(*queue), GFP_KERNEL);
+ queue = kzalloc_objs(*queue, size);
if (!queue)
return -ENOMEM;
}
@@ -1461,7 +1472,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
if (err < 0)
return err;
- tu = kzalloc(sizeof(*tu), GFP_KERNEL);
+ tu = kzalloc_obj(*tu);
if (tu == NULL)
return -ENOMEM;
spin_lock_init(&tu->qlock);
@@ -1614,12 +1625,12 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
static int snd_timer_user_ginfo(struct file *file,
struct snd_timer_ginfo __user *_ginfo)
{
- struct snd_timer_ginfo *ginfo __free(kfree) = NULL;
struct snd_timer_id tid;
struct snd_timer *t;
struct list_head *p;
+ struct snd_timer_ginfo *ginfo __free(kfree) =
+ memdup_user(_ginfo, sizeof(*ginfo));
- ginfo = memdup_user(_ginfo, sizeof(*ginfo));
if (IS_ERR(ginfo))
return PTR_ERR(ginfo);
@@ -1756,7 +1767,6 @@ static int snd_timer_user_info(struct file *file,
struct snd_timer_info __user *_info)
{
struct snd_timer_user *tu;
- struct snd_timer_info *info __free(kfree) = NULL;
struct snd_timer *t;
tu = file->private_data;
@@ -1766,7 +1776,8 @@ static int snd_timer_user_info(struct file *file,
if (!t)
return -EBADFD;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ struct snd_timer_info *info __free(kfree) =
+ kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
info->card = t->card ? t->card->number : -1;
@@ -2128,7 +2139,7 @@ static int snd_utimer_create(struct snd_timer_uinfo *utimer_info,
if (!utimer_info || utimer_info->resolution == 0)
return -EINVAL;
- utimer = kzalloc(sizeof(*utimer), GFP_KERNEL);
+ utimer = kzalloc_obj(*utimer);
if (!utimer)
return -ENOMEM;
@@ -2139,14 +2150,14 @@ static int snd_utimer_create(struct snd_timer_uinfo *utimer_info,
goto err_take_id;
}
+ utimer->id = utimer_id;
+
utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id);
if (!utimer->name) {
err = -ENOMEM;
goto err_get_name;
}
- utimer->id = utimer_id;
-
tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
tid.card = -1;
@@ -2192,10 +2203,10 @@ static int snd_utimer_ioctl_create(struct file *file,
struct snd_timer_uinfo __user *_utimer_info)
{
struct snd_utimer *utimer;
- struct snd_timer_uinfo *utimer_info __free(kfree) = NULL;
int err, timer_fd;
+ struct snd_timer_uinfo *utimer_info __free(kfree) =
+ memdup_user(_utimer_info, sizeof(*utimer_info));
- utimer_info = memdup_user(_utimer_info, sizeof(*utimer_info));
if (IS_ERR(utimer_info))
return PTR_ERR(utimer_info);
diff --git a/sound/core/ump.c b/sound/core/ump.c
index 8d8681a42ca5..70520c7ca293 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -166,7 +166,7 @@ int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
if (input && output)
info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
- ump = kzalloc(sizeof(*ump), GFP_KERNEL);
+ ump = kzalloc_obj(*ump);
if (!ump)
return -ENOMEM;
INIT_LIST_HEAD(&ump->block_list);
@@ -408,7 +408,7 @@ int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
if (snd_ump_get_block(ump, blk))
return -EBUSY;
- fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+ fb = kzalloc_obj(*fb);
if (!fb)
return -ENOMEM;
@@ -1352,8 +1352,7 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
bool input, output;
int err, num;
- ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS,
- sizeof(*ump->out_cvts), GFP_KERNEL);
+ ump->out_cvts = kzalloc_objs(*ump->out_cvts, SNDRV_UMP_MAX_GROUPS);
if (!ump->out_cvts)
return -ENOMEM;
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index c657659b236c..cd3dcaaf9f72 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -56,10 +56,10 @@ struct link_follower {
static int follower_update(struct link_follower *follower)
{
- struct snd_ctl_elem_value *uctl __free(kfree) = NULL;
int err, ch;
+ struct snd_ctl_elem_value *uctl __free(kfree) =
+ kzalloc_obj(*uctl);
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return -ENOMEM;
uctl->id = follower->follower.id;
@@ -74,7 +74,6 @@ static int follower_update(struct link_follower *follower)
/* get the follower ctl info and save the initial values */
static int follower_init(struct link_follower *follower)
{
- struct snd_ctl_elem_info *uinfo __free(kfree) = NULL;
int err;
if (follower->info.count) {
@@ -84,7 +83,8 @@ static int follower_init(struct link_follower *follower)
return 0;
}
- uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+ struct snd_ctl_elem_info *uinfo __free(kfree) =
+ kmalloc_obj(*uinfo);
if (!uinfo)
return -ENOMEM;
uinfo->id = follower->follower.id;
@@ -256,8 +256,7 @@ int _snd_ctl_add_follower(struct snd_kcontrol *master,
struct link_master *master_link = snd_kcontrol_chip(master);
struct link_follower *srec;
- srec = kzalloc(struct_size(srec, follower.vd, follower->count),
- GFP_KERNEL);
+ srec = kzalloc_flex(*srec, follower.vd, follower->count);
if (!srec)
return -ENOMEM;
srec->kctl = follower;
@@ -341,9 +340,9 @@ static int master_get(struct snd_kcontrol *kcontrol,
static int sync_followers(struct link_master *master, int old_val, int new_val)
{
struct link_follower *follower;
- struct snd_ctl_elem_value *uval __free(kfree) = NULL;
+ struct snd_ctl_elem_value *uval __free(kfree) =
+ kmalloc_obj(*uval);
- uval = kmalloc(sizeof(*uval), GFP_KERNEL);
if (!uval)
return -ENOMEM;
list_for_each_entry(follower, &master->followers, list) {
@@ -430,7 +429,7 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
knew.name = name;
knew.info = master_info;
- master = kzalloc(sizeof(*master), GFP_KERNEL);
+ master = kzalloc_obj(*master);
if (!master)
return NULL;
INIT_LIST_HEAD(&master->followers);