Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

ALSA: hda - Fix memory leak and error handling in CA0132 DSP loader



This patch fixes a few obvious bugs in DSP loader stuff:
- Fix possible memory leaks in the error path
- Avoid double-free calls in dma_reset()
- Properly set/unset WC bits for DMA buffers
- Add missing error status checks

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 6d67530e
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -2628,8 +2628,9 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
				  snd_dma_pci_data(chip->pci),
				  byte_size, bufp);
	if (err < 0)
		goto error;
		goto unlock;

	mark_pages_wc(chip, bufp, true);
	azx_dev = azx_get_dsp_loader_dev(chip);
	azx_dev->bufsize = byte_size;
	azx_dev->period_bytes = byte_size;
@@ -2651,6 +2652,9 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
	return azx_dev->stream_tag;

 error:
	mark_pages_wc(chip, bufp, false);
	snd_dma_free_pages(bufp);
unlock:
	snd_hda_unlock_devices(bus);
	return err;
}
@@ -2673,6 +2677,9 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
	struct azx *chip = bus->private_data;
	struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);

	if (!dmab->area)
		return;

	/* reset BDL address */
	azx_sd_writel(azx_dev, SD_BDLPL, 0);
	azx_sd_writel(azx_dev, SD_BDLPU, 0);
@@ -2681,7 +2688,9 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
	azx_dev->period_bytes = 0;
	azx_dev->format_val = 0;

	mark_pages_wc(chip, dmab, false);
	snd_dma_free_pages(dmab);
	dmab->area = NULL;

	snd_hda_unlock_devices(bus);
}
+7 −3
Original line number Diff line number Diff line
@@ -2065,7 +2065,7 @@ static int dma_reset(struct dma_engine *dma)
	struct ca0132_spec *spec = codec->spec;
	int status;

	if (dma->dmab)
	if (dma->dmab->area)
		snd_hda_codec_load_dsp_cleanup(codec, dma->dmab);

	status = snd_hda_codec_load_dsp_prepare(codec,
@@ -2357,10 +2357,14 @@ static int dspxfr_one_seg(struct hda_codec *codec,
						chip_addx_remainder,
						data_remainder,
						remainder_words);
			if (status < 0)
				return status;
			remainder_words = 0;
		}
		if (hci_write) {
			status = dspxfr_hci_write(codec, hci_write);
			if (status < 0)
				return status;
			hci_write = NULL;
		}

@@ -2376,7 +2380,7 @@ static int dspxfr_one_seg(struct hda_codec *codec,

		snd_printdd(KERN_INFO "+++++ DMA complete");
		dma_set_state(dma_engine, DMA_STATE_STOP);
		dma_reset(dma_engine);
		status = dma_reset(dma_engine);

		if (status < 0)
			return status;
@@ -2517,7 +2521,7 @@ static int dspxfr_image(struct hda_codec *codec,
	if (ovly && (dma_chan != INVALID_DMA_CHANNEL))
		dspio_free_dma_chan(codec, dma_chan);

	if (dma_engine->dmab)
	if (dma_engine->dmab->area)
		snd_hda_codec_load_dsp_cleanup(codec, dma_engine->dmab);
	kfree(dma_engine->dmab);
	kfree(dma_engine);