Commit 9001b8e4 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 705d43db 67ec1072
......@@ -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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment