public inbox for opensbi@lists.infradead.org
 help / color / mirror / Atom feed
From: Raymond Mao <raymondmaoca@gmail.com>
To: Anup Patel <anup.patel@oss.qualcomm.com>
Cc: Atish Patra <atish.patra@linux.dev>,
	Andrew Jones <andrew.jones@oss.qualcomm.com>,
	Dave Patel <dave.patel@riscstar.com>,
	Samuel Holland <samuel.holland@sifive.com>,
	Anup Patel <anup@brainfault.org>,
	opensbi@lists.infradead.org,
	Anup Patel <anup.patel@oss.qualcomm.com>
Subject: Re: [PATCH 8/8] lib: sbi_irqchip: Allow registering interrupt handlers
Date: Mon, 9 Feb 2026 15:34:31 -0500	[thread overview]
Message-ID: <1a7845c2-8272-472c-a3c4-81da4ff1601e@gmail.com> (raw)
In-Reply-To: <20260207102602.2917520-9-anup.patel@oss.qualcomm.com>

Hi Anup,

On 2026-02-07 5:26 a.m., anup.patel at oss.qualcomm.com (Anup Patel) wrote:
> To handle external interrupts in M-mode, the sbi_irqchip framework
> must allow registering interrupt handlers from device drivers.
>
> Signed-off-by: Anup Patel <anup.patel at oss.qualcomm.com>
> ---
>   include/sbi/sbi_irqchip.h |  56 ++++++++++-
>   lib/sbi/sbi_irqchip.c     | 202 +++++++++++++++++++++++++++++++++++++-
>   lib/utils/irqchip/aplic.c |   1 +
>   lib/utils/irqchip/imsic.c |   9 ++
>   lib/utils/irqchip/plic.c  |   1 +
>   5 files changed, 267 insertions(+), 2 deletions(-)
>
> diff --git a/include/sbi/sbi_irqchip.h b/include/sbi/sbi_irqchip.h
> index d2c47ae8..77b54110 100644
> --- a/include/sbi/sbi_irqchip.h
> +++ b/include/sbi/sbi_irqchip.h
> @@ -18,12 +18,21 @@ struct sbi_scratch;
>   
>   /** irqchip hardware device */
>   struct sbi_irqchip_device {
> -	/** Node in the list of irqchip devices */
> +	/** Node in the list of irqchip devices (private) */
>   	struct sbi_dlist node;
>   
> +	/** Internal data of all hardware interrupts of this irqchip (private) */
> +	struct sbi_irqchip_hwirq_data *hwirqs;
> +
> +	/** List of interrupt handlers */
> +	struct sbi_dlist handler_list;
> +
>   	/** Unique ID of this irqchip */
>   	u32 id;
>   
> +	/** Number of hardware IRQs of this irqchip */
> +	u32 num_hwirq;
> +
>   	/** Set of harts targetted by this irqchip */
>   	struct sbi_hartmask target_harts;
>   
> @@ -32,6 +41,21 @@ struct sbi_irqchip_device {
>   
>   	/** Process hardware interrupts from this irqchip */
>   	int (*process_hwirqs)(struct sbi_irqchip_device *chip);
> +
> +	/** Setup a hardware interrupt of this irqchip */
> +	int (*hwirq_setup)(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +	/** Cleanup a hardware interrupt of this irqchip */
> +	void (*hwirq_cleanup)(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +	/** End of hardware interrupt of this irqchip */
> +	void (*hwirq_eoi)(struct sbi_irqchip_device *chip, u32 hwirq);


If hwirq_eoi() is an equivalent of claim(), then hwirq should be a 
pointer of memory, since we need to read and return the IDC_TOPI_ID from 
CLAIMI.

Regards,
Raymond


> +
> +	/** Mask a hardware interrupt of this irqchip */
> +	void (*hwirq_mask)(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +	/** Unmask a hardware interrupt of this irqchip */
> +	void (*hwirq_unmask)(struct sbi_irqchip_device *chip, u32 hwirq);
>   };
>   
>   /**
> @@ -44,6 +68,36 @@ struct sbi_irqchip_device {
>    */
>   int sbi_irqchip_process(void);
>   
> +/**
> + * Process a hwirq of an irqchip device
> + *
> + * This function is called by irqchip drivers to handle hardware
> + * interrupts of the irqchip.
> + */
> +int sbi_irqchip_process_hwirq(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +/** Unmask a hardware interrupt */
> +int sbi_irqchip_unmask_hwirq(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +/** Mask a hardware interrupt */
> +int sbi_irqchip_mask_hwirq(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +/** Default raw hardware interrupt handler */
> +int sbi_irqchip_raw_handler_default(struct sbi_irqchip_device *chip, u32 hwirq);
> +
> +/** Set raw hardware interrupt handler */
> +int sbi_irqchip_set_raw_handler(struct sbi_irqchip_device *chip, u32 hwirq,
> +				int (*raw_hndl)(struct sbi_irqchip_device *, u32));
> +
> +/** Register a hardware interrupt handler */
> +int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
> +				 u32 first_hwirq, u32 num_hwirq,
> +				 int (*callback)(u32 hwirq, void *opaque), void *opaque);
> +
> +/** Unregister a hardware interrupt handler */
> +int sbi_irqchip_unregister_handler(struct sbi_irqchip_device *chip,
> +				   u32 first_hwirq, u32 num_hwirq);
> +
>   /** Find an irqchip device based on unique ID */
>   struct sbi_irqchip_device *sbi_irqchip_find_device(u32 id);
>   
> diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c
> index fb3357f3..736dde6c 100644
> --- a/lib/sbi/sbi_irqchip.c
> +++ b/lib/sbi/sbi_irqchip.c
> @@ -7,10 +7,35 @@
>    *   Anup Patel <apatel at ventanamicro.com>
>    */
>   
> +#include <sbi/sbi_heap.h>
>   #include <sbi/sbi_irqchip.h>
>   #include <sbi/sbi_list.h>
>   #include <sbi/sbi_platform.h>
>   
> +/** Internal irqchip hardware interrupt data */
> +struct sbi_irqchip_hwirq_data {
> +	/** raw hardware interrupt handler */
> +	int (*raw_handler)(struct sbi_irqchip_device *chip, u32 hwirq);
> +};
> +
> +/** Internal irqchip interrupt handler */
> +struct sbi_irqchip_handler {
> +	/** Node in the list of irqchip handlers (private) */
> +	struct sbi_dlist node;
> +
> +	/** First hardware IRQ handled by this handler */
> +	u32 first_hwirq;
> +
> +	/** Number of consecutive hardware IRQs handled by this handler */
> +	u32 num_hwirq;
> +
> +	/** Callback function of this handler */
> +	int (*callback)(u32 hwirq, void *priv);
> +
> +	/** Callback private data */
> +	void *priv;
> +};
> +
>   static SBI_LIST_HEAD(irqchip_list);
>   
>   int sbi_irqchip_process(void)
> @@ -31,6 +56,172 @@ int sbi_irqchip_process(void)
>   	return rc;
>   }
>   
> +int sbi_irqchip_process_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 (!data->raw_handler)
> +		return SBI_ENOENT;
> +
> +	return data->raw_handler(chip, hwirq);
> +}
> +
> +int sbi_irqchip_unmask_hwirq(struct sbi_irqchip_device *chip, u32 hwirq)
> +{
> +	if (!chip || chip->num_hwirq <= hwirq)
> +		return SBI_EINVAL;
> +
> +	if (chip->hwirq_unmask)
> +		chip->hwirq_unmask(chip, hwirq);
> +	return 0;
> +}
> +
> +int sbi_irqchip_mask_hwirq(struct sbi_irqchip_device *chip, u32 hwirq)
> +{
> +	if (!chip || chip->num_hwirq <= hwirq)
> +		return SBI_EINVAL;
> +
> +	if (chip->hwirq_mask)
> +		chip->hwirq_mask(chip, hwirq);
> +	return 0;
> +}
> +
> +static struct sbi_irqchip_handler *sbi_irqchip_find_handler(struct sbi_irqchip_device *chip,
> +							    u32 hwirq)
> +{
> +	struct sbi_irqchip_handler *h;
> +
> +	if (!chip || chip->num_hwirq <= hwirq)
> +		return NULL;
> +
> +	sbi_list_for_each_entry(h, &chip->handler_list, node) {
> +		if (h->first_hwirq <= hwirq && hwirq < (h->first_hwirq + h->num_hwirq))
> +			return h;
> +	}
> +
> +	return NULL;
> +}
> +
> +int sbi_irqchip_raw_handler_default(struct sbi_irqchip_device *chip, u32 hwirq)
> +{
> +	struct sbi_irqchip_handler *h;
> +	int rc;
> +
> +	if (!chip || chip->num_hwirq <= hwirq)
> +		return SBI_EINVAL;
> +
> +	h = sbi_irqchip_find_handler(chip, hwirq);
> +	rc = h->callback(hwirq, h->priv);
> +
> +	if (chip->hwirq_eoi)
> +		chip->hwirq_eoi(chip, hwirq);
> +
> +	return rc;
> +}
> +
> +int sbi_irqchip_set_raw_handler(struct sbi_irqchip_device *chip, u32 hwirq,
> +				int (*raw_hndl)(struct sbi_irqchip_device *, u32))
> +{
> +	struct sbi_irqchip_hwirq_data *data;
> +
> +	if (!chip || chip->num_hwirq <= hwirq)
> +		return SBI_EINVAL;
> +
> +	data = &chip->hwirqs[hwirq];
> +	data->raw_handler = raw_hndl;
> +	return 0;
> +}
> +
> +int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
> +				 u32 first_hwirq, u32 num_hwirq,
> +				 int (*callback)(u32 hwirq, void *opaque), void *priv)
> +{
> +	struct sbi_irqchip_handler *h;
> +	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;
> +
> +	h = sbi_irqchip_find_handler(chip, first_hwirq);
> +	if (h)
> +		return SBI_EALREADY;
> +	h = sbi_irqchip_find_handler(chip, first_hwirq + num_hwirq - 1);
> +	if (h)
> +		return SBI_EALREADY;
> +
> +	h = sbi_zalloc(sizeof(*h));
> +	if (!h)
> +		return SBI_ENOMEM;
> +	h->first_hwirq = first_hwirq;
> +	h->num_hwirq = num_hwirq;
> +	h->callback = callback;
> +	h->priv = priv;
> +	sbi_list_add_tail(&h->node, &chip->handler_list);
> +
> +	if (chip->hwirq_setup) {
> +		for (i = 0; i < h->num_hwirq; i++) {
> +			rc = chip->hwirq_setup(chip, h->first_hwirq + i);
> +			if (rc) {
> +				if (chip->hwirq_cleanup) {
> +					for (j = 0; j < i; j++)
> +						chip->hwirq_cleanup(chip, h->first_hwirq + j);
> +				}
> +				sbi_list_del(&h->node);
> +				sbi_free(h);
> +				return rc;
> +			}
> +		}
> +	}
> +
> +	if (chip->hwirq_unmask) {
> +		for (i = 0; i < h->num_hwirq; i++)
> +			chip->hwirq_unmask(chip, h->first_hwirq + i);
> +	}
> +
> +	return 0;
> +}
> +
> +int sbi_irqchip_unregister_handler(struct sbi_irqchip_device *chip,
> +				   u32 first_hwirq, u32 num_hwirq)
> +{
> +	struct sbi_irqchip_handler *fh, *lh;
> +	u32 i;
> +
> +	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;
> +
> +	fh = sbi_irqchip_find_handler(chip, first_hwirq);
> +	if (!fh || fh->first_hwirq != first_hwirq || fh->num_hwirq != num_hwirq)
> +		return SBI_ENODEV;
> +	lh = sbi_irqchip_find_handler(chip, first_hwirq + num_hwirq - 1);
> +	if (!lh || lh != fh)
> +		return SBI_ENODEV;
> +
> +	if (chip->hwirq_mask) {
> +		for (i = 0; i < fh->num_hwirq; i++)
> +			chip->hwirq_mask(chip, fh->first_hwirq + i);
> +	}
> +
> +	if (chip->hwirq_cleanup) {
> +		for (i = 0; i < fh->num_hwirq; i++)
> +			chip->hwirq_cleanup(chip, fh->first_hwirq + i);
> +	}
> +
> +	sbi_list_del(&fh->node);
> +	return 0;
> +}
> +
>   struct sbi_irqchip_device *sbi_irqchip_find_device(u32 id)
>   {
>   	struct sbi_irqchip_device *chip;
> @@ -47,8 +238,9 @@ int sbi_irqchip_add_device(struct sbi_irqchip_device *chip)
>   {
>   	struct sbi_irqchip_device *c;
>   	struct sbi_hartmask hm;
> +	u32 i;
>   
> -	if (!chip || !sbi_hartmask_weight(&chip->target_harts))
> +	if (!chip || !chip->num_hwirq || !sbi_hartmask_weight(&chip->target_harts))
>   		return SBI_EINVAL;
>   
>   	if (sbi_irqchip_find_device(chip->id))
> @@ -64,6 +256,14 @@ int sbi_irqchip_add_device(struct sbi_irqchip_device *chip)
>   		}
>   	}
>   
> +	chip->hwirqs = sbi_zalloc(sizeof(*chip->hwirqs) * chip->num_hwirq);
> +	if (!chip->hwirqs)
> +		return SBI_ENOMEM;
> +	for (i = 0; i < chip->num_hwirq; i++)
> +		sbi_irqchip_set_raw_handler(chip, i, sbi_irqchip_raw_handler_default);
> +
> +	SBI_INIT_LIST_HEAD(&chip->handler_list);
> +
>   	sbi_list_add_tail(&chip->node, &irqchip_list);
>   	return 0;
>   }
> diff --git a/lib/utils/irqchip/aplic.c b/lib/utils/irqchip/aplic.c
> index d47a810b..ec69c82b 100644
> --- a/lib/utils/irqchip/aplic.c
> +++ b/lib/utils/irqchip/aplic.c
> @@ -307,6 +307,7 @@ int aplic_cold_irqchip_init(struct aplic_data *aplic)
>   
>   	/* Register irqchip device */
>   	aplic->irqchip.id = aplic->unique_id;
> +	aplic->irqchip.num_hwirq = aplic->num_source + 1;
>   	rc = sbi_irqchip_add_device(&aplic->irqchip);
>   	if (rc)
>   		return rc;
> diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c
> index 0f296c89..7559a069 100644
> --- a/lib/utils/irqchip/imsic.c
> +++ b/lib/utils/irqchip/imsic.c
> @@ -346,9 +346,17 @@ int imsic_data_check(struct imsic_data *imsic)
>   	return 0;
>   }
>   
> +static int imsic_hwirq_setup(struct sbi_irqchip_device *chip, u32 hwirq)
> +{
> +	if (!hwirq || hwirq == IMSIC_IPI_ID)
> +		return SBI_ENOTSUPP;
> +	return 0;
> +}
> +
>   static struct sbi_irqchip_device imsic_device = {
>   	.warm_init	= imsic_warm_irqchip_init,
>   	.process_hwirqs	= imsic_process_hwirqs,
> +	.hwirq_setup	= imsic_hwirq_setup,
>   };
>   
>   int imsic_cold_irqchip_init(struct imsic_data *imsic)
> @@ -392,6 +400,7 @@ int imsic_cold_irqchip_init(struct imsic_data *imsic)
>   
>   	/* Register irqchip device */
>   	imsic_device.id = imsic->unique_id;
> +	imsic_device.num_hwirq = imsic->num_ids + 1;
>   	sbi_hartmask_set_all(&imsic_device.target_harts);
>   	rc = sbi_irqchip_add_device(&imsic_device);
>   	if (rc)
> diff --git a/lib/utils/irqchip/plic.c b/lib/utils/irqchip/plic.c
> index 973f7c2a..2d721724 100644
> --- a/lib/utils/irqchip/plic.c
> +++ b/lib/utils/irqchip/plic.c
> @@ -281,6 +281,7 @@ int plic_cold_irqchip_init(struct plic_data *plic)
>   
>   	/* Register irqchip device */
>   	plic->irqchip.id = plic->unique_id;
> +	plic->irqchip.num_hwirq = plic->num_src + 1;
>   	plic->irqchip.warm_init = plic_warm_irqchip_init;
>   	return sbi_irqchip_add_device(&plic->irqchip);
>   }

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

  parent reply	other threads:[~2026-02-09 20:34 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-07 10:25 [PATCH 0/8] Extend irqchip framework for M-mode interrupts Anup Patel
2026-02-07 10:25 ` [PATCH 1/8] lib: sbi_irqchip: Use chip as variable name for irqchip device Anup Patel
2026-02-07 10:25 ` [PATCH 2/8] lib: sbi_irqchip: Rename irq_handle() callback to process_hwirqs() Anup Patel
2026-02-07 10:25 ` [PATCH 3/8] lib: utils/irqchip: Fix context_map init in irqchip_plic_update_context_map() Anup Patel
2026-02-07 10:25 ` [PATCH 4/8] lib: utils/irqchip: Add IDC to hartindex map in struct aplic_data Anup Patel
2026-02-09 16:50   ` Andrew Jones
2026-02-13  3:57     ` Anup Patel
2026-02-07 10:25 ` [PATCH 5/8] lib: sbi_irqchip: Support irqchip device targetting subset of harts Anup Patel
2026-02-09 16:50   ` Andrew Jones
2026-02-13  3:59     ` Anup Patel
2026-02-09 17:03   ` Samuel Holland
2026-02-13  4:01     ` Anup Patel
2026-02-09 20:25   ` Raymond Mao
2026-02-10 16:09     ` Anup Patel
2026-02-11 15:02       ` Raymond Mao
2026-02-11 15:43         ` Anup Patel
2026-02-11 17:49           ` Raymond Mao
2026-02-07 10:26 ` [PATCH 6/8] lib: utils/irqchip: Add unique_id to plic, aplic, and imsic data Anup Patel
2026-02-07 10:26 ` [PATCH 7/8] lib: sbi_irqchip: Associate 32-bit unique ID for each irqchip device Anup Patel
2026-02-07 10:26 ` [PATCH 8/8] lib: sbi_irqchip: Allow registering interrupt handlers Anup Patel
2026-02-09 16:52   ` Andrew Jones
2026-02-09 17:19   ` Samuel Holland
2026-02-09 20:34   ` Raymond Mao [this message]
     [not found]   ` <CAMkFH19feRsme6Mfr1vQ7hSnr2yhFMivNpGkwfTT2uSV3ojnjg@mail.gmail.com>
2026-02-10 16:39     ` Anup Patel
2026-02-10 16:57       ` Raymond Mao
2026-02-11 17:30         ` Anup Patel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1a7845c2-8272-472c-a3c4-81da4ff1601e@gmail.com \
    --to=raymondmaoca@gmail.com \
    --cc=andrew.jones@oss.qualcomm.com \
    --cc=anup.patel@oss.qualcomm.com \
    --cc=anup@brainfault.org \
    --cc=atish.patra@linux.dev \
    --cc=dave.patel@riscstar.com \
    --cc=opensbi@lists.infradead.org \
    --cc=samuel.holland@sifive.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox