From patchwork Wed Jan 11 14:24:40 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hiroshi Doyu X-Patchwork-Id: 135396 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2E2D6B6EEC for ; Thu, 12 Jan 2012 01:28:11 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Rkz7H-0007xG-JJ; Wed, 11 Jan 2012 14:25:27 +0000 Received: from hqemgate04.nvidia.com ([216.228.121.35]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Rkz7C-0007w6-W3 for linux-arm-kernel@lists.infradead.org; Wed, 11 Jan 2012 14:25:24 +0000 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate04.nvidia.com id ; Wed, 11 Jan 2012 06:24:03 -0800 Received: from hqemhub02.nvidia.com ([172.17.108.22]) by hqnvupgp08.nvidia.com (PGP Universal service); Wed, 11 Jan 2012 06:25:18 -0800 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Wed, 11 Jan 2012 06:25:18 -0800 Received: from deemhub01.nvidia.com (10.21.69.137) by hqemhub02.nvidia.com (172.20.150.31) with Microsoft SMTP Server (TLS) id 8.3.213.0; Wed, 11 Jan 2012 06:25:17 -0800 Received: from DEMAIL01.nvidia.com ([10.21.69.140]) by deemhub01.nvidia.com ([10.21.69.137]) with mapi; Wed, 11 Jan 2012 15:25:16 +0100 From: Hiroshi Doyu To: "linux@arm.linux.org.uk" Date: Wed, 11 Jan 2012 15:24:40 +0100 Subject: Re: [PATCH v3 0/2] ARM: IOMMU: tegra: Add iommu_ops for GART/SMMU driver Thread-Topic: [PATCH v3 0/2] ARM: IOMMU: tegra: Add iommu_ops for GART/SMMU driver Thread-Index: AczQbNX119GnLoLjSdWNg4Ji4xrFlQ== Message-ID: <20120111.162440.1854857348878391112.hdoyu@nvidia.com> References: <20120105125326.GT11810@n2100.arm.linux.org.uk><20120105.162930.604365154868332443.hdoyu@nvidia.com><20120105144631.GV11810@n2100.arm.linux.org.uk> In-Reply-To: <20120105144631.GV11810@n2100.arm.linux.org.uk> Accept-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: x-nvconfidentiality: public acceptlanguage: en-US MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.7 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [216.228.121.35 listed in list.dnswl.org] -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record 2.5 SUSPICIOUS_RECIPS Similar addresses in recipient list -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: "linux-tegra@vger.kernel.org" , "linaro-mm-sig-bounces@lists.linaro.org" , "iommu@lists.linux-foundation.org" , "linux-kernel@vger.kernel.org" , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org From: Russell King - ARM Linux Subject: Re: [PATCH v3 0/2] ARM: IOMMU: tegra: Add iommu_ops for GART/SMMU driver Date: Thu, 5 Jan 2012 15:46:31 +0100 Message-ID: <20120105144631.GV11810@n2100.arm.linux.org.uk> > On Thu, Jan 05, 2012 at 03:29:30PM +0100, Hiroshi Doyu wrote: > > Ok, the above function order should be as below? > > > > page = alloc_page(GFP_KERNEL); > > cpu_addr = kmap(page); > > memset(cpu_addr, 0xa5, PAGE_SIZE); > > dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_TO_DEVICE); > > < expect GPU does something > > > dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_TO_DEVICE); > > < CPU can access data here again> > > kunmap(cpu_addr); > > __free_page(page); > > That should work, but it's not particularly nice to wrap kmap around > the DMA API. > > Bear in mind that alloc_page(GFP_KERNEL) will always give you a lowmem > page. So, you might as well do: > > page = alloc_page(GFP_KERNEL); > cpu_addr = page_address(page); > memset() > dma_addr = dma_map_single(dev, cpu_addr, PAGE_SIZE, DMA_TO_DEVICE); > < GPU access > > dma_unmap_single(dev, dma_ddr, PAGE_SIZE, DMA_TO_DEVICE); > < CPU access > > __free_page(page); > > and this doesn't raise any issues with kmap vs DMA API. Attached the update one just in case that someone wants to use it for theirs. From 76aefea1c7ad004590295dbe63c27f0c6f482f7a Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Thu, 15 Dec 2011 13:24:24 +0200 Subject: [PATCH 1/1] [NOT-FOR-MERGE] TEST: Simple dma-iommu-mapping API TEST module This is not posted to merge but this is necessary to understand how SMMU/GART works with DMA(-iommu-mapping-)API. This is a test to verify DMA API(DMA iommu mapping API), where SoC specific iommu_ops is used internally. This does alloc/(un)map/free, but there's no actual access from device side since it requires device specific communications. Signed-off-by: Hiroshi DOYU --- drivers/iommu/dmaapi-test.c | 202 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 202 insertions(+), 0 deletions(-) create mode 100644 drivers/iommu/dmaapi-test.c diff --git a/drivers/iommu/dmaapi-test.c b/drivers/iommu/dmaapi-test.c new file mode 100644 index 0000000..3199386 --- /dev/null +++ b/drivers/iommu/dmaapi-test.c @@ -0,0 +1,202 @@ +/* + * DMA IOMMU mapping API test module + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * Author: Krishna Reddy , + * Hiroshi DOYU + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define DEBUG +#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "devices.h" + +/* FIXME: 2x and 3x should be supported at once */ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +#define IOVA_START TEGRA_GART_BASE +#define IOVA_SIZE TEGRA_GART_SIZE +static struct platform_device *tegra_iommu_device = &tegra_gart_device; +#elif CONFIG_ARCH_TEGRA_3x_SOC +#define IOVA_START TEGRA_SMMU_BASE +#define IOVA_SIZE TEGRA_SMMU_SIZE +static struct platform_device *tegra_iommu_device = &tegra_smmu_device; +#else +#error Unsupported device +#endif + +#define NUM_TEST 3 +#define MAP_SIZE (4 * PAGE_SIZE) + +struct dmaapi_test_case { + char *name; + void (*fn)(struct device *); +}; + +static void dmaapi_test_map_page(struct device *dev) +{ + struct page *page; + dma_addr_t dma_addr; + void *cpu_addr; + + page = alloc_page(GFP_KERNEL); + BUG_ON(!page); + + cpu_addr = page_address(page); + BUG_ON(!cpu_addr); + memset(cpu_addr, 0xa5, PAGE_SIZE); + + dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_TO_DEVICE); + BUG_ON(!dma_addr); + + pr_debug("pid:%d,%s mapped\t%08x:%08x\n", + current->pid, dev_name(dev), dma_addr, page_to_phys(page)); + + /* + * Expect GPU access + */ + + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_TO_DEVICE); + + /* + * CPU access + */ + BUG_ON(*(char *)cpu_addr != 0xa5); + + __free_page(page); +} + +static void dmaapi_test_alloc_coherent(struct device *dev) +{ + dma_addr_t da[NUM_TEST]; + void *va[NUM_TEST]; + int i; + + for (i = 0; i < NUM_TEST; i++) { + void *cpu_addr; + dma_addr_t dma_addr; + + cpu_addr = dma_alloc_coherent(dev, MAP_SIZE, + &dma_addr, GFP_KERNEL); + BUG_ON(!cpu_addr); + memset(cpu_addr, 0xa5, MAP_SIZE); + + pr_debug("pid:%d,%s,[%d] mapped\t%08x:%08x\n", + current->pid, dev_name(dev), i, + dma_addr, virt_to_phys(cpu_addr)); + + da[i] = dma_addr; + va[i] = cpu_addr; + } + + while (--i >= 0) { + pr_debug("pid:%d,%s,[%d] unmapping\t%08x:%08x\n", + current->pid, dev_name(dev), i, + da[i], virt_to_phys(va[i])); + dma_free_coherent(dev, MAP_SIZE, va[i], da[i]); + } +} + +static struct dmaapi_test_case test[] = { + { + .name = "dmaapi/map page", + .fn = dmaapi_test_map_page, + }, + { + .name = "dmaapi/alloc coherent", + .fn = dmaapi_test_alloc_coherent, + }, +}; + +static u32 dummy_hwgrp_map[] = { + HWG_DC | HWG_AFI | HWG_AVPC | HWG_DCB, + HWG_EPP | HWG_HC | HWG_G2 | HWG_MPE | HWG_HDA | HWG_ISP, + HWG_NV | HWG_PPCS | HWG_SATA | HWG_NV2 | HWG_VI | HWG_VDE, +}; + +/* FIXME: Need driver for iommu context? */ +static struct platform_device dmaapi_dummy_device[] = { + { .name = "hwgrp@a", .id = -1, }, + { .name = "hwgrp@b", .id = -1, }, + { .name = "hwgrp@c", .id = -1, }, +}; + +static int dmaapi_test_thread(void *data) +{ + int i; + struct dmaapi_test_case *c = data; + + for (i = 0; true; i++) { + struct device *dev; + int interval[] = {7, 3, 5,}; + int n; + + n = i % ARRAY_SIZE(dmaapi_dummy_device); + ssleep(interval[n]); + dev = &dmaapi_dummy_device[n].dev; + c->fn(dev); + } + return 0; +} + +static int __init dmaapi_test_init(void) +{ + int i; + struct dma_iommu_mapping *map; + + map = arm_iommu_create_mapping(IOVA_START, IOVA_SIZE, 0); + BUG_ON(!map); + pr_debug("Allocate IOVA: %08x-%08x\n", map->base, map->base + IOVA_SIZE); + + for (i = 0; i < ARRAY_SIZE(dmaapi_dummy_device); i++) { + int err; + struct platform_device *pdev = &dmaapi_dummy_device[i]; + + pdev->dev.platform_data = (void *)dummy_hwgrp_map[i]; + pdev->dev.parent = &tegra_iommu_device->dev; + err = platform_device_register(pdev); + BUG_ON(err); + + err = arm_iommu_attach_device(&pdev->dev, map); + BUG_ON(err); + pr_debug("IOMMU API: Attached to %s\n", dev_name(&pdev->dev)); + } + + for (i = 0; i < ARRAY_SIZE(test); i++) + kthread_run(dmaapi_test_thread, &test[i], test[i].name); + + return 0; +} +module_init(dmaapi_test_init); + +MODULE_AUTHOR("Krishna Reddy "); +MODULE_AUTHOR("Hiroshi DOYU "); +MODULE_DESCRIPTION("DMA IOMMU mapping API test"); +MODULE_LICENSE("GPL v2"); -- 1.7.5.4