From patchwork Thu Feb 26 09:31:12 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Han, Weidong" X-Patchwork-Id: 8903 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n1Q9WGG4003179 for ; Thu, 26 Feb 2009 09:32:16 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752694AbZBZJcK (ORCPT ); Thu, 26 Feb 2009 04:32:10 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753039AbZBZJcJ (ORCPT ); Thu, 26 Feb 2009 04:32:09 -0500 Received: from mga01.intel.com ([192.55.52.88]:62521 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752996AbZBZJcI (ORCPT ); Thu, 26 Feb 2009 04:32:08 -0500 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 26 Feb 2009 01:25:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.38,270,1233561600"; d="scan'208,223";a="434314985" Received: from pgsmsx603.gar.corp.intel.com ([10.221.43.87]) by fmsmga002.fm.intel.com with ESMTP; 26 Feb 2009 01:27:56 -0800 Received: from pgsmsx601.gar.corp.intel.com (10.221.43.69) by pgsmsx603.gar.corp.intel.com (10.221.43.87) with Microsoft SMTP Server (TLS) id 8.1.311.2; Thu, 26 Feb 2009 17:31:16 +0800 Received: from pdsmsx602.ccr.corp.intel.com (172.16.12.184) by pgsmsx601.gar.corp.intel.com (10.221.43.69) with Microsoft SMTP Server (TLS) id 8.1.311.2; Thu, 26 Feb 2009 17:31:15 +0800 Received: from pdsmsx503.ccr.corp.intel.com ([172.16.12.95]) by pdsmsx602.ccr.corp.intel.com ([172.16.12.184]) with mapi; Thu, 26 Feb 2009 17:31:14 +0800 From: "Han, Weidong" To: "'dwmw2@infradead.org'" , "'Avi Kivity'" CC: "'iommu@lists.linux-foundation.org'" , "'kvm'" Date: Thu, 26 Feb 2009 17:31:12 +0800 Subject: [PATCH] VT-d: fix PCI device detach from virtual machine Thread-Topic: [PATCH] VT-d: fix PCI device detach from virtual machine Thread-Index: AcmX9Pb+a4II6OIgTWia2/NVUjME7A== Message-ID: <715D42877B251141A38726ABF5CABF2C0195A7B959@pdsmsx503.ccr.corp.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When assign a device behind conventional PCI bridge or PCIe to PCI/PCI-x bridge to a domain, it must assign its bridge and may also need to assign secondary interface to the same domain. Dependent assignment is already there, but dependent deassignment is missed when detach device from virtual machine. This results in conventional PCI device assignment failure after it has been assigned once. This patch addes dependent deassignment, and fixes the issue. Signed-off-by: Weidong Han --- drivers/pci/intel-iommu.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index f3f6865..d21a1a5 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2772,6 +2772,33 @@ static int vm_domain_add_dev_info(struct dmar_domain *domain, return 0; } +static void iommu_detach_dependent_devices(struct intel_iommu *iommu, + struct pci_dev *pdev) +{ + struct pci_dev *tmp, *parent; + + if (!iommu || !pdev) + return; + + /* dependent device detach */ + tmp = pci_find_upstream_pcie_bridge(pdev); + /* Secondary interface's bus number and devfn 0 */ + if (tmp) { + parent = pdev->bus->self; + while (parent != tmp) { + iommu_detach_dev(iommu, parent->bus->number, + parent->devfn); + parent = parent->bus->self; + } + if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ + iommu_detach_dev(iommu, + tmp->subordinate->number, 0); + else /* this is a legacy PCI bridge */ + iommu_detach_dev(iommu, + tmp->bus->number, tmp->devfn); + } +} + static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, struct pci_dev *pdev) { @@ -2797,6 +2824,7 @@ static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, spin_unlock_irqrestore(&device_domain_lock, flags); iommu_detach_dev(iommu, info->bus, info->devfn); + iommu_detach_dependent_devices(iommu, pdev); free_devinfo_mem(info); spin_lock_irqsave(&device_domain_lock, flags); @@ -2846,6 +2874,7 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) iommu = device_to_iommu(info->bus, info->devfn); iommu_detach_dev(iommu, info->bus, info->devfn); + iommu_detach_dependent_devices(iommu, info->dev); /* clear this iommu in iommu_bmp, update iommu count * and coherency