Move the freeing of context data out of sdw_intel_exit() into a new exported function sdw_intel_remove(). This splits shutdown and cleanup into separate stages, allowing the calling code to perform its own shutdown after the bus has shutdown but before the context has been deleted. The struct sdw_intel_ctx pointer is passed to the calling code by sdw_intel_probe() and the calling code passes it back as an opaque token. When the caller is removed it must have the opportunity to teardown its use of this token after the bus driver has stopped but before the context memory has been freed. It should not be doing its teardown before calling sdw_intel_exit() because that will break any bus activity currently in progress and the removal of child drivers. Signed-off-by: Richard Fitzgerald <rf@xxxxxxxxxxxxxxxxxxxxx> --- drivers/soundwire/intel_init.c | 24 ++++++++++++++++++++---- include/linux/soundwire/sdw_intel.h | 2 ++ sound/soc/sof/intel/hda.c | 4 +++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index d091513919df..078e01f67830 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -292,6 +292,13 @@ static struct sdw_intel_ctx return NULL; } +static void sdw_intel_remove_controller(struct sdw_intel_ctx *ctx) +{ + kfree(ctx->ids); + kfree(ctx->ldev); + kfree(ctx); +} + static int sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) { @@ -360,6 +367,18 @@ struct sdw_intel_ctx } EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT); +/** + * sdw_intel_remove() - SoundWire Intel remove routine + * @ctx: SoundWire context allocated in the probe + * + * Free all the context created by sdw_intel_probe. + */ +void sdw_intel_remove(struct sdw_intel_ctx *ctx) +{ + return sdw_intel_remove_controller(ctx); +} +EXPORT_SYMBOL_NS(sdw_intel_remove, SOUNDWIRE_INTEL_INIT); + /** * sdw_intel_startup() - SoundWire Intel startup * @ctx: SoundWire context allocated in the probe @@ -376,14 +395,11 @@ EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT); * sdw_intel_exit() - SoundWire Intel exit * @ctx: SoundWire context allocated in the probe * - * Delete the controller instances created and cleanup + * Stop the controller instances. */ void sdw_intel_exit(struct sdw_intel_ctx *ctx) { sdw_intel_cleanup(ctx); - kfree(ctx->ids); - kfree(ctx->ldev); - kfree(ctx); } EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT); diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 2e9fd91572d4..7f7327cab712 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -282,6 +282,8 @@ void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx); struct sdw_intel_ctx * sdw_intel_probe(struct sdw_intel_res *res); +void sdw_intel_remove(struct sdw_intel_ctx *ctx); + int sdw_intel_startup(struct sdw_intel_ctx *ctx); void sdw_intel_exit(struct sdw_intel_ctx *ctx); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8639ea63a10d..ee67e21e739f 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -241,8 +241,10 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev) hda_sdw_int_enable(sdev, false); - if (hdev->sdw) + if (hdev->sdw) { sdw_intel_exit(hdev->sdw); + sdw_intel_remove(hdev->sdw); + } hdev->sdw = NULL; return 0; -- 2.30.2