Re: [PATCH v2 5/6] lib: utils/irqchip/imsic: track IRQ enable state and restore EIE on warm init
Pawandeep Oza <[email protected]> Sat, 11 Jul 2026 12:32:19 -0700
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <CAAVgOkLLWgAB+SndkPqwrS2WUDy4TpzqYZoFofJYd9WXtne=Pw@mail.gmail.com> |
On Thu, Jul 9, 2026 at 1:34 AM Anup Patel <[email protected]> wrote: > > On Thu, Jun 18, 2026 at 12:16 AM Pawandeep Oza > <[email protected]> wrote: > > > > Add an irq_state field to struct sbi_irqchip_hwirq_data with a single > > IRQ_ENABLED flag (bit 0) to track whether a hardware interrupt has been > > enabled via the irqchip framework. Set IRQ_ENABLED in > > sbi_irqchip_unmask_hwirq() when the unmask callback is invoked. > > > > Add sbi_irqchip_get_irq_state() as a private inline accessor and expose > > sbi_irqchip_is_irq_enabled() as a public API for drivers to query the > > enabled state of a hardware interrupt by chip pointer and hwirq number. > > > > Refactor imsic_local_eix_update() to operate on a single interrupt ID > > instead of a base+count range, simplifying the CSR bit manipulation to > > a direct BIT(id) write without the inner loop. Update all call sites > > accordingly. > > > > Use sbi_irqchip_is_irq_enabled() in imsic_warm_irqchip_init() to > > restore per-EIID EIE CSR state on warm boot and HSM resume based on > > the saved irq_state, replacing the previous blanket disable of all > > interrupts. This ensures that EIIDs enabled during hotplug/warminit > > cycle are correctly re-enabled on the resuming hart without requiring > > software to re-register or re-unmask each interrupt. > > > > Signed-off-by: Oza Pawandeep <[email protected]> > > --- > > include/sbi/sbi_irqchip.h | 4 +++ > > lib/sbi/sbi_irqchip.c | 25 ++++++++++++++++++ > > lib/utils/irqchip/imsic.c | 55 ++++++++++++++++++--------------------- > > 3 files changed, 55 insertions(+), 29 deletions(-) > > > > diff --git a/include/sbi/sbi_irqchip.h b/include/sbi/sbi_irqchip.h > > index e778d747..14b79cbf 100644 > > --- a/include/sbi/sbi_irqchip.h > > +++ b/include/sbi/sbi_irqchip.h > > @@ -162,4 +162,8 @@ int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot); > > /** Exit interrupt controllers */ > > void sbi_irqchip_exit(struct sbi_scratch *scratch); > > > > +/** Check if the interrupt is enabled */ > > +bool sbi_irqchip_is_irq_enabled(struct sbi_irqchip_device *chip, > > + u32 hwirq); > > + > > #endif > > diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c > > index 6d0df02e..49fa4806 100644 > > --- a/lib/sbi/sbi_irqchip.c > > +++ b/lib/sbi/sbi_irqchip.c > > @@ -20,6 +20,11 @@ struct sbi_irqchip_hwirq_data { > > /** raw hardware interrupt handler */ > > int (*raw_handler)(struct sbi_irqchip_device *chip, u32 hwirq); > > > > +#define IRQ_ENABLED BIT(0) > > + /** interrupt state > > + * bit 0 - 1: enabled, 0: disabled */ > > + u32 irq_state; > > + > > /** target hart index */ > > u32 hart_index; > > }; > > @@ -52,6 +57,21 @@ struct sbi_irqchip_hart_data { > > static unsigned long irqchip_hart_data_off; > > static SBI_LIST_HEAD(irqchip_list); > > > > +static inline u32 sbi_irqchip_get_irq_state(struct sbi_irqchip_device *chip, > > + u32 hwirq) > > +{ > > + if (!chip || !chip->hwirqs || hwirq >= chip->num_hwirq) > > + return 0; > > + > > + return chip->hwirqs[hwirq].irq_state; > > +} > > + > > +bool sbi_irqchip_is_irq_enabled(struct sbi_irqchip_device *chip, > > + u32 hwirq) > > +{ > > + return !!(sbi_irqchip_get_irq_state(chip, hwirq) & IRQ_ENABLED); > > +} > > + > > int sbi_irqchip_process(void) > > { > > struct sbi_irqchip_hart_data *hd; > > @@ -79,11 +99,16 @@ int sbi_irqchip_process_hwirq(struct sbi_irqchip_device *chip, u32 hwirq) > > > > int sbi_irqchip_unmask_hwirq(struct sbi_irqchip_device *chip, u32 hwirq) > > { > > + struct sbi_irqchip_hwirq_data *data; > > + > > if (!chip || chip->num_hwirq <= hwirq) > > return SBI_EINVAL; > > This function should fail if the hwirq was already unmasked. > > > > > if (chip->hwirq_unmask) > > chip->hwirq_unmask(chip, hwirq); > > + > > + data = &chip->hwirqs[hwirq]; > > + data->irq_state = data->irq_state | IRQ_ENABLED; > > return 0; > > } > > You need to clear IRQ_ENABLED in sbi_irqchip_mask_hwirq() Oza: how did I miss this ? yeah sure. > > > > > diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c > > index b26fd9ca..dbe76645 100644 > > --- a/lib/utils/irqchip/imsic.c > > +++ b/lib/utils/irqchip/imsic.c > > @@ -223,29 +223,20 @@ static struct sbi_ipi_device imsic_ipi_device = { > > .ipi_send = imsic_ipi_send > > }; > > > > -static void imsic_local_eix_update(unsigned long base_id, > > - unsigned long num_id, bool pend, bool val) > > +static void imsic_local_eix_update(unsigned long id, > > + bool pend, bool val) > > { > > - unsigned long i, isel, ireg; > > - unsigned long id = base_id, last_id = base_id + num_id; > > - > > - while (id < last_id) { > > - isel = id / __riscv_xlen; > > - isel *= __riscv_xlen / IMSIC_EIPx_BITS; > > - isel += (pend) ? IMSIC_EIP0 : IMSIC_EIE0; > > - > > - ireg = 0; > > - for (i = id & (__riscv_xlen - 1); > > - (id < last_id) && (i < __riscv_xlen); i++) { > > - ireg |= BIT(i); > > - id++; > > - } > > + unsigned long isel, ireg = 0; > > > > - if (val) > > - imsic_csr_set(isel, ireg); > > - else > > - imsic_csr_clear(isel, ireg); > > - } > > + isel = id / __riscv_xlen; > > + isel *= __riscv_xlen / IMSIC_EIPx_BITS; > > + isel += (pend) ? IMSIC_EIP0 : IMSIC_EIE0; > > + ireg |= BIT(id); > > + > > + if (val) > > + imsic_csr_set(isel, ireg); > > + else > > + imsic_csr_clear(isel, ireg); > > } > > > > void imsic_local_irqchip_init(void) > > @@ -273,13 +264,14 @@ void imsic_local_irqchip_init(void) > > imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY); > > > > /* Enable IPI */ > > - imsic_local_eix_update(IMSIC_IPI_ID, 1, false, true); > > + imsic_local_eix_update(IMSIC_IPI_ID, false, true); > > } > > > > static int imsic_warm_irqchip_init(struct sbi_irqchip_device *dev) > > { > > struct imsic_data *imsic; > > struct imsic_data *hart_imsic; > > + int i; > > > > imsic = container_of(dev, struct imsic_data, irqchip); > > hart_imsic = imsic_get_data(current_hartindex()); > > @@ -289,11 +281,16 @@ static int imsic_warm_irqchip_init(struct sbi_irqchip_device *dev) > > !hart_imsic->targets_mmode) > > return SBI_EINVAL; > > > > - /* Disable all interrupts */ > > - imsic_local_eix_update(1, imsic->num_ids, false, false); > > + /* enable interrutps based on the irq state */ > > + for (i = 1; i < imsic->num_ids; i++) { > > + if (sbi_irqchip_is_irq_enabled(&imsic->irqchip, i) == true) > > + imsic_local_eix_update(i, true, true); > > + else > > + imsic_local_eix_update(i, false, false); > > + } > > > > /* Clear IPI pending */ > > - imsic_local_eix_update(IMSIC_IPI_ID, 1, true, false); > > + imsic_local_eix_update(IMSIC_IPI_ID, true, false); > > > > /* Local IMSIC initialization */ > > imsic_local_irqchip_init(); > > @@ -393,8 +390,8 @@ static void imsic_hwirq_cleanup(struct sbi_irqchip_device *chip, u32 hwirq) > > if (!imsic || !imsic->targets_mmode) > > return; > > > > - imsic_local_eix_update(hwirq, 1, false, false); > > - imsic_local_eix_update(hwirq, 1, true, false); > > + imsic_local_eix_update(hwirq, false, false); > > + imsic_local_eix_update(hwirq, true, false); > > } > > > > static void imsic_hwirq_eoi(struct sbi_irqchip_device *chip, u32 hwirq) > > @@ -533,7 +530,7 @@ static void imsic_hwirq_mask(struct sbi_irqchip_device *chip, u32 hwirq) > > if (!imsic || !imsic->targets_mmode) > > return; > > > > - imsic_local_eix_update(hwirq, 1, false, false); > > + imsic_local_eix_update(hwirq, false, false); > > } > > > > static void imsic_hwirq_unmask(struct sbi_irqchip_device *chip, u32 hwirq) > > @@ -550,7 +547,7 @@ static void imsic_hwirq_unmask(struct sbi_irqchip_device *chip, u32 hwirq) > > if (!hwirq || hwirq == IMSIC_IPI_ID) > > return; > > > > - imsic_local_eix_update(hwirq, 1, false, true); > > + imsic_local_eix_update(hwirq, false, true); > > > > sbi_printf("imsic_hwirq_unmask: hart=%lu eiid=%u\n", > > (unsigned long)current_hartindex(), hwirq); > > -- > > 2.43.0 > > > > > > -- > > opensbi mailing list > > [email protected] > > http://lists.infradead.org/mailman/listinfo/opensbi > > Regards, > Anup -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi