msm: qdsp5: Add ION framework support for 7x27A & 8x25 targets
Modified adsp driver to support the ION memory framework
for 7x27A and 8x25 targets
Change-Id: I0df75ed3d71575a28fe9f2267117a94c5a224296
Signed-off-by: Saikumar Kondaparthi <saikumar@codeaurora.org>
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index b485058..eee7e37 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -1262,7 +1262,7 @@
clk_set_rate(mod->clk, adsp_info.module[i].clk_rate);
mod->verify_cmd = adsp_info.module[i].verify_cmd;
mod->patch_event = adsp_info.module[i].patch_event;
- INIT_HLIST_HEAD(&mod->pmem_regions);
+ INIT_HLIST_HEAD(&mod->ion_regions);
mod->pdev.name = adsp_info.module[i].pdev_name;
mod->pdev.id = -1;
adsp_info.id_to_module[i] = mod;
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 0f16111..06e2f22 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -20,12 +20,16 @@
#include <linux/types.h>
#include <linux/msm_adsp.h>
+#include <linux/ion.h>
#include <mach/msm_rpcrouter.h>
#include <mach/msm_adsp.h>
int adsp_pmem_fixup(struct msm_adsp_module *module, void **addr,
unsigned long len);
-int adsp_pmem_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
+int adsp_ion_do_cache_op(struct msm_adsp_module *module, void *addr,
+ void *paddr, unsigned long len,
+ unsigned long offset, int cmd);
+int adsp_ion_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
unsigned long *kvaddr, unsigned long len,
struct file **filp, unsigned long *offset);
int adsp_pmem_paddr_fixup(struct msm_adsp_module *module, void **addr);
@@ -276,8 +280,8 @@
struct clk *clk;
int open_count;
- struct mutex pmem_regions_lock;
- struct hlist_head pmem_regions;
+ struct mutex ion_regions_lock;
+ struct hlist_head ion_regions;
int (*verify_cmd) (struct msm_adsp_module*, unsigned int, void *,
size_t);
int (*patch_event) (struct msm_adsp_module*, struct adsp_event *);
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index 6860d84..9d261ae 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/qdsp5/adsp_driver.c
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2012 Code Aurora Forum. All rights reserved.
* Author: Iliyan Malchev <ibm@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -23,25 +23,27 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/module.h>
-
#include "adsp.h"
-
#include <linux/msm_adsp.h>
#include <linux/android_pmem.h>
#include <mach/debug_mm.h>
-struct adsp_pmem_info {
+struct adsp_ion_info {
int fd;
void *vaddr;
};
-struct adsp_pmem_region {
+struct adsp_ion_region {
struct hlist_node list;
void *vaddr;
unsigned long paddr;
unsigned long kvaddr;
unsigned long len;
+ unsigned long ion_flag;
struct file *file;
+ struct ion_handle *handle;
+ struct ion_client *client;
+ int fd;
};
struct adsp_device {
@@ -90,14 +92,14 @@
res; \
})
-static int adsp_pmem_check(struct msm_adsp_module *module,
+static int adsp_ion_check(struct msm_adsp_module *module,
void *vaddr, unsigned long len)
{
- struct adsp_pmem_region *region_elt;
+ struct adsp_ion_region *region_elt;
struct hlist_node *node;
- struct adsp_pmem_region t = { .vaddr = vaddr, .len = len };
+ struct adsp_ion_region t = { .vaddr = vaddr, .len = len };
- hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
+ hlist_for_each_entry(region_elt, node, &module->ion_regions, list) {
if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
OVERLAPS(region_elt, &t)) {
MM_ERR("module %s:"
@@ -116,58 +118,109 @@
return 0;
}
-static int adsp_pmem_add(struct msm_adsp_module *module,
- struct adsp_pmem_info *info)
+static int get_ion_region_info(int fd, struct adsp_ion_region *region)
{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct adsp_pmem_region *region;
+ unsigned long ionflag;
+ void *temp_ptr;
int rc = -EINVAL;
- mutex_lock(&module->pmem_regions_lock);
- region = kmalloc(sizeof(*region), GFP_KERNEL);
+ region->client = msm_ion_client_create(UINT_MAX, "Video_Client");
+ if (IS_ERR_OR_NULL(region->client)) {
+ pr_err("Unable to create ION client\n");
+ goto client_error;
+ }
+ region->handle = ion_import_dma_buf(region->client, fd);
+ if (IS_ERR_OR_NULL(region->handle)) {
+ pr_err("%s: could not get handle of the given fd\n", __func__);
+ goto import_error;
+ }
+ rc = ion_handle_get_flags(region->client, region->handle, &ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n", __func__);
+ goto flag_error;
+ }
+ temp_ptr = ion_map_kernel(region->client, region->handle, ionflag);
+ if (IS_ERR_OR_NULL(temp_ptr)) {
+ pr_err("%s: could not get virtual address\n", __func__);
+ goto map_error;
+ }
+ region->kvaddr = (unsigned long) temp_ptr;
+ region->ion_flag = (unsigned long) ionflag;
+
+ rc = ion_phys(region->client, region->handle, ®ion->paddr,
+ (size_t *)(®ion->len));
+ if (rc) {
+ pr_err("%s: could not get physical address\n", __func__);
+ goto ion_error;
+ }
+ return rc;
+ion_error:
+ ion_unmap_kernel(region->client, region->handle);
+map_error:
+ ion_free(region->client, region->handle);
+flag_error:
+import_error:
+ ion_client_destroy(region->client);
+client_error:
+ return -EINVAL;
+}
+
+static void free_ion_region(struct ion_client *client,
+ struct ion_handle *handle)
+{
+ ion_unmap_kernel(client, handle);
+ ion_free(client, handle);
+ ion_client_destroy(client);
+}
+
+static int adsp_ion_add(struct msm_adsp_module *module,
+ struct adsp_ion_info *info)
+{
+ struct adsp_ion_region *region;
+ int rc = -EINVAL;
+ mutex_lock(&module->ion_regions_lock);
+ region = kmalloc(sizeof(struct adsp_ion_region), GFP_KERNEL);
if (!region) {
rc = -ENOMEM;
goto end;
}
INIT_HLIST_NODE(®ion->list);
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
+ if (get_ion_region_info(info->fd, region)) {
kfree(region);
goto end;
}
- rc = adsp_pmem_check(module, info->vaddr, len);
+ rc = adsp_ion_check(module, info->vaddr, region->len);
if (rc < 0) {
- put_pmem_file(file);
+ free_ion_region(region->client, region->handle);
kfree(region);
goto end;
}
-
region->vaddr = info->vaddr;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
-
- hlist_add_head(®ion->list, &module->pmem_regions);
+ region->fd = info->fd;
+ region->file = NULL;
+ MM_INFO("adsp_ion_add: module %s: fd %d, vaddr Ox%x, len %d\n",
+ module->name, region->fd, (unsigned int)region->vaddr,
+ (int)region->len);
+ hlist_add_head(®ion->list, &module->ion_regions);
end:
- mutex_unlock(&module->pmem_regions_lock);
+ mutex_unlock(&module->ion_regions_lock);
return rc;
}
-static int adsp_pmem_lookup_vaddr(struct msm_adsp_module *module, void **addr,
- unsigned long len, struct adsp_pmem_region **region)
+static int adsp_ion_lookup_vaddr(struct msm_adsp_module *module, void **addr,
+ unsigned long len, struct adsp_ion_region **region)
{
struct hlist_node *node;
void *vaddr = *addr;
- struct adsp_pmem_region *region_elt;
+ struct adsp_ion_region *region_elt;
int match_count = 0;
*region = NULL;
/* returns physical address or zero */
- hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
+ hlist_for_each_entry(region_elt, node, &module->ion_regions, list) {
if (vaddr >= region_elt->vaddr &&
vaddr < region_elt->vaddr + region_elt->len &&
vaddr + len <= region_elt->vaddr + region_elt->len) {
@@ -186,7 +239,7 @@
"multiple hits for vaddr %p, len %ld\n",
module->name, vaddr, len);
hlist_for_each_entry(region_elt, node,
- &module->pmem_regions, list) {
+ &module->ion_regions, list) {
if (vaddr >= region_elt->vaddr &&
vaddr < region_elt->vaddr + region_elt->len &&
vaddr + len <= region_elt->vaddr + region_elt->len)
@@ -200,16 +253,37 @@
return *region ? 0 : -1;
}
-int adsp_pmem_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
+int adsp_ion_do_cache_op(struct msm_adsp_module *module,
+ void *addr, void *paddr, unsigned long len,
+ unsigned long offset, int cmd)
+{
+ struct adsp_ion_region *region;
+ void *vaddr = addr;
+ int ret;
+ ret = adsp_ion_lookup_vaddr(module, &vaddr, len, ®ion);
+ if (ret) {
+ MM_ERR("not patching %s (paddr & kvaddr)," \
+ " lookup (%p, %ld) failed\n",
+ module->name, vaddr, len);
+ return ret;
+ }
+ if ((region->ion_flag == CACHED) && region->handle) {
+ len = ((((len) + 31) & (~31)) + 32);
+ ret = msm_ion_do_cache_op(region->client, region->handle,
+ (void *)paddr, len, cmd);
+ }
+ return ret;
+}
+int adsp_ion_fixup_kvaddr(struct msm_adsp_module *module, void **addr,
unsigned long *kvaddr, unsigned long len,
struct file **filp, unsigned long *offset)
{
- struct adsp_pmem_region *region;
+ struct adsp_ion_region *region;
void *vaddr = *addr;
unsigned long *paddr = (unsigned long *)addr;
int ret;
- ret = adsp_pmem_lookup_vaddr(module, addr, len, ®ion);
+ ret = adsp_ion_lookup_vaddr(module, addr, len, ®ion);
if (ret) {
MM_ERR("not patching %s (paddr & kvaddr),"
" lookup (%p, %ld) failed\n",
@@ -228,12 +302,12 @@
int adsp_pmem_fixup(struct msm_adsp_module *module, void **addr,
unsigned long len)
{
- struct adsp_pmem_region *region;
+ struct adsp_ion_region *region;
void *vaddr = *addr;
unsigned long *paddr = (unsigned long *)addr;
int ret;
- ret = adsp_pmem_lookup_vaddr(module, addr, len, ®ion);
+ ret = adsp_ion_lookup_vaddr(module, addr, len, ®ion);
if (ret) {
MM_ERR("not patching %s, lookup (%p, %ld) failed\n",
module->name, vaddr, len);
@@ -281,7 +355,7 @@
goto end;
}
- mutex_lock(&adev->module->pmem_regions_lock);
+ mutex_lock(&adev->module->ion_regions_lock);
if (adsp_verify_cmd(adev->module, cmd.queue, cmd_data, cmd.len)) {
MM_ERR("module %s: verify failed.\n", adev->module->name);
rc = -EINVAL;
@@ -291,7 +365,7 @@
wmb();
rc = msm_adsp_write(adev->module, cmd.queue, cmd_data, cmd.len);
end:
- mutex_unlock(&adev->module->pmem_regions_lock);
+ mutex_unlock(&adev->module->ion_regions_lock);
if (cmd.len > 256)
kfree(cmd_data);
@@ -309,14 +383,14 @@
return yes || adev->abort;
}
-static int adsp_pmem_lookup_paddr(struct msm_adsp_module *module, void **addr,
- struct adsp_pmem_region **region)
+static int adsp_ion_lookup_paddr(struct msm_adsp_module *module, void **addr,
+ struct adsp_ion_region **region)
{
struct hlist_node *node;
unsigned long paddr = (unsigned long)(*addr);
- struct adsp_pmem_region *region_elt;
+ struct adsp_ion_region *region_elt;
- hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
+ hlist_for_each_entry(region_elt, node, &module->ion_regions, list) {
if (paddr >= region_elt->paddr &&
paddr < region_elt->paddr + region_elt->len) {
*region = region_elt;
@@ -328,12 +402,12 @@
int adsp_pmem_paddr_fixup(struct msm_adsp_module *module, void **addr)
{
- struct adsp_pmem_region *region;
+ struct adsp_ion_region *region;
unsigned long paddr = (unsigned long)(*addr);
unsigned long *vaddr = (unsigned long *)addr;
int ret;
- ret = adsp_pmem_lookup_paddr(module, addr, ®ion);
+ ret = adsp_ion_lookup_paddr(module, addr, ®ion);
if (ret) {
MM_ERR("not patching %s, paddr %p lookup failed\n",
module->name, vaddr);
@@ -429,20 +503,23 @@
return rc;
}
-static int adsp_pmem_del(struct msm_adsp_module *module)
+static int adsp_ion_del(struct msm_adsp_module *module)
{
struct hlist_node *node, *tmp;
- struct adsp_pmem_region *region;
+ struct adsp_ion_region *region;
- mutex_lock(&module->pmem_regions_lock);
- hlist_for_each_safe(node, tmp, &module->pmem_regions) {
- region = hlist_entry(node, struct adsp_pmem_region, list);
+ mutex_lock(&module->ion_regions_lock);
+ hlist_for_each_safe(node, tmp, &module->ion_regions) {
+ region = hlist_entry(node, struct adsp_ion_region, list);
hlist_del(node);
- put_pmem_file(region->file);
+ MM_INFO("adsp_ion_del: module %s: fd %d, vaddr Ox%x, len %d\n",
+ module->name, region->fd, (unsigned int)region->vaddr,
+ (int)region->len);
+ free_ion_region(region->client, region->handle);
kfree(region);
}
- mutex_unlock(&module->pmem_regions_lock);
- BUG_ON(!hlist_empty(&module->pmem_regions));
+ mutex_unlock(&module->ion_regions_lock);
+ BUG_ON(!hlist_empty(&module->ion_regions));
return 0;
}
@@ -479,10 +556,10 @@
}
case ADSP_IOCTL_REGISTER_PMEM: {
- struct adsp_pmem_info info;
+ struct adsp_ion_info info;
if (copy_from_user(&info, (void *) arg, sizeof(info)))
return -EFAULT;
- return adsp_pmem_add(adev->module, &info);
+ return adsp_ion_add(adev->module, &info);
}
case ADSP_IOCTL_ABORT_EVENT_READ:
@@ -491,7 +568,7 @@
break;
case ADSP_IOCTL_UNREGISTER_PMEM:
- return adsp_pmem_del(adev->module);
+ return adsp_ion_del(adev->module);
default:
break;
@@ -510,7 +587,7 @@
/* clear module before putting it to avoid race with open() */
adev->module = NULL;
- rc = adsp_pmem_del(module);
+ rc = adsp_ion_del(module);
msm_adsp_put(module);
return rc;
@@ -581,8 +658,8 @@
MM_INFO("opened module '%s' adev %p\n", adev->name, adev);
filp->private_data = adev;
adev->abort = 0;
- INIT_HLIST_HEAD(&adev->module->pmem_regions);
- mutex_init(&adev->module->pmem_regions_lock);
+ INIT_HLIST_HEAD(&adev->module->ion_regions);
+ mutex_init(&adev->module->ion_regions_lock);
return 0;
}
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index 492fa0e..af259b5 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -3,7 +3,7 @@
* Verificion code for aDSP VDEC packets from userspace.
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -55,7 +55,7 @@
MM_DBG("virt %x %x\n", (unsigned int)phys_addr,
(unsigned int)phys_size);
if (phys_addr) {
- if (adsp_pmem_fixup_kvaddr(module, &phys_addr,
+ if (adsp_ion_fixup_kvaddr(module, &phys_addr,
&kvaddr, phys_size, filp, offset)) {
MM_ERR("ah%x al%x sh%x sl%x addr %x size %x\n",
*high, *low, size_high,
@@ -77,6 +77,7 @@
static int verify_vdec_pkt_cmd(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
+ void *phys_addr;
unsigned short cmd_id = ((unsigned short *)cmd_data)[0];
viddec_cmd_subframe_pkt *pkt;
unsigned long subframe_pkt_addr;
@@ -89,7 +90,6 @@
unsigned short frame_buffer_size_high, frame_buffer_size_low;
struct file *filp = NULL;
unsigned long offset = 0;
- struct pmem_addr pmem_addr;
unsigned long Codec_Id = 0;
MM_DBG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id,
@@ -102,6 +102,8 @@
return -1;
pkt = (viddec_cmd_subframe_pkt *)cmd_data;
+ phys_addr = high_low_short_to_ptr(pkt->subframe_packet_high,
+ pkt->subframe_packet_low);
if (pmem_fixup_high_low(&(pkt->subframe_packet_high),
&(pkt->subframe_packet_low),
@@ -114,16 +116,12 @@
return -1;
Codec_Id = pkt->codec_selection_word;
/*Invalidate cache before accessing the cached pmem buffer*/
- if (filp) {
- pmem_addr.vaddr = subframe_pkt_addr;
- pmem_addr.length = (((subframe_pkt_size*2) + 31) & (~31)) + 32;
- pmem_addr.offset = offset;
- if (pmem_cache_maint (filp, PMEM_INV_CACHES, &pmem_addr)) {
- MM_ERR("Cache operation failed for phys addr high %x"
- " addr low %x\n", pkt->subframe_packet_high,
- pkt->subframe_packet_low);
- return -EINVAL;
- }
+ if (adsp_ion_do_cache_op(module, phys_addr, (void *)subframe_pkt_addr,
+ subframe_pkt_size*2, offset, ION_IOC_INV_CACHES)){
+ MM_ERR("Cache operation failed for" \
+ " phys addr high %x addr low %x\n",
+ pkt->subframe_packet_high, pkt->subframe_packet_low);
+ return -EINVAL;
}
/* deref those ptrs and check if they are a frame header packet */
frame_header_pkt = (unsigned short *)subframe_pkt_addr;
@@ -241,19 +239,14 @@
frame_buffer_low += 2;
}
}
- /*Flush the cached pmem subframe packet before sending to DSP*/
- if (filp) {
- pmem_addr.vaddr = subframe_pkt_addr;
- pmem_addr.length = MAX_FLUSH_SIZE;
- pmem_addr.offset = offset;
- if (pmem_cache_maint(filp, PMEM_CLEAN_CACHES, &pmem_addr)) {
- MM_ERR("Cache operation failed for phys addr high %x"
- " addr low %x\n", pkt->subframe_packet_high,
- pkt->subframe_packet_low);
- return -1;
- }
+ /*Flush the cached mem subframe packet before sending to DSP*/
+ if (adsp_ion_do_cache_op(module, phys_addr, (void *)subframe_pkt_addr,
+ MAX_FLUSH_SIZE, offset, ION_IOC_CLEAN_CACHES)){
+ MM_ERR("Cache operation failed for" \
+ " phys addr high %x addr low %x\n",
+ pkt->subframe_packet_high, pkt->subframe_packet_low);
+ return -EINVAL;
}
-
return 0;
}
diff --git a/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c
index 936b7af..290a14c 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_videoenc_verify_cmd.c
@@ -3,7 +3,7 @@
* Verificion code for aDSP VENC packets from userspace.
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -53,7 +53,7 @@
phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low);
MM_DBG("virt %x %x\n", (unsigned int)phys_addr,
(unsigned int)phys_size);
- if (adsp_pmem_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size,
+ if (adsp_ion_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size,
NULL, NULL)) {
MM_ERR("ah%x al%x sh%x sl%x addr %x size %x\n",
*high, *low, size_high,