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

Commit b76a0252 authored by Karthikeyan Mani's avatar Karthikeyan Mani Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: wcd934x: Fix rmmod issues



Remove any child devices associated with this
driver so that rmmod and then insmod again will
run without issues. Also add NULL checks for
codec pointers before dereferencing.

CRs-fixed: 2092930
Change-Id: I7bd2dec2f6bb84e59e8bd43e29055db81962e3b6
Signed-off-by: default avatarKarthikeyan Mani <kmani@codeaurora.org>
parent 1b24115d
Loading
Loading
Loading
Loading
+36 −4
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ static const struct snd_kcontrol_new name##_mux = \
#define WCD934X_DIG_CORE_REG_MIN  WCD934X_CDC_ANC0_CLK_RESET_CTL
#define WCD934X_DIG_CORE_REG_MAX  0xFFF

#define WCD934X_CHILD_DEVICES_MAX	6

#define WCD934X_MAX_MICBIAS 4
#define DAPM_MICBIAS1_STANDALONE "MIC BIAS1 Standalone"
#define DAPM_MICBIAS2_STANDALONE "MIC BIAS2 Standalone"
@@ -654,6 +656,11 @@ struct tavil_priv {
	int power_active_ref;
	int sidetone_coeff_array[IIR_MAX][BAND_MAX]
		[WCD934X_CDC_SIDETONE_IIR_COEFF_MAX];

	struct spi_device *spi;
	struct platform_device *pdev_child_devices
		[WCD934X_CHILD_DEVICES_MAX];
	int child_count;
};

static const struct tavil_reg_mask_val tavil_spkr_default[] = {
@@ -5210,6 +5217,13 @@ static void tavil_restore_iir_coeff(struct tavil_priv *tavil, int iir_idx)
	int band_idx = 0, coeff_idx = 0;
	struct snd_soc_codec *codec = tavil->codec;

	/*
	 * snd_soc_write call crashes at rmmod if there is no machine
	 * driver and hence no codec pointer available
	 */
	if (!codec)
		return;

	for (band_idx = 0; band_idx < BAND_MAX; band_idx++) {
		snd_soc_write(codec,
		(WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
@@ -9382,6 +9396,9 @@ static int tavil_soc_codec_remove(struct snd_soc_codec *codec)

	control = dev_get_drvdata(codec->dev->parent);
	devm_kfree(codec->dev, control->rx_chs);
	/* slimslave deinit in wcd core looks for this value */
	control->num_rx_port = 0;
	control->num_tx_port = 0;
	control->rx_chs = NULL;
	control->tx_chs = NULL;
	tavil_cleanup_irqs(tavil);
@@ -9721,6 +9738,7 @@ static void tavil_codec_add_spi_device(struct tavil_priv *tavil,
		goto err_dt_parse;
	}

	tavil->spi = spi;
	/* Put the reference to SPI master */
	put_device(&master->dev);

@@ -9767,6 +9785,7 @@ static void tavil_add_child_devices(struct work_struct *work)
	}

	platdata = &tavil->swr.plat_data;
	tavil->child_count = 0;

	for_each_child_of_node(wcd9xxx->dev->of_node, node) {

@@ -9834,6 +9853,10 @@ static void tavil_add_child_devices(struct work_struct *work)
				__func__);
			tavil->swr.ctrl_data = swr_ctrl_data;
		}
		if (tavil->child_count < WCD934X_CHILD_DEVICES_MAX)
			tavil->pdev_child_devices[tavil->child_count++] = pdev;
		else
			goto err_mem;
	}

	return;
@@ -10061,11 +10084,24 @@ static int tavil_probe(struct platform_device *pdev)
static int tavil_remove(struct platform_device *pdev)
{
	struct tavil_priv *tavil;
	int count = 0;

	tavil = platform_get_drvdata(pdev);
	if (!tavil)
		return -EINVAL;

	/* do dsd deinit before codec->component->regmap becomes freed */
	if (tavil->dsd_config) {
		tavil_dsd_deinit(tavil->dsd_config);
		tavil->dsd_config = NULL;
	}

	if (tavil->spi)
		spi_unregister_device(tavil->spi);
	for (count = 0; count < tavil->child_count &&
				count < WCD934X_CHILD_DEVICES_MAX; count++)
		platform_device_unregister(tavil->pdev_child_devices[count]);

	mutex_destroy(&tavil->micb_lock);
	mutex_destroy(&tavil->svs_mutex);
	mutex_destroy(&tavil->codec_mutex);
@@ -10076,10 +10112,6 @@ static int tavil_remove(struct platform_device *pdev)
	snd_soc_unregister_codec(&pdev->dev);
	clk_put(tavil->wcd_ext_clk);
	wcd_resmgr_remove(tavil->resmgr);
	if (tavil->dsd_config) {
		tavil_dsd_deinit(tavil->dsd_config);
		tavil->dsd_config = NULL;
	}
	devm_kfree(&pdev->dev, tavil);
	return 0;
}