summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <[email protected]>2026-04-23 10:53:37 +0530
committerAnup Patel <[email protected]>2026-05-12 09:55:58 +0530
commitd861447b0b0297db5fbe28878f8568a93fcfa965 (patch)
treec4337e0d785550676ff63da8d2cd6e350bbf9683
parentadb4caf765cc977c8de6534d0bf77df9dd243e41 (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.h6
-rw-r--r--lib/sbi/sbi_irqchip.c44
-rw-r--r--lib/utils/irqchip/imsic.c7
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);