From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935010AbcJUWcO (ORCPT ); Fri, 21 Oct 2016 18:32:14 -0400 Received: from mga06.intel.com ([134.134.136.31]:36598 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755178AbcJUWcM (ORCPT ); Fri, 21 Oct 2016 18:32:12 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,527,1473145200"; d="scan'208";a="22357513" From: Ashok Raj To: linux-kernel@vger.kernel.org Cc: Ashok Raj , David Woodhouse , Joerg Roedel , Sainath Grandhi , iommu@lists.linux-foundation.org, stable@vger.kernel.org Subject: [PATCH] iommu/vt-d: Fix IOMMU lookup for VF's Date: Fri, 21 Oct 2016 15:32:05 -0700 Message-Id: <1477089125-18523-1-git-send-email-ashok.raj@intel.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org IOMMU driver must pick the same IOMMU as that of a Physical Function (PF) for any of its Virtual Functions (VF). It is not practical to list all the VF's in the DMAR scope, as this list could be quite large. Linux also ignores any VF's listed in DMAR. See dmar_pci_bus_notifier() for virtfn handling. Since the driver is looking for the bdf of the VF, it will not find one from searching the DRHD listed in BIOS. As a result, the IOMMU driver associates the VF's under the INCLUDE_ALL iommu incorrectly. This patch looks up the IOMMU of the PF when handling VF's. Cc: David Woodhouse Cc: Joerg Roedel Cc: Ashok Raj Cc: Sainath Grandhi Cc: iommu@lists.linux-foundation.org Cc: stable@vger.kernel.org Signed-off-by: Sainath Grandhi Signed-off-by: Ashok Raj --- drivers/iommu/intel-iommu.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a4407ea..c2e4b5c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -885,6 +885,7 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf struct intel_iommu *iommu; struct device *tmp; struct pci_dev *ptmp, *pdev = NULL; + struct pci_dev *pf_pdev = NULL; u16 segment = 0; int i; @@ -893,6 +894,11 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf if (dev_is_pci(dev)) { pdev = to_pci_dev(dev); + /* + * Always lookup the PF's IOMMU when handling VF's + */ + pf_pdev = pci_physfn(pdev); + dev = &pf_pdev->dev; segment = pci_domain_nr(pdev->bus); } else if (has_acpi_companion(dev)) dev = &ACPI_COMPANION(dev)->dev; @@ -905,6 +911,9 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, tmp) { if (tmp == dev) { + if (pdev->is_virtfn) + goto got_pdev; + *bus = drhd->devices[i].bus; *devfn = drhd->devices[i].devfn; goto out; -- 2.7.4