diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-02-10 05:58:40 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-02-10 05:58:40 -0500 |
commit | b3667bd7579e6d4dfe709315f13cff9bc9ee9053 (patch) | |
tree | 6edfef15c2a1598de92c6fff7f17700ffb4ec53c /sound/pci/hda/patch_ca0132.c | |
parent | 6d67530e2c73e375b9204eba10ee2d589ba353ae (diff) |
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>
Diffstat (limited to 'sound/pci/hda/patch_ca0132.c')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 710dae81fc8e..fb7a32e730af 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -2065,7 +2065,7 @@ static int dma_reset(struct dma_engine *dma) | |||
2065 | struct ca0132_spec *spec = codec->spec; | 2065 | struct ca0132_spec *spec = codec->spec; |
2066 | int status; | 2066 | int status; |
2067 | 2067 | ||
2068 | if (dma->dmab) | 2068 | if (dma->dmab->area) |
2069 | snd_hda_codec_load_dsp_cleanup(codec, dma->dmab); | 2069 | snd_hda_codec_load_dsp_cleanup(codec, dma->dmab); |
2070 | 2070 | ||
2071 | status = snd_hda_codec_load_dsp_prepare(codec, | 2071 | status = snd_hda_codec_load_dsp_prepare(codec, |
@@ -2357,10 +2357,14 @@ static int dspxfr_one_seg(struct hda_codec *codec, | |||
2357 | chip_addx_remainder, | 2357 | chip_addx_remainder, |
2358 | data_remainder, | 2358 | data_remainder, |
2359 | remainder_words); | 2359 | remainder_words); |
2360 | if (status < 0) | ||
2361 | return status; | ||
2360 | remainder_words = 0; | 2362 | remainder_words = 0; |
2361 | } | 2363 | } |
2362 | if (hci_write) { | 2364 | if (hci_write) { |
2363 | status = dspxfr_hci_write(codec, hci_write); | 2365 | status = dspxfr_hci_write(codec, hci_write); |
2366 | if (status < 0) | ||
2367 | return status; | ||
2364 | hci_write = NULL; | 2368 | hci_write = NULL; |
2365 | } | 2369 | } |
2366 | 2370 | ||
@@ -2376,7 +2380,7 @@ static int dspxfr_one_seg(struct hda_codec *codec, | |||
2376 | 2380 | ||
2377 | snd_printdd(KERN_INFO "+++++ DMA complete"); | 2381 | snd_printdd(KERN_INFO "+++++ DMA complete"); |
2378 | dma_set_state(dma_engine, DMA_STATE_STOP); | 2382 | dma_set_state(dma_engine, DMA_STATE_STOP); |
2379 | dma_reset(dma_engine); | 2383 | status = dma_reset(dma_engine); |
2380 | 2384 | ||
2381 | if (status < 0) | 2385 | if (status < 0) |
2382 | return status; | 2386 | return status; |
@@ -2517,7 +2521,7 @@ exit: | |||
2517 | if (ovly && (dma_chan != INVALID_DMA_CHANNEL)) | 2521 | if (ovly && (dma_chan != INVALID_DMA_CHANNEL)) |
2518 | dspio_free_dma_chan(codec, dma_chan); | 2522 | dspio_free_dma_chan(codec, dma_chan); |
2519 | 2523 | ||
2520 | if (dma_engine->dmab) | 2524 | if (dma_engine->dmab->area) |
2521 | snd_hda_codec_load_dsp_cleanup(codec, dma_engine->dmab); | 2525 | snd_hda_codec_load_dsp_cleanup(codec, dma_engine->dmab); |
2522 | kfree(dma_engine->dmab); | 2526 | kfree(dma_engine->dmab); |
2523 | kfree(dma_engine); | 2527 | kfree(dma_engine); |