/*
* drivers/video/tegra/host/nvhost_memmgr.c
*
* Tegra Graphics Host Memory Management Abstraction
*
* Copyright (c) 2012, NVIDIA Corporation.
*
* 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, see .
*/
#include
#include
#include "nvhost_memmgr.h"
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
#include "nvmap.h"
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
#include "dmabuf.h"
#endif
#include "chip_support.h"
struct mem_mgr *nvhost_memmgr_alloc_mgr(void)
{
struct mem_mgr *mgr = NULL;
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
mgr = nvhost_nvmap_alloc_mgr();
#else
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
mgr = (struct mem_mgr)1;
#endif
#endif
return mgr;
}
void nvhost_memmgr_put_mgr(struct mem_mgr *mgr)
{
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
nvhost_nvmap_put_mgr(mgr);
#else
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
mgr = (struct mem_mgr)1;
#endif
#endif
}
struct mem_mgr *nvhost_memmgr_get_mgr(struct mem_mgr *_mgr)
{
struct mem_mgr *mgr = NULL;
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
mgr = nvhost_nvmap_get_mgr(_mgr);
#else
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
mgr = (struct mem_mgr)1;
#endif
#endif
return mgr;
}
struct mem_mgr *nvhost_memmgr_get_mgr_file(int fd)
{
struct mem_mgr *mgr = NULL;
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
mgr = nvhost_nvmap_get_mgr_file(fd);
#else
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
mgr = (struct mem_mgr)1;
#endif
#endif
return mgr;
}
struct mem_handle *nvhost_memmgr_alloc(struct mem_mgr *mgr,
size_t size, size_t align, int flags)
{
struct mem_handle *h = NULL;
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
h = nvhost_nvmap_alloc(mgr, size, align, flags);
#else
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
h = nvhost_dmabuf_alloc(mgr, size, align, flags);
#endif
#endif
return h;
}
struct mem_handle *nvhost_memmgr_get(struct mem_mgr *mgr,
u32 id, struct platform_device *dev)
{
struct mem_handle *h = NULL;
switch (nvhost_memmgr_type(id)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
h = (struct mem_handle *) nvhost_nvmap_get(mgr, id, dev);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
h = (struct mem_handle *) nvhost_dmabuf_get(id, dev);
break;
#endif
default:
break;
}
return h;
}
void nvhost_memmgr_put(struct mem_mgr *mgr, struct mem_handle *handle)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
nvhost_nvmap_put(mgr, handle);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
nvhost_dmabuf_put(handle);
break;
#endif
default:
break;
}
}
struct sg_table *nvhost_memmgr_pin(struct mem_mgr *mgr,
struct mem_handle *handle)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
return nvhost_nvmap_pin(mgr, handle);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
return nvhost_dmabuf_pin(handle);
break;
#endif
default:
return 0;
break;
}
}
void nvhost_memmgr_unpin(struct mem_mgr *mgr,
struct mem_handle *handle, struct sg_table *sgt)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
nvhost_nvmap_unpin(mgr, handle, sgt);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
nvhost_dmabuf_unpin(handle, sgt);
break;
#endif
default:
break;
}
}
void *nvhost_memmgr_mmap(struct mem_handle *handle)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
return nvhost_nvmap_mmap(handle);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
return nvhost_dmabuf_mmap(handle);
break;
#endif
default:
return 0;
break;
}
}
void nvhost_memmgr_munmap(struct mem_handle *handle, void *addr)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
nvhost_nvmap_munmap(handle, addr);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
nvhost_dmabuf_munmap(handle, addr);
break;
#endif
default:
break;
}
}
void *nvhost_memmgr_kmap(struct mem_handle *handle, unsigned int pagenum)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
return nvhost_nvmap_kmap(handle, pagenum);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
return nvhost_dmabuf_kmap(handle, pagenum);
break;
#endif
default:
return 0;
break;
}
}
void nvhost_memmgr_kunmap(struct mem_handle *handle, unsigned int pagenum,
void *addr)
{
switch (nvhost_memmgr_type((u32)handle)) {
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
case mem_mgr_type_nvmap:
nvhost_nvmap_kunmap(handle, pagenum, addr);
break;
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
case mem_mgr_type_dmabuf:
nvhost_dmabuf_kunmap(handle, pagenum, addr);
break;
#endif
default:
break;
}
}
int nvhost_memmgr_pin_array_ids(struct mem_mgr *mgr,
struct platform_device *dev,
long unsigned *ids,
dma_addr_t *phys_addr,
u32 count,
struct nvhost_job_unpin *unpin_data)
{
int pin_count = 0;
#ifdef CONFIG_TEGRA_GRHOST_USE_NVMAP
{
int nvmap_count = 0;
nvmap_count = nvhost_nvmap_pin_array_ids(mgr,
ids, MEMMGR_TYPE_MASK,
mem_mgr_type_nvmap,
count, unpin_data,
phys_addr);
if (nvmap_count < 0)
return nvmap_count;
pin_count += nvmap_count;
}
#endif
#ifdef CONFIG_TEGRA_GRHOST_USE_DMABUF
{
int dmabuf_count = 0;
dmabuf_count = nvhost_dmabuf_pin_array_ids(dev,
ids, MEMMGR_TYPE_MASK,
mem_mgr_type_dmabuf,
count, &unpin_data[pin_count],
phys_addr);
if (dmabuf_count < 0) {
/* clean up previous handles */
while (pin_count) {
pin_count--;
/* unpin, put */
nvhost_memmgr_unpin(mgr,
unpin_data[pin_count].h,
unpin_data[pin_count].mem);
nvhost_memmgr_put(mgr,
unpin_data[pin_count].h);
}
return dmabuf_count;
}
pin_count += dmabuf_count;
}
#endif
return pin_count;
}
static const struct nvhost_mem_ops mem_ops = {
.alloc_mgr = nvhost_memmgr_alloc_mgr,
.put_mgr = nvhost_memmgr_put_mgr,
.get_mgr = nvhost_memmgr_get_mgr,
.get_mgr_file = nvhost_memmgr_get_mgr_file,
.alloc = nvhost_memmgr_alloc,
.get = nvhost_memmgr_get,
.put = nvhost_memmgr_put,
.pin = nvhost_memmgr_pin,
.unpin = nvhost_memmgr_unpin,
.mmap = nvhost_memmgr_mmap,
.munmap = nvhost_memmgr_munmap,
.kmap = nvhost_memmgr_kmap,
.kunmap = nvhost_memmgr_kunmap,
.pin_array_ids = nvhost_memmgr_pin_array_ids,
};
int nvhost_memmgr_init(struct nvhost_chip_support *chip)
{
chip->mem = mem_ops;
return 0;
}