All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Andrianov <andrew@ncrmnt.org>
To: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Arve Hj�nnev�g" <arve@android.com>,
	"Riley Andrews" <riandrews@android.com>,
	"Chen Gang" <gang.chen.5i5j@gmail.com>,
	"Fabian Frederick" <fabf@skynet.be>
Cc: Andrew Andrianov <andrew@ncrmnt.org>, linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] staging: ion: Add ion-physmem driver
Date: Mon,  6 Apr 2015 18:58:54 +0300	[thread overview]
Message-ID: <1428335934-10026-1-git-send-email-andrew@ncrmnt.org> (raw)
In-Reply-To: <1428335363-9854-1-git-send-email-andrew@ncrmnt.org>

Signed-off-by: Andrew Andrianov <andrew@ncrmnt.org>
---
 drivers/staging/android/ion/Kconfig       |    7 +
 drivers/staging/android/ion/Makefile      |    5 +-
 drivers/staging/android/ion/ion_physmem.c |  237 +++++++++++++++++++++++++++++
 3 files changed, 247 insertions(+), 2 deletions(-)
 create mode 100644 drivers/staging/android/ion/ion_physmem.c

diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 3452346..c558cf8 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -33,3 +33,10 @@ config ION_TEGRA
 	help
 	  Choose this option if you wish to use ion on an nVidia Tegra.
 
+config ION_PHYSMEM
+	bool "Generic PhysMem ION driver"
+	depends on ION
+	help
+	  Provides a generic ION driver that registers the
+	  /dev/ion device with heaps from devicetree entries.
+	  This heaps are made of chunks of physical memory
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index b56fd2b..ac9856d 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -5,6 +5,7 @@ ifdef CONFIG_COMPAT
 obj-$(CONFIG_ION) += compat_ion.o
 endif
 
-obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
-obj-$(CONFIG_ION_TEGRA) += tegra/
+obj-$(CONFIG_ION_DUMMY)   += ion_dummy_driver.o
+obj-$(CONFIG_ION_PHYSMEM) += ion_physmem.o
+obj-$(CONFIG_ION_TEGRA)   += tegra/
 
diff --git a/drivers/staging/android/ion/ion_physmem.c b/drivers/staging/android/ion/ion_physmem.c
new file mode 100644
index 0000000..e922d74
--- /dev/null
+++ b/drivers/staging/android/ion/ion_physmem.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 RC Module
+ * Andrew Andrianov <andrew@ncrmnt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Generic devicetree physmem driver for ION Memory Manager
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include "ion.h"
+#include "ion_priv.h"
+
+#define DRVNAME "ion-physmem"
+
+static struct ion_device *idev;
+
+static const struct of_device_id of_match_table[] = {
+	{ .compatible = "ion,physmem", },
+	{ /* end of list */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_table);
+
+/*
+#define PHYSMAP_ION_DEBUG y
+*/
+
+struct physmem_ion_dev {
+	struct ion_platform_heap  data;
+	struct ion_heap          *heap;
+	int                       need_free_coherent;
+	void                     *freepage_ptr;
+};
+
+static long ion_physmem_custom_ioctl(struct ion_client *client,
+				     unsigned int cmd,
+				     unsigned long arg)
+{
+/* Just an ugly debugging hack. */
+#ifdef PHYSMAP_ION_DEBUG
+	if ((cmd == 0xff)) {
+		ion_phys_addr_t addr;
+		size_t len;
+		struct ion_handle *hndl;
+
+		printk(KERN_INFO "=== ION PHYSMEM DEBUG PRINTOUT ===\n");
+		printk(KERN_INFO "N.B. DO disable CONFIG_ION_PHYSMEM_DEBUG in production\n");
+		printk(KERN_INFO "Shared fd is %d\n", (int) arg);
+		hndl = ion_import_dma_buf(client, arg);
+		if (!hndl) {
+			printk(KERN_INFO "Failed to import shared descriptor.\n");
+			return 0;
+		}
+		ion_phys(client, hndl, &addr, &len);
+		printk(KERN_INFO "shared buffer: phys 0x%lx len %ul\n",
+		       addr, len);
+		printk(KERN_INFO "=== ION PHYSMEM DEBUG PRINTOUT ===\n");
+	}
+#endif
+	return 0;
+}
+
+static int ion_physmem_probe(struct platform_device *pdev)
+{
+	int ret;
+	u32 ion_heap_id, ion_heap_align, ion_heap_type;
+	ion_phys_addr_t addr;
+	size_t size = 0;
+	const char *ion_heap_name;
+	struct resource *res;
+	struct physmem_ion_dev *ipdev;
+
+	/*
+	   Looks like we can only have one ION device in our system.
+	   Therefore we call ion_device_create on first probe and only
+	   add heaps to it on subsequent probe calls.
+	   FixMe: Do we need to hold a spinlock here once device probing
+	   becomes async?
+	*/
+
+	if (!idev) {
+		idev = ion_device_create(ion_physmem_custom_ioctl);
+		dev_info(&pdev->dev, "ion-physmem: ION PhysMem Driver. (c) RC Module 2015\n");
+		if (!idev)
+			return -ENOMEM;
+	}
+
+	ipdev = kzalloc(sizeof(struct physmem_ion_dev), GFP_KERNEL);
+	if (!ipdev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ipdev);
+
+	ret =  of_property_read_u32(pdev->dev.of_node, "ion-heap-id",
+				    &ion_heap_id);
+	if (ret != 0)
+		goto errfreeipdev;
+
+	ret =  of_property_read_u32(pdev->dev.of_node, "ion-heap-type",
+				    &ion_heap_type);
+	if (ret != 0)
+		goto errfreeipdev;
+
+	ret =  of_property_read_u32(pdev->dev.of_node, "ion-heap-align",
+				    &ion_heap_align);
+	if (ret != 0)
+		goto errfreeipdev;
+
+	ret =  of_property_read_string(pdev->dev.of_node, "ion-heap-name",
+				       &ion_heap_name);
+	if (ret != 0)
+		goto errfreeipdev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory");
+	/* Not always needed, throw no error if missing */
+	if (res) {
+		/* Fill in some defaults */
+		addr = res->start;
+		size = resource_size(res);
+	}
+
+	switch (ion_heap_type) {
+	case ION_HEAP_TYPE_DMA:
+		if (res) {
+			ret = dma_declare_coherent_memory(&pdev->dev,
+							  res->start,
+							  res->start,
+							  resource_size(res),
+							  DMA_MEMORY_MAP |
+							  DMA_MEMORY_EXCLUSIVE);
+			if (ret == 0) {
+				ret = -ENODEV;
+				goto errfreeipdev;
+			}
+		}
+		/*
+		 *  If no memory region declared in dt we assume that
+		 *  the user is okay with plain dma_alloc_coherent.
+		 */
+		break;
+	case ION_HEAP_TYPE_CARVEOUT:
+	case ION_HEAP_TYPE_CHUNK:
+	{
+		if (size == 0) {
+			ret = -EIO;
+			goto errfreeipdev;
+		}
+		ipdev->freepage_ptr = alloc_pages_exact(size, GFP_KERNEL);
+		if (ipdev->freepage_ptr) {
+			addr = virt_to_phys(ipdev->freepage_ptr);
+		} else {
+			ret = -ENOMEM;
+			goto errfreeipdev;
+		}
+		break;
+	}
+	}
+
+	ipdev->data.id    = ion_heap_id;
+	ipdev->data.type  = ion_heap_type;
+	ipdev->data.name  = ion_heap_name;
+	ipdev->data.align = ion_heap_align;
+	ipdev->data.base  = addr;
+	ipdev->data.size  = size;
+	/* This one make dma_declare_coherent_memory actually work */
+	ipdev->data.priv  = &pdev->dev;
+
+
+	ipdev->heap = ion_heap_create(&ipdev->data);
+	if (!ipdev->heap)
+		goto errfreeipdev;
+
+	if (!try_module_get(THIS_MODULE))
+		goto errfreeheap;
+
+	ion_device_add_heap(idev, ipdev->heap);
+
+	dev_info(&pdev->dev, "ion-physmem: heap %s id %d type %d align 0x%x at phys 0x%lx len %lu KiB\n",
+	       ion_heap_name, ion_heap_id, ion_heap_type, ion_heap_align,
+	       (unsigned long int) addr, ((unsigned long int) size / 1024));
+
+	return 0;
+
+errfreeheap:
+	kfree(ipdev->heap);
+errfreeipdev:
+	kfree(ipdev);
+	return -ENOMEM;
+}
+
+static int ion_physmem_remove(struct platform_device *pdev)
+{
+	struct physmem_ion_dev *ipdev = platform_get_drvdata(pdev);
+
+	ion_heap_destroy(ipdev->heap);
+	if (ipdev->need_free_coherent)
+		dma_release_declared_memory(&pdev->dev);
+	if (ipdev->freepage_ptr)
+		free_pages_exact(ipdev->freepage_ptr, ipdev->data.size);
+	kfree(ipdev->heap);
+	kfree(ipdev);
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+static void __exit ion_physmem_exit(void)
+{
+	if (idev)
+		ion_device_destroy(idev);
+}
+__exitcall(ion_physmem_exit);
+
+static struct platform_driver ion_physmem_driver = {
+	.probe		= ion_physmem_probe,
+	.remove		= ion_physmem_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ion-physmem",
+		.of_match_table = of_match_ptr(of_match_table),
+	},
+};
+module_platform_driver(ion_physmem_driver);
+
+MODULE_DESCRIPTION("Generic physmem driver for ION");
+MODULE_AUTHOR("Andrew Andrianov <andrew@ncrmnt.org>");
+MODULE_LICENSE("GPL");
-- 
1.7.10.4


  reply	other threads:[~2015-04-06 15:59 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-06 15:49 [PATCH 0/2] staging: ion: Add ion-physmem driver Andrew Andrianov
2015-04-06 15:58 ` Andrew Andrianov [this message]
2015-04-07  8:35   ` [PATCH 1/2] " Paul Bolle
2015-04-07  8:57     ` Greg Kroah-Hartman
2015-04-07 11:35     ` Andrew
2015-04-06 15:59 ` [PATCH 2/2] staging: ion: Add ion-physmem documentation Andrew Andrianov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1428335934-10026-1-git-send-email-andrew@ncrmnt.org \
    --to=andrew@ncrmnt.org \
    --cc=arve@android.com \
    --cc=fabf@skynet.be \
    --cc=gang.chen.5i5j@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=riandrews@android.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.