aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2010-08-03 18:55:28 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-12 09:00:17 -0400
commit87a0632b29410bab5c1783d7eb979c8d942d4209 (patch)
tree16762ec323b99ead5ab618b05ce99da234950800 /sound/soc/fsl
parent1a3c5a491af6756dbba6ee166a9dee72bb414ba8 (diff)
asoc/multi-component: fsl: fix exit and error paths in DMA and SSI drivers
The error handling code in the OF probe function of the SSI driver is not freeing all resources correctly. Since the machine driver no longer calls the DMA driver to provide information about the SSI, we don't need to keep a list of DMA objects any more. In addition, the fsl_soc_dma_remove() function is incorrectly removing *all* DMA objects when it should only remove one. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_dma.c23
-rw-r--r--sound/soc/fsl/fsl_ssi.c29
2 files changed, 23 insertions, 29 deletions
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 4450f9d845c6..57774cb91ae3 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -57,7 +57,6 @@
57 SNDRV_PCM_RATE_CONTINUOUS) 57 SNDRV_PCM_RATE_CONTINUOUS)
58 58
59struct dma_object { 59struct dma_object {
60 struct list_head list;
61 struct snd_soc_platform_driver dai; 60 struct snd_soc_platform_driver dai;
62 dma_addr_t ssi_stx_phys; 61 dma_addr_t ssi_stx_phys;
63 dma_addr_t ssi_srx_phys; 62 dma_addr_t ssi_srx_phys;
@@ -825,9 +824,6 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
825 } 824 }
826} 825}
827 826
828/* List of DMA nodes that we've probed */
829static LIST_HEAD(dma_list);
830
831/** 827/**
832 * find_ssi_node -- returns the SSI node that points to his DMA channel node 828 * find_ssi_node -- returns the SSI node that points to his DMA channel node
833 * 829 *
@@ -915,25 +911,20 @@ static int __devinit fsl_soc_dma_probe(struct of_device *of_dev,
915 911
916 dma->channel = of_iomap(np, 0); 912 dma->channel = of_iomap(np, 0);
917 dma->irq = irq_of_parse_and_map(np, 0); 913 dma->irq = irq_of_parse_and_map(np, 0);
918 list_add(&dma->list, &dma_list); 914
915 dev_set_drvdata(&of_dev->dev, dma);
919 916
920 return 0; 917 return 0;
921} 918}
922 919
923static int __devexit fsl_soc_dma_remove(struct of_device *of_dev) 920static int __devexit fsl_soc_dma_remove(struct of_device *of_dev)
924{ 921{
925 struct list_head *n, *ptr; 922 struct dma_object *dma = dev_get_drvdata(&of_dev->dev);
926 struct dma_object *dma;
927 923
928 list_for_each_safe(ptr, n, &dma_list) { 924 snd_soc_unregister_platform(&of_dev->dev);
929 dma = list_entry(ptr, struct dma_object, list); 925 iounmap(dma->channel);
930 list_del_init(ptr); 926 irq_dispose_mapping(dma->irq);
931 927 kfree(dma);
932 snd_soc_unregister_platform(&of_dev->dev);
933 iounmap(dma->channel);
934 irq_dispose_mapping(dma->irq);
935 kfree(dma);
936 }
937 928
938 return 0; 929 return 0;
939} 930}
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 51b089f9751c..00e3e625b52a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -619,7 +619,7 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
619{ 619{
620 struct fsl_ssi_private *ssi_private; 620 struct fsl_ssi_private *ssi_private;
621 int ret = 0; 621 int ret = 0;
622 struct device_attribute *dev_attr; 622 struct device_attribute *dev_attr = NULL;
623 struct device_node *np = of_dev->dev.of_node; 623 struct device_node *np = of_dev->dev.of_node;
624 const char *p, *sprop; 624 const char *p, *sprop;
625 struct resource res; 625 struct resource res;
@@ -681,18 +681,16 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
681 if (ret) { 681 if (ret) {
682 dev_err(&of_dev->dev, "could not create sysfs %s file\n", 682 dev_err(&of_dev->dev, "could not create sysfs %s file\n",
683 ssi_private->dev_attr.attr.name); 683 ssi_private->dev_attr.attr.name);
684 kfree(ssi_private); 684 goto error;
685 return ret;
686 } 685 }
687 686
688 /* Register with ASoC */ 687 /* Register with ASoC */
689 dev_set_drvdata(&of_dev->dev, ssi_private); 688 dev_set_drvdata(&of_dev->dev, ssi_private);
690 689
691 ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv); 690 ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv);
692 if (ret != 0) { 691 if (ret) {
693 dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret); 692 dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret);
694 kfree(ssi_private); 693 goto error;
695 return ret;
696 } 694 }
697 695
698 /* Trigger the machine driver's probe function. The platform driver 696 /* Trigger the machine driver's probe function. The platform driver
@@ -713,18 +711,23 @@ static int __devinit fsl_ssi_probe(struct of_device *of_dev,
713 if (IS_ERR(ssi_private->pdev)) { 711 if (IS_ERR(ssi_private->pdev)) {
714 ret = PTR_ERR(ssi_private->pdev); 712 ret = PTR_ERR(ssi_private->pdev);
715 dev_err(&of_dev->dev, "failed to register platform: %d\n", ret); 713 dev_err(&of_dev->dev, "failed to register platform: %d\n", ret);
716 kfree(ssi_private); 714 goto error;
717 return ret;
718 } 715 }
719 716
720 return 0; 717 return 0;
718
719error:
720 snd_soc_unregister_dai(&of_dev->dev);
721 dev_set_drvdata(&of_dev->dev, NULL);
722 if (dev_attr)
723 device_remove_file(&of_dev->dev, dev_attr);
724 irq_dispose_mapping(ssi_private->irq);
725 iounmap(ssi_private->ssi);
726 kfree(ssi_private);
727
728 return ret;
721} 729}
722 730
723/**
724 * fsl_ssi_destroy_dai: destroy the snd_soc_dai object
725 *
726 * This function undoes the operations of fsl_ssi_probe()
727 */
728static int fsl_ssi_remove(struct of_device *of_dev) 731static int fsl_ssi_remove(struct of_device *of_dev)
729{ 732{
730 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev); 733 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev);