Commit c1864790 authored by Robin Murphy's avatar Robin Murphy Committed by Joerg Roedel

iommu/dma: Relax locking in iommu_dma_prepare_msi()

Since commit ece6e6f0 ("iommu/dma-iommu: Split iommu_dma_map_msi_msg()
in two parts"), iommu_dma_prepare_msi() should no longer have to worry
about preempting itself, nor being called in atomic context at all. Thus
we can downgrade the IRQ-safe locking to a simple mutex to avoid angering
the new might_sleep() check in iommu_map().
Reported-by: default avatarQian Cai <cai@lca.pw>
Tested-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent f81b846d
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/iova.h> #include <linux/iova.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -44,7 +45,6 @@ struct iommu_dma_cookie { ...@@ -44,7 +45,6 @@ struct iommu_dma_cookie {
dma_addr_t msi_iova; dma_addr_t msi_iova;
}; };
struct list_head msi_page_list; struct list_head msi_page_list;
spinlock_t msi_lock;
/* Domain for flush queue callback; NULL if flush queue not in use */ /* Domain for flush queue callback; NULL if flush queue not in use */
struct iommu_domain *fq_domain; struct iommu_domain *fq_domain;
...@@ -63,7 +63,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type) ...@@ -63,7 +63,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (cookie) { if (cookie) {
spin_lock_init(&cookie->msi_lock);
INIT_LIST_HEAD(&cookie->msi_page_list); INIT_LIST_HEAD(&cookie->msi_page_list);
cookie->type = type; cookie->type = type;
} }
...@@ -1176,7 +1175,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev, ...@@ -1176,7 +1175,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
if (msi_page->phys == msi_addr) if (msi_page->phys == msi_addr)
return msi_page; return msi_page;
msi_page = kzalloc(sizeof(*msi_page), GFP_ATOMIC); msi_page = kzalloc(sizeof(*msi_page), GFP_KERNEL);
if (!msi_page) if (!msi_page)
return NULL; return NULL;
...@@ -1206,7 +1205,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) ...@@ -1206,7 +1205,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
struct iommu_domain *domain = iommu_get_domain_for_dev(dev); struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
struct iommu_dma_cookie *cookie; struct iommu_dma_cookie *cookie;
struct iommu_dma_msi_page *msi_page; struct iommu_dma_msi_page *msi_page;
unsigned long flags; static DEFINE_MUTEX(msi_prepare_lock); /* see below */
if (!domain || !domain->iova_cookie) { if (!domain || !domain->iova_cookie) {
desc->iommu_cookie = NULL; desc->iommu_cookie = NULL;
...@@ -1216,13 +1215,13 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) ...@@ -1216,13 +1215,13 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
cookie = domain->iova_cookie; cookie = domain->iova_cookie;
/* /*
* We disable IRQs to rule out a possible inversion against * In fact the whole prepare operation should already be serialised by
* irq_desc_lock if, say, someone tries to retarget the affinity * irq_domain_mutex further up the callchain, but that's pretty subtle
* of an MSI from within an IPI handler. * on its own, so consider this locking as failsafe documentation...
*/ */
spin_lock_irqsave(&cookie->msi_lock, flags); mutex_lock(&msi_prepare_lock);
msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
spin_unlock_irqrestore(&cookie->msi_lock, flags); mutex_unlock(&msi_prepare_lock);
msi_desc_set_iommu_cookie(desc, msi_page); msi_desc_set_iommu_cookie(desc, msi_page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment