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: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6d67530e2c
commit
b3667bd757
|
@ -2628,8 +2628,9 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
|
||||||
snd_dma_pci_data(chip->pci),
|
snd_dma_pci_data(chip->pci),
|
||||||
byte_size, bufp);
|
byte_size, bufp);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto unlock;
|
||||||
|
|
||||||
|
mark_pages_wc(chip, bufp, true);
|
||||||
azx_dev = azx_get_dsp_loader_dev(chip);
|
azx_dev = azx_get_dsp_loader_dev(chip);
|
||||||
azx_dev->bufsize = byte_size;
|
azx_dev->bufsize = byte_size;
|
||||||
azx_dev->period_bytes = 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;
|
return azx_dev->stream_tag;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
mark_pages_wc(chip, bufp, false);
|
||||||
|
snd_dma_free_pages(bufp);
|
||||||
|
unlock:
|
||||||
snd_hda_unlock_devices(bus);
|
snd_hda_unlock_devices(bus);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2673,6 +2677,9 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
|
||||||
struct azx *chip = bus->private_data;
|
struct azx *chip = bus->private_data;
|
||||||
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
|
||||||
|
|
||||||
|
if (!dmab->area)
|
||||||
|
return;
|
||||||
|
|
||||||
/* reset BDL address */
|
/* reset BDL address */
|
||||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||||
azx_sd_writel(azx_dev, SD_BDLPU, 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->period_bytes = 0;
|
||||||
azx_dev->format_val = 0;
|
azx_dev->format_val = 0;
|
||||||
|
|
||||||
|
mark_pages_wc(chip, dmab, false);
|
||||||
snd_dma_free_pages(dmab);
|
snd_dma_free_pages(dmab);
|
||||||
|
dmab->area = NULL;
|
||||||
|
|
||||||
snd_hda_unlock_devices(bus);
|
snd_hda_unlock_devices(bus);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2065,7 +2065,7 @@ static int dma_reset(struct dma_engine *dma)
|
||||||
struct ca0132_spec *spec = codec->spec;
|
struct ca0132_spec *spec = codec->spec;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (dma->dmab)
|
if (dma->dmab->area)
|
||||||
snd_hda_codec_load_dsp_cleanup(codec, dma->dmab);
|
snd_hda_codec_load_dsp_cleanup(codec, dma->dmab);
|
||||||
|
|
||||||
status = snd_hda_codec_load_dsp_prepare(codec,
|
status = snd_hda_codec_load_dsp_prepare(codec,
|
||||||
|
@ -2357,10 +2357,14 @@ static int dspxfr_one_seg(struct hda_codec *codec,
|
||||||
chip_addx_remainder,
|
chip_addx_remainder,
|
||||||
data_remainder,
|
data_remainder,
|
||||||
remainder_words);
|
remainder_words);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
remainder_words = 0;
|
remainder_words = 0;
|
||||||
}
|
}
|
||||||
if (hci_write) {
|
if (hci_write) {
|
||||||
status = dspxfr_hci_write(codec, hci_write);
|
status = dspxfr_hci_write(codec, hci_write);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
hci_write = NULL;
|
hci_write = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2376,7 +2380,7 @@ static int dspxfr_one_seg(struct hda_codec *codec,
|
||||||
|
|
||||||
snd_printdd(KERN_INFO "+++++ DMA complete");
|
snd_printdd(KERN_INFO "+++++ DMA complete");
|
||||||
dma_set_state(dma_engine, DMA_STATE_STOP);
|
dma_set_state(dma_engine, DMA_STATE_STOP);
|
||||||
dma_reset(dma_engine);
|
status = dma_reset(dma_engine);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
@ -2517,7 +2521,7 @@ static int dspxfr_image(struct hda_codec *codec,
|
||||||
if (ovly && (dma_chan != INVALID_DMA_CHANNEL))
|
if (ovly && (dma_chan != INVALID_DMA_CHANNEL))
|
||||||
dspio_free_dma_chan(codec, dma_chan);
|
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);
|
snd_hda_codec_load_dsp_cleanup(codec, dma_engine->dmab);
|
||||||
kfree(dma_engine->dmab);
|
kfree(dma_engine->dmab);
|
||||||
kfree(dma_engine);
|
kfree(dma_engine);
|
||||||
|
|
Loading…
Reference in New Issue