|
Takashi Iwai |
0db6b6 |
From c1f0616124c455c5c762b6f123e40bba5df759e6 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
0db6b6 |
From: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
0db6b6 |
Date: Sun, 16 May 2021 18:17:55 +0200
|
|
Takashi Iwai |
0db6b6 |
Subject: [PATCH] ALSA: intel8x0: Don't update period unless prepared
|
|
Takashi Iwai |
0db6b6 |
Git-commit: c1f0616124c455c5c762b6f123e40bba5df759e6
|
|
Takashi Iwai |
0db6b6 |
Patch-mainline: v5.13-rc3
|
|
Takashi Iwai |
0db6b6 |
References: git-fixes
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
The interrupt handler of intel8x0 calls snd_intel8x0_update() whenever
|
|
Takashi Iwai |
0db6b6 |
the hardware sets the corresponding status bit for each stream. This
|
|
Takashi Iwai |
0db6b6 |
works fine for most cases as long as the hardware behaves properly.
|
|
Takashi Iwai |
0db6b6 |
But when the hardware gives a wrong bit set, this leads to a zero-
|
|
Takashi Iwai |
0db6b6 |
division Oops, and reportedly, this seems what happened on a VM.
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
For fixing the crash, this patch adds a internal flag indicating that
|
|
Takashi Iwai |
0db6b6 |
the stream is ready to be updated, and check it (as well as the flag
|
|
Takashi Iwai |
0db6b6 |
being in suspended) to ignore such spurious update.
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
Cc: <stable@vger.kernel.org>
|
|
Takashi Iwai |
0db6b6 |
Reported-and-tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
|
|
Takashi Iwai |
0db6b6 |
Link: https://lore.kernel.org/r/s5h5yzi7uh0.wl-tiwai@suse.de
|
|
Takashi Iwai |
0db6b6 |
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
---
|
|
Takashi Iwai |
0db6b6 |
sound/pci/intel8x0.c | 7 +++++++
|
|
Takashi Iwai |
0db6b6 |
1 file changed, 7 insertions(+)
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
--- a/sound/pci/intel8x0.c
|
|
Takashi Iwai |
0db6b6 |
+++ b/sound/pci/intel8x0.c
|
|
Takashi Iwai |
0db6b6 |
@@ -354,6 +354,7 @@ struct ichdev {
|
|
Takashi Iwai |
0db6b6 |
unsigned int ali_slot; /* ALI DMA slot */
|
|
Takashi Iwai |
0db6b6 |
struct ac97_pcm *pcm;
|
|
Takashi Iwai |
0db6b6 |
int pcm_open_flag;
|
|
Takashi Iwai |
0db6b6 |
+ unsigned int prepared:1;
|
|
Takashi Iwai |
0db6b6 |
unsigned int suspended: 1;
|
|
Takashi Iwai |
0db6b6 |
};
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
@@ -714,6 +715,9 @@ static inline void snd_intel8x0_update(s
|
|
Takashi Iwai |
0db6b6 |
int status, civ, i, step;
|
|
Takashi Iwai |
0db6b6 |
int ack = 0;
|
|
Takashi Iwai |
0db6b6 |
|
|
Takashi Iwai |
0db6b6 |
+ if (!ichdev->prepared || ichdev->suspended)
|
|
Takashi Iwai |
0db6b6 |
+ return;
|
|
Takashi Iwai |
0db6b6 |
+
|
|
Takashi Iwai |
0db6b6 |
spin_lock_irqsave(&chip->reg_lock, flags);
|
|
Takashi Iwai |
0db6b6 |
status = igetbyte(chip, port + ichdev->roff_sr);
|
|
Takashi Iwai |
0db6b6 |
civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
|
|
Takashi Iwai |
0db6b6 |
@@ -907,6 +911,7 @@ static int snd_intel8x0_hw_params(struct
|
|
Takashi Iwai |
0db6b6 |
if (ichdev->pcm_open_flag) {
|
|
Takashi Iwai |
0db6b6 |
snd_ac97_pcm_close(ichdev->pcm);
|
|
Takashi Iwai |
0db6b6 |
ichdev->pcm_open_flag = 0;
|
|
Takashi Iwai |
0db6b6 |
+ ichdev->prepared = 0;
|
|
Takashi Iwai |
0db6b6 |
}
|
|
Takashi Iwai |
0db6b6 |
err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
|
|
Takashi Iwai |
0db6b6 |
params_channels(hw_params),
|
|
Takashi Iwai |
0db6b6 |
@@ -928,6 +933,7 @@ static int snd_intel8x0_hw_free(struct s
|
|
Takashi Iwai |
0db6b6 |
if (ichdev->pcm_open_flag) {
|
|
Takashi Iwai |
0db6b6 |
snd_ac97_pcm_close(ichdev->pcm);
|
|
Takashi Iwai |
0db6b6 |
ichdev->pcm_open_flag = 0;
|
|
Takashi Iwai |
0db6b6 |
+ ichdev->prepared = 0;
|
|
Takashi Iwai |
0db6b6 |
}
|
|
Takashi Iwai |
0db6b6 |
return snd_pcm_lib_free_pages(substream);
|
|
Takashi Iwai |
0db6b6 |
}
|
|
Takashi Iwai |
0db6b6 |
@@ -1002,6 +1008,7 @@ static int snd_intel8x0_pcm_prepare(stru
|
|
Takashi Iwai |
0db6b6 |
ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
|
|
Takashi Iwai |
0db6b6 |
}
|
|
Takashi Iwai |
0db6b6 |
snd_intel8x0_setup_periods(chip, ichdev);
|
|
Takashi Iwai |
0db6b6 |
+ ichdev->prepared = 1;
|
|
Takashi Iwai |
0db6b6 |
return 0;
|
|
Takashi Iwai |
0db6b6 |
}
|
|
Takashi Iwai |
0db6b6 |
|