From patchwork Thu Jun 18 08:50:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joerg Roedel X-Patchwork-Id: 6634601 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B60049F358 for ; Thu, 18 Jun 2015 08:50:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E4BCB20811 for ; Thu, 18 Jun 2015 08:50:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CD5E9207FC for ; Thu, 18 Jun 2015 08:50:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752607AbbFRIul (ORCPT ); Thu, 18 Jun 2015 04:50:41 -0400 Received: from 8bytes.org ([81.169.241.247]:56959 "EHLO theia.8bytes.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752322AbbFRIuj (ORCPT ); Thu, 18 Jun 2015 04:50:39 -0400 Received: by theia.8bytes.org (Postfix, from userid 1000) id 652363EE; Thu, 18 Jun 2015 10:50:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=8bytes.org; s=mail-1; t=1434617438; bh=2LOeXRc7ToRA9dlxQYXuYMnhZ/yiUN/do0v7QfY2sHE=; h=From:To:Cc:Subject:Date:From; b=VcYI1amhnfHe2EK/iJBhiv+jWJ4TaATRr53IJdSlCz4w0+79yidWTaXla4WSRI1Y6 s0uaPtt9JyK/0/iFMKYRYjMNL74UtXID+rq2flQ/Kg53arBpChIMNXQEH06gCt0tuS 7hP0cXvf8ZTmb0q7Zi9qOii2NfRRZRHl6x0nixqDLcmlbILNeaVrh6phBLPSVsDI1P WQcr35wqLKiqEhOhLNHpcEpA9LhtoT1TjxSLHAl6hmJkvSXJY4nhVgzcyGeKz1IhKQ 12uGIPKpRA/hgKIcq6dEPYXhRF1y5shbew0MViccfFNDPS7BFoHQEoi7QJRXJAd2ds zcVnxzRyXOpQg== From: Joerg Roedel To: Bjorn Helgaas Cc: Gregor Dick , linux-pci@vger.kernel.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, Joerg Roedel , stable@kernel.org Subject: [PATCH] PCI: Don't use SR-IOV lock for ATS Date: Thu, 18 Jun 2015 10:50:20 +0200 Message-Id: <1434617420-18313-1-git-send-email-joro@8bytes.org> X-Mailer: git-send-email 1.9.1 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Joerg Roedel The use of the SR-IOV lock for ATS causes a dead-lock in the AMD-IOMMU driver when virtual functions are added that have an ATS capability. The problem is that the VFs will be added to the bus with the SR-IOV lock held. While added to the bus the device-notifiers will run and invoke AMD IOMMU code, which itself will assign the device to a domain try to enable ATS. When it calls pci_enable_ats() this will dead-lock. Fix this by introducing a global ats_lock. ATS enablement and disablement isn't in any fast-path, so a global lock shouldn't hurt here. Cc: stable@kernel.org Reported-by: Gregor Dick Signed-off-by: Joerg Roedel --- drivers/pci/ats.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index a8099d4..f0c3c6f 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -17,6 +17,8 @@ #include "pci.h" +static DEFINE_MUTEX(ats_lock); + static int ats_alloc_one(struct pci_dev *dev, int ps) { int pos; @@ -67,7 +69,7 @@ int pci_enable_ats(struct pci_dev *dev, int ps) if (dev->is_physfn || dev->is_virtfn) { struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn; - mutex_lock(&pdev->sriov->lock); + mutex_lock(&ats_lock); if (pdev->ats) rc = pdev->ats->stu == ps ? 0 : -EINVAL; else @@ -75,7 +77,7 @@ int pci_enable_ats(struct pci_dev *dev, int ps) if (!rc) pdev->ats->ref_cnt++; - mutex_unlock(&pdev->sriov->lock); + mutex_unlock(&ats_lock); if (rc) return rc; } @@ -116,11 +118,11 @@ void pci_disable_ats(struct pci_dev *dev) if (dev->is_physfn || dev->is_virtfn) { struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn; - mutex_lock(&pdev->sriov->lock); + mutex_lock(&ats_lock); pdev->ats->ref_cnt--; if (!pdev->ats->ref_cnt) ats_free_one(pdev); - mutex_unlock(&pdev->sriov->lock); + mutex_unlock(&ats_lock); } if (!dev->is_physfn)