From patchwork Fri Apr 8 08:17:10 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joerg Roedel X-Patchwork-Id: 694171 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p388I91a009877 for ; Fri, 8 Apr 2011 08:18:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750773Ab1DHIRl (ORCPT ); Fri, 8 Apr 2011 04:17:41 -0400 Received: from ch1outboundpool.messaging.microsoft.com ([216.32.181.181]:16666 "EHLO ch1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751503Ab1DHIRX (ORCPT ); Fri, 8 Apr 2011 04:17:23 -0400 Received: from mail171-ch1-R.bigfish.com (216.32.181.173) by CH1EHSOBE002.bigfish.com (10.43.70.52) with Microsoft SMTP Server id 14.1.225.8; Fri, 8 Apr 2011 08:17:20 +0000 Received: from mail171-ch1 (localhost.localdomain [127.0.0.1]) by mail171-ch1-R.bigfish.com (Postfix) with ESMTP id 46B19E016C; Fri, 8 Apr 2011 08:17:20 +0000 (UTC) X-SpamScore: -2 X-BigFish: VPS-2(zzbb2cKzz1202hzz8275bhz32i668h839h61h) X-Spam-TCS-SCL: 0:0 X-Forefront-Antispam-Report: KIP:(null); UIP:(null); IPVD:NLI; H:ausb3twp02.amd.com; RD:none; EFVD:NLI Received: from mail171-ch1 (localhost.localdomain [127.0.0.1]) by mail171-ch1 (MessageSwitch) id 1302250639951698_7037; Fri, 8 Apr 2011 08:17:19 +0000 (UTC) Received: from CH1EHSMHS007.bigfish.com (snatpool1.int.messaging.microsoft.com [10.43.68.248]) by mail171-ch1.bigfish.com (Postfix) with ESMTP id E060517E004E; Fri, 8 Apr 2011 08:17:19 +0000 (UTC) Received: from ausb3twp02.amd.com (163.181.249.109) by CH1EHSMHS007.bigfish.com (10.43.70.7) with Microsoft SMTP Server id 14.1.225.8; Fri, 8 Apr 2011 08:17:18 +0000 X-WSS-ID: 0LJBR0R-02-3ML-02 X-M-MSG: Received: from sausexedgep02.amd.com (sausexedgep02-ext.amd.com [163.181.249.73]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by ausb3twp02.amd.com (Axway MailGate 3.8.1) with ESMTP id 296C1FCC0B2; Fri, 8 Apr 2011 03:17:15 -0500 (CDT) Received: from sausexhtp02.amd.com (163.181.3.152) by sausexedgep02.amd.com (163.181.36.59) with Microsoft SMTP Server (TLS) id 8.3.106.1; Fri, 8 Apr 2011 03:17:41 -0500 Received: from storexhtp01.amd.com (172.24.4.3) by sausexhtp02.amd.com (163.181.3.152) with Microsoft SMTP Server (TLS) id 8.3.83.0; Fri, 8 Apr 2011 03:17:16 -0500 Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp01.amd.com (172.24.4.3) with Microsoft SMTP Server id 8.3.83.0; Fri, 8 Apr 2011 04:17:14 -0400 Received: from lemmy.osrc.amd.com (lemmy.osrc.amd.com [165.204.15.93]) by gwo.osrc.amd.com (Postfix) with ESMTP id D48E549C5A1; Fri, 8 Apr 2011 09:17:12 +0100 (BST) Received: by lemmy.osrc.amd.com (Postfix, from userid 1000) id BD1F5FFDB1; Fri, 8 Apr 2011 10:17:12 +0200 (CEST) From: Joerg Roedel To: , Jesse Barnes CC: , , Joerg Roedel Subject: [PATCH 5/5] x86/amd-iommu: Add ATS enable/disable code Date: Fri, 8 Apr 2011 10:17:10 +0200 Message-ID: <1302250630-8183-6-git-send-email-joerg.roedel@amd.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1302250630-8183-1-git-send-email-joerg.roedel@amd.com> References: <1302250630-8183-1-git-send-email-joerg.roedel@amd.com> MIME-Version: 1.0 X-OriginatorOrg: amd.com Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 08 Apr 2011 08:18:09 +0000 (UTC) This patch adds the necessary code to the AMD IOMMU driver for enabling and disabling the ATS capability on a device and to setup the IOMMU data structures correctly. Signed-off-by: Joerg Roedel --- arch/x86/include/asm/amd_iommu_types.h | 2 ++ arch/x86/kernel/amd_iommu.c | 29 +++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index cb811c9..7434377 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -216,6 +216,8 @@ #define IOMMU_PTE_IR (1ULL << 61) #define IOMMU_PTE_IW (1ULL << 62) +#define DTE_FLAG_IOTLB 0x01 + #define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL) #define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P) #define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK)) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index f3ce433..ad97fd6 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1452,17 +1452,22 @@ static bool dma_ops_domain(struct protection_domain *domain) return domain->flags & PD_DMA_OPS_MASK; } -static void set_dte_entry(u16 devid, struct protection_domain *domain) +static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) { u64 pte_root = virt_to_phys(domain->pt_root); + u32 flags = 0; pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) << DEV_ENTRY_MODE_SHIFT; pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; - amd_iommu_dev_table[devid].data[2] = domain->id; - amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); - amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); + if (ats) + flags |= DTE_FLAG_IOTLB; + + amd_iommu_dev_table[devid].data[3] |= flags; + amd_iommu_dev_table[devid].data[2] = domain->id; + amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); + amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); } static void clear_dte_entry(u16 devid) @@ -1479,16 +1484,22 @@ static void do_attach(struct device *dev, struct protection_domain *domain) { struct iommu_dev_data *dev_data; struct amd_iommu *iommu; + struct pci_dev *pdev; + bool ats = false; u16 devid; devid = get_device_id(dev); iommu = amd_iommu_rlookup_table[devid]; dev_data = get_dev_data(dev); + pdev = to_pci_dev(dev); + + if (amd_iommu_iotlb_sup) + ats = pci_enable_ats(pdev, PAGE_SHIFT) == 0; /* Update data structures */ dev_data->domain = domain; list_add(&dev_data->list, &domain->dev_list); - set_dte_entry(devid, domain); + set_dte_entry(devid, domain, ats); /* Do reference counting */ domain->dev_iommu[iommu->index] += 1; @@ -1502,11 +1513,13 @@ static void do_detach(struct device *dev) { struct iommu_dev_data *dev_data; struct amd_iommu *iommu; + struct pci_dev *pdev; u16 devid; devid = get_device_id(dev); iommu = amd_iommu_rlookup_table[devid]; dev_data = get_dev_data(dev); + pdev = to_pci_dev(dev); /* decrease reference counters */ dev_data->domain->dev_iommu[iommu->index] -= 1; @@ -1517,6 +1530,9 @@ static void do_detach(struct device *dev) list_del(&dev_data->list); clear_dte_entry(devid); + if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev)) + pci_disable_ats(pdev); + /* Flush the DTE entry */ device_flush_dte(dev); } @@ -1795,8 +1811,9 @@ static void update_device_table(struct protection_domain *domain) struct iommu_dev_data *dev_data; list_for_each_entry(dev_data, &domain->dev_list, list) { + struct pci_dev *pdev = to_pci_dev(dev_data->dev); u16 devid = get_device_id(dev_data->dev); - set_dte_entry(devid, domain); + set_dte_entry(devid, domain, pci_ats_enabled(pdev)); } }