--- /dev/null
+From f6044cc3030e139f60c281386f28bda6e3049d66 Mon Sep 17 00:00:00 2001
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Date: Wed, 1 Feb 2023 15:59:44 +0000
+Subject: crypto: qat - fix out-of-bounds read
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+commit f6044cc3030e139f60c281386f28bda6e3049d66 upstream.
+
+When preparing an AER-CTR request, the driver copies the key provided by
+the user into a data structure that is accessible by the firmware.
+If the target device is QAT GEN4, the key size is rounded up by 16 since
+a rounded up size is expected by the device.
+If the key size is rounded up before the copy, the size used for copying
+the key might be bigger than the size of the region containing the key,
+causing an out-of-bounds read.
+
+Fix by doing the copy first and then update the keylen.
+
+This is to fix the following warning reported by KASAN:
+
+ [ 138.150574] BUG: KASAN: global-out-of-bounds in qat_alg_skcipher_init_com.isra.0+0x197/0x250 [intel_qat]
+ [ 138.150641] Read of size 32 at addr ffffffff88c402c0 by task cryptomgr_test/2340
+
+ [ 138.150651] CPU: 15 PID: 2340 Comm: cryptomgr_test Not tainted 6.2.0-rc1+ #45
+ [ 138.150659] Hardware name: Intel Corporation ArcherCity/ArcherCity, BIOS EGSDCRB1.86B.0087.D13.2208261706 08/26/2022
+ [ 138.150663] Call Trace:
+ [ 138.150668] <TASK>
+ [ 138.150922] kasan_check_range+0x13a/0x1c0
+ [ 138.150931] memcpy+0x1f/0x60
+ [ 138.150940] qat_alg_skcipher_init_com.isra.0+0x197/0x250 [intel_qat]
+ [ 138.151006] qat_alg_skcipher_init_sessions+0xc1/0x240 [intel_qat]
+ [ 138.151073] crypto_skcipher_setkey+0x82/0x160
+ [ 138.151085] ? prepare_keybuf+0xa2/0xd0
+ [ 138.151095] test_skcipher_vec_cfg+0x2b8/0x800
+
+Fixes: 67916c951689 ("crypto: qat - add AES-CTR support for QAT GEN4 devices")
+Cc: <stable@vger.kernel.org>
+Reported-by: Vladis Dronov <vdronov@redhat.com>
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Fiona Trahe <fiona.trahe@intel.com>
+Reviewed-by: Vladis Dronov <vdronov@redhat.com>
+Tested-by: Vladis Dronov <vdronov@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/qat/qat_common/qat_algs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/crypto/qat/qat_common/qat_algs.c
++++ b/drivers/crypto/qat/qat_common/qat_algs.c
+@@ -435,8 +435,8 @@ static void qat_alg_skcipher_init_com(st
+ } else if (aes_v2_capable && mode == ICP_QAT_HW_CIPHER_CTR_MODE) {
+ ICP_QAT_FW_LA_SLICE_TYPE_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE);
+- keylen = round_up(keylen, 16);
+ memcpy(cd->ucs_aes.key, key, keylen);
++ keylen = round_up(keylen, 16);
+ } else {
+ memcpy(cd->aes.key, key, keylen);
+ }
--- /dev/null
+From e3b7ab025e931accdc2c12acf9b75c6197f1c062 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:45 +0100
+Subject: irqdomain: Drop bogus fwspec-mapping error handling
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit e3b7ab025e931accdc2c12acf9b75c6197f1c062 upstream.
+
+In case a newly allocated IRQ ever ends up not having any associated
+struct irq_data it would not even be possible to dispose the mapping.
+
+Replace the bogus disposal with a WARN_ON().
+
+This will also be used to fix a shared-interrupt mapping race, hence the
+CC-stable tag.
+
+Fixes: 1e2a7d78499e ("irqdomain: Don't set type when mapping an IRQ")
+Cc: stable@vger.kernel.org # 4.8
+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>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-4-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -853,13 +853,8 @@ unsigned int irq_create_fwspec_mapping(s
+ }
+
+ irq_data = irq_get_irq_data(virq);
+- if (!irq_data) {
+- if (irq_domain_is_hierarchy(domain))
+- irq_domain_free_irqs(virq, 1);
+- else
+- irq_dispose_mapping(virq);
++ if (WARN_ON(!irq_data))
+ return 0;
+- }
+
+ /* Store trigger type */
+ irqd_set_trigger_type(irq_data, type);
--- /dev/null
+From b06730a571a9ff1ba5bd6b20bf9e50e5a12f1ec6 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:43 +0100
+Subject: irqdomain: Fix association race
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit b06730a571a9ff1ba5bd6b20bf9e50e5a12f1ec6 upstream.
+
+The sanity check for an already mapped virq is done outside of the
+irq_domain_mutex-protected section which means that an (unlikely) racing
+association may not be detected.
+
+Fix this by factoring out the association implementation, which will
+also be used in a follow-on change to fix a shared-interrupt mapping
+race.
+
+Fixes: ddaf144c61da ("irqdomain: Refactor irq_domain_associate_many()")
+Cc: stable@vger.kernel.org # 3.11
+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>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-2-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -559,8 +559,8 @@ static void irq_domain_disassociate(stru
+ irq_domain_clear_mapping(domain, hwirq);
+ }
+
+-int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
+- irq_hw_number_t hwirq)
++static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq,
++ irq_hw_number_t hwirq)
+ {
+ struct irq_data *irq_data = irq_get_irq_data(virq);
+ int ret;
+@@ -573,7 +573,6 @@ int irq_domain_associate(struct irq_doma
+ if (WARN(irq_data->domain, "error: virq%i is already associated", virq))
+ return -EINVAL;
+
+- mutex_lock(&irq_domain_mutex);
+ irq_data->hwirq = hwirq;
+ irq_data->domain = domain;
+ if (domain->ops->map) {
+@@ -590,7 +589,6 @@ int irq_domain_associate(struct irq_doma
+ }
+ irq_data->domain = NULL;
+ irq_data->hwirq = 0;
+- mutex_unlock(&irq_domain_mutex);
+ return ret;
+ }
+
+@@ -601,12 +599,23 @@ int irq_domain_associate(struct irq_doma
+
+ domain->mapcount++;
+ irq_domain_set_mapping(domain, hwirq, irq_data);
+- mutex_unlock(&irq_domain_mutex);
+
+ irq_clear_status_flags(virq, IRQ_NOREQUEST);
+
+ return 0;
+ }
++
++int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
++ irq_hw_number_t hwirq)
++{
++ int ret;
++
++ mutex_lock(&irq_domain_mutex);
++ ret = irq_domain_associate_locked(domain, virq, hwirq);
++ mutex_unlock(&irq_domain_mutex);
++
++ return ret;
++}
+ EXPORT_SYMBOL_GPL(irq_domain_associate);
+
+ void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
--- /dev/null
+From 3f883c38f5628f46b30bccf090faec054088e262 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:44 +0100
+Subject: irqdomain: Fix disassociation race
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 3f883c38f5628f46b30bccf090faec054088e262 upstream.
+
+The global irq_domain_mutex is held when mapping interrupts from
+non-hierarchical domains but currently not when disposing them.
+
+This specifically means that updates of the domain mapcount is racy
+(currently only used for statistics in debugfs).
+
+Make sure to hold the global irq_domain_mutex also when disposing
+mappings from non-hierarchical domains.
+
+Fixes: 9dc6be3d4193 ("genirq/irqdomain: Add map counter")
+Cc: stable@vger.kernel.org # 4.13
+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>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-3-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -538,6 +538,9 @@ static void irq_domain_disassociate(stru
+ return;
+
+ hwirq = irq_data->hwirq;
++
++ mutex_lock(&irq_domain_mutex);
++
+ irq_set_status_flags(irq, IRQ_NOREQUEST);
+
+ /* remove chip and handler */
+@@ -557,6 +560,8 @@ static void irq_domain_disassociate(stru
+
+ /* Clear reverse map for this hwirq */
+ irq_domain_clear_mapping(domain, hwirq);
++
++ mutex_unlock(&irq_domain_mutex);
+ }
+
+ static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq,
--- /dev/null
+From 8932c32c3053accd50702b36e944ac2016cd103c Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:49 +0100
+Subject: irqdomain: Fix domain registration race
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 8932c32c3053accd50702b36e944ac2016cd103c upstream.
+
+Hierarchical domains created using irq_domain_create_hierarchy() are
+currently added to the domain list before having been fully initialised.
+
+This specifically means that a racing allocation request might fail to
+allocate irq data for the inner domains of a hierarchy in case the
+parent domain pointer has not yet been set up.
+
+Note that this is not really any issue for irqchip drivers that are
+registered early (e.g. via IRQCHIP_DECLARE() or IRQCHIP_ACPI_DECLARE())
+but could potentially cause trouble with drivers that are registered
+later (e.g. modular drivers using IRQCHIP_PLATFORM_DRIVER_BEGIN(),
+gpiochip drivers, etc.).
+
+Fixes: afb7da83b9f4 ("irqdomain: Introduce helper function irq_domain_add_hierarchy()")
+Cc: stable@vger.kernel.org # 3.19
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+[ johan: add commit message ]
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-8-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 62 +++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 43 insertions(+), 19 deletions(-)
+
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -126,23 +126,12 @@ void irq_domain_free_fwnode(struct fwnod
+ }
+ EXPORT_SYMBOL_GPL(irq_domain_free_fwnode);
+
+-/**
+- * __irq_domain_add() - Allocate a new irq_domain data structure
+- * @fwnode: firmware node for the interrupt controller
+- * @size: Size of linear map; 0 for radix mapping only
+- * @hwirq_max: Maximum number of interrupts supported by controller
+- * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no
+- * direct mapping
+- * @ops: domain callbacks
+- * @host_data: Controller private data pointer
+- *
+- * Allocates and initializes an irq_domain structure.
+- * Returns pointer to IRQ domain, or NULL on failure.
+- */
+-struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size,
+- irq_hw_number_t hwirq_max, int direct_max,
+- const struct irq_domain_ops *ops,
+- void *host_data)
++static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
++ unsigned int size,
++ irq_hw_number_t hwirq_max,
++ int direct_max,
++ const struct irq_domain_ops *ops,
++ void *host_data)
+ {
+ struct irqchip_fwid *fwid;
+ struct irq_domain *domain;
+@@ -230,12 +219,44 @@ struct irq_domain *__irq_domain_add(stru
+
+ irq_domain_check_hierarchy(domain);
+
++ return domain;
++}
++
++static void __irq_domain_publish(struct irq_domain *domain)
++{
+ mutex_lock(&irq_domain_mutex);
+ debugfs_add_domain_dir(domain);
+ list_add(&domain->link, &irq_domain_list);
+ mutex_unlock(&irq_domain_mutex);
+
+ pr_debug("Added domain %s\n", domain->name);
++}
++
++/**
++ * __irq_domain_add() - Allocate a new irq_domain data structure
++ * @fwnode: firmware node for the interrupt controller
++ * @size: Size of linear map; 0 for radix mapping only
++ * @hwirq_max: Maximum number of interrupts supported by controller
++ * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no
++ * direct mapping
++ * @ops: domain callbacks
++ * @host_data: Controller private data pointer
++ *
++ * Allocates and initializes an irq_domain structure.
++ * Returns pointer to IRQ domain, or NULL on failure.
++ */
++struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size,
++ irq_hw_number_t hwirq_max, int direct_max,
++ const struct irq_domain_ops *ops,
++ void *host_data)
++{
++ struct irq_domain *domain;
++
++ domain = __irq_domain_create(fwnode, size, hwirq_max, direct_max,
++ ops, host_data);
++ if (domain)
++ __irq_domain_publish(domain);
++
+ return domain;
+ }
+ EXPORT_SYMBOL_GPL(__irq_domain_add);
+@@ -1138,12 +1159,15 @@ struct irq_domain *irq_domain_create_hie
+ struct irq_domain *domain;
+
+ if (size)
+- domain = irq_domain_create_linear(fwnode, size, ops, host_data);
++ domain = __irq_domain_create(fwnode, size, size, 0, ops, host_data);
+ else
+- domain = irq_domain_create_tree(fwnode, ops, host_data);
++ domain = __irq_domain_create(fwnode, 0, ~0, 0, ops, host_data);
++
+ if (domain) {
+ domain->parent = parent;
+ domain->flags |= flags;
++
++ __irq_domain_publish(domain);
+ }
+
+ return domain;
--- /dev/null
+From 601363cc08da25747feb87c55573dd54de91d66a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:48 +0100
+Subject: irqdomain: Fix mapping-creation race
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 601363cc08da25747feb87c55573dd54de91d66a upstream.
+
+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>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-7-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 64 +++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 46 insertions(+), 18 deletions(-)
+
+--- 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(s
+ 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
+ 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
+ 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(s
+ 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(s
+ * 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
+@@ -829,35 +840,45 @@ unsigned int irq_create_fwspec_mapping(s
+ */
+ if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
+ irq_data = irq_get_irq_data(virq);
+- if (!irq_data)
+- return 0;
++ if (!irq_data) {
++ virq = 0;
++ goto out;
++ }
+
+ 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;
++ virq = 0;
++ goto out;
+ }
+
+ if (irq_domain_is_hierarchy(domain)) {
+- virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
+- if (virq <= 0)
+- return 0;
++ virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE,
++ fwspec, false, NULL);
++ if (virq <= 0) {
++ virq = 0;
++ goto out;
++ }
+ } 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 out;
+ }
+
+ irq_data = irq_get_irq_data(virq);
+- if (WARN_ON(!irq_data))
+- return 0;
++ if (WARN_ON(!irq_data)) {
++ virq = 0;
++ goto out;
++ }
+
+ /* Store trigger type */
+ irqd_set_trigger_type(irq_data, type);
++out:
++ mutex_unlock(&irq_domain_mutex);
+
+ return virq;
+ }
+@@ -1888,6 +1909,13 @@ void irq_domain_set_info(struct irq_doma
+ irq_set_handler_data(virq, handler_data);
+ }
+
++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)
++{
++ return -EINVAL;
++}
++
+ static void irq_domain_check_hierarchy(struct irq_domain *domain)
+ {
+ }
--- /dev/null
+From 6e6f75c9c98d2d246d90411ff2b6f0cd271f4cba Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:46 +0100
+Subject: irqdomain: Look for existing mapping only once
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 6e6f75c9c98d2d246d90411ff2b6f0cd271f4cba upstream.
+
+Avoid looking for an existing mapping twice when creating a new mapping
+using irq_create_fwspec_mapping() by factoring out the actual allocation
+which is shared with irq_create_mapping_affinity().
+
+The new helper function will also be used to fix a shared-interrupt
+mapping race, hence the Fixes tag.
+
+Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings")
+Cc: stable@vger.kernel.org # 4.8
+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>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-5-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 60 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 33 insertions(+), 27 deletions(-)
+
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -682,6 +682,34 @@ unsigned int irq_create_direct_mapping(s
+ 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)
++{
++ struct device_node *of_node = irq_domain_get_of_node(domain);
++ int virq;
++
++ pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
++
++ /* Allocate a virtual interrupt number */
++ virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
++ affinity);
++ if (virq <= 0) {
++ pr_debug("-> virq allocation failed\n");
++ return 0;
++ }
++
++ if (irq_domain_associate(domain, virq, hwirq)) {
++ irq_free_desc(virq);
++ return 0;
++ }
++
++ pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
++ hwirq, of_node_full_name(of_node), virq);
++
++ return virq;
++}
++
+ /**
+ * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
+ * @domain: domain owning this hardware interrupt or NULL for default domain
+@@ -694,14 +722,11 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapp
+ * on the number returned from that call.
+ */
+ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
+- irq_hw_number_t hwirq,
+- const struct irq_affinity_desc *affinity)
++ irq_hw_number_t hwirq,
++ const struct irq_affinity_desc *affinity)
+ {
+- struct device_node *of_node;
+ int virq;
+
+- pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
+-
+ /* Look for default domain if necessary */
+ if (domain == NULL)
+ domain = irq_default_domain;
+@@ -709,34 +734,15 @@ unsigned int irq_create_mapping_affinity
+ WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq);
+ return 0;
+ }
+- pr_debug("-> using domain @%p\n", domain);
+-
+- of_node = irq_domain_get_of_node(domain);
+
+ /* Check if mapping already exists */
+ virq = irq_find_mapping(domain, hwirq);
+ if (virq) {
+- pr_debug("-> existing mapping on virq %d\n", virq);
++ pr_debug("existing mapping on virq %d\n", virq);
+ return virq;
+ }
+
+- /* Allocate a virtual interrupt number */
+- virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
+- affinity);
+- if (virq <= 0) {
+- pr_debug("-> virq allocation failed\n");
+- return 0;
+- }
+-
+- if (irq_domain_associate(domain, virq, hwirq)) {
+- irq_free_desc(virq);
+- return 0;
+- }
+-
+- pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
+- hwirq, of_node_full_name(of_node), virq);
+-
+- return virq;
++ return __irq_create_mapping_affinity(domain, hwirq, affinity);
+ }
+ EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
+
+@@ -841,7 +847,7 @@ unsigned int irq_create_fwspec_mapping(s
+ return 0;
+ } else {
+ /* Create mapping */
+- virq = irq_create_mapping(domain, hwirq);
++ virq = __irq_create_mapping_affinity(domain, hwirq, NULL);
+ if (!virq)
+ return virq;
+ }
--- /dev/null
+From d55f7f4c58c07beb5050a834bf57ae2ede599c7e Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:47 +0100
+Subject: irqdomain: Refactor __irq_domain_alloc_irqs()
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit d55f7f4c58c07beb5050a834bf57ae2ede599c7e upstream.
+
+Refactor __irq_domain_alloc_irqs() so that it can be called internally
+while holding the irq_domain_mutex.
+
+This will be used to fix a shared-interrupt mapping race, hence the
+Fixes tag.
+
+Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings")
+Cc: stable@vger.kernel.org # 4.8
+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>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-6-johan+linaro@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irqdomain.c | 88 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 48 insertions(+), 40 deletions(-)
+
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -1441,40 +1441,12 @@ int irq_domain_alloc_irqs_hierarchy(stru
+ return domain->ops->alloc(domain, irq_base, nr_irqs, arg);
+ }
+
+-/**
+- * __irq_domain_alloc_irqs - Allocate IRQs from domain
+- * @domain: domain to allocate from
+- * @irq_base: allocate specified IRQ number if irq_base >= 0
+- * @nr_irqs: number of IRQs to allocate
+- * @node: NUMA node id for memory allocation
+- * @arg: domain specific argument
+- * @realloc: IRQ descriptors have already been allocated if true
+- * @affinity: Optional irq affinity mask for multiqueue devices
+- *
+- * Allocate IRQ numbers and initialized all data structures to support
+- * hierarchy IRQ domains.
+- * Parameter @realloc is mainly to support legacy IRQs.
+- * Returns error code or allocated IRQ number
+- *
+- * The whole process to setup an IRQ has been split into two steps.
+- * The first step, __irq_domain_alloc_irqs(), is to allocate IRQ
+- * descriptor and required hardware resources. The second step,
+- * irq_domain_activate_irq(), is to program the hardware with preallocated
+- * resources. In this way, it's easier to rollback when failing to
+- * allocate resources.
+- */
+-int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
+- unsigned int nr_irqs, int node, void *arg,
+- bool realloc, const struct irq_affinity_desc *affinity)
++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)
+ {
+ int i, ret, virq;
+
+- if (domain == NULL) {
+- domain = irq_default_domain;
+- if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n"))
+- return -EINVAL;
+- }
+-
+ if (realloc && irq_base >= 0) {
+ virq = irq_base;
+ } else {
+@@ -1493,24 +1465,18 @@ int __irq_domain_alloc_irqs(struct irq_d
+ goto out_free_desc;
+ }
+
+- mutex_lock(&irq_domain_mutex);
+ ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg);
+- if (ret < 0) {
+- mutex_unlock(&irq_domain_mutex);
++ if (ret < 0)
+ goto out_free_irq_data;
+- }
+
+ for (i = 0; i < nr_irqs; i++) {
+ ret = irq_domain_trim_hierarchy(virq + i);
+- if (ret) {
+- mutex_unlock(&irq_domain_mutex);
++ if (ret)
+ goto out_free_irq_data;
+- }
+ }
+-
++
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_insert_irq(virq + i);
+- mutex_unlock(&irq_domain_mutex);
+
+ return virq;
+
+@@ -1520,6 +1486,48 @@ out_free_desc:
+ irq_free_descs(virq, nr_irqs);
+ return ret;
+ }
++
++/**
++ * __irq_domain_alloc_irqs - Allocate IRQs from domain
++ * @domain: domain to allocate from
++ * @irq_base: allocate specified IRQ number if irq_base >= 0
++ * @nr_irqs: number of IRQs to allocate
++ * @node: NUMA node id for memory allocation
++ * @arg: domain specific argument
++ * @realloc: IRQ descriptors have already been allocated if true
++ * @affinity: Optional irq affinity mask for multiqueue devices
++ *
++ * Allocate IRQ numbers and initialized all data structures to support
++ * hierarchy IRQ domains.
++ * Parameter @realloc is mainly to support legacy IRQs.
++ * Returns error code or allocated IRQ number
++ *
++ * The whole process to setup an IRQ has been split into two steps.
++ * The first step, __irq_domain_alloc_irqs(), is to allocate IRQ
++ * descriptor and required hardware resources. The second step,
++ * irq_domain_activate_irq(), is to program the hardware with preallocated
++ * resources. In this way, it's easier to rollback when failing to
++ * allocate resources.
++ */
++int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
++ unsigned int nr_irqs, int node, void *arg,
++ bool realloc, const struct irq_affinity_desc *affinity)
++{
++ int ret;
++
++ if (domain == NULL) {
++ domain = irq_default_domain;
++ if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n"))
++ return -EINVAL;
++ }
++
++ mutex_lock(&irq_domain_mutex);
++ ret = irq_domain_alloc_irqs_locked(domain, irq_base, nr_irqs, node, arg,
++ realloc, affinity);
++ mutex_unlock(&irq_domain_mutex);
++
++ return ret;
++}
+ EXPORT_SYMBOL_GPL(__irq_domain_alloc_irqs);
+
+ /* The irq_data was moved, fix the revmap to refer to the new location */
selftests-dmabuf-heaps-fix-incorrect-kernel-headers-search-path.patch
selftests-vm-fix-incorrect-kernel-headers-search-path.patch
selftests-seccomp-fix-incorrect-kernel-headers-search-path.patch
+irqdomain-fix-association-race.patch
+irqdomain-fix-disassociation-race.patch
+irqdomain-look-for-existing-mapping-only-once.patch
+irqdomain-drop-bogus-fwspec-mapping-error-handling.patch
+irqdomain-refactor-__irq_domain_alloc_irqs.patch
+irqdomain-fix-mapping-creation-race.patch
+irqdomain-fix-domain-registration-race.patch
+crypto-qat-fix-out-of-bounds-read.patch