From: Marc Zyngier <maz@kernel.org>
To: Johan Hovold <johan+linaro@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
x86@kernel.org, platform-driver-x86@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
Dmitry Torokhov <dtor@chromium.org>,
Jon Hunter <jonathanh@nvidia.com>,
Hsin-Yi Wang <hsinyi@chromium.org>,
Mark-PK Tsai <mark-pk.tsai@mediatek.com>
Subject: Re: [PATCH v5 06/19] irqdomain: Fix mapping-creation race
Date: Thu, 09 Feb 2023 14:03:19 +0000 [thread overview]
Message-ID: <86edqzylzs.wl-maz@kernel.org> (raw)
In-Reply-To: <20230209132323.4599-7-johan+linaro@kernel.org>
On Thu, 09 Feb 2023 13:23:10 +0000,
Johan Hovold <johan+linaro@kernel.org> wrote:
>
> Parallel probing of devices that share interrupts (e.g. when a driver
> uses asynchronous probing) can currently result in two mappings for the
> same hardware interrupt to be created due to missing serialisation.
>
> Make sure to hold the irq_domain_mutex when creating mappings so that
> looking for an existing mapping before creating a new one is done
> atomically.
>
> Fixes: 765230b5f084 ("driver-core: add asynchronous probing support for drivers")
> Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings")
> Link: https://lore.kernel.org/r/YuJXMHoT4ijUxnRb@hovoldconsulting.com
> Cc: stable@vger.kernel.org # 4.8
> Cc: Dmitry Torokhov <dtor@chromium.org>
> Cc: Jon Hunter <jonathanh@nvidia.com>
> Tested-by: Hsin-Yi Wang <hsinyi@chromium.org>
> Tested-by: Mark-PK Tsai <mark-pk.tsai@mediatek.com>
> Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
> ---
> kernel/irq/irqdomain.c | 55 ++++++++++++++++++++++++++++++------------
> 1 file changed, 40 insertions(+), 15 deletions(-)
>
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 7b57949bc79c..1ddb01bd49a4 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -25,6 +25,9 @@ static DEFINE_MUTEX(irq_domain_mutex);
>
> static struct irq_domain *irq_default_domain;
>
> +static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
> + unsigned int nr_irqs, int node, void *arg,
> + bool realloc, const struct irq_affinity_desc *affinity);
> static void irq_domain_check_hierarchy(struct irq_domain *domain);
>
> struct irqchip_fwid {
> @@ -682,9 +685,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
> EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
> #endif
>
> -static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
> - irq_hw_number_t hwirq,
> - const struct irq_affinity_desc *affinity)
> +static unsigned int irq_create_mapping_affinity_locked(struct irq_domain *domain,
> + irq_hw_number_t hwirq,
> + const struct irq_affinity_desc *affinity)
> {
> struct device_node *of_node = irq_domain_get_of_node(domain);
> int virq;
> @@ -699,7 +702,7 @@ static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
> return 0;
> }
>
> - if (irq_domain_associate(domain, virq, hwirq)) {
> + if (irq_domain_associate_locked(domain, virq, hwirq)) {
> irq_free_desc(virq);
> return 0;
> }
> @@ -735,14 +738,20 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
> return 0;
> }
>
> + mutex_lock(&irq_domain_mutex);
> +
> /* Check if mapping already exists */
> virq = irq_find_mapping(domain, hwirq);
> if (virq) {
> pr_debug("existing mapping on virq %d\n", virq);
> - return virq;
> + goto out;
> }
>
> - return __irq_create_mapping_affinity(domain, hwirq, affinity);
> + virq = irq_create_mapping_affinity_locked(domain, hwirq, affinity);
> +out:
> + mutex_unlock(&irq_domain_mutex);
> +
> + return virq;
> }
> EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
>
> @@ -809,6 +818,8 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
> if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))
> type &= IRQ_TYPE_SENSE_MASK;
>
> + mutex_lock(&irq_domain_mutex);
> +
> /*
> * If we've already configured this interrupt,
> * don't do it again, or hell will break loose.
> @@ -821,7 +832,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
> * interrupt number.
> */
> if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
> - return virq;
> + goto out;
>
> /*
> * If the trigger type has not been set yet, then set
> @@ -830,36 +841,43 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
> if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
> irq_data = irq_get_irq_data(virq);
> if (!irq_data)
> - return 0;
> + goto err;
>
> irqd_set_trigger_type(irq_data, type);
> - return virq;
> + goto out;
> }
>
> pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",
> hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));
> - return 0;
> + goto err;
> }
>
> if (irq_domain_is_hierarchy(domain)) {
> - virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
> + virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE,
> + fwspec, false, NULL);
> if (virq <= 0)
> - return 0;
> + goto err;
> } else {
> /* Create mapping */
> - virq = __irq_create_mapping_affinity(domain, hwirq, NULL);
> + virq = irq_create_mapping_affinity_locked(domain, hwirq, NULL);
> if (!virq)
> - return virq;
> + goto err;
> }
>
> irq_data = irq_get_irq_data(virq);
> if (WARN_ON(!irq_data))
> - return 0;
> + goto err;
>
> /* Store trigger type */
> irqd_set_trigger_type(irq_data, type);
> +out:
> + mutex_unlock(&irq_domain_mutex);
>
> return virq;
> +err:
> + mutex_unlock(&irq_domain_mutex);
> +
> + return 0;
nit: it'd look better if we had a single exit path with the unlock,
setting virq to 0 on failure. Not a big deal, as this can be tidied up
when applied.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: Johan Hovold <johan+linaro@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
x86@kernel.org, platform-driver-x86@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
Dmitry Torokhov <dtor@chromium.org>,
Jon Hunter <jonathanh@nvidia.com>,
Hsin-Yi Wang <hsinyi@chromium.org>,
Mark-PK Tsai <mark-pk.tsai@mediatek.com>
Subject: Re: [PATCH v5 06/19] irqdomain: Fix mapping-creation race
Date: Thu, 09 Feb 2023 14:03:19 +0000 [thread overview]
Message-ID: <86edqzylzs.wl-maz@kernel.org> (raw)
In-Reply-To: <20230209132323.4599-7-johan+linaro@kernel.org>
On Thu, 09 Feb 2023 13:23:10 +0000,
Johan Hovold <johan+linaro@kernel.org> wrote:
>
> Parallel probing of devices that share interrupts (e.g. when a driver
> uses asynchronous probing) can currently result in two mappings for the
> same hardware interrupt to be created due to missing serialisation.
>
> Make sure to hold the irq_domain_mutex when creating mappings so that
> looking for an existing mapping before creating a new one is done
> atomically.
>
> Fixes: 765230b5f084 ("driver-core: add asynchronous probing support for drivers")
> Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings")
> Link: https://lore.kernel.org/r/YuJXMHoT4ijUxnRb@hovoldconsulting.com
> Cc: stable@vger.kernel.org # 4.8
> Cc: Dmitry Torokhov <dtor@chromium.org>
> Cc: Jon Hunter <jonathanh@nvidia.com>
> Tested-by: Hsin-Yi Wang <hsinyi@chromium.org>
> Tested-by: Mark-PK Tsai <mark-pk.tsai@mediatek.com>
> Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
> ---
> kernel/irq/irqdomain.c | 55 ++++++++++++++++++++++++++++++------------
> 1 file changed, 40 insertions(+), 15 deletions(-)
>
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 7b57949bc79c..1ddb01bd49a4 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -25,6 +25,9 @@ static DEFINE_MUTEX(irq_domain_mutex);
>
> static struct irq_domain *irq_default_domain;
>
> +static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
> + unsigned int nr_irqs, int node, void *arg,
> + bool realloc, const struct irq_affinity_desc *affinity);
> static void irq_domain_check_hierarchy(struct irq_domain *domain);
>
> struct irqchip_fwid {
> @@ -682,9 +685,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
> EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
> #endif
>
> -static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
> - irq_hw_number_t hwirq,
> - const struct irq_affinity_desc *affinity)
> +static unsigned int irq_create_mapping_affinity_locked(struct irq_domain *domain,
> + irq_hw_number_t hwirq,
> + const struct irq_affinity_desc *affinity)
> {
> struct device_node *of_node = irq_domain_get_of_node(domain);
> int virq;
> @@ -699,7 +702,7 @@ static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
> return 0;
> }
>
> - if (irq_domain_associate(domain, virq, hwirq)) {
> + if (irq_domain_associate_locked(domain, virq, hwirq)) {
> irq_free_desc(virq);
> return 0;
> }
> @@ -735,14 +738,20 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
> return 0;
> }
>
> + mutex_lock(&irq_domain_mutex);
> +
> /* Check if mapping already exists */
> virq = irq_find_mapping(domain, hwirq);
> if (virq) {
> pr_debug("existing mapping on virq %d\n", virq);
> - return virq;
> + goto out;
> }
>
> - return __irq_create_mapping_affinity(domain, hwirq, affinity);
> + virq = irq_create_mapping_affinity_locked(domain, hwirq, affinity);
> +out:
> + mutex_unlock(&irq_domain_mutex);
> +
> + return virq;
> }
> EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
>
> @@ -809,6 +818,8 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
> if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))
> type &= IRQ_TYPE_SENSE_MASK;
>
> + mutex_lock(&irq_domain_mutex);
> +
> /*
> * If we've already configured this interrupt,
> * don't do it again, or hell will break loose.
> @@ -821,7 +832,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
> * interrupt number.
> */
> if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
> - return virq;
> + goto out;
>
> /*
> * If the trigger type has not been set yet, then set
> @@ -830,36 +841,43 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
> if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
> irq_data = irq_get_irq_data(virq);
> if (!irq_data)
> - return 0;
> + goto err;
>
> irqd_set_trigger_type(irq_data, type);
> - return virq;
> + goto out;
> }
>
> pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",
> hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));
> - return 0;
> + goto err;
> }
>
> if (irq_domain_is_hierarchy(domain)) {
> - virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
> + virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE,
> + fwspec, false, NULL);
> if (virq <= 0)
> - return 0;
> + goto err;
> } else {
> /* Create mapping */
> - virq = __irq_create_mapping_affinity(domain, hwirq, NULL);
> + virq = irq_create_mapping_affinity_locked(domain, hwirq, NULL);
> if (!virq)
> - return virq;
> + goto err;
> }
>
> irq_data = irq_get_irq_data(virq);
> if (WARN_ON(!irq_data))
> - return 0;
> + goto err;
>
> /* Store trigger type */
> irqd_set_trigger_type(irq_data, type);
> +out:
> + mutex_unlock(&irq_domain_mutex);
>
> return virq;
> +err:
> + mutex_unlock(&irq_domain_mutex);
> +
> + return 0;
nit: it'd look better if we had a single exit path with the unlock,
setting virq to 0 on failure. Not a big deal, as this can be tidied up
when applied.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-02-09 14:03 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-09 13:23 [PATCH v5 00/19] irqdomain: fix mapping race and clean up locking Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 01/19] irqdomain: Fix association race Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 02/19] irqdomain: Fix disassociation race Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 03/19] irqdomain: Drop bogus fwspec-mapping error handling Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 04/19] irqdomain: Look for existing mapping only once Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 05/19] irqdomain: Refactor __irq_domain_alloc_irqs() Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 06/19] irqdomain: Fix mapping-creation race Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 14:03 ` Marc Zyngier [this message]
2023-02-09 14:03 ` Marc Zyngier
2023-02-10 9:10 ` Johan Hovold
2023-02-10 9:10 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 07/19] irqdomain: Drop revmap mutex Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 08/19] irqdomain: Drop dead domain-name assignment Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 09/19] irqdomain: Drop leftover brackets Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 10/19] irqdomain: Clean up irq_domain_push/pop_irq() Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 11/19] x86/ioapic: Use irq_domain_create_hierarchy() Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 12/19] x86/apic: " Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 13/19] irqchip/alpine-msi: Use irq_domain_add_hierarchy() Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 14/19] irqchip/gic-v2m: Use irq_domain_create_hierarchy() Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 15/19] irqchip/gic-v3-its: " Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 16/19] irqchip/gic-v3-mbi: " Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 17/19] irqchip/loongson-pch-msi: " Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 18/19] irqchip/mvebu-odmi: " Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 13:23 ` [PATCH v5 19/19] irqdomain: Switch to per-domain locking Johan Hovold
2023-02-09 13:23 ` Johan Hovold
2023-02-09 16:00 ` Marc Zyngier
2023-02-09 16:00 ` Marc Zyngier
2023-02-10 9:56 ` Johan Hovold
2023-02-10 9:56 ` Johan Hovold
2023-02-10 11:38 ` Marc Zyngier
2023-02-10 11:38 ` Marc Zyngier
2023-02-10 12:57 ` Johan Hovold
2023-02-10 12:57 ` Johan Hovold
2023-02-10 15:06 ` Marc Zyngier
2023-02-10 15:06 ` Marc Zyngier
2023-02-11 11:35 ` Johan Hovold
2023-02-11 11:35 ` Johan Hovold
2023-02-11 12:52 ` Marc Zyngier
2023-02-11 12:52 ` Marc Zyngier
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=86edqzylzs.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=dtor@chromium.org \
--cc=hsinyi@chromium.org \
--cc=johan+linaro@kernel.org \
--cc=jonathanh@nvidia.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@vger.kernel.org \
--cc=mark-pk.tsai@mediatek.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/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.