Commit c77a6edb authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: x86: Fix potential crash at error path



When LPE audio driver gets some error at probing, it may lead to a
crash because of canceling the pending work in hdmi_lpe_audio_free(),
since some of ports might be still not initialized.

For assuring the proper free of each port, initialize all ports at the
beginning of the probe.

Fixes: b4eb0d52 ("ALSA: x86: Split snd_intelhad into card and PCM specific structures")
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 35014406
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -1751,6 +1751,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
{
	struct snd_card *card;
	struct snd_intelhad_card *card_ctx;
	struct snd_intelhad *ctx;
	struct snd_pcm *pcm;
	struct intel_hdmi_lpe_audio_pdata *pdata;
	int irq;
@@ -1795,6 +1796,21 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, card_ctx);

	card_ctx->num_pipes = pdata->num_pipes;
	card_ctx->num_ports = single_port ? 1 : pdata->num_ports;

	for_each_port(card_ctx, port) {
		ctx = &card_ctx->pcm_ctx[port];
		ctx->card_ctx = card_ctx;
		ctx->dev = card_ctx->dev;
		ctx->port = single_port ? -1 : port;
		ctx->pipe = -1;

		spin_lock_init(&ctx->had_spinlock);
		mutex_init(&ctx->mutex);
		INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
	}

	dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n",
		__func__, (unsigned int)res_mmio->start,
		(unsigned int)res_mmio->end);
@@ -1827,18 +1843,9 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
	card_ctx->num_ports = single_port ? 1 : pdata->num_ports;

	for_each_port(card_ctx, port) {
		struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
		int i;

		ctx->card_ctx = card_ctx;
		ctx->dev = card_ctx->dev;
		ctx->port = single_port ? -1 : port;
		ctx->pipe = -1;

		spin_lock_init(&ctx->had_spinlock);
		mutex_init(&ctx->mutex);
		INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);

		ctx = &card_ctx->pcm_ctx[port];
		ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
				  MAX_CAP_STREAMS, &pcm);
		if (ret)