add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2010 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_kernel_license.h
* Defines for the macro MODULE_LICENSE.
*/
#ifndef __MALI_KERNEL_LICENSE_H__
#define __MALI_KERNEL_LICENSE_H__
#ifdef __cplusplus
extern "C"
{
#endif
#define MALI_KERNEL_LINUX_LICENSE "GPL"
#define MALI_LICENSE_IS_GPL 1
#ifdef __cplusplus
}
#endif
#endif /* __MALI_KERNEL_LICENSE_H__ */

View File

@@ -0,0 +1,82 @@
/**
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_device_pause_resume.c
* Implementation of the Mali pause/resume functionality
*/
#if USING_MALI_PMM
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/module.h>
#include "mali_osk.h"
#include "mali_kernel_common.h"
#include "mali_platform.h"
#include "mali_linux_pm.h"
#include "mali_device_pause_resume.h"
#include "mali_pmm.h"
#include "mali_kernel_license.h"
#ifdef CONFIG_PM
#if MALI_LICENSE_IS_GPL
/* Mali Pause Resume APIs */
int mali_dev_pause()
{
int err = 0;
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
if ((mali_dvfs_device_state == _MALI_DEVICE_SUSPEND) || (mali_device_state == _MALI_DEVICE_SUSPEND_IN_PROGRESS)
|| (mali_device_state == _MALI_DEVICE_SUSPEND)
#ifdef CONFIG_HAS_EARLYSUSPEND
|| (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB))
#else
)
#endif
{
err = -EPERM;
}
if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) && (!err))
{
mali_device_suspend(MALI_PMM_EVENT_DVFS_PAUSE, &dvfs_pm_thread);
mali_dvfs_device_state = _MALI_DEVICE_SUSPEND;
}
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
EXPORT_SYMBOL(mali_dev_pause);
int mali_dev_resume()
{
int err = 0;
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) || (mali_device_state == _MALI_DEVICE_SUSPEND_IN_PROGRESS)
|| (mali_device_state == _MALI_DEVICE_SUSPEND)
#ifdef CONFIG_HAS_EARLYSUSPEND
|| (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB))
#else
)
#endif
{
err = -EPERM;
}
if (!err)
{
mali_device_resume(MALI_PMM_EVENT_DVFS_RESUME, &dvfs_pm_thread);
mali_dvfs_device_state = _MALI_DEVICE_RESUME;
}
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
EXPORT_SYMBOL(mali_dev_resume);
#endif /* MALI_LICENSE_IS_GPL */
#endif /* CONFIG_PM */
#endif /* USING_MALI_PMM */

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_DEVICE_PAUSE_RESUME_H__
#define __MALI_DEVICE_PAUSE_RESUME_H__
#if USING_MALI_PMM
int mali_dev_pause(void);
int mali_dev_resume(void);
#endif /* USING_MALI_PMM */
#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_KERNEL_IOCTL_H__
#define __MALI_KERNEL_IOCTL_H__
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/fs.h> /* file system operations */
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @file mali_kernel_ioctl.h
* Interface to the Linux device driver.
* This file describes the interface needed to use the Linux device driver.
* Its interface is designed to used by the HAL implementation through a thin arch layer.
*/
/**
* ioctl commands
*/
#define MALI_IOC_BASE 0x82
#define MALI_IOC_CORE_BASE (_MALI_UK_CORE_SUBSYSTEM + MALI_IOC_BASE)
#define MALI_IOC_MEMORY_BASE (_MALI_UK_MEMORY_SUBSYSTEM + MALI_IOC_BASE)
#define MALI_IOC_PP_BASE (_MALI_UK_PP_SUBSYSTEM + MALI_IOC_BASE)
#define MALI_IOC_GP_BASE (_MALI_UK_GP_SUBSYSTEM + MALI_IOC_BASE)
#define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE)
#define MALI_IOC_VSYNC_BASE (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE)
#define MALI_IOC_GET_SYSTEM_INFO_SIZE _IOR (MALI_IOC_CORE_BASE, _MALI_UK_GET_SYSTEM_INFO_SIZE, _mali_uk_get_system_info_s *)
#define MALI_IOC_GET_SYSTEM_INFO _IOR (MALI_IOC_CORE_BASE, _MALI_UK_GET_SYSTEM_INFO, _mali_uk_get_system_info_s *)
#define MALI_IOC_WAIT_FOR_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_WAIT_FOR_NOTIFICATION, _mali_uk_wait_for_notification_s *)
#define MALI_IOC_GET_API_VERSION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_API_VERSION, _mali_uk_get_api_version_s *)
#define MALI_IOC_POST_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *)
#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, _mali_uk_get_big_block_s *)
#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, _mali_uk_free_big_block_s *)
#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _mali_uk_init_mem_s *)
#define MALI_IOC_MEM_TERM _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_TERM_MEM, _mali_uk_term_mem_s *)
#define MALI_IOC_MEM_MAP_EXT _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MAP_EXT_MEM, _mali_uk_map_external_mem_s *)
#define MALI_IOC_MEM_UNMAP_EXT _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_UNMAP_EXT_MEM, _mali_uk_unmap_external_mem_s *)
#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s *)
#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s *)
#define MALI_IOC_MEM_ATTACH_UMP _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_UMP_MEM, _mali_uk_attach_ump_mem_s *)
#define MALI_IOC_MEM_RELEASE_UMP _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_UMP_MEM, _mali_uk_release_ump_mem_s *)
#define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s *)
#define MALI_IOC_PP_NUMBER_OF_CORES_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_NUMBER_OF_CORES, _mali_uk_get_pp_number_of_cores_s *)
#define MALI_IOC_PP_CORE_VERSION_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_CORE_VERSION, _mali_uk_get_pp_core_version_s * )
#define MALI_IOC_PP_ABORT_JOB _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_ABORT_JOB, _mali_uk_pp_abort_job_s * )
#define MALI_IOC_GP2_START_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_START_JOB, _mali_uk_gp_start_job_s *)
#define MALI_IOC_GP2_ABORT_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_ABORT_JOB, _mali_uk_gp_abort_job_s *)
#define MALI_IOC_GP2_NUMBER_OF_CORES_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_NUMBER_OF_CORES, _mali_uk_get_gp_number_of_cores_s *)
#define MALI_IOC_GP2_CORE_VERSION_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_CORE_VERSION, _mali_uk_get_gp_core_version_s *)
#define MALI_IOC_GP2_SUSPEND_RESPONSE _IOW (MALI_IOC_GP_BASE, _MALI_UK_GP_SUSPEND_RESPONSE,_mali_uk_gp_suspend_response_s *)
#define MALI_IOC_PROFILING_START _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_START, _mali_uk_profiling_start_s *)
#define MALI_IOC_PROFILING_ADD_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_ADD_EVENT, _mali_uk_profiling_add_event_s*)
#define MALI_IOC_PROFILING_STOP _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *)
#define MALI_IOC_PROFILING_GET_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *)
#define MALI_IOC_PROFILING_CLEAR _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *)
#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *)
#ifdef __cplusplus
}
#endif
#endif /* __MALI_KERNEL_IOCTL_H__ */

View File

@@ -0,0 +1,508 @@
/**
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
* Copyright (C) 2011 STMicroelectronics R&D Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_kernel_linux.c
* Implementation of the Linux device driver entrypoints
*/
#include <linux/module.h> /* kernel module definitions */
#include <linux/fs.h> /* file system operations */
#include <linux/cdev.h> /* character device definitions */
#include <linux/mm.h> /* memory manager definitions */
#include <asm/uaccess.h> /* user space access */
#include <linux/device.h>
#include <linux/proc_fs.h>
#include <linux/platform_device.h>
#include <linux/io.h>
/* the mali kernel subsystem types */
#include "mali_kernel_subsystem.h"
/* A memory subsystem always exists, so no need to conditionally include it */
#include "mali_kernel_common.h"
#include "mali_kernel_mem.h"
#include "mali_kernel_session_manager.h"
#include "mali_kernel_core.h"
#include "mali_osk.h"
#include "mali_kernel_linux.h"
#include "mali_ukk.h"
#include "mali_kernel_ioctl.h"
#include "mali_ukk_wrappers.h"
#include "mali_kernel_pm.h"
#include "mali_kernel_sysfs.h"
/* */
#include "mali_kernel_license.h"
/* Module parameter to control log level */
int mali_debug_level = 2;
module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output");
/* By default the module uses any available major, but it's possible to set it at load time to a specific number */
int mali_major = 0;
module_param(mali_major, int, S_IRUGO); /* r--r--r-- */
MODULE_PARM_DESC(mali_major, "Device major number");
int mali_benchmark = 0;
module_param(mali_benchmark, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
MODULE_PARM_DESC(mali_benchmark, "Bypass Mali hardware when non-zero");
extern int mali_hang_check_interval;
module_param(mali_hang_check_interval, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_hang_check_interval, "Interval at which to check for progress after the hw watchdog has been triggered");
extern int mali_max_job_runtime;
module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what");
#if defined(USING_MALI400_L2_CACHE)
extern int mali_l2_max_reads;
module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache");
#endif
static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
/* the mali device */
static struct mali_dev device;
/* uncached remapped memory, for an STBus uncached write barrier */
struct page *stbus_barrier_system_page;
volatile int *stbus_system_memory_barrier;
/*
* probed platform device pointer, note this is not static as we need access
* to it in the resource code.
*/
struct platform_device *mali_platform_device;
static int mali_open(struct inode *inode, struct file *filp);
static int mali_release(struct inode *inode, struct file *filp);
#ifdef HAVE_UNLOCKED_IOCTL
static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
#else
static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
#endif
static int mali_mmap(struct file * filp, struct vm_area_struct * vma);
/* Linux char file operations provided by the Mali module */
struct file_operations mali_fops =
{
.owner = THIS_MODULE,
.open = mali_open,
.release = mali_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = mali_ioctl,
#else
.ioctl = mali_ioctl,
#endif
.mmap = mali_mmap
};
int mali_driver_init(void)
{
int err;
u32 phys;
stbus_barrier_system_page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN, 1 );
if(NULL == stbus_barrier_system_page)
return -ENOMEM;
#if defined(__sh__)
SetPageReserved(stbus_barrier_system_page);
#endif
phys = page_to_phys( stbus_barrier_system_page );
stbus_system_memory_barrier = (int *)ioremap_nocache(phys,sizeof(int));
if(NULL == stbus_system_memory_barrier)
{
__free_pages(stbus_barrier_system_page,1);
return -ENOMEM;
}
*stbus_system_memory_barrier = 0;
#if USING_MALI_PMM
#if MALI_LICENSE_IS_GPL
err = _mali_dev_platform_register();
if (err)
{
__free_pages(stbus_barrier_system_page,1);
return err;
}
#endif
#endif
err = mali_kernel_constructor();
if (_MALI_OSK_ERR_OK != err)
{
MALI_PRINT(("Failed to initialize driver (error %d)\n", err));
return -EFAULT;
}
return 0;
}
void mali_driver_exit(void)
{
#if USING_MALI_PMM
malipmm_force_powerup();
#endif
mali_kernel_destructor();
if(NULL != stbus_system_memory_barrier)
iounmap((void*)stbus_system_memory_barrier);
if(NULL != stbus_barrier_system_page)
{
#if defined(__sh__)
ClearPageReserved(stbus_barrier_system_page);
#endif
__free_pages(stbus_barrier_system_page,1);
}
#if USING_MALI_PMM
malipmm_force_powerdown();
#endif
#if USING_MALI_PMM
#if MALI_LICENSE_IS_GPL
_mali_dev_platform_unregister();
#endif
#endif
}
/* called from _mali_osk_init */
int initialize_kernel_device(void)
{
int err;
dev_t dev = 0;
if (0 == mali_major)
{
/* auto select a major */
err = alloc_chrdev_region(&dev, 0/*first minor*/, 1/*count*/, mali_dev_name);
mali_major = MAJOR(dev);
}
else
{
/* use load time defined major number */
dev = MKDEV(mali_major, 0);
err = register_chrdev_region(dev, 1/*count*/, mali_dev_name);
}
if (err)
{
goto init_chrdev_err;
}
memset(&device, 0, sizeof(device));
/* initialize our char dev data */
cdev_init(&device.cdev, &mali_fops);
device.cdev.owner = THIS_MODULE;
device.cdev.ops = &mali_fops;
kobject_set_name(&(device.cdev.kobj), mali_dev_name);
/* register char dev with the kernel */
err = cdev_add(&device.cdev, dev, 1/*count*/);
if (err)
{
goto init_cdev_err;
}
err = mali_sysfs_register(&device, dev, mali_dev_name);
if (err)
{
goto init_sysfs_err;
}
/* Success! */
return 0;
init_sysfs_err:
cdev_del(&device.cdev);
init_cdev_err:
unregister_chrdev_region(dev, 1/*count*/);
init_chrdev_err:
return err;
}
/* called from _mali_osk_term */
void terminate_kernel_device(void)
{
dev_t dev = MKDEV(mali_major, 0);
mali_sysfs_unregister(&device, dev, mali_dev_name);
/* unregister char device */
cdev_del(&device.cdev);
/* free major */
unregister_chrdev_region(dev, 1/*count*/);
return;
}
/** @note munmap handler is done by vma close handler */
static int mali_mmap(struct file * filp, struct vm_area_struct * vma)
{
struct mali_session_data * session_data;
_mali_uk_mem_mmap_s args = {0, };
session_data = (struct mali_session_data *)filp->private_data;
if (NULL == session_data)
{
MALI_PRINT_ERROR(("mmap called without any session data available\n"));
return -EFAULT;
}
MALI_DEBUG_PRINT(3, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X\n", (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT), (unsigned int)(vma->vm_end - vma->vm_start)) );
/* Re-pack the arguments that mmap() packed for us */
args.ctx = session_data;
args.phys_addr = vma->vm_pgoff << PAGE_SHIFT;
args.size = vma->vm_end - vma->vm_start;
args.ukk_private = vma;
/* Call the common mmap handler */
MALI_CHECK(_MALI_OSK_ERR_OK ==_mali_ukk_mem_mmap( &args ), -EFAULT);
return 0;
}
static int mali_open(struct inode *inode, struct file *filp)
{
struct mali_session_data * session_data;
_mali_osk_errcode_t err;
/* input validation */
if (0 != MINOR(inode->i_rdev)) return -ENODEV;
/* allocated struct to track this session */
err = _mali_ukk_open((void **)&session_data);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
/* initialize file pointer */
filp->f_pos = 0;
/* link in our session data */
filp->private_data = (void*)session_data;
return 0;
}
static int mali_release(struct inode *inode, struct file *filp)
{
_mali_osk_errcode_t err;
/* input validation */
if (0 != MINOR(inode->i_rdev)) return -ENODEV;
err = _mali_ukk_close((void **)&filp->private_data);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
return 0;
}
int map_errcode( _mali_osk_errcode_t err )
{
switch(err)
{
case _MALI_OSK_ERR_OK : return 0;
case _MALI_OSK_ERR_FAULT: return -EFAULT;
case _MALI_OSK_ERR_INVALID_FUNC: return -ENOTTY;
case _MALI_OSK_ERR_INVALID_ARGS: return -EINVAL;
case _MALI_OSK_ERR_NOMEM: return -ENOMEM;
case _MALI_OSK_ERR_TIMEOUT: return -ETIMEDOUT;
case _MALI_OSK_ERR_RESTARTSYSCALL: return -ERESTARTSYS;
case _MALI_OSK_ERR_ITEM_NOT_FOUND: return -ENOENT;
default: return -EFAULT;
}
}
#ifdef HAVE_UNLOCKED_IOCTL
static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
#else
static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
#endif
{
int err;
struct mali_session_data *session_data;
#ifndef HAVE_UNLOCKED_IOCTL
/* inode not used */
(void)inode;
#endif
MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg));
session_data = (struct mali_session_data *)filp->private_data;
if (NULL == session_data)
{
MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n"));
return -ENOTTY;
}
if (NULL == (void *)arg)
{
MALI_DEBUG_PRINT(7, ("arg was NULL\n"));
return -ENOTTY;
}
switch(cmd)
{
case MALI_IOC_GET_SYSTEM_INFO_SIZE:
err = get_system_info_size_wrapper(session_data, (_mali_uk_get_system_info_size_s __user *)arg);
break;
case MALI_IOC_GET_SYSTEM_INFO:
err = get_system_info_wrapper(session_data, (_mali_uk_get_system_info_s __user *)arg);
break;
case MALI_IOC_WAIT_FOR_NOTIFICATION:
err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg);
break;
case MALI_IOC_GET_API_VERSION:
err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg);
break;
case MALI_IOC_POST_NOTIFICATION:
err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg);
break;
#if MALI_TIMELINE_PROFILING_ENABLED
case MALI_IOC_PROFILING_START:
err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg);
break;
case MALI_IOC_PROFILING_ADD_EVENT:
err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg);
break;
case MALI_IOC_PROFILING_STOP:
err = profiling_stop_wrapper(session_data, (_mali_uk_profiling_stop_s __user *)arg);
break;
case MALI_IOC_PROFILING_GET_EVENT:
err = profiling_get_event_wrapper(session_data, (_mali_uk_profiling_get_event_s __user *)arg);
break;
case MALI_IOC_PROFILING_CLEAR:
err = profiling_clear_wrapper(session_data, (_mali_uk_profiling_clear_s __user *)arg);
break;
#endif
case MALI_IOC_MEM_INIT:
err = mem_init_wrapper(session_data, (_mali_uk_init_mem_s __user *)arg);
break;
case MALI_IOC_MEM_TERM:
err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg);
break;
case MALI_IOC_MEM_MAP_EXT:
err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg);
break;
case MALI_IOC_MEM_UNMAP_EXT:
err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg);
break;
case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE:
err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg);
break;
case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE:
err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg);
break;
case MALI_IOC_MEM_GET_BIG_BLOCK:
err = mem_get_big_block_wrapper(filp, (_mali_uk_get_big_block_s __user *)arg);
break;
case MALI_IOC_MEM_FREE_BIG_BLOCK:
err = mem_free_big_block_wrapper(session_data, (_mali_uk_free_big_block_s __user *)arg);
break;
#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
case MALI_IOC_MEM_ATTACH_UMP:
err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg);
break;
case MALI_IOC_MEM_RELEASE_UMP:
err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg);
break;
#else
case MALI_IOC_MEM_ATTACH_UMP:
case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */
MALI_DEBUG_PRINT(2, ("UMP not supported\n"));
err = -ENOTTY;
break;
#endif
case MALI_IOC_PP_START_JOB:
err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg);
break;
case MALI_IOC_PP_ABORT_JOB:
err = pp_abort_job_wrapper(session_data, (_mali_uk_pp_abort_job_s __user *)arg);
break;
case MALI_IOC_PP_NUMBER_OF_CORES_GET:
err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg);
break;
case MALI_IOC_PP_CORE_VERSION_GET:
err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg);
break;
case MALI_IOC_GP2_START_JOB:
err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
break;
case MALI_IOC_GP2_ABORT_JOB:
err = gp_abort_job_wrapper(session_data, (_mali_uk_gp_abort_job_s __user *)arg);
break;
case MALI_IOC_GP2_NUMBER_OF_CORES_GET:
err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg);
break;
case MALI_IOC_GP2_CORE_VERSION_GET:
err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg);
break;
case MALI_IOC_GP2_SUSPEND_RESPONSE:
err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg);
break;
case MALI_IOC_VSYNC_EVENT_REPORT:
err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
break;
default:
MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg));
err = -ENOTTY;
};
return err;
}
module_init(mali_driver_init);
module_exit(mali_driver_exit);
MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
MODULE_AUTHOR("ARM Ltd.");
MODULE_VERSION(SVN_REV_STRING);

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_KERNEL_LINUX_H__
#define __MALI_KERNEL_LINUX_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <linux/cdev.h> /* character device definitions */
#include "mali_kernel_license.h"
struct mali_dev
{
struct cdev cdev;
#if MALI_LICENSE_IS_GPL
struct class * mali_class;
#endif
};
_mali_osk_errcode_t initialize_kernel_device(void);
void terminate_kernel_device(void);
void mali_osk_low_level_mem_init(void);
void mali_osk_low_level_mem_term(void);
#ifdef __cplusplus
}
#endif
#endif /* __MALI_KERNEL_LINUX_H__ */

View File

@@ -0,0 +1,801 @@
/**
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
* Copyright (C) 2011 STMicroelectronics R&D Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Even if the knl has no PM we need to configure it here so we have access to ARM's
* platform driver code implementation. */
#ifndef CONFIG_PM
#define CONFIG_PM
#endif
/**
* @file mali_kernel_pm.c
* Implementation of the Linux Power Management for Mali GPU kernel driver
*/
#if USING_MALI_PMM
#include <linux/sched.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif /* CONFIG_HAS_EARLYSUSPEND */
#ifdef CONFIG_PM_RUNTIME
#include <linux/pm_runtime.h>
#endif /* CONFIG_PM_RUNTIME */
#include <linux/platform_device.h>
#include <linux/version.h>
#include <asm/current.h>
#include <asm/delay.h>
#include <linux/suspend.h>
#include "mali_platform.h"
#include "mali_osk.h"
#include "mali_uk_types.h"
#include "mali_pmm.h"
#include "mali_ukk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_license.h"
#include "mali_kernel_pm.h"
#include "mali_device_pause_resume.h"
#include "mali_linux_pm.h"
#if MALI_GPU_UTILIZATION
#include "mali_kernel_utilization.h"
#endif /* MALI_GPU_UTILIZATION */
#if MALI_POWER_MGMT_TEST_SUITE
#ifdef CONFIG_PM
#include "mali_linux_pm_testsuite.h"
unsigned int pwr_mgmt_status_reg = 0;
#endif /* CONFIG_PM */
#endif /* MALI_POWER_MGMT_TEST_SUITE */
#if MALI_STATE_TRACKING
int is_os_pmm_thread_waiting = -1;
#endif /* MALI_STATE_TRACKING */
extern struct platform_device *mali_platform_device;
/* kernel should be configured with power management support */
#ifdef CONFIG_PM
/* License should be GPL */
#if MALI_LICENSE_IS_GPL
/* Linux kernel major version */
#define LINUX_KERNEL_MAJOR_VERSION 2
/* Linux kernel minor version */
#define LINUX_KERNEL_MINOR_VERSION 6
/* Linux kernel development version */
#define LINUX_KERNEL_DEVELOPMENT_VERSION 29
#ifdef CONFIG_PM_DEBUG
static const char* const mali_states[_MALI_MAX_DEBUG_OPERATIONS] = {
[_MALI_DEVICE_SUSPEND] = "suspend",
[_MALI_DEVICE_RESUME] = "resume",
#ifdef CONFIG_HAS_EARLYSUSPEND
[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB] = "early_suspend_level_disable_framebuffer",
[_MALI_DEVICE_LATERESUME] = "late_resume",
#endif /* CONFIG_HAS_EARLYSUSPEND */
[_MALI_DVFS_PAUSE_EVENT] = "dvfs_pause",
[_MALI_DVFS_RESUME_EVENT] = "dvfs_resume",
};
#endif /* CONFIG_PM_DEBUG */
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
extern void set_mali_parent_power_domain(struct platform_device* dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifndef CONFIG_HAS_EARLYSUSPEND
static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy);
static struct notifier_block mali_pwr_notif_block = {
.notifier_call = mali_pwr_suspend_notifier
};
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
/* Power management thread pointer */
struct task_struct *pm_thread;
/* dvfs power management thread */
struct task_struct *dvfs_pm_thread;
/* is wake up needed */
short is_wake_up_needed = 0;
int timeout_fired = 2;
unsigned int is_mali_pmm_testsuite_enabled = 0;
_mali_device_power_states mali_device_state = _MALI_DEVICE_RESUME;
_mali_device_power_states mali_dvfs_device_state = _MALI_DEVICE_RESUME;
_mali_osk_lock_t *lock;
#if MALI_POWER_MGMT_TEST_SUITE
const char* const mali_pmm_recording_events[_MALI_DEVICE_MAX_PMM_EVENTS] = {
[_MALI_DEVICE_PMM_TIMEOUT_EVENT] = "timeout",
[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS] = "job_scheduling",
[_MALI_DEVICE_PMM_REGISTERED_CORES] = "cores",
};
unsigned int mali_timeout_event_recording_on = 0;
unsigned int mali_job_scheduling_events_recording_on = 0;
unsigned int is_mali_pmu_present = 0;
#endif /* MALI_POWER_MGMT_TEST_SUITE */
/* Function prototypes */
static int mali_pm_probe(struct platform_device *pdev);
static int mali_pm_remove(struct platform_device *pdev);
/* Mali device suspend function */
static int mali_pm_suspend(struct device *dev);
/* Mali device resume function */
static int mali_pm_resume(struct device *dev);
/* Run time suspend and resume functions */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
static int mali_device_runtime_suspend(struct device *dev);
static int mali_device_runtime_resume(struct device *dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
/* Early suspend functions */
#ifdef CONFIG_HAS_EARLYSUSPEND
static void mali_pm_early_suspend(struct early_suspend *mali_dev);
static void mali_pm_late_resume(struct early_suspend *mali_dev);
#endif /* CONFIG_HAS_EARLYSUSPEND */
/* OS suspend and resume callbacks */
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifndef CONFIG_PM_RUNTIME
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_suspend(struct platform_device *pdev, pm_message_t state);
#else
static int mali_pm_os_suspend(struct device *dev);
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_resume(struct platform_device *pdev);
#else
static int mali_pm_os_resume(struct device *dev);
#endif
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
/* OS Hibernation suspend callback */
static int mali_pm_os_suspend_on_hibernation(struct device *dev);
/* OS Hibernation resume callback */
static int mali_pm_os_resume_on_hibernation(struct device *dev);
static void _mali_release_pm(struct device* device);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static const struct dev_pm_ops mali_dev_pm_ops = {
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
.runtime_suspend = mali_device_runtime_suspend,
.runtime_resume = mali_device_runtime_resume,
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
.suspend = mali_pm_os_suspend,
.resume = mali_pm_os_resume,
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
.freeze = mali_pm_os_suspend_on_hibernation,
.poweroff = mali_pm_os_suspend_on_hibernation,
.thaw = mali_pm_os_resume_on_hibernation,
.restore = mali_pm_os_resume_on_hibernation,
};
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
struct pm_ext_ops mali_pm_operations = {
.base = {
.freeze = mali_pm_os_suspend_on_hibernation,
.thaw = mali_pm_os_resume_on_hibernation,
.poweroff = mali_pm_os_resume_on_hibernation,
.restore = mali_pm_os_resume_on_hibernation,
},
};
#endif
static struct platform_driver mali_plat_driver = {
.probe = mali_pm_probe,
.remove = mali_pm_remove,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
.suspend = mali_pm_os_suspend,
.resume = mali_pm_os_resume,
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
.pm = &mali_pm_operations,
#endif
.driver = {
.name = "mali",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
.pm = &mali_dev_pm_ops,
#endif
},
};
#ifdef CONFIG_HAS_EARLYSUSPEND
/* Early suspend hooks */
static struct early_suspend mali_dev_early_suspend = {
.suspend = mali_pm_early_suspend,
.resume = mali_pm_late_resume,
.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
};
#endif /* CONFIG_HAS_EARLYSUSPEND */
/* Mali GPU platform device */
struct platform_device mali_gpu_device = {
.name = "mali_dev",
.id = 0,
.dev.release = _mali_release_pm
};
/** This function is called when platform device is unregistered. This function
* is necessary when the platform device is unregistered.
*/
static void _mali_release_pm(struct device *device)
{
MALI_DEBUG_PRINT(4, ("OSPMM: MALI Platform device removed\n" ));
}
#if MALI_POWER_MGMT_TEST_SUITE
void mali_is_pmu_present(void)
{
int temp = 0;
temp = pmu_get_power_up_down_info();
if (4095 == temp)
{
is_mali_pmu_present = 0;
}
else
{
is_mali_pmu_present = 1;
}
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
#endif /* MALI_LICENSE_IS_GPL */
#if MALI_LICENSE_IS_GPL
static int mali_wait_for_power_management_policy_event(void)
{
int err = 0;
for (; ;)
{
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
{
err = -EINTR;
break;
}
if (is_wake_up_needed == 1)
{
break;
}
schedule();
}
__set_current_state(TASK_RUNNING);
is_wake_up_needed =0;
return err;
}
/** This function is invoked when mali device is suspended
*/
int mali_device_suspend(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
{
int err = 0;
_mali_uk_pmm_message_s event = {
NULL,
event_id,
timeout_fired};
*pwr_mgmt_thread = current;
MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being suspended\n" ));
_mali_ukk_pmm_event_message(&event);
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 1;
#endif /* MALI_STATE_TRACKING */
err = mali_wait_for_power_management_policy_event();
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 0;
#endif /* MALI_STATE_TRACKING */
return err;
}
/** This function is called when Operating system wants to power down
* the mali GPU device.
*/
static int mali_pm_suspend(struct device *dev)
{
int err = 0;
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
#if MALI_GPU_UTILIZATION
mali_utilization_suspend();
#endif /* MALI_GPU_UTILIZATION */
if ((mali_device_state == _MALI_DEVICE_SUSPEND)
#ifdef CONFIG_HAS_EARLYSUSPEND
|| mali_device_state == (_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB))
#else
)
#endif /* CONFIG_HAS_EARLYSUSPEND */
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
mali_device_state = _MALI_DEVICE_SUSPEND_IN_PROGRESS;
err = mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread);
mali_device_state = _MALI_DEVICE_SUSPEND;
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_suspend(struct platform_device *pdev, pm_message_t state)
#else
static int mali_pm_os_suspend(struct device *dev)
#endif
{
int err = 0;
err = mali_pm_suspend(NULL);
return err;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifndef CONFIG_HAS_EARLYSUSPEND
static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy)
{
int err = 0;
switch (event)
{
case PM_SUSPEND_PREPARE:
err = mali_pm_suspend(NULL);
break;
case PM_POST_SUSPEND:
err = mali_pm_resume(NULL);
break;
default:
break;
}
return 0;
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
/** This function is called when mali GPU device is to be resumed.
*/
int mali_device_resume(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
{
int err = 0;
_mali_uk_pmm_message_s event = {
NULL,
event_id,
timeout_fired};
*pwr_mgmt_thread = current;
MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being resumed\n" ));
_mali_ukk_pmm_event_message(&event);
MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power up event is scheduled\n" ));
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 1;
#endif /* MALI_STATE_TRACKING */
err = mali_wait_for_power_management_policy_event();
#if MALI_STATE_TRACKING
is_os_pmm_thread_waiting = 0;
#endif /* MALI_STATE_TRACKING */
return err;
}
/** This function is called when mali GPU device is to be resumed
*/
static int mali_pm_resume(struct device *dev)
{
int err = 0;
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
if (mali_device_state == _MALI_DEVICE_RESUME)
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
err = mali_device_resume(MALI_PMM_EVENT_OS_POWER_UP, &pm_thread);
mali_device_state = _MALI_DEVICE_RESUME;
mali_dvfs_device_state = _MALI_DEVICE_RESUME;
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return err;
}
#ifndef CONFIG_PM_RUNTIME
#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
static int mali_pm_os_resume(struct platform_device *pdev)
#else
static int mali_pm_os_resume(struct device *dev)
#endif
{
int err = 0;
err = mali_pm_resume(NULL);
return err;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
static int mali_pm_os_suspend_on_hibernation(struct device *dev)
{
int err = 0;
err = mali_pm_suspend(NULL);
return err;
}
static int mali_pm_os_resume_on_hibernation(struct device *dev)
{
int err = 0;
err = mali_pm_resume(NULL);
return err;
}
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
/** This function is called when runtime suspend of mali device is required.
*/
static int mali_device_runtime_suspend(struct device *dev)
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time suspended \n" ));
return 0;
}
/** This function is called when runtime resume of mali device is required.
*/
static int mali_device_runtime_resume(struct device *dev)
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time Resumed \n" ));
return 0;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_HAS_EARLYSUSPEND
/* This function is called from android framework.
*/
static void mali_pm_early_suspend(struct early_suspend *mali_dev)
{
switch(mali_dev->level)
{
/* Screen should be turned off but framebuffer will be accessible */
case EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Screen is off\n" ));
break;
case EARLY_SUSPEND_LEVEL_STOP_DRAWING:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Suspend level stop drawing\n" ));
break;
/* Turn off the framebuffer. In our case No Mali GPU operation */
case EARLY_SUSPEND_LEVEL_DISABLE_FB:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Suspend level Disable framebuffer\n" ));
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
#if MALI_GPU_UTILIZATION
mali_utilization_suspend();
#endif /* MALI_GPU_UTILIZATION */
if ((mali_device_state == _MALI_DEVICE_SUSPEND) || (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB))
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return;
}
mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread);
mali_device_state = _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB;
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
break;
default:
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Invalid Suspend Mode\n" ));
break;
}
}
/* This function is invoked from android framework when mali device needs to be
* resumed.
*/
static void mali_pm_late_resume(struct early_suspend *mali_dev)
{
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
if (mali_device_state == _MALI_DEVICE_RESUME)
{
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
return;
}
if (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB)
{
mali_device_resume(MALI_PMM_EVENT_OS_POWER_UP, &pm_thread);
mali_dvfs_device_state = _MALI_DEVICE_RESUME;
mali_device_state = _MALI_DEVICE_RESUME;
}
_mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
#ifdef CONFIG_PM_DEBUG
/** This function is used for debugging purposes when the user want to see
* which power management operations are supported for
* mali device.
*/
static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
{
char *str = buf;
#if !MALI_POWER_MGMT_TEST_SUITE
int pm_counter = 0;
for (pm_counter = 0; pm_counter<_MALI_MAX_DEBUG_OPERATIONS; pm_counter++)
{
str += sprintf(str, "%s ", mali_states[pm_counter]);
}
#else
str += sprintf(str, "%d ",pwr_mgmt_status_reg);
#endif
if (str != buf)
{
*(str-1) = '\n';
}
return (str-buf);
}
/** This function is called when user wants to suspend the mali GPU device in order
* to simulate the power up and power down events.
*/
static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int err = 0;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend mali_dev;
#endif /* CONFIG_HAS_EARLYSUSPEND */
#if MALI_POWER_MGMT_TEST_SUITE
int test_flag_dvfs = 0;
pwr_mgmt_status_reg = 0;
mali_is_pmu_present();
#endif
if (!strncmp(buf,mali_states[_MALI_DEVICE_SUSPEND],strlen(mali_states[_MALI_DEVICE_SUSPEND])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI suspend Power operation is scheduled\n" ));
err = mali_pm_suspend(NULL);
}
#if MALI_POWER_MGMT_TEST_SUITE
else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_REGISTERED_CORES],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_REGISTERED_CORES])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Device get number of registerd cores\n" ));
pwr_mgmt_status_reg = _mali_pmm_cores_list();
return count;
}
else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_TIMEOUT_EVENT],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_TIMEOUT_EVENT])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI timeout event recording is enabled\n" ));
mali_timeout_event_recording_on = 1;
}
else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Job scheduling events recording is enabled\n" ));
mali_job_scheduling_events_recording_on = 1;
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
else if (!strncmp(buf,mali_states[_MALI_DEVICE_RESUME],strlen(mali_states[_MALI_DEVICE_RESUME])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" ));
err = mali_pm_resume(NULL);
}
#ifdef CONFIG_HAS_EARLYSUSPEND
else if (!strncmp(buf,mali_states[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB],strlen(mali_states[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB])))
{
mali_dev.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Android early suspend operation is scheduled\n" ));
mali_pm_early_suspend(&mali_dev);
}
else if (!strncmp(buf,mali_states[_MALI_DEVICE_LATERESUME],strlen(mali_states[_MALI_DEVICE_LATERESUME])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" ));
mali_pm_late_resume(NULL);
}
#endif /* CONFIG_HAS_EARLYSUSPEND */
else if (!strncmp(buf,mali_states[_MALI_DVFS_PAUSE_EVENT],strlen(mali_states[_MALI_DVFS_PAUSE_EVENT])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Pause Power operation is scheduled\n" ));
err = mali_dev_pause();
#if MALI_POWER_MGMT_TEST_SUITE
test_flag_dvfs = 1;
#endif /* MALI_POWER_MGMT_TEST_SUITE */
}
else if (!strncmp(buf,mali_states[_MALI_DVFS_RESUME_EVENT],strlen(mali_states[_MALI_DVFS_RESUME_EVENT])))
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Resume Power operation is scheduled\n" ));
err = mali_dev_resume();
#if MALI_POWER_MGMT_TEST_SUITE
test_flag_dvfs = 1;
#endif /* MALI_POWER_MGMT_TEST_SUITE */
}
else
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Invalid Power Mode Operation selected\n" ));
}
#if MALI_POWER_MGMT_TEST_SUITE
if (test_flag_dvfs == 1)
{
if (err)
{
pwr_mgmt_status_reg = 2;
}
else
{
pwr_mgmt_status_reg = 1;
}
}
else
{
if (1 == is_mali_pmu_present)
{
pwr_mgmt_status_reg = pmu_get_power_up_down_info();
}
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
return count;
}
/* Device attribute file */
static DEVICE_ATTR(file, 0644, show_file, store_file);
#endif /* CONFIG_PM_DEBUG */
static int mali_pm_remove(struct platform_device *pdev)
{
#ifdef CONFIG_PM_DEBUG
device_remove_file(&mali_gpu_device.dev, &dev_attr_file);
#endif /* CONFIG_PM_DEBUG */
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
pm_runtime_disable(&pdev->dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
return 0;
}
/** This function is called when the device is probed */
static int mali_pm_probe(struct platform_device *pdev)
{
MALI_DEBUG_PRINT(2, ("Mali Platform device probe id = %d num_resources = %d resource = %p.\n",pdev->id,pdev->num_resources,pdev->resource));
/*
* As OS init has already created the platform device we record it in the global
*/
mali_platform_device = pdev;
#ifdef CONFIG_PM_DEBUG
int err;
err = device_create_file(&mali_gpu_device.dev, &dev_attr_file);
if (err)
{
MALI_DEBUG_PRINT(4, ("PMMDEBUG: Error in creating device file\n" ));
}
#endif /* CONFIG_PM_DEBUG */
return 0;
}
/** This function is called when Mali GPU device is initialized
*/
int _mali_dev_platform_register(void)
{
int err;
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
set_mali_parent_power_domain(&mali_gpu_device);
#endif
#ifdef CONFIG_PM_RUNTIME
#ifndef CONFIG_HAS_EARLYSUSPEND
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
err = register_pm_notifier(&mali_pwr_notif_block);
if (err)
{
return err;
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* CONFIG_PM_RUNTIME */
/* The platform device is actually registered by the OS startup code so we don't
* need to do it here. All we do is register the platform driver
*/
MALI_DEBUG_PRINT(3, ("[%s] Not registering platform device\n", __FUNCTION__));
lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)( _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 0);
err = platform_driver_register(&mali_plat_driver);
if (!err)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
register_early_suspend(&mali_dev_early_suspend);
#endif /* CONFIG_HAS_EARLYSUSPEND */
}
else
{
_mali_osk_lock_term(lock);
#ifdef CONFIG_PM_RUNTIME
#ifndef CONFIG_HAS_EARLYSUSPEND
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
unregister_pm_notifier(&mali_pwr_notif_block);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* CONFIG_PM_RUNTIME */
}
return err;
}
/** This function is called when Mali GPU device is unloaded
*/
void _mali_dev_platform_unregister(void)
{
_mali_osk_lock_term(lock);
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&mali_dev_early_suspend);
#endif /* CONFIG_HAS_EARLYSUSPEND */
#ifdef CONFIG_PM_RUNTIME
#ifndef CONFIG_HAS_EARLYSUSPEND
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
unregister_pm_notifier(&mali_pwr_notif_block);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_HAS_EARLYSUSPEND */
#endif /* CONFIG_PM_RUNTIME */
platform_driver_unregister(&mali_plat_driver);
/* We dont unregister the platform_device as it was registered by the OS not us */
}
#endif /* MALI_LICENSE_IS_GPL */
#endif /* CONFIG_PM */
#if MALI_STATE_TRACKING
u32 mali_pmm_dump_os_thread_state( char *buf, u32 size )
{
return snprintf(buf, size, "OSPMM: OS PMM thread is waiting: %s\n", is_os_pmm_thread_waiting ? "true" : "false");
}
#endif /* MALI_STATE_TRACKING */
#endif /* USING_MALI_PMM */

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_KERNEL_PM_H__
#define __MALI_KERNEL_PM_H__
#ifdef USING_MALI_PMM
int _mali_dev_platform_register(void);
void _mali_dev_platform_unregister(void);
#endif /* USING_MALI_PMM */
#endif /* __MALI_KERNEL_PM_H__ */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_LINUX_PM_H__
#define __MALI_LINUX_PM_H__
#if USING_MALI_PMM
#ifdef CONFIG_PM
/* Number of power states supported for making power up and down */
typedef enum
{
_MALI_DEVICE_SUSPEND, /* Suspend */
_MALI_DEVICE_RESUME, /* Resume */
#ifdef CONFIG_HAS_EARLYSUSPEND
_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB, /* Early suspend */
_MALI_DEVICE_LATERESUME, /* Late resume */
#endif /* CONFIG_HAS_EARLYSUSPEND */
_MALI_DEVICE_SUSPEND_IN_PROGRESS, /* Suspend in progress */
_MALI_DEVICE_MAX_POWER_STATES, /* Maximum power states */
} _mali_device_power_states;
/* Number of DVFS events */
typedef enum
{
_MALI_DVFS_PAUSE_EVENT = _MALI_DEVICE_MAX_POWER_STATES-1, /* DVFS Pause event */
_MALI_DVFS_RESUME_EVENT, /* DVFS Resume event */
_MALI_MAX_DEBUG_OPERATIONS,
} _mali_device_dvfs_events;
extern _mali_device_power_states mali_device_state;
extern _mali_device_power_states mali_dvfs_device_state;
extern _mali_osk_lock_t *lock;
extern short is_wake_up_needed;
extern int timeout_fired;
extern struct platform_device mali_gpu_device;
/* dvfs pm thread */
extern struct task_struct *dvfs_pm_thread;
/* Power management thread */
extern struct task_struct *pm_thread;
int mali_device_suspend(u32 event_id, struct task_struct **pwr_mgmt_thread);
int mali_device_resume(u32 event_id, struct task_struct **pwr_mgmt_thread);
#endif /* CONFIG_PM */
#endif /* USING_MALI_PMM */
#endif /* __MALI_LINUX_PM_H___ */

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_LINUX_PM_TESTSUITE_H__
#define __MALI_LINUX_PM_TESTSUITE_H__
#if USING_MALI_PMM
#if MALI_POWER_MGMT_TEST_SUITE
#ifdef CONFIG_PM
typedef enum
{
_MALI_DEVICE_PMM_TIMEOUT_EVENT,
_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS,
_MALI_DEVICE_PMM_REGISTERED_CORES,
_MALI_DEVICE_MAX_PMM_EVENTS
} _mali_device_pmm_recording_events;
extern unsigned int mali_timeout_event_recording_on;
extern unsigned int mali_job_scheduling_events_recording_on;
extern unsigned int pwr_mgmt_status_reg;
extern unsigned int is_mali_pmm_testsuite_enabled;
extern unsigned int is_mali_pmu_present;
#endif /* CONFIG_PM */
#endif /* MALI_POWER_MGMT_TEST_SUITE */
#endif /* USING_MALI_PMM */
#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_atomics.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include "mali_osk.h"
#include <asm/atomic.h>
#include "mali_kernel_common.h"
void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom )
{
atomic_dec((atomic_t *)&atom->u.val);
}
u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom )
{
return atomic_dec_return((atomic_t *)&atom->u.val);
}
void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom )
{
atomic_inc((atomic_t *)&atom->u.val);
}
u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom )
{
return atomic_inc_return((atomic_t *)&atom->u.val);
}
_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val )
{
MALI_CHECK_NON_NULL(atom, _MALI_OSK_ERR_INVALID_ARGS);
atomic_set((atomic_t *)&atom->u.val, val);
return _MALI_OSK_ERR_OK;
}
u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom )
{
return atomic_read((atomic_t *)&atom->u.val);
}
void _mali_osk_atomic_term( _mali_osk_atomic_t *atom )
{
MALI_IGNORE(atom);
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/sched.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/atomic.h>
#include "mali_osk.h"
#include "mali_ukk.h"
#include "mali_kernel_common.h"
/**
* @file mali_osk_specific.c
* Implementation of per-OS Kernel level specifics
*/
_mali_osk_errcode_t _mali_osk_specific_indirect_mmap( _mali_uk_mem_mmap_s *args )
{
/* args->ctx ignored here; args->ukk_private required instead */
/* we need to lock the mmap semaphore before calling the do_mmap function */
down_write(&current->mm->mmap_sem);
args->mapping = (void __user *)do_mmap(
(struct file *)args->ukk_private,
0, /* start mapping from any address after NULL */
args->size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
args->phys_addr
);
/* and unlock it after the call */
up_write(&current->mm->mmap_sem);
/* No cookie required here */
args->cookie = 0;
/* uku_private meaningless, so zero */
args->uku_private = NULL;
if ( (NULL == args->mapping) || IS_ERR((void *)args->mapping) )
{
return _MALI_OSK_ERR_FAULT;
}
/* Success */
return _MALI_OSK_ERR_OK;
}
_mali_osk_errcode_t _mali_osk_specific_indirect_munmap( _mali_uk_mem_munmap_s *args )
{
/* args->ctx and args->cookie ignored here */
if ((NULL != current) && (NULL != current->mm))
{
/* remove mapping of mali memory from the process' view */
/* lock mmap semaphore before call */
/* lock mmap_sem before calling do_munmap */
down_write(&current->mm->mmap_sem);
do_munmap(
current->mm,
(unsigned long)args->mapping,
args->size
);
/* and unlock after call */
up_write(&current->mm->mmap_sem);
MALI_DEBUG_PRINT(5, ("unmapped\n"));
}
else
{
MALI_DEBUG_PRINT(2, ("Freeing of a big block while no user process attached, assuming crash cleanup in progress\n"));
}
return _MALI_OSK_ERR_OK; /* always succeeds */
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_specific.h
* Defines per-OS Kernel level specifics, such as unusual workarounds for
* certain OSs.
*/
#ifndef __MALI_OSK_INDIR_MMAP_H__
#define __MALI_OSK_INDIR_MMAP_H__
#include "mali_uk_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* Linux specific means for calling _mali_ukk_mem_mmap/munmap
*
* The presence of _MALI_OSK_SPECIFIC_INDIRECT_MMAP indicates that
* _mali_osk_specific_indirect_mmap and _mali_osk_specific_indirect_munmap
* should be used instead of _mali_ukk_mem_mmap/_mali_ukk_mem_munmap.
*
* The arguments are the same as _mali_ukk_mem_mmap/_mali_ukk_mem_munmap.
*
* In ALL operating system other than Linux, it is expected that common code
* should be able to call _mali_ukk_mem_mmap/_mali_ukk_mem_munmap directly.
* Such systems should NOT define _MALI_OSK_SPECIFIC_INDIRECT_MMAP.
*/
_mali_osk_errcode_t _mali_osk_specific_indirect_mmap( _mali_uk_mem_mmap_s *args );
_mali_osk_errcode_t _mali_osk_specific_indirect_munmap( _mali_uk_mem_munmap_s *args );
#ifdef __cplusplus
}
#endif
#endif /* __MALI_OSK_INDIR_MMAP_H__ */

View File

@@ -0,0 +1,239 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_irq.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include <linux/slab.h> /* For memory allocation */
#include <linux/workqueue.h>
#include "mali_osk.h"
#include "mali_kernel_core.h"
#include "mali_kernel_common.h"
#include "mali_kernel_license.h"
#include "linux/interrupt.h"
typedef struct _mali_osk_irq_t_struct
{
u32 irqnum;
void *data;
_mali_osk_irq_uhandler_t uhandler;
_mali_osk_irq_bhandler_t bhandler;
struct work_struct work_queue_irq_handle; /* Workqueue for the bottom half of the IRQ-handling. This job is activated when this core gets an IRQ.*/
} mali_osk_irq_object_t;
#if MALI_LICENSE_IS_GPL
static struct workqueue_struct *pmm_wq=NULL;
#endif
typedef void (*workqueue_func_t)(void *);
typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *);
static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/
#if defined(INIT_DELAYED_WORK)
static void irq_handler_bottom_half ( struct work_struct *work );
#else
static void irq_handler_bottom_half ( void * input );
#endif
/**
* Linux kernel version has marked SA_SHIRQ as deprecated, IRQF_SHARED should be used.
* This is to handle older kernels which haven't done this swap.
*/
#ifndef IRQF_SHARED
#define IRQF_SHARED SA_SHIRQ
#endif /* IRQF_SHARED */
_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description )
{
mali_osk_irq_object_t *irq_object;
irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
if (NULL == irq_object) return NULL;
/* workqueue API changed in 2.6.20, support both versions: */
#if defined(INIT_DELAYED_WORK)
/* New syntax: INIT_WORK( struct work_struct *work, void (*function)(struct work_struct *)) */
INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half);
#else
/* Old syntax: INIT_WORK( struct work_struct *work, void (*function)(void *), void *data) */
INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half, irq_object);
#endif /* defined(INIT_DELAYED_WORK) */
if (-1 == irqnum)
{
/* Probe for IRQ */
if ( (NULL != trigger_func) && (NULL != ack_func) )
{
unsigned long probe_count = 3;
_mali_osk_errcode_t err;
int irq;
MALI_DEBUG_PRINT(2, ("Probing for irq\n"));
do
{
unsigned long mask;
mask = probe_irq_on();
trigger_func(data);
_mali_osk_time_ubusydelay(5);
irq = probe_irq_off(mask);
err = ack_func(data);
}
while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--);
if (irq < 0 || (_MALI_OSK_ERR_OK != err)) irqnum = -1;
else irqnum = irq;
}
else irqnum = -1; /* no probe functions, fault */
if (-1 != irqnum)
{
/* found an irq */
MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum));
}
else
{
MALI_DEBUG_PRINT(2, ("Probe for irq failed\n"));
}
}
irq_object->irqnum = irqnum;
irq_object->uhandler = uhandler;
irq_object->bhandler = bhandler;
irq_object->data = data;
/* Is this a real IRQ handler we need? */
if (!mali_benchmark && irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM)
{
if (-1 == irqnum)
{
MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
kfree(irq_object);
return NULL;
}
if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object))
{
MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
kfree(irq_object);
return NULL;
}
}
#if MALI_LICENSE_IS_GPL
if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum )
{
pmm_wq = create_singlethread_workqueue("mali-pmm-wq");
}
#endif
return irq_object;
}
void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq )
{
mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
#if MALI_LICENSE_IS_GPL
if ( irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
{
queue_work( pmm_wq,&irq_object->work_queue_irq_handle );
}
else
{
#endif
schedule_work(&irq_object->work_queue_irq_handle);
#if MALI_LICENSE_IS_GPL
}
#endif
}
void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq )
{
#if MALI_LICENSE_IS_GPL
mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
{
flush_workqueue(pmm_wq);
}
#endif
}
void _mali_osk_irq_term( _mali_osk_irq_t *irq )
{
mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
#if MALI_LICENSE_IS_GPL
if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
{
flush_workqueue(pmm_wq);
destroy_workqueue(pmm_wq);
}
#endif
if (!mali_benchmark)
{
free_irq(irq_object->irqnum, irq_object);
}
kfree(irq_object);
flush_scheduled_work();
}
/** This function is called directly in interrupt context from the OS just after
* the CPU get the hw-irq from mali, or other devices on the same IRQ-channel.
* It is registered one of these function for each mali core. When an interrupt
* arrives this function will be called equal times as registered mali cores.
* That means that we only check one mali core in one function call, and the
* core we check for each turn is given by the \a dev_id variable.
* If we detect an pending interrupt on the given core, we mask the interrupt
* out by settging the core's IRQ_MASK register to zero.
* Then we schedule the mali_core_irq_handler_bottom_half to run as high priority
* work queue job.
*/
static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , struct pt_regs *regs*/
{
mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id;
if (irq_object->uhandler(irq_object->data) == _MALI_OSK_ERR_OK)
{
return IRQ_HANDLED;
}
return IRQ_NONE;
}
/* Is executed when an interrupt occur on one core */
/* workqueue API changed in 2.6.20, support both versions: */
#if defined(INIT_DELAYED_WORK)
static void irq_handler_bottom_half ( struct work_struct *work )
#else
static void irq_handler_bottom_half ( void * input )
#endif
{
mali_osk_irq_object_t *irq_object;
#if defined(INIT_DELAYED_WORK)
irq_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_irq_object_t, work_queue_irq_handle);
#else
if ( NULL == input )
{
MALI_PRINT_ERROR(("IRQ: Null pointer! Illegal!"));
return; /* Error */
}
irq_object = (mali_osk_irq_object_t *) input;
#endif
irq_object->bhandler(irq_object->data);
}

View File

@@ -0,0 +1,271 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_locks.c
* Implemenation of the OS abstraction layer for the kernel device driver
*/
/* needed to detect kernel version specific code */
#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#else /* pre 2.6.26 the file was in the arch specific location */
#include <asm/semaphore.h>
#endif
#include <linux/slab.h>
#include "mali_osk.h"
#include "mali_kernel_common.h"
/* These are all the locks we implement: */
typedef enum
{
_MALI_OSK_INTERNAL_LOCKTYPE_SPIN, /* Mutex, implicitly non-interruptable, use spin_lock/spin_unlock */
_MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ, /* Mutex, IRQ version of spinlock, use spin_lock_irqsave/spin_unlock_irqrestore */
_MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use up()/down_interruptable() */
_MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use up()/down() */
_MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {up,down}{read,write}() */
/* Linux supports, but we do not support:
* Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off
*/
/* Linux does not support:
* One-locks, of any sort - no optimization for this fact will be made.
*/
} _mali_osk_internal_locktype;
struct _mali_osk_lock_t_struct
{
_mali_osk_internal_locktype type;
unsigned long flags;
union
{
spinlock_t spinlock;
struct semaphore sema;
struct rw_semaphore rw_sema;
} obj;
MALI_DEBUG_CODE(
/** original flags for debug checking */
_mali_osk_lock_flags_t orig_flags;
_mali_osk_lock_mode_t locked_as;
); /* MALI_DEBUG_CODE */
};
_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order )
{
_mali_osk_lock_t *lock = NULL;
/* Validate parameters: */
/* Flags acceptable */
MALI_DEBUG_ASSERT( 0 == ( flags & ~(_MALI_OSK_LOCKFLAG_SPINLOCK
| _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ
| _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE
| _MALI_OSK_LOCKFLAG_READERWRITER
| _MALI_OSK_LOCKFLAG_ORDERED
| _MALI_OSK_LOCKFLAG_ONELOCK )) );
/* Spinlocks are always non-interruptable */
MALI_DEBUG_ASSERT( (((flags & _MALI_OSK_LOCKFLAG_SPINLOCK) || (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ)) && (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE))
|| !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK));
/* Parameter initial SBZ - for future expansion */
MALI_DEBUG_ASSERT( 0 == initial );
lock = kmalloc(sizeof(_mali_osk_lock_t), GFP_KERNEL);
if ( NULL == lock )
{
return lock;
}
/* Determine type of mutex: */
/* defaults to interruptable mutex if no flags are specified */
if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK) )
{
/* Non-interruptable Spinlocks override all others */
lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN;
spin_lock_init( &lock->obj.spinlock );
}
else if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ ) )
{
lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ;
lock->flags = 0;
spin_lock_init( &lock->obj.spinlock );
}
else if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE)
&& (flags & _MALI_OSK_LOCKFLAG_READERWRITER) )
{
lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW;
init_rwsem( &lock->obj.rw_sema );
}
else
{
/* Usual mutex types */
if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) )
{
lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT;
}
else
{
lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX;
}
/* Initially unlocked */
sema_init( &lock->obj.sema, 1 );
}
MALI_DEBUG_CODE(
/* Debug tracking of flags */
lock->orig_flags = flags;
lock->locked_as = _MALI_OSK_LOCKMODE_UNDEF;
); /* MALI_DEBUG_CODE */
return lock;
}
_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode)
{
_mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
/* Parameter validation */
MALI_DEBUG_ASSERT_POINTER( lock );
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
|| _MALI_OSK_LOCKMODE_RO == mode );
/* Only allow RO locks when the initial object was a Reader/Writer lock
* Since information is lost on the internal locktype, we use the original
* information, which is only stored when built for DEBUG */
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
|| (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) );
switch ( lock->type )
{
case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN:
spin_lock(&lock->obj.spinlock);
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ:
spin_lock_irqsave(&lock->obj.spinlock, lock->flags);
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX:
if ( down_interruptible(&lock->obj.sema) )
{
err = _MALI_OSK_ERR_RESTARTSYSCALL;
}
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT:
down(&lock->obj.sema);
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW:
if (mode == _MALI_OSK_LOCKMODE_RO)
{
down_read(&lock->obj.rw_sema);
}
else
{
down_write(&lock->obj.rw_sema);
}
break;
default:
/* Reaching here indicates a programming error, so you will not get here
* on non-DEBUG builds */
MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) );
break;
}
/* DEBUG tracking of previously locked state - occurs after lock obtained */
MALI_DEBUG_CODE(
if ( _MALI_OSK_ERR_OK == err )
{
/* Assert that this is not currently locked */
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_UNDEF == lock->locked_as );
lock->locked_as = mode;
}
); /* MALI_DEBUG_CODE */
return err;
}
void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode )
{
/* Parameter validation */
MALI_DEBUG_ASSERT_POINTER( lock );
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
|| _MALI_OSK_LOCKMODE_RO == mode );
/* Only allow RO locks when the initial object was a Reader/Writer lock
* Since information is lost on the internal locktype, we use the original
* information, which is only stored when built for DEBUG */
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
|| (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) );
/* For DEBUG only, assert that we previously locked this, and in the same way (RW/RO) */
MALI_DEBUG_ASSERT( mode == lock->locked_as );
/* DEBUG tracking of previously locked state - occurs before lock released */
MALI_DEBUG_CODE( lock->locked_as = _MALI_OSK_LOCKMODE_UNDEF );
switch ( lock->type )
{
case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN:
spin_unlock(&lock->obj.spinlock);
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ:
spin_unlock_irqrestore(&lock->obj.spinlock, lock->flags);
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX:
/* FALLTHROUGH */
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT:
up(&lock->obj.sema);
break;
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW:
if (mode == _MALI_OSK_LOCKMODE_RO)
{
up_read(&lock->obj.rw_sema);
}
else
{
up_write(&lock->obj.rw_sema);
}
break;
default:
/* Reaching here indicates a programming error, so you will not get here
* on non-DEBUG builds */
MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) );
break;
}
}
void _mali_osk_lock_term( _mali_osk_lock_t *lock )
{
/* Parameter validation */
MALI_DEBUG_ASSERT_POINTER( lock );
/* For DEBUG only, assert that this is not currently locked */
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_UNDEF == lock->locked_as );
/* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
kfree(lock);
}

View File

@@ -0,0 +1,636 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
* Copyright (C) 2011 STMicroelectronics R&D Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_low_level_mem.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
/* needed to detect kernel version specific code */
#include <linux/version.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
#include "mali_osk.h"
#include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */
#include "mali_kernel_common.h"
#include "mali_kernel_linux.h"
#ifndef CONFIG_PARANOID_MEM_BARRIERS
#define CONFIG_PARANOID_MEM_BARRIERS 1
#endif
static void mali_kernel_memory_vma_open(struct vm_area_struct * vma);
static void mali_kernel_memory_vma_close(struct vm_area_struct * vma);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf);
#else
static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address);
#endif
extern volatile int *stbus_system_memory_barrier;
typedef struct mali_vma_usage_tracker
{
int references;
u32 cookie;
} mali_vma_usage_tracker;
/* Linked list structure to hold details of all OS allocations in a particular
* mapping
*/
struct AllocationList
{
struct AllocationList *next;
u32 offset;
u32 physaddr;
};
typedef struct AllocationList AllocationList;
/* Private structure to store details of a mapping region returned
* from _mali_osk_mem_mapregion_init
*/
struct MappingInfo
{
struct vm_area_struct *vma;
mali_vma_usage_tracker *vma_usage_tracker;
struct AllocationList *list;
};
typedef struct MappingInfo MappingInfo;
static u32 _kernel_page_allocate(void);
static void _kernel_page_release(u32 physical_address);
static AllocationList * _allocation_list_item_get(void);
static void _allocation_list_item_release(AllocationList * item);
/* Variable declarations */
spinlock_t allocation_list_spinlock;
static AllocationList * pre_allocated_memory = (AllocationList*) NULL ;
static int pre_allocated_memory_size_current = 0;
#ifdef MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB
static int pre_allocated_memory_size_max = MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 1024 * 1024;
#else
static int pre_allocated_memory_size_max = 6 * 1024 * 1024; /* 6 MiB */
#endif
static struct vm_operations_struct mali_kernel_vm_ops =
{
.open = mali_kernel_memory_vma_open,
.close = mali_kernel_memory_vma_close,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
.fault = mali_kernel_memory_cpu_page_fault_handler
#else
.nopfn = mali_kernel_memory_cpu_page_fault_handler
#endif
};
void mali_osk_low_level_mem_init(void)
{
spin_lock_init( &allocation_list_spinlock );
pre_allocated_memory = (AllocationList*) NULL ;
}
void mali_osk_low_level_mem_term(void)
{
while ( NULL != pre_allocated_memory )
{
AllocationList *item;
item = pre_allocated_memory;
pre_allocated_memory = item->next;
_kernel_page_release(item->physaddr);
_mali_osk_free( item );
}
pre_allocated_memory_size_current = 0;
}
static u32 _kernel_page_allocate(void)
{
struct page *new_page;
u32 linux_phys_addr;
new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD);
if ( NULL == new_page )
{
return 0;
}
/* Ensure page is flushed from CPU caches. */
linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
#if defined(__sh__)
_mali_osk_mem_barrier();
#endif
return linux_phys_addr;
}
static void _kernel_page_release(u32 physical_address)
{
struct page *unmap_page;
#if 1
dma_unmap_page(NULL, physical_address, PAGE_SIZE, DMA_BIDIRECTIONAL);
#endif
unmap_page = pfn_to_page( physical_address >> PAGE_SHIFT );
MALI_DEBUG_ASSERT_POINTER( unmap_page );
__free_page( unmap_page );
}
static AllocationList * _allocation_list_item_get(void)
{
AllocationList *item = NULL;
unsigned long flags;
spin_lock_irqsave(&allocation_list_spinlock,flags);
if ( pre_allocated_memory )
{
item = pre_allocated_memory;
pre_allocated_memory = pre_allocated_memory->next;
pre_allocated_memory_size_current -= PAGE_SIZE;
spin_unlock_irqrestore(&allocation_list_spinlock,flags);
return item;
}
spin_unlock_irqrestore(&allocation_list_spinlock,flags);
item = _mali_osk_malloc( sizeof(AllocationList) );
if ( NULL == item)
{
return NULL;
}
item->physaddr = _kernel_page_allocate();
if ( 0 == item->physaddr )
{
/* Non-fatal error condition, out of memory. Upper levels will handle this. */
_mali_osk_free( item );
return NULL;
}
return item;
}
static void _allocation_list_item_release(AllocationList * item)
{
unsigned long flags;
spin_lock_irqsave(&allocation_list_spinlock,flags);
if ( pre_allocated_memory_size_current < pre_allocated_memory_size_max)
{
item->next = pre_allocated_memory;
pre_allocated_memory = item;
pre_allocated_memory_size_current += PAGE_SIZE;
spin_unlock_irqrestore(&allocation_list_spinlock,flags);
return;
}
spin_unlock_irqrestore(&allocation_list_spinlock,flags);
_kernel_page_release(item->physaddr);
_mali_osk_free( item );
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf)
#else
static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address)
#endif
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
void __user * address;
address = vmf->virtual_address;
#endif
/*
* We always fail the call since all memory is pre-faulted when assigned to the process.
* Only the Mali cores can use page faults to extend buffers.
*/
MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n"));
MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void*)address));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
return VM_FAULT_SIGBUS;
#else
return NOPFN_SIGBUS;
#endif
}
static void mali_kernel_memory_vma_open(struct vm_area_struct * vma)
{
mali_vma_usage_tracker * vma_usage_tracker;
MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma));
vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data;
vma_usage_tracker->references++;
return;
}
static void mali_kernel_memory_vma_close(struct vm_area_struct * vma)
{
_mali_uk_mem_munmap_s args = {0, };
mali_memory_allocation * descriptor;
mali_vma_usage_tracker * vma_usage_tracker;
MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma));
vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data;
BUG_ON(!vma_usage_tracker);
BUG_ON(0 == vma_usage_tracker->references);
vma_usage_tracker->references--;
if (0 != vma_usage_tracker->references)
{
MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", vma_usage_tracker->references));
return;
}
/** @note args->context unused, initialized to 0.
* Instead, we use the memory_session from the cookie */
descriptor = (mali_memory_allocation *)vma_usage_tracker->cookie;
args.cookie = (u32)descriptor;
args.mapping = descriptor->mapping;
args.size = descriptor->size;
_mali_ukk_mem_munmap( &args );
/* vma_usage_tracker is free()d by _mali_osk_mem_mapregion_term().
* In the case of the memory engine, it is called as the release function that has been registered with the engine*/
}
void _mali_osk_mem_barrier( void )
{
/*
* Note: mb() is a NOP on ST SH4 architectures
*/
mb();
#if defined(__sh__) && (CONFIG_PARANOID_MEM_BARRIERS == 1)
/*
* This is what mb would have done but it is pretty useless on ST SoCs as
* the CPU sync will return as soon as STBus says the write has happened,
* but all writes are posted, so this doesn't mean the write has reached
* its target.
*/
__asm__ __volatile__ ("synco": : :"memory");
#endif
/*
* This ensures that any previous uncached writes, from the CPU to the
* memory interface the Linux kernel is mapped in to, have really reached
* DDR and are available to be read by the GPU. It is actually the read
* here which ensures the ordering, the write is just there to make sure the
* compiler doesn't optimize it out.
*
*/
(*stbus_system_memory_barrier)++;
}
mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description )
{
return (mali_io_address)ioremap_nocache(phys, size);
}
void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address virt )
{
iounmap((void*)virt);
}
mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size )
{
void * virt;
MALI_DEBUG_ASSERT_POINTER( phys );
MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) );
MALI_DEBUG_ASSERT( 0 != size );
/* dma_alloc_* uses a limited region of address space. On most arch/marchs
* 2 to 14 MiB is available. This should be enough for the page tables, which
* currently is the only user of this function. */
virt = dma_alloc_coherent(NULL, size, phys, GFP_KERNEL | GFP_DMA );
MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys));
if ( NULL == virt )
{
MALI_DEBUG_PRINT(1, ("allocioregion: Failed to allocate Pagetable memory, size=0x%.8X\n", size ));
MALI_DEBUG_PRINT(1, ("Solution: When configuring and building linux kernel, set CONSISTENT_DMA_SIZE to be 14 MB.\n"));
return 0;
}
MALI_DEBUG_ASSERT( 0 == (*phys & ~_MALI_OSK_CPU_PAGE_MASK) );
return (mali_io_address)virt;
}
void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt )
{
MALI_DEBUG_ASSERT_POINTER( (void*)virt );
MALI_DEBUG_ASSERT( 0 != size );
MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) );
dma_free_coherent(NULL, size, virt, phys);
}
_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description )
{
return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK);
}
void inline _mali_osk_mem_unreqregion( u32 phys, u32 size )
{
release_mem_region(phys, size);
}
u32 inline _mali_osk_mem_ioread32( volatile mali_io_address addr, u32 offset )
{
return ioread32(((u8*)addr) + offset);
}
void inline _mali_osk_mem_iowrite32( volatile mali_io_address addr, u32 offset, u32 val )
{
iowrite32(val, ((u8*)addr) + offset);
#if (CONFIG_PARANOID_MEM_BARRIERS == 1)
#if defined(__sh__)
__asm__ __volatile__ ("synco": : :"memory");
#endif
/*
* This readback ensures that the previous write must have reached the
* bus target it was intended for. The usual place this can catch you out
* is clearing interrupts, if the write to the clear register doesn't
* complete before the interrupt handler returns, the interrupt controller
* may still see the interrupt as asserted and the linux interrupt
* dispatcher will call the handler again spuriously.
*/
val = ioread32(((u8*)addr) + offset);
#endif
}
void _mali_osk_cache_flushall( void )
{
/** @note Cached memory is not currently supported in this implementation */
}
void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size )
{
/*
* On the SH4 the address we get here is a userspace address, for
* which we have no interface that can be used to flush the L2. So
* instead we flush pages during the map function when they are
* allocated from the kernel. However just for paranoia we put a
* bus barrier here.
*/
_mali_osk_mem_barrier();
}
_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor )
{
struct vm_area_struct *vma;
mali_vma_usage_tracker * vma_usage_tracker;
MappingInfo *mappingInfo;
if (NULL == descriptor) return _MALI_OSK_ERR_FAULT;
MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
vma = (struct vm_area_struct*)descriptor->process_addr_mapping_info;
if (NULL == vma ) return _MALI_OSK_ERR_FAULT;
/* Re-write the process_addr_mapping_info */
mappingInfo = _mali_osk_calloc( 1, sizeof(MappingInfo) );
if ( NULL == mappingInfo ) return _MALI_OSK_ERR_FAULT;
vma_usage_tracker = _mali_osk_calloc( 1, sizeof(mali_vma_usage_tracker) );
if (NULL == vma_usage_tracker)
{
MALI_DEBUG_PRINT(2, ("Failed to allocate memory to track memory usage\n"));
_mali_osk_free( mappingInfo );
return _MALI_OSK_ERR_FAULT;
}
mappingInfo->vma = vma;
mappingInfo->vma_usage_tracker = vma_usage_tracker;
descriptor->process_addr_mapping_info = mappingInfo;
/* Do the va range allocation - in this case, it was done earlier, so we copy in that information */
descriptor->mapping = (void __user*)vma->vm_start;
/* list member is already NULL */
/*
set some bits which indicate that:
The memory is IO memory, meaning that no paging is to be performed and the memory should not be included in crash dumps
The memory is reserved, meaning that it's present and can never be paged out (see also previous entry)
*/
vma->vm_flags |= VM_IO;
vma->vm_flags |= VM_RESERVED;
vma->vm_flags |= VM_DONTCOPY;
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */
vma_usage_tracker->references = 1; /* set initial reference count to be 1 as vma_open won't be called for the first mmap call */
vma_usage_tracker->cookie = (u32)descriptor; /* cookie for munmap */
vma->vm_private_data = vma_usage_tracker;
return _MALI_OSK_ERR_OK;
}
void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor )
{
mali_vma_usage_tracker * vma_usage_tracker;
MappingInfo *mappingInfo;
if (NULL == descriptor) return;
MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
MALI_DEBUG_ASSERT_POINTER( mappingInfo );
/* Linux does the right thing as part of munmap to remove the mapping
* All that remains is that we remove the vma_usage_tracker setup in init() */
/* vma_area_struct in descriptor and in vma_close can be different.
* Dereferencing vma to get tracker can fault, as kernel MIGHT have
* freed the vma_area_struct in the descriptor. Now vma_usage_tracker
* can be obtained from mappingInfo, which will be valid at this point.
*/
vma_usage_tracker = mappingInfo->vma_usage_tracker;
/* ASSERT that there are no allocations on the list. Unmap should've been
* called on all OS allocations. */
MALI_DEBUG_ASSERT( NULL == mappingInfo->list );
/* We only get called if mem_mapregion_init succeeded */
_mali_osk_free(vma_usage_tracker);
_mali_osk_free( mappingInfo );
return;
}
_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size )
{
struct vm_area_struct *vma;
MappingInfo *mappingInfo;
if (NULL == descriptor) return _MALI_OSK_ERR_FAULT;
MALI_DEBUG_ASSERT_POINTER( phys_addr );
MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) );
MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK));
if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS;
if (size > (descriptor->size - offset))
{
MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n",
*phys_addr, size, descriptor->mapping, offset));
return _MALI_OSK_ERR_FAULT;
}
mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
MALI_DEBUG_ASSERT_POINTER( mappingInfo );
vma = mappingInfo->vma;
if (NULL == vma ) return _MALI_OSK_ERR_FAULT;
MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", *phys_addr, (long unsigned int)(descriptor->mapping + offset), size));
if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == *phys_addr )
{
_mali_osk_errcode_t ret;
AllocationList *alloc_item;
u32 linux_phys_frame_num;
alloc_item = _allocation_list_item_get();
linux_phys_frame_num = alloc_item->physaddr >> PAGE_SHIFT;
ret = ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, linux_phys_frame_num, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;
if ( ret != _MALI_OSK_ERR_OK)
{
_allocation_list_item_release(alloc_item);
return ret;
}
/* Put our alloc_item into the list of allocations on success */
alloc_item->next = mappingInfo->list;
alloc_item->offset = offset;
/*alloc_item->physaddr = linux_phys_addr;*/
mappingInfo->list = alloc_item;
/* Write out new physical address on success */
*phys_addr = alloc_item->physaddr;
return ret;
}
/* Otherwise, Use the supplied physical address */
/* ASSERT that supplied phys_addr is page aligned */
MALI_DEBUG_ASSERT( 0 == ((*phys_addr) & ~_MALI_OSK_CPU_PAGE_MASK) );
return ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, *phys_addr >> PAGE_SHIFT, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;
}
void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags )
{
MappingInfo *mappingInfo;
if (NULL == descriptor) return;
MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) );
MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK) );
if (NULL == descriptor->mapping) return;
if (size > (descriptor->size - offset))
{
MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n",
size, descriptor->mapping, offset));
return;
}
mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
MALI_DEBUG_ASSERT_POINTER( mappingInfo );
if ( 0 != (flags & _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR) )
{
/* This physical RAM was allocated in _mali_osk_mem_mapregion_map and
* so needs to be unmapped
*/
while (size)
{
/* First find the allocation in the list of allocations */
AllocationList *alloc = mappingInfo->list;
AllocationList **prev = &(mappingInfo->list);
while (NULL != alloc && alloc->offset != offset)
{
prev = &(alloc->next);
alloc = alloc->next;
}
if (alloc == NULL) {
MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n"));
size -= _MALI_OSK_CPU_PAGE_SIZE;
offset += _MALI_OSK_CPU_PAGE_SIZE;
continue;
}
_kernel_page_release(alloc->physaddr);
/* Remove the allocation from the list */
*prev = alloc->next;
_mali_osk_free( alloc );
/* Move onto the next allocation */
size -= _MALI_OSK_CPU_PAGE_SIZE;
offset += _MALI_OSK_CPU_PAGE_SIZE;
}
}
/* Linux does the right thing as part of munmap to remove the mapping */
return;
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
* Copyright (C) 2011 STMicroelectronics R&D Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_mali.c
* Implementation of the OS abstraction layer which is specific for the Mali kernel device driver
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/stm/platform.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include "mali_kernel_common.h" /* MALI_xxx macros */
#include "mali_osk.h" /* kernel side OS functions */
#include "mali_uk_types.h"
#include "mali_kernel_linux.h" /* exports initialize/terminate_kernel_device() */
extern struct platform_device *mali_platform_device;
/* Help to convert platform device resources into mali resources */
struct mali_resource_properties
{
const char *name;
_mali_osk_resource_type_t type;
u32 has_irq;
u32 mmu_id;
};
struct mali_resource_properties mali_resource_table[] = {
{ "MALI400GP", MALI400GP, 1, 1 },
{ "MALI400PP-0", MALI400PP, 1, 2 },
{ "MALI400PP-1", MALI400PP, 1, 3 },
{ "MALI400PP-2", MALI400PP, 1, 4 },
{ "MALI400PP-3", MALI400PP, 1, 5 },
{ "MMU-1", MMU, 1, 1 },
{ "MMU-2", MMU, 1, 2 },
{ "MMU-3", MMU, 1, 3 },
{ "MMU-4", MMU, 1, 4 },
{ "MMU-5", MMU, 1, 5 },
{ "MALI400L2", MALI400L2, 0, 0 },
{ "OS_MEMORY", OS_MEMORY, 0, 0 },
{ "MEMORY", MEMORY, 0, 0 },
{ "EXTERNAL_MEMORY_RANGE", MEM_VALIDATION, 0, 0 }
};
/* is called from mali_kernel_constructor in common code */
_mali_osk_errcode_t _mali_osk_init( void )
{
if (0 != initialize_kernel_device()) MALI_ERROR(_MALI_OSK_ERR_FAULT);
mali_osk_low_level_mem_init();
MALI_SUCCESS;
}
/* is called from mali_kernel_deconstructor in common code */
void _mali_osk_term( void )
{
mali_osk_low_level_mem_term();
terminate_kernel_device();
}
static struct mali_resource_properties *get_resource_properties(const char *name)
{
int i;
for(i=0;i<ARRAY_SIZE(mali_resource_table);i++)
{
if(!strcmp(mali_resource_table[i].name,name))
return &mali_resource_table[i];
}
MALI_PRINT(("Cannot find resource name %s\n", name));
return NULL;
}
static int mali_get_mem_resources(_mali_osk_resource_t *resources, struct stm_mali_resource *mem_resources, int num_resources, int *index)
{
int n = 0;
while(n < num_resources)
{
struct mali_resource_properties *properties;
struct stm_mali_resource *mem_resource;
_mali_osk_resource_t *mali_resource = &resources[*index];
mem_resource = &mem_resources[n];
if(!(properties = get_resource_properties(mem_resource->name)))
return _MALI_OSK_ERR_FAULT;
mali_resource->type = properties->type;
mali_resource->base = mem_resource->start;
mali_resource->size = mem_resource->end - mem_resource->start + 1;
switch(properties->type)
{
case MEMORY:
case OS_MEMORY:
mali_resource->flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE;
mali_resource->alloc_order = n;
break;
case MEM_VALIDATION:
mali_resource->flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE;
break;
default:
MALI_PRINT(("Resource %s should not be passed as mem_resources\n",mem_resource->name));
return _MALI_OSK_ERR_FAULT;
}
MALI_DEBUG_PRINT(3, ("Constructed resources for %s\n",mem_resource->name));
mali_resource->description = mem_resource->name;
(*index)++;
n++;
}
return _MALI_OSK_ERR_OK;
}
_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources )
{
struct resource *platform_resource;
_mali_osk_resource_t *resources;
int n,resource_count;
struct stm_mali_config *mali_config = (struct stm_mali_config *)
mali_platform_device->dev.platform_data;
resource_count = mali_platform_device->num_resources +
mali_config->num_mem_resources +
mali_config->num_ext_resources;
resources = kzalloc((resource_count * sizeof(_mali_osk_resource_t)),GFP_KERNEL);
if(!resources)
MALI_ERROR(_MALI_OSK_ERR_NOMEM);
resource_count = 0;
n = 0;
while((platform_resource = platform_get_resource(mali_platform_device,IORESOURCE_MEM,n)) != NULL)
{
_mali_osk_resource_t *mali_resource = &resources[resource_count];
struct mali_resource_properties *properties;
if(!(properties = get_resource_properties(platform_resource->name)))
goto error;
mali_resource->type = properties->type;
mali_resource->base = platform_resource->start;
mali_resource->size = 0;
switch(properties->type)
{
case MEMORY:
case OS_MEMORY:
case MEM_VALIDATION:
MALI_PRINT(("Mali Memory resource %s should be passed in platfrom priv data not IORESOURCE_MEM\n",platform_resource->name));
goto error;
default:
break;
}
mali_resource->mmu_id = properties->mmu_id;
if(properties->has_irq)
{
int irq;
MALI_DEBUG_PRINT(3, ("finding IRQ for %s\n",platform_resource->name));
if((irq = platform_get_irq_byname(mali_platform_device,platform_resource->name)) < 0)
{
MALI_PRINT(("Unable to find IRQ resource for %s\n",platform_resource->name));
goto error;
}
MALI_DEBUG_PRINT(3, ("found IRQ %d for %s\n",irq,platform_resource->name));
mali_resource->irq = irq;
}
MALI_DEBUG_PRINT(3, ("Constructed resources for %s\n",platform_resource->name));
mali_resource->description = platform_resource->name;
resource_count++;
n++;
}
/* Memory resources */
/* Memory resources allocated by Linux kernel and Memory managed by
* mali driver memory allocator */
if (mali_config->mem)
mali_get_mem_resources(resources, mali_config->mem,
mali_config->num_mem_resources, &resource_count);
/* External memory regions for mali to directly render */
if (mali_config->ext_mem)
mali_get_mem_resources(resources, mali_config->ext_mem,
mali_config->num_ext_resources, &resource_count);
*num_resources = resource_count;
*arch_config = resources;
return _MALI_OSK_ERR_OK;
error:
kfree(resources);
*arch_config = NULL;
MALI_ERROR(_MALI_OSK_ERR_FAULT);
}
void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources )
{
kfree(*arch_config);
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_math.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include "mali_osk.h"
#include <linux/bitops.h>
u32 inline _mali_osk_clz( u32 input )
{
return 32-fls(input);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_memory.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include "mali_osk.h"
#include <linux/slab.h>
void inline *_mali_osk_calloc( u32 n, u32 size )
{
return kcalloc(n, size, GFP_KERNEL);
}
void inline *_mali_osk_malloc( u32 size )
{
return kmalloc(size, GFP_KERNEL);
}
void inline _mali_osk_free( void *ptr )
{
kfree(ptr);
}
void inline *_mali_osk_memcpy( void *dst, const void *src, u32 len )
{
return memcpy(dst, src, len);
}
void inline *_mali_osk_memset( void *s, u32 c, u32 n )
{
return memset(s, c, n);
}
mali_bool _mali_osk_mem_check_allocated( u32 max_allocated )
{
/* No need to prevent an out-of-memory dialogue appearing on Linux,
* so we always return MALI_TRUE.
*/
return MALI_TRUE;
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_misc.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
#include <linux/sched.h>
#include <linux/module.h>
#include "mali_osk.h"
void _mali_osk_dbgmsg( const char *fmt, ... )
{
va_list args;
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
}
u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... )
{
int res;
va_list args;
va_start(args, fmt);
res = vsnprintf(buf, (size_t)size, fmt, args);
va_end(args);
return res;
}
void _mali_osk_abort(void)
{
/* make a simple fault by dereferencing a NULL pointer */
*(int *)0 = 0;
}
void _mali_osk_break(void)
{
_mali_osk_abort();
}
u32 _mali_osk_get_pid(void)
{
/* Thread group ID is the process ID on Linux */
return (u32)current->tgid;
}
u32 _mali_osk_get_tid(void)
{
/* pid is actually identifying the thread on Linux */
return (u32)current->pid;
}

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_notification.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include "mali_osk.h"
#include "mali_kernel_common.h"
/* needed to detect kernel version specific code */
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#else /* pre 2.6.26 the file was in the arch specific location */
#include <asm/semaphore.h>
#endif
/**
* Declaration of the notification queue object type
* Contains a linked list of notification pending delivery to user space.
* It also contains a wait queue of exclusive waiters blocked in the ioctl
* When a new notification is posted a single thread is resumed.
*/
struct _mali_osk_notification_queue_t_struct
{
struct semaphore mutex; /**< Mutex protecting the list */
wait_queue_head_t receive_queue; /**< Threads waiting for new entries to the queue */
struct list_head head; /**< List of notifications waiting to be picked up */
};
typedef struct _mali_osk_notification_wrapper_t_struct
{
struct list_head list; /**< Internal linked list variable */
_mali_osk_notification_t data; /**< Notification data */
} _mali_osk_notification_wrapper_t;
_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void )
{
_mali_osk_notification_queue_t * result;
result = (_mali_osk_notification_queue_t *)kmalloc(sizeof(_mali_osk_notification_queue_t), GFP_KERNEL);
if (NULL == result) return NULL;
sema_init(&result->mutex, 1);
init_waitqueue_head(&result->receive_queue);
INIT_LIST_HEAD(&result->head);
return result;
}
_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
{
/* OPT Recycling of notification objects */
_mali_osk_notification_wrapper_t *notification;
notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, GFP_KERNEL );
if (NULL == notification)
{
MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n"));
return NULL;
}
/* Init the list */
INIT_LIST_HEAD(&notification->list);
if (0 != size)
{
notification->data.result_buffer = ((u8*)notification) + sizeof(_mali_osk_notification_wrapper_t);
}
else
{
notification->data.result_buffer = NULL;
}
/* set up the non-allocating fields */
notification->data.notification_type = type;
notification->data.result_buffer_size = size;
/* all ok */
return &(notification->data);
}
void _mali_osk_notification_delete( _mali_osk_notification_t *object )
{
_mali_osk_notification_wrapper_t *notification;
MALI_DEBUG_ASSERT_POINTER( object );
notification = container_of( object, _mali_osk_notification_wrapper_t, data );
/* Remove from the list */
list_del(&notification->list);
/* Free the container */
kfree(notification);
}
void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue )
{
MALI_DEBUG_ASSERT_POINTER( queue );
/* not much to do, just free the memory */
kfree(queue);
}
void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object )
{
_mali_osk_notification_wrapper_t *notification;
MALI_DEBUG_ASSERT_POINTER( queue );
MALI_DEBUG_ASSERT_POINTER( object );
notification = container_of( object, _mali_osk_notification_wrapper_t, data );
/* lock queue access */
down(&queue->mutex);
/* add to list */
list_add_tail(&notification->list, &queue->head);
/* unlock the queue */
up(&queue->mutex);
/* and wake up one possible exclusive waiter */
wake_up(&queue->receive_queue);
}
static int _mali_notification_queue_is_empty( _mali_osk_notification_queue_t *queue )
{
int ret;
down(&queue->mutex);
ret = list_empty(&queue->head);
up(&queue->mutex);
return ret;
}
#if MALI_STATE_TRACKING
mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue )
{
return _mali_notification_queue_is_empty(queue) ? MALI_TRUE : MALI_FALSE;
}
#endif
_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result )
{
_mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND;
_mali_osk_notification_wrapper_t *wrapper_object;
down(&queue->mutex);
if (!list_empty(&queue->head))
{
wrapper_object = list_entry(queue->head.next, _mali_osk_notification_wrapper_t, list);
*result = &(wrapper_object->data);
list_del_init(&wrapper_object->list);
ret = _MALI_OSK_ERR_OK;
}
up(&queue->mutex);
return ret;
}
_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result )
{
/* check input */
MALI_DEBUG_ASSERT_POINTER( queue );
MALI_DEBUG_ASSERT_POINTER( result );
/* default result */
*result = NULL;
while (_MALI_OSK_ERR_OK != _mali_osk_notification_queue_dequeue(queue, result))
{
if (wait_event_interruptible(queue->receive_queue, !_mali_notification_queue_is_empty(queue)))
{
return _MALI_OSK_ERR_RESTARTSYSCALL;
}
}
return _MALI_OSK_ERR_OK; /* all ok */
}

View File

@@ -0,0 +1,195 @@
/**
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_pm.c
* Implementation of the callback functions from common power management
*/
#include <linux/sched.h>
#ifdef CONFIG_PM_RUNTIME
#include <linux/pm_runtime.h>
#endif /* CONFIG_PM_RUNTIME */
#include <linux/platform_device.h>
#include "mali_platform.h"
#include "mali_osk.h"
#include "mali_uk_types.h"
#include "mali_pmm.h"
#include "mali_ukk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_license.h"
#include "mali_kernel_pm.h"
#include "mali_device_pause_resume.h"
#include "mali_linux_pm.h"
#include "mali_linux_pm_testsuite.h"
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
#ifdef CONFIG_PM_RUNTIME
static int is_runtime =0;
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#if MALI_POWER_MGMT_TEST_SUITE
#ifdef CONFIG_PM
unsigned int mali_pmm_events_triggered_mask = 0;
#endif /* CONFIG_PM */
void _mali_osk_pmm_policy_events_notifications(mali_pmm_event_id mali_pmm_event)
{
#if MALI_LICENSE_IS_GPL
#ifdef CONFIG_PM
switch (mali_pmm_event)
{
case MALI_PMM_EVENT_JOB_QUEUED:
if (mali_job_scheduling_events_recording_on == 1)
{
mali_pmm_events_triggered_mask |= (1<<0);
}
break;
case MALI_PMM_EVENT_JOB_SCHEDULED:
if (mali_job_scheduling_events_recording_on == 1)
{
mali_pmm_events_triggered_mask |= (1<<1);
}
break;
case MALI_PMM_EVENT_JOB_FINISHED:
if (mali_job_scheduling_events_recording_on == 1)
{
mali_pmm_events_triggered_mask |= (1<<2);
mali_job_scheduling_events_recording_on = 0;
pwr_mgmt_status_reg = mali_pmm_events_triggered_mask;
}
break;
case MALI_PMM_EVENT_TIMEOUT:
if (mali_timeout_event_recording_on == 1)
{
pwr_mgmt_status_reg = (1<<3);
mali_timeout_event_recording_on = 0;
}
break;
default:
break;
}
#endif /* CONFIG_PM */
#endif /* MALI_LICENSE_IS_GPL */
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
/** This function is called when the Mali device has completed power up
* operation.
*/
void _mali_osk_pmm_power_up_done(mali_pmm_message_data data)
{
#if MALI_LICENSE_IS_GPL
#ifdef CONFIG_PM
is_wake_up_needed = 1;
wake_up_process(pm_thread);
MALI_DEBUG_PRINT(4, ("OSPMM: MALI OSK Power up Done\n" ));
return;
#endif /* CONFIG_PM */
#endif /* MALI_LICENSE_IS_GPL */
}
/** This function is called when the Mali device has completed power down
* operation.
*/
void _mali_osk_pmm_power_down_done(mali_pmm_message_data data)
{
#if MALI_LICENSE_IS_GPL
#ifdef CONFIG_PM
is_wake_up_needed = 1;
#if MALI_POWER_MGMT_TEST_SUITE
if (is_mali_pmu_present == 0)
{
pwr_mgmt_status_reg = _mali_pmm_cores_list();
}
#endif /* MALI_POWER_MGMT_TEST_SUITE */
wake_up_process(pm_thread);
MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power down Done\n" ));
return;
#endif /* CONFIG_PM */
#endif /* MALI_LICENSE_IS_GPL */
}
/** This function is invoked when mali device is idle.
*/
_mali_osk_errcode_t _mali_osk_pmm_dev_idle(void)
{
_mali_osk_errcode_t err = 0;
#if MALI_LICENSE_IS_GPL
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
err = pm_runtime_put_sync(&(mali_gpu_device.dev));
if(err)
{
MALI_DEBUG_PRINT(4, ("OSPMM: Error in _mali_osk_pmm_dev_idle\n" ));
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_LICENSE_IS_GPL */
return err;
}
/** This funtion is invoked when mali device needs to be activated.
*/
void _mali_osk_pmm_dev_activate(void)
{
#if MALI_LICENSE_IS_GPL
#ifdef CONFIG_PM_RUNTIME
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
int err = 0;
if(is_runtime == 0)
{
pm_suspend_ignore_children(&(mali_gpu_device.dev), true);
pm_runtime_enable(&(mali_gpu_device.dev));
pm_runtime_get_sync(&(mali_gpu_device.dev));
is_runtime = 1;
}
else
{
err = pm_runtime_get_sync(&(mali_gpu_device.dev));
}
if(err)
{
MALI_DEBUG_PRINT(4, ("OSPMM: Error in _mali_osk_pmm_dev_activate\n" ));
}
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
#endif /* CONFIG_PM_RUNTIME */
#endif /* MALI_LICENSE_IS_GPL */
}
void _mali_osk_pmm_dvfs_operation_done(mali_pmm_message_data data)
{
#if MALI_LICENSE_IS_GPL
#ifdef CONFIG_PM
is_wake_up_needed = 1;
wake_up_process(dvfs_pm_thread);
MALI_DEBUG_PRINT(4, ("OSPMM: MALI OSK DVFS Operation done\n" ));
return;
#endif /* CONFIG_PM */
#endif /* MALI_LICENSE_IS_GPL */
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_specific.h
* Defines per-OS Kernel level specifics, such as unusual workarounds for
* certain OSs.
*/
#ifndef __MALI_OSK_SPECIFIC_H__
#define __MALI_OSK_SPECIFIC_H__
#ifdef __cplusplus
extern "C"
{
#endif
#define MALI_STATIC_INLINE static inline
#define MALI_NON_STATIC_INLINE inline
#ifdef __cplusplus
}
#endif
#endif /* __MALI_OSK_SPECIFIC_H__ */

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_time.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include "mali_osk.h"
#include <linux/jiffies.h>
#include <linux/time.h>
#include <asm/delay.h>
int _mali_osk_time_after( u32 ticka, u32 tickb )
{
return time_after((unsigned long)ticka, (unsigned long)tickb);
}
u32 _mali_osk_time_mstoticks( u32 ms )
{
return msecs_to_jiffies(ms);
}
u32 _mali_osk_time_tickstoms( u32 ticks )
{
return jiffies_to_msecs(ticks);
}
u32 _mali_osk_time_tickcount( void )
{
return jiffies;
}
void _mali_osk_time_ubusydelay( u32 usecs )
{
udelay(usecs);
}
u64 _mali_osk_time_get_ns( void )
{
struct timespec tsval;
getnstimeofday(&tsval);
return (u64)timespec_to_ns(&tsval);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_osk_timers.c
* Implementation of the OS abstraction layer for the kernel device driver
*/
#include <linux/timer.h>
#include <linux/slab.h>
#include "mali_osk.h"
#include "mali_kernel_common.h"
struct _mali_osk_timer_t_struct
{
struct timer_list timer;
};
typedef void (*timer_timeout_function_t)(unsigned long);
_mali_osk_timer_t *_mali_osk_timer_init(void)
{
_mali_osk_timer_t *t = (_mali_osk_timer_t*)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL);
if (NULL != t) init_timer(&t->timer);
return t;
}
void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire )
{
MALI_DEBUG_ASSERT_POINTER(tim);
tim->timer.expires = _mali_osk_time_tickcount() + ticks_to_expire;
add_timer(&(tim->timer));
}
void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick)
{
MALI_DEBUG_ASSERT_POINTER(tim);
mod_timer(&(tim->timer), expiry_tick);
}
void _mali_osk_timer_del( _mali_osk_timer_t *tim )
{
MALI_DEBUG_ASSERT_POINTER(tim);
del_timer_sync(&(tim->timer));
}
void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data )
{
MALI_DEBUG_ASSERT_POINTER(tim);
tim->timer.data = (unsigned long)data;
tim->timer.function = (timer_timeout_function_t)callback;
}
void _mali_osk_timer_term( _mali_osk_timer_t *tim )
{
MALI_DEBUG_ASSERT_POINTER(tim);
kfree(tim);
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/fs.h> /* file system operations */
#include <linux/slab.h> /* memort allocation functions */
#include <asm/uaccess.h> /* user space access */
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_session_manager.h"
#include "mali_ukk_wrappers.h"
int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs)
{
_mali_uk_get_api_version_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
if (0 != get_user(kargs.version, &uargs->version)) return -EFAULT;
kargs.ctx = session_data;
err = _mali_ukk_get_api_version(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
if (0 != put_user(kargs.compatible, &uargs->compatible)) return -EFAULT;
return 0;
}
int get_system_info_size_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_size_s __user *uargs)
{
_mali_uk_get_system_info_size_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_get_system_info_size(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
return 0;
}
int get_system_info_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_s __user *uargs)
{
_mali_uk_get_system_info_s kargs;
_mali_osk_errcode_t err;
_mali_system_info *system_info_user;
_mali_system_info *system_info_kernel;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
if (0 != get_user(kargs.system_info, &uargs->system_info)) return -EFAULT;
if (0 != get_user(kargs.size, &uargs->size)) return -EFAULT;
/* A temporary kernel buffer for the system_info datastructure is passed through the system_info
* member. The ukk_private member will point to the user space destination of this buffer so
* that _mali_ukk_get_system_info() can correct the pointers in the system_info correctly
* for user space.
*/
system_info_kernel = kmalloc(kargs.size, GFP_KERNEL);
if (NULL == system_info_kernel) return -EFAULT;
system_info_user = kargs.system_info;
kargs.system_info = system_info_kernel;
kargs.ukk_private = (u32)system_info_user;
kargs.ctx = session_data;
err = _mali_ukk_get_system_info(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
kfree(system_info_kernel);
return map_errcode(err);
}
if (0 != copy_to_user(system_info_user, system_info_kernel, kargs.size))
{
kfree(system_info_kernel);
return -EFAULT;
}
kfree(system_info_kernel);
return 0;
}
int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs)
{
_mali_uk_wait_for_notification_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_wait_for_notification(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if(_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS != kargs.type)
{
kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_wait_for_notification_s))) return -EFAULT;
}
else
{
if (0 != put_user(kargs.type, &uargs->type)) return -EFAULT;
}
return 0;
}
int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs)
{
_mali_uk_post_notification_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
if (0 != get_user(kargs.type, &uargs->type))
{
return -EFAULT;
}
err = _mali_ukk_post_notification(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
return 0;
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/fs.h> /* file system operations */
#include <asm/uaccess.h> /* user space access */
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_session_manager.h"
#include "mali_ukk_wrappers.h"
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs)
{
_mali_uk_gp_start_job_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_gp_start_job_s)))
{
return -EFAULT;
}
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_start_job_s))) return -EFAULT;
kargs.ctx = session_data;
err = _mali_ukk_gp_start_job(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_gp_start_job_s)))
{
/*
* If this happens, then user space will not know that the job was actually started,
* and if we return a queued job, then user space will still think that one is still queued.
* This will typically lead to a deadlock in user space.
* This could however only happen if user space deliberately passes a user buffer which
* passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user().
* The official Mali driver will never attempt to do that, and kernel space should not be affected.
* That is why we do not bother to do a complex rollback in this very very very rare case.
*/
return -EFAULT;
}
return 0;
}
int gp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_abort_job_s __user *uargs)
{
_mali_uk_gp_abort_job_s kargs;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_abort_job_s))) return -EFAULT;
kargs.ctx = session_data;
_mali_ukk_gp_abort_job(&kargs);
return 0;
}
int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs)
{
_mali_uk_get_gp_core_version_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_get_gp_core_version(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
/* no known transactions to roll-back */
if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
return 0;
}
int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs)
{
_mali_uk_gp_suspend_response_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_suspend_response_s))) return -EFAULT;
kargs.ctx = session_data;
err = _mali_ukk_gp_suspend_response(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.cookie, &uargs->cookie)) return -EFAULT;
/* no known transactions to roll-back */
return 0;
}
int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs)
{
_mali_uk_get_gp_number_of_cores_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_get_gp_number_of_cores(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
/* no known transactions to roll-back */
if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT;
return 0;
}

View File

@@ -0,0 +1,336 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/fs.h> /* file system operations */
#include <asm/uaccess.h> /* user space access */
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_session_manager.h"
#include "mali_ukk_wrappers.h"
int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs)
{
_mali_uk_init_mem_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_init_mem(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback;
if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback;
return 0;
mem_init_rollback:
{
_mali_uk_term_mem_s kargs;
kargs.ctx = session_data;
err = _mali_ukk_term_mem(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n"));
}
}
return -EFAULT;
}
int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs)
{
_mali_uk_term_mem_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_term_mem(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
return 0;
}
int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument)
{
_mali_uk_map_external_mem_s uk_args;
_mali_osk_errcode_t err_code;
/* validate input */
/* the session_data pointer was validated by caller */
MALI_CHECK_NON_NULL( argument, -EINVAL);
/* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) )
{
return -EFAULT;
}
uk_args.ctx = session_data;
err_code = _mali_ukk_map_external_mem( &uk_args );
if (0 != put_user(uk_args.cookie, &argument->cookie))
{
if (_MALI_OSK_ERR_OK == err_code)
{
/* Rollback */
_mali_uk_unmap_external_mem_s uk_args_unmap;
uk_args_unmap.ctx = session_data;
uk_args_unmap.cookie = uk_args.cookie;
err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap );
if (_MALI_OSK_ERR_OK != err_code)
{
MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n"));
}
}
return -EFAULT;
}
/* Return the error that _mali_ukk_free_big_block produced */
return map_errcode(err_code);
}
int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument)
{
_mali_uk_unmap_external_mem_s uk_args;
_mali_osk_errcode_t err_code;
/* validate input */
/* the session_data pointer was validated by caller */
MALI_CHECK_NON_NULL( argument, -EINVAL);
/* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) )
{
return -EFAULT;
}
uk_args.ctx = session_data;
err_code = _mali_ukk_unmap_external_mem( &uk_args );
/* Return the error that _mali_ukk_free_big_block produced */
return map_errcode(err_code);
}
#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument)
{
_mali_uk_release_ump_mem_s uk_args;
_mali_osk_errcode_t err_code;
/* validate input */
/* the session_data pointer was validated by caller */
MALI_CHECK_NON_NULL( argument, -EINVAL);
/* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) )
{
return -EFAULT;
}
uk_args.ctx = session_data;
err_code = _mali_ukk_release_ump_mem( &uk_args );
/* Return the error that _mali_ukk_free_big_block produced */
return map_errcode(err_code);
}
int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument)
{
_mali_uk_attach_ump_mem_s uk_args;
_mali_osk_errcode_t err_code;
/* validate input */
/* the session_data pointer was validated by caller */
MALI_CHECK_NON_NULL( argument, -EINVAL);
/* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) )
{
return -EFAULT;
}
uk_args.ctx = session_data;
err_code = _mali_ukk_attach_ump_mem( &uk_args );
if (0 != put_user(uk_args.cookie, &argument->cookie))
{
if (_MALI_OSK_ERR_OK == err_code)
{
/* Rollback */
_mali_uk_release_ump_mem_s uk_args_unmap;
uk_args_unmap.ctx = session_data;
uk_args_unmap.cookie = uk_args.cookie;
err_code = _mali_ukk_release_ump_mem( &uk_args_unmap );
if (_MALI_OSK_ERR_OK != err_code)
{
MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n"));
}
}
return -EFAULT;
}
/* Return the error that _mali_ukk_map_external_ump_mem produced */
return map_errcode(err_code);
}
#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs)
{
_mali_uk_query_mmu_page_table_dump_size_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
return 0;
}
int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs)
{
_mali_uk_dump_mmu_page_table_s kargs;
_mali_osk_errcode_t err;
void *buffer;
int rc = -EFAULT;
/* validate input */
MALI_CHECK_NON_NULL(uargs, -EINVAL);
/* the session_data pointer was validated by caller */
kargs.buffer = NULL;
/* get location of user buffer */
if (0 != get_user(buffer, &uargs->buffer)) goto err_exit;
/* get size of mmu page table info buffer from user space */
if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit;
/* verify we can access the whole of the user buffer */
if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit;
/* allocate temporary buffer (kernel side) to store mmu page table info */
kargs.buffer = _mali_osk_malloc(kargs.size);
if (NULL == kargs.buffer)
{
rc = -ENOMEM;
goto err_exit;
}
kargs.ctx = session_data;
err = _mali_ukk_dump_mmu_page_table(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
rc = map_errcode(err);
goto err_exit;
}
/* copy mmu page table info back to user space and update pointers */
if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit;
if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit;
if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit;
if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit;
if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit;
rc = 0;
err_exit:
if (kargs.buffer) _mali_osk_free(kargs.buffer);
return rc;
}
int mem_get_big_block_wrapper( struct file * filp, _mali_uk_get_big_block_s __user * argument )
{
_mali_uk_get_big_block_s uk_args;
_mali_osk_errcode_t err_code;
/* validate input */
/* the session_data pointer was validated by caller */
MALI_CHECK_NON_NULL( argument, -EINVAL);
/* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_get_big_block_s)) )
{
return -EFAULT;
}
/* This interface inserts something into the ukk_private word */
uk_args.ukk_private = (u32)filp;
uk_args.ctx = filp->private_data;
err_code = _mali_ukk_get_big_block( &uk_args );
/* Do not leak the private word back into user space */
uk_args.ukk_private = 0;
if ( _MALI_OSK_ERR_OK != err_code )
{
return map_errcode(err_code);
}
/* From this point on, we must roll-back any failing action to preserve the
* meaning of the U/K interface (e.g. when excluded) */
/* transfer response back to user space */
if ( 0 != copy_to_user(argument, &uk_args, sizeof(_mali_uk_get_big_block_s)) )
{
/* Roll-back - the _mali_uk_get_big_block call succeeded, so all
* values in uk_args will be correct */
_mali_uk_free_big_block_s uk_args_rollback = {0, };
uk_args_rollback.ctx = uk_args.ctx;
uk_args_rollback.cookie = uk_args.cookie;
err_code = _mali_ukk_free_big_block( &uk_args_rollback );
if ( _MALI_OSK_ERR_OK != err_code )
{
/* error in DEBUG and RELEASE */
MALI_PRINT_ERROR( ("Failed to rollback get_big_block: %.8X\n", (u32)err_code) );
}
return -EFAULT;
}
return 0;
}
int mem_free_big_block_wrapper(struct mali_session_data *session_data, _mali_uk_free_big_block_s __user * argument)
{
_mali_uk_free_big_block_s uk_args;
_mali_osk_errcode_t err_code;
/* validate input */
/* the session_data pointer was validated by caller */
MALI_CHECK_NON_NULL( argument, -EINVAL );
/* get call arguments from user space. get_user returns 0 on success */
if ( 0 != get_user(uk_args.cookie, &argument->cookie) )
{
return -EFAULT;
}
uk_args.ctx = session_data;
err_code = _mali_ukk_free_big_block( &uk_args );
/* Return the error that _mali_ukk_free_big_block produced */
return map_errcode(err_code);
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/fs.h> /* file system operations */
#include <asm/uaccess.h> /* user space access */
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_session_manager.h"
#include "mali_ukk_wrappers.h"
int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs)
{
_mali_uk_pp_start_job_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_pp_start_job_s)))
{
return -EFAULT;
}
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_start_job_s))) return -EFAULT;
kargs.ctx = session_data;
err = _mali_ukk_pp_start_job(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.returned_user_job_ptr, &uargs->returned_user_job_ptr) ||
0 != put_user(kargs.status, &uargs->status))
{
/*
* If this happens, then user space will not know that the job was actually started,
* and if we return a queued job, then user space will still think that one is still queued.
* This will typically lead to a deadlock in user space.
* This could however only happen if user space deliberately passes a user buffer which
* passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user().
* The official Mali driver will never attempt to do that, and kernel space should not be affected.
* That is why we do not bother to do a complex rollback in this very very very rare case.
*/
return -EFAULT;
}
return 0;
}
int pp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_abort_job_s __user *uargs)
{
_mali_uk_pp_abort_job_s kargs;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_abort_job_s))) return -EFAULT;
kargs.ctx = session_data;
_mali_ukk_pp_abort_job(&kargs);
return 0;
}
int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs)
{
_mali_uk_get_pp_number_of_cores_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_get_pp_number_of_cores(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT;
return 0;
}
int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs)
{
_mali_uk_get_pp_core_version_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
MALI_CHECK_NON_NULL(session_data, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_get_pp_core_version(&kargs);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
return 0;
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/fs.h> /* file system operations */
#include <asm/uaccess.h> /* user space access */
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
#include "mali_kernel_session_manager.h"
#include "mali_ukk_wrappers.h"
int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs)
{
_mali_uk_profiling_start_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_start_s)))
{
return -EFAULT;
}
kargs.ctx = session_data;
err = _mali_ukk_profiling_start(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
if (0 != put_user(kargs.limit, &uargs->limit))
{
return -EFAULT;
}
return 0;
}
int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs)
{
_mali_uk_profiling_add_event_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_add_event_s)))
{
return -EFAULT;
}
kargs.ctx = session_data;
err = _mali_ukk_profiling_add_event(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
return 0;
}
int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs)
{
_mali_uk_profiling_stop_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_profiling_stop(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
if (0 != put_user(kargs.count, &uargs->count))
{
return -EFAULT;
}
return 0;
}
int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs)
{
_mali_uk_profiling_get_event_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
if (0 != get_user(kargs.index, &uargs->index))
{
return -EFAULT;
}
kargs.ctx = session_data;
err = _mali_ukk_profiling_get_event(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_get_event_s)))
{
return -EFAULT;
}
return 0;
}
int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs)
{
_mali_uk_profiling_clear_s kargs;
_mali_osk_errcode_t err;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
kargs.ctx = session_data;
err = _mali_ukk_profiling_clear(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
return map_errcode(err);
}
return 0;
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2010-2011 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file mali_ukk_wrappers.h
* Defines the wrapper functions for each user-kernel function
*/
#ifndef __MALI_UKK_WRAPPERS_H__
#define __MALI_UKK_WRAPPERS_H__
#include "mali_uk_types.h"
#include "mali_osk.h"
#ifdef __cplusplus
extern "C"
{
#endif
int get_system_info_size_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_size_s __user *uargs);
int get_system_info_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_s __user *uargs);
int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs);
int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs);
int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs);
int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs);
int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs);
int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument);
int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument);
int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs);
int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs);
#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument);
int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument);
#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
int mem_get_big_block_wrapper( struct file * filp, _mali_uk_get_big_block_s __user * argument );
int mem_free_big_block_wrapper( struct mali_session_data *session_data, _mali_uk_free_big_block_s __user * argument);
int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs);
int pp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_abort_job_s __user *uargs);
int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs);
int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs);
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs);
int gp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_abort_job_s __user *uargs);
int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs);
int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs);
int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs);
int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs);
int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs);
int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs);
int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs);
int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs);
int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs);
int map_errcode( _mali_osk_errcode_t err );
#ifdef __cplusplus
}
#endif
#endif /* __MALI_UKK_WRAPPERS_H__ */