Skip to content

Commit

Permalink
ALSA: rawmidi: Undo my 3.18.117 resolution
Browse files Browse the repository at this point in the history
This reverts commit bfa30d8 ("ALSA: rawmidi: Change resized buffers
atomically") in favor of commit b68f2a9 ("ANDROID: sound: rawmidi:
Hold lock around realloc").

This matches Qualcomm's resolution in 4.4: https://source.codeaurora.org/quic/la/kernel/msm-4.4/commit/?id=facb909e66d37224f564750e8ebc693b91934ec6

Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Signed-off-by: khusika <khusikadhamar@gmail.com>
  • Loading branch information
nathanchance authored and khusika committed Sep 10, 2018
1 parent 3272d43 commit 395aea6
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 15 deletions.
1 change: 1 addition & 0 deletions include/sound/rawmidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct snd_rawmidi_runtime {
size_t xruns; /* over/underruns counter */
/* misc */
spinlock_t lock;
struct mutex realloc_mutex;
wait_queue_head_t sleep;
/* event handler (new bytes, input only) */
void (*event)(struct snd_rawmidi_substream *substream);
Expand Down
56 changes: 41 additions & 15 deletions sound/core/rawmidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
return -ENOMEM;
runtime->substream = substream;
spin_lock_init(&runtime->lock);
mutex_init(&runtime->realloc_mutex);
init_waitqueue_head(&runtime->sleep);
INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
runtime->event = NULL;
Expand Down Expand Up @@ -645,9 +646,11 @@ static int snd_rawmidi_info_select_user(struct snd_card *card,
int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_params * params)
{
char *newbuf, *oldbuf;
char *newbuf;
char *oldbuf;
struct snd_rawmidi_runtime *runtime = substream->runtime;

unsigned long flags;

if (substream->append && substream->use_count > 1)
return -EBUSY;
snd_rawmidi_drain_output(substream);
Expand All @@ -658,17 +661,22 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
if (!newbuf)
mutex_lock(&runtime->realloc_mutex);
newbuf = __krealloc(runtime->buffer, params->buffer_size,
GFP_KERNEL);
if (!newbuf) {
mutex_unlock(&runtime->realloc_mutex);
return -ENOMEM;
spin_lock_irq(&runtime->lock);
}
spin_lock_irqsave(&runtime->lock, flags);
oldbuf = runtime->buffer;
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
runtime->avail = runtime->buffer_size;
runtime->appl_ptr = runtime->hw_ptr = 0;
spin_unlock_irq(&runtime->lock);
kfree(oldbuf);
spin_unlock_irqrestore(&runtime->lock, flags);
if (oldbuf != newbuf)
kfree(oldbuf);
mutex_unlock(&runtime->realloc_mutex);
}
runtime->avail_min = params->avail_min;
substream->active_sensing = !params->no_active_sensing;
Expand All @@ -679,8 +687,10 @@ EXPORT_SYMBOL(snd_rawmidi_output_params);
int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_params * params)
{
char *newbuf, *oldbuf;
char *newbuf;
char *oldbuf;
struct snd_rawmidi_runtime *runtime = substream->runtime;
unsigned long flags;

snd_rawmidi_drain_input(substream);
if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
Expand All @@ -690,16 +700,21 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
if (!newbuf)
mutex_lock(&runtime->realloc_mutex);
newbuf = __krealloc(runtime->buffer, params->buffer_size,
GFP_KERNEL);
if (!newbuf) {
mutex_unlock(&runtime->realloc_mutex);
return -ENOMEM;
spin_lock_irq(&runtime->lock);
}
spin_lock_irqsave(&runtime->lock, flags);
oldbuf = runtime->buffer;
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
runtime->appl_ptr = runtime->hw_ptr = 0;
spin_unlock_irq(&runtime->lock);
kfree(oldbuf);
spin_unlock_irqrestore(&runtime->lock, flags);
if (oldbuf != newbuf)
kfree(oldbuf);
mutex_unlock(&runtime->realloc_mutex);
}
runtime->avail_min = params->avail_min;
return 0;
Expand Down Expand Up @@ -971,6 +986,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_runtime *runtime = substream->runtime;
unsigned long appl_ptr;

if (userbuf)
mutex_lock(&runtime->realloc_mutex);
spin_lock_irqsave(&runtime->lock, flags);
while (count > 0 && runtime->avail) {
count1 = runtime->buffer_size - runtime->appl_ptr;
Expand All @@ -991,6 +1008,7 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_to_user(userbuf + result,
runtime->buffer + appl_ptr, count1)) {
mutex_unlock(&runtime->realloc_mutex);
return result > 0 ? result : -EFAULT;
}
spin_lock_irqsave(&runtime->lock, flags);
Expand All @@ -999,6 +1017,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
count -= count1;
}
spin_unlock_irqrestore(&runtime->lock, flags);
if (userbuf)
mutex_unlock(&runtime->realloc_mutex);
return result;
}

Expand Down Expand Up @@ -1263,10 +1283,14 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
return -EINVAL;

result = 0;
if (userbuf)
mutex_lock(&runtime->realloc_mutex);
spin_lock_irqsave(&runtime->lock, flags);
if (substream->append) {
if ((long)runtime->avail < count) {
spin_unlock_irqrestore(&runtime->lock, flags);
if (userbuf)
mutex_unlock(&runtime->realloc_mutex);
return -EAGAIN;
}
}
Expand Down Expand Up @@ -1302,6 +1326,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
__end:
count1 = runtime->avail < runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
if (userbuf)
mutex_unlock(&runtime->realloc_mutex);
if (count1)
snd_rawmidi_output_trigger(substream, 1);
return result;
Expand Down

0 comments on commit 395aea6

Please sign in to comment.