summaryrefslogtreecommitdiffstats
path: root/pvr-source/services4/srvkm/env/linux/gc_bvmapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'pvr-source/services4/srvkm/env/linux/gc_bvmapping.c')
-rw-r--r--pvr-source/services4/srvkm/env/linux/gc_bvmapping.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/pvr-source/services4/srvkm/env/linux/gc_bvmapping.c b/pvr-source/services4/srvkm/env/linux/gc_bvmapping.c
new file mode 100644
index 0000000..6c5d17a
--- /dev/null
+++ b/pvr-source/services4/srvkm/env/linux/gc_bvmapping.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2011 Texas Instruments, Inc
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/bltsville.h>
+#include <linux/bvinternal.h>
+#include <linux/gcbv-iface.h>
+
+#include "gc_bvmapping.h"
+#include "services_headers.h"
+
+void gc_bvmap_meminfo(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ int i;
+ IMG_CPU_PHYADDR phy_addr;
+ unsigned long *page_addrs;
+ struct bvbuffdesc *buffdesc;
+ struct bvphysdesc *physdesc;
+ int num_pages;
+ struct bventry bv_entry;
+ enum bverror bv_error;
+
+ gcbv_init(&bv_entry);
+ if (!bv_entry.bv_map) {
+ psMemInfo->bvmap_handle = NULL;
+ return;
+ }
+
+ num_pages = (psMemInfo->uAllocSize +
+ PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ page_addrs = kzalloc(sizeof(*page_addrs) * num_pages, GFP_KERNEL);
+ if (!page_addrs) {
+ printk(KERN_ERR "%s: Out of memory\n", __func__);
+ return;
+ }
+
+ physdesc = kzalloc(sizeof(*physdesc), GFP_KERNEL);
+ buffdesc = kzalloc(sizeof(*buffdesc), GFP_KERNEL);
+ if (!buffdesc || !physdesc) {
+ printk(KERN_ERR "%s: Out of memory\n", __func__);
+ kfree(page_addrs);
+ kfree(physdesc);
+ kfree(buffdesc);
+ return;
+ }
+
+ for (i = 0; i < num_pages; i++) {
+ phy_addr = OSMemHandleToCpuPAddr(
+ psMemInfo->sMemBlk.hOSMemHandle, i << PAGE_SHIFT);
+ page_addrs[i] = (u32)phy_addr.uiAddr;
+ }
+
+ buffdesc->structsize = sizeof(*buffdesc);
+ buffdesc->map = NULL;
+ buffdesc->length = psMemInfo->uAllocSize;
+ buffdesc->auxtype = BVAT_PHYSDESC;
+ buffdesc->auxptr = physdesc;
+ physdesc->structsize = sizeof(*physdesc);
+ physdesc->pagesize = PAGE_SIZE;
+ physdesc->pagearray = page_addrs;
+ physdesc->pagecount = num_pages;
+
+ /*
+ * For ion allocated buffers let's verify how many planes this
+ * meminfo consist of
+ */
+ if(psMemInfo->ui32Flags & PVRSRV_MEM_ION) {
+ IMG_UINT32 num_addr_offsets = 0;
+ OSGetMemMultiPlaneInfo(psMemInfo->sMemBlk.hOSMemHandle,
+ NULL, &num_addr_offsets);
+
+ /*
+ * Account for this meminfo plane offset (relative to the base
+ * address) if necessary
+ */
+ if(num_addr_offsets > 0)
+ physdesc->pageoffset = psMemInfo->planeOffsets[0];
+
+ /*
+ * In BV there is no way to specify multiple offsets, check
+ * all planes have the same offset and report any discrepancy
+ */
+ for (i = 1; i < num_addr_offsets; i++) {
+ IMG_UINT32 plane_offset =
+ psMemInfo->planeOffsets[i] % PAGE_SIZE;
+ if (psMemInfo->planeOffsets[0] != plane_offset) {
+ printk(KERN_WARNING "%s: meminfo %p offset 0 %d"
+ " != offset %d %d, coalignment is "
+ "missing\n", __func__, psMemInfo,
+ psMemInfo->planeOffsets[0],
+ i, plane_offset);
+ }
+ }
+ }
+
+ bv_error = bv_entry.bv_map(buffdesc);
+ if (bv_error) {
+ printk(KERN_ERR "%s: Failed to map meminfo %p, bverror %d\n",
+ __func__, psMemInfo, bv_error);
+ psMemInfo->bvmap_handle = NULL;
+ } else
+ psMemInfo->bvmap_handle = buffdesc;
+
+}
+
+void gc_bvunmap_meminfo(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ struct bvbuffdesc *buffdesc;
+ struct bvphysdesc *physdesc;
+ struct bventry bv_entry;
+ enum bverror bv_error;
+
+ gcbv_init(&bv_entry);
+ if (!bv_entry.bv_map || !psMemInfo || !psMemInfo->bvmap_handle)
+ return;
+
+ buffdesc = psMemInfo->bvmap_handle;
+ physdesc = (struct bvphysdesc*) buffdesc->auxptr;
+ bv_error = bv_entry.bv_unmap(buffdesc);
+ if (bv_error) {
+ printk(KERN_ERR "%s: Failed to unmap bvhandle %p from meminfo "
+ "%p, bverror %d\n", __func__, buffdesc, psMemInfo,
+ bv_error);
+ }
+
+ kfree(physdesc->pagearray);
+ kfree(physdesc);
+ kfree(psMemInfo->bvmap_handle);
+ psMemInfo->bvmap_handle = NULL;
+}
+
+IMG_VOID *gc_meminfo_to_hndl(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ return psMemInfo->bvmap_handle;
+}