[SRU][R][PATCH v3 2/7] ASoC: SDCA: Add sdca_irq_cleanup_late()

Chris Chiu chris.chiu at canonical.com
Wed Sep 2 05:19:06 UTC 2026


From: Charles Keepax <ckeepax at opensource.cirrus.com>

BugLink: https://bugs.launchpad.net/bugs/2163215

The SDCA IRQs are split into two groups, those registered at bus probe
time (basically just FDL) and those registered at component time.
There currently exists only a single cleanup function, if the FDL IRQ
is freed at component time, then nothing would re-register it if the
component is probed again. But the IRQs depending on a component need
to be freed if the card is destroyed so they can't use stale
components.

Split the clean up into two functions one for the component level and
one for the bus level.

Signed-off-by: Charles Keepax <ckeepax at opensource.cirrus.com>
Link: https://patch.msgid.link/20260721143636.361814-3-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie at kernel.org>
(backported from commit f18e97fa7f125e0e7da130b4d0ff1edd48d7510a)
[ChrisChiu: Conflict in sdca_interrupts.c due to different doc comment
 (@sdev vs @dev) and the old sdca_irq_cleanup() function declaration.
 Resolved by taking the upstream version which replaces the old function
 with the new static sdca_irq_cleanup_flags() helper. The rest of the
 changes (early_request flag, new cleanup functions) were already applied.]
Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
---
 include/sound/sdca_interrupts.h      |  5 +++
 sound/soc/sdca/sdca_class_function.c |  2 +-
 sound/soc/sdca/sdca_interrupts.c     | 53 ++++++++++++++++++++++------
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
index 28fd44eb9334..38c6c58c2cc7 100644
--- a/include/sound/sdca_interrupts.h
+++ b/include/sound/sdca_interrupts.h
@@ -33,6 +33,7 @@ struct sdca_function_data;
  * @priv: Pointer to private data for use by the handler.
  * @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.
  */
 struct sdca_interrupt {
 	const char *name;
@@ -48,6 +49,7 @@ struct sdca_interrupt {
 	void *priv;
 
 	int irq;
+	bool early_request;
 };
 
 /**
@@ -86,6 +88,9 @@ int sdca_irq_populate(struct sdca_function_data *function,
 void sdca_irq_cleanup(struct device *dev,
 		      struct sdca_function_data *function,
 		      struct sdca_interrupt_info *info);
+void sdca_irq_cleanup_late(struct device *dev,
+			   struct sdca_function_data *function,
+			   struct sdca_interrupt_info *info);
 
 struct sdca_interrupt_info *devm_sdca_irq_allocate(struct device *dev,
 						   struct regmap *regmap, int irq);
diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 730103120514..2f9bbe6a9b51 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -415,7 +415,7 @@ static void class_function_remove(struct auxiliary_device *auxdev)
 {
 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
 
-	sdca_irq_cleanup(drv->dev, drv->function, drv->core->irq_info);
+	sdca_irq_cleanup_late(drv->dev, drv->function, drv->core->irq_info);
 }
 
 static int class_function_runtime_suspend(struct device *dev)
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 8a8d0c061053..6ff0a0a12755 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -447,6 +447,8 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *regmap,
 				if (ret)
 					return ret;
 
+				interrupt->early_request = true;
+
 				ret = sdca_fdl_alloc_state(interrupt);
 				if (ret)
 					return ret;
@@ -553,17 +555,10 @@ int sdca_irq_populate(struct sdca_function_data *function,
 }
 EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA");
 
-/**
- * sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function
- * @sdev: Device pointer against which the sdca_interrupt_info was allocated.
- * @function: Pointer to the SDCA Function.
- * @info: Pointer to the SDCA interrupt info for this device.
- *
- * Typically this would be called from the driver for a single SDCA Function.
- */
-void sdca_irq_cleanup(struct device *dev,
-		      struct sdca_function_data *function,
-		      struct sdca_interrupt_info *info)
+static void sdca_irq_cleanup_flags(struct device *dev,
+				   struct sdca_function_data *function,
+				   struct sdca_interrupt_info *info,
+				   bool late_cleanup)
 {
 	int i;
 
@@ -575,13 +570,49 @@ void sdca_irq_cleanup(struct device *dev,
 		if (interrupt->function != function || !interrupt->irq)
 			continue;
 
+		if (interrupt->early_request && !late_cleanup)
+			continue;
+
 		sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt);
 
 		kfree(interrupt->name);
 	}
 }
+
+/**
+ * sdca_irq_cleanup - Free the regular IRQs for an SDCA Function
+ * @dev: Device pointer against which the sdca_interrupt_info was allocated.
+ * @function: Pointer to the SDCA Function.
+ * @info: Pointer to the SDCA interrupt info for this device.
+ *
+ * Typically this would be called from the driver for a single SDCA Function
+ * from component remove.
+ */
+void sdca_irq_cleanup(struct device *dev,
+		      struct sdca_function_data *function,
+		      struct sdca_interrupt_info *info)
+{
+	sdca_irq_cleanup_flags(dev, function, info, false);
+}
 EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA");
 
+/**
+ * sdca_irq_cleanup_late - Free the early IRQs for an SDCA Function
+ * @dev: Device pointer against which the sdca_interrupt_info was allocated.
+ * @function: Pointer to the SDCA Function.
+ * @info: Pointer to the SDCA interrupt info for this device.
+ *
+ * Typically this would be called from the driver for a single SDCA Function
+ * from bus remove.
+ */
+void sdca_irq_cleanup_late(struct device *dev,
+			   struct sdca_function_data *function,
+			   struct sdca_interrupt_info *info)
+{
+	sdca_irq_cleanup_flags(dev, function, info, true);
+}
+EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup_late, "SND_SOC_SDCA");
+
 /**
  * devm_sdca_irq_allocate - allocate an SDCA interrupt structure for a device
  * @sdev: Device pointer against which things should be allocated.
-- 
2.43.0




More information about the kernel-team mailing list