diff options
| author | Anup Patel <[email protected]> | 2026-04-23 10:53:37 +0530 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2026-05-12 09:55:58 +0530 |
| commit | d861447b0b0297db5fbe28878f8568a93fcfa965 (patch) | |
| tree | c4337e0d785550676ff63da8d2cd6e350bbf9683 | |
| parent | adb4caf765cc977c8de6534d0bf77df9dd243e41 (diff) | |
lib: sbi_irqchip: Allow marking hardware interrupts as reserved
Some of the hardware interrupts may be special so allow irqchip
drivers to make these hardware interrupts as reserved. Introduce
sbi_irqchip_register_reserved() for this purpose.
Signed-off-by: Anup Patel <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Anup Patel <[email protected]>
| -rw-r--r-- | include/sbi/sbi_irqchip.h | 6 | ||||
| -rw-r--r-- | lib/sbi/sbi_irqchip.c | 44 | ||||
| -rw-r--r-- | lib/utils/irqchip/imsic.c | 7 |
3 files changed, 44 insertions, 13 deletions
diff --git a/include/sbi/sbi_irqchip.h b/include/sbi/sbi_irqchip.h index 9035dcef..880ff49f 100644 --- a/include/sbi/sbi_irqchip.h +++ b/include/sbi/sbi_irqchip.h @@ -101,7 +101,11 @@ int sbi_irqchip_set_raw_handler(struct sbi_irqchip_device *chip, u32 hwirq, /** Register a hardware interrupt handler */ int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip, u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags, - int (*callback)(u32 hwirq, void *opaque), void *opaque); + int (*callback)(u32 hwirq, void *priv), void *priv); + +/** Register a hardware interrupts as reserved */ +int sbi_irqchip_register_reserved(struct sbi_irqchip_device *chip, + u32 first_hwirq, u32 num_hwirq); /** Unregister a hardware interrupt handler */ int sbi_irqchip_unregister_handler(struct sbi_irqchip_device *chip, diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c index ea684303..15ea2211 100644 --- a/lib/sbi/sbi_irqchip.c +++ b/lib/sbi/sbi_irqchip.c @@ -108,13 +108,14 @@ static struct sbi_irqchip_handler *sbi_irqchip_find_handler(struct sbi_irqchip_d int sbi_irqchip_raw_handler_default(struct sbi_irqchip_device *chip, u32 hwirq) { struct sbi_irqchip_handler *h; - int rc; + int rc = SBI_OK; if (!chip || chip->num_hwirq <= hwirq) return SBI_EINVAL; h = sbi_irqchip_find_handler(chip, hwirq); - rc = h->callback(hwirq, h->priv); + if (h->callback) + rc = h->callback(hwirq, h->priv); if (chip->hwirq_eoi) chip->hwirq_eoi(chip, hwirq); @@ -135,20 +136,14 @@ int sbi_irqchip_set_raw_handler(struct sbi_irqchip_device *chip, u32 hwirq, return 0; } -int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip, - u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags, - int (*callback)(u32 hwirq, void *opaque), void *priv) +static int __sbi_irqchip_register_handler(struct sbi_irqchip_device *chip, + u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags, + int (*callback)(u32 hwirq, void *priv), void *priv) { struct sbi_irqchip_handler *h, *th, *nh; u32 i, j; int rc; - if (!chip || !num_hwirq || !callback) - return SBI_EINVAL; - if (chip->num_hwirq <= first_hwirq || - chip->num_hwirq <= (first_hwirq + num_hwirq - 1)) - return SBI_EBAD_RANGE; - for (i = first_hwirq; i < (first_hwirq + num_hwirq); i++) { h = sbi_irqchip_find_handler(chip, i); if (h) @@ -198,6 +193,33 @@ int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip, return 0; } +int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip, + u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags, + int (*callback)(u32 hwirq, void *priv), void *priv) +{ + if (!chip || !num_hwirq || !callback) + return SBI_EINVAL; + if (chip->num_hwirq <= first_hwirq || + chip->num_hwirq <= (first_hwirq + num_hwirq - 1)) + return SBI_EBAD_RANGE; + + return __sbi_irqchip_register_handler(chip, first_hwirq, num_hwirq, hwirq_flags, + callback, priv); +} + +int sbi_irqchip_register_reserved(struct sbi_irqchip_device *chip, + u32 first_hwirq, u32 num_hwirq) +{ + if (!chip || !num_hwirq) + return SBI_EINVAL; + if (chip->num_hwirq <= first_hwirq || + chip->num_hwirq <= (first_hwirq + num_hwirq - 1)) + return SBI_EBAD_RANGE; + + return __sbi_irqchip_register_handler(chip, first_hwirq, num_hwirq, + SBI_HWIRQ_FLAGS_NONE, NULL, NULL); +} + int sbi_irqchip_unregister_handler(struct sbi_irqchip_device *chip, u32 first_hwirq, u32 num_hwirq) { diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c index 877255f8..521d17fe 100644 --- a/lib/utils/irqchip/imsic.c +++ b/lib/utils/irqchip/imsic.c @@ -348,7 +348,7 @@ int imsic_data_check(struct imsic_data *imsic) static int imsic_hwirq_setup(struct sbi_irqchip_device *chip, u32 hwirq, u32 hwirq_flags) { - if (!hwirq || hwirq == IMSIC_IPI_ID || hwirq_flags != SBI_HWIRQ_FLAGS_NONE) + if (hwirq_flags != SBI_HWIRQ_FLAGS_NONE) return SBI_ENOTSUPP; return 0; } @@ -406,6 +406,11 @@ int imsic_cold_irqchip_init(struct imsic_data *imsic) if (rc) return rc; + /* Mark hwirq 0 and IPI hwirq as reserved */ + rc = sbi_irqchip_register_reserved(&imsic_device, 0, IMSIC_IPI_ID + 1); + if (rc) + return rc; + /* Register IPI device */ sbi_ipi_add_device(&imsic_ipi_device); |
