|
@@ -942,31 +942,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
|
|
|
unsigned long flags;
|
|
|
long result = 0, count1;
|
|
|
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
+ unsigned long appl_ptr;
|
|
|
|
|
|
+ spin_lock_irqsave(&runtime->lock, flags);
|
|
|
while (count > 0 && runtime->avail) {
|
|
|
count1 = runtime->buffer_size - runtime->appl_ptr;
|
|
|
if (count1 > count)
|
|
|
count1 = count;
|
|
|
- spin_lock_irqsave(&runtime->lock, flags);
|
|
|
if (count1 > (int)runtime->avail)
|
|
|
count1 = runtime->avail;
|
|
|
+
|
|
|
+ /* update runtime->appl_ptr before unlocking for userbuf */
|
|
|
+ appl_ptr = runtime->appl_ptr;
|
|
|
+ runtime->appl_ptr += count1;
|
|
|
+ runtime->appl_ptr %= runtime->buffer_size;
|
|
|
+ runtime->avail -= count1;
|
|
|
+
|
|
|
if (kernelbuf)
|
|
|
- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
|
|
|
+ memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
|
|
|
if (userbuf) {
|
|
|
spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
if (copy_to_user(userbuf + result,
|
|
|
- runtime->buffer + runtime->appl_ptr, count1)) {
|
|
|
+ runtime->buffer + appl_ptr, count1)) {
|
|
|
return result > 0 ? result : -EFAULT;
|
|
|
}
|
|
|
spin_lock_irqsave(&runtime->lock, flags);
|
|
|
}
|
|
|
- runtime->appl_ptr += count1;
|
|
|
- runtime->appl_ptr %= runtime->buffer_size;
|
|
|
- runtime->avail -= count1;
|
|
|
- spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
result += count1;
|
|
|
count -= count1;
|
|
|
}
|
|
|
+ spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -1223,6 +1228,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
|
|
unsigned long flags;
|
|
|
long count1, result;
|
|
|
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
+ unsigned long appl_ptr;
|
|
|
|
|
|
if (!kernelbuf && !userbuf)
|
|
|
return -EINVAL;
|
|
@@ -1243,12 +1249,19 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
|
|
count1 = count;
|
|
|
if (count1 > (long)runtime->avail)
|
|
|
count1 = runtime->avail;
|
|
|
+
|
|
|
+ /* update runtime->appl_ptr before unlocking for userbuf */
|
|
|
+ appl_ptr = runtime->appl_ptr;
|
|
|
+ runtime->appl_ptr += count1;
|
|
|
+ runtime->appl_ptr %= runtime->buffer_size;
|
|
|
+ runtime->avail -= count1;
|
|
|
+
|
|
|
if (kernelbuf)
|
|
|
- memcpy(runtime->buffer + runtime->appl_ptr,
|
|
|
+ memcpy(runtime->buffer + appl_ptr,
|
|
|
kernelbuf + result, count1);
|
|
|
else if (userbuf) {
|
|
|
spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
- if (copy_from_user(runtime->buffer + runtime->appl_ptr,
|
|
|
+ if (copy_from_user(runtime->buffer + appl_ptr,
|
|
|
userbuf + result, count1)) {
|
|
|
spin_lock_irqsave(&runtime->lock, flags);
|
|
|
result = result > 0 ? result : -EFAULT;
|
|
@@ -1256,9 +1269,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
|
|
}
|
|
|
spin_lock_irqsave(&runtime->lock, flags);
|
|
|
}
|
|
|
- runtime->appl_ptr += count1;
|
|
|
- runtime->appl_ptr %= runtime->buffer_size;
|
|
|
- runtime->avail -= count1;
|
|
|
result += count1;
|
|
|
count -= count1;
|
|
|
}
|