mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2026-07-27 00:11:30 +01:00
lib: utils/irqchip/imsic: track IRQ enable state and restore EIE on warm init
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 <pawandeep.oza@oss.qualcomm.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260721214833.687361-6-pawandeep.oza@oss.qualcomm.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
committed by
Anup Patel
parent
193b1d9e7e
commit
b2ead3b037
@@ -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;
|
||||
|
||||
@@ -80,23 +85,54 @@ int sbi_irqchip_process_hwirq(struct sbi_irqchip_device *chip, u32 hwirq)
|
||||
return data->raw_handler(chip, hwirq);
|
||||
}
|
||||
|
||||
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_hwirq_enabled(struct sbi_irqchip_device *chip,
|
||||
u32 hwirq)
|
||||
{
|
||||
return !!(sbi_irqchip_get_irq_state(chip, hwirq) & IRQ_ENABLED);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
data = &chip->hwirqs[hwirq];
|
||||
if (sbi_irqchip_is_hwirq_enabled(chip, hwirq))
|
||||
return SBI_EALREADY;
|
||||
|
||||
if (chip->hwirq_unmask)
|
||||
chip->hwirq_unmask(chip, hwirq);
|
||||
|
||||
data->irq_state |= IRQ_ENABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sbi_irqchip_mask_hwirq(struct sbi_irqchip_device *chip, u32 hwirq)
|
||||
{
|
||||
struct sbi_irqchip_hwirq_data *data;
|
||||
|
||||
if (!chip || chip->num_hwirq <= hwirq)
|
||||
return SBI_EINVAL;
|
||||
|
||||
if (!sbi_irqchip_is_hwirq_enabled(chip, hwirq))
|
||||
return SBI_EALREADY;
|
||||
|
||||
if (chip->hwirq_mask)
|
||||
chip->hwirq_mask(chip, hwirq);
|
||||
|
||||
data = &chip->hwirqs[hwirq];
|
||||
data->irq_state &= ~IRQ_ENABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user