From d38087b67afcd332244b99efb33a49840c369f2d Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 10 Sep 2021 16:15:11 +0800 Subject: [PATCH] ASoC: rk3308_codec: Fix missing device_unregister() in error path rk3308_platform_probe() should call device_unregister() in error path. Otherwise, the memory of dev will free without unregister. Kernel will panic when reboot. kobject: '(null)' (ffffffc01e94a830): is not initialized, yet kobject_get() is being called. [] kobject_get+0x30/0x80 [] get_device+0x14/0x24 [] device_shutdown+0x84/0x1a8 [] kernel_restart_prepare+0x34/0x3c [] kernel_restart+0x14/0x5c [] SyS_reboot+0x1a0/0x1bc [] el0_svc_naked+0x24/0x28 Change-Id: I8eb838deb3b540792f63124365bf821f7ee15649 Signed-off-by: Tao Huang --- sound/soc/codecs/rk3308_codec.c | 49 ++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c index c17045911faf..783aad4178f9 100644 --- a/sound/soc/codecs/rk3308_codec.c +++ b/sound/soc/codecs/rk3308_codec.c @@ -4719,6 +4719,16 @@ static int rk3308_codec_sysfs_init(struct platform_device *pdev, return 0; } +static void rk3308_codec_sysfs_exit(struct rk3308_codec_priv *rk3308) +{ + struct device *dev = &rk3308->dev; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++) + device_remove_file(dev, &acodec_attrs[i]); + device_unregister(dev); +} + #if defined(CONFIG_DEBUG_FS) static int rk3308_codec_debugfs_reg_show(struct seq_file *s, void *v) { @@ -4859,7 +4869,7 @@ static int rk3308_platform_probe(struct platform_device *pdev) if (IS_ERR(rk3308->reset)) { ret = PTR_ERR(rk3308->reset); if (ret != -ENOENT) - return ret; + goto out_sysfs; dev_dbg(&pdev->dev, "No reset control found\n"); rk3308->reset = NULL; @@ -4872,7 +4882,7 @@ static int rk3308_platform_probe(struct platform_device *pdev) } else if (IS_ERR(rk3308->hp_ctl_gpio)) { ret = PTR_ERR(rk3308->hp_ctl_gpio); dev_err(&pdev->dev, "Unable to claim gpio hp-ctl\n"); - return ret; + goto out_sysfs; } rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-ctl", @@ -4883,7 +4893,7 @@ static int rk3308_platform_probe(struct platform_device *pdev) } else if (IS_ERR(rk3308->spk_ctl_gpio)) { ret = PTR_ERR(rk3308->spk_ctl_gpio); dev_err(&pdev->dev, "Unable to claim gpio spk-ctl\n"); - return ret; + goto out_sysfs; } rk3308->pa_drv_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-drv", @@ -4894,7 +4904,7 @@ static int rk3308_platform_probe(struct platform_device *pdev) } else if (IS_ERR(rk3308->pa_drv_gpio)) { ret = PTR_ERR(rk3308->pa_drv_gpio); dev_err(&pdev->dev, "Unable to claim gpio pa-drv\n"); - return ret; + goto out_sysfs; } if (rk3308->pa_drv_gpio) { @@ -4916,37 +4926,40 @@ static int rk3308_platform_probe(struct platform_device *pdev) rk3308->pclk = devm_clk_get(&pdev->dev, "acodec"); if (IS_ERR(rk3308->pclk)) { dev_err(&pdev->dev, "Can't get acodec pclk\n"); - return PTR_ERR(rk3308->pclk); + ret = PTR_ERR(rk3308->pclk); + goto out_sysfs; } rk3308->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx"); if (IS_ERR(rk3308->mclk_rx)) { dev_err(&pdev->dev, "Can't get acodec mclk_rx\n"); - return PTR_ERR(rk3308->mclk_rx); + ret = PTR_ERR(rk3308->mclk_rx); + goto out_sysfs; } rk3308->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx"); if (IS_ERR(rk3308->mclk_tx)) { dev_err(&pdev->dev, "Can't get acodec mclk_tx\n"); - return PTR_ERR(rk3308->mclk_tx); + ret = PTR_ERR(rk3308->mclk_tx); + goto out_sysfs; } ret = clk_prepare_enable(rk3308->pclk); if (ret < 0) { dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret); - return ret; + goto out_sysfs; } ret = clk_prepare_enable(rk3308->mclk_rx); if (ret < 0) { dev_err(&pdev->dev, "Failed to enable i2s mclk_rx: %d\n", ret); - return ret; + goto out_pclk; } ret = clk_prepare_enable(rk3308->mclk_tx); if (ret < 0) { dev_err(&pdev->dev, "Failed to enable i2s mclk_tx: %d\n", ret); - return ret; + goto out_mclk_rx; } rk3308_codec_check_micbias(rk3308, np); @@ -4981,21 +4994,21 @@ static int rk3308_platform_probe(struct platform_device *pdev) if (ret < 0 && ret != -EINVAL) { dev_err(&pdev->dev, "Failed to read loopback property: %d\n", ret); - return ret; + goto failed; } ret = rk3308_codec_adc_grps_route(rk3308, np); if (ret < 0) { dev_err(&pdev->dev, "Failed to route ADC groups: %d\n", ret); - return ret; + goto failed; } ret = rk3308_codec_setup_en_always_adcs(rk3308, np); if (ret < 0) { dev_err(&pdev->dev, "Failed to setup enabled always ADCs: %d\n", ret); - return ret; + goto failed; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -5044,7 +5057,8 @@ static int rk3308_platform_probe(struct platform_device *pdev) if (IS_ERR(rk3308->detect_grf)) { dev_err(&pdev->dev, "Missing 'rockchip,detect-grf' property\n"); - return PTR_ERR(rk3308->detect_grf); + ret = PTR_ERR(rk3308->detect_grf); + goto failed; } /* Configure filter count and enable hpdet irq. */ @@ -5079,10 +5093,13 @@ static int rk3308_platform_probe(struct platform_device *pdev) return ret; failed: - clk_disable_unprepare(rk3308->mclk_rx); clk_disable_unprepare(rk3308->mclk_tx); +out_mclk_rx: + clk_disable_unprepare(rk3308->mclk_rx); +out_pclk: clk_disable_unprepare(rk3308->pclk); - device_unregister(&rk3308->dev); +out_sysfs: + rk3308_codec_sysfs_exit(rk3308); return ret; }