From d5cf9911988287e819ce98ccd9f61ca82fbc90c6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Oct 2011 10:07:58 +0200 Subject: [PATCH] ALSA: hda - Distinguish each substream for better sticky assignment The commit ef18beded8ddbaafdf4914bab209f77e60ae3a18 introduced a mechanism to assign the previously used slot for the next reopen of a PCM stream. But the PCM device number isn't always unique (it may have multiple substreams), and also the code doesn't check the stream direction, thus both playback and capture streams share the same device number. For avoiding this conflict, make a unique key for each substream and store/check this value at reopening. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 8a5dc574b65..90713f0b526 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -381,7 +381,7 @@ struct azx_dev { */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */ - int device; /* last device number assigned to */ + int assigned_key; /* last device# key assigned to */ unsigned int opened :1; unsigned int running :1; @@ -1613,6 +1613,9 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) { int dev, i, nums; struct azx_dev *res = NULL; + /* make a non-zero unique key for the substream */ + int key = (substream->pcm->device << 16) | (substream->number << 2) | + (substream->stream + 1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev = chip->playback_index_offset; @@ -1624,12 +1627,12 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) for (i = 0; i < nums; i++, dev++) if (!chip->azx_dev[dev].opened) { res = &chip->azx_dev[dev]; - if (res->device == substream->pcm->device) + if (res->assigned_key == key) break; } if (res) { res->opened = 1; - res->device = substream->pcm->device; + res->assigned_key = key; } return res; }