Skip to content

Commit 2e5dc73

Browse files
committed
Merge branch 'topic/core-fixes' into for-linus
2 parents 2154cc0 + 7f0973e commit 2e5dc73

File tree

5 files changed

+243
-146
lines changed

5 files changed

+243
-146
lines changed

include/sound/rawmidi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
167167
int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
168168
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
169169
unsigned char *buffer, int count);
170+
int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
171+
unsigned char *buffer, int count);
172+
int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
173+
int count);
170174

171175
/* main midi functions */
172176

sound/core/rawmidi.c

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -942,31 +942,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
942942
unsigned long flags;
943943
long result = 0, count1;
944944
struct snd_rawmidi_runtime *runtime = substream->runtime;
945+
unsigned long appl_ptr;
945946

947+
spin_lock_irqsave(&runtime->lock, flags);
946948
while (count > 0 && runtime->avail) {
947949
count1 = runtime->buffer_size - runtime->appl_ptr;
948950
if (count1 > count)
949951
count1 = count;
950-
spin_lock_irqsave(&runtime->lock, flags);
951952
if (count1 > (int)runtime->avail)
952953
count1 = runtime->avail;
954+
955+
/* update runtime->appl_ptr before unlocking for userbuf */
956+
appl_ptr = runtime->appl_ptr;
957+
runtime->appl_ptr += count1;
958+
runtime->appl_ptr %= runtime->buffer_size;
959+
runtime->avail -= count1;
960+
953961
if (kernelbuf)
954-
memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
962+
memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
955963
if (userbuf) {
956964
spin_unlock_irqrestore(&runtime->lock, flags);
957965
if (copy_to_user(userbuf + result,
958-
runtime->buffer + runtime->appl_ptr, count1)) {
966+
runtime->buffer + appl_ptr, count1)) {
959967
return result > 0 ? result : -EFAULT;
960968
}
961969
spin_lock_irqsave(&runtime->lock, flags);
962970
}
963-
runtime->appl_ptr += count1;
964-
runtime->appl_ptr %= runtime->buffer_size;
965-
runtime->avail -= count1;
966-
spin_unlock_irqrestore(&runtime->lock, flags);
967971
result += count1;
968972
count -= count1;
969973
}
974+
spin_unlock_irqrestore(&runtime->lock, flags);
970975
return result;
971976
}
972977

@@ -1055,23 +1060,16 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
10551060
EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
10561061

10571062
/**
1058-
* snd_rawmidi_transmit_peek - copy data from the internal buffer
1063+
* __snd_rawmidi_transmit_peek - copy data from the internal buffer
10591064
* @substream: the rawmidi substream
10601065
* @buffer: the buffer pointer
10611066
* @count: data size to transfer
10621067
*
1063-
* Copies data from the internal output buffer to the given buffer.
1064-
*
1065-
* Call this in the interrupt handler when the midi output is ready,
1066-
* and call snd_rawmidi_transmit_ack() after the transmission is
1067-
* finished.
1068-
*
1069-
* Return: The size of copied data, or a negative error code on failure.
1068+
* This is a variant of snd_rawmidi_transmit_peek() without spinlock.
10701069
*/
1071-
int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
1070+
int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
10721071
unsigned char *buffer, int count)
10731072
{
1074-
unsigned long flags;
10751073
int result, count1;
10761074
struct snd_rawmidi_runtime *runtime = substream->runtime;
10771075

@@ -1081,7 +1079,6 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
10811079
return -EINVAL;
10821080
}
10831081
result = 0;
1084-
spin_lock_irqsave(&runtime->lock, flags);
10851082
if (runtime->avail >= runtime->buffer_size) {
10861083
/* warning: lowlevel layer MUST trigger down the hardware */
10871084
goto __skip;
@@ -1106,33 +1103,54 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
11061103
}
11071104
}
11081105
__skip:
1106+
return result;
1107+
}
1108+
EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
1109+
1110+
/**
1111+
* snd_rawmidi_transmit_peek - copy data from the internal buffer
1112+
* @substream: the rawmidi substream
1113+
* @buffer: the buffer pointer
1114+
* @count: data size to transfer
1115+
*
1116+
* Copies data from the internal output buffer to the given buffer.
1117+
*
1118+
* Call this in the interrupt handler when the midi output is ready,
1119+
* and call snd_rawmidi_transmit_ack() after the transmission is
1120+
* finished.
1121+
*
1122+
* Return: The size of copied data, or a negative error code on failure.
1123+
*/
1124+
int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
1125+
unsigned char *buffer, int count)
1126+
{
1127+
struct snd_rawmidi_runtime *runtime = substream->runtime;
1128+
int result;
1129+
unsigned long flags;
1130+
1131+
spin_lock_irqsave(&runtime->lock, flags);
1132+
result = __snd_rawmidi_transmit_peek(substream, buffer, count);
11091133
spin_unlock_irqrestore(&runtime->lock, flags);
11101134
return result;
11111135
}
11121136
EXPORT_SYMBOL(snd_rawmidi_transmit_peek);
11131137

11141138
/**
1115-
* snd_rawmidi_transmit_ack - acknowledge the transmission
1139+
* __snd_rawmidi_transmit_ack - acknowledge the transmission
11161140
* @substream: the rawmidi substream
11171141
* @count: the transferred count
11181142
*
1119-
* Advances the hardware pointer for the internal output buffer with
1120-
* the given size and updates the condition.
1121-
* Call after the transmission is finished.
1122-
*
1123-
* Return: The advanced size if successful, or a negative error code on failure.
1143+
* This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
11241144
*/
1125-
int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
1145+
int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
11261146
{
1127-
unsigned long flags;
11281147
struct snd_rawmidi_runtime *runtime = substream->runtime;
11291148

11301149
if (runtime->buffer == NULL) {
11311150
rmidi_dbg(substream->rmidi,
11321151
"snd_rawmidi_transmit_ack: output is not active!!!\n");
11331152
return -EINVAL;
11341153
}
1135-
spin_lock_irqsave(&runtime->lock, flags);
11361154
snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
11371155
runtime->hw_ptr += count;
11381156
runtime->hw_ptr %= runtime->buffer_size;
@@ -1142,9 +1160,32 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
11421160
if (runtime->drain || snd_rawmidi_ready(substream))
11431161
wake_up(&runtime->sleep);
11441162
}
1145-
spin_unlock_irqrestore(&runtime->lock, flags);
11461163
return count;
11471164
}
1165+
EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
1166+
1167+
/**
1168+
* snd_rawmidi_transmit_ack - acknowledge the transmission
1169+
* @substream: the rawmidi substream
1170+
* @count: the transferred count
1171+
*
1172+
* Advances the hardware pointer for the internal output buffer with
1173+
* the given size and updates the condition.
1174+
* Call after the transmission is finished.
1175+
*
1176+
* Return: The advanced size if successful, or a negative error code on failure.
1177+
*/
1178+
int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
1179+
{
1180+
struct snd_rawmidi_runtime *runtime = substream->runtime;
1181+
int result;
1182+
unsigned long flags;
1183+
1184+
spin_lock_irqsave(&runtime->lock, flags);
1185+
result = __snd_rawmidi_transmit_ack(substream, count);
1186+
spin_unlock_irqrestore(&runtime->lock, flags);
1187+
return result;
1188+
}
11481189
EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
11491190

11501191
/**
@@ -1160,12 +1201,22 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
11601201
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
11611202
unsigned char *buffer, int count)
11621203
{
1204+
struct snd_rawmidi_runtime *runtime = substream->runtime;
1205+
int result;
1206+
unsigned long flags;
1207+
1208+
spin_lock_irqsave(&runtime->lock, flags);
11631209
if (!substream->opened)
1164-
return -EBADFD;
1165-
count = snd_rawmidi_transmit_peek(substream, buffer, count);
1166-
if (count < 0)
1167-
return count;
1168-
return snd_rawmidi_transmit_ack(substream, count);
1210+
result = -EBADFD;
1211+
else {
1212+
count = __snd_rawmidi_transmit_peek(substream, buffer, count);
1213+
if (count <= 0)
1214+
result = count;
1215+
else
1216+
result = __snd_rawmidi_transmit_ack(substream, count);
1217+
}
1218+
spin_unlock_irqrestore(&runtime->lock, flags);
1219+
return result;
11691220
}
11701221
EXPORT_SYMBOL(snd_rawmidi_transmit);
11711222

@@ -1177,6 +1228,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
11771228
unsigned long flags;
11781229
long count1, result;
11791230
struct snd_rawmidi_runtime *runtime = substream->runtime;
1231+
unsigned long appl_ptr;
11801232

11811233
if (!kernelbuf && !userbuf)
11821234
return -EINVAL;
@@ -1197,22 +1249,26 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
11971249
count1 = count;
11981250
if (count1 > (long)runtime->avail)
11991251
count1 = runtime->avail;
1252+
1253+
/* update runtime->appl_ptr before unlocking for userbuf */
1254+
appl_ptr = runtime->appl_ptr;
1255+
runtime->appl_ptr += count1;
1256+
runtime->appl_ptr %= runtime->buffer_size;
1257+
runtime->avail -= count1;
1258+
12001259
if (kernelbuf)
1201-
memcpy(runtime->buffer + runtime->appl_ptr,
1260+
memcpy(runtime->buffer + appl_ptr,
12021261
kernelbuf + result, count1);
12031262
else if (userbuf) {
12041263
spin_unlock_irqrestore(&runtime->lock, flags);
1205-
if (copy_from_user(runtime->buffer + runtime->appl_ptr,
1264+
if (copy_from_user(runtime->buffer + appl_ptr,
12061265
userbuf + result, count1)) {
12071266
spin_lock_irqsave(&runtime->lock, flags);
12081267
result = result > 0 ? result : -EFAULT;
12091268
goto __end;
12101269
}
12111270
spin_lock_irqsave(&runtime->lock, flags);
12121271
}
1213-
runtime->appl_ptr += count1;
1214-
runtime->appl_ptr %= runtime->buffer_size;
1215-
runtime->avail -= count1;
12161272
result += count1;
12171273
count -= count1;
12181274
}

sound/core/seq/seq_clientmgr.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
678678
else
679679
down_read(&grp->list_mutex);
680680
list_for_each_entry(subs, &grp->list_head, src_list) {
681+
/* both ports ready? */
682+
if (atomic_read(&subs->ref_count) != 2)
683+
continue;
681684
event->dest = subs->info.dest;
682685
if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
683686
/* convert time according to flag with subscription */

0 commit comments

Comments
 (0)