From: Charles Keepax <ckeepax@opensource.cirrus.com>
To: broonie@kernel.org
Cc: lgirdwood@gmail.com, yung-chuan.liao@linux.intel.com,
pierre-louis.bossart@linux.dev, linux-sound@vger.kernel.org,
linux-kernel@vger.kernel.org, patches@opensource.cirrus.com
Subject: [PATCH v2 2/3] ASoC: SDCA: Populate IRQ data earlier
Date: Wed, 15 Jul 2026 17:29:17 +0100 [thread overview]
Message-ID: <20260715162918.1898396-3-ckeepax@opensource.cirrus.com> (raw)
In-Reply-To: <20260715162918.1898396-1-ckeepax@opensource.cirrus.com>
Currently, the IRQ data (attached Entity/Control/etc) is populated
as the IRQ is requested. However, this can cause issues as
occasionally the setup process wants to access specifics of
an IRQ before the IRQ is actually enabled. To facilitate this
cache all the IRQ data during sdca_irq_populate_early() and make
sdca_irq_populate() simply request the outstanding IRQs. This
also has the advantage that sdca_irq_populate() can now just
iterate through the IRQ array which is much smaller/faster than
going through every Entity in the Function for Controls.
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
Changes since v1:
- devm_ allocate the interrupt name now that it will always be
called from irq_populate_early which happens at probe time. This
also avoids a memory leak Sashiko spotted.
include/sound/sdca_interrupts.h | 2 +
sound/soc/sdca/sdca_interrupts.c | 98 ++++++++++++--------------------
2 files changed, 38 insertions(+), 62 deletions(-)
diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
index a515cc3df0971..20ff5eac34eaa 100644
--- a/include/sound/sdca_interrupts.h
+++ b/include/sound/sdca_interrupts.h
@@ -30,6 +30,7 @@ struct sdca_function_data;
* @function: Pointer to the Function that the interrupt is associated with.
* @entity: Pointer to the Entity that the interrupt is associated with.
* @control: Pointer to the Control that the interrupt is associated with.
+ * @handler: Handler function to be called for the IRQ.
* @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.
@@ -44,6 +45,7 @@ struct sdca_interrupt {
struct sdca_function_data *function;
struct sdca_entity *entity;
struct sdca_control *control;
+ irq_handler_t handler;
void *priv;
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 4539a52a8e32b..6bbe65ac3d2f0 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -375,7 +375,7 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap,
if (!dev)
return -ENODEV;
- name = kasprintf(GFP_KERNEL, "%s %s", entity->label, control->label);
+ name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", entity->label, control->label);
if (!name)
return -ENOMEM;
@@ -448,21 +448,34 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *regmap,
else if (!interrupt)
continue;
+ ret = sdca_irq_data_populate(dev, regmap, NULL, function,
+ entity, control, interrupt);
+ if (ret)
+ return ret;
+
+ interrupt->handler = base_handler;
+
switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
- case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
- ret = sdca_irq_data_populate(dev, regmap, NULL,
- function, entity,
- control, interrupt);
+ case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS):
+ interrupt->handler = function_status_handler;
+ break;
+ case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
+ ret = sdca_jack_alloc_state(interrupt);
if (ret)
return ret;
+ interrupt->handler = detected_mode_handler;
+ break;
+ case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
ret = sdca_fdl_alloc_state(interrupt);
if (ret)
return ret;
+ interrupt->handler = fdl_owner_handler;
+
ret = sdca_irq_request_locked(dev, info, irq,
interrupt->name,
- fdl_owner_handler,
+ interrupt->handler,
interrupt);
if (ret) {
dev_err(dev, "failed to request irq %s: %d\n",
@@ -470,6 +483,9 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *regmap,
return ret;
}
break;
+ case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER):
+ interrupt->handler = hid_handler;
+ break;
default:
break;
}
@@ -495,66 +511,26 @@ int sdca_irq_populate(struct sdca_function_data *function,
struct sdca_interrupt_info *info)
{
struct device *dev = component->dev;
- int i, j;
+ int i, ret;
guard(mutex)(&info->irq_lock);
- for (i = 0; i < function->num_entities; i++) {
- struct sdca_entity *entity = &function->entities[i];
-
- for (j = 0; j < entity->num_controls; j++) {
- struct sdca_control *control = &entity->controls[j];
- int irq = control->interrupt_position;
- struct sdca_interrupt *interrupt;
- irq_handler_t handler;
- int ret;
-
- interrupt = get_interrupt_data(dev, irq, info);
- if (IS_ERR(interrupt))
- return PTR_ERR(interrupt);
- else if (!interrupt)
- continue;
-
- ret = sdca_irq_data_populate(dev, NULL, component,
- function, entity, control,
- interrupt);
- if (ret)
- return ret;
-
- handler = base_handler;
-
- switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
- case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS):
- handler = function_status_handler;
- break;
- case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
- ret = sdca_jack_alloc_state(interrupt);
- if (ret)
- return ret;
+ for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
+ struct sdca_interrupt *interrupt = &info->irqs[i];
+ int irq;
- handler = detected_mode_handler;
- break;
- case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
- ret = sdca_fdl_alloc_state(interrupt);
- if (ret)
- return ret;
+ if (interrupt->function != function || interrupt->irq)
+ continue;
- handler = fdl_owner_handler;
- break;
- case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER):
- handler = hid_handler;
- break;
- default:
- break;
- }
+ interrupt->component = component;
- ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
- handler, interrupt);
- if (ret) {
- dev_err(dev, "failed to request irq %s: %d\n",
- interrupt->name, ret);
- return ret;
- }
+ irq = interrupt->control->interrupt_position;
+ ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
+ interrupt->handler, interrupt);
+ if (ret) {
+ dev_err(dev, "failed to request irq %s: %d\n",
+ interrupt->name, ret);
+ return ret;
}
}
@@ -585,8 +561,6 @@ void sdca_irq_cleanup(struct device *dev,
continue;
sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt);
-
- kfree(interrupt->name);
}
}
EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA");
--
2.47.3
next prev parent reply other threads:[~2026-07-15 16:29 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-15 16:29 [PATCH v2 0/3] Fix races on creation of SDCA jack detection Charles Keepax
2026-07-15 16:29 ` [PATCH v2 1/3] ASoC: Add a component fixup_controls callback Charles Keepax
2026-07-15 16:29 ` Charles Keepax [this message]
2026-07-15 16:29 ` [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration Charles Keepax
2026-07-16 9:32 ` Charles Keepax
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260715162918.1898396-3-ckeepax@opensource.cirrus.com \
--to=ckeepax@opensource.cirrus.com \
--cc=broonie@kernel.org \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
--cc=pierre-louis.bossart@linux.dev \
--cc=yung-chuan.liao@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox