From: Jiang Liu <jiang.liu@linux.intel.com>
To: Qais Yousef <qais.yousef@imgtec.com>,
linux-kernel@vger.kernel.org, tglx@linutronix.de
Cc: marc.zyngier@arm.com, jason@lakedaemon.net, linux-mips@linux-mips.org
Subject: Re: [PATCH 4/6] irq: add a new generic IPI handling code to irq core
Date: Thu, 24 Sep 2015 00:50:43 +0800 [thread overview]
Message-ID: <5602D863.4040503@linux.intel.com> (raw)
In-Reply-To: <1443019758-20620-5-git-send-email-qais.yousef@imgtec.com>
On 2015/9/23 22:49, Qais Yousef wrote:
> Add a generic mechanism to dynamically allocate an IPI.
>
> With this change the user can call irq_reserve_ipi() to dynamically allocate an
> IPI and use the associate virq to send one to 1 or more cpus.
>
> No irq_get_irq_hwcfg() as I hope we can provide an implementation without
> hardware specific part. Hopefully I'm not being too optimistic :)
>
> Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
> ---
> include/linux/irqdomain.h | 4 ++
> kernel/irq/irqdomain.c | 161 +++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 164 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 76a0e7aaa8df..4bdd7b48d205 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -329,6 +329,10 @@ extern struct ipi_virq *irq_domain_find_ipi_virq(struct irq_domain *d,
> extern int irq_domain_ipi_virq_add_hwirq(struct ipi_virq *v,
> struct ipi_hwirq *h);
> extern struct ipi_hwirq *irq_domain_ipi_virq_rm_hwirq(struct ipi_virq *v);
> +extern unsigned int irq_reserve_ipi(struct irq_domain *domain,
> + const struct cpumask *dest, void *devid);
> +extern void irq_destroy_ipi(unsigned int irq, void *devid);
> +extern void irq_send_ipi(unsigned int irq, const struct cpumask *dest, void *devid);
>
> /* V2 interfaces to support hierarchy IRQ domains. */
> extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 6d911fc8fa52..d38d78a994ca 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -873,7 +873,7 @@ struct ipi_virq *irq_domain_find_ipi_virq(struct irq_domain *d,
> * returns a pointer to ipi_virq struct on success and NULL on failure
> */
> static struct ipi_virq *irq_domain_alloc_ipi_virq(unsigned int virq,
> - struct cpumask *cpumask, void *devid)
> + const struct cpumask *cpumask, void *devid)
> {
> struct ipi_virq *v;
>
> @@ -942,6 +942,165 @@ struct ipi_hwirq *irq_domain_ipi_virq_rm_hwirq(struct ipi_virq *v)
> return h;
> }
>
> +/**
> + * irq_reserve_ipi() - setup an IPI to destination cpumask
> + * @domain: IPI domain
> + * @dest: cpumask of cpus to receive the IPI
> + * @devid: devid that requested the reservation
> + *
> + * Allocate a virq that can be used to send IPI to any CPU in dest mask.
> + *
> + * On success it'll return linux irq number and 0 on failure
> + */
> +unsigned int irq_reserve_ipi(struct irq_domain *domain,
> + const struct cpumask *dest, void *devid)
Hi Qais,
I have caught the idea why we need "dest" here. Per my
understanding, IPI could be sent to any active CPUs and the target
CPUs are specified when calling send_ipi(). What's the benefit or
usage to use "dest" to define a possible target scope here? And
how cpu hotplug?
Thanks!
Gerry
> +{
> + int virq, ret;
> + unsigned int nr_irqs;
> + struct ipi_virq *v;
> +
> + if (domain == NULL)
> + domain = irq_default_domain; /* need a separate ipi_default_domain? */
> +
> + if (domain == NULL) {
> + pr_warn("Must provide a valid IPI domain!\n");
> + return 0;
> + }
> +
> + if (!irq_domain_is_ipi(domain)) {
> + pr_warn("Not an IPI domain!\n");
> + return 0;
> + }
> +
> + if (cpumask_empty(dest)) {
> + pr_warn("Can't reserve IPI due to empty cpumask\n");
> + return 0;
> + }
> +
> + /* always allocate a virq per cpu */
> + nr_irqs = cpumask_weight(dest);
> +
> + virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
> + if (virq <= 0) {
> + pr_warn("Can't reserve IPI, failed to alloc descs\n");
> + return 0;
> + }
> +
> + v = irq_domain_alloc_ipi_virq(virq, dest, devid);
> + if (!v) {
> + pr_warn("Can't reserve IPI, failed to alloc ipi_virq\n");
> + goto free_descs;
> + }
> +
> + /* we are reusing hierarchy alloc function, should we create another one? */
> + virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
> + v, true);
> + if (virq <= 0) {
> + pr_warn("Can't reserve IPI, failed to alloc irqs\n");
> + goto free_ipi;
> + }
> +
> + ret = irq_domain_add_ipi_virq(domain, v);
> + if (ret) {
> + pr_warn("Can't reserve IPI, failed to add ipi_virq\n");
> + goto free_ipi;
> + }
> +
> + return virq;
> +
> +free_ipi:
> + irq_domain_free_ipi_virq(v);
> +free_descs:
> + irq_free_descs(virq, nr_irqs);
> + return 0;
> +}
> +
> +/**
> + * irq_destroy_ipi() - unreserve an IPI that was previously allocated
> + * @irq: linux irq number to be destroyed
> + * @devid: devid that reserved the IPI
> + *
> + * Return an IPI allocated with irq_reserve_ipi() to the system.
> + */
> +void irq_destroy_ipi(unsigned int irq, void *devid)
> +{
> + struct irq_data *irq_data = irq_get_irq_data(irq);
> + struct irq_domain *domain;
> + struct ipi_virq *v;
> +
> + if (!irq || !irq_data)
> + return;
> +
> + domain = irq_data->domain;
> + if (WARN_ON(domain == NULL))
> + return;
> +
> + if (!irq_domain_is_ipi(domain)) {
> + pr_warn("Not an IPI domain!\n");
> + return;
> + }
> +
> + v = irq_domain_find_ipi_virq(domain, irq);
> + if (!v)
> + return;
> +
> + if (v->devid != devid) {
> + pr_warn("Only the device that allocated the IPI can destroy it\n");
> + return;
> + }
> +
> + irq_domain_free_irqs(irq, cpumask_weight(&v->cpumask));
> +
> + v = irq_domain_rm_ipi_virq(domain, irq);
> + irq_domain_free_ipi_virq(v);
> +}
> +
> +/**
> + * irq_send_ipi() - send an IPI to target CPU(s)
> + * @irq: linux irq number from irq_reserve_ipi()
> + * @dest: dest CPU(s), must be the same or a subset of the mask past to
> + * irq_reserve_ipi()
> + * @devid: devid that reserved the IPI
> + *
> + * Sends an IPI to all cpus in dest mask
> + */
> +void irq_send_ipi(unsigned int irq, const struct cpumask *dest, void *devid)
> +{
> + struct irq_data *irq_data = irq_get_irq_data(irq);
> + struct irq_domain *domain;
> + struct ipi_virq *v;
> + struct ipi_hwirq *h;
> +
> + if (!irq || !irq_data)
> + return;
> +
> + domain = irq_data->domain;
> + if (WARN_ON(domain == NULL))
> + return;
> +
> + if (!irq_domain_is_ipi(domain)) {
> + pr_warn("Not an IPI domain!\n");
> + return;
> + }
> +
> + v = irq_domain_find_ipi_virq(domain, irq);
> + if (!v)
> + return;
> +
> + if (v->devid != devid) {
> + pr_warn("Only the device that allocated the IPI can send one\n");
> + return;
> + }
> +
> + if (!cpumask_intersects(&v->cpumask, dest))
> + return;
> +
> + list_for_each_entry(h, &v->mapped_hwirq, link) {
> + if (cpumask_intersects(&h->cpumask, dest))
> + domain->ops->send_ipi(h->hwirq);
> + }
> +}
> +
> #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
> /**
> * irq_domain_add_hierarchy - Add a irqdomain into the hierarchy
>
next prev parent reply other threads:[~2015-09-23 16:50 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-23 14:49 [PATCH 0/6] Implement generic IPI support mechanism Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 14:49 ` [PATCH 1/6] irqdomain: add new IRQ_DOMAIN_FLAGS_IPI Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 14:49 ` [PATCH 2/6] irqdomain: add a new send_ipi() to irq_domain_ops Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 16:44 ` Jiang Liu
2015-09-24 8:12 ` Qais Yousef
2015-09-24 8:12 ` Qais Yousef
2015-09-23 14:49 ` [PATCH 3/6] irqdomain: add struct irq_hwcfg and helper functions Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 14:49 ` [PATCH 4/6] irq: add a new generic IPI handling code to irq core Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 16:50 ` Jiang Liu [this message]
2015-09-24 8:26 ` Qais Yousef
2015-09-24 8:26 ` Qais Yousef
2015-09-29 16:15 ` Thomas Gleixner
2015-09-23 14:49 ` [PATCH 5/6] irqchip: mips-gic: add a IPI hierarchy domain Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 14:49 ` [PATCH 6/6] irqchip: mips-gic: use the new generic IPI API Qais Yousef
2015-09-23 14:49 ` Qais Yousef
2015-09-23 16:54 ` [PATCH 0/6] Implement generic IPI support mechanism Jiang Liu
2015-09-24 8:39 ` Qais Yousef
2015-09-24 8:39 ` Qais Yousef
2015-09-29 20:48 ` Thomas Gleixner
2015-09-30 13:34 ` Qais Yousef
2015-09-30 13:34 ` Qais Yousef
2015-09-30 14:03 ` Thomas Gleixner
2015-09-30 14:08 ` Qais Yousef
2015-09-30 14:08 ` Qais Yousef
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=5602D863.4040503@linux.intel.com \
--to=jiang.liu@linux.intel.com \
--cc=jason@lakedaemon.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@linux-mips.org \
--cc=marc.zyngier@arm.com \
--cc=qais.yousef@imgtec.com \
--cc=tglx@linutronix.de \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.