From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Geert Uytterhoeven , Joerg Roedel , Sasha Levin Subject: [PATCH AUTOSEL 4.18 110/131] iommu/ipmmu-vmsa: Fix allocation in atomic context Date: Sun, 2 Sep 2018 13:05:21 +0000 Message-ID: <20180902064601.183036-110-alexander.levin@microsoft.com> References: <20180902064601.183036-1-alexander.levin@microsoft.com> In-Reply-To: <20180902064601.183036-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: From: Geert Uytterhoeven [ Upstream commit 46583e8c48c5a094ba28060615b3a7c8c576690f ] When attaching a device to an IOMMU group with CONFIG_DEBUG_ATOMIC_SLEEP=3Dy: BUG: sleeping function called from invalid context at mm/slab.h:421 in_atomic(): 1, irqs_disabled(): 128, pid: 61, name: kworker/1:1 ... Call trace: ... arm_lpae_alloc_pgtable+0x114/0x184 arm_64_lpae_alloc_pgtable_s1+0x2c/0x128 arm_32_lpae_alloc_pgtable_s1+0x40/0x6c alloc_io_pgtable_ops+0x60/0x88 ipmmu_attach_device+0x140/0x334 ipmmu_attach_device() takes a spinlock, while arm_lpae_alloc_pgtable() allocates memory using GFP_KERNEL. Originally, the ipmmu-vmsa driver had its own custom page table allocation implementation using GFP_ATOMIC, hence the spinlock was fine. Fix this by replacing the spinlock by a mutex, like the arm-smmu driver does. Fixes: f20ed39f53145e45 ("iommu/ipmmu-vmsa: Use the ARM LPAE page table all= ocator") Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Joerg Roedel Signed-off-by: Sasha Levin --- drivers/iommu/ipmmu-vmsa.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 40ae6e87cb88..ef566b4989d6 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -73,7 +73,7 @@ struct ipmmu_vmsa_domain { struct io_pgtable_ops *iop; =20 unsigned int context_id; - spinlock_t lock; /* Protects mappings */ + struct mutex mutex; /* Protects mappings */ }; =20 static struct ipmmu_vmsa_domain *to_vmsa_domain(struct iommu_domain *dom) @@ -595,7 +595,7 @@ static struct iommu_domain *__ipmmu_domain_alloc(unsign= ed type) if (!domain) return NULL; =20 - spin_lock_init(&domain->lock); + mutex_init(&domain->mutex); =20 return &domain->io_domain; } @@ -641,7 +641,6 @@ static int ipmmu_attach_device(struct iommu_domain *io_= domain, struct iommu_fwspec *fwspec =3D dev->iommu_fwspec; struct ipmmu_vmsa_device *mmu =3D to_ipmmu(dev); struct ipmmu_vmsa_domain *domain =3D to_vmsa_domain(io_domain); - unsigned long flags; unsigned int i; int ret =3D 0; =20 @@ -650,7 +649,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_= domain, return -ENXIO; } =20 - spin_lock_irqsave(&domain->lock, flags); + mutex_lock(&domain->mutex); =20 if (!domain->mmu) { /* The domain hasn't been used yet, initialize it. */ @@ -674,7 +673,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_= domain, } else dev_info(dev, "Reusing IPMMU context %u\n", domain->context_id); =20 - spin_unlock_irqrestore(&domain->lock, flags); + mutex_unlock(&domain->mutex); =20 if (ret < 0) return ret; --=20 2.17.1