In BOARDCFG_MANAGED mode, the firmware cannot restore IRQs during
resume. This responsibility is delegated to the ti_sci driver,
which maintains an internal list of all requested IRQs. This list
is updated on each set/free operation, and all IRQs are restored
during the resume_noirq() phase.
Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
---
drivers/firmware/ti_sci.c | 147 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 138 insertions(+), 9 deletions(-)
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index d77b631d9c855..8d94745376e2a 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -12,6 +12,7 @@
#include <linux/cpu.h>
#include <linux/debugfs.h>
#include <linux/export.h>
+#include <linux/hashtable.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
@@ -87,6 +88,16 @@ struct ti_sci_desc {
int max_msg_size;
};
+/**
+ * struct ti_sci_irq - Description of allocated irqs
+ * @node: Link to hash table
+ * @desc: Description of the irq
+ */
+struct ti_sci_irq {
+ struct hlist_node node;
+ struct ti_sci_msg_req_manage_irq desc;
+};
+
/**
* struct ti_sci_info - Structure representing a TI SCI instance
* @dev: Device pointer
@@ -101,6 +112,7 @@ struct ti_sci_desc {
* @chan_rx: Receive mailbox channel
* @minfo: Message info
* @node: list head
+ * @irqs: List of allocated irqs
* @host_id: Host ID
* @fw_caps: FW/SoC low power capabilities
* @users: Number of users of this instance
@@ -117,6 +129,7 @@ struct ti_sci_info {
struct mbox_chan *chan_tx;
struct mbox_chan *chan_rx;
struct ti_sci_xfers_info minfo;
+ DECLARE_HASHTABLE(irqs, 8);
struct list_head node;
u8 host_id;
u64 fw_caps;
@@ -2301,6 +2314,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle,
return ret;
}
+/**
+ * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table.
+ * @irq: irq to hash
+ *
+ * Return: the computed hash value.
+ */
+static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq)
+{
+ return irq->src_id ^ irq->src_index;
+}
+
+/**
+ * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not
+ * compared)
+ * @irq_a: irq_a to compare
+ * @irq_b: irq_b to compare
+ *
+ * Return: true if the two irqs are equal, else false.
+ */
+static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a,
+ struct ti_sci_msg_req_manage_irq *irq_b)
+{
+ return !memcmp(&irq_a->valid_params, &irq_b->valid_params,
+ sizeof(*irq_a) - sizeof(irq_a->hdr));
+}
+
/**
* ti_sci_set_irq() - Helper api to configure the irq route between the
* requested source and destination
@@ -2324,15 +2363,43 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params,
u16 dst_host_irq, u16 ia_id, u16 vint,
u16 global_event, u8 vint_status_bit, u8 s_host)
{
+ struct ti_sci_info *info = handle_to_ti_sci_info(handle);
+ struct ti_sci_msg_req_manage_irq *desc;
+ struct ti_sci_irq *irq;
+ int ret;
+
pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
__func__, valid_params, src_id, src_index,
dst_id, dst_host_irq, ia_id, vint, global_event,
vint_status_bit);
- return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
- dst_id, dst_host_irq, ia_id, vint,
- global_event, vint_status_bit, s_host,
- TI_SCI_MSG_SET_IRQ);
+ ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
+ dst_id, dst_host_irq, ia_id, vint,
+ global_event, vint_status_bit, s_host,
+ TI_SCI_MSG_SET_IRQ);
+
+ if (ret)
+ return ret;
+
+ irq = kzalloc(sizeof(*irq), GFP_KERNEL);
+ if (!irq)
+ return -ENOMEM;
+
+ desc = &irq->desc;
+ desc->valid_params = valid_params;
+ desc->src_id = src_id;
+ desc->src_index = src_index;
+ desc->dst_id = dst_id;
+ desc->dst_host_irq = dst_host_irq;
+ desc->ia_id = ia_id;
+ desc->vint = vint;
+ desc->global_event = global_event;
+ desc->vint_status_bit = vint_status_bit;
+ desc->secondary_host = s_host;
+
+ hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc));
+
+ return 0;
}
/**
@@ -2358,15 +2425,46 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params,
u16 dst_host_irq, u16 ia_id, u16 vint,
u16 global_event, u8 vint_status_bit, u8 s_host)
{
+ struct ti_sci_info *info = handle_to_ti_sci_info(handle);
+ struct ti_sci_msg_req_manage_irq irq_desc;
+ struct ti_sci_irq *this_irq;
+ struct hlist_node *tmp_node;
+ int ret;
+
pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
__func__, valid_params, src_id, src_index,
dst_id, dst_host_irq, ia_id, vint, global_event,
vint_status_bit);
- return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
- dst_id, dst_host_irq, ia_id, vint,
- global_event, vint_status_bit, s_host,
- TI_SCI_MSG_FREE_IRQ);
+ ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
+ dst_id, dst_host_irq, ia_id, vint,
+ global_event, vint_status_bit, s_host,
+ TI_SCI_MSG_FREE_IRQ);
+
+ if (ret)
+ return ret;
+
+ irq_desc.valid_params = valid_params;
+ irq_desc.src_id = src_id;
+ irq_desc.src_index = src_index;
+ irq_desc.dst_id = dst_id;
+ irq_desc.dst_host_irq = dst_host_irq;
+ irq_desc.ia_id = ia_id;
+ irq_desc.vint = vint;
+ irq_desc.global_event = global_event;
+ irq_desc.vint_status_bit = vint_status_bit;
+ irq_desc.secondary_host = s_host;
+
+ hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node,
+ ti_sci_irq_hash(&irq_desc)) {
+ if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) {
+ hlist_del(&this_irq->node);
+ kfree(this_irq);
+ return 0;
+ }
+ }
+
+ return 0;
}
/**
@@ -3847,7 +3945,10 @@ static int ti_sci_suspend_noirq(struct device *dev)
static int ti_sci_resume_noirq(struct device *dev)
{
struct ti_sci_info *info = dev_get_drvdata(dev);
- int ret = 0;
+ struct ti_sci_msg_req_manage_irq *irq_desc;
+ struct ti_sci_irq *irq;
+ struct hlist_node *tmp_node;
+ int ret = 0, i;
u32 source;
u64 time;
u8 pin;
@@ -3859,6 +3960,32 @@ static int ti_sci_resume_noirq(struct device *dev)
return ret;
}
+ switch (pm_suspend_target_state) {
+ case PM_SUSPEND_MEM:
+ if (info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED) {
+ hash_for_each_safe(info->irqs, i, tmp_node, irq, node) {
+ irq_desc = &irq->desc;
+ ret = ti_sci_manage_irq(&info->handle,
+ irq_desc->valid_params,
+ irq_desc->src_id,
+ irq_desc->src_index,
+ irq_desc->dst_id,
+ irq_desc->dst_host_irq,
+ irq_desc->ia_id,
+ irq_desc->vint,
+ irq_desc->global_event,
+ irq_desc->vint_status_bit,
+ irq_desc->secondary_host,
+ TI_SCI_MSG_SET_IRQ);
+ if (ret)
+ return ret;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode);
/* Do not fail to resume on error as the wake reason is not critical */
if (!ret)
@@ -4053,6 +4180,8 @@ static int ti_sci_probe(struct platform_device *pdev)
list_add_tail(&info->node, &ti_sci_list);
mutex_unlock(&ti_sci_list_mutex);
+ hash_init(info->irqs);
+
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret) {
dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret));
--
2.51.0
On 12/5/2025 7:58 PM, Thomas Richard (TI.com) wrote:
> In BOARDCFG_MANAGED mode, the firmware cannot restore IRQs during
> resume. This responsibility is delegated to the ti_sci driver,
> which maintains an internal list of all requested IRQs. This list
> is updated on each set/free operation, and all IRQs are restored
> during the resume_noirq() phase.
>
> Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
> ---
> drivers/firmware/ti_sci.c | 147 +++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 138 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> index d77b631d9c855..8d94745376e2a 100644
> --- a/drivers/firmware/ti_sci.c
> +++ b/drivers/firmware/ti_sci.c
> @@ -12,6 +12,7 @@
> #include <linux/cpu.h>
> #include <linux/debugfs.h>
> #include <linux/export.h>
> +#include <linux/hashtable.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> @@ -87,6 +88,16 @@ struct ti_sci_desc {
> int max_msg_size;
> };
>
> +/**
> + * struct ti_sci_irq - Description of allocated irqs
> + * @node: Link to hash table
> + * @desc: Description of the irq
> + */
> +struct ti_sci_irq {
> + struct hlist_node node;
> + struct ti_sci_msg_req_manage_irq desc;
> +};
> +
> /**
> * struct ti_sci_info - Structure representing a TI SCI instance
> * @dev: Device pointer
> @@ -101,6 +112,7 @@ struct ti_sci_desc {
> * @chan_rx: Receive mailbox channel
> * @minfo: Message info
> * @node: list head
> + * @irqs: List of allocated irqs
> * @host_id: Host ID
> * @fw_caps: FW/SoC low power capabilities
> * @users: Number of users of this instance
> @@ -117,6 +129,7 @@ struct ti_sci_info {
> struct mbox_chan *chan_tx;
> struct mbox_chan *chan_rx;
> struct ti_sci_xfers_info minfo;
> + DECLARE_HASHTABLE(irqs, 8);
> struct list_head node;
> u8 host_id;
> u64 fw_caps;
> @@ -2301,6 +2314,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle,
> return ret;
> }
>
> +/**
> + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table.
> + * @irq: irq to hash
> + *
> + * Return: the computed hash value.
> + */
> +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq)
> +{
> + return irq->src_id ^ irq->src_index;
> +}
> +
> +/**
> + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not
> + * compared)
> + * @irq_a: irq_a to compare
> + * @irq_b: irq_b to compare
> + *
> + * Return: true if the two irqs are equal, else false.
> + */
> +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a,
> + struct ti_sci_msg_req_manage_irq *irq_b)
> +{
> + return !memcmp(&irq_a->valid_params, &irq_b->valid_params,
> + sizeof(*irq_a) - sizeof(irq_a->hdr));
> +}
> +
> /**
> * ti_sci_set_irq() - Helper api to configure the irq route between the
> * requested source and destination
> @@ -2324,15 +2363,43 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params,
> u16 dst_host_irq, u16 ia_id, u16 vint,
> u16 global_event, u8 vint_status_bit, u8 s_host)
> {
> + struct ti_sci_info *info = handle_to_ti_sci_info(handle);
> + struct ti_sci_msg_req_manage_irq *desc;
> + struct ti_sci_irq *irq;
> + int ret;
> +
> pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
> __func__, valid_params, src_id, src_index,
> dst_id, dst_host_irq, ia_id, vint, global_event,
> vint_status_bit);
>
> - return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> - dst_id, dst_host_irq, ia_id, vint,
> - global_event, vint_status_bit, s_host,
> - TI_SCI_MSG_SET_IRQ);
> + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> + dst_id, dst_host_irq, ia_id, vint,
> + global_event, vint_status_bit, s_host,
> + TI_SCI_MSG_SET_IRQ);
> +
> + if (ret)
> + return ret;
> +
> + irq = kzalloc(sizeof(*irq), GFP_KERNEL);
> + if (!irq)
> + return -ENOMEM;
> +
> + desc = &irq->desc;
> + desc->valid_params = valid_params;
> + desc->src_id = src_id;
> + desc->src_index = src_index;
> + desc->dst_id = dst_id;
> + desc->dst_host_irq = dst_host_irq;
> + desc->ia_id = ia_id;
> + desc->vint = vint;
> + desc->global_event = global_event;
> + desc->vint_status_bit = vint_status_bit;
> + desc->secondary_host = s_host;
> +
> + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc));
> +
> + return 0;
> }
>
> /**
> @@ -2358,15 +2425,46 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params,
> u16 dst_host_irq, u16 ia_id, u16 vint,
> u16 global_event, u8 vint_status_bit, u8 s_host)
> {
> + struct ti_sci_info *info = handle_to_ti_sci_info(handle);
> + struct ti_sci_msg_req_manage_irq irq_desc;
> + struct ti_sci_irq *this_irq;
> + struct hlist_node *tmp_node;
> + int ret;
> +
> pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
> __func__, valid_params, src_id, src_index,
> dst_id, dst_host_irq, ia_id, vint, global_event,
> vint_status_bit);
>
> - return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> - dst_id, dst_host_irq, ia_id, vint,
> - global_event, vint_status_bit, s_host,
> - TI_SCI_MSG_FREE_IRQ);
> + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> + dst_id, dst_host_irq, ia_id, vint,
> + global_event, vint_status_bit, s_host,
> + TI_SCI_MSG_FREE_IRQ);
> +
> + if (ret)
> + return ret;
> +
> + irq_desc.valid_params = valid_params;
> + irq_desc.src_id = src_id;
> + irq_desc.src_index = src_index;
> + irq_desc.dst_id = dst_id;
> + irq_desc.dst_host_irq = dst_host_irq;
> + irq_desc.ia_id = ia_id;
> + irq_desc.vint = vint;
> + irq_desc.global_event = global_event;
> + irq_desc.vint_status_bit = vint_status_bit;
> + irq_desc.secondary_host = s_host;
> +
> + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node,
> + ti_sci_irq_hash(&irq_desc)) {
> + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) {
> + hlist_del(&this_irq->node);
> + kfree(this_irq);
> + return 0;
IMO, you can restrict saving of irq and list management to fw having
BOARDCFG_MANAGED capability.
Dhurva ?
> + }
> + }
> +
> + return 0;
> }
>
> /**
> [..]
On Dec 16, 2025 at 08:17:24 +0530, Kumar, Udit wrote:
>
> On 12/5/2025 7:58 PM, Thomas Richard (TI.com) wrote:
> > In BOARDCFG_MANAGED mode, the firmware cannot restore IRQs during
> > resume. This responsibility is delegated to the ti_sci driver,
> > which maintains an internal list of all requested IRQs. This list
> > is updated on each set/free operation, and all IRQs are restored
> > during the resume_noirq() phase.
> >
> > Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
> > ---
> > drivers/firmware/ti_sci.c | 147 +++++++++++++++++++++++++++++++++++++++++++---
> > 1 file changed, 138 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> > index d77b631d9c855..8d94745376e2a 100644
> > --- a/drivers/firmware/ti_sci.c
> > +++ b/drivers/firmware/ti_sci.c
> > @@ -12,6 +12,7 @@
> > #include <linux/cpu.h>
> > #include <linux/debugfs.h>
> > #include <linux/export.h>
> > +#include <linux/hashtable.h>
> > #include <linux/io.h>
> > #include <linux/iopoll.h>
> > #include <linux/kernel.h>
> > @@ -87,6 +88,16 @@ struct ti_sci_desc {
> > int max_msg_size;
> > };
> > +/**
> > + * struct ti_sci_irq - Description of allocated irqs
> > + * @node: Link to hash table
> > + * @desc: Description of the irq
> > + */
> > +struct ti_sci_irq {
> > + struct hlist_node node;
> > + struct ti_sci_msg_req_manage_irq desc;
> > +};
> > +
> > /**
> > * struct ti_sci_info - Structure representing a TI SCI instance
> > * @dev: Device pointer
> > @@ -101,6 +112,7 @@ struct ti_sci_desc {
> > * @chan_rx: Receive mailbox channel
> > * @minfo: Message info
> > * @node: list head
> > + * @irqs: List of allocated irqs
> > * @host_id: Host ID
> > * @fw_caps: FW/SoC low power capabilities
> > * @users: Number of users of this instance
> > @@ -117,6 +129,7 @@ struct ti_sci_info {
> > struct mbox_chan *chan_tx;
> > struct mbox_chan *chan_rx;
> > struct ti_sci_xfers_info minfo;
> > + DECLARE_HASHTABLE(irqs, 8);
> > struct list_head node;
> > u8 host_id;
> > u64 fw_caps;
> > @@ -2301,6 +2314,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle,
> > return ret;
> > }
> > +/**
> > + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table.
> > + * @irq: irq to hash
> > + *
> > + * Return: the computed hash value.
> > + */
> > +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq)
> > +{
> > + return irq->src_id ^ irq->src_index;
> > +}
> > +
> > +/**
> > + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not
> > + * compared)
> > + * @irq_a: irq_a to compare
> > + * @irq_b: irq_b to compare
> > + *
> > + * Return: true if the two irqs are equal, else false.
> > + */
> > +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a,
> > + struct ti_sci_msg_req_manage_irq *irq_b)
> > +{
> > + return !memcmp(&irq_a->valid_params, &irq_b->valid_params,
> > + sizeof(*irq_a) - sizeof(irq_a->hdr));
> > +}
> > +
> > /**
> > * ti_sci_set_irq() - Helper api to configure the irq route between the
> > * requested source and destination
> > @@ -2324,15 +2363,43 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params,
> > u16 dst_host_irq, u16 ia_id, u16 vint,
> > u16 global_event, u8 vint_status_bit, u8 s_host)
> > {
> > + struct ti_sci_info *info = handle_to_ti_sci_info(handle);
> > + struct ti_sci_msg_req_manage_irq *desc;
> > + struct ti_sci_irq *irq;
> > + int ret;
> > +
> > pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
> > __func__, valid_params, src_id, src_index,
> > dst_id, dst_host_irq, ia_id, vint, global_event,
> > vint_status_bit);
> > - return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> > - dst_id, dst_host_irq, ia_id, vint,
> > - global_event, vint_status_bit, s_host,
> > - TI_SCI_MSG_SET_IRQ);
> > + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> > + dst_id, dst_host_irq, ia_id, vint,
> > + global_event, vint_status_bit, s_host,
> > + TI_SCI_MSG_SET_IRQ);
> > +
> > + if (ret)
> > + return ret;
> > +
> > + irq = kzalloc(sizeof(*irq), GFP_KERNEL);
> > + if (!irq)
> > + return -ENOMEM;
> > +
> > + desc = &irq->desc;
> > + desc->valid_params = valid_params;
> > + desc->src_id = src_id;
> > + desc->src_index = src_index;
> > + desc->dst_id = dst_id;
> > + desc->dst_host_irq = dst_host_irq;
> > + desc->ia_id = ia_id;
> > + desc->vint = vint;
> > + desc->global_event = global_event;
> > + desc->vint_status_bit = vint_status_bit;
> > + desc->secondary_host = s_host;
> > +
> > + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc));
> > +
> > + return 0;
> > }
> > /**
> > @@ -2358,15 +2425,46 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params,
> > u16 dst_host_irq, u16 ia_id, u16 vint,
> > u16 global_event, u8 vint_status_bit, u8 s_host)
> > {
> > + struct ti_sci_info *info = handle_to_ti_sci_info(handle);
> > + struct ti_sci_msg_req_manage_irq irq_desc;
> > + struct ti_sci_irq *this_irq;
> > + struct hlist_node *tmp_node;
> > + int ret;
> > +
> > pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
> > __func__, valid_params, src_id, src_index,
> > dst_id, dst_host_irq, ia_id, vint, global_event,
> > vint_status_bit);
> > - return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> > - dst_id, dst_host_irq, ia_id, vint,
> > - global_event, vint_status_bit, s_host,
> > - TI_SCI_MSG_FREE_IRQ);
> > + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
> > + dst_id, dst_host_irq, ia_id, vint,
> > + global_event, vint_status_bit, s_host,
> > + TI_SCI_MSG_FREE_IRQ);
> > +
> > + if (ret)
> > + return ret;
> > +
> > + irq_desc.valid_params = valid_params;
> > + irq_desc.src_id = src_id;
> > + irq_desc.src_index = src_index;
> > + irq_desc.dst_id = dst_id;
> > + irq_desc.dst_host_irq = dst_host_irq;
> > + irq_desc.ia_id = ia_id;
> > + irq_desc.vint = vint;
> > + irq_desc.global_event = global_event;
> > + irq_desc.vint_status_bit = vint_status_bit;
> > + irq_desc.secondary_host = s_host;
> > +
> > + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node,
> > + ti_sci_irq_hash(&irq_desc)) {
> > + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) {
> > + hlist_del(&this_irq->node);
> > + kfree(this_irq);
> > + return 0;
>
>
> IMO, you can restrict saving of irq and list management to fw having
>
> BOARDCFG_MANAGED capability.
>
> Dhurva ?
Yes I agree with Udit, we should gate hash operations by firmware capability.
Everywhere else you'll need to make it conditional accordingly.
Also, how much is the IRQ count usually? If IRQ count is typically small (< 50),
then won't a simple linked list be more efficient than a hash table? The
code becomes a bit more readable too that way IMO.
Take a call based on if there's really that many IRQs that LL's become
less practical.
--
Best regards,
Dhruva Gole
Texas Instruments Incorporated
On 12/17/25 6:29 AM, Dhruva Gole wrote:
> On Dec 16, 2025 at 08:17:24 +0530, Kumar, Udit wrote:
>>
>> On 12/5/2025 7:58 PM, Thomas Richard (TI.com) wrote:
>>> In BOARDCFG_MANAGED mode, the firmware cannot restore IRQs during
>>> resume. This responsibility is delegated to the ti_sci driver,
>>> which maintains an internal list of all requested IRQs. This list
>>> is updated on each set/free operation, and all IRQs are restored
>>> during the resume_noirq() phase.
>>>
>>> Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
[...]
>>> +
>>> + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node,
>>> + ti_sci_irq_hash(&irq_desc)) {
>>> + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) {
>>> + hlist_del(&this_irq->node);
>>> + kfree(this_irq);
>>> + return 0;
>>
>>
>> IMO, you can restrict saving of irq and list management to fw having
>>
>> BOARDCFG_MANAGED capability.
>>
>> Dhurva ?
>
> Yes I agree with Udit, we should gate hash operations by firmware capability.
> Everywhere else you'll need to make it conditional accordingly.
ack
>
> Also, how much is the IRQ count usually? If IRQ count is typically small (< 50),
> then won't a simple linked list be more efficient than a hash table? The
> code becomes a bit more readable too that way IMO.
> Take a call based on if there's really that many IRQs that LL's become
> less practical.
>
I tested a TI kernel on J721S2 and I got 60 entries. I guess we can
expect this number to grow with the next SOCs. But maybe the test does
not reflect the usual cases.
Best Regards,
Thomas
© 2016 - 2025 Red Hat, Inc.