/* * drivers/gpu/ion/ion_system_mapper.c * * Copyright (C) 2011 Google, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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. * */ #include #include #include #include #include #include #include "ion_priv.h" /* * This mapper is valid for any heap that allocates memory that already has * a kernel mapping, this includes vmalloc'd memory, kmalloc'd memory, * pages obtained via io_remap, etc. */ static void *ion_kernel_mapper_map(struct ion_mapper *mapper, struct ion_buffer *buffer, struct ion_mapping **mapping) { if (!((1 << buffer->heap->type) & mapper->heap_mask)) { pr_err("%s: attempting to map an unsupported heap\n", __func__); return ERR_PTR(-EINVAL); } /* XXX REVISIT ME!!! */ *((unsigned long *)mapping) = (unsigned long)buffer->priv; return buffer->priv; } static void ion_kernel_mapper_unmap(struct ion_mapper *mapper, struct ion_buffer *buffer, struct ion_mapping *mapping) { if (!((1 << buffer->heap->type) & mapper->heap_mask)) pr_err("%s: attempting to unmap an unsupported heap\n", __func__); } static void *ion_kernel_mapper_map_kernel(struct ion_mapper *mapper, struct ion_buffer *buffer, struct ion_mapping *mapping) { if (!((1 << buffer->heap->type) & mapper->heap_mask)) { pr_err("%s: attempting to unmap an unsupported heap\n", __func__); return ERR_PTR(-EINVAL); } return buffer->priv; } static int ion_kernel_mapper_map_user(struct ion_mapper *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma, struct ion_mapping *mapping) { int ret; switch (buffer->heap->type) { case ION_HEAP_KMALLOC: { unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv)); ret = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); break; } case ION_HEAP_VMALLOC: ret = remap_vmalloc_range(vma, buffer->priv, vma->vm_pgoff); break; default: pr_err("%s: attempting to map unsupported heap to userspace\n", __func__); return -EINVAL; } return ret; } static struct ion_mapper_ops ops = { .map = ion_kernel_mapper_map, .map_kernel = ion_kernel_mapper_map_kernel, .map_user = ion_kernel_mapper_map_user, .unmap = ion_kernel_mapper_unmap, }; struct ion_mapper *ion_system_mapper_create(void) { struct ion_mapper *mapper; mapper = kzalloc(sizeof(struct ion_mapper), GFP_KERNEL); if (!mapper) return ERR_PTR(-ENOMEM); mapper->type = ION_SYSTEM_MAPPER; mapper->ops = &ops; mapper->heap_mask = (1 << ION_HEAP_VMALLOC) | (1 << ION_HEAP_KMALLOC); return mapper; } void ion_system_mapper_destroy(struct ion_mapper *mapper) { kfree(mapper); }