From patchwork Thu Jul 5 06:24:19 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Barry Song X-Patchwork-Id: 1158071 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 02425DFB7C for ; Thu, 5 Jul 2012 06:29:58 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SmfWG-0004Da-Db; Thu, 05 Jul 2012 06:26:28 +0000 Received: from cluster-d.mailcontrol.com ([85.115.60.190]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1SmfVf-00049d-14 for linux-arm-kernel@lists.infradead.org; Thu, 05 Jul 2012 06:25:55 +0000 Received: from rly18d.srv.mailcontrol.com (localhost.localdomain [127.0.0.1]) by rly18d.srv.mailcontrol.com (MailControl) with ESMTP id q656Pcjp018061 for ; Thu, 5 Jul 2012 07:25:45 +0100 Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by rly18d.srv.mailcontrol.com (MailControl) id q656OffH014973 for ; Thu, 5 Jul 2012 07:24:41 +0100 Received: from banasiexc02.ASIA.ROOT.PRI ([202.80.51.114]) by rly18d-eth0.srv.mailcontrol.com (envelope-sender ) (MIMEDefang) with ESMTP id q656OW36014842 (TLS bits=128 verify=FAIL); Thu, 05 Jul 2012 07:24:41 +0100 (BST) Received: from SHAASIEXC01.ASIA.ROOT.PRI (10.125.12.84) by banasiexc02.ASIA.ROOT.PRI (10.190.12.22) with Microsoft SMTP Server (TLS) id 14.1.289.1; Thu, 5 Jul 2012 11:54:38 +0530 Received: from localhost.localdomain (10.125.36.195) by asimail.csr.com (10.125.12.88) with Microsoft SMTP Server (TLS) id 14.1.289.1; Thu, 5 Jul 2012 15:24:36 +0900 From: Barry Song To: , Subject: [PATCH v4 RESEND] mm: cma: add a simple kernel module as the helper to test CMA Date: Thu, 5 Jul 2012 14:24:19 +0800 Message-ID: <1341469459-29558-1-git-send-email-Barry.Song@csr.com> X-Mailer: git-send-email 1.7.1 MIME-Version: 1.0 X-Originating-IP: [10.125.36.195] X-Scanned-By: MailControl 7.7.2 (www.mailcontrol.com) on 10.68.1.128 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [85.115.60.190 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Greg Kroah-Hartman , Marek Szyprowski , workgroup.linux@csr.com, mina86@mina86.com, Barry Song X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Barry Song Any write request to /dev/cma_test will let the module to allocate memory from CMA, for example: 1st time $ echo 1024 > /dev/cma_test will require cma_test to request 1MB(1024KB) 2nd time $ echo 2048 > /dev/cma_test will require cma_test to request 2MB(2048KB) Any read request to /dev/cma_test will let the module to free the 1st valid memory from CMA, for example: 1st time $ cat /dev/cma_test will require cma_test to free the 1MB allocated in the first write request 2nd time $ cat /dev/cma_test will require cma_test to free the 2MB allocated in the second write request Signed-off-by: Barry Song Reviewed-by: Michal Nazarewicz Cc: Marek Szyprowski Cc: Greg Kroah-Hartman --- resend to Greg KH so that he can decide whether it should be placed at tools or drivers/misc; See the discussion thread: [1] https://lkml.org/lkml/2012/7/3/80 [2] https://lkml.org/lkml/2012/7/3/224 [3] https://lkml.org/lkml/2012/7/4/87 tools/cma/Makefile | 13 +++++ tools/cma/cma_test.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 0 deletions(-) create mode 100644 tools/cma/Makefile create mode 100644 tools/cma/cma_test.c diff --git a/tools/cma/Makefile b/tools/cma/Makefile new file mode 100644 index 0000000..d15c2c0 --- /dev/null +++ b/tools/cma/Makefile @@ -0,0 +1,13 @@ +# Kernel modules +# +# To compile for ARM: +# make ARCH=arm CC=arm-none-linux-gnueabi-gcc +# +obj-m += cma_test.o + +build: kernel_modules + +kernel_modules: + ${MAKE} -C $(CURDIR)/../.. M=$(CURDIR) +clean: + ${MAKE} -C $(CURDIR)/../.. M=$(CURDIR) clean diff --git a/tools/cma/cma_test.c b/tools/cma/cma_test.c new file mode 100644 index 0000000..7eb96db --- /dev/null +++ b/tools/cma/cma_test.c @@ -0,0 +1,140 @@ +/* + * kernel module helper for testing CMA + * + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct cma_allocation { + struct list_head list; + size_t size; + dma_addr_t dma; + void *virt; +}; + +static struct device *cma_dev; +static LIST_HEAD(cma_allocations); +static DEFINE_SPINLOCK(cma_lock); + +/* + * any read request will free the 1st allocated coherent memory, eg. + * cat /dev/cma_test + */ +static ssize_t +cma_test_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct cma_allocation *alloc = NULL; + + spin_lock(&cma_lock); + if (!list_empty(&cma_allocations)) { + alloc = list_first_entry(&cma_allocations, + struct cma_allocation, list); + list_del(&alloc->list); + } + spin_unlock(&cma_lock); + + if (!alloc) + return -EIDRM; + + dma_free_coherent(cma_dev, alloc->size, alloc->virt, + alloc->dma); + + _dev_info(cma_dev, "free: CM virt: %p dma: %p size:%zuK\n", + alloc->virt, (void *)alloc->dma, alloc->size / SZ_1K); + kfree(alloc); + + return 0; +} + +/* + * any write request will alloc a new coherent memory, eg. + * echo 1024 > /dev/cma_test + * will request 1024KiB by CMA + */ +static ssize_t +cma_test_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + struct cma_allocation *alloc; + unsigned long size; + int ret; + + ret = kstrtoul_from_user(buf, count, 0, &size); + if (ret) + return ret; + + if (!size) + return -EINVAL; + + if (size > ~(size_t)0 / SZ_1K) + return -EOVERFLOW; + + alloc = kmalloc(sizeof *alloc, GFP_KERNEL); + if (!alloc) + return -ENOMEM; + + alloc->size = size * SZ_1K; + alloc->virt = dma_alloc_coherent(cma_dev, alloc->size, + &alloc->dma, GFP_KERNEL); + + if (alloc->virt) { + _dev_info(cma_dev, "alloc: virt: %p dma: %p size: %zuK\n", + alloc->virt, (void *)alloc->dma, alloc->size / SZ_1K); + + spin_lock(&cma_lock); + list_add_tail(&alloc->list, &cma_allocations); + spin_unlock(&cma_lock); + + return count; + } else { + dev_err(cma_dev, "no mem in CMA area\n"); + kfree(alloc); + return -ENOSPC; + } +} + +static const struct file_operations cma_test_fops = { + .owner = THIS_MODULE, + .read = cma_test_read, + .write = cma_test_write, +}; + +static struct miscdevice cma_test_misc = { + .name = "cma_test", + .fops = &cma_test_fops, +}; + +static int __init cma_test_init(void) +{ + int ret = misc_register(&cma_test_misc); + + if (unlikely(ret)) { + pr_err("failed to register cma test misc device!\n"); + return ret; + } + cma_dev = cma_test_misc.this_device; + cma_dev->coherent_dma_mask = ~0; + _dev_info(cma_dev, "registered.\n"); + + return 0; +} +module_init(cma_test_init); + +static void __exit cma_test_exit(void) +{ + misc_deregister(&cma_test_misc); +} +module_exit(cma_test_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Barry Song "); +MODULE_DESCRIPTION("kernel module to help the test of CMA"); +MODULE_ALIAS("cma_test");