From: Charles Keepax Date: Tue, 21 Jul 2026 14:36:32 +0000 (+0100) Subject: ASoC: SDCA: Remove devm from primary IRQ cleanup X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0880082c27b6251cc3fea307dffa6899ad163e8b;p=thirdparty%2Flinux.git ASoC: SDCA: Remove devm from primary IRQ cleanup To provide greater flexibility on when the IRQs are requested for client drivers don't use devm for the primary IRQ request/cleanup helper functions. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- diff --git a/include/sound/sdca_fdl.h b/include/sound/sdca_fdl.h index fbaf4b384c8a..dc33927b82bd 100644 --- a/include/sound/sdca_fdl.h +++ b/include/sound/sdca_fdl.h @@ -67,6 +67,8 @@ struct fdl_state { #if IS_ENABLED(CONFIG_SND_SOC_SDCA_FDL) int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt); +void sdca_fdl_free_state(struct sdca_interrupt *interrupt); + int sdca_fdl_process(struct sdca_interrupt *interrupt); int sdca_fdl_sync(struct device *dev, struct sdca_function_data *function, struct sdca_interrupt_info *info); diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index 38c6c58c2cc7..8a44c19e917c 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -31,6 +31,7 @@ struct sdca_function_data; * @entity: Pointer to the Entity that the interrupt is associated with. * @control: Pointer to the Control that the interrupt is associated with. * @priv: Pointer to private data for use by the handler. + * @free_priv: Pointer to a function that can be used to free the priv data. * @irq: IRQ number allocated to this interrupt, also used internally to track * the IRQ being assigned. * @early_request: Flag to indicate this IRQ was requested at bus probe time. @@ -47,6 +48,7 @@ struct sdca_interrupt { struct sdca_control *control; void *priv; + void (*free_priv)(struct sdca_interrupt *interrupt); int irq; bool early_request; diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h index 181541f0f4d8..59de40b7d7d0 100644 --- a/include/sound/sdca_jack.h +++ b/include/sound/sdca_jack.h @@ -28,6 +28,8 @@ struct jack_state { }; int sdca_jack_alloc_state(struct sdca_interrupt *interrupt); +void sdca_jack_free_state(struct sdca_interrupt *interrupt); + int sdca_jack_process(struct sdca_interrupt *interrupt); int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack); int sdca_jack_report(struct sdca_interrupt *interrupt); diff --git a/sound/soc/sdca/sdca_fdl.c b/sound/soc/sdca/sdca_fdl.c index 994821a6df61..82e09d960c12 100644 --- a/sound/soc/sdca/sdca_fdl.c +++ b/sound/soc/sdca/sdca_fdl.c @@ -481,10 +481,9 @@ EXPORT_SYMBOL_NS_GPL(sdca_fdl_process, "SND_SOC_SDCA"); */ int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt) { - struct device *dev = interrupt->dev; struct fdl_state *fdl_state; - fdl_state = devm_kzalloc(dev, sizeof(*fdl_state), GFP_KERNEL); + fdl_state = kzalloc_obj(*fdl_state); if (!fdl_state) return -ENOMEM; @@ -499,3 +498,13 @@ int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt) return 0; } EXPORT_SYMBOL_NS_GPL(sdca_fdl_alloc_state, "SND_SOC_SDCA"); + +/** + * sdca_fdl_free_state - free state for an FDL interrupt + * @interrupt: SDCA interrupt structure. + */ +void sdca_fdl_free_state(struct sdca_interrupt *interrupt) +{ + kfree(interrupt->priv); +} +EXPORT_SYMBOL_NS_GPL(sdca_fdl_free_state, "SND_SOC_SDCA"); diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index d86884a89c40..cd2c5d49bb95 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -457,6 +457,7 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *regmap, return ret; interrupt->early_request = true; + interrupt->free_priv = sdca_fdl_free_state; ret = sdca_fdl_alloc_state(interrupt); if (ret) @@ -530,6 +531,8 @@ int sdca_irq_populate(struct sdca_function_data *function, handler = function_status_handler; break; case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): + interrupt->free_priv = sdca_jack_free_state; + ret = sdca_jack_alloc_state(interrupt); if (ret) return ret; @@ -537,6 +540,8 @@ int sdca_irq_populate(struct sdca_function_data *function, handler = detected_mode_handler; break; case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): + interrupt->free_priv = sdca_fdl_free_state; + ret = sdca_fdl_alloc_state(interrupt); if (ret) return ret; @@ -584,6 +589,9 @@ static void sdca_irq_cleanup_flags(struct device *dev, sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt); + if (interrupt->free_priv) + interrupt->free_priv(interrupt); + kfree(interrupt->name); } } diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c index ae9636622a84..ffa870964924 100644 --- a/sound/soc/sdca/sdca_jack.c +++ b/sound/soc/sdca/sdca_jack.c @@ -132,10 +132,9 @@ EXPORT_SYMBOL_NS_GPL(sdca_jack_process, "SND_SOC_SDCA"); */ int sdca_jack_alloc_state(struct sdca_interrupt *interrupt) { - struct device *dev = interrupt->dev; struct jack_state *jack_state; - jack_state = devm_kzalloc(dev, sizeof(*jack_state), GFP_KERNEL); + jack_state = kzalloc_obj(*jack_state); if (!jack_state) return -ENOMEM; @@ -145,6 +144,16 @@ int sdca_jack_alloc_state(struct sdca_interrupt *interrupt) } EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA"); +/** + * sdca_jack_free_state - free state for a jack interrupt + * @interrupt: SDCA interrupt structure. + */ +void sdca_jack_free_state(struct sdca_interrupt *interrupt) +{ + kfree(interrupt->priv); +} +EXPORT_SYMBOL_NS_GPL(sdca_jack_free_state, "SND_SOC_SDCA"); + static int type_get_mask(enum sdca_terminal_type type) { switch (type) {