sound fixes for 4.5-rc5
this update contains again a few more fixes for ALSA core stuff although it's no longer high flux: two race fixes in sequencer and one PCM race fix for non-atomic PCM ops. In addition, HD-audio gained a similar fix for race at reloading the driver. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJWxvBBAAoJEGwxgFQ9KSmk2RoQALqPcE1WomF9KoCTRDQ0+V2V CDQFBDZsrlBPNH0p5tiVOWdzk8tsKh/asF5JO83g5RmIBd3MP06MJYdMnbEa7xVE 77WykgGT3onmiY7fka4ufNysm0LGdPNjaPvdOmzrrU0z3+JdrffuWPT2nnd6znDF aZH3sx/Hy+Hl7nrfhG+xh08OAQJNK9ro6ZrEzQFAdhZMUoWTAlI0cV6fTxdnMLVf DV9lYT4TMfCijHAu+ujPoP5TihgQ2215RvQa4GCERX2vmoXK7yPfDB6Kbkh7uQhl HW8blEKHKfrEOElmg/VKUKaa1W7Of+n3m1eFrBgPiDfUEzpBM4U0Bp3dr/097rnk v2arIBQQcu/V3yInID8BxQAH9Rq4P+wS8UREBXws5AEe0OSyMsYheVmkPOJoBSST uudqKSf876qqC2+ze7R90rUF91UNiWJNyraynUPPgXO5IXMpUbt6H8oucICU+vys eaIl/sl0n0fB3XUcMLXKGySgXxeKUGKqWPNga5v2YLdyFLhtd3uHJFuoq7vy8as2 vzjq/sd87R2VUCxN907UKdhQkvXuhIXs5I6ugc7Wwv+RHv9dhLNs+zB8yOnA+iFT T6tMX0M/5lgJ+s8DH9mLUxZWb8cUjLWU0llVedBuicFAilnujIkw4Gc+3RKcf3h0 Hj/sHiss0F9q0XhPI5gI =u/fj -----END PGP SIGNATURE----- Merge tag 'sound-4.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "This update contains again a few more fixes for ALSA core stuff although it's no longer high flux: two race fixes in sequencer and one PCM race fix for non-atomic PCM ops. In addition, HD-audio gained a similar fix for race at reloading the driver" * tag 'sound-4.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: pcm: Fix rwsem deadlock for non-atomic PCM stream ALSA: seq: Fix double port list deletion ALSA: hda - Cancel probe work instead of flush at remove ALSA: seq: Fix leak of pool buffer at concurrent writes
This commit is contained in:
commit
9001b8e4f0
|
@ -74,6 +74,18 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
|
|||
static DEFINE_RWLOCK(snd_pcm_link_rwlock);
|
||||
static DECLARE_RWSEM(snd_pcm_link_rwsem);
|
||||
|
||||
/* Writer in rwsem may block readers even during its waiting in queue,
|
||||
* and this may lead to a deadlock when the code path takes read sem
|
||||
* twice (e.g. one in snd_pcm_action_nonatomic() and another in
|
||||
* snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
|
||||
* spin until it gets the lock.
|
||||
*/
|
||||
static inline void down_write_nonblock(struct rw_semaphore *lock)
|
||||
{
|
||||
while (!down_write_trylock(lock))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_pcm_stream_lock - Lock the PCM stream
|
||||
* @substream: PCM substream
|
||||
|
@ -1813,7 +1825,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
|||
res = -ENOMEM;
|
||||
goto _nolock;
|
||||
}
|
||||
down_write(&snd_pcm_link_rwsem);
|
||||
down_write_nonblock(&snd_pcm_link_rwsem);
|
||||
write_lock_irq(&snd_pcm_link_rwlock);
|
||||
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
|
||||
substream->runtime->status->state != substream1->runtime->status->state ||
|
||||
|
@ -1860,7 +1872,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
|
|||
struct snd_pcm_substream *s;
|
||||
int res = 0;
|
||||
|
||||
down_write(&snd_pcm_link_rwsem);
|
||||
down_write_nonblock(&snd_pcm_link_rwsem);
|
||||
write_lock_irq(&snd_pcm_link_rwlock);
|
||||
if (!snd_pcm_stream_linked(substream)) {
|
||||
res = -EALREADY;
|
||||
|
|
|
@ -383,15 +383,20 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
|
|||
|
||||
if (snd_BUG_ON(!pool))
|
||||
return -EINVAL;
|
||||
if (pool->ptr) /* should be atomic? */
|
||||
return 0;
|
||||
|
||||
pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
|
||||
if (!pool->ptr)
|
||||
cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
|
||||
if (!cellptr)
|
||||
return -ENOMEM;
|
||||
|
||||
/* add new cells to the free cell list */
|
||||
spin_lock_irqsave(&pool->lock, flags);
|
||||
if (pool->ptr) {
|
||||
spin_unlock_irqrestore(&pool->lock, flags);
|
||||
vfree(cellptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pool->ptr = cellptr;
|
||||
pool->free = NULL;
|
||||
|
||||
for (cell = 0; cell < pool->size; cell++) {
|
||||
|
|
|
@ -535,19 +535,22 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
|||
bool is_src, bool ack)
|
||||
{
|
||||
struct snd_seq_port_subs_info *grp;
|
||||
struct list_head *list;
|
||||
bool empty;
|
||||
|
||||
grp = is_src ? &port->c_src : &port->c_dest;
|
||||
list = is_src ? &subs->src_list : &subs->dest_list;
|
||||
down_write(&grp->list_mutex);
|
||||
write_lock_irq(&grp->list_lock);
|
||||
if (is_src)
|
||||
list_del(&subs->src_list);
|
||||
else
|
||||
list_del(&subs->dest_list);
|
||||
empty = list_empty(list);
|
||||
if (!empty)
|
||||
list_del_init(list);
|
||||
grp->exclusive = 0;
|
||||
write_unlock_irq(&grp->list_lock);
|
||||
up_write(&grp->list_mutex);
|
||||
|
||||
unsubscribe_port(client, port, grp, &subs->info, ack);
|
||||
if (!empty)
|
||||
unsubscribe_port(client, port, grp, &subs->info, ack);
|
||||
}
|
||||
|
||||
/* connect two ports */
|
||||
|
|
|
@ -2168,10 +2168,10 @@ static void azx_remove(struct pci_dev *pci)
|
|||
struct hda_intel *hda;
|
||||
|
||||
if (card) {
|
||||
/* flush the pending probing work */
|
||||
/* cancel the pending probing work */
|
||||
chip = card->private_data;
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
flush_work(&hda->probe_work);
|
||||
cancel_work_sync(&hda->probe_work);
|
||||
|
||||
snd_card_free(card);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue