linux-rt-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts
@ 2019-04-29 14:44 Julien Grall
  2019-04-29 14:44 ` [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie Julien Grall
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

Hi all,

On RT, the function iommu_dma_map_msi_msg expects to be called from preemptible
context. However, this is not always the case resulting a splat with
!CONFIG_DEBUG_ATOMIC_SLEEP:

[   48.875777] BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:974
[   48.875779] in_atomic(): 1, irqs_disabled(): 128, pid: 2103, name: ip
[   48.875782] INFO: lockdep is turned off.
[   48.875784] irq event stamp: 10684
[   48.875786] hardirqs last  enabled at (10683): [<ffff0000110c8d70>] _raw_spin_unlock_irqrestore+0x88/0x90
[   48.875791] hardirqs last disabled at (10684): [<ffff0000110c8b2c>] _raw_spin_lock_irqsave+0x24/0x68
[   48.875796] softirqs last  enabled at (0): [<ffff0000100ec590>] copy_process.isra.1.part.2+0x8d8/0x1970
[   48.875801] softirqs last disabled at (0): [<0000000000000000>]           (null)
[   48.875805] Preemption disabled at:
[   48.875805] [<ffff000010189ae8>] __setup_irq+0xd8/0x6c0
[   48.875811] CPU: 2 PID: 2103 Comm: ip Not tainted 5.0.3-rt1-00007-g42ede9a0fed6 #45
[   48.875815] Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Jan 23 2017
[   48.875817] Call trace:
[   48.875818]  dump_backtrace+0x0/0x140
[   48.875821]  show_stack+0x14/0x20
[   48.875823]  dump_stack+0xa0/0xd4
[   48.875827]  ___might_sleep+0x16c/0x1f8
[   48.875831]  rt_spin_lock+0x5c/0x70
[   48.875835]  iommu_dma_map_msi_msg+0x5c/0x1d8
[   48.875839]  gicv2m_compose_msi_msg+0x3c/0x48
[   48.875843]  irq_chip_compose_msi_msg+0x40/0x58
[   48.875846]  msi_domain_activate+0x38/0x98
[   48.875849]  __irq_domain_activate_irq+0x58/0xa0
[   48.875852]  irq_domain_activate_irq+0x34/0x58
[   48.875855]  irq_activate+0x28/0x30
[   48.875858]  __setup_irq+0x2b0/0x6c0
[   48.875861]  request_threaded_irq+0xdc/0x188
[   48.875865]  sky2_setup_irq+0x44/0xf8
[   48.875868]  sky2_open+0x1a4/0x240
[   48.875871]  __dev_open+0xd8/0x188
[   48.875874]  __dev_change_flags+0x164/0x1f0
[   48.875877]  dev_change_flags+0x20/0x60
[   48.875879]  do_setlink+0x2a0/0xd30
[   48.875882]  __rtnl_newlink+0x5b4/0x6d8
[   48.875885]  rtnl_newlink+0x50/0x78
[   48.875888]  rtnetlink_rcv_msg+0x178/0x640
[   48.875891]  netlink_rcv_skb+0x58/0x118
[   48.875893]  rtnetlink_rcv+0x14/0x20
[   48.875896]  netlink_unicast+0x188/0x200
[   48.875898]  netlink_sendmsg+0x248/0x3d8
[   48.875900]  sock_sendmsg+0x18/0x40
[   48.875904]  ___sys_sendmsg+0x294/0x2d0
[   48.875908]  __sys_sendmsg+0x68/0xb8
[   48.875911]  __arm64_sys_sendmsg+0x20/0x28
[   48.875914]  el0_svc_common+0x90/0x118
[   48.875918]  el0_svc_handler+0x2c/0x80
[   48.875922]  el0_svc+0x8/0xc

This series is a first attempt to rework how MSI are mapped and composed
when an IOMMU is present.

I was able to test the changes in GICv2m and GICv3 ITS. I don't have
hardware for the other interrupt controllers.

Cheers,

Julien Grall (7):
  genirq/msi: Add a new field in msi_desc to store an IOMMU cookie
  iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts
  irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg()
  irqchip/gic-v3-its: Don't map the MSI page in
    its_irq_compose_msi_msg()
  irqchip/ls-scfg-msi: Don't map the MSI page in
    ls_scfg_msi_compose_msg()
  irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b,
    s}i_msg()
  iommu/dma-iommu: Remove iommu_dma_map_msi_msg()

 drivers/iommu/Kconfig             |  1 +
 drivers/iommu/dma-iommu.c         | 49 +++++++++++++++++++++++----------------
 drivers/irqchip/irq-gic-v2m.c     |  8 ++++++-
 drivers/irqchip/irq-gic-v3-its.c  |  5 +++-
 drivers/irqchip/irq-gic-v3-mbi.c  | 15 ++++++++++--
 drivers/irqchip/irq-ls-scfg-msi.c |  7 +++++-
 include/linux/dma-iommu.h         | 22 ++++++++++++++++--
 include/linux/msi.h               | 26 +++++++++++++++++++++
 kernel/irq/Kconfig                |  3 +++
 9 files changed, 109 insertions(+), 27 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-29 15:12   ` Robin Murphy
  2019-04-30 12:53   ` Auger Eric
  2019-04-29 14:44 ` [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts Julien Grall
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

When an MSI doorbell is located downstream of an IOMMU, it is required
to swizzle the physical address with an appropriately-mapped IOVA for any
device attached to one of our DMA ops domain.

At the moment, the allocation of the mapping may be done when composing
the message. However, the composing may be done in non-preemtible
context while the allocation requires to be called from preemptible
context.

A follow-up change will split the current logic in two functions
requiring to keep an IOMMU cookie per MSI.

A new field is introduced in msi_desc to store an IOMMU cookie. As the
cookie may not be required in some configuration, the field is protected
under a new config CONFIG_IRQ_MSI_IOMMU.

A pair of helpers has also been introduced to access the field.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Update the commit message to use imperative mood
        - Protect the field with a new config that will be selected by
        IOMMU_DMA later on
        - Add a set of helpers to access the new field
---
 include/linux/msi.h | 26 ++++++++++++++++++++++++++
 kernel/irq/Kconfig  |  3 +++
 2 files changed, 29 insertions(+)

diff --git a/include/linux/msi.h b/include/linux/msi.h
index 7e9b81c3b50d..82a308c19222 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -77,6 +77,9 @@ struct msi_desc {
 	struct device			*dev;
 	struct msi_msg			msg;
 	struct irq_affinity_desc	*affinity;
+#ifdef CONFIG_IRQ_MSI_IOMMU
+	const void			*iommu_cookie;
+#endif
 
 	union {
 		/* PCI MSI/X specific data */
@@ -119,6 +122,29 @@ struct msi_desc {
 #define for_each_msi_entry_safe(desc, tmp, dev)	\
 	list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
 
+#ifdef CONFIG_IRQ_MSI_IOMMU
+static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
+{
+	return desc->iommu_cookie;
+}
+
+static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
+					     const void *iommu_cookie)
+{
+	desc->iommu_cookie = iommu_cookie;
+}
+#else
+static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
+{
+	return NULL;
+}
+
+static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
+					     const void *iommu_cookie)
+{
+}
+#endif
+
 #ifdef CONFIG_PCI_MSI
 #define first_pci_msi_entry(pdev)	first_msi_entry(&(pdev)->dev)
 #define for_each_pci_msi_entry(desc, pdev)	\
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 5f3e2baefca9..8fee06625c37 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -91,6 +91,9 @@ config GENERIC_MSI_IRQ_DOMAIN
 	select IRQ_DOMAIN_HIERARCHY
 	select GENERIC_MSI_IRQ
 
+config IRQ_MSI_IOMMU
+	bool
+
 config HANDLE_DOMAIN_IRQ
 	bool
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
  2019-04-29 14:44 ` [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-29 15:16   ` Robin Murphy
                     ` (2 more replies)
  2019-04-29 14:44 ` [PATCH v2 3/7] irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg() Julien Grall
                   ` (5 subsequent siblings)
  7 siblings, 3 replies; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

On RT, iommu_dma_map_msi_msg() may be called from non-preemptible
context. This will lead to a splat with CONFIG_DEBUG_ATOMIC_SLEEP as
the function is using spin_lock (they can sleep on RT).

iommu_dma_map_msi_msg() is used to map the MSI page in the IOMMU PT
and update the MSI message with the IOVA.

Only the part to lookup for the MSI page requires to be called in
preemptible context. As the MSI page cannot change over the lifecycle
of the MSI interrupt, the lookup can be cached and re-used later on.

iomma_dma_map_msi_msg() is now split in two functions:
    - iommu_dma_prepare_msi(): This function will prepare the mapping
    in the IOMMU and store the cookie in the structure msi_desc. This
    function should be called in preemptible context.
    - iommu_dma_compose_msi_msg(): This function will update the MSI
    message with the IOVA when the device is behind an IOMMU.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Rework the commit message to use imperative mood
        - Use the MSI accessor to get/set the iommu cookie
        - Don't use ternary on return
        - Select CONFIG_IRQ_MSI_IOMMU
        - Pass an msi_desc rather than the irq number
---
 drivers/iommu/Kconfig     |  1 +
 drivers/iommu/dma-iommu.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 include/linux/dma-iommu.h | 23 +++++++++++++++++++++++
 3 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 6f07f3b21816..eb1c8cd243f9 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -94,6 +94,7 @@ config IOMMU_DMA
 	bool
 	select IOMMU_API
 	select IOMMU_IOVA
+	select IRQ_MSI_IOMMU
 	select NEED_SG_DMA_LENGTH
 
 config FSL_PAMU
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 77aabe637a60..2309f59cefa4 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -888,17 +888,18 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
 	return NULL;
 }
 
-void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
+int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
 {
-	struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
+	struct device *dev = msi_desc_to_dev(desc);
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 	struct iommu_dma_cookie *cookie;
 	struct iommu_dma_msi_page *msi_page;
-	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
 	unsigned long flags;
 
-	if (!domain || !domain->iova_cookie)
-		return;
+	if (!domain || !domain->iova_cookie) {
+		desc->iommu_cookie = NULL;
+		return 0;
+	}
 
 	cookie = domain->iova_cookie;
 
@@ -911,7 +912,37 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
 	msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
 	spin_unlock_irqrestore(&cookie->msi_lock, flags);
 
-	if (WARN_ON(!msi_page)) {
+	msi_desc_set_iommu_cookie(desc, msi_page);
+
+	if (!msi_page)
+		return -ENOMEM;
+	else
+		return 0;
+}
+
+void iommu_dma_compose_msi_msg(struct msi_desc *desc,
+			       struct msi_msg *msg)
+{
+	struct device *dev = msi_desc_to_dev(desc);
+	const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+	const struct iommu_dma_msi_page *msi_page;
+
+	msi_page = msi_desc_get_iommu_cookie(desc);
+
+	if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
+		return;
+
+	msg->address_hi = upper_32_bits(msi_page->iova);
+	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
+	msg->address_lo += lower_32_bits(msi_page->iova);
+}
+
+void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
+{
+	struct msi_desc *desc = irq_get_msi_desc(irq);
+	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
+
+	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
 		/*
 		 * We're called from a void callback, so the best we can do is
 		 * 'fail' by filling the message with obviously bogus values.
@@ -922,8 +953,6 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
 		msg->address_lo = ~0U;
 		msg->data = ~0U;
 	} else {
-		msg->address_hi = upper_32_bits(msi_page->iova);
-		msg->address_lo &= cookie_msi_granule(cookie) - 1;
-		msg->address_lo += lower_32_bits(msi_page->iova);
+		iommu_dma_compose_msi_msg(desc, msg);
 	}
 }
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index e760dc5d1fa8..3fc48fbd6f63 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -71,12 +71,24 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir, unsigned long attrs);
 
 /* The DMA API isn't _quite_ the whole story, though... */
+/*
+ * Map the MSI page in the IOMMU device and store it in @desc
+ *
+ * Return 0 if succeeded other an error if the preparation has failed.
+ */
+int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
+
+/* Update the MSI message if required. */
+void iommu_dma_compose_msi_msg(struct msi_desc *desc,
+			       struct msi_msg *msg);
+
 void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
 
 #else
 
 struct iommu_domain;
+struct msi_desc;
 struct msi_msg;
 struct device;
 
@@ -99,6 +111,17 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
 {
 }
 
+static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
+					phys_addr_t msi_addr)
+{
+	return 0;
+}
+
+static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
+					     struct msi_msg *msg)
+{
+}
+
 static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
 {
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 3/7] irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg()
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
  2019-04-29 14:44 ` [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie Julien Grall
  2019-04-29 14:44 ` [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-30 12:34   ` Auger Eric
  2019-04-29 14:44 ` [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg() Julien Grall
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

gicv2m_compose_msi_msg() may be called from non-preemptible context.
However, on RT, iommu_dma_map_msi_msg() requires to be called from a
preemptible context.

A recent change split iommu_dma_map_msi_msg() in two new functions:
one that should be called in preemptible context, the other does
not have any requirement.

The GICv2m driver is reworked to avoid executing preemptible code in
non-preemptible context. This can be achieved by preparing the MSI
mapping when allocating the MSI interrupt.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Rework the commit message to use imperative mood
---
 drivers/irqchip/irq-gic-v2m.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index f5fe0100f9ff..4359f0583377 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -110,7 +110,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
 		msg->data -= v2m->spi_offset;
 
-	iommu_dma_map_msi_msg(data->irq, msg);
+	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
 }
 
 static struct irq_chip gicv2m_irq_chip = {
@@ -167,6 +167,7 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq,
 static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				   unsigned int nr_irqs, void *args)
 {
+	msi_alloc_info_t *info = args;
 	struct v2m_data *v2m = NULL, *tmp;
 	int hwirq, offset, i, err = 0;
 
@@ -186,6 +187,11 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 
 	hwirq = v2m->spi_start + offset;
 
+	err = iommu_dma_prepare_msi(info->desc,
+				    v2m->res.start + V2M_MSI_SETSPI_NS);
+	if (err)
+		return err;
+
 	for (i = 0; i < nr_irqs; i++) {
 		err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
 		if (err)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg()
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
                   ` (2 preceding siblings ...)
  2019-04-29 14:44 ` [PATCH v2 3/7] irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg() Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-30 12:34   ` Auger Eric
  2019-04-29 14:44 ` [PATCH v2 5/7] irqchip/ls-scfg-msi: Don't map the MSI page in ls_scfg_msi_compose_msg() Julien Grall
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

its_irq_compose_msi_msg() may be called from non-preemptible context.
However, on RT, iommu_dma_map_msi_msg requires to be called from a
preemptible context.

A recent change split iommu_dma_map_msi_msg() in two new functions:
one that should be called in preemptible context, the other does
not have any requirement.

The GICv3 ITS driver is reworked to avoid executing preemptible code in
non-preemptible context. This can be achieved by preparing the MSI
maping when allocating the MSI interrupt.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Rework the commit message to use imperative mood
---
 drivers/irqchip/irq-gic-v3-its.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 7577755bdcf4..12ddbcfe1b1e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1179,7 +1179,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
 	msg->address_hi		= upper_32_bits(addr);
 	msg->data		= its_get_event_id(d);
 
-	iommu_dma_map_msi_msg(d->irq, msg);
+	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
 }
 
 static int its_irq_set_irqchip_state(struct irq_data *d,
@@ -2566,6 +2566,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 {
 	msi_alloc_info_t *info = args;
 	struct its_device *its_dev = info->scratchpad[0].ptr;
+	struct its_node *its = its_dev->its;
 	irq_hw_number_t hwirq;
 	int err;
 	int i;
@@ -2574,6 +2575,8 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	if (err)
 		return err;
 
+	err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
+
 	for (i = 0; i < nr_irqs; i++) {
 		err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
 		if (err)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 5/7] irqchip/ls-scfg-msi: Don't map the MSI page in ls_scfg_msi_compose_msg()
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
                   ` (3 preceding siblings ...)
  2019-04-29 14:44 ` [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg() Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-29 14:44 ` [PATCH v2 6/7] irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b, s}i_msg() Julien Grall
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

ls_scfg_msi_compose_msg() may be called from non-preemptible context.
However, on RT, iommu_dma_map_msi_msg() requires to be called from a
preemptible context.

A recent patch split iommu_dma_map_msi_msg() in two new functions:
one that should be called in preemptible context, the other does
not have any requirement.

The FreeScale SCFG MSI driver is reworked to avoid executing preemptible
code in non-preemptible context. This can be achieved by preparing the
MSI maping when allocating the MSI interrupt.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Rework the commit message to use imperative mood
---
 drivers/irqchip/irq-ls-scfg-msi.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index c671b3212010..669d29105772 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -100,7 +100,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 		msg->data |= cpumask_first(mask);
 	}
 
-	iommu_dma_map_msi_msg(data->irq, msg);
+	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
@@ -141,6 +141,7 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
 					unsigned int nr_irqs,
 					void *args)
 {
+	msi_alloc_info_t *info = args;
 	struct ls_scfg_msi *msi_data = domain->host_data;
 	int pos, err = 0;
 
@@ -157,6 +158,10 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
 	if (err)
 		return err;
 
+	err = iommu_dma_prepare_msi(info->desc, msi_data->msiir_addr);
+	if (err)
+		return err;
+
 	irq_domain_set_info(domain, virq, pos,
 			    &ls_scfg_msi_parent_chip, msi_data,
 			    handle_simple_irq, NULL, NULL);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 6/7] irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b, s}i_msg()
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
                   ` (4 preceding siblings ...)
  2019-04-29 14:44 ` [PATCH v2 5/7] irqchip/ls-scfg-msi: Don't map the MSI page in ls_scfg_msi_compose_msg() Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-29 14:44 ` [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg() Julien Grall
  2019-04-29 15:57 ` [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Marc Zyngier
  7 siblings, 0 replies; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

The functions mbi_compose_m{b, s}i_msg may be called from non-preemptible
context. However, on RT, iommu_dma_map_msi_msg() requires to be called
from a preemptible context.

A recent patch split iommu_dma_map_msi_msg in two new functions:
one that should be called in preemptible context, the other does
not have any requirement.

The GICv3 MSI driver is reworked to avoid executing preemptible code in
non-preemptible context. This can be achieved by preparing the two MSI
mappings when allocating the MSI interrupt.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Rework the commit message to use imperative mood
---
 drivers/irqchip/irq-gic-v3-mbi.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c
index fbfa7ff6deb1..d50f6cdf043c 100644
--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -84,6 +84,7 @@ static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq,
 static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				   unsigned int nr_irqs, void *args)
 {
+	msi_alloc_info_t *info = args;
 	struct mbi_range *mbi = NULL;
 	int hwirq, offset, i, err = 0;
 
@@ -104,6 +105,16 @@ static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 
 	hwirq = mbi->spi_start + offset;
 
+	err = iommu_dma_prepare_msi(info->desc,
+				    mbi_phys_base + GICD_CLRSPI_NSR);
+	if (err)
+		return err;
+
+	err = iommu_dma_prepare_msi(info->desc,
+				    mbi_phys_base + GICD_SETSPI_NSR);
+	if (err)
+		return err;
+
 	for (i = 0; i < nr_irqs; i++) {
 		err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
 		if (err)
@@ -142,7 +153,7 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 	msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
 	msg[0].data = data->parent_data->hwirq;
 
-	iommu_dma_map_msi_msg(data->irq, msg);
+	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
 }
 
 #ifdef CONFIG_PCI_MSI
@@ -202,7 +213,7 @@ static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg)
 	msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
 	msg[1].data = data->parent_data->hwirq;
 
-	iommu_dma_map_msi_msg(data->irq, &msg[1]);
+	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), &msg[1]);
 }
 
 /* Platform-MSI specific irqchip */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg()
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
                   ` (5 preceding siblings ...)
  2019-04-29 14:44 ` [PATCH v2 6/7] irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b, s}i_msg() Julien Grall
@ 2019-04-29 14:44 ` Julien Grall
  2019-04-29 15:19   ` Robin Murphy
  2019-04-30 13:38   ` Auger Eric
  2019-04-29 15:57 ` [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Marc Zyngier
  7 siblings, 2 replies; 21+ messages in thread
From: Julien Grall @ 2019-04-29 14:44 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, robin.murphy, bigeasy, linux-rt-users, Julien Grall

A recent change split iommu_dma_map_msi_msg() in two new functions. The
function was still implemented to avoid modifying all the callers at
once.

Now that all the callers have been reworked, iommu_dma_map_msi_msg() can
be removed.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Rework the commit message
---
 drivers/iommu/dma-iommu.c | 20 --------------------
 include/linux/dma-iommu.h |  5 -----
 2 files changed, 25 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 2309f59cefa4..12f4464828a4 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -936,23 +936,3 @@ void iommu_dma_compose_msi_msg(struct msi_desc *desc,
 	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
 	msg->address_lo += lower_32_bits(msi_page->iova);
 }
-
-void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
-{
-	struct msi_desc *desc = irq_get_msi_desc(irq);
-	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
-
-	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
-		/*
-		 * We're called from a void callback, so the best we can do is
-		 * 'fail' by filling the message with obviously bogus values.
-		 * Since we got this far due to an IOMMU being present, it's
-		 * not like the existing address would have worked anyway...
-		 */
-		msg->address_hi = ~0U;
-		msg->address_lo = ~0U;
-		msg->data = ~0U;
-	} else {
-		iommu_dma_compose_msi_msg(desc, msg);
-	}
-}
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 3fc48fbd6f63..ddd217c197df 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -82,7 +82,6 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
 void iommu_dma_compose_msi_msg(struct msi_desc *desc,
 			       struct msi_msg *msg);
 
-void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
 
 #else
@@ -122,10 +121,6 @@ static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
 {
 }
 
-static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
-{
-}
-
 static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 {
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie
  2019-04-29 14:44 ` [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie Julien Grall
@ 2019-04-29 15:12   ` Robin Murphy
  2019-04-30 12:53   ` Auger Eric
  1 sibling, 0 replies; 21+ messages in thread
From: Robin Murphy @ 2019-04-29 15:12 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, bigeasy, linux-rt-users

On 29/04/2019 15:44, Julien Grall wrote:
> When an MSI doorbell is located downstream of an IOMMU, it is required
> to swizzle the physical address with an appropriately-mapped IOVA for any
> device attached to one of our DMA ops domain.
> 
> At the moment, the allocation of the mapping may be done when composing
> the message. However, the composing may be done in non-preemtible
> context while the allocation requires to be called from preemptible
> context.
> 
> A follow-up change will split the current logic in two functions
> requiring to keep an IOMMU cookie per MSI.
> 
> A new field is introduced in msi_desc to store an IOMMU cookie. As the
> cookie may not be required in some configuration, the field is protected
> under a new config CONFIG_IRQ_MSI_IOMMU.
> 
> A pair of helpers has also been introduced to access the field.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

> Signed-off-by: Julien Grall <julien.grall@arm.com>
> 
> ---
>      Changes in v2:
>          - Update the commit message to use imperative mood
>          - Protect the field with a new config that will be selected by
>          IOMMU_DMA later on
>          - Add a set of helpers to access the new field
> ---
>   include/linux/msi.h | 26 ++++++++++++++++++++++++++
>   kernel/irq/Kconfig  |  3 +++
>   2 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/msi.h b/include/linux/msi.h
> index 7e9b81c3b50d..82a308c19222 100644
> --- a/include/linux/msi.h
> +++ b/include/linux/msi.h
> @@ -77,6 +77,9 @@ struct msi_desc {
>   	struct device			*dev;
>   	struct msi_msg			msg;
>   	struct irq_affinity_desc	*affinity;
> +#ifdef CONFIG_IRQ_MSI_IOMMU
> +	const void			*iommu_cookie;
> +#endif
>   
>   	union {
>   		/* PCI MSI/X specific data */
> @@ -119,6 +122,29 @@ struct msi_desc {
>   #define for_each_msi_entry_safe(desc, tmp, dev)	\
>   	list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
>   
> +#ifdef CONFIG_IRQ_MSI_IOMMU
> +static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
> +{
> +	return desc->iommu_cookie;
> +}
> +
> +static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
> +					     const void *iommu_cookie)
> +{
> +	desc->iommu_cookie = iommu_cookie;
> +}
> +#else
> +static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
> +{
> +	return NULL;
> +}
> +
> +static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
> +					     const void *iommu_cookie)
> +{
> +}
> +#endif
> +
>   #ifdef CONFIG_PCI_MSI
>   #define first_pci_msi_entry(pdev)	first_msi_entry(&(pdev)->dev)
>   #define for_each_pci_msi_entry(desc, pdev)	\
> diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
> index 5f3e2baefca9..8fee06625c37 100644
> --- a/kernel/irq/Kconfig
> +++ b/kernel/irq/Kconfig
> @@ -91,6 +91,9 @@ config GENERIC_MSI_IRQ_DOMAIN
>   	select IRQ_DOMAIN_HIERARCHY
>   	select GENERIC_MSI_IRQ
>   
> +config IRQ_MSI_IOMMU
> +	bool
> +
>   config HANDLE_DOMAIN_IRQ
>   	bool
>   
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts
  2019-04-29 14:44 ` [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts Julien Grall
@ 2019-04-29 15:16   ` Robin Murphy
  2019-04-29 15:28   ` Marc Zyngier
  2019-04-30 12:54   ` Auger Eric
  2 siblings, 0 replies; 21+ messages in thread
From: Robin Murphy @ 2019-04-29 15:16 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, bigeasy, linux-rt-users

On 29/04/2019 15:44, Julien Grall wrote:
> On RT, iommu_dma_map_msi_msg() may be called from non-preemptible
> context. This will lead to a splat with CONFIG_DEBUG_ATOMIC_SLEEP as
> the function is using spin_lock (they can sleep on RT).
> 
> iommu_dma_map_msi_msg() is used to map the MSI page in the IOMMU PT
> and update the MSI message with the IOVA.
> 
> Only the part to lookup for the MSI page requires to be called in
> preemptible context. As the MSI page cannot change over the lifecycle
> of the MSI interrupt, the lookup can be cached and re-used later on.
> 
> iomma_dma_map_msi_msg() is now split in two functions:
>      - iommu_dma_prepare_msi(): This function will prepare the mapping
>      in the IOMMU and store the cookie in the structure msi_desc. This
>      function should be called in preemptible context.
>      - iommu_dma_compose_msi_msg(): This function will update the MSI
>      message with the IOVA when the device is behind an IOMMU.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
> 
> ---
>      Changes in v2:
>          - Rework the commit message to use imperative mood
>          - Use the MSI accessor to get/set the iommu cookie
>          - Don't use ternary on return
>          - Select CONFIG_IRQ_MSI_IOMMU
>          - Pass an msi_desc rather than the irq number
> ---
>   drivers/iommu/Kconfig     |  1 +
>   drivers/iommu/dma-iommu.c | 47 ++++++++++++++++++++++++++++++++++++++---------
>   include/linux/dma-iommu.h | 23 +++++++++++++++++++++++
>   3 files changed, 62 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index 6f07f3b21816..eb1c8cd243f9 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -94,6 +94,7 @@ config IOMMU_DMA
>   	bool
>   	select IOMMU_API
>   	select IOMMU_IOVA
> +	select IRQ_MSI_IOMMU
>   	select NEED_SG_DMA_LENGTH
>   
>   config FSL_PAMU
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 77aabe637a60..2309f59cefa4 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -888,17 +888,18 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
>   	return NULL;
>   }
>   
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
>   {
> -	struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
> +	struct device *dev = msi_desc_to_dev(desc);
>   	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
>   	struct iommu_dma_cookie *cookie;
>   	struct iommu_dma_msi_page *msi_page;
> -	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
>   	unsigned long flags;
>   
> -	if (!domain || !domain->iova_cookie)
> -		return;
> +	if (!domain || !domain->iova_cookie) {
> +		desc->iommu_cookie = NULL;
> +		return 0;
> +	}
>   
>   	cookie = domain->iova_cookie;
>   
> @@ -911,7 +912,37 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>   	msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
>   	spin_unlock_irqrestore(&cookie->msi_lock, flags);
>   
> -	if (WARN_ON(!msi_page)) {
> +	msi_desc_set_iommu_cookie(desc, msi_page);
> +
> +	if (!msi_page)
> +		return -ENOMEM;
> +	else

Nit: the "else" isn't really necessary.

> +		return 0;
> +}
> +
> +void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +			       struct msi_msg *msg)
> +{
> +	struct device *dev = msi_desc_to_dev(desc);
> +	const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> +	const struct iommu_dma_msi_page *msi_page;
> +
> +	msi_page = msi_desc_get_iommu_cookie(desc);
> +
> +	if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
> +		return;
> +
> +	msg->address_hi = upper_32_bits(msi_page->iova);
> +	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
> +	msg->address_lo += lower_32_bits(msi_page->iova);
> +}
> +
> +void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +{
> +	struct msi_desc *desc = irq_get_msi_desc(irq);
> +	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
> +
> +	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
>   		/*
>   		 * We're called from a void callback, so the best we can do is
>   		 * 'fail' by filling the message with obviously bogus values.
> @@ -922,8 +953,6 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>   		msg->address_lo = ~0U;
>   		msg->data = ~0U;
>   	} else {
> -		msg->address_hi = upper_32_bits(msi_page->iova);
> -		msg->address_lo &= cookie_msi_granule(cookie) - 1;
> -		msg->address_lo += lower_32_bits(msi_page->iova);
> +		iommu_dma_compose_msi_msg(desc, msg);
>   	}
>   }
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index e760dc5d1fa8..3fc48fbd6f63 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -71,12 +71,24 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
>   		size_t size, enum dma_data_direction dir, unsigned long attrs);
>   
>   /* The DMA API isn't _quite_ the whole story, though... */
> +/*
> + * Map the MSI page in the IOMMU device and store it in @desc
> + *
> + * Return 0 if succeeded other an error if the preparation has failed.
> + */

Nit: If you want to document these, please use proper kerneldoc comments 
on the definitions, rather than ad-hoc ones on the declarations.

Modulo that, though:

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

> +int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
> +
> +/* Update the MSI message if required. */
> +void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +			       struct msi_msg *msg);
> +
>   void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
>   void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
>   
>   #else
>   
>   struct iommu_domain;
> +struct msi_desc;
>   struct msi_msg;
>   struct device;
>   
> @@ -99,6 +111,17 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
>   {
>   }
>   
> +static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
> +					phys_addr_t msi_addr)
> +{
> +	return 0;
> +}
> +
> +static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +					     struct msi_msg *msg)
> +{
> +}
> +
>   static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>   {
>   }
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg()
  2019-04-29 14:44 ` [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg() Julien Grall
@ 2019-04-29 15:19   ` Robin Murphy
  2019-04-30 13:38   ` Auger Eric
  1 sibling, 0 replies; 21+ messages in thread
From: Robin Murphy @ 2019-04-29 15:19 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, marc.zyngier, jason, tglx,
	joro, bigeasy, linux-rt-users

On 29/04/2019 15:44, Julien Grall wrote:
> A recent change split iommu_dma_map_msi_msg() in two new functions. The
> function was still implemented to avoid modifying all the callers at
> once.
> 
> Now that all the callers have been reworked, iommu_dma_map_msi_msg() can
> be removed.

Yay! The end of my horrible bodge :)

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

> Signed-off-by: Julien Grall <julien.grall@arm.com>
> 
> ---
>      Changes in v2:
>          - Rework the commit message
> ---
>   drivers/iommu/dma-iommu.c | 20 --------------------
>   include/linux/dma-iommu.h |  5 -----
>   2 files changed, 25 deletions(-)
> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 2309f59cefa4..12f4464828a4 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -936,23 +936,3 @@ void iommu_dma_compose_msi_msg(struct msi_desc *desc,
>   	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
>   	msg->address_lo += lower_32_bits(msi_page->iova);
>   }
> -
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> -{
> -	struct msi_desc *desc = irq_get_msi_desc(irq);
> -	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
> -
> -	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
> -		/*
> -		 * We're called from a void callback, so the best we can do is
> -		 * 'fail' by filling the message with obviously bogus values.
> -		 * Since we got this far due to an IOMMU being present, it's
> -		 * not like the existing address would have worked anyway...
> -		 */
> -		msg->address_hi = ~0U;
> -		msg->address_lo = ~0U;
> -		msg->data = ~0U;
> -	} else {
> -		iommu_dma_compose_msi_msg(desc, msg);
> -	}
> -}
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index 3fc48fbd6f63..ddd217c197df 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -82,7 +82,6 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
>   void iommu_dma_compose_msi_msg(struct msi_desc *desc,
>   			       struct msi_msg *msg);
>   
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
>   void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
>   
>   #else
> @@ -122,10 +121,6 @@ static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
>   {
>   }
>   
> -static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> -{
> -}
> -
>   static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
>   {
>   }
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts
  2019-04-29 14:44 ` [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts Julien Grall
  2019-04-29 15:16   ` Robin Murphy
@ 2019-04-29 15:28   ` Marc Zyngier
  2019-04-30 12:54   ` Auger Eric
  2 siblings, 0 replies; 21+ messages in thread
From: Marc Zyngier @ 2019-04-29 15:28 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, jason, tglx, joro,
	robin.murphy, bigeasy, linux-rt-users

On 29/04/2019 15:44, Julien Grall wrote:
> On RT, iommu_dma_map_msi_msg() may be called from non-preemptible
> context. This will lead to a splat with CONFIG_DEBUG_ATOMIC_SLEEP as
> the function is using spin_lock (they can sleep on RT).
> 
> iommu_dma_map_msi_msg() is used to map the MSI page in the IOMMU PT
> and update the MSI message with the IOVA.
> 
> Only the part to lookup for the MSI page requires to be called in
> preemptible context. As the MSI page cannot change over the lifecycle
> of the MSI interrupt, the lookup can be cached and re-used later on.
> 
> iomma_dma_map_msi_msg() is now split in two functions:
>     - iommu_dma_prepare_msi(): This function will prepare the mapping
>     in the IOMMU and store the cookie in the structure msi_desc. This
>     function should be called in preemptible context.
>     - iommu_dma_compose_msi_msg(): This function will update the MSI
>     message with the IOVA when the device is behind an IOMMU.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
> 
> ---
>     Changes in v2:
>         - Rework the commit message to use imperative mood
>         - Use the MSI accessor to get/set the iommu cookie
>         - Don't use ternary on return
>         - Select CONFIG_IRQ_MSI_IOMMU
>         - Pass an msi_desc rather than the irq number
> ---
>  drivers/iommu/Kconfig     |  1 +
>  drivers/iommu/dma-iommu.c | 47 ++++++++++++++++++++++++++++++++++++++---------
>  include/linux/dma-iommu.h | 23 +++++++++++++++++++++++
>  3 files changed, 62 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index 6f07f3b21816..eb1c8cd243f9 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -94,6 +94,7 @@ config IOMMU_DMA
>  	bool
>  	select IOMMU_API
>  	select IOMMU_IOVA
> +	select IRQ_MSI_IOMMU
>  	select NEED_SG_DMA_LENGTH
>  
>  config FSL_PAMU
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 77aabe637a60..2309f59cefa4 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -888,17 +888,18 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
>  	return NULL;
>  }
>  
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
>  {
> -	struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
> +	struct device *dev = msi_desc_to_dev(desc);
>  	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
>  	struct iommu_dma_cookie *cookie;
>  	struct iommu_dma_msi_page *msi_page;
> -	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
>  	unsigned long flags;
>  
> -	if (!domain || !domain->iova_cookie)
> -		return;
> +	if (!domain || !domain->iova_cookie) {
> +		desc->iommu_cookie = NULL;

nit: This could be

		msi_desc_set_iommu_cookie(desc, NULL);

now that you have introduced the relevant accessors.

> +		return 0;
> +	}
>  
>  	cookie = domain->iova_cookie;
>  
> @@ -911,7 +912,37 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  	msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
>  	spin_unlock_irqrestore(&cookie->msi_lock, flags);
>  
> -	if (WARN_ON(!msi_page)) {
> +	msi_desc_set_iommu_cookie(desc, msi_page);
> +
> +	if (!msi_page)
> +		return -ENOMEM;
> +	else
> +		return 0;
> +}
> +
> +void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +			       struct msi_msg *msg)
> +{
> +	struct device *dev = msi_desc_to_dev(desc);
> +	const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> +	const struct iommu_dma_msi_page *msi_page;
> +
> +	msi_page = msi_desc_get_iommu_cookie(desc);
> +
> +	if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
> +		return;
> +
> +	msg->address_hi = upper_32_bits(msi_page->iova);
> +	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
> +	msg->address_lo += lower_32_bits(msi_page->iova);
> +}
> +
> +void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +{
> +	struct msi_desc *desc = irq_get_msi_desc(irq);
> +	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
> +
> +	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
>  		/*
>  		 * We're called from a void callback, so the best we can do is
>  		 * 'fail' by filling the message with obviously bogus values.
> @@ -922,8 +953,6 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  		msg->address_lo = ~0U;
>  		msg->data = ~0U;
>  	} else {
> -		msg->address_hi = upper_32_bits(msi_page->iova);
> -		msg->address_lo &= cookie_msi_granule(cookie) - 1;
> -		msg->address_lo += lower_32_bits(msi_page->iova);
> +		iommu_dma_compose_msi_msg(desc, msg);
>  	}
>  }
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index e760dc5d1fa8..3fc48fbd6f63 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -71,12 +71,24 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
>  		size_t size, enum dma_data_direction dir, unsigned long attrs);
>  
>  /* The DMA API isn't _quite_ the whole story, though... */
> +/*
> + * Map the MSI page in the IOMMU device and store it in @desc
> + *
> + * Return 0 if succeeded other an error if the preparation has failed.

s/other/or/

This could be a proper kerneldoc thing, while you're at it.

> + */
> +int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
> +
> +/* Update the MSI message if required. */
> +void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +			       struct msi_msg *msg);
> +
>  void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
>  void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
>  
>  #else
>  
>  struct iommu_domain;
> +struct msi_desc;
>  struct msi_msg;
>  struct device;
>  
> @@ -99,6 +111,17 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
>  {
>  }
>  
> +static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
> +					phys_addr_t msi_addr)
> +{
> +	return 0;
> +}
> +
> +static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +					     struct msi_msg *msg)
> +{
> +}
> +
>  static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  {
>  }
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts
  2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
                   ` (6 preceding siblings ...)
  2019-04-29 14:44 ` [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg() Julien Grall
@ 2019-04-29 15:57 ` Marc Zyngier
  2019-04-29 19:35   ` Christoph Hellwig
  7 siblings, 1 reply; 21+ messages in thread
From: Marc Zyngier @ 2019-04-29 15:57 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: logang, douliyangs, miquel.raynal, jason, tglx, joro,
	robin.murphy, bigeasy, linux-rt-users

Hi Julien,

On 29/04/2019 15:44, Julien Grall wrote:
> Hi all,
> 
> On RT, the function iommu_dma_map_msi_msg expects to be called from preemptible
> context. However, this is not always the case resulting a splat with
> !CONFIG_DEBUG_ATOMIC_SLEEP:
> 
> [   48.875777] BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:974
> [   48.875779] in_atomic(): 1, irqs_disabled(): 128, pid: 2103, name: ip
> [   48.875782] INFO: lockdep is turned off.
> [   48.875784] irq event stamp: 10684
> [   48.875786] hardirqs last  enabled at (10683): [<ffff0000110c8d70>] _raw_spin_unlock_irqrestore+0x88/0x90
> [   48.875791] hardirqs last disabled at (10684): [<ffff0000110c8b2c>] _raw_spin_lock_irqsave+0x24/0x68
> [   48.875796] softirqs last  enabled at (0): [<ffff0000100ec590>] copy_process.isra.1.part.2+0x8d8/0x1970
> [   48.875801] softirqs last disabled at (0): [<0000000000000000>]           (null)
> [   48.875805] Preemption disabled at:
> [   48.875805] [<ffff000010189ae8>] __setup_irq+0xd8/0x6c0
> [   48.875811] CPU: 2 PID: 2103 Comm: ip Not tainted 5.0.3-rt1-00007-g42ede9a0fed6 #45
> [   48.875815] Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Jan 23 2017
> [   48.875817] Call trace:
> [   48.875818]  dump_backtrace+0x0/0x140
> [   48.875821]  show_stack+0x14/0x20
> [   48.875823]  dump_stack+0xa0/0xd4
> [   48.875827]  ___might_sleep+0x16c/0x1f8
> [   48.875831]  rt_spin_lock+0x5c/0x70
> [   48.875835]  iommu_dma_map_msi_msg+0x5c/0x1d8
> [   48.875839]  gicv2m_compose_msi_msg+0x3c/0x48
> [   48.875843]  irq_chip_compose_msi_msg+0x40/0x58
> [   48.875846]  msi_domain_activate+0x38/0x98
> [   48.875849]  __irq_domain_activate_irq+0x58/0xa0
> [   48.875852]  irq_domain_activate_irq+0x34/0x58
> [   48.875855]  irq_activate+0x28/0x30
> [   48.875858]  __setup_irq+0x2b0/0x6c0
> [   48.875861]  request_threaded_irq+0xdc/0x188
> [   48.875865]  sky2_setup_irq+0x44/0xf8
> [   48.875868]  sky2_open+0x1a4/0x240
> [   48.875871]  __dev_open+0xd8/0x188
> [   48.875874]  __dev_change_flags+0x164/0x1f0
> [   48.875877]  dev_change_flags+0x20/0x60
> [   48.875879]  do_setlink+0x2a0/0xd30
> [   48.875882]  __rtnl_newlink+0x5b4/0x6d8
> [   48.875885]  rtnl_newlink+0x50/0x78
> [   48.875888]  rtnetlink_rcv_msg+0x178/0x640
> [   48.875891]  netlink_rcv_skb+0x58/0x118
> [   48.875893]  rtnetlink_rcv+0x14/0x20
> [   48.875896]  netlink_unicast+0x188/0x200
> [   48.875898]  netlink_sendmsg+0x248/0x3d8
> [   48.875900]  sock_sendmsg+0x18/0x40
> [   48.875904]  ___sys_sendmsg+0x294/0x2d0
> [   48.875908]  __sys_sendmsg+0x68/0xb8
> [   48.875911]  __arm64_sys_sendmsg+0x20/0x28
> [   48.875914]  el0_svc_common+0x90/0x118
> [   48.875918]  el0_svc_handler+0x2c/0x80
> [   48.875922]  el0_svc+0x8/0xc
> 
> This series is a first attempt to rework how MSI are mapped and composed
> when an IOMMU is present.
> 
> I was able to test the changes in GICv2m and GICv3 ITS. I don't have
> hardware for the other interrupt controllers.
> 
> Cheers,
> 
> Julien Grall (7):
>   genirq/msi: Add a new field in msi_desc to store an IOMMU cookie
>   iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts
>   irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg()
>   irqchip/gic-v3-its: Don't map the MSI page in
>     its_irq_compose_msi_msg()
>   irqchip/ls-scfg-msi: Don't map the MSI page in
>     ls_scfg_msi_compose_msg()
>   irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b,
>     s}i_msg()
>   iommu/dma-iommu: Remove iommu_dma_map_msi_msg()
> 
>  drivers/iommu/Kconfig             |  1 +
>  drivers/iommu/dma-iommu.c         | 49 +++++++++++++++++++++++----------------
>  drivers/irqchip/irq-gic-v2m.c     |  8 ++++++-
>  drivers/irqchip/irq-gic-v3-its.c  |  5 +++-
>  drivers/irqchip/irq-gic-v3-mbi.c  | 15 ++++++++++--
>  drivers/irqchip/irq-ls-scfg-msi.c |  7 +++++-
>  include/linux/dma-iommu.h         | 22 ++++++++++++++++--
>  include/linux/msi.h               | 26 +++++++++++++++++++++
>  kernel/irq/Kconfig                |  3 +++
>  9 files changed, 109 insertions(+), 27 deletions(-)

Thanks for having reworked this. I'm quite happy with the way this looks
now (modulo the couple of nits Robin and I mentioned, which I'm to
address myself).

Jorg: are you OK with this going via the irq tree?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts
  2019-04-29 15:57 ` [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Marc Zyngier
@ 2019-04-29 19:35   ` Christoph Hellwig
  0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2019-04-29 19:35 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Julien Grall, linux-kernel, iommu, jason, douliyangs,
	robin.murphy, miquel.raynal, tglx, logang, bigeasy,
	linux-rt-users

On Mon, Apr 29, 2019 at 04:57:20PM +0100, Marc Zyngier wrote:
> Thanks for having reworked this. I'm quite happy with the way this looks
> now (modulo the couple of nits Robin and I mentioned, which I'm to
> address myself).
> 
> Jorg: are you OK with this going via the irq tree?

As-is this has a trivial conflict with my
"implement generic dma_map_ops for IOMMUs" series.  But I can tweak
it a bit to avoid that conflict.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 3/7] irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg()
  2019-04-29 14:44 ` [PATCH v2 3/7] irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg() Julien Grall
@ 2019-04-30 12:34   ` Auger Eric
  0 siblings, 0 replies; 21+ messages in thread
From: Auger Eric @ 2019-04-30 12:34 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: jason, douliyangs, marc.zyngier, robin.murphy, miquel.raynal,
	tglx, logang, bigeasy, linux-rt-users

Hi Julien,

On 4/29/19 4:44 PM, Julien Grall wrote:
> gicv2m_compose_msi_msg() may be called from non-preemptible context.
> However, on RT, iommu_dma_map_msi_msg() requires to be called from a
> preemptible context.
> 
> A recent change split iommu_dma_map_msi_msg() in two new functions:
> one that should be called in preemptible context, the other does
> not have any requirement.
> 
> The GICv2m driver is reworked to avoid executing preemptible code in
> non-preemptible context. This can be achieved by preparing the MSI
> mapping when allocating the MSI interrupt.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> ---
>     Changes in v2:
>         - Rework the commit message to use imperative mood
> ---
>  drivers/irqchip/irq-gic-v2m.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
> index f5fe0100f9ff..4359f0583377 100644
> --- a/drivers/irqchip/irq-gic-v2m.c
> +++ b/drivers/irqchip/irq-gic-v2m.c
> @@ -110,7 +110,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>  	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
>  		msg->data -= v2m->spi_offset;
>  
> -	iommu_dma_map_msi_msg(data->irq, msg);
> +	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
>  }
>  
>  static struct irq_chip gicv2m_irq_chip = {
> @@ -167,6 +167,7 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq,
>  static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>  				   unsigned int nr_irqs, void *args)
>  {
> +	msi_alloc_info_t *info = args;
>  	struct v2m_data *v2m = NULL, *tmp;
>  	int hwirq, offset, i, err = 0;
>  
> @@ -186,6 +187,11 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>  
>  	hwirq = v2m->spi_start + offset;
>  
> +	err = iommu_dma_prepare_msi(info->desc,
> +				    v2m->res.start + V2M_MSI_SETSPI_NS);
> +	if (err)
> +		return err;
> +
>  	for (i = 0; i < nr_irqs; i++) {
>  		err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
>  		if (err)
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg()
  2019-04-29 14:44 ` [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg() Julien Grall
@ 2019-04-30 12:34   ` Auger Eric
  2019-05-01 11:14     ` Julien Grall
  0 siblings, 1 reply; 21+ messages in thread
From: Auger Eric @ 2019-04-30 12:34 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: jason, douliyangs, marc.zyngier, robin.murphy, miquel.raynal,
	tglx, logang, bigeasy, linux-rt-users

Hi Julien,

On 4/29/19 4:44 PM, Julien Grall wrote:
> its_irq_compose_msi_msg() may be called from non-preemptible context.
> However, on RT, iommu_dma_map_msi_msg requires to be called from a
> preemptible context.
> 
> A recent change split iommu_dma_map_msi_msg() in two new functions:
> one that should be called in preemptible context, the other does
> not have any requirement.
> 
> The GICv3 ITS driver is reworked to avoid executing preemptible code in
> non-preemptible context. This can be achieved by preparing the MSI
> maping when allocating the MSI interrupt.
mapping
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
> 
> ---
>     Changes in v2:
>         - Rework the commit message to use imperative mood
> ---
>  drivers/irqchip/irq-gic-v3-its.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 7577755bdcf4..12ddbcfe1b1e 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -1179,7 +1179,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
>  	msg->address_hi		= upper_32_bits(addr);
>  	msg->data		= its_get_event_id(d);
>  
> -	iommu_dma_map_msi_msg(d->irq, msg);
> +	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
>  }
>  
>  static int its_irq_set_irqchip_state(struct irq_data *d,
> @@ -2566,6 +2566,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>  {
>  	msi_alloc_info_t *info = args;
>  	struct its_device *its_dev = info->scratchpad[0].ptr;
> +	struct its_node *its = its_dev->its;
>  	irq_hw_number_t hwirq;
>  	int err;
>  	int i;
> @@ -2574,6 +2575,8 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>  	if (err)
>  		return err;
>  
> +	err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
Test err as in gicv2m driver?
> +
>  	for (i = 0; i < nr_irqs; i++) {
>  		err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
>  		if (err)
> 
Besides
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie
  2019-04-29 14:44 ` [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie Julien Grall
  2019-04-29 15:12   ` Robin Murphy
@ 2019-04-30 12:53   ` Auger Eric
  1 sibling, 0 replies; 21+ messages in thread
From: Auger Eric @ 2019-04-30 12:53 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: jason, douliyangs, marc.zyngier, robin.murphy, miquel.raynal,
	tglx, logang, bigeasy, linux-rt-users

Hi

On 4/29/19 4:44 PM, Julien Grall wrote:
> When an MSI doorbell is located downstream of an IOMMU, it is required
> to swizzle the physical address with an appropriately-mapped IOVA for any
> device attached to one of our DMA ops domain.
> 
> At the moment, the allocation of the mapping may be done when composing
> the message. However, the composing may be done in non-preemtible
> context while the allocation requires to be called from preemptible
> context.
> 
> A follow-up change will split the current logic in two functions
> requiring to keep an IOMMU cookie per MSI.
> 
> A new field is introduced in msi_desc to store an IOMMU cookie. As the
> cookie may not be required in some configuration, the field is protected
> under a new config CONFIG_IRQ_MSI_IOMMU.
> 
> A pair of helpers has also been introduced to access the field.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
Besides other's comments
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> ---
>     Changes in v2:
>         - Update the commit message to use imperative mood
>         - Protect the field with a new config that will be selected by
>         IOMMU_DMA later on
>         - Add a set of helpers to access the new field
> ---
>  include/linux/msi.h | 26 ++++++++++++++++++++++++++
>  kernel/irq/Kconfig  |  3 +++
>  2 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/msi.h b/include/linux/msi.h
> index 7e9b81c3b50d..82a308c19222 100644
> --- a/include/linux/msi.h
> +++ b/include/linux/msi.h
> @@ -77,6 +77,9 @@ struct msi_desc {
>  	struct device			*dev;
>  	struct msi_msg			msg;
>  	struct irq_affinity_desc	*affinity;
> +#ifdef CONFIG_IRQ_MSI_IOMMU
> +	const void			*iommu_cookie;
> +#endif
>  
>  	union {
>  		/* PCI MSI/X specific data */
> @@ -119,6 +122,29 @@ struct msi_desc {
>  #define for_each_msi_entry_safe(desc, tmp, dev)	\
>  	list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
>  
> +#ifdef CONFIG_IRQ_MSI_IOMMU
> +static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
> +{
> +	return desc->iommu_cookie;
> +}
> +
> +static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
> +					     const void *iommu_cookie)
> +{
> +	desc->iommu_cookie = iommu_cookie;
> +}
> +#else
> +static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
> +{
> +	return NULL;
> +}
> +
> +static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
> +					     const void *iommu_cookie)
> +{
> +}
> +#endif
> +
>  #ifdef CONFIG_PCI_MSI
>  #define first_pci_msi_entry(pdev)	first_msi_entry(&(pdev)->dev)
>  #define for_each_pci_msi_entry(desc, pdev)	\
> diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
> index 5f3e2baefca9..8fee06625c37 100644
> --- a/kernel/irq/Kconfig
> +++ b/kernel/irq/Kconfig
> @@ -91,6 +91,9 @@ config GENERIC_MSI_IRQ_DOMAIN
>  	select IRQ_DOMAIN_HIERARCHY
>  	select GENERIC_MSI_IRQ
>  
> +config IRQ_MSI_IOMMU
> +	bool
> +
>  config HANDLE_DOMAIN_IRQ
>  	bool
>  
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts
  2019-04-29 14:44 ` [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts Julien Grall
  2019-04-29 15:16   ` Robin Murphy
  2019-04-29 15:28   ` Marc Zyngier
@ 2019-04-30 12:54   ` Auger Eric
  2 siblings, 0 replies; 21+ messages in thread
From: Auger Eric @ 2019-04-30 12:54 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: jason, douliyangs, marc.zyngier, robin.murphy, miquel.raynal,
	tglx, logang, bigeasy, linux-rt-users

Hu Julien,

On 4/29/19 4:44 PM, Julien Grall wrote:
> On RT, iommu_dma_map_msi_msg() may be called from non-preemptible
> context. This will lead to a splat with CONFIG_DEBUG_ATOMIC_SLEEP as
> the function is using spin_lock (they can sleep on RT).
> 
> iommu_dma_map_msi_msg() is used to map the MSI page in the IOMMU PT
> and update the MSI message with the IOVA.
> 
> Only the part to lookup for the MSI page requires to be called in
> preemptible context. As the MSI page cannot change over the lifecycle
> of the MSI interrupt, the lookup can be cached and re-used later on.
> 
> iomma_dma_map_msi_msg() is now split in two functions:
>     - iommu_dma_prepare_msi(): This function will prepare the mapping
>     in the IOMMU and store the cookie in the structure msi_desc. This
>     function should be called in preemptible context.
>     - iommu_dma_compose_msi_msg(): This function will update the MSI
>     message with the IOVA when the device is behind an IOMMU.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
Besides other's comments,

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> ---
>     Changes in v2:
>         - Rework the commit message to use imperative mood
>         - Use the MSI accessor to get/set the iommu cookie
>         - Don't use ternary on return
>         - Select CONFIG_IRQ_MSI_IOMMU
>         - Pass an msi_desc rather than the irq number
> ---
>  drivers/iommu/Kconfig     |  1 +
>  drivers/iommu/dma-iommu.c | 47 ++++++++++++++++++++++++++++++++++++++---------
>  include/linux/dma-iommu.h | 23 +++++++++++++++++++++++
>  3 files changed, 62 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index 6f07f3b21816..eb1c8cd243f9 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -94,6 +94,7 @@ config IOMMU_DMA
>  	bool
>  	select IOMMU_API
>  	select IOMMU_IOVA
> +	select IRQ_MSI_IOMMU
>  	select NEED_SG_DMA_LENGTH
>  
>  config FSL_PAMU
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 77aabe637a60..2309f59cefa4 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -888,17 +888,18 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
>  	return NULL;
>  }
>  
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
>  {
> -	struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
> +	struct device *dev = msi_desc_to_dev(desc);
>  	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
>  	struct iommu_dma_cookie *cookie;
>  	struct iommu_dma_msi_page *msi_page;
> -	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
>  	unsigned long flags;
>  
> -	if (!domain || !domain->iova_cookie)
> -		return;
> +	if (!domain || !domain->iova_cookie) {
> +		desc->iommu_cookie = NULL;
> +		return 0;
> +	}
>  
>  	cookie = domain->iova_cookie;
>  
> @@ -911,7 +912,37 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  	msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
>  	spin_unlock_irqrestore(&cookie->msi_lock, flags);
>  
> -	if (WARN_ON(!msi_page)) {
> +	msi_desc_set_iommu_cookie(desc, msi_page);
> +
> +	if (!msi_page)
> +		return -ENOMEM;
> +	else
> +		return 0;
> +}
> +
> +void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +			       struct msi_msg *msg)
> +{
> +	struct device *dev = msi_desc_to_dev(desc);
> +	const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> +	const struct iommu_dma_msi_page *msi_page;
> +
> +	msi_page = msi_desc_get_iommu_cookie(desc);
> +
> +	if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
> +		return;
> +
> +	msg->address_hi = upper_32_bits(msi_page->iova);
> +	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
> +	msg->address_lo += lower_32_bits(msi_page->iova);
> +}
> +
> +void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +{
> +	struct msi_desc *desc = irq_get_msi_desc(irq);
> +	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
> +
> +	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
>  		/*
>  		 * We're called from a void callback, so the best we can do is
>  		 * 'fail' by filling the message with obviously bogus values.
> @@ -922,8 +953,6 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  		msg->address_lo = ~0U;
>  		msg->data = ~0U;
>  	} else {
> -		msg->address_hi = upper_32_bits(msi_page->iova);
> -		msg->address_lo &= cookie_msi_granule(cookie) - 1;
> -		msg->address_lo += lower_32_bits(msi_page->iova);
> +		iommu_dma_compose_msi_msg(desc, msg);
>  	}
>  }
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index e760dc5d1fa8..3fc48fbd6f63 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -71,12 +71,24 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
>  		size_t size, enum dma_data_direction dir, unsigned long attrs);
>  
>  /* The DMA API isn't _quite_ the whole story, though... */
> +/*
> + * Map the MSI page in the IOMMU device and store it in @desc
> + *
> + * Return 0 if succeeded other an error if the preparation has failed.
> + */
> +int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
> +
> +/* Update the MSI message if required. */
> +void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +			       struct msi_msg *msg);
> +
>  void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
>  void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
>  
>  #else
>  
>  struct iommu_domain;
> +struct msi_desc;
>  struct msi_msg;
>  struct device;
>  
> @@ -99,6 +111,17 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
>  {
>  }
>  
> +static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
> +					phys_addr_t msi_addr)
> +{
> +	return 0;
> +}
> +
> +static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
> +					     struct msi_msg *msg)
> +{
> +}
> +
>  static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  {
>  }
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg()
  2019-04-29 14:44 ` [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg() Julien Grall
  2019-04-29 15:19   ` Robin Murphy
@ 2019-04-30 13:38   ` Auger Eric
  1 sibling, 0 replies; 21+ messages in thread
From: Auger Eric @ 2019-04-30 13:38 UTC (permalink / raw)
  To: Julien Grall, linux-kernel, iommu
  Cc: jason, douliyangs, marc.zyngier, robin.murphy, miquel.raynal,
	tglx, logang, bigeasy, linux-rt-users

Hi Julien,

On 4/29/19 4:44 PM, Julien Grall wrote:
> A recent change split iommu_dma_map_msi_msg() in two new functions. The
> function was still implemented to avoid modifying all the callers at
> once.
> 
> Now that all the callers have been reworked, iommu_dma_map_msi_msg() can
> be removed.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> ---
>     Changes in v2:
>         - Rework the commit message
> ---
>  drivers/iommu/dma-iommu.c | 20 --------------------
>  include/linux/dma-iommu.h |  5 -----
>  2 files changed, 25 deletions(-)
> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 2309f59cefa4..12f4464828a4 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -936,23 +936,3 @@ void iommu_dma_compose_msi_msg(struct msi_desc *desc,
>  	msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
>  	msg->address_lo += lower_32_bits(msi_page->iova);
>  }
> -
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> -{
> -	struct msi_desc *desc = irq_get_msi_desc(irq);
> -	phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
> -
> -	if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
> -		/*
> -		 * We're called from a void callback, so the best we can do is
> -		 * 'fail' by filling the message with obviously bogus values.
> -		 * Since we got this far due to an IOMMU being present, it's
> -		 * not like the existing address would have worked anyway...
> -		 */
> -		msg->address_hi = ~0U;
> -		msg->address_lo = ~0U;
> -		msg->data = ~0U;
> -	} else {
> -		iommu_dma_compose_msi_msg(desc, msg);
> -	}
> -}
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index 3fc48fbd6f63..ddd217c197df 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -82,7 +82,6 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
>  void iommu_dma_compose_msi_msg(struct msi_desc *desc,
>  			       struct msi_msg *msg);
>  
> -void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
>  void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
>  
>  #else
> @@ -122,10 +121,6 @@ static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
>  {
>  }
>  
> -static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> -{
> -}
> -
>  static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
>  {
>  }
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg()
  2019-04-30 12:34   ` Auger Eric
@ 2019-05-01 11:14     ` Julien Grall
  2019-05-01 11:37       ` Marc Zyngier
  0 siblings, 1 reply; 21+ messages in thread
From: Julien Grall @ 2019-05-01 11:14 UTC (permalink / raw)
  To: Auger Eric, linux-kernel, iommu
  Cc: jason, douliyangs, marc.zyngier, robin.murphy, miquel.raynal,
	tglx, logang, bigeasy, linux-rt-users

On 30/04/2019 13:34, Auger Eric wrote:
> Hi Julien,

Hi Eric,

Thank you for the review!

> 
> On 4/29/19 4:44 PM, Julien Grall wrote:
>> its_irq_compose_msi_msg() may be called from non-preemptible context.
>> However, on RT, iommu_dma_map_msi_msg requires to be called from a
>> preemptible context.
>>
>> A recent change split iommu_dma_map_msi_msg() in two new functions:
>> one that should be called in preemptible context, the other does
>> not have any requirement.
>>
>> The GICv3 ITS driver is reworked to avoid executing preemptible code in
>> non-preemptible context. This can be achieved by preparing the MSI
>> maping when allocating the MSI interrupt.
> mapping
>>
>> Signed-off-by: Julien Grall <julien.grall@arm.com>
>>
>> ---
>>      Changes in v2:
>>          - Rework the commit message to use imperative mood
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index 7577755bdcf4..12ddbcfe1b1e 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -1179,7 +1179,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
>>   	msg->address_hi		= upper_32_bits(addr);
>>   	msg->data		= its_get_event_id(d);
>>   
>> -	iommu_dma_map_msi_msg(d->irq, msg);
>> +	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
>>   }
>>   
>>   static int its_irq_set_irqchip_state(struct irq_data *d,
>> @@ -2566,6 +2566,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>>   {
>>   	msi_alloc_info_t *info = args;
>>   	struct its_device *its_dev = info->scratchpad[0].ptr;
>> +	struct its_node *its = its_dev->its;
>>   	irq_hw_number_t hwirq;
>>   	int err;
>>   	int i;
>> @@ -2574,6 +2575,8 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>>   	if (err)
>>   		return err;
>>   
>> +	err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
> Test err as in gicv2m driver?

Hmmm yes. Marc, do you want me to respin the patch?

Cheers,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg()
  2019-05-01 11:14     ` Julien Grall
@ 2019-05-01 11:37       ` Marc Zyngier
  0 siblings, 0 replies; 21+ messages in thread
From: Marc Zyngier @ 2019-05-01 11:37 UTC (permalink / raw)
  To: Julien Grall, Auger Eric, linux-kernel, iommu
  Cc: jason, douliyangs, robin.murphy, miquel.raynal, tglx, logang,
	bigeasy, linux-rt-users

On 01/05/2019 12:14, Julien Grall wrote:
> On 30/04/2019 13:34, Auger Eric wrote:
>> Hi Julien,
> 
> Hi Eric,
> 
> Thank you for the review!
> 
>>
>> On 4/29/19 4:44 PM, Julien Grall wrote:
>>> its_irq_compose_msi_msg() may be called from non-preemptible context.
>>> However, on RT, iommu_dma_map_msi_msg requires to be called from a
>>> preemptible context.
>>>
>>> A recent change split iommu_dma_map_msi_msg() in two new functions:
>>> one that should be called in preemptible context, the other does
>>> not have any requirement.
>>>
>>> The GICv3 ITS driver is reworked to avoid executing preemptible code in
>>> non-preemptible context. This can be achieved by preparing the MSI
>>> maping when allocating the MSI interrupt.
>> mapping
>>>
>>> Signed-off-by: Julien Grall <julien.grall@arm.com>
>>>
>>> ---
>>>      Changes in v2:
>>>          - Rework the commit message to use imperative mood
>>> ---
>>>   drivers/irqchip/irq-gic-v3-its.c | 5 ++++-
>>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>>> index 7577755bdcf4..12ddbcfe1b1e 100644
>>> --- a/drivers/irqchip/irq-gic-v3-its.c
>>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>>> @@ -1179,7 +1179,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
>>>   	msg->address_hi		= upper_32_bits(addr);
>>>   	msg->data		= its_get_event_id(d);
>>>   
>>> -	iommu_dma_map_msi_msg(d->irq, msg);
>>> +	iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
>>>   }
>>>   
>>>   static int its_irq_set_irqchip_state(struct irq_data *d,
>>> @@ -2566,6 +2566,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>>>   {
>>>   	msi_alloc_info_t *info = args;
>>>   	struct its_device *its_dev = info->scratchpad[0].ptr;
>>> +	struct its_node *its = its_dev->its;
>>>   	irq_hw_number_t hwirq;
>>>   	int err;
>>>   	int i;
>>> @@ -2574,6 +2575,8 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>>>   	if (err)
>>>   		return err;
>>>   
>>> +	err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
>> Test err as in gicv2m driver?
> 
> Hmmm yes. Marc, do you want me to respin the patch?

Sure, feel free to if you can. But what I really need is an Ack from
Jorg on the first few patches.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2019-05-01 11:37 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-29 14:44 [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Julien Grall
2019-04-29 14:44 ` [PATCH v2 1/7] genirq/msi: Add a new field in msi_desc to store an IOMMU cookie Julien Grall
2019-04-29 15:12   ` Robin Murphy
2019-04-30 12:53   ` Auger Eric
2019-04-29 14:44 ` [PATCH v2 2/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts Julien Grall
2019-04-29 15:16   ` Robin Murphy
2019-04-29 15:28   ` Marc Zyngier
2019-04-30 12:54   ` Auger Eric
2019-04-29 14:44 ` [PATCH v2 3/7] irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg() Julien Grall
2019-04-30 12:34   ` Auger Eric
2019-04-29 14:44 ` [PATCH v2 4/7] irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg() Julien Grall
2019-04-30 12:34   ` Auger Eric
2019-05-01 11:14     ` Julien Grall
2019-05-01 11:37       ` Marc Zyngier
2019-04-29 14:44 ` [PATCH v2 5/7] irqchip/ls-scfg-msi: Don't map the MSI page in ls_scfg_msi_compose_msg() Julien Grall
2019-04-29 14:44 ` [PATCH v2 6/7] irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b, s}i_msg() Julien Grall
2019-04-29 14:44 ` [PATCH v2 7/7] iommu/dma-iommu: Remove iommu_dma_map_msi_msg() Julien Grall
2019-04-29 15:19   ` Robin Murphy
2019-04-30 13:38   ` Auger Eric
2019-04-29 15:57 ` [PATCH v2 0/7] iommu/dma-iommu: Split iommu_dma_map_msi_msg in two parts Marc Zyngier
2019-04-29 19:35   ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).