diff options
author | mcampbellsmith <mcampbellsmith@gmail.com> | 2013-11-20 22:34:44 +1100 |
---|---|---|
committer | sbrissen <sbrissen@hotmail.com> | 2013-12-10 14:54:28 -0500 |
commit | 74bcc029c6ab942f252477a74102877f7d093388 (patch) | |
tree | 044bd97b98693c073841663c62f57e1520509109 | |
parent | 2a6649bf6aa50c44a05fc02e1efb8b788c58e82b (diff) | |
download | kernel_samsung_smdk4412-74bcc029c6ab942f252477a74102877f7d093388.zip kernel_samsung_smdk4412-74bcc029c6ab942f252477a74102877f7d093388.tar.gz kernel_samsung_smdk4412-74bcc029c6ab942f252477a74102877f7d093388.tar.bz2 |
mali: bulk import of r3p2-01rel3 drivers from i9300-update12
Courtesy of a similar commit from OMNI ROM. Requires updated mali blobs
Change-Id: I9ee55b653b57b7c390f8e0e8cd4fc068f1c751c3
231 files changed, 17217 insertions, 14931 deletions
diff --git a/arch/arm/configs/cyanogenmod_i9305_defconfig b/arch/arm/configs/cyanogenmod_i9305_defconfig index c1abc23..2fe449c 100755 --- a/arch/arm/configs/cyanogenmod_i9305_defconfig +++ b/arch/arm/configs/cyanogenmod_i9305_defconfig @@ -2901,7 +2901,7 @@ CONFIG_EXT2_FS=y CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_EXT4_FS_XATTR=y -# CONFIG_EXT4_FS_POSIX_ACL is not set +CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y diff --git a/drivers/Kconfig b/drivers/Kconfig index eb24286..b16fa42 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -1,5 +1,7 @@ menu "Device Drivers" +source "drivers/gpu/mali400/Kconfig" + source "drivers/base/Kconfig" source "drivers/connector/Kconfig" diff --git a/drivers/base/sync.c b/drivers/base/sync.c index d6913f8..06a5eac 100644 --- a/drivers/base/sync.c +++ b/drivers/base/sync.c @@ -15,6 +15,7 @@ */ #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/kernel.h> @@ -27,8 +28,13 @@ #include <linux/anon_inodes.h> +#define CREATE_TRACE_POINTS +#include <trace/events/sync.h> + static void sync_fence_signal_pt(struct sync_pt *pt); static int _sync_pt_has_signaled(struct sync_pt *pt); +static void sync_fence_free(struct kref *kref); +static void sync_dump(void); static LIST_HEAD(sync_timeline_list_head); static DEFINE_SPINLOCK(sync_timeline_list_lock); @@ -49,6 +55,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, if (obj == NULL) return NULL; + kref_init(&obj->kref); obj->ops = ops; strlcpy(obj->name, name, sizeof(obj->name)); @@ -64,9 +71,12 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, return obj; } +EXPORT_SYMBOL(sync_timeline_create); -static void sync_timeline_free(struct sync_timeline *obj) +static void sync_timeline_free(struct kref *kref) { + struct sync_timeline *obj = + container_of(kref, struct sync_timeline, kref); unsigned long flags; if (obj->ops->release_obj) @@ -81,19 +91,17 @@ static void sync_timeline_free(struct sync_timeline *obj) void sync_timeline_destroy(struct sync_timeline *obj) { - unsigned long flags; - bool needs_freeing; - - spin_lock_irqsave(&obj->child_list_lock, flags); obj->destroyed = true; - needs_freeing = list_empty(&obj->child_list_head); - spin_unlock_irqrestore(&obj->child_list_lock, flags); - if (needs_freeing) - sync_timeline_free(obj); - else + /* + * If this is not the last reference, signal any children + * that their parent is going away. + */ + + if (!kref_put(&obj->kref, sync_timeline_free)) sync_timeline_signal(obj); } +EXPORT_SYMBOL(sync_timeline_destroy); static void sync_timeline_add_pt(struct sync_timeline *obj, struct sync_pt *pt) { @@ -110,7 +118,6 @@ static void sync_timeline_remove_pt(struct sync_pt *pt) { struct sync_timeline *obj = pt->parent; unsigned long flags; - bool needs_freeing; spin_lock_irqsave(&obj->active_list_lock, flags); if (!list_empty(&pt->active_list)) @@ -118,12 +125,10 @@ static void sync_timeline_remove_pt(struct sync_pt *pt) spin_unlock_irqrestore(&obj->active_list_lock, flags); spin_lock_irqsave(&obj->child_list_lock, flags); - list_del(&pt->child_list); - needs_freeing = obj->destroyed && list_empty(&obj->child_list_head); + if (!list_empty(&pt->child_list)) { + list_del_init(&pt->child_list); + } spin_unlock_irqrestore(&obj->child_list_lock, flags); - - if (needs_freeing) - sync_timeline_free(obj); } void sync_timeline_signal(struct sync_timeline *obj) @@ -132,26 +137,33 @@ void sync_timeline_signal(struct sync_timeline *obj) LIST_HEAD(signaled_pts); struct list_head *pos, *n; + trace_sync_timeline(obj); + spin_lock_irqsave(&obj->active_list_lock, flags); list_for_each_safe(pos, n, &obj->active_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, active_list); - if (_sync_pt_has_signaled(pt)) - list_move(pos, &signaled_pts); + if (_sync_pt_has_signaled(pt)) { + list_del_init(pos); + list_add(&pt->signaled_list, &signaled_pts); + kref_get(&pt->fence->kref); + } } spin_unlock_irqrestore(&obj->active_list_lock, flags); list_for_each_safe(pos, n, &signaled_pts) { struct sync_pt *pt = - container_of(pos, struct sync_pt, active_list); + container_of(pos, struct sync_pt, signaled_list); list_del_init(pos); sync_fence_signal_pt(pt); + kref_put(&pt->fence->kref, sync_fence_free); } } +EXPORT_SYMBOL(sync_timeline_signal); struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size) { @@ -165,10 +177,12 @@ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size) return NULL; INIT_LIST_HEAD(&pt->active_list); + kref_get(&parent->kref); sync_timeline_add_pt(parent, pt); return pt; } +EXPORT_SYMBOL(sync_pt_create); void sync_pt_free(struct sync_pt *pt) { @@ -177,8 +191,11 @@ void sync_pt_free(struct sync_pt *pt) sync_timeline_remove_pt(pt); + kref_put(&pt->parent->kref, sync_timeline_free); + kfree(pt); } +EXPORT_SYMBOL(sync_pt_free); /* call with pt->parent->active_list_lock held */ static int _sync_pt_has_signaled(struct sync_pt *pt) @@ -247,6 +264,7 @@ static struct sync_fence *sync_fence_alloc(const char *name) if (fence->file == NULL) goto err; + kref_init(&fence->kref); strlcpy(fence->name, name, sizeof(fence->name)); INIT_LIST_HEAD(&fence->pt_list_head); @@ -282,29 +300,67 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) list_add(&pt->pt_list, &fence->pt_list_head); sync_pt_activate(pt); + /* + * signal the fence in case pt was activated before + * sync_pt_activate(pt) was called + */ + sync_fence_signal_pt(pt); + return fence; } +EXPORT_SYMBOL(sync_fence_create); static int sync_fence_copy_pts(struct sync_fence *dst, struct sync_fence *src) { - struct list_head *pos; + struct list_head *pos, *test_pos; list_for_each(pos, &src->pt_list_head) { struct sync_pt *orig_pt = container_of(pos, struct sync_pt, pt_list); - struct sync_pt *new_pt = sync_pt_dup(orig_pt); + struct sync_pt *new_pt; + + /* Skip already signaled points */ + if (1 == orig_pt->status) + continue; + + list_for_each(test_pos, &src->pt_list_head) { + struct sync_pt *test_pt = + container_of(pos, struct sync_pt, pt_list); + if (orig_pt->parent == test_pt->parent) { + int diff; + diff = orig_pt->parent->ops->compare(orig_pt, + test_pt); + if (diff == -1) { + /* Skip orig_pt; another point will + * signal after it */ + continue; + } + break; + } + } + + new_pt = sync_pt_dup(orig_pt); if (new_pt == NULL) return -ENOMEM; new_pt->fence = dst; list_add(&new_pt->pt_list, &dst->pt_list_head); - sync_pt_activate(new_pt); } return 0; } +static void sync_fence_detach_pts(struct sync_fence *fence) +{ + struct list_head *pos, *n; + + list_for_each_safe(pos, n, &fence->pt_list_head) { + struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + sync_timeline_remove_pt(pt); + } +} + static void sync_fence_free_pts(struct sync_fence *fence) { struct list_head *pos, *n; @@ -331,16 +387,19 @@ err: fput(file); return NULL; } +EXPORT_SYMBOL(sync_fence_fdget); void sync_fence_put(struct sync_fence *fence) { fput(fence->file); } +EXPORT_SYMBOL(sync_fence_put); void sync_fence_install(struct sync_fence *fence, int fd) { fd_install(fd, fence->file); } +EXPORT_SYMBOL(sync_fence_install); static int sync_fence_get_status(struct sync_fence *fence) { @@ -349,7 +408,13 @@ static int sync_fence_get_status(struct sync_fence *fence) list_for_each(pos, &fence->pt_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); - int pt_status = pt->status; + int pt_status; + + if (pt == NULL) { + printk(KERN_ERR"[sync driver] sync_fence_get_status : sync_pt is NULL\n"); + break; + } + pt_status = pt->status; if (pt_status < 0) { status = pt_status; @@ -365,6 +430,7 @@ static int sync_fence_get_status(struct sync_fence *fence) struct sync_fence *sync_fence_merge(const char *name, struct sync_fence *a, struct sync_fence *b) { + struct list_head *pos; struct sync_fence *fence; int err; @@ -380,7 +446,29 @@ struct sync_fence *sync_fence_merge(const char *name, if (err < 0) goto err; - fence->status = sync_fence_get_status(fence); + /* Make sure there is at least one point in the fence */ + if (list_empty(&fence->pt_list_head)) { + struct sync_pt *orig_pt = list_first_entry(&a->pt_list_head, + struct sync_pt, pt_list); + struct sync_pt *new_pt = sync_pt_dup(orig_pt); + + new_pt->fence = fence; + list_add(&new_pt->pt_list, &fence->pt_list_head); + } + + list_for_each(pos, &fence->pt_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, pt_list); + sync_pt_activate(pt); + } + + /* + * signal the fence in case one of it's pts were activated before + * they were activated + */ + sync_fence_signal_pt(list_first_entry(&fence->pt_list_head, + struct sync_pt, + pt_list)); return fence; err: @@ -388,6 +476,7 @@ err: kfree(fence); return NULL; } +EXPORT_SYMBOL(sync_fence_merge); static void sync_fence_signal_pt(struct sync_pt *pt) { @@ -421,33 +510,22 @@ static void sync_fence_signal_pt(struct sync_pt *pt) container_of(pos, struct sync_fence_waiter, waiter_list); - waiter->callback(fence, waiter->callback_data); list_del(pos); - kfree(waiter); + waiter->callback(fence, waiter); } wake_up(&fence->wq); } } int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data) + struct sync_fence_waiter *waiter) { - struct sync_fence_waiter *waiter; unsigned long flags; int err = 0; - waiter = kzalloc(sizeof(struct sync_fence_waiter), GFP_KERNEL); - if (waiter == NULL) - return -ENOMEM; - - waiter->callback = callback; - waiter->callback_data = callback_data; - spin_lock_irqsave(&fence->waiter_list_lock, flags); if (fence->status) { - kfree(waiter); err = fence->status; goto out; } @@ -458,44 +536,120 @@ out: return err; } +EXPORT_SYMBOL(sync_fence_wait_async); + +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter) +{ + struct list_head *pos; + struct list_head *n; + unsigned long flags; + int ret = -ENOENT; + + spin_lock_irqsave(&fence->waiter_list_lock, flags); + /* + * Make sure waiter is still in waiter_list because it is possible for + * the waiter to be removed from the list while the callback is still + * pending. + */ + list_for_each_safe(pos, n, &fence->waiter_list_head) { + struct sync_fence_waiter *list_waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + if (list_waiter == waiter) { + list_del(pos); + ret = 0; + break; + } + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); + return ret; +} +EXPORT_SYMBOL(sync_fence_cancel_async); + +static bool sync_fence_check(struct sync_fence *fence) +{ + /* + * Make sure that reads to fence->status are ordered with the + * wait queue event triggering + */ + smp_rmb(); + return fence->status != 0; +} int sync_fence_wait(struct sync_fence *fence, long timeout) { - int err; + int err = 0; + struct sync_pt *pt; - if (timeout) { + trace_sync_wait(fence, 1); + list_for_each_entry(pt, &fence->pt_list_head, pt_list) + trace_sync_pt(pt); + + if (timeout > 0) { timeout = msecs_to_jiffies(timeout); err = wait_event_interruptible_timeout(fence->wq, - fence->status != 0, + sync_fence_check(fence), timeout); - } else { - err = wait_event_interruptible(fence->wq, fence->status != 0); + } else if (timeout < 0) { + err = wait_event_interruptible(fence->wq, + sync_fence_check(fence)); } + trace_sync_wait(fence, 0); if (err < 0) return err; - if (fence->status < 0) + if (fence->status < 0) { + pr_info("fence error %d on [%p]\n", fence->status, fence); + sync_dump(); return fence->status; + } - if (fence->status == 0) + if (fence->status == 0) { + if (timeout > 0) { + pr_info("fence timeout on [%p] after %dms\n", fence, + jiffies_to_msecs(timeout)); + sync_dump(); + } return -ETIME; + } return 0; } +EXPORT_SYMBOL(sync_fence_wait); + +static void sync_fence_free(struct kref *kref) +{ + struct sync_fence *fence = container_of(kref, struct sync_fence, kref); + + sync_fence_free_pts(fence); + + kfree(fence); +} static int sync_fence_release(struct inode *inode, struct file *file) { struct sync_fence *fence = file->private_data; unsigned long flags; - sync_fence_free_pts(fence); - + /* + * We need to remove all ways to access this fence before droping + * our ref. + * + * start with its membership in the global fence list + */ spin_lock_irqsave(&sync_fence_list_lock, flags); list_del(&fence->sync_fence_list); spin_unlock_irqrestore(&sync_fence_list_lock, flags); - kfree(fence); + /* + * remove its pts from their parents so that sync_timeline_signal() + * can't reference the fence. + */ + sync_fence_detach_pts(fence); + + kref_put(&fence->kref, sync_fence_free); return 0; } @@ -506,6 +660,12 @@ static unsigned int sync_fence_poll(struct file *file, poll_table *wait) poll_wait(file, &fence->wq, wait); + /* + * Make sure that reads to fence->status are ordered with the + * wait queue event triggering + */ + smp_rmb(); + if (fence->status == 1) return POLLIN; else if (fence->status < 0) @@ -516,7 +676,7 @@ static unsigned int sync_fence_poll(struct file *file, poll_table *wait) static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg) { - __u32 value; + __s32 value; if (copy_from_user(&value, (void __user *)arg, sizeof(value))) return -EFAULT; @@ -531,8 +691,13 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) struct sync_fence *fence2, *fence3; struct sync_merge_data data; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; + if (fd < 0) + return fd; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + err = -EFAULT; + goto err_put_fd; + } fence2 = sync_fence_fdget(data.fd2); if (fence2 == NULL) { @@ -568,7 +733,7 @@ err_put_fd: return err; } -int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) +static int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) { struct sync_pt_info *info = data; int ret; @@ -596,7 +761,6 @@ int sync_fill_pt_info(struct sync_pt *pt, void *data, int size) return info->len; } - static long sync_fence_ioctl_fence_info(struct sync_fence *fence, unsigned long arg) { @@ -690,7 +854,17 @@ static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec); } - if (pt->parent->ops->print_pt) { + if (pt->parent->ops->timeline_value_str && + pt->parent->ops->pt_value_str) { + char value[64]; + pt->parent->ops->pt_value_str(pt, value, sizeof(value)); + seq_printf(s, ": %s", value); + if (fence) { + pt->parent->ops->timeline_value_str(pt->parent, value, + sizeof(value)); + seq_printf(s, " / %s", value); + } + } else if (pt->parent->ops->print_pt) { seq_printf(s, ": "); pt->parent->ops->print_pt(s, pt); } @@ -705,7 +879,11 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) seq_printf(s, "%s %s", obj->name, obj->ops->driver_name); - if (obj->ops->print_obj) { + if (obj->ops->timeline_value_str) { + char value[64]; + obj->ops->timeline_value_str(obj, value, sizeof(value)); + seq_printf(s, ": %s", value); + } else if (obj->ops->print_obj) { seq_printf(s, ": "); obj->ops->print_obj(s, obj); } @@ -726,7 +904,8 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) struct list_head *pos; unsigned long flags; - seq_printf(s, "%s: %s\n", fence->name, sync_status_str(fence->status)); + seq_printf(s, "[%p] %s: %s\n", fence, fence->name, + sync_status_str(fence->status)); list_for_each(pos, &fence->pt_list_head) { struct sync_pt *pt = @@ -740,8 +919,7 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) container_of(pos, struct sync_fence_waiter, waiter_list); - seq_printf(s, "waiter %pF %p\n", waiter->callback, - waiter->callback_data); + seq_printf(s, "waiter %pF\n", waiter->callback); } spin_unlock_irqrestore(&fence->waiter_list_lock, flags); } @@ -795,7 +973,34 @@ static __init int sync_debugfs_init(void) debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops); return 0; } - late_initcall(sync_debugfs_init); +#define DUMP_CHUNK 256 +static char sync_dump_buf[64 * 1024]; +void sync_dump(void) +{ + struct seq_file s = { + .buf = sync_dump_buf, + .size = sizeof(sync_dump_buf) - 1, + }; + int i; + + sync_debugfs_show(&s, NULL); + + for (i = 0; i < s.count; i += DUMP_CHUNK) { + if ((s.count - i) > DUMP_CHUNK) { + char c = s.buf[i + DUMP_CHUNK]; + s.buf[i + DUMP_CHUNK] = 0; + pr_cont("%s", s.buf + i); + s.buf[i + DUMP_CHUNK] = c; + } else { + s.buf[s.count] = 0; + pr_cont("%s", s.buf + i); + } + } +} +#else +static void sync_dump(void) +{ +} #endif diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index 00efbf6..8a0ed22 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -4,3 +4,9 @@ else obj-y += drm/ vga/ stub/ ion/ endif +ifeq ($(CONFIG_MALI400),y) +ifeq ($(CONFIG_MALI_VER_R3P2),y) +obj-y += mali400/r3p2/mali/ +obj-y += mali400/r3p2/ump/ +endif +endif diff --git a/drivers/gpu/mali400/Kconfig b/drivers/gpu/mali400/Kconfig new file mode 100644 index 0000000..8ec13b3 --- /dev/null +++ b/drivers/gpu/mali400/Kconfig @@ -0,0 +1,26 @@ +menuconfig MALI400 + tristate "Mali-300/400/450 support" + depends on ARM + default y + ---help--- + This enables support for the ARM Mali-300, Mali-400, and Mali-450 + GPUs. + + To compile this driver as a module, choose M here: the module will be + called mali. + +choice +depends on MALI400 +prompt "Select MALI VER" +default MALI_VER_R3P2 +config MALI_VER_R3P2 + bool "Mali400 Version R3P2" + help + Choose this option to select DDK version. + +if MALI_VER_R3P2 +source "drivers/gpu/mali400/r3p2/mali/Kconfig" +source "drivers/gpu/mali400/r3p2/ump/Kconfig" +endif + +endchoice diff --git a/drivers/gpu/mali400/r3p2/mali/Kbuild b/drivers/gpu/mali400/r3p2/mali/Kbuild new file mode 100644 index 0000000..81acbb8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/Kbuild @@ -0,0 +1,220 @@ +# +# 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. +# + +# This file is called by the Linux build system. + +# set up defaults if not defined by the user +TIMESTAMP ?= default +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 +USING_GPU_UTILIZATION ?= 1 +PROFILING_SKIP_PP_JOBS ?= 0 +PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 +MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 +MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 +MALI_UPPER_HALF_SCHEDULING ?= 1 +# MALI_SEC +# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM +ifeq ($(CONFIG_CPU_EXYNOS4210),y) + TARGET_PLATFORM=pegasus-m400 +endif +ifeq ($(CONFIG_CPU_EXYNOS4212),y) + TARGET_PLATFORM=pegasus-m400 +endif +ifeq ($(CONFIG_CPU_EXYNOS4412),y) + TARGET_PLATFORM=pegasus-m400 +endif +ifeq ($(CONFIG_SOC_EXYNOS3470),y) + TARGET_PLATFORM=exynos4270 +endif + +include $(srctree)/$(src)/MALI_CONFIGURATION +MALI_PLATFORM = $(MALI_PLATFORM-$(TARGET_PLATFORM)) +EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 +MALI_PLATFORM_FILES = $(subst $(srctree)/$(src)/,,$(wildcard $(srctree)/$(src)/platform/$(MALI_PLATFORM)/*.c)) +# End of MALI_SEC + +# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: +# The ARM proprietary product will only include the license/proprietary directory +# The GPL product will only include the license/gpl directory +$(warning Current directory is $(srctree)/$(src) from $(shell pwd)) +ifeq ($(wildcard $(srctree)/$(src)/linux/license/gpl/*),) + ccflags-y += -I$(srctree)/$(src)/linux/license/proprietary + ifeq ($(CONFIG_MALI400_PROFILING),y) + $(error Profiling is incompatible with non-GPL license) + endif + ifeq ($(CONFIG_PM_RUNTIME),y) + $(error Runtime PM is incompatible with non-GPL license) + endif + ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) + $(error DMA-BUF is incompatible with non-GPL license) + endif + $(error Linux Device integration is incompatible with non-GPL license) +else + ccflags-y += -I$(srctree)/$(src)/linux/license/gpl +endif + +mali-y += \ + linux/mali_osk_atomics.o \ + linux/mali_osk_irq.o \ + linux/mali_osk_wq.o \ + linux/mali_osk_locks.o \ + linux/mali_osk_wait_queue.o \ + linux/mali_osk_low_level_mem.o \ + linux/mali_osk_math.o \ + linux/mali_osk_memory.o \ + linux/mali_osk_misc.o \ + linux/mali_osk_mali.o \ + linux/mali_osk_notification.o \ + linux/mali_osk_time.o \ + linux/mali_osk_timers.o + +mali-y += \ + linux/mali_ukk_mem.o \ + linux/mali_ukk_gp.o \ + linux/mali_ukk_pp.o \ + linux/mali_ukk_core.o + +# Source files which always are included in a build +mali-y += \ + common/mali_kernel_core.o \ + linux/mali_kernel_linux.o \ + common/mali_kernel_descriptor_mapping.o \ + common/mali_session.o \ + linux/mali_device_pause_resume.o \ + common/mali_kernel_vsync.o \ + linux/mali_ukk_vsync.o \ + linux/mali_kernel_sysfs.o \ + common/mali_mmu.o \ + common/mali_mmu_page_directory.o \ + common/mali_memory.o \ + common/mali_kernel_memory_engine.o \ + common/mali_block_allocator.o \ + common/mali_kernel_mem_os.o \ + common/mali_mem_validation.o \ + common/mali_hw_core.o \ + common/mali_gp.o \ + common/mali_pp.o \ + common/mali_pp_job.o \ + common/mali_gp_job.o \ + common/mali_scheduler.o \ + common/mali_gp_scheduler.o \ + common/mali_pp_scheduler.o \ + common/mali_group.o \ + common/mali_dlbu.o \ + common/mali_broadcast.o \ + common/mali_pm.o \ + common/mali_pmu.o \ + common/mali_user_settings_db.o \ + common/mali_kernel_utilization.o \ + common/mali_l2_cache.o \ + common/mali_pm_domain.o \ + linux/mali_osk_pm.o \ + linux/mali_pmu_power_up_down.o \ + __malidrv_build_info.o + +ifneq ($(MALI_PLATFORM_FILES),) + mali-y += $(MALI_PLATFORM_FILES:.c=.o) +endif + +mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o +mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o + +mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o +ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(srctree)/$(src)/timestamp-$(TIMESTAMP) + +mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o +mali-$(CONFIG_SYNC) += linux/mali_sync.o linux/mali_sync_user.o + +# Tell the Linux build system from which .o file to create the kernel module +obj-$(CONFIG_MALI400) := mali.o + +ccflags-y += $(EXTRA_DEFINES) + +# Set up our defines, which will be passed to gcc +ccflags-y += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) +ccflags-y += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) + +ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) +ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) +ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) +ccflags-y += -DMALI_STATE_TRACKING=1 +ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) +ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) + +ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) + ccflags-y += -DMALI_UPPER_HALF_SCHEDULING +endif + +ccflags-$(CONFIG_MALI400_UMP) += -I$(srctree)/$(src)/../../ump/include/ump +ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG + +# Use our defines when compiling +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/include -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/platform +# MALI_SEC +ccflags-y += -I$(srctree)/$(src)/../ump/include -I$(srctree)/$(src)/include/linux/mali + +# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available +MALI_RELEASE_NAME=$(shell cat $(srctree)/$(src)/.version 2> /dev/null) + +SVN_INFO = (cd $(srctree)/$(src); svn info 2>/dev/null) + +ifneq ($(shell $(SVN_INFO) 2>/dev/null),) +# SVN detected +SVN_REV := $(shell $(SVN_INFO) | grep '^Revision: '| sed -e 's/^Revision: //' 2>/dev/null) +DRIVER_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) +CHANGE_DATE := $(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) +CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) +REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) + +else # SVN +GIT_REV := $(shell cd $(srctree)/$(src); git describe --always 2>/dev/null) +ifneq ($(GIT_REV),) +# Git detected +DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) +CHANGE_DATE := $(shell cd $(srctree)/$(src); git log -1 --format="%ci") +CHANGED_REVISION := $(GIT_REV) +REPO_URL := $(shell cd $(srctree)/$(src); git describe --all --always 2>/dev/null) + +else # Git +# No Git or SVN detected +DRIVER_REV := $(MALI_RELEASE_NAME) +CHANGE_DATE := $(MALI_RELEASE_NAME) +CHANGED_REVISION := $(MALI_RELEASE_NAME) +endif +endif + +ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" + +VERSION_STRINGS := +VERSION_STRINGS += API_VERSION=$(shell cd $(srctree)/$(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) +VERSION_STRINGS += REPO_URL=$(REPO_URL) +VERSION_STRINGS += REVISION=$(DRIVER_REV) +VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) +VERSION_STRINGS += CHANGE_DATE=$(CHANGE_DATE) +VERSION_STRINGS += BUILD_DATE=$(shell date) +ifdef CONFIG_MALI400_DEBUG +VERSION_STRINGS += BUILD=debug +else +VERSION_STRINGS += BUILD=release +endif +VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM) +VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM) +VERSION_STRINGS += KDIR=$(KDIR) +VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) +VERSION_STRINGS += USING_UMP=$(CONFIG_MALI400_UMP) +VERSION_STRINGS += USING_PROFILING=$(CONFIG_MALI400_PROFILING) +VERSION_STRINGS += USING_INTERNAL_PROFILING=$(CONFIG_MALI400_INTERNAL_PROFILING) +VERSION_STRINGS += USING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) +VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) + +# Create file with Mali driver configuration +$(srctree)/$(src)/__malidrv_build_info.c: + @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(srctree)/$(src)/__malidrv_build_info.c diff --git a/drivers/gpu/mali400/r3p2/mali/Kconfig b/drivers/gpu/mali400/r3p2/mali/Kconfig new file mode 100644 index 0000000..14af54a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/Kconfig @@ -0,0 +1,67 @@ +config MALI400_DEBUG + bool "Enable debug in Mali driver" + depends on MALI400 + ---help--- + This enabled extra debug checks and messages in the Mali driver. + +config MALI400_PROFILING + bool "Enable Mali profiling" + depends on MALI400 + select TRACEPOINTS + default n + ---help--- + This enables gator profiling of Mali GPU events. + +config MALI400_INTERNAL_PROFILING + bool "Enable internal Mali profiling API" + depends on MALI400_PROFILING + default n + ---help--- + This enables the internal legacy Mali profiling API. + +if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 +config MALI_DVFS + bool "Enable mali DVFS" + depends on MALI400 && PM + default y + ---help--- + This enables Mali driver DVFS. +endif + +if SOC_EXYNOS3470 +config MALI_DVFS + bool "Enable mali DVFS" + depends on MALI400 && PM_DEVFREQ + default y + ---help--- + This enables Mali driver DVFS. +endif + +if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 +config MALI400_UMP + bool "Enable UMP support" + depends on MALI400 + default y + ---help--- + This enables support for the UMP memory sharing API in the Mali driver. +endif + +config MALI_DMA_BUF_MAP_ON_ATTACH + bool "Map dma-buf attachments on attach" + depends on MALI400 && DMA_SHARED_BUFFER + default y + ---help--- + This makes the Mali driver map dma-buf attachments after doing + attach. If this is not set the dma-buf attachments will be mapped for + every time the GPU need to access the buffer. + + Mapping for each access can cause lower performance. + +config MALI_SHARED_INTERRUPTS + bool "Support for shared interrupts" + depends on MALI400 + default n + ---help--- + Adds functionality required to properly support shared interrupts. Without this support, + the device driver will fail during insmod if it detects shared interrupts. Works even if + the GPU is not using shared interrupts, but can cause lower performance. diff --git a/drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION b/drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION new file mode 100644 index 0000000..4b099b7 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/MALI_CONFIGURATION @@ -0,0 +1,24 @@ +# Location of default kernels +KDIR-odroida:=/projects/pr297/linux/odroid-a/current/linux +KDIR-odroidpc:=/projects/pr297/linux/odroid-pc/current/linux +KDIR-odroidq:=/projects/pr297/linux/odroid-q/current/linux +KDIR-orion:=/projects/pr297/linux/orion/current/linux +KDIR-pegasus:=/projects/pr297/linux/pegasus-smdk/current/linux +KDIR-tcc8900:=/projects/pr297/linux/tcc8900/current/linux +KDIR-pb11mp:=/projects/pr297/linux/pb11mp/current/linux +KDIR-vea9:=/projects/pr297/linux/vea9/current/linux +KDIR-snowball:=/no/default/kernel/yet + +# Name of platform directory with platform specific code (should be built into kernel on a real system) +MALI_PLATFORM-odroida=exynos4 +MALI_PLATFORM-odroidpc=exynos4 +MALI_PLATFORM-odroidq=exynos4 +MALI_PLATFORM-orion=exynos4 +MALI_PLATFORM-pegasus=exynos4 +# MALI_SEC +MALI_PLATFORM-pegasus-m400=pegasus-m400 +MALI_PLATFORM-exynos4270=exynos4270 +MALI_PLATFORM-tcc8900=tcc8900 +MALI_PLATFORM-pb11mp=arm +MALI_PLATFORM-vea9=arm +MALI_PLATFORM-snowball=ux500 diff --git a/drivers/media/video/samsung/mali/Makefile_module b/drivers/gpu/mali400/r3p2/mali/Makefile index 361ce08..b487011 100644 --- a/drivers/media/video/samsung/mali/Makefile_module +++ b/drivers/gpu/mali400/r3p2/mali/Makefile @@ -9,6 +9,9 @@ # USE_UMPV2=0 +USING_PROFILING ?= 1 +USING_INTERNAL_PROFILING ?= 0 +MALI_DMA_BUF_MAP_ON_ATTACH ?= 1 # The Makefile sets up "arch" based on the CONFIG, creates the version info # string and the __malidrv_build_info.c file, and then call the Linux build @@ -32,15 +35,35 @@ check_cc2 = \ # This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak -include ../../../arm_internal.mak -# Check that required parameters are supplied. -ifeq ($(CONFIG),) -$(error "CONFIG must be specified.") +# Give warning of old config parameters are used +ifneq ($(CONFIG),) +$(warning "You have specified the CONFIG variable which is no longer in used. Use TARGET_PLATFORM instead.") endif -ifeq ($(CPU)$(KDIR),) -$(error "KDIR or CPU must be specified.") + +ifneq ($(CPU),) +$(warning "You have specified the CPU variable which is no longer in used. Use TARGET_PLATFORM instead.") +endif + +# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM +-include MALI_CONFIGURATION +export KDIR ?= $(KDIR-$(TARGET_PLATFORM)) +export MALI_PLATFORM ?= $(MALI_PLATFORM-$(TARGET_PLATFORM)) + +ifneq ($(TARGET_PLATFORM),) +ifeq ($(MALI_PLATFORM),) +$(error "Invalid TARGET_PLATFORM: $(TARGET_PLATFORM)") +endif +endif + +# validate lookup result +ifeq ($(KDIR),) +$(error No KDIR found for platform $(TARGET_PLATFORM)) endif + ifeq ($(USING_UMP),1) +export CONFIG_MALI400_UMP=y +export EXTRA_DEFINES += -DCONFIG_MALI400_UMP=1 ifeq ($(USE_UMPV2),1) UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers else @@ -50,38 +73,56 @@ KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE)) $(warning $(KBUILD_EXTRA_SYMBOLS)) endif -# Get any user defined KDIR-<names> or maybe even a hardcoded KDIR --include KDIR_CONFIGURATION - # Define host system directory KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build +include $(KDIR)/.config + ifeq ($(ARCH), arm) # when compiling for ARM we're cross compiling export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) endif -# look up KDIR based om CPU selection -KDIR ?= $(KDIR-$(CPU)) - -# validate lookup result -ifeq ($(KDIR),) -$(error No KDIR found for platform $(CPU)) -endif - # report detected/selected settings ifdef ARM_INTERNAL_BUILD -$(warning Config $(CONFIG)) -$(warning Host CPU $(CPU)) -$(warning OS_MEMORY $(USING_OS_MEMORY)) +$(warning TARGET_PLATFORM $(TARGET_PLATFORM)) +$(warning KDIR $(KDIR)) +$(warning MALI_PLATFORM $(MALI_PLATFORM)) endif # Set up build config export CONFIG_MALI400=m -ifeq ($(USING_GPU_UTILIZATION),1) -export EXTRA_DEFINES += -DCONFIG_MALI400_GPU_UTILIZATION=1 -export CONFIG_MALI400_GPU_UTILIZATION := y +ifneq ($(MALI_PLATFORM),) +export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 +export MALI_PLATFORM_FILES = $(wildcard platform/$(MALI_PLATFORM)/*.c) +endif + +ifeq ($(USING_PROFILING),1) +ifeq ($(CONFIG_TRACEPOINTS),) +$(warning CONFIG_TRACEPOINTS reqired for profiling) +else +export CONFIG_MALI400_PROFILING=y +export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1 +ifeq ($(USING_INTERNAL_PROFILING),1) +export CONFIG_MALI400_INTERNAL_PROFILING=y +export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1 +endif +endif +endif + +ifeq ($(MALI_DMA_BUF_MAP_ON_ATTACH),1) +export CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y +export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH +endif + +ifeq ($(MALI_SHARED_INTERRUPTS),1) +export CONFIG_MALI_SHARED_INTERRUPTS=y +export EXTRA_DEFINES += -DCONFIG_MALI_SHARED_INTERRUPTS +endif + +ifneq ($(BUILD),release) +export CONFIG_MALI400_DEBUG=y endif all: $(UMP_SYMVERS_FILE) diff --git a/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c b/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c new file mode 100644 index 0000000..af5e808 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/__malidrv_build_info.c @@ -0,0 +1 @@ +const char *__malidrv_build_info(void) { return "malidrv: API_VERSION=23 REPO_URL=heads/master REVISION=r3p2-01rel3-137c649 CHANGED_REVISION=137c649 CHANGE_DATE=2013-08-22 17:45:49 +0900 BUILD_DATE=Fri Aug 23 20:48:48 KST 2013 BUILD=release TARGET_PLATFORM=pegasus-m400 MALI_PLATFORM=pegasus-m400 KDIR= OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=16 USING_UMP=y USING_PROFILING= USING_INTERNAL_PROFILING= USING_GPU_UTILIZATION=1 MALI_UPPER_HALF_SCHEDULING=1";} diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.c b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.c index 269e662..3651ce5 100644 --- a/drivers/media/video/samsung/mali/common/mali_block_allocator.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.c @@ -8,7 +8,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mali_kernel_common.h" -#include "mali_kernel_core.h" #include "mali_kernel_memory_engine.h" #include "mali_block_allocator.h" #include "mali_osk.h" @@ -320,6 +319,8 @@ static mali_physical_memory_allocation_result block_allocator_allocate_page_tabl alloc->next = NULL; /* Could potentially link many blocks together instead */ + _mali_osk_memset(block->mapping, 0, size); + result = MALI_MEM_ALLOC_FINISHED; } } diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.h b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.h index 6c6f13e..d3f0f9b 100644 --- a/drivers/media/video/samsung/mali/common/mali_block_allocator.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_block_allocator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c new file mode 100644 index 0000000..8b05496 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2012 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 "mali_broadcast.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" + +static const int bcast_unit_reg_size = 0x1000; +static const int bcast_unit_addr_broadcast_mask = 0x0; +static const int bcast_unit_addr_irq_override_mask = 0x4; + +struct mali_bcast_unit +{ + struct mali_hw_core hw_core; + u32 current_mask; +}; + +struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t *resource) +{ + struct mali_bcast_unit *bcast_unit = NULL; + + MALI_DEBUG_ASSERT_POINTER(resource); + MALI_DEBUG_PRINT(2, ("Mali Broadcast unit: Creating Mali Broadcast unit: %s\n", resource->description)); + + bcast_unit = _mali_osk_malloc(sizeof(struct mali_bcast_unit)); + if (NULL == bcast_unit) + { + MALI_PRINT_ERROR(("Mali Broadcast unit: Failed to allocate memory for Broadcast unit\n")); + return NULL; + } + + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&bcast_unit->hw_core, resource, bcast_unit_reg_size)) + { + bcast_unit->current_mask = 0; + mali_bcast_reset(bcast_unit); + + return bcast_unit; + } + else + { + MALI_PRINT_ERROR(("Mali Broadcast unit: Failed map broadcast unit\n")); + } + + _mali_osk_free(bcast_unit); + + return NULL; +} + +void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit) +{ + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + + mali_hw_core_delete(&bcast_unit->hw_core); + _mali_osk_free(bcast_unit); +} + +void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group) +{ + u32 bcast_id; + u32 broadcast_mask; + + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + MALI_DEBUG_ASSERT_POINTER(group); + + bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group)); + + broadcast_mask = bcast_unit->current_mask; + + broadcast_mask |= (bcast_id); /* add PP core to broadcast */ + broadcast_mask |= (bcast_id << 16); /* add MMU to broadcast */ + + /* store mask so we can restore on reset */ + bcast_unit->current_mask = broadcast_mask; +} + +void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group) +{ + u32 bcast_id; + u32 broadcast_mask; + + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + MALI_DEBUG_ASSERT_POINTER(group); + + bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group)); + + broadcast_mask = bcast_unit->current_mask; + + broadcast_mask &= ~((bcast_id << 16) | bcast_id); + + /* store mask so we can restore on reset */ + bcast_unit->current_mask = broadcast_mask; +} + +void mali_bcast_reset(struct mali_bcast_unit *bcast_unit) +{ + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + + /* set broadcast mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_broadcast_mask, + bcast_unit->current_mask); + + /* set IRQ override mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_irq_override_mask, + bcast_unit->current_mask & 0xFF); +} + +void mali_bcast_disable(struct mali_bcast_unit *bcast_unit) +{ + MALI_DEBUG_ASSERT_POINTER(bcast_unit); + + /* set broadcast mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_broadcast_mask, + 0x0); + + /* set IRQ override mask */ + mali_hw_core_register_write(&bcast_unit->hw_core, + bcast_unit_addr_irq_override_mask, + 0x0); +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h new file mode 100644 index 0000000..df5f2f9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_broadcast.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 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. + */ + +/* + * Interface for the broadcast unit on Mali-450. + * + * - Represents up to 8 × (MMU + PP) pairs. + * - Supports dynamically changing which (MMU + PP) pairs receive the broadcast by + * setting a mask. + */ + +#include "mali_hw_core.h" +#include "mali_group.h" + +struct mali_bcast_unit; + +struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t *resource); +void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit); + +/* Add a group to the list of (MMU + PP) pairs broadcasts go out to. */ +void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group); + +/* Remove a group to the list of (MMU + PP) pairs broadcasts go out to. */ +void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group); + +/* Re-set cached mask. This needs to be called after having been suspended. */ +void mali_bcast_reset(struct mali_bcast_unit *bcast_unit); + +/** + * Disable broadcast unit + * + * mali_bcast_enable must be called to re-enable the unit. Cores may not be + * added or removed when the unit is disabled. + */ +void mali_bcast_disable(struct mali_bcast_unit *bcast_unit); + +/** + * Re-enable broadcast unit + * + * This resets the masks to include the cores present when mali_bcast_disable was called. + */ +MALI_STATIC_INLINE void mali_bcast_enable(struct mali_bcast_unit *bcast_unit) +{ + mali_bcast_reset(bcast_unit); +} diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.c b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c index fcc51fa..0181663 100644 --- a/drivers/media/video/samsung/mali/common/mali_dlbu.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.c @@ -23,8 +23,6 @@ u32 mali_dlbu_phys_addr = 0; static mali_io_address mali_dlbu_cpu_addr = 0; -static u32 mali_dlbu_tile_position; - /** * DLBU register numbers * Used in the register read/write routines. @@ -86,7 +84,7 @@ struct mali_dlbu_core _mali_osk_errcode_t mali_dlbu_initialize(void) { - MALI_DEBUG_PRINT(2, ("Dynamic Load Balancing Unit initializing\n")); + MALI_DEBUG_PRINT(2, ("Mali DLBU: Initializing\n")); if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) { @@ -114,10 +112,9 @@ struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource) { if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) { + core->pp_cores_mask = 0; if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) { - mali_hw_core_register_write(&core->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR, MALI_DLB_VIRT_ADDR); - return core; } MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description)); @@ -136,150 +133,85 @@ struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource) void mali_dlbu_delete(struct mali_dlbu_core *dlbu) { + MALI_DEBUG_ASSERT_POINTER(dlbu); + mali_dlbu_reset(dlbu); mali_hw_core_delete(&dlbu->hw_core); _mali_osk_free(dlbu); } -void mali_dlbu_enable(struct mali_dlbu_core *dlbu) -{ - u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR); - - wval |= 0x1; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval); -} - -void mali_dlbu_disable(struct mali_dlbu_core *dlbu) -{ - u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR); - - wval |= (wval & 0xFFFFFFFE); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval); -} - -_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val) -{ - u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK); - - if((pp_core_enable < mali_pp_get_glob_num_pp_cores()) && ((0 == val) || (1 == val))) /* check for valid input parameters */ - { - if (val == 1) - { - val = (wval | (pp_core_enable <<= 0x1)); - } - if (val == 0) - { - val = (wval & ~(pp_core_enable << 0x1)); - } - wval |= val; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, wval); - dlbu->pp_cores_mask = wval; - - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu) -{ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); -} - -void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu) -{ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, 0x0); -} - -void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1) -{ - u32 wval = 0x0; - - /* write the framebuffer dimensions */ - wval = (16 << (u32)fb_ydim) | (u32)fb_xdim; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, wval); - - /* write the tile list configuration */ - wval = 0x0; - wval = (28 << (u32)blocksize) | (16 << (u32)ytilesize) | ((u32)xtilesize); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, wval); - - /* write the start tile position */ - wval = 0x0; - wval = (24 << (u32)ygr1 | (16 << (u32)xgr1) | 8 << (u32)ygr0) | (u32)xgr0; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, wval); -} - _mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu) { + u32 dlbu_registers[7]; _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; MALI_DEBUG_ASSERT_POINTER(dlbu); MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description)); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, mali_dlbu_phys_addr); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, 0x00); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, 0x00); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, 0x00); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, 0x00); + dlbu_registers[0] = mali_dlbu_phys_addr | 1; /* bit 0 enables the whole core */ + dlbu_registers[1] = MALI_DLBU_VIRT_ADDR; + dlbu_registers[2] = 0; + dlbu_registers[3] = 0; + dlbu_registers[4] = 0; + dlbu_registers[5] = 0; + dlbu_registers[6] = dlbu->pp_cores_mask; - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); + /* write reset values to core registers */ + mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, dlbu_registers, 7); err = _MALI_OSK_ERR_OK; return err; } -_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group) +void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu) { - _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; - u32 wval, rval; - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - - /* find the core id and set the mask */ - - if (NULL != pp_core) - { - wval = mali_pp_core_get_id(pp_core); - rval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK); - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, (wval << 0x1) | rval); - err = _MALI_OSK_ERR_OK; - } + MALI_DEBUG_ASSERT_POINTER(dlbu); - return err; + mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask); } -void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val) +void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group) { - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, val); + struct mali_pp_core *pp_core; + u32 bcast_id; + + MALI_DEBUG_ASSERT_POINTER( dlbu ); + MALI_DEBUG_ASSERT_POINTER( group ); + + pp_core = mali_group_get_pp_core(group); + bcast_id = mali_pp_core_get_bcast_id(pp_core); + + dlbu->pp_cores_mask |= bcast_id; + MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n", bcast_id , dlbu->pp_cores_mask)); } -void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu) +/* Remove a group from the DLBU */ +void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group) { - /* this function to implement (see documentation): - * 1) clear all bits in the enable register - * 2) wait until all PPs have finished - mali_pp_scheduler.c code - this done in interrupts call? - * 3) read the current tile position registers to get current tile positions - - * note that current tile position register is the same as start tile position - perhaps the name should be changed!!! */ + struct mali_pp_core *pp_core; + u32 bcast_id; + + MALI_DEBUG_ASSERT_POINTER( dlbu ); + MALI_DEBUG_ASSERT_POINTER( group ); - /* 1) */ - mali_dlbu_disable_all_pp_cores(dlbu); + pp_core = mali_group_get_pp_core(group); + bcast_id = mali_pp_core_get_bcast_id(pp_core); - /* 3) */ - mali_dlbu_tile_position = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS); + dlbu->pp_cores_mask &= ~bcast_id; + MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", bcast_id, dlbu->pp_cores_mask)); } -void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu) +/* Configure the DLBU for \a job. This needs to be done before the job is started on the groups in the DLBU. */ +void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job) { - /* this function to implement (see the document): - * 1) configure the dynamic load balancing unit as normal - * 2) set the current tile position registers as read when stopping the job - * 3) configure the PPs to start the job as normal - done by another part of the system - scheduler */ + u32 *registers; + MALI_DEBUG_ASSERT(job); + registers = mali_pp_job_get_dlbu_registers(job); + MALI_DEBUG_PRINT(4, ("Mali DLBU: Starting job\n")); - /* 1) */ - mali_dlbu_reset(dlbu); - /* ++ setup the needed values - see this */ + /* Writing 4 registers: + * DLBU registers except the first two (written once at DLBU initialisation / reset) and the PP_ENABLE_MASK register */ + mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4); - /* 2) */ - mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, mali_dlbu_tile_position); } diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.h b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h index e3c3b9d..b1a59d6 100644 --- a/drivers/media/video/samsung/mali/common/mali_dlbu.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_dlbu.h @@ -11,10 +11,12 @@ #ifndef __MALI_DLBU_H__ #define __MALI_DLBU_H__ +#define MALI_DLBU_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */ + #include "mali_osk.h" -#include "mali_group.h" -#define MALI_DLB_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */ +struct mali_pp_job; +struct mali_group; extern u32 mali_dlbu_phys_addr; @@ -26,20 +28,19 @@ void mali_dlbu_terminate(void); struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource); void mali_dlbu_delete(struct mali_dlbu_core *dlbu); -void mali_dlbu_enable(struct mali_dlbu_core *dlbu); -void mali_dlbu_disable(struct mali_dlbu_core *dlbu); - -_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val); -void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu); -void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu); - _mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu); -void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1); -_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group); -void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val); +void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group); +void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group); + +/** @brief Called to update HW after DLBU state changed + * + * This function must be called after \a mali_dlbu_add_group or \a + * mali_dlbu_remove_group to write the updated mask to hardware, unless the + * same is accomplished by calling \a mali_dlbu_reset. + */ +void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu); -void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu); -void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu); +void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job); #endif /* __MALI_DLBU_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp.c b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.c new file mode 100644 index 0000000..c2b01f9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2011-2012 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 "mali_gp.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "regs/mali_gp_regs.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +static struct mali_gp_core *mali_global_gp_core = NULL; + +/* Interrupt handlers */ +static void mali_gp_irq_probe_trigger(void *data); +static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data); + +struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group) +{ + struct mali_gp_core* core = NULL; + + MALI_DEBUG_ASSERT(NULL == mali_global_gp_core); + MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description)); + + core = _mali_osk_malloc(sizeof(struct mali_gp_core)); + if (NULL != core) + { + core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; + core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE)) + { + _mali_osk_errcode_t ret; + + ret = mali_gp_reset(core); + + if (_MALI_OSK_ERR_OK == ret) + { + ret = mali_group_add_gp_core(group, core); + if (_MALI_OSK_ERR_OK == ret) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + core->irq = _mali_osk_irq_init(resource->irq, + mali_group_upper_half_gp, + group, + mali_gp_irq_probe_trigger, + mali_gp_irq_probe_ack, + core, + "mali_gp_irq_handlers"); + if (NULL != core->irq) + { + MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core)); + mali_global_gp_core = core; + + return core; + } + else + { + MALI_PRINT_ERROR(("Mali GP: Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description)); + } + mali_group_remove_gp_core(group); + } + else + { + MALI_PRINT_ERROR(("Mali GP: Failed to add core %s to group\n", core->hw_core.description)); + } + } + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n")); + } + + return NULL; +} + +void mali_gp_delete(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + _mali_osk_irq_term(core->irq); + mali_hw_core_delete(&core->hw_core); + mali_global_gp_core = NULL; + _mali_osk_free(core); +} + +void mali_gp_stop_bus(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); +} + +_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core) +{ + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Send the stop bus command. */ + mali_gp_stop_bus(core); + + /* Wait for bus to be stopped */ + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) + { + break; + } + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description)); + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_gp_hard_reset(struct mali_gp_core *core) +{ + const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW; + const u32 reset_invalid_value = 0xC0FFE000; + const u32 reset_check_value = 0xC01A0000; + const u32 reset_default_value = 0; + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description)); + + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value); + if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register)) + { + break; + } + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n")); + } + + mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */ + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + +} + +void mali_gp_reset_async(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description)); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET); + +} + +_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core) +{ + int i; + u32 rawstat = 0; + + MALI_DEBUG_ASSERT_POINTER(core); + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + rawstat = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); + if (rawstat & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) + { + break; + } + } + + if (i == MALI_REG_POLL_COUNT_FAST) + { + MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, rawstat: 0x%08x\n", + core->hw_core.description, rawstat)); + return _MALI_OSK_ERR_FAULT; + } + + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core) +{ + mali_gp_reset_async(core); + return mali_gp_reset_wait(core); +} + +void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) +{ + u32 startcmd = 0; + u32 *frame_registers = mali_gp_job_get_frame_registers(job); + + core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job); + core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job); + + MALI_DEBUG_ASSERT_POINTER(core); + + if (mali_gp_job_has_vs_job(job)) + { + startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS; + } + + if (mali_gp_job_has_plbu_job(job)) + { + startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU; + } + + MALI_DEBUG_ASSERT(0 != startcmd); + + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME); + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); + } + + MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd)); + + /* Barrier to make sure the previous register write is finished */ + _mali_osk_write_mem_barrier(); + + /* This is the command that starts the core. */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); + + /* Barrier to make sure the previous register write is finished */ + _mali_osk_write_mem_barrier(); +} + +void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) +{ + u32 irq_readout; + + MALI_DEBUG_ASSERT_POINTER(core); + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); + + if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); + mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); + + MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); + _mali_osk_write_mem_barrier(); + } + /* + * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response. + * A timeout or a page fault on Mali-200 PP core can cause this behaviour. + */ +} + +u32 mali_gp_core_get_version(struct mali_gp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION); +} + +struct mali_gp_core *mali_gp_get_global_gp_core(void) +{ + return mali_global_gp_core; +} + +/* ------------- interrupt handling below ------------------ */ +static void mali_gp_irq_probe_trigger(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG); + _mali_osk_mem_barrier(); +} + +static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data) +{ + struct mali_gp_core *core = (struct mali_gp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); + if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout) + { + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + +/* ------ local helper functions below --------- */ +#if MALI_STATE_TRACKING +u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description); + + return n; +} +#endif + +void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend) +{ + u32 val0 = 0; + u32 val1 = 0; + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); + mali_gp_job_set_perf_counter_value0(job, val0); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(COUNTER_VP_0_C0, val0); +#endif + + } + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + mali_gp_job_set_perf_counter_value1(job, val1); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(COUNTER_VP_0_C1, val1); +#endif + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp.h b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.h new file mode 100644 index 0000000..2750c75 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011-2012 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_GP_H__ +#define __MALI_GP_H__ + +#include "mali_osk.h" +#include "mali_gp_job.h" +#include "mali_hw_core.h" +#include "regs/mali_gp_regs.h" + +struct mali_group; + +/** + * Definition of the GP core struct + * Used to track a GP core in the system. + */ +struct mali_gp_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + _mali_osk_irq_t *irq; /**< IRQ handler */ + u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ + u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ +}; + +_mali_osk_errcode_t mali_gp_initialize(void); +void mali_gp_terminate(void); + +struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group); +void mali_gp_delete(struct mali_gp_core *core); + +void mali_gp_stop_bus(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core); +void mali_gp_reset_async(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core); +void mali_gp_hard_reset(struct mali_gp_core *core); +_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core); + +void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job); +void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr); + +u32 mali_gp_core_get_version(struct mali_gp_core *core); + +struct mali_gp_core *mali_gp_get_global_gp_core(void); + +u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size); + +void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend); + +/*** Accessor functions ***/ +MALI_STATIC_INLINE const char *mali_gp_get_hw_core_desc(struct mali_gp_core *core) +{ + return core->hw_core.description; +} + +/*** Register reading/writing functions ***/ +MALI_STATIC_INLINE u32 mali_gp_get_int_stat(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); +} + +MALI_STATIC_INLINE void mali_gp_mask_all_interrupts(struct mali_gp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); +} + +MALI_STATIC_INLINE u32 mali_gp_read_rawstat(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED; +} + +MALI_STATIC_INLINE u32 mali_gp_read_core_status(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS); +} + +MALI_STATIC_INLINE void mali_gp_enable_interrupts(struct mali_gp_core *core, u32 irq_exceptions) +{ + /* Enable all interrupts, except those specified in irq_exceptions */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, + MALIGP2_REG_VAL_IRQ_MASK_USED & ~irq_exceptions); +} + +MALI_STATIC_INLINE u32 mali_gp_read_plbu_alloc_start_addr(struct mali_gp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR); +} + +#endif /* __MALI_GP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c new file mode 100644 index 0000000..dae68b1 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011-2012 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 "mali_gp_job.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_uk_types.h" + +static u32 gp_counter_src0 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ +static u32 gp_counter_src1 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id) +{ + struct mali_gp_job *job; + u32 perf_counter_flag; + + job = _mali_osk_malloc(sizeof(struct mali_gp_job)); + if (NULL != job) + { + job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); + if (NULL == job->finished_notification) + { + _mali_osk_free(job); + return NULL; + } + + job->oom_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); + if (NULL == job->oom_notification) + { + _mali_osk_notification_delete(job->finished_notification); + _mali_osk_free(job); + return NULL; + } + + if (0 != copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s))) + { + _mali_osk_notification_delete(job->finished_notification); + _mali_osk_notification_delete(job->oom_notification); + _mali_osk_free(job); + return NULL; + } + + perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); + + /* case when no counters came from user space + * so pass the debugfs / DS-5 provided global ones to the job object */ + if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) || + (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) + { + mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0()); + mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1()); + } + + _mali_osk_list_init(&job->list); + job->session = session; + job->id = id; + job->heap_current_addr = job->uargs.frame_registers[4]; + job->perf_counter_value0 = 0; + job->perf_counter_value1 = 0; + job->pid = _mali_osk_get_pid(); + job->tid = _mali_osk_get_tid(); + + return job; + } + + return NULL; +} + +void mali_gp_job_delete(struct mali_gp_job *job) +{ + + /* de-allocate the pre-allocated oom notifications */ + if (NULL != job->oom_notification) + { + _mali_osk_notification_delete(job->oom_notification); + job->oom_notification = NULL; + } + if (NULL != job->finished_notification) + { + _mali_osk_notification_delete(job->finished_notification); + job->finished_notification = NULL; + } + + _mali_osk_free(job); +} + +u32 mali_gp_job_get_gp_counter_src0(void) +{ + return gp_counter_src0; +} + +mali_bool mali_gp_job_set_gp_counter_src0(u32 counter) +{ + gp_counter_src0 = counter; + + return MALI_TRUE; +} + +u32 mali_gp_job_get_gp_counter_src1(void) +{ + return gp_counter_src1; +} + +mali_bool mali_gp_job_set_gp_counter_src1(u32 counter) +{ + gp_counter_src1 = counter; + + return MALI_TRUE; +} diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.h b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h index 9c29f1c..e021b9b 100644 --- a/drivers/media/video/samsung/mali/common/mali_gp_job.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_job.h @@ -17,32 +17,33 @@ #include "mali_session.h" /** - * The structure represends a GP job, including all sub-jobs - * (This struct unfortunatly needs to be public because of how the _mali_osk_list_* + * The structure represents a GP job, including all sub-jobs + * (This struct unfortunately needs to be public because of how the _mali_osk_list_* * mechanism works) */ struct mali_gp_job { _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ struct mali_session_data *session; /**< Session which submitted this job */ + _mali_uk_gp_start_job_s uargs; /**< Arguments from user space */ u32 id; /**< identifier for this job in kernel space (sequential numbering) */ - u32 user_id; /**< identifier for the job in user space */ - u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< core specific registers associated with this job, see ARM DDI0415A */ u32 heap_current_addr; /**< Holds the current HEAP address when the job has completed */ - u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ - u32 perf_counter_src0; /**< source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_src1; /**< source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ u32 perf_counter_value0; /**< Value of performance counter 0 (to be returned to user space) */ u32 perf_counter_value1; /**< Value of performance counter 1 (to be returned to user space) */ u32 pid; /**< Process ID of submitting process */ u32 tid; /**< Thread ID of submitting thread */ - u32 frame_builder_id; /**< id of the originating frame builder */ - u32 flush_id; /**< flush id within the originating frame builder */ + _mali_osk_notification_t *finished_notification; /**< Notification sent back to userspace on job complete */ + _mali_osk_notification_t *oom_notification; /**< Notification sent back to userspace on OOM */ }; -struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id); +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id); void mali_gp_job_delete(struct mali_gp_job *job); +u32 mali_gp_job_get_gp_counter_src0(void); +mali_bool mali_gp_job_set_gp_counter_src0(u32 counter); +u32 mali_gp_job_get_gp_counter_src1(void); +mali_bool mali_gp_job_set_gp_counter_src1(u32 counter); + MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) { return (NULL == job) ? 0 : job->id; @@ -50,22 +51,32 @@ MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job) { - return job->user_id; + return job->uargs.user_job_ptr; } MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job) { - return job->frame_builder_id; + return job->uargs.frame_builder_id; } MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job) { - return job->flush_id; + return job->uargs.flush_id; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_pid(struct mali_gp_job *job) +{ + return job->pid; +} + +MALI_STATIC_INLINE u32 mali_gp_job_get_tid(struct mali_gp_job *job) +{ + return job->tid; } MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job) { - return job->frame_registers; + return job->uargs.frame_registers; } MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job) @@ -75,12 +86,12 @@ MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job) { - return (job->frame_registers[0] != job->frame_registers[1]) ? MALI_TRUE : MALI_FALSE; + return (job->uargs.frame_registers[0] != job->uargs.frame_registers[1]) ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job) { - return (job->frame_registers[2] != job->frame_registers[3]) ? MALI_TRUE : MALI_FALSE; + return (job->uargs.frame_registers[2] != job->uargs.frame_registers[3]) ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job) @@ -95,17 +106,17 @@ MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *jo MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job) { - return job->perf_counter_flag; + return job->uargs.perf_counter_flag; } MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job) { - return job->perf_counter_src0; + return job->uargs.perf_counter_src0; } MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job) { - return job->perf_counter_src1; + return job->uargs.perf_counter_src1; } MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job) @@ -118,6 +129,16 @@ MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *j return job->perf_counter_value1; } +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src0(struct mali_gp_job *job, u32 src) +{ + job->uargs.perf_counter_src0 = src; +} + +MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src1(struct mali_gp_job *job, u32 src) +{ + job->uargs.perf_counter_src1 = src; +} + MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value) { job->perf_counter_value0 = value; diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c new file mode 100644 index 0000000..ebbc281 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.c @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2012 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 "mali_gp_scheduler.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_scheduler.h" +#include "mali_gp.h" +#include "mali_gp_job.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_kernel_utilization.h" +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) +#include <linux/sched.h> +#include <trace/events/gpu.h> +#endif + +enum mali_gp_slot_state +{ + MALI_GP_SLOT_STATE_IDLE, + MALI_GP_SLOT_STATE_WORKING, + MALI_GP_SLOT_STATE_DISABLED, +}; + +/* A render slot is an entity which jobs can be scheduled onto */ +struct mali_gp_slot +{ + struct mali_group *group; + /* + * We keep track of the state here as well as in the group object + * so we don't need to take the group lock so often (and also avoid clutter with the working lock) + */ + enum mali_gp_slot_state state; + u32 returned_cookie; +}; + +static u32 gp_version = 0; +static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ +static struct mali_gp_slot slot; + +/* Variables to allow safe pausing of the scheduler */ +static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL; +static u32 pause_count = 0; + +static mali_bool mali_gp_scheduler_is_suspended(void); +static void mali_gp_scheduler_job_queued(void); +static void mali_gp_scheduler_job_completed(void); + +static _mali_osk_lock_t *gp_scheduler_lock = NULL; +/* Contains tid of thread that locked the scheduler or 0, if not locked */ + +_mali_osk_errcode_t mali_gp_scheduler_initialize(void) +{ + u32 num_groups; + u32 i; + + _MALI_OSK_INIT_LIST_HEAD(&job_queue); + + gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + if (NULL == gp_scheduler_lock) + { + return _MALI_OSK_ERR_NOMEM; + } + + gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); + if (NULL == gp_scheduler_working_wait_queue) + { + _mali_osk_lock_term(gp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + /* Find all the available GP cores */ + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) + { + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) + { + if (0 == gp_version) + { + /* Retrieve GP version */ + gp_version = mali_gp_core_get_version(gp_core); + } + slot.group = group; + slot.state = MALI_GP_SLOT_STATE_IDLE; + break; /* There is only one GP, no point in looking for more */ + } + } + + return _MALI_OSK_ERR_OK; +} + +void mali_gp_scheduler_terminate(void) +{ + MALI_DEBUG_ASSERT( MALI_GP_SLOT_STATE_IDLE == slot.state + || MALI_GP_SLOT_STATE_DISABLED == slot.state); + MALI_DEBUG_ASSERT_POINTER(slot.group); + mali_group_delete(slot.group); + + _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue); + _mali_osk_lock_term(gp_scheduler_lock); +} + +MALI_STATIC_INLINE void mali_gp_scheduler_lock(void) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n")); +} + +MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void) +{ + MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n")); + _mali_osk_lock_signal(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +MALI_STATIC_INLINE void mali_gp_scheduler_assert_locked(void) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); +} +#define MALI_ASSERT_GP_SCHEDULER_LOCKED() mali_gp_scheduler_assert_locked() +#else +#define MALI_ASSERT_GP_SCHEDULER_LOCKED() +#endif + +static void mali_gp_scheduler_schedule(void) +{ + struct mali_gp_job *job; + + mali_gp_scheduler_lock(); + + if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) + { + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", + pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); + mali_gp_scheduler_unlock(); + return; /* Nothing to do, so early out */ + } + + /* Get (and remove) next job in queue */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); + _mali_osk_list_del(&job->list); + + /* Mark slot as busy */ + slot.state = MALI_GP_SLOT_STATE_WORKING; + + mali_gp_scheduler_unlock(); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); + + mali_group_lock(slot.group); + mali_group_start_gp_job(slot.group, job); + mali_group_unlock(slot.group); +} + +static void mali_gp_scheduler_schedule_on_group(struct mali_group *group) +{ + struct mali_gp_job *job; + + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); + + if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) + { + mali_gp_scheduler_unlock(); + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", + pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(), 0, 0, 0); +#endif + return; /* Nothing to do, so early out */ + } + + /* Get (and remove) next job in queue */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); + _mali_osk_list_del(&job->list); + + /* Mark slot as busy */ + slot.state = MALI_GP_SLOT_STATE_WORKING; + + mali_gp_scheduler_unlock(); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); + + mali_group_start_gp_job(slot.group, job); +} + +static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) +{ + _mali_uk_gp_job_finished_s *jobres = job->finished_notification->result_buffer; + _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ + jobres->user_job_ptr = mali_gp_job_get_user_id(job); + if (MALI_TRUE == success) + { + jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; + } + else + { + jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; + } + + jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); + jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); + jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); + + mali_session_send_notification(mali_gp_job_get_session(job), job->finished_notification); + job->finished_notification = NULL; + + mali_gp_job_delete(job); +} + +void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success) +{ + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure")); + + mali_gp_scheduler_return_job_to_user(job, success); + + mali_gp_scheduler_lock(); + + /* Mark slot as idle again */ + slot.state = MALI_GP_SLOT_STATE_IDLE; + + /* If paused, then this was the last job, so wake up sleeping workers */ + if (pause_count > 0) + { + _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue); + } + + mali_gp_scheduler_schedule_on_group(group); + + /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ + mali_gp_scheduler_job_completed(); +} + +void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) +{ + _mali_uk_gp_job_suspended_s * jobres; + _mali_osk_notification_t * notification; + + mali_gp_scheduler_lock(); + + notification = job->oom_notification; + job->oom_notification = NULL; + slot.returned_cookie = mali_gp_job_get_id(job); + + jobres = (_mali_uk_gp_job_suspended_s *)notification->result_buffer; + jobres->user_job_ptr = mali_gp_job_get_user_id(job); + jobres->cookie = mali_gp_job_get_id(job); + + mali_gp_scheduler_unlock(); + + jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; + + mali_session_send_notification(mali_gp_job_get_session(job), notification); + + /* + * If this function failed, then we could return the job to user space right away, + * but there is a job timer anyway that will do that eventually. + * This is not exactly a common case anyway. + */ +} + +void mali_gp_scheduler_suspend(void) +{ + mali_gp_scheduler_lock(); + pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ + mali_gp_scheduler_unlock(); + + _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended); +} + +void mali_gp_scheduler_resume(void) +{ + mali_gp_scheduler_lock(); + pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ + mali_gp_scheduler_unlock(); + if (0 == pause_count) + { + mali_gp_scheduler_schedule(); + } +} + +_mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *uargs) +{ + struct mali_session_data *session; + struct mali_gp_job *job; + + MALI_DEBUG_ASSERT_POINTER(uargs); + MALI_DEBUG_ASSERT_POINTER(ctx); + + session = (struct mali_session_data*)ctx; + + job = mali_gp_job_create(session, uargs, mali_scheduler_get_new_id()); + if (NULL == job) + { + return _MALI_OSK_ERR_NOMEM; + } + +#if PROFILING_SKIP_PP_AND_GP_JOBS +#warning GP jobs will not be executed + mali_gp_scheduler_return_job_to_user(job, MALI_TRUE); + return _MALI_OSK_ERR_OK; +#endif + +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_job_enqueue(mali_gp_job_get_tid(job), mali_gp_job_get_id(job), "GP"); +#endif + + mali_gp_scheduler_job_queued(); + + mali_gp_scheduler_lock(); + _mali_osk_list_addtail(&job->list, &job_queue); + mali_gp_scheduler_unlock(); + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job)); + + mali_gp_scheduler_schedule(); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + args->number_of_cores = 1; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + args->version = gp_version; + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args) +{ + struct mali_session_data *session; + struct mali_gp_job *resumed_job; + _mali_osk_notification_t *new_notification = 0; + + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + session = (struct mali_session_data*)args->ctx; + if (NULL == session) + { + return _MALI_OSK_ERR_FAULT; + } + + if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) + { + new_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); + + if (NULL == new_notification) + { + MALI_PRINT_ERROR(("Mali GP scheduler: Failed to allocate notification object. Will abort GP job.\n")); + mali_group_lock(slot.group); + mali_group_abort_gp_job(slot.group, args->cookie); + mali_group_unlock(slot.group); + return _MALI_OSK_ERR_FAULT; + } + } + + mali_group_lock(slot.group); + + if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) + { + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1])); + + resumed_job = mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]); + if (NULL != resumed_job) + { + resumed_job->oom_notification = new_notification; + mali_group_unlock(slot.group); + return _MALI_OSK_ERR_OK; + } + else + { + mali_group_unlock(slot.group); + _mali_osk_notification_delete(new_notification); + return _MALI_OSK_ERR_FAULT; + } + } + + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie)); + mali_group_abort_gp_job(slot.group, args->cookie); + mali_group_unlock(slot.group); + return _MALI_OSK_ERR_OK; +} + +void mali_gp_scheduler_abort_session(struct mali_session_data *session) +{ + struct mali_gp_job *job, *tmp; + + mali_gp_scheduler_lock(); + MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session)); + + /* Check queue for jobs and remove */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) + { + if (mali_gp_job_get_session(job) == session) + { + MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job)); + _mali_osk_list_del(&(job->list)); + mali_gp_job_delete(job); + + mali_gp_scheduler_job_completed(); + } + } + + mali_gp_scheduler_unlock(); + + mali_group_abort_session(slot.group, session); +} + +static mali_bool mali_gp_scheduler_is_suspended(void) +{ + mali_bool ret; + + mali_gp_scheduler_lock(); + ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE; + mali_gp_scheduler_unlock(); + + return ret; +} + + +#if MALI_STATE_TRACKING +u32 mali_gp_scheduler_dump_state(char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "GP\n"); + n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); + + n += mali_group_dump_state(slot.group, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + + return n; +} +#endif + +void mali_gp_scheduler_reset_all_groups(void) +{ + if (NULL != slot.group) + { + mali_group_lock(slot.group); + mali_group_reset(slot.group); + mali_group_unlock(slot.group); + } +} + +void mali_gp_scheduler_zap_all_active(struct mali_session_data *session) +{ + if (NULL != slot.group) + { + mali_group_zap_session(slot.group, session); + } +} + +void mali_gp_scheduler_enable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT(slot.group == group); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: enabling gp group %p\n", group)); + + mali_group_lock(group); + + if (MALI_GROUP_STATE_DISABLED != group->state) + { + mali_group_unlock(group); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: gp group %p already enabled\n", group)); + return; + } + + mali_gp_scheduler_lock(); + + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_DISABLED == slot.state); + slot.state = MALI_GP_SLOT_STATE_IDLE; + group->state = MALI_GROUP_STATE_IDLE; + + mali_group_power_on_group(group); + mali_group_reset(group); + + mali_gp_scheduler_unlock(); + mali_group_unlock(group); + + /* Pick up any jobs that might have been queued while the GP group was disabled. */ + mali_gp_scheduler_schedule(); +} + +void mali_gp_scheduler_disable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT(slot.group == group); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: disabling gp group %p\n", group)); + + mali_gp_scheduler_suspend(); + mali_group_lock(group); + mali_gp_scheduler_lock(); + + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_DISABLED == slot.state); + MALI_DEBUG_PRINT(2, ("Mali GP scheduler: gp group %p already disabled\n", group)); + } + else + { + MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_IDLE == slot.state); + slot.state = MALI_GP_SLOT_STATE_DISABLED; + group->state = MALI_GROUP_STATE_DISABLED; + + mali_group_power_off_group(group); + } + + mali_gp_scheduler_unlock(); + mali_group_unlock(group); + mali_gp_scheduler_resume(); +} + +static void mali_gp_scheduler_job_queued(void) +{ + /* We hold a PM reference for every job we hold queued (and running) */ + _mali_osk_pm_dev_ref_add(); + + if (mali_utilization_enabled()) + { + /* + * We cheat a little bit by counting the PP as busy from the time a GP job is queued. + * This will be fine because we only loose the tiny idle gap between jobs, but + * we will instead get less utilization work to do (less locks taken) + */ + mali_utilization_gp_start(); + } +} + +static void mali_gp_scheduler_job_completed(void) +{ + /* Release the PM reference we got in the mali_gp_scheduler_job_queued() function */ + _mali_osk_pm_dev_ref_dec(); + + if (mali_utilization_enabled()) + { + mali_utilization_gp_end(); + } +} diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.h index ef58509..7f61a78 100644 --- a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_gp_scheduler.h @@ -12,13 +12,12 @@ #define __MALI_GP_SCHEDULER_H__ #include "mali_osk.h" -#include "mali_cluster.h" #include "mali_gp_job.h" +#include "mali_group.h" _mali_osk_errcode_t mali_gp_scheduler_initialize(void); void mali_gp_scheduler_terminate(void); -void mali_gp_scheduler_do_schedule(void); void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success); void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job); void mali_gp_scheduler_abort_session(struct mali_session_data *session); @@ -27,4 +26,22 @@ u32 mali_gp_scheduler_dump_state(char *buf, u32 size); void mali_gp_scheduler_suspend(void); void mali_gp_scheduler_resume(void); +/** + * @brief Reset all groups + * + * This function resets all groups known by the GP scheuduler. This must be + * called after the Mali HW has been powered on in order to reset the HW. + */ +void mali_gp_scheduler_reset_all_groups(void); + +/** + * @brief Zap TLB on all groups with \a session active + * + * The scheculer will zap the session on all groups it owns. + */ +void mali_gp_scheduler_zap_all_active(struct mali_session_data *session); + +void mali_gp_scheduler_enable_group(struct mali_group *group); +void mali_gp_scheduler_disable_group(struct mali_group *group); + #endif /* __MALI_GP_SCHEDULER_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_group.c b/drivers/gpu/mali400/r3p2/mali/common/mali_group.c new file mode 100644 index 0000000..070879e --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_group.c @@ -0,0 +1,2046 @@ +/* + * Copyright (C) 2011-2012 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 "mali_kernel_common.h" +#include "mali_group.h" +#include "mali_osk.h" +#include "mali_l2_cache.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_mmu.h" +#include "mali_dlbu.h" +#include "mali_broadcast.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_kernel_core.h" +#include "mali_osk_profiling.h" +#include "mali_pm_domain.h" +#include "mali_pm.h" +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) +#include <linux/sched.h> +#include <trace/events/gpu.h> +#endif + + +static void mali_group_bottom_half_mmu(void *data); +static void mali_group_bottom_half_gp(void *data); +static void mali_group_bottom_half_pp(void *data); + +static void mali_group_timeout(void *data); +static void mali_group_reset_pp(struct mali_group *group); +static void mali_group_reset_mmu(struct mali_group *group); + +#if defined(CONFIG_MALI400_PROFILING) +static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num); +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + +/* + * The group object is the most important object in the device driver, + * and acts as the center of many HW operations. + * The reason for this is that operations on the MMU will affect all + * cores connected to this MMU (a group is defined by the MMU and the + * cores which are connected to this). + * The group lock is thus the most important lock, followed by the + * GP and PP scheduler locks. They must be taken in the following + * order: + * GP/PP lock first, then group lock(s). + */ + +static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS] = { NULL, }; +static u32 mali_global_num_groups = 0; + +enum mali_group_activate_pd_status +{ + MALI_GROUP_ACTIVATE_PD_STATUS_FAILED, + MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD, + MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD, +}; + +/* local helper functions */ +static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session); +static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session); +static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session); +static void mali_group_recovery_reset(struct mali_group *group); +static void mali_group_mmu_page_fault(struct mali_group *group); + +static void mali_group_post_process_job_pp(struct mali_group *group); +static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend); + +void mali_group_lock(struct mali_group *group) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group)); +} + +void mali_group_unlock(struct mali_group *group) +{ + MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group)); + _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW); +} + +#ifdef DEBUG +void mali_group_assert_locked(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); +} +#endif + + +struct mali_group *mali_group_create(struct mali_l2_cache_core *core, struct mali_dlbu_core *dlbu, struct mali_bcast_unit *bcast) +{ + struct mali_group *group = NULL; + _mali_osk_lock_flags_t lock_flags; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#else + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#endif + + if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS) + { + MALI_PRINT_ERROR(("Mali group: Too many group objects created\n")); + return NULL; + } + + group = _mali_osk_calloc(1, sizeof(struct mali_group)); + if (NULL != group) + { + group->timeout_timer = _mali_osk_timer_init(); + + if (NULL != group->timeout_timer) + { + _mali_osk_lock_order_t order; + _mali_osk_timer_setcallback(group->timeout_timer, mali_group_timeout, (void *)group); + + if (NULL != dlbu) + { + order = _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL; + } + else + { + order = _MALI_OSK_LOCK_ORDER_GROUP; + } + + group->lock = _mali_osk_lock_init(lock_flags, 0, order); + if (NULL != group->lock) + { + group->l2_cache_core[0] = core; + group->session = NULL; + group->page_dir_ref_count = 0; + group->power_is_on = MALI_TRUE; + group->state = MALI_GROUP_STATE_IDLE; + _mali_osk_list_init(&group->group_list); + _mali_osk_list_init(&group->pp_scheduler_list); + group->parent_group = NULL; + group->l2_cache_core_ref_count[0] = 0; + group->l2_cache_core_ref_count[1] = 0; + group->bcast_core = bcast; + group->dlbu_core = dlbu; + + mali_global_groups[mali_global_num_groups] = group; + mali_global_num_groups++; + + return group; + } + _mali_osk_timer_term(group->timeout_timer); + } + _mali_osk_free(group); + } + + return NULL; +} + +_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core) +{ + /* This group object now owns the MMU core object */ + group->mmu= mmu_core; + group->bottom_half_work_mmu = _mali_osk_wq_create_work(mali_group_bottom_half_mmu, group); + if (NULL == group->bottom_half_work_mmu) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_group_remove_mmu_core(struct mali_group *group) +{ + /* This group object no longer owns the MMU core object */ + group->mmu = NULL; + if (NULL != group->bottom_half_work_mmu) + { + _mali_osk_wq_delete_work(group->bottom_half_work_mmu); + } +} + +_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core) +{ + /* This group object now owns the GP core object */ + group->gp_core = gp_core; + group->bottom_half_work_gp = _mali_osk_wq_create_work(mali_group_bottom_half_gp, group); + if (NULL == group->bottom_half_work_gp) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_group_remove_gp_core(struct mali_group *group) +{ + /* This group object no longer owns the GP core object */ + group->gp_core = NULL; + if (NULL != group->bottom_half_work_gp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_gp); + } +} + +_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core) +{ + /* This group object now owns the PP core object */ + group->pp_core = pp_core; + group->bottom_half_work_pp = _mali_osk_wq_create_work(mali_group_bottom_half_pp, group); + if (NULL == group->bottom_half_work_pp) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +void mali_group_remove_pp_core(struct mali_group *group) +{ + /* This group object no longer owns the PP core object */ + group->pp_core = NULL; + if (NULL != group->bottom_half_work_pp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_pp); + } +} + +void mali_group_set_pm_domain(struct mali_group *group, struct mali_pm_domain *domain) +{ + group->pm_domain = domain; +} + +void mali_group_delete(struct mali_group *group) +{ + u32 i; + + MALI_DEBUG_PRINT(4, ("Deleting group %p\n", group)); + + MALI_DEBUG_ASSERT(NULL == group->parent_group); + + /* Delete the resources that this group owns */ + if (NULL != group->gp_core) + { + mali_gp_delete(group->gp_core); + } + + if (NULL != group->pp_core) + { + mali_pp_delete(group->pp_core); + } + + if (NULL != group->mmu) + { + mali_mmu_delete(group->mmu); + } + + if (mali_group_is_virtual(group)) + { + /* Remove all groups from virtual group */ + struct mali_group *child; + struct mali_group *temp; + + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + child->parent_group = NULL; + mali_group_delete(child); + } + + mali_dlbu_delete(group->dlbu_core); + + if (NULL != group->bcast_core) + { + mali_bcast_unit_delete(group->bcast_core); + } + } + + for (i = 0; i < mali_global_num_groups; i++) + { + if (mali_global_groups[i] == group) + { + mali_global_groups[i] = NULL; + mali_global_num_groups--; + + if (i != mali_global_num_groups) + { + /* We removed a group from the middle of the array -- move the last + * group to the current position to close the gap */ + mali_global_groups[i] = mali_global_groups[mali_global_num_groups]; + mali_global_groups[mali_global_num_groups] = NULL; + } + + break; + } + } + + if (NULL != group->timeout_timer) + { + _mali_osk_timer_del(group->timeout_timer); + _mali_osk_timer_term(group->timeout_timer); + } + + if (NULL != group->bottom_half_work_mmu) + { + _mali_osk_wq_delete_work(group->bottom_half_work_mmu); + } + + if (NULL != group->bottom_half_work_gp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_gp); + } + + if (NULL != group->bottom_half_work_pp) + { + _mali_osk_wq_delete_work(group->bottom_half_work_pp); + } + + _mali_osk_lock_term(group->lock); + + _mali_osk_free(group); +} + +MALI_DEBUG_CODE(static void mali_group_print_virtual(struct mali_group *vgroup) +{ + u32 i; + struct mali_group *group; + struct mali_group *temp; + + MALI_DEBUG_PRINT(4, ("Virtual group %p\n", vgroup)); + MALI_DEBUG_PRINT(4, ("l2_cache_core[0] = %p, ref = %d\n", vgroup->l2_cache_core[0], vgroup->l2_cache_core_ref_count[0])); + MALI_DEBUG_PRINT(4, ("l2_cache_core[1] = %p, ref = %d\n", vgroup->l2_cache_core[1], vgroup->l2_cache_core_ref_count[1])); + + i = 0; + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &vgroup->group_list, struct mali_group, group_list) + { + MALI_DEBUG_PRINT(4, ("[%d] %p, l2_cache_core[0] = %p\n", i, group, group->l2_cache_core[0])); + i++; + } +}) + +/** + * @brief Add child group to virtual group parent + * + * Before calling this function, child must have it's state set to JOINING_VIRTUAL + * to ensure it's not touched during the transition period. When this function returns, + * child's state will be IN_VIRTUAL. + */ +void mali_group_add_group(struct mali_group *parent, struct mali_group *child, mali_bool update_hw) +{ + mali_bool found; + u32 i; + struct mali_session_data *child_session; + + MALI_DEBUG_PRINT(3, ("Adding group %p to virtual group %p\n", child, parent)); + + MALI_ASSERT_GROUP_LOCKED(parent); + + MALI_DEBUG_ASSERT(mali_group_is_virtual(parent)); + MALI_DEBUG_ASSERT(!mali_group_is_virtual(child)); + MALI_DEBUG_ASSERT(NULL == child->parent_group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_JOINING_VIRTUAL == child->state); + + _mali_osk_list_addtail(&child->group_list, &parent->group_list); + + child->state = MALI_GROUP_STATE_IN_VIRTUAL; + child->parent_group = parent; + + MALI_DEBUG_ASSERT_POINTER(child->l2_cache_core[0]); + + MALI_DEBUG_PRINT(4, ("parent->l2_cache_core: [0] = %p, [1] = %p\n", parent->l2_cache_core[0], parent->l2_cache_core[1])); + MALI_DEBUG_PRINT(4, ("child->l2_cache_core: [0] = %p, [1] = %p\n", child->l2_cache_core[0], child->l2_cache_core[1])); + + /* Keep track of the L2 cache cores of child groups */ + found = MALI_FALSE; + for (i = 0; i < 2; i++) + { + if (parent->l2_cache_core[i] == child->l2_cache_core[0]) + { + MALI_DEBUG_ASSERT(parent->l2_cache_core_ref_count[i] > 0); + parent->l2_cache_core_ref_count[i]++; + found = MALI_TRUE; + } + } + + if (!found) + { + /* First time we see this L2 cache, add it to our list */ + i = (NULL == parent->l2_cache_core[0]) ? 0 : 1; + + MALI_DEBUG_PRINT(4, ("First time we see l2_cache %p. Adding to [%d] = %p\n", child->l2_cache_core[0], i, parent->l2_cache_core[i])); + + MALI_DEBUG_ASSERT(NULL == parent->l2_cache_core[i]); + + parent->l2_cache_core[i] = child->l2_cache_core[0]; + parent->l2_cache_core_ref_count[i]++; + } + + /* Update Broadcast Unit and DLBU */ + mali_bcast_add_group(parent->bcast_core, child); + mali_dlbu_add_group(parent->dlbu_core, child); + + child_session = child->session; + child->session = NULL; + + /* Above this comment, only software state is updated and the HW is not + * touched. Now, check if Mali is powered and skip the rest if it isn't + * powered. + */ + + if (!update_hw) + { + MALI_DEBUG_CODE(mali_group_print_virtual(parent)); + return; + } + + /* Update MMU */ + MALI_DEBUG_ASSERT(0 == child->page_dir_ref_count); + if (parent->session == child_session) + { + mali_mmu_zap_tlb(child->mmu); + } + else + { + if (NULL == parent->session) + { + mali_mmu_activate_empty_page_directory(child->mmu); + } + else + { + + mali_bool activate_success = mali_mmu_activate_page_directory(child->mmu, + mali_session_get_page_directory(parent->session)); + MALI_DEBUG_ASSERT(activate_success); + MALI_IGNORE(activate_success); + } + } + + /* Update HW only if power is on */ + mali_bcast_reset(parent->bcast_core); + mali_dlbu_update_mask(parent->dlbu_core); + + /* Start job on child when parent is active */ + if (NULL != parent->pp_running_job) + { + struct mali_pp_job *job = parent->pp_running_job; + MALI_DEBUG_PRINT(3, ("Group %x joining running job %d on virtual group %x\n", + child, mali_pp_job_get_id(job), parent)); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING == parent->state); + mali_pp_job_start(child->pp_core, job, mali_pp_core_get_id(child->pp_core), MALI_TRUE); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL, + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + } + + MALI_DEBUG_CODE(mali_group_print_virtual(parent);) +} + +/** + * @brief Remove child group from virtual group parent + * + * After the child is removed, it's state will be LEAVING_VIRTUAL and must be set + * to IDLE before it can be used. + */ +void mali_group_remove_group(struct mali_group *parent, struct mali_group *child) +{ + u32 i; + + MALI_ASSERT_GROUP_LOCKED(parent); + + MALI_DEBUG_PRINT(3, ("Removing group %p from virtual group %p\n", child, parent)); + + MALI_DEBUG_ASSERT(mali_group_is_virtual(parent)); + MALI_DEBUG_ASSERT(!mali_group_is_virtual(child)); + MALI_DEBUG_ASSERT(parent == child->parent_group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IN_VIRTUAL == child->state); + /* Removing groups while running is not yet supported. */ + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == parent->state); + + mali_group_lock(child); + + /* Update Broadcast Unit and DLBU */ + mali_bcast_remove_group(parent->bcast_core, child); + mali_dlbu_remove_group(parent->dlbu_core, child); + + /* Update HW only if power is on */ + if (mali_pm_is_power_on()) + { + mali_bcast_reset(parent->bcast_core); + mali_dlbu_update_mask(parent->dlbu_core); + } + + _mali_osk_list_delinit(&child->group_list); + + child->session = parent->session; + child->parent_group = NULL; + child->state = MALI_GROUP_STATE_LEAVING_VIRTUAL; + + /* Keep track of the L2 cache cores of child groups */ + i = (child->l2_cache_core[0] == parent->l2_cache_core[0]) ? 0 : 1; + + MALI_DEBUG_ASSERT(child->l2_cache_core[0] == parent->l2_cache_core[i]); + + parent->l2_cache_core_ref_count[i]--; + + if (parent->l2_cache_core_ref_count[i] == 0) + { + parent->l2_cache_core[i] = NULL; + } + + MALI_DEBUG_CODE(mali_group_print_virtual(parent)); + + mali_group_unlock(child); +} + +struct mali_group *mali_group_acquire_group(struct mali_group *parent) +{ + struct mali_group *child; + + MALI_ASSERT_GROUP_LOCKED(parent); + + MALI_DEBUG_ASSERT(mali_group_is_virtual(parent)); + MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&parent->group_list)); + + child = _MALI_OSK_LIST_ENTRY(parent->group_list.prev, struct mali_group, group_list); + + mali_group_remove_group(parent, child); + + return child; +} + +void mali_group_reset(struct mali_group *group) +{ + /* + * This function should not be used to abort jobs, + * currently only called during insmod and PM resume + */ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT(NULL == group->gp_running_job); + MALI_DEBUG_ASSERT(NULL == group->pp_running_job); + + group->session = NULL; + + if (NULL != group->dlbu_core) + { + mali_dlbu_reset(group->dlbu_core); + } + + if (NULL != group->bcast_core) + { + mali_bcast_reset(group->bcast_core); + } + + if (NULL != group->mmu) + { + mali_group_reset_mmu(group); + } + + if (NULL != group->gp_core) + { + mali_gp_reset(group->gp_core); + } + + if (NULL != group->pp_core) + { + mali_group_reset_pp(group); + } +} + +struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group) +{ + return group->gp_core; +} + +struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group) +{ + return group->pp_core; +} + +void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job) +{ + struct mali_session_data *session; + enum mali_group_activate_pd_status activate_status; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state); + + session = mali_gp_job_get_session(job); + + if (NULL != group->l2_cache_core[0]) + { + mali_l2_cache_invalidate_conditional(group->l2_cache_core[0], mali_gp_job_get_id(job)); + } + + activate_status = mali_group_activate_page_directory(group, session); + if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) + { + /* if session is NOT kept Zapping is done as part of session switch */ + if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) + { + mali_mmu_zap_tlb_without_stall(group->mmu); + } + mali_gp_job_start(group->gp_core, job); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START | + MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), + mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0); +#if defined(CONFIG_MALI400_PROFILING) + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + mali_group_report_l2_cache_counters_per_core(group, 0); +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(), + mali_gp_job_get_pid(job), 0, mali_gp_job_get_id(job)); +#endif + group->gp_running_job = job; + group->state = MALI_GROUP_STATE_WORKING; + + } + + /* Setup the timeout timer value and save the job id for the job running on the gp core */ + _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); +} + +void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job) +{ + struct mali_session_data *session; + enum mali_group_activate_pd_status activate_status; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state); + + session = mali_pp_job_get_session(job); + + if (NULL != group->l2_cache_core[0]) + { + mali_l2_cache_invalidate_conditional(group->l2_cache_core[0], mali_pp_job_get_id(job)); + } + + if (NULL != group->l2_cache_core[1]) + { + mali_l2_cache_invalidate_conditional(group->l2_cache_core[1], mali_pp_job_get_id(job)); + } + + activate_status = mali_group_activate_page_directory(group, session); + if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) + { + /* if session is NOT kept Zapping is done as part of session switch */ + if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) + { + MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n")); + mali_mmu_zap_tlb_without_stall(group->mmu); + } + + if (mali_group_is_virtual(group)) + { + struct mali_group *child; + struct mali_group *temp; + u32 core_num = 0; + + /* Configure DLBU for the job */ + mali_dlbu_config_job(group->dlbu_core, job); + + /* Write stack address for each child group */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_write_addr_stack(child->pp_core, job); + core_num++; + } + } + + mali_pp_job_start(group->pp_core, job, sub_job, MALI_FALSE); + + /* if the group is virtual, loop through physical groups which belong to this group + * and call profiling events for its cores as virtual */ + if (MALI_TRUE == mali_group_is_virtual(group)) + { + struct mali_group *child; + struct mali_group *temp; + + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL, + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + } +#if defined(CONFIG_MALI400_PROFILING) + if (0 != group->l2_cache_core_ref_count[0]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } + } + if (0 != group->l2_cache_core_ref_count[1]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1])); + } + } +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + } + else /* group is physical - call profiling events for physical cores */ + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))| + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL, + mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); +#if defined(CONFIG_MALI400_PROFILING) + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + } +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), mali_pp_job_get_tid(job), 0, mali_pp_job_get_id(job)); +#endif + group->pp_running_job = job; + group->pp_running_sub_job = sub_job; + group->state = MALI_GROUP_STATE_WORKING; + + } + + /* Setup the timeout timer value and save the job id for the job running on the pp core */ + _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); +} + +struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (group->state != MALI_GROUP_STATE_OOM || + mali_gp_job_get_id(group->gp_running_job) != job_id) + { + return NULL; /* Illegal request or job has already been aborted */ + } + + if (NULL != group->l2_cache_core[0]) + { + mali_l2_cache_invalidate(group->l2_cache_core[0]); + } + + mali_mmu_zap_tlb_without_stall(group->mmu); + + mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); + + group->state = MALI_GROUP_STATE_WORKING; + + return group->gp_running_job; +} + +static void mali_group_reset_mmu(struct mali_group *group) +{ + struct mali_group *child; + struct mali_group *temp; + _mali_osk_errcode_t err; + + if (!mali_group_is_virtual(group)) + { + /* This is a physical group or an idle virtual group -- simply wait for + * the reset to complete. */ + err = mali_mmu_reset(group->mmu); + MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err); + } + else /* virtual group */ + { + err = mali_mmu_reset(group->mmu); + if (_MALI_OSK_ERR_OK == err) + { + return; + } + + /* Loop through all members of this virtual group and wait + * until they are done resetting. + */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + err = mali_mmu_reset(child->mmu); + MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err); + } + } +} + +static void mali_group_reset_pp(struct mali_group *group) +{ + struct mali_group *child; + struct mali_group *temp; + + mali_pp_reset_async(group->pp_core); + + if (!mali_group_is_virtual(group) || NULL == group->pp_running_job) + { + /* This is a physical group or an idle virtual group -- simply wait for + * the reset to complete. */ + mali_pp_reset_wait(group->pp_core); + } + else /* virtual group */ + { + /* Loop through all members of this virtual group and wait until they + * are done resetting. + */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_reset_wait(child->pp_core); + } + } +} + +static void mali_group_complete_pp(struct mali_group *group, mali_bool success) +{ + struct mali_pp_job *pp_job_to_return; + u32 pp_sub_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->pp_core); + MALI_DEBUG_ASSERT_POINTER(group->pp_running_job); + MALI_ASSERT_GROUP_LOCKED(group); + + mali_group_post_process_job_pp(group); + + if (success) + { + /* Only do soft reset for successful jobs, a full recovery + * reset will be done for failed jobs. */ + mali_pp_reset_async(group->pp_core); + } + + pp_job_to_return = group->pp_running_job; + pp_sub_job_to_return = group->pp_running_sub_job; + group->state = MALI_GROUP_STATE_IDLE; + group->pp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + /* Do hard reset if the job failed, or if soft reset fails */ + if (!success || _MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core)) + { + MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n")); + + mali_group_recovery_reset(group); + } + + mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, success); +} + +static void mali_group_complete_gp(struct mali_group *group, mali_bool success) +{ + struct mali_gp_job *gp_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->gp_core); + MALI_DEBUG_ASSERT_POINTER(group->gp_running_job); + MALI_ASSERT_GROUP_LOCKED(group); + + mali_group_post_process_job_gp(group, MALI_FALSE); + + mali_gp_reset_async(group->gp_core); + + gp_job_to_return = group->gp_running_job; + group->state = MALI_GROUP_STATE_IDLE; + group->gp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + if (_MALI_OSK_ERR_OK != mali_gp_reset_wait(group->gp_core)) + { + MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n")); + + mali_group_recovery_reset(group); + } + + mali_gp_scheduler_job_done(group, gp_job_to_return, success); +} + +void mali_group_abort_gp_job(struct mali_group *group, u32 job_id) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (MALI_GROUP_STATE_IDLE == group->state || + mali_gp_job_get_id(group->gp_running_job) != job_id) + { + return; /* No need to cancel or job has already been aborted or completed */ + } + + mali_group_complete_gp(group, MALI_FALSE); +} + +static void mali_group_abort_pp_job(struct mali_group *group, u32 job_id) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (MALI_GROUP_STATE_IDLE == group->state || + mali_pp_job_get_id(group->pp_running_job) != job_id) + { + return; /* No need to cancel or job has already been aborted or completed */ + } + + mali_group_complete_pp(group, MALI_FALSE); +} + +void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session) +{ + struct mali_gp_job *gp_job; + struct mali_pp_job *pp_job; + u32 gp_job_id = 0; + u32 pp_job_id = 0; + mali_bool abort_pp = MALI_FALSE; + mali_bool abort_gp = MALI_FALSE; + + mali_group_lock(group); + + if (mali_group_is_in_virtual(group)) + { + /* Group is member of a virtual group, don't touch it! */ + mali_group_unlock(group); + return; + } + + gp_job = group->gp_running_job; + pp_job = group->pp_running_job; + + if ((NULL != gp_job) && (mali_gp_job_get_session(gp_job) == session)) + { + MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session)); + + gp_job_id = mali_gp_job_get_id(gp_job); + abort_gp = MALI_TRUE; + } + + if ((NULL != pp_job) && (mali_pp_job_get_session(pp_job) == session)) + { + MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session)); + + pp_job_id = mali_pp_job_get_id(pp_job); + abort_pp = MALI_TRUE; + } + + if (abort_gp) + { + mali_group_abort_gp_job(group, gp_job_id); + } + if (abort_pp) + { + mali_group_abort_pp_job(group, pp_job_id); + } + + mali_group_remove_session_if_unused(group, session); + + mali_group_unlock(group); +} + +struct mali_group *mali_group_get_glob_group(u32 index) +{ + if(mali_global_num_groups > index) + { + return mali_global_groups[index]; + } + + return NULL; +} + +u32 mali_group_get_glob_num_groups(void) +{ + return mali_global_num_groups; +} + +static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session) +{ + enum mali_group_activate_pd_status retval; + MALI_ASSERT_GROUP_LOCKED(group); + + MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group)); + MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); + + if (0 != group->page_dir_ref_count) + { + if (group->session != session) + { + MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session)); + return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; + } + else + { + MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count)); + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; + + } + } + else + { + /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */ + if (group->session != session) + { + mali_bool activate_success; + MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count)); + + activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session)); + MALI_DEBUG_ASSERT(activate_success); + if ( MALI_FALSE== activate_success ) return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; + group->session = session; + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD; + } + else + { + MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count)); + retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; + } + } + + group->page_dir_ref_count++; + return retval; +} + +static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count); + MALI_DEBUG_ASSERT(session == group->session); + + group->page_dir_ref_count--; + + /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count), + and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */ + MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); +} + +static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (0 == group->page_dir_ref_count) + { + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING != group->state); + + if (group->session == session) + { + MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); + MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group)); + mali_mmu_activate_empty_page_directory(group->mmu); + group->session = NULL; + } + } +} + +mali_bool mali_group_power_is_on(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + return group->power_is_on; +} + +void mali_group_power_on_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_IN_VIRTUAL == group->state + || MALI_GROUP_STATE_JOINING_VIRTUAL == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + MALI_DEBUG_PRINT(3, ("Group %p powered on\n", group)); + + group->power_is_on = MALI_TRUE; +} + +void mali_group_power_off_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_IN_VIRTUAL == group->state + || MALI_GROUP_STATE_JOINING_VIRTUAL == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + MALI_DEBUG_PRINT(3, ("Group %p powered off\n", group)); + + /* It is necessary to set group->session = NULL so that the powered off MMU is not written + * to on map/unmap. It is also necessary to set group->power_is_on = MALI_FALSE so that + * pending bottom_halves does not access powered off cores. */ + + group->session = NULL; + group->power_is_on = MALI_FALSE; +} + +void mali_group_power_on(void) +{ + int i; + for (i = 0; i < mali_global_num_groups; i++) + { + struct mali_group *group = mali_global_groups[i]; + + mali_group_lock(group); + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_ASSERT(MALI_FALSE == group->power_is_on); + } + else + { + mali_group_power_on_group(group); + } + mali_group_unlock(group); + } + MALI_DEBUG_PRINT(4, ("Mali Group: power on\n")); +} + +void mali_group_power_off(void) +{ + int i; + + for (i = 0; i < mali_global_num_groups; i++) + { + struct mali_group *group = mali_global_groups[i]; + + mali_group_lock(group); + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_ASSERT(MALI_FALSE == group->power_is_on); + } + else + { + mali_group_power_off_group(group); + } + mali_group_unlock(group); + } + MALI_DEBUG_PRINT(4, ("Mali Group: power off\n")); +} + +static void mali_group_recovery_reset(struct mali_group *group) +{ + _mali_osk_errcode_t err; + + MALI_ASSERT_GROUP_LOCKED(group); + + /* Stop cores, bus stop */ + if (NULL != group->pp_core) + { + mali_pp_stop_bus(group->pp_core); + } + else + { + mali_gp_stop_bus(group->gp_core); + } + + /* Flush MMU and clear page fault (if any) */ + mali_mmu_activate_fault_flush_page_directory(group->mmu); + mali_mmu_page_fault_done(group->mmu); + + /* Wait for cores to stop bus, then do a hard reset on them */ + if (NULL != group->pp_core) + { + if (mali_group_is_virtual(group)) + { + struct mali_group *child, *temp; + + /* Disable the broadcast unit while we do reset directly on the member cores. */ + mali_bcast_disable(group->bcast_core); + + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_stop_bus_wait(child->pp_core); + mali_pp_hard_reset(child->pp_core); + } + + mali_bcast_enable(group->bcast_core); + } + else + { + mali_pp_stop_bus_wait(group->pp_core); + mali_pp_hard_reset(group->pp_core); + } + } + else + { + mali_gp_stop_bus_wait(group->gp_core); + mali_gp_hard_reset(group->gp_core); + } + + /* Reset MMU */ + err = mali_mmu_reset(group->mmu); + MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err); + MALI_IGNORE(err); + + group->session = NULL; +} + +#if MALI_STATE_TRACKING +u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group); + n += _mali_osk_snprintf(buf + n, size - n, "\tstate: %d\n", group->state); + if (group->gp_core) + { + n += mali_gp_dump_state(group->gp_core, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job); + } + if (group->pp_core) + { + n += mali_pp_dump_state(group->pp_core, buf + n, size - n); + n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n", + group->pp_running_job, group->pp_running_sub_job); + } + + return n; +} +#endif + +static void mali_group_mmu_page_fault(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + if (NULL != group->pp_core) + { + struct mali_pp_job *pp_job_to_return; + u32 pp_sub_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->pp_running_job); + + mali_group_post_process_job_pp(group); + + pp_job_to_return = group->pp_running_job; + pp_sub_job_to_return = group->pp_running_sub_job; + group->state = MALI_GROUP_STATE_IDLE; + group->pp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + mali_group_recovery_reset(group); /* This will also clear the page fault itself */ + + mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, MALI_FALSE); + } + else + { + struct mali_gp_job *gp_job_to_return; + + MALI_DEBUG_ASSERT_POINTER(group->gp_running_job); + + mali_group_post_process_job_gp(group, MALI_FALSE); + + gp_job_to_return = group->gp_running_job; + group->state = MALI_GROUP_STATE_IDLE; + group->gp_running_job = NULL; + + mali_group_deactivate_page_directory(group, group->session); + + mali_group_recovery_reset(group); /* This will also clear the page fault itself */ + + mali_gp_scheduler_job_done(group, gp_job_to_return, MALI_FALSE); + } +} + +_mali_osk_errcode_t mali_group_upper_half_mmu(void * data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + struct mali_group *group = (struct mali_group *)data; + struct mali_mmu_core *mmu = group->mmu; + u32 int_stat; + + MALI_DEBUG_ASSERT_POINTER(mmu); + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) + { + goto out; + } +#endif + + /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */ + int_stat = mali_mmu_get_int_status(mmu); + if (0 != int_stat) + { + struct mali_group *parent = group->parent_group; + + /* page fault or bus error, we thread them both in the same way */ + mali_mmu_mask_all_interrupts(mmu); + if (NULL == parent) + { + _mali_osk_wq_schedule_work(group->bottom_half_work_mmu); + } + else + { + _mali_osk_wq_schedule_work(parent->bottom_half_work_mmu); + } + err = _MALI_OSK_ERR_OK; + goto out; + } + +out: +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + mali_pm_domain_unlock_state(group->pm_domain); +#endif + + return err; +} + +static void mali_group_bottom_half_mmu(void * data) +{ + struct mali_group *group = (struct mali_group *)data; + struct mali_mmu_core *mmu = group->mmu; + u32 rawstat; + MALI_DEBUG_CODE(u32 status); + + MALI_DEBUG_ASSERT_POINTER(mmu); + + mali_group_lock(group); + + MALI_DEBUG_ASSERT(NULL == group->parent_group); + + if ( MALI_FALSE == mali_group_power_is_on(group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mmu->hw_core.description)); + mali_group_unlock(group); + return; + } + + rawstat = mali_mmu_get_rawstat(mmu); + MALI_DEBUG_CODE(status = mali_mmu_get_status(mmu)); + + MALI_DEBUG_PRINT(4, ("Mali MMU: Bottom half, interrupt 0x%08X, status 0x%08X\n", rawstat, status)); + + if (rawstat & (MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR)) + { + /* An actual page fault has occurred. */ + u32 fault_address = mali_mmu_get_page_fault_addr(mmu); + MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n", + (void*)fault_address, + (status >> 6) & 0x1F, + (status & 32) ? "write" : "read", + mmu->hw_core.description)); + MALI_IGNORE(fault_address); + + mali_group_mmu_page_fault(group); + } + + mali_group_unlock(group); +} + +_mali_osk_errcode_t mali_group_upper_half_gp(void *data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + struct mali_group *group = (struct mali_group *)data; + struct mali_gp_core *core = group->gp_core; + u32 irq_readout; + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) + { + goto out; + } +#endif + + irq_readout = mali_gp_get_int_stat(core); + + if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) + { + /* Mask out all IRQs from this core until IRQ is handled */ + mali_gp_mask_all_interrupts(core); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); + + /* We do need to handle this in a bottom half */ + _mali_osk_wq_schedule_work(group->bottom_half_work_gp); + + err = _MALI_OSK_ERR_OK; + goto out; + } + +out: +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + mali_pm_domain_unlock_state(group->pm_domain); +#endif + + return err; +} + +static void mali_group_bottom_half_gp(void *data) +{ + struct mali_group *group = (struct mali_group *)data; + u32 irq_readout; + u32 irq_errors; + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0); + + mali_group_lock(group); + + if ( MALI_FALSE == mali_group_power_is_on(group) ) + { + MALI_PRINT_ERROR(("Mali group: Interrupt bottom half of %s when core is OFF.", mali_gp_get_hw_core_desc(group->gp_core))); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + irq_readout = mali_gp_read_rawstat(group->gp_core); + + MALI_DEBUG_PRINT(4, ("Mali group: GP bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core))); + + if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) + { + u32 core_status = mali_gp_read_core_status(group->gp_core); + if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) + { + MALI_DEBUG_PRINT(4, ("Mali group: GP job completed, calling group handler\n")); + group->core_timed_out = MALI_FALSE; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + mali_group_complete_gp(group, MALI_TRUE); + mali_group_unlock(group); + return; + } + } + + /* + * Now lets look at the possible error cases (IRQ indicating error or timeout) + * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error. + */ + irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM); + if (0 != irq_errors) + { + MALI_PRINT_ERROR(("Mali group: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core))); + group->core_timed_out = MALI_FALSE; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + mali_group_complete_gp(group, MALI_FALSE); + mali_group_unlock(group); + return; + } + else if (group->core_timed_out) /* SW timeout */ + { + group->core_timed_out = MALI_FALSE; + if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->gp_running_job) + { + MALI_PRINT(("Mali group: Job %d timed out\n", mali_gp_job_get_id(group->gp_running_job))); + mali_group_complete_gp(group, MALI_FALSE); + mali_group_unlock(group); + return; + } + } + else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) + { + /* GP wants more memory in order to continue. */ + MALI_DEBUG_PRINT(3, ("Mali group: PLBU needs more heap memory\n")); + + group->state = MALI_GROUP_STATE_OOM; + mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */ + mali_gp_scheduler_oom(group, group->gp_running_job); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + /* + * The only way to get here is if we only got one of two needed END_CMD_LST + * interrupts. Enable all but not the complete interrupt that has been + * received and continue to run. + */ + mali_gp_enable_interrupts(group->gp_core, irq_readout & (MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST)); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); +} + +static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend) +{ + /* Stop the timeout timer. */ + _mali_osk_timer_del_async(group->timeout_timer); + + if (NULL == group->gp_running_job) + { + /* Nothing to do */ + return; + } + + mali_gp_update_performance_counters(group->gp_core, group->gp_running_job, suspend); + +#if defined(CONFIG_MALI400_PROFILING) + if (suspend) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), + mali_gp_job_get_perf_counter_value0(group->gp_running_job), + mali_gp_job_get_perf_counter_value1(group->gp_running_job), + mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8), + 0, 0); + } + else + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), + mali_gp_job_get_perf_counter_value0(group->gp_running_job), + mali_gp_job_get_perf_counter_value1(group->gp_running_job), + mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8), + 0, 0); + + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + mali_group_report_l2_cache_counters_per_core(group, 0); + } +#endif + + mali_gp_job_set_current_heap_addr(group->gp_running_job, + mali_gp_read_plbu_alloc_start_addr(group->gp_core)); +} + +_mali_osk_errcode_t mali_group_upper_half_pp(void *data) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; + struct mali_group *group = (struct mali_group *)data; + struct mali_pp_core *core = group->pp_core; + u32 irq_readout; + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) + { + goto out; + } +#endif + + /* + * For Mali-450 there is one particular case we need to watch out for: + * + * Criteria 1) this function call can be due to a shared interrupt, + * and not necessary because this core signaled an interrupt. + * Criteria 2) this core is a part of a virtual group, and thus it should + * not do any post processing. + * Criteria 3) this core has actually indicated that is has completed by + * having set raw_stat/int_stat registers to != 0 + * + * If all this criteria is meet, then we could incorrectly start post + * processing on the wrong group object (this should only happen on the + * parent group) + */ +#if !defined(MALI_UPPER_HALF_SCHEDULING) + if (mali_group_is_in_virtual(group)) + { + /* + * This check is done without the group lock held, which could lead to + * a potential race. This is however ok, since we will safely re-check + * this with the group lock held at a later stage. This is just an + * early out which will strongly benefit shared IRQ systems. + */ + err = _MALI_OSK_ERR_OK; + goto out; + } +#endif + + irq_readout = mali_pp_get_int_stat(core); + if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) + { + /* Mask out all IRQs from this core until IRQ is handled */ + mali_pp_mask_all_interrupts(core); + +#if defined(CONFIG_MALI400_PROFILING) + /* Currently no support for this interrupt event for the virtual PP core */ + if (!mali_group_is_virtual(group)) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | + MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, + irq_readout, 0, 0, 0, 0); + } +#endif + +#if defined(MALI_UPPER_HALF_SCHEDULING) + /* Check if job is complete without errors */ + if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + + MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler from upper half\n")); + + mali_group_lock(group); + + /* Check if job is complete without errors, again, after taking the group lock */ + irq_readout = mali_pp_read_rawstat(core); + if (MALI200_REG_VAL_IRQ_END_OF_FRAME != irq_readout) + { + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + err = _MALI_OSK_ERR_OK; + goto out; + } + + if (mali_group_is_virtual(group)) + { + u32 status_readout = mali_pp_read_status(group->pp_core); + if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE) + { + MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n")); + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + err = _MALI_OSK_ERR_OK; + goto out; + } + } + + if (mali_group_is_in_virtual(group)) + { + /* We're member of a virtual group, so interrupt should be handled by the virtual group */ + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + err = _MALI_OSK_ERR_FAULT; + goto out; + } + + group->core_timed_out = MALI_FALSE; + mali_group_complete_pp(group, MALI_TRUE); + /* No need to enable interrupts again, since the core will be reset while completing the job */ + + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF, + 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + + err = _MALI_OSK_ERR_OK; + goto out; + } +#endif + + /* We do need to handle this in a bottom half */ + _mali_osk_wq_schedule_work(group->bottom_half_work_pp); + err = _MALI_OSK_ERR_OK; + goto out; + } + +out: +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + mali_pm_domain_unlock_state(group->pm_domain); +#endif + + return err; +} + +static void mali_group_bottom_half_pp(void *data) +{ + struct mali_group *group = (struct mali_group *)data; + struct mali_pp_core *core = group->pp_core; + u32 irq_readout; + u32 irq_errors; + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); + + mali_group_lock(group); + + if (mali_group_is_in_virtual(group)) + { + /* We're member of a virtual group, so interrupt should be handled by the virtual group */ + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + if ( MALI_FALSE == mali_group_power_is_on(group) ) + { + MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mali_pp_get_hw_core_desc(core))); + mali_group_unlock(group); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + irq_readout = mali_pp_read_rawstat(group->pp_core); + + MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_pp_get_hw_core_desc(group->pp_core))); + + /* Check if job is complete without errors */ + if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout) + { + if (mali_group_is_virtual(group)) + { + u32 status_readout = mali_pp_read_status(group->pp_core); + + if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE) + { + MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n")); + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + } + + MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); + group->core_timed_out = MALI_FALSE; + mali_group_complete_pp(group, MALI_TRUE); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + /* + * Now lets look at the possible error cases (IRQ indicating error or timeout) + * END_OF_FRAME and HANG interrupts are not considered error. + */ + irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG); + if (0 != irq_errors) + { + MALI_PRINT_ERROR(("Mali PP: Unexpected interrupt 0x%08X from core %s, aborting job\n", + irq_readout, mali_pp_get_hw_core_desc(group->pp_core))); + group->core_timed_out = MALI_FALSE; + mali_group_complete_pp(group, MALI_FALSE); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + else if (group->core_timed_out) /* SW timeout */ + { + group->core_timed_out = MALI_FALSE; + if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->pp_running_job) + { + MALI_PRINT(("Mali PP: Job %d timed out on core %s\n", + mali_pp_job_get_id(group->pp_running_job), mali_pp_get_hw_core_desc(core))); + mali_group_complete_pp(group, MALI_FALSE); + mali_group_unlock(group); + } + else + { + mali_group_unlock(group); + } + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); + return; + } + + /* + * We should never get here, re-enable interrupts and continue + */ + if (0 == irq_readout) + { + MALI_DEBUG_PRINT(3, ("Mali group: No interrupt found on core %s\n", + mali_pp_get_hw_core_desc(group->pp_core))); + } + else + { + MALI_PRINT_ERROR(("Mali group: Unhandled PP interrupt 0x%08X on %s\n", irq_readout, + mali_pp_get_hw_core_desc(group->pp_core))); + } + mali_pp_enable_interrupts(core); + mali_group_unlock(group); + + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP | + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, + 0, _mali_osk_get_tid(), 0, 0, 0); +} + +static void mali_group_post_process_job_pp(struct mali_group *group) +{ + MALI_ASSERT_GROUP_LOCKED(group); + + /* Stop the timeout timer. */ + _mali_osk_timer_del_async(group->timeout_timer); + + if (NULL != group->pp_running_job) + { + if (MALI_TRUE == mali_group_is_virtual(group)) + { + struct mali_group *child; + struct mali_group *temp; + + /* update performance counters from each physical pp core within this virtual group */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + mali_pp_update_performance_counters(group->pp_core, child->pp_core, group->pp_running_job, mali_pp_core_get_id(child->pp_core)); + } + +#if defined(CONFIG_MALI400_PROFILING) + /* send profiling data per physical core */ + _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) + { + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL, + mali_pp_job_get_perf_counter_value0(group->pp_running_job, mali_pp_core_get_id(child->pp_core)), + mali_pp_job_get_perf_counter_value1(group->pp_running_job, mali_pp_core_get_id(child->pp_core)), + mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8), + 0, 0); + } + if (0 != group->l2_cache_core_ref_count[0]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } + } + if (0 != group->l2_cache_core_ref_count[1]) + { + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1])); + } + } + +#endif + } + else + { + /* update performance counters for a physical group's pp core */ + mali_pp_update_performance_counters(group->pp_core, group->pp_core, group->pp_running_job, group->pp_running_sub_job); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP| + MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))| + MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL, + mali_pp_job_get_perf_counter_value0(group->pp_running_job, group->pp_running_sub_job), + mali_pp_job_get_perf_counter_value1(group->pp_running_job, group->pp_running_sub_job), + mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8), + 0, 0); + if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) && + (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) + { + mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0])); + } +#endif + } + } +} + +static void mali_group_timeout(void *data) +{ + struct mali_group *group = (struct mali_group *)data; + + group->core_timed_out = MALI_TRUE; + + if (NULL != group->gp_core) + { + MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_gp_get_hw_core_desc(group->gp_core))); + _mali_osk_wq_schedule_work(group->bottom_half_work_gp); + } + else + { + MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_pp_get_hw_core_desc(group->pp_core))); + _mali_osk_wq_schedule_work(group->bottom_half_work_pp); + } +} + +void mali_group_zap_session(struct mali_group *group, struct mali_session_data *session) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_POINTER(session); + + /* Early out - safe even if mutex is not held */ + if (group->session != session) return; + + mali_group_lock(group); + + mali_group_remove_session_if_unused(group, session); + + if (group->session == session) + { + /* The Zap also does the stall and disable_stall */ + mali_bool zap_success = mali_mmu_zap_tlb(group->mmu); + if (MALI_TRUE != zap_success) + { + MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n")); + mali_group_mmu_page_fault(group); + } + } + + mali_group_unlock(group); +} + +#if defined(CONFIG_MALI400_PROFILING) +static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num) +{ + u32 source0 = 0; + u32 value0 = 0; + u32 source1 = 0; + u32 value1 = 0; + u32 profiling_channel = 0; + + switch(core_num) + { + case 0: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS; + break; + case 1: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS; + break; + case 2: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS; + break; + default: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS; + break; + } + + if (0 == core_num) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1); + } + if (1 == core_num) + { + if (1 == mali_l2_cache_get_id(group->l2_cache_core[0])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1); + } + else if (1 == mali_l2_cache_get_id(group->l2_cache_core[1])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1); + } + } + if (2 == core_num) + { + if (2 == mali_l2_cache_get_id(group->l2_cache_core[0])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1); + } + else if (2 == mali_l2_cache_get_id(group->l2_cache_core[1])) + { + mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1); + } + } + + _mali_osk_profiling_add_event(profiling_channel, source1 << 8 | source0, value0, value1, 0, 0); +} +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ + +mali_bool mali_group_is_enabled(struct mali_group *group) +{ + mali_bool enabled = MALI_TRUE; + + MALI_DEBUG_ASSERT_POINTER(group); + + mali_group_lock(group); + if (MALI_GROUP_STATE_DISABLED == group->state) + { + enabled = MALI_FALSE; + } + mali_group_unlock(group); + + return enabled; +} + +void mali_group_enable(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT( NULL != mali_group_get_pp_core(group) + || NULL != mali_group_get_gp_core(group)); + + if (NULL != mali_group_get_pp_core(group)) + { + mali_pp_scheduler_enable_group(group); + } + else + { + mali_gp_scheduler_enable_group(group); + } +} + +void mali_group_disable(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT( NULL != mali_group_get_pp_core(group) + || NULL != mali_group_get_gp_core(group)); + + if (NULL != mali_group_get_pp_core(group)) + { + mali_pp_scheduler_disable_group(group); + } + else + { + mali_gp_scheduler_disable_group(group); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_group.h b/drivers/gpu/mali400/r3p2/mali/common/mali_group.h new file mode 100644 index 0000000..6a6a777 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_group.h @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2011-2012 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_GROUP_H__ +#define __MALI_GROUP_H__ + +#include "linux/jiffies.h" +#include "mali_osk.h" +#include "mali_l2_cache.h" +#include "mali_mmu.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_session.h" + +/* max runtime [ms] for a core job - used by timeout timers */ +#define MAX_RUNTIME 5000 +/** @brief A mali group object represents a MMU and a PP and/or a GP core. + * + */ +#define MALI_MAX_NUMBER_OF_GROUPS 10 + +enum mali_group_core_state +{ + MALI_GROUP_STATE_IDLE, + MALI_GROUP_STATE_WORKING, + MALI_GROUP_STATE_OOM, + MALI_GROUP_STATE_IN_VIRTUAL, + MALI_GROUP_STATE_JOINING_VIRTUAL, + MALI_GROUP_STATE_LEAVING_VIRTUAL, + MALI_GROUP_STATE_DISABLED, +}; + +/* Forward declaration from mali_pm_domain.h */ +struct mali_pm_domain; + +/** + * The structure represents a render group + * A render group is defined by all the cores that share the same Mali MMU + */ + +struct mali_group +{ + struct mali_mmu_core *mmu; + struct mali_session_data *session; + int page_dir_ref_count; + + mali_bool power_is_on; + enum mali_group_core_state state; + + struct mali_gp_core *gp_core; + struct mali_gp_job *gp_running_job; + + struct mali_pp_core *pp_core; + struct mali_pp_job *pp_running_job; + u32 pp_running_sub_job; + + struct mali_l2_cache_core *l2_cache_core[2]; + u32 l2_cache_core_ref_count[2]; + + struct mali_dlbu_core *dlbu_core; + struct mali_bcast_unit *bcast_core; + + _mali_osk_lock_t *lock; + + _mali_osk_list_t pp_scheduler_list; + + /* List used for virtual groups. For a virtual group, the list represents the + * head element. */ + _mali_osk_list_t group_list; + + struct mali_group *pm_domain_list; + struct mali_pm_domain *pm_domain; + + /* Parent virtual group (if any) */ + struct mali_group *parent_group; + + _mali_osk_wq_work_t *bottom_half_work_mmu; + _mali_osk_wq_work_t *bottom_half_work_gp; + _mali_osk_wq_work_t *bottom_half_work_pp; + + _mali_osk_timer_t *timeout_timer; + mali_bool core_timed_out; +}; + +/** @brief Create a new Mali group object + * + * @param cluster Pointer to the cluster to which the group is connected. + * @param mmu Pointer to the MMU that defines this group + * @return A pointer to a new group object + */ +struct mali_group *mali_group_create(struct mali_l2_cache_core *core, + struct mali_dlbu_core *dlbu, + struct mali_bcast_unit *bcast); + +_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core); +void mali_group_remove_mmu_core(struct mali_group *group); + +_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core); +void mali_group_remove_gp_core(struct mali_group *group); + +_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core); +void mali_group_remove_pp_core(struct mali_group *group); + +void mali_group_set_pm_domain(struct mali_group *group, struct mali_pm_domain *domain); + +void mali_group_delete(struct mali_group *group); + +/** @brief Virtual groups */ +void mali_group_add_group(struct mali_group *parent, struct mali_group *child, mali_bool update_hw); +void mali_group_remove_group(struct mali_group *parent, struct mali_group *child); +struct mali_group *mali_group_acquire_group(struct mali_group *parent); + +MALI_STATIC_INLINE mali_bool mali_group_is_virtual(struct mali_group *group) +{ + return (NULL != group->dlbu_core); +} + +/** @brief Check if a group is considered as part of a virtual group + * + * @note A group is considered to be "part of" a virtual group also during the transition + * in to / out of the virtual group. + */ +MALI_STATIC_INLINE mali_bool mali_group_is_in_virtual(struct mali_group *group) +{ + return (MALI_GROUP_STATE_IN_VIRTUAL == group->state || + MALI_GROUP_STATE_JOINING_VIRTUAL == group->state || + MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state); +} + +/** @brief Reset group + * + * This function will reset the entire group, including all the cores present in the group. + * + * @param group Pointer to the group to reset + */ +void mali_group_reset(struct mali_group *group); + +/** @brief Zap MMU TLB on all groups + * + * Zap TLB on group if \a session is active. + */ +void mali_group_zap_session(struct mali_group* group, struct mali_session_data *session); + +/** @brief Get pointer to GP core object + */ +struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group); + +/** @brief Get pointer to PP core object + */ +struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group); + +/** @brief Lock group object + * + * Most group functions will lock the group object themselves. The expection is + * the group_bottom_half which requires the group to be locked on entry. + * + * @param group Pointer to group to lock + */ +void mali_group_lock(struct mali_group *group); + +/** @brief Unlock group object + * + * @param group Pointer to group to unlock + */ +void mali_group_unlock(struct mali_group *group); +#ifdef DEBUG +void mali_group_assert_locked(struct mali_group *group); +#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group) +#else +#define MALI_ASSERT_GROUP_LOCKED(group) +#endif + +/** @brief Start GP job + */ +void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job); +/** @brief Start fragment of PP job + */ +void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job); + +/** @brief Resume GP job that suspended waiting for more heap memory + */ +struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr); +/** @brief Abort GP job + * + * Used to abort suspended OOM jobs when user space failed to allocte more memory. + */ +void mali_group_abort_gp_job(struct mali_group *group, u32 job_id); +/** @brief Abort all GP jobs from \a session + * + * Used on session close when terminating all running and queued jobs from \a session. + */ +void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session); + +mali_bool mali_group_power_is_on(struct mali_group *group); +void mali_group_power_on_group(struct mali_group *group); +void mali_group_power_off_group(struct mali_group *group); +void mali_group_power_on(void); +void mali_group_power_off(void); + +struct mali_group *mali_group_get_glob_group(u32 index); +u32 mali_group_get_glob_num_groups(void); + +u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size); + +/* MMU-related functions */ +_mali_osk_errcode_t mali_group_upper_half_mmu(void * data); + +/* GP-related functions */ +_mali_osk_errcode_t mali_group_upper_half_gp(void *data); + +/* PP-related functions */ +_mali_osk_errcode_t mali_group_upper_half_pp(void *data); + +/** @brief Check if group is enabled + * + * @param group group to check + * @return MALI_TRUE if enabled, MALI_FALSE if not + */ +mali_bool mali_group_is_enabled(struct mali_group *group); + +/** @brief Enable group + * + * An enabled job is put on the idle scheduler list and can be used to handle jobs. Does nothing if + * group is already enabled. + * + * @param group group to enable + */ +void mali_group_enable(struct mali_group *group); + +/** @brief Disable group + * + * A disabled group will no longer be used by the scheduler. If part of a virtual group, the group + * will be removed before being disabled. Cores part of a disabled group is safe to power down. + * + * @param group group to disable + */ +void mali_group_disable(struct mali_group *group); + +MALI_STATIC_INLINE mali_bool mali_group_virtual_disable_if_empty(struct mali_group *group) +{ + mali_bool empty = MALI_FALSE; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(mali_group_is_virtual(group)); + + if (_mali_osk_list_empty(&group->group_list)) + { + group->state = MALI_GROUP_STATE_DISABLED; + group->session = NULL; + + empty = MALI_TRUE; + } + + return empty; +} + +MALI_STATIC_INLINE mali_bool mali_group_virtual_enable_if_empty(struct mali_group *group) +{ + mali_bool empty = MALI_FALSE; + + MALI_ASSERT_GROUP_LOCKED(group); + MALI_DEBUG_ASSERT(mali_group_is_virtual(group)); + + if (_mali_osk_list_empty(&group->group_list)) + { + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + + group->state = MALI_GROUP_STATE_IDLE; + + empty = MALI_TRUE; + } + + return empty; +} + +#endif /* __MALI_GROUP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.c b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.c index 0b08622..c3a9c8b 100644 --- a/drivers/media/video/samsung/mali/common/mali_hw_core.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.c @@ -17,6 +17,7 @@ _mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_o core->phys_addr = resource->base; core->description = resource->description; core->size = reg_size; + if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description)) { core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description); diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.h b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.h index c797804..e687f60 100644 --- a/drivers/media/video/samsung/mali/common/mali_hw_core.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_hw_core.h @@ -26,8 +26,8 @@ struct mali_hw_core const char* description; /**< Name of unit (as specified in device configuration) */ }; -#define MALI_HW_CORE_NO_COUNTER ((u32)-1) -#define MALI_HW_CORE_INVALID_VALUE ((u32)-1) +#define MALI_REG_POLL_COUNT_FAST 1000 +#define MALI_REG_POLL_COUNT_SLOW 1000000 _mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size); void mali_hw_core_delete(struct mali_hw_core *core); @@ -48,6 +48,20 @@ MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); } +/* Conditionally write a register. + * The register will only be written if the new value is different from the old_value. + * If the new value is different, the old value will also be updated */ +MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 new_val, const u32 old_val) +{ + MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n", + core->description, relative_address, new_val)); + if(old_val != new_val) + { + _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); + } +} + + MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val) { MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n", @@ -68,4 +82,23 @@ MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw } } +/* Conditionally write a set of registers. + * The register will only be written if the new value is different from the old_value. + * If the new value is different, the old value will also be updated */ +MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs, const u32* old_array) +{ + u32 i; + MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n", + core->description,relative_address, nr_of_regs)); + + /* Do not use burst writes against the registers */ + for (i = 0; i< nr_of_regs; i++) + { + if(old_array[i] != write_array[i]) + { + mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]); + } + } +} + #endif /* __MALI_HW_CORE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_common.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_common.h index b354f92..3376a07 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_common.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_common.h @@ -11,6 +11,8 @@ #ifndef __MALI_KERNEL_COMMON_H__ #define __MALI_KERNEL_COMMON_H__ +#include "mali_osk.h" + /* Make sure debug is defined when it should be */ #ifndef DEBUG #if defined(_DEBUG) @@ -18,6 +20,7 @@ #endif #endif +/* MALI_SEC */ /* Macro for generating a kernel panic. * Turned on off by compile-time Makefile settings */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c new file mode 100644 index 0000000..5680374 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.c @@ -0,0 +1,1293 @@ +/* + * Copyright (C) 2010-2012 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 "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_kernel_core.h" +#include "mali_memory.h" +#include "mali_mem_validation.h" +#include "mali_mmu.h" +#include "mali_mmu_page_directory.h" +#include "mali_dlbu.h" +#include "mali_broadcast.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_pmu.h" +#include "mali_scheduler.h" +#include "mali_kernel_utilization.h" +#include "mali_l2_cache.h" +#include "mali_pm_domain.h" +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) +#include "mali_profiling_internal.h" +#endif + + +/* Mali GPU memory. Real values come from module parameter or from device specific data */ +unsigned int mali_dedicated_mem_start = 0; +unsigned int mali_dedicated_mem_size = 0; +unsigned int mali_shared_mem_size = 0; + +/* Frame buffer memory to be accessible by Mali GPU */ +int mali_fb_start = 0; +int mali_fb_size = 0; + +/** Start profiling from module load? */ +int mali_boot_profiling = 0; + +/** Limits for the number of PP cores behind each L2 cache. */ +int mali_max_pp_cores_group_1 = 0xFF; +int mali_max_pp_cores_group_2 = 0xFF; + +int mali_inited_pp_cores_group_1 = 0; +int mali_inited_pp_cores_group_2 = 0; + +static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN; +static u32 global_gpu_base_address = 0; +static u32 global_gpu_major_version = 0; +static u32 global_gpu_minor_version = 0; + +#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */ + +/* timer related */ +int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; + +static _mali_osk_errcode_t mali_set_global_gpu_base_address(void) +{ + global_gpu_base_address = _mali_osk_resource_base_address(); + if (0 == global_gpu_base_address) + { + return _MALI_OSK_ERR_ITEM_NOT_FOUND; + } + + return _MALI_OSK_ERR_OK; +} + +static u32 mali_get_bcast_id(_mali_osk_resource_t *resource_pp) +{ + switch (resource_pp->base - global_gpu_base_address) + { + case 0x08000: + case 0x20000: /* fall-through for aliased mapping */ + return 0x01; + case 0x0A000: + case 0x22000: /* fall-through for aliased mapping */ + return 0x02; + case 0x0C000: + case 0x24000: /* fall-through for aliased mapping */ + return 0x04; + case 0x0E000: + case 0x26000: /* fall-through for aliased mapping */ + return 0x08; + case 0x28000: + return 0x10; + case 0x2A000: + return 0x20; + case 0x2C000: + return 0x40; + case 0x2E000: + return 0x80; + default: + return 0; + } +} + +static _mali_osk_errcode_t mali_parse_product_info(void) +{ + /* + * Mali-200 has the PP core first, while Mali-300, Mali-400 and Mali-450 have the GP core first. + * Look at the version register for the first PP core in order to determine the GPU HW revision. + */ + + u32 first_pp_offset; + _mali_osk_resource_t first_pp_resource; + + /* Find out where the first PP core is located */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL)) + { + /* Mali-300/400/450 */ + first_pp_offset = 0x8000; + } + else + { + /* Mali-200 */ + first_pp_offset = 0x0000; + } + + /* Find the first PP core resource (again) */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + first_pp_offset, &first_pp_resource)) + { + /* Create a dummy PP object for this core so that we can read the version register */ + struct mali_group *group = mali_group_create(NULL, NULL, NULL); + if (NULL != group) + { + struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE, mali_get_bcast_id(&first_pp_resource)); + if (NULL != pp_core) + { + u32 pp_version = mali_pp_core_get_version(pp_core); + mali_group_delete(group); + + global_gpu_major_version = (pp_version >> 8) & 0xFF; + global_gpu_minor_version = pp_version & 0xFF; + + switch (pp_version >> 16) + { + case MALI200_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI200; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + MALI_PRINT_ERROR(("Mali-200 is not supported by this driver.\n")); + _mali_osk_abort(); + break; + case MALI300_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI300; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI400_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI400; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + case MALI450_PP_PRODUCT_ID: + global_product_id = _MALI_PRODUCT_ID_MALI450; + MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); + break; + default: + MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version)); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; + } + else + { + MALI_PRINT_ERROR(("Failed to create initial PP object\n")); + } + } + else + { + MALI_PRINT_ERROR(("Failed to create initial group object\n")); + } + } + else + { + MALI_PRINT_ERROR(("First PP core not specified in config file\n")); + } + + return _MALI_OSK_ERR_FAULT; +} + + +void mali_resource_count(u32 *pp_count, u32 *l2_count) +{ + *pp_count = 0; + *l2_count = 0; + + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL)) + { + ++(*pp_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL)) + { + ++(*pp_count); + } + + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL)) + { + ++(*l2_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL)) + { + ++(*l2_count); + } + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL)) + { + ++(*l2_count); + } +} + +static void mali_delete_groups(void) +{ + while (0 < mali_group_get_glob_num_groups()) + { + mali_group_delete(mali_group_get_glob_group(0)); + } +} + +static void mali_delete_l2_cache_cores(void) +{ + while (0 < mali_l2_cache_core_get_glob_num_l2_cores()) + { + mali_l2_cache_delete(mali_l2_cache_core_get_glob_l2_core(0)); + } +} + +static struct mali_l2_cache_core *mali_create_l2_cache_core(_mali_osk_resource_t *resource) +{ + struct mali_l2_cache_core *l2_cache = NULL; + + if (NULL != resource) + { + + MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description)); + + l2_cache = mali_l2_cache_create(resource); + if (NULL == l2_cache) + { + MALI_PRINT_ERROR(("Failed to create L2 cache object\n")); + return NULL; + } + } + MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n")); + + return l2_cache; +} + +static _mali_osk_errcode_t mali_parse_config_l2_cache(void) +{ + struct mali_l2_cache_core *l2_cache = NULL; + + if (mali_is_mali400()) + { + _mali_osk_resource_t l2_resource; + if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_resource)) + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + l2_cache = mali_create_l2_cache_core(&l2_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + } + else if (mali_is_mali450()) + { + /* + * L2 for GP at 0x10000 + * L2 for PP0-3 at 0x01000 + * L2 for PP4-7 at 0x11000 (optional) + */ + + _mali_osk_resource_t l2_gp_resource; + _mali_osk_resource_t l2_pp_grp0_resource; + _mali_osk_resource_t l2_pp_grp1_resource; + + /* Make cluster for GP's L2 */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, &l2_gp_resource)) + { + MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n")); + l2_cache = mali_create_l2_cache_core(&l2_gp_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + } + else + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Make cluster for first PP core group */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_pp_grp0_resource)) + { + MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n")); + l2_cache = mali_create_l2_cache_core(&l2_pp_grp0_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + mali_pm_domain_add_l2(MALI_PMU_M450_DOM1, l2_cache); + } + else + { + MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Second PP core group is optional, don't fail if we don't find it */ + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, &l2_pp_grp1_resource)) + { + MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n")); + l2_cache = mali_create_l2_cache_core(&l2_pp_grp1_resource); + if (NULL == l2_cache) + { + return _MALI_OSK_ERR_FAULT; + } + mali_pm_domain_add_l2(MALI_PMU_M450_DOM3, l2_cache); + } + } + + return _MALI_OSK_ERR_OK; +} + +static struct mali_group *mali_create_group(struct mali_l2_cache_core *cache, + _mali_osk_resource_t *resource_mmu, + _mali_osk_resource_t *resource_gp, + _mali_osk_resource_t *resource_pp) +{ + struct mali_mmu_core *mmu; + struct mali_group *group; + + MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description)); + + /* Create the group object */ + group = mali_group_create(cache, NULL, NULL); + if (NULL == group) + { + MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description)); + return NULL; + } + + /* Create the MMU object inside group */ + mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE); + if (NULL == mmu) + { + MALI_PRINT_ERROR(("Failed to create MMU object\n")); + mali_group_delete(group); + return NULL; + } + + if (NULL != resource_gp) + { + /* Create the GP core object inside this group */ + struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group); + if (NULL == gp_core) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create GP object\n")); + mali_group_delete(group); + return NULL; + } + } + + if (NULL != resource_pp) + { + struct mali_pp_core *pp_core; + + /* Create the PP core object inside this group */ + pp_core = mali_pp_create(resource_pp, group, MALI_FALSE, mali_get_bcast_id(resource_pp)); + if (NULL == pp_core) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create PP object\n")); + mali_group_delete(group); + return NULL; + } + } + + /* Reset group */ + mali_group_lock(group); + mali_group_reset(group); + mali_group_unlock(group); + + return group; +} + +static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast, + _mali_osk_resource_t *resource_pp_bcast, + _mali_osk_resource_t *resource_dlbu, + _mali_osk_resource_t *resource_bcast) +{ + struct mali_mmu_core *mmu_pp_bcast_core; + struct mali_pp_core *pp_bcast_core; + struct mali_dlbu_core *dlbu_core; + struct mali_bcast_unit *bcast_core; + struct mali_group *group; + + MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description)); + + /* Create the DLBU core object */ + dlbu_core = mali_dlbu_create(resource_dlbu); + if (NULL == dlbu_core) + { + MALI_PRINT_ERROR(("Failed to create DLBU object \n")); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the Broadcast unit core */ + bcast_core = mali_bcast_unit_create(resource_bcast); + if (NULL == bcast_core) + { + MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n")); + mali_dlbu_delete(dlbu_core); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the group object */ + group = mali_group_create(NULL, dlbu_core, bcast_core); + if (NULL == group) + { + MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description)); + mali_bcast_unit_delete(bcast_core); + mali_dlbu_delete(dlbu_core); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the MMU object inside group */ + mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE); + if (NULL == mmu_pp_bcast_core) + { + MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n")); + mali_group_delete(group); + return _MALI_OSK_ERR_FAULT; + } + + /* Create the PP core object inside this group */ + pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE, 0); + if (NULL == pp_bcast_core) + { + /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ + MALI_PRINT_ERROR(("Failed to create PP object\n")); + mali_group_delete(group); + return _MALI_OSK_ERR_FAULT; + } + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_groups(void) +{ + struct mali_group *group; + int cluster_id_gp = 0; + int cluster_id_pp_grp0 = 0; + int cluster_id_pp_grp1 = 0; + int i; + + _mali_osk_resource_t resource_gp; + _mali_osk_resource_t resource_gp_mmu; + _mali_osk_resource_t resource_pp[8]; + _mali_osk_resource_t resource_pp_mmu[8]; + _mali_osk_resource_t resource_pp_mmu_bcast; + _mali_osk_resource_t resource_pp_bcast; + _mali_osk_resource_t resource_dlbu; + _mali_osk_resource_t resource_bcast; + _mali_osk_errcode_t resource_gp_found; + _mali_osk_errcode_t resource_gp_mmu_found; + _mali_osk_errcode_t resource_pp_found[8]; + _mali_osk_errcode_t resource_pp_mmu_found[8]; + _mali_osk_errcode_t resource_pp_mmu_bcast_found; + _mali_osk_errcode_t resource_pp_bcast_found; + _mali_osk_errcode_t resource_dlbu_found; + _mali_osk_errcode_t resource_bcast_found; + + if (!(mali_is_mali400() || mali_is_mali450())) + { + /* No known HW core */ + return _MALI_OSK_ERR_FAULT; + } + + if (mali_is_mali450()) + { + /* Mali-450 have separate L2s for GP, and PP core group(s) */ + cluster_id_pp_grp0 = 1; + cluster_id_pp_grp1 = 2; + } + + resource_gp_found = _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_gp); + resource_gp_mmu_found = _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_gp_mmu); + resource_pp_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x08000, &(resource_pp[0])); + resource_pp_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x0A000, &(resource_pp[1])); + resource_pp_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x0C000, &(resource_pp[2])); + resource_pp_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x0E000, &(resource_pp[3])); + resource_pp_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x28000, &(resource_pp[4])); + resource_pp_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x2A000, &(resource_pp[5])); + resource_pp_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x2C000, &(resource_pp[6])); + resource_pp_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x2E000, &(resource_pp[7])); + resource_pp_mmu_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x04000, &(resource_pp_mmu[0])); + resource_pp_mmu_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x05000, &(resource_pp_mmu[1])); + resource_pp_mmu_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x06000, &(resource_pp_mmu[2])); + resource_pp_mmu_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x07000, &(resource_pp_mmu[3])); + resource_pp_mmu_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x1C000, &(resource_pp_mmu[4])); + resource_pp_mmu_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x1D000, &(resource_pp_mmu[5])); + resource_pp_mmu_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x1E000, &(resource_pp_mmu[6])); + resource_pp_mmu_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x1F000, &(resource_pp_mmu[7])); + + + if (mali_is_mali450()) + { + resource_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x13000, &resource_bcast); + resource_dlbu_found = _mali_osk_resource_find(global_gpu_base_address + 0x14000, &resource_dlbu); + resource_pp_mmu_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x15000, &resource_pp_mmu_bcast); + resource_pp_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x16000, &resource_pp_bcast); + + if (_MALI_OSK_ERR_OK != resource_bcast_found || + _MALI_OSK_ERR_OK != resource_dlbu_found || + _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found || + _MALI_OSK_ERR_OK != resource_pp_bcast_found) + { + /* Missing mandatory core(s) for Mali-450 */ + MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n")); + return _MALI_OSK_ERR_FAULT; + } + } + + if (_MALI_OSK_ERR_OK != resource_gp_found || + _MALI_OSK_ERR_OK != resource_gp_mmu_found || + _MALI_OSK_ERR_OK != resource_pp_found[0] || + _MALI_OSK_ERR_OK != resource_pp_mmu_found[0]) + { + /* Missing mandatory core(s) */ + MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n")); + return _MALI_OSK_ERR_FAULT; + } + + MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores()); + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_gp), &resource_gp_mmu, &resource_gp, NULL); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + + /* Create group for first (and mandatory) PP core */ + MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */ + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0]); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + if (mali_is_mali450()) + { + mali_pm_domain_add_group(MALI_PMU_M450_DOM1, group); + } + else + { + mali_pm_domain_add_group(MALI_PMU_M400_PP0, group); + } + mali_inited_pp_cores_group_1++; + + /* Create groups for rest of the cores in the first PP core group */ + for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */ + { + if (mali_inited_pp_cores_group_1 < mali_max_pp_cores_group_1) + { + if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) + { + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i]); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + if (mali_is_mali450()) + { + mali_pm_domain_add_group(MALI_PMU_M450_DOM2, group); + } + else + { + mali_pm_domain_add_group(MALI_PMU_M400_PP0 + i, group); + } + mali_inited_pp_cores_group_1++; + } + } + } + + /* Create groups for cores in the second PP core group */ + for (i = 4; i < 8; i++) /* Second half of the PP cores belong to second core group */ + { + if (mali_inited_pp_cores_group_2 < mali_max_pp_cores_group_2) + { + if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) + { + MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */ + group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i]); + if (NULL == group) + { + return _MALI_OSK_ERR_FAULT; + } + mali_pm_domain_add_group(MALI_PMU_M450_DOM3, group); + mali_inited_pp_cores_group_2++; + } + } + } + + if(mali_is_mali450()) + { + _mali_osk_errcode_t err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast); + if (_MALI_OSK_ERR_OK != err) + { + return err; + } + } + + mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1; + mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2; + MALI_DEBUG_PRINT(2, ("%d+%d PP cores initialized\n", mali_inited_pp_cores_group_1, mali_inited_pp_cores_group_2)); + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_check_shared_interrupts(void) +{ +#if !defined(CONFIG_MALI_SHARED_INTERRUPTS) + if (MALI_TRUE == _mali_osk_shared_interrupts()) + { + MALI_PRINT_ERROR(("Shared interrupts detected, but driver support is not enabled\n")); + return _MALI_OSK_ERR_FAULT; + } +#endif /* !defined(CONFIG_MALI_SHARED_INTERRUPTS) */ + + /* It is OK to compile support for shared interrupts even if Mali is not using it. */ + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_create_pm_domains(void) +{ + struct mali_pm_domain *domain; + u32 number_of_pp_cores = 0; + u32 number_of_l2_caches = 0; + + mali_resource_count(&number_of_pp_cores, &number_of_l2_caches); + + if (mali_is_mali450()) + { + MALI_DEBUG_PRINT(2, ("Creating PM domains for Mali-450 MP%d\n", number_of_pp_cores)); + switch (number_of_pp_cores) + { + case 8: /* Fall through */ + case 6: /* Fall through */ + domain = mali_pm_domain_create(MALI_PMU_M450_DOM3, MALI_PMU_M450_DOM3_MASK); + MALI_CHECK(NULL != domain, _MALI_OSK_ERR_NOMEM); + case 4: /* Fall through */ + case 3: /* Fall through */ + case 2: /* Fall through */ + domain = mali_pm_domain_create(MALI_PMU_M450_DOM2, MALI_PMU_M450_DOM2_MASK); + MALI_CHECK(NULL != domain, _MALI_OSK_ERR_NOMEM); + domain = mali_pm_domain_create(MALI_PMU_M450_DOM1, MALI_PMU_M450_DOM1_MASK); + MALI_CHECK(NULL != domain, _MALI_OSK_ERR_NOMEM); + + break; + default: + MALI_PRINT_ERROR(("Unsupported core configuration\n")); + MALI_DEBUG_ASSERT(0); + } + } + else + { + int i; + u32 mask = MALI_PMU_M400_PP0_MASK; + + MALI_DEBUG_PRINT(2, ("Creating PM domains for Mali-400 MP%d\n", number_of_pp_cores)); + + MALI_DEBUG_ASSERT(mali_is_mali400()); + + for (i = 0; i < number_of_pp_cores; i++) + { + MALI_CHECK(NULL != mali_pm_domain_create(i, mask), _MALI_OSK_ERR_NOMEM); + + /* Shift mask up, for next core */ + mask = mask << 1; + } + } + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_pmu(void) +{ + _mali_osk_resource_t resource_pmu; + + MALI_DEBUG_ASSERT(0 != global_gpu_base_address); + + if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu)) + { + struct mali_pmu_core *pmu; + u32 number_of_pp_cores = 0; + u32 number_of_l2_caches = 0; + + mali_resource_count(&number_of_pp_cores, &number_of_l2_caches); + + pmu = mali_pmu_create(&resource_pmu, number_of_pp_cores, number_of_l2_caches); + if (NULL == pmu) + { + MALI_PRINT_ERROR(("Failed to create PMU\n")); + return _MALI_OSK_ERR_FAULT; + } + } + + /* It's ok if the PMU doesn't exist */ + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_parse_config_memory(void) +{ + _mali_osk_errcode_t ret; + + if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) + { + /* Memory settings are not overridden by module parameters, so use device settings */ + struct _mali_osk_device_data data = { 0, }; + + if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) + { + /* Use device specific settings (if defined) */ + mali_dedicated_mem_start = data.dedicated_mem_start; + mali_dedicated_mem_size = data.dedicated_mem_size; + mali_shared_mem_size = data.shared_mem_size; + } + + if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) + { + /* No GPU memory specified */ + return _MALI_OSK_ERR_INVALID_ARGS; + } + + MALI_DEBUG_PRINT(2, ("Using device defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n", + mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size)); + } + else + { + MALI_DEBUG_PRINT(2, ("Using module defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n", + mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size)); + } + + if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start) + { + /* Dedicated memory */ + ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register dedicated memory\n")); + mali_memory_terminate(); + return ret; + } + } + + if (0 < mali_shared_mem_size) + { + /* Shared OS memory */ + ret = mali_memory_core_resource_os_memory(mali_shared_mem_size); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register shared OS memory\n")); + mali_memory_terminate(); + return ret; + } + } + + if (0 == mali_fb_start && 0 == mali_fb_size) + { + /* Frame buffer settings are not overridden by module parameters, so use device settings */ + struct _mali_osk_device_data data = { 0, }; + + if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) + { + /* Use device specific settings (if defined) */ + mali_fb_start = data.fb_start; + mali_fb_size = data.fb_size; + } + + MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n", + mali_fb_size, mali_fb_start)); + } + else + { + MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n", + mali_fb_size, mali_fb_start)); + } + + if (0 != mali_fb_size) + { + /* Register frame buffer */ + ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n")); + mali_memory_terminate(); + return ret; + } + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_initialize_subsystems(void) +{ + _mali_osk_errcode_t err; + struct mali_pmu_core *pmu; + + err = mali_session_initialize(); + if (_MALI_OSK_ERR_OK != err) goto session_init_failed; + +#if defined(CONFIG_MALI400_PROFILING) + err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); + if (_MALI_OSK_ERR_OK != err) + { + /* No biggie if we weren't able to initialize the profiling */ + MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); + } +#endif + + err = mali_memory_initialize(); + if (_MALI_OSK_ERR_OK != err) goto memory_init_failed; + + /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */ + err = mali_parse_config_memory(); + if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed; + + err = mali_set_global_gpu_base_address(); + if (_MALI_OSK_ERR_OK != err) goto set_global_gpu_base_address_failed; + + err = mali_check_shared_interrupts(); + if (_MALI_OSK_ERR_OK != err) goto check_shared_interrupts_failed; + + err = mali_pp_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed; + + /* Initialize the power management module */ + err = mali_pm_initialize(); + if (_MALI_OSK_ERR_OK != err) goto pm_init_failed; + + /* Initialize the MALI PMU */ + err = mali_parse_config_pmu(); + if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed; + + /* Make sure the power stays on for the rest of this function */ + err = _mali_osk_pm_dev_ref_add(); + if (_MALI_OSK_ERR_OK != err) goto pm_always_on_failed; + + /* + * If run-time PM is used, then the mali_pm module has now already been + * notified that the power now is on (through the resume callback functions). + * However, if run-time PM is not used, then there will probably not be any + * calls to the resume callback functions, so we need to explicitly tell it + * that the power is on. + */ + mali_pm_set_power_is_on(); + + /* Reset PMU HW and ensure all Mali power domains are on */ + pmu = mali_pmu_get_global_pmu_core(); + if (NULL != pmu) + { + err = mali_pmu_reset(pmu); + if (_MALI_OSK_ERR_OK != err) goto pmu_reset_failed; + } + + /* Detect which Mali GPU we are dealing with */ + err = mali_parse_product_info(); + if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed; + + /* The global_product_id is now populated with the correct Mali GPU */ + + /* Create PM domains only if PMU exists */ + if (NULL != pmu) + { + err = mali_create_pm_domains(); + if (_MALI_OSK_ERR_OK != err) goto pm_domain_failed; + } + + /* Initialize MMU module */ + err = mali_mmu_initialize(); + if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed; + + if (mali_is_mali450()) + { + err = mali_dlbu_initialize(); + if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed; + } + + /* Start configuring the actual Mali hardware. */ + err = mali_parse_config_l2_cache(); + if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; + err = mali_parse_config_groups(); + if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; + + /* Initialize the schedulers */ + err = mali_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed; + err = mali_gp_scheduler_initialize(); + if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed; + + /* PP scheduler population can't fail */ + mali_pp_scheduler_populate(); + + /* Initialize the GPU utilization tracking */ + err = mali_utilization_init(); + if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed; + + /* Allowing the system to be turned off */ + _mali_osk_pm_dev_ref_dec(); + + MALI_SUCCESS; /* all ok */ + + /* Error handling */ + +utilization_init_failed: + mali_pp_scheduler_depopulate(); + mali_gp_scheduler_terminate(); +gp_scheduler_init_failed: + mali_scheduler_terminate(); +scheduler_init_failed: +config_parsing_failed: + mali_delete_groups(); /* Delete any groups not (yet) owned by a scheduler */ + mali_delete_l2_cache_cores(); /* Delete L2 cache cores even if config parsing failed. */ +dlbu_init_failed: + mali_dlbu_terminate(); +mmu_init_failed: + mali_pm_domain_terminate(); +pm_domain_failed: + /* Nothing to roll back */ +product_info_parsing_failed: + /* Nothing to roll back */ +pmu_reset_failed: + /* Allowing the system to be turned off */ + _mali_osk_pm_dev_ref_dec(); +pm_always_on_failed: + pmu = mali_pmu_get_global_pmu_core(); + if (NULL != pmu) + { + mali_pmu_delete(pmu); + } +parse_pmu_config_failed: + mali_pm_terminate(); +pm_init_failed: + mali_pp_scheduler_terminate(); +pp_scheduler_init_failed: +check_shared_interrupts_failed: + global_gpu_base_address = 0; +set_global_gpu_base_address_failed: + global_gpu_base_address = 0; +parse_memory_config_failed: + mali_memory_terminate(); +memory_init_failed: +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_term(); +#endif + mali_session_terminate(); +session_init_failed: + return err; +} + +void mali_terminate_subsystems(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n")); + + /* shut down subsystems in reverse order from startup */ + + /* We need the GPU to be powered up for the terminate sequence */ + _mali_osk_pm_dev_ref_add(); + + mali_utilization_term(); + mali_pp_scheduler_depopulate(); + mali_gp_scheduler_terminate(); + mali_scheduler_terminate(); + mali_delete_l2_cache_cores(); + if (mali_is_mali450()) + { + mali_dlbu_terminate(); + } + mali_mmu_terminate(); + if (NULL != pmu) + { + mali_pmu_delete(pmu); + } + mali_pm_terminate(); + mali_memory_terminate(); +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_term(); +#endif + + /* Allowing the system to be turned off */ + _mali_osk_pm_dev_ref_dec(); + + mali_pp_scheduler_terminate(); + mali_session_terminate(); +} + +_mali_product_id_t mali_kernel_core_get_product_id(void) +{ + return global_product_id; +} + +u32 mali_kernel_core_get_gpu_major_version(void) +{ + return global_gpu_major_version; +} + +u32 mali_kernel_core_get_gpu_minor_version(void) +{ + return global_gpu_minor_version; +} + +_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + /* check compatability */ + if ( args->version == _MALI_UK_API_VERSION ) + { + args->compatible = 1; + } + else + { + args->compatible = 0; + } + + args->version = _MALI_UK_API_VERSION; /* report our version */ + + /* success regardless of being compatible or not */ + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ) +{ + _mali_osk_errcode_t err; + _mali_osk_notification_t * notification; + _mali_osk_notification_queue_t *queue; + + /* check input */ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; + + /* if the queue does not exist we're currently shutting down */ + if (NULL == queue) + { + MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); + args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS; + MALI_SUCCESS; + } + + /* receive a notification, might sleep */ + err = _mali_osk_notification_queue_receive(queue, ¬ification); + if (_MALI_OSK_ERR_OK != err) + { + MALI_ERROR(err); /* errcode returned, pass on to caller */ + } + + /* copy the buffer to the user */ + args->type = (_mali_uk_notification_type)notification->notification_type; + _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size); + + /* finished with the notification */ + _mali_osk_notification_delete( notification ); + + MALI_SUCCESS; /* all ok */ +} + +_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ) +{ + _mali_osk_notification_t * notification; + _mali_osk_notification_queue_t *queue; + + /* check input */ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); + + queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; + + /* if the queue does not exist we're currently shutting down */ + if (NULL == queue) + { + MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); + MALI_SUCCESS; + } + + notification = _mali_osk_notification_create(args->type, 0); + if (NULL == notification) + { + MALI_PRINT_ERROR( ("Failed to create notification object\n")); + return _MALI_OSK_ERR_NOMEM; + } + + _mali_osk_notification_queue_send(queue, notification); + + MALI_SUCCESS; /* all ok */ +} + +_mali_osk_errcode_t _mali_ukk_open(void **context) +{ + struct mali_session_data *session; + + /* allocated struct to track this session */ + session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data)); + MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM); + + MALI_DEBUG_PRINT(3, ("Session starting\n")); + + /* create a response queue for this session */ + session->ioctl_queue = _mali_osk_notification_queue_init(); + if (NULL == session->ioctl_queue) + { + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + session->page_directory = mali_mmu_pagedir_alloc(); + if (NULL == session->page_directory) + { + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) + { + MALI_PRINT_ERROR(("Failed to map DLBU page into session\n")); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + + if (0 != mali_dlbu_phys_addr) + { + mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr, + _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD); + } + + if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session)) + { + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } + +#ifdef CONFIG_SYNC + _mali_osk_list_init(&session->pending_jobs); + session->pending_jobs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK, + 0, _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS); + if (NULL == session->pending_jobs_lock) + { + MALI_PRINT_ERROR(("Failed to create pending jobs lock\n")); + mali_memory_session_end(session); + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + MALI_ERROR(_MALI_OSK_ERR_NOMEM); + } +#endif + + *context = (void*)session; + + /* Add session to the list of all sessions. */ + mali_session_add(session); + + /* Initialize list of jobs on this session */ + _MALI_OSK_INIT_LIST_HEAD(&session->job_list); + + MALI_DEBUG_PRINT(2, ("Session started\n")); + MALI_SUCCESS; +} + +_mali_osk_errcode_t _mali_ukk_close(void **context) +{ + struct mali_session_data *session; + MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS); + session = (struct mali_session_data *)*context; + + MALI_DEBUG_PRINT(3, ("Session ending\n")); + + /* Remove session from list of all sessions. */ + mali_session_remove(session); + + /* Abort pending jobs */ +#ifdef CONFIG_SYNC + { + _mali_osk_list_t tmp_job_list; + struct mali_pp_job *job, *tmp; + _MALI_OSK_INIT_LIST_HEAD(&tmp_job_list); + + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + /* Abort asynchronous wait on fence. */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &session->pending_jobs, struct mali_pp_job, list) + { + MALI_DEBUG_PRINT(2, ("Sync: Aborting wait for session %x job %x\n", session, job)); + if (sync_fence_cancel_async(job->pre_fence, &job->sync_waiter)) + { + MALI_DEBUG_PRINT(2, ("Sync: Failed to abort job %x\n", job)); + } + _mali_osk_list_add(&job->list, &tmp_job_list); + } + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_wq_flush(); + + _mali_osk_lock_term(session->pending_jobs_lock); + + /* Delete jobs */ + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &tmp_job_list, struct mali_pp_job, list) + { + mali_pp_job_delete(job); + } + } +#endif + + /* Abort queued and running jobs */ + mali_gp_scheduler_abort_session(session); + mali_pp_scheduler_abort_session(session); + + /* Flush pending work. + * Needed to make sure all bottom half processing related to this + * session has been completed, before we free internal data structures. + */ + _mali_osk_wq_flush(); + + /* Free remaining memory allocated to this session */ + mali_memory_session_end(session); + + /* Free session data structures */ + mali_mmu_pagedir_free(session->page_directory); + _mali_osk_notification_queue_term(session->ioctl_queue); + _mali_osk_free(session); + + *context = NULL; + + MALI_DEBUG_PRINT(2, ("Session has ended\n")); + + MALI_SUCCESS; +} + +#if MALI_STATE_TRACKING +u32 _mali_kernel_core_dump_state(char* buf, u32 size) +{ + int n = 0; /* Number of bytes written to buf */ + + n += mali_gp_scheduler_dump_state(buf + n, size - n); + n += mali_pp_scheduler_dump_state(buf + n, size - n); + + return n; +} +#endif diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.h index d424c48..bf56b5c 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_core.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_core.h @@ -13,7 +13,6 @@ #include "mali_osk.h" -extern int mali_hang_check_interval; extern int mali_max_job_runtime; typedef enum @@ -29,11 +28,24 @@ _mali_osk_errcode_t mali_initialize_subsystems(void); void mali_terminate_subsystems(void); -void mali_kernel_core_wakeup(void); - _mali_product_id_t mali_kernel_core_get_product_id(void); +u32 mali_kernel_core_get_gpu_major_version(void); + +u32 mali_kernel_core_get_gpu_minor_version(void); + u32 _mali_kernel_core_dump_state(char* buf, u32 size); +MALI_STATIC_INLINE mali_bool mali_is_mali450(void) +{ + return _MALI_PRODUCT_ID_MALI450 == mali_kernel_core_get_product_id(); +} + +MALI_STATIC_INLINE mali_bool mali_is_mali400(void) +{ + u32 id = mali_kernel_core_get_product_id(); + return _MALI_PRODUCT_ID_MALI400 == id || _MALI_PRODUCT_ID_MALI300 == id; +} + #endif /* __MALI_KERNEL_CORE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.c index b9f05ca..b9f05ca 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.c diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.h index 82ed94d..82ed94d 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_descriptor_mapping.h diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.c index 8ff3d37..0ab3a80 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.c @@ -9,7 +9,6 @@ */ #include "mali_kernel_common.h" -#include "mali_kernel_core.h" #include "mali_kernel_memory_engine.h" #include "mali_osk.h" @@ -127,11 +126,12 @@ static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, m allocation = _mali_osk_malloc(sizeof(os_allocation)); if (NULL != allocation) { - u32 os_mem_max_usage = info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE; + /* MALI_SEC */ + //u32 os_mem_max_usage = info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE; allocation->offset_start = *offset; allocation->num_pages = ((left + _MALI_OSK_CPU_PAGE_SIZE - 1) & ~(_MALI_OSK_CPU_PAGE_SIZE - 1)) >> _MALI_OSK_CPU_PAGE_ORDER; MALI_DEBUG_PRINT(6, ("Allocating page array of size %d bytes\n", allocation->num_pages * sizeof(struct page*))); - + /* MALI_SEC */ while (left > 0) { err = mali_allocation_engine_map_physical(engine, descriptor, *offset, MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, info->cpu_usage_adjust, _MALI_OSK_CPU_PAGE_SIZE); @@ -243,15 +243,12 @@ static void os_allocator_release(void * ctx, void * handle) static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) { -#if defined(CONFIG_MACH_KONA) +/* MALI_SEC 6->10 */ #ifndef CONFIG_FORCE_MAX_ZONEORDER int allocation_order = 10; #else int allocation_order = CONFIG_FORCE_MAX_ZONEORDER - 1; #endif -#else - int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ -#endif void *virt = NULL; u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; os_allocator * info; diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.h index 59e6494..0946169 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_mem_os.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.c index d770e3e..00257ec 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.c @@ -9,7 +9,6 @@ */ #include "mali_kernel_common.h" -#include "mali_kernel_core.h" #include "mali_kernel_memory_engine.h" #include "mali_osk.h" #include "mali_osk_list.h" diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.h index 3b41cee..3b41cee 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_memory_engine.h diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c new file mode 100644 index 0000000..9dae2e8 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.c @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2010-2012 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 "mali_kernel_utilization.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_kernel_common.h" + +/* Define how often to calculate and report GPU utilization, in milliseconds */ +static _mali_osk_lock_t *time_data_lock; + +static u32 num_running_gp_cores; +static u32 num_running_pp_cores; + +static u64 work_start_time_gpu = 0; +static u64 work_start_time_gp = 0; +static u64 work_start_time_pp = 0; +static u64 accumulated_work_time_gpu = 0; +static u64 accumulated_work_time_gp = 0; +static u64 accumulated_work_time_pp = 0; + +static u64 period_start_time = 0; + +#ifndef CONFIG_PM_DEVFREQ /* MALI_SEC */ +static _mali_osk_timer_t *utilization_timer = NULL; +#endif +static mali_bool timer_running = MALI_FALSE; + +static u32 last_utilization_gpu = 0 ; +static u32 last_utilization_gp = 0 ; +static u32 last_utilization_pp = 0 ; + +#ifndef CONFIG_PM_DEVFREQ /* MALI_SEC */ +static u32 mali_utilization_timeout = 100; +#endif +void (*mali_utilization_callback)(struct mali_gpu_utilization_data *data) = NULL; + +#ifndef CONFIG_PM_DEVFREQ +static void calculate_gpu_utilization(void* arg) +{ +#else +void calculate_gpu_utilization(void *arg) +{ +#endif + u64 time_now; + u64 time_period; + u32 leading_zeroes; + u32 shift_val; + u32 work_normalized_gpu; + u32 work_normalized_gp; + u32 work_normalized_pp; + u32 period_normalized; + u32 utilization_gpu; + u32 utilization_gp; + u32 utilization_pp; + + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (accumulated_work_time_gpu == 0 && work_start_time_gpu == 0) + { + /* + * No work done for this period + * - No need to reschedule timer + * - Report zero usage + */ + timer_running = MALI_FALSE; + + last_utilization_gpu = 0; + last_utilization_gp = 0; + last_utilization_pp = 0; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (NULL != mali_utilization_callback) + { + struct mali_gpu_utilization_data data = { 0, }; + mali_utilization_callback(&data); + } + + return; + } + + time_now = _mali_osk_time_get_ns(); + + time_period = time_now - period_start_time; + + /* If we are currently busy, update working period up to now */ + if (work_start_time_gpu != 0) + { + accumulated_work_time_gpu += (time_now - work_start_time_gpu); + work_start_time_gpu = time_now; + + /* GP and/or PP will also be busy if the GPU is busy at this point */ + + if (work_start_time_gp != 0) + { + accumulated_work_time_gp += (time_now - work_start_time_gp); + work_start_time_gp = time_now; + } + + if (work_start_time_pp != 0) + { + accumulated_work_time_pp += (time_now - work_start_time_pp); + work_start_time_pp = time_now; + } + } + + /* + * We have two 64-bit values, a dividend and a divisor. + * To avoid dependencies to a 64-bit divider, we shift down the two values + * equally first. + * We shift the dividend up and possibly the divisor down, making the result X in 256. + */ + + /* Shift the 64-bit values down so they fit inside a 32-bit integer */ + leading_zeroes = _mali_osk_clz((u32)(time_period >> 32)); + shift_val = 32 - leading_zeroes; + work_normalized_gpu = (u32)(accumulated_work_time_gpu >> shift_val); + work_normalized_gp = (u32)(accumulated_work_time_gp >> shift_val); + work_normalized_pp = (u32)(accumulated_work_time_pp >> shift_val); + period_normalized = (u32)(time_period >> shift_val); + + /* + * Now, we should report the usage in parts of 256 + * this means we must shift up the dividend or down the divisor by 8 + * (we could do a combination, but we just use one for simplicity, + * but the end result should be good enough anyway) + */ + if (period_normalized > 0x00FFFFFF) + { + /* The divisor is so big that it is safe to shift it down */ + period_normalized >>= 8; + } + else + { + /* + * The divisor is so small that we can shift up the dividend, without loosing any data. + * (dividend is always smaller than the divisor) + */ + work_normalized_gpu <<= 8; + work_normalized_gp <<= 8; + work_normalized_pp <<= 8; + } + + utilization_gpu = work_normalized_gpu / period_normalized; + utilization_gp = work_normalized_gp / period_normalized; + utilization_pp = work_normalized_pp / period_normalized; + + last_utilization_gpu = utilization_gpu; + last_utilization_gp = utilization_gp; + last_utilization_pp = utilization_pp; + + /* starting a new period */ + accumulated_work_time_gpu = 0; + accumulated_work_time_gp = 0; + accumulated_work_time_pp = 0; + period_start_time = time_now; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + +#ifndef CONFIG_PM_DEVFREQ + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout)); +#endif + + if (NULL != mali_utilization_callback) + { + struct mali_gpu_utilization_data data = { utilization_gpu, utilization_gp, utilization_pp }; + mali_utilization_callback(&data); + } +} + +_mali_osk_errcode_t mali_utilization_init(void) +{ +#if USING_GPU_UTILIZATION + struct _mali_osk_device_data data; + if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) + { + /* Use device specific settings (if defined) */ +#ifndef CONFIG_PM_DEVFREQ + if (0 != data.utilization_interval) + { + mali_utilization_timeout = data.utilization_interval; + } +#endif + if (NULL != data.utilization_callback) + { + mali_utilization_callback = data.utilization_callback; + } + } +#endif + + if (NULL != mali_utilization_callback) + { +#ifndef CONFIG_PM_DEVFREQ + MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: Utilization handler installed with interval %u\n", mali_utilization_timeout)); +#endif + } + else + { + MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: No utilization handler installed\n")); + } + + time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | + _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION); + + if (NULL == time_data_lock) + { + return _MALI_OSK_ERR_FAULT; + } + + num_running_gp_cores = 0; + num_running_pp_cores = 0; + +#ifndef CONFIG_PM_DEVFREQ + utilization_timer = _mali_osk_timer_init(); + if (NULL == utilization_timer) + { + _mali_osk_lock_term(time_data_lock); + return _MALI_OSK_ERR_FAULT; + } + _mali_osk_timer_setcallback(utilization_timer, calculate_gpu_utilization, NULL); +#endif + + return _MALI_OSK_ERR_OK; +} + +#ifndef CONFIG_PM_DEVFREQ +void mali_utilization_suspend(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (timer_running == MALI_TRUE) + { + timer_running = MALI_FALSE; + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_timer_del(utilization_timer); + return; + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +} +#endif + +void mali_utilization_term(void) +{ +#ifndef CONFIG_PM_DEVFREQ + if (NULL != utilization_timer) + { + _mali_osk_timer_del(utilization_timer); + timer_running = MALI_FALSE; + _mali_osk_timer_term(utilization_timer); + utilization_timer = NULL; + } +#endif + + _mali_osk_lock_term(time_data_lock); +} + +void mali_utilization_gp_start(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + ++num_running_gp_cores; + if (1 == num_running_gp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* First GP core started, consider GP busy from now and onwards */ + work_start_time_gp = time_now; + + if (0 == num_running_pp_cores) + { + /* + * There are no PP cores running, so this is also the point + * at which we consider the GPU to be busy as well. + */ + work_start_time_gpu = time_now; + } + + /* Start a new period (and timer) if needed */ + if (timer_running != MALI_TRUE) + { + timer_running = MALI_TRUE; + period_start_time = time_now; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout)); + } + else + { + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } + } + else + { + /* Nothing to do */ + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} + +void mali_utilization_pp_start(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + ++num_running_pp_cores; + if (1 == num_running_pp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* First PP core started, consider PP busy from now and onwards */ + work_start_time_pp = time_now; + + if (0 == num_running_gp_cores) + { + /* + * There are no GP cores running, so this is also the point + * at which we consider the GPU to be busy as well. + */ + work_start_time_gpu = time_now; + } + + /* Start a new period (and timer) if needed */ + if (timer_running != MALI_TRUE) + { + timer_running = MALI_TRUE; + period_start_time = time_now; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +#ifndef CONFIG_PM_DEVFREQ + _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout)); +#endif + } + else + { + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } + } + else + { + /* Nothing to do */ + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} + +void mali_utilization_gp_end(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + --num_running_gp_cores; + if (0 == num_running_gp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* Last GP core ended, consider GP idle from now and onwards */ + accumulated_work_time_gp += (time_now - work_start_time_gp); + work_start_time_gp = 0; + + if (0 == num_running_pp_cores) + { + /* + * There are no PP cores running, so this is also the point + * at which we consider the GPU to be idle as well. + */ + accumulated_work_time_gpu += (time_now - work_start_time_gpu); + work_start_time_gpu = 0; + } + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +} + +void mali_utilization_pp_end(void) +{ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + --num_running_pp_cores; + if (0 == num_running_pp_cores) + { + u64 time_now = _mali_osk_time_get_ns(); + + /* Last PP core ended, consider PP idle from now and onwards */ + accumulated_work_time_pp += (time_now - work_start_time_pp); + work_start_time_pp = 0; + + if (0 == num_running_gp_cores) + { + /* + * There are no GP cores running, so this is also the point + * at which we consider the GPU to be idle as well. + */ + accumulated_work_time_gpu += (time_now - work_start_time_gpu); + work_start_time_gpu = 0; + } + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); +} + +u32 _mali_ukk_utilization_gp_pp(void) +{ + return last_utilization_gpu; +} + +u32 _mali_ukk_utilization_gp(void) +{ + return last_utilization_gp; +} + +u32 _mali_ukk_utilization_pp(void) +{ + return last_utilization_pp; +} diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.h index 1f60517..6ee5101 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_utilization.h @@ -11,8 +11,14 @@ #ifndef __MALI_KERNEL_UTILIZATION_H__ #define __MALI_KERNEL_UTILIZATION_H__ +#include <linux/mali/mali_utgard.h> #include "mali_osk.h" +extern void (*mali_utilization_callback)(struct mali_gpu_utilization_data *data); + +#ifdef CONFIG_PM_DEVFREQ /* MALI_SEC */ +void calculate_gpu_utilization(void *arg); +#endif /** * Initialize/start the Mali GPU utilization metrics reporting. * @@ -26,19 +32,37 @@ _mali_osk_errcode_t mali_utilization_init(void); void mali_utilization_term(void); /** - * Should be called when a job is about to execute a job + * Check if Mali utilization is enabled */ -void mali_utilization_core_start(u64 time_now); +MALI_STATIC_INLINE mali_bool mali_utilization_enabled(void) +{ + return (NULL != mali_utilization_callback); +} /** - * Should be called to stop the utilization timer during system suspend + * Should be called when a job is about to execute a GP job */ -void mali_utilization_suspend(void); +void mali_utilization_gp_start(void); + +/** + * Should be called when a job has completed executing a GP job + */ +void mali_utilization_gp_end(void); + +/** + * Should be called when a job is about to execute a PP job + */ +void mali_utilization_pp_start(void); /** - * Should be called when a job has completed executing a job + * Should be called when a job has completed executing a PP job */ -void mali_utilization_core_end(u64 time_now); +void mali_utilization_pp_end(void); + +/** + * Should be called to stop the utilization timer during system suspend + */ +void mali_utilization_suspend(void); #endif /* __MALI_KERNEL_UTILIZATION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_vsync.c index 63c9f5b..a1fdf00 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_kernel_vsync.c @@ -12,7 +12,7 @@ #include "mali_osk.h" #include "mali_ukk.h" -#if MALI_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_PROFILING) #include "mali_osk_profiling.h" #endif @@ -21,7 +21,7 @@ _mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s * _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event; MALI_IGNORE(event); /* event is not used for release code, and that is OK */ -#if MALI_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_PROFILING) /* * Manually generate user space events in kernel space. * This saves user space from calling kernel space twice in this case. diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.c b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.c index b7267f1..b5cfcb5 100644 --- a/drivers/media/video/samsung/mali/common/mali_l2_cache.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.c @@ -9,18 +9,16 @@ */ #include "mali_kernel_common.h" #include "mali_osk.h" - #include "mali_l2_cache.h" #include "mali_hw_core.h" -#include "mali_pm.h" +#include "mali_scheduler.h" +#include "mali_pm_domain.h" /** * Size of the Mali L2 cache registers in bytes */ #define MALI400_L2_CACHE_REGISTERS_SIZE 0x30 -#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES 3 - /** * Mali L2 cache register numbers * Used in the register read/write routines. @@ -69,24 +67,9 @@ typedef enum mali_l2_cache_status MALI400_L2_CACHE_STATUS_DATA_BUSY = 0x02, /**< L2 cache is busy handling data requests */ } mali_l2_cache_status; -/** - * Definition of the L2 cache core struct - * Used to track a L2 cache unit in the system. - * Contains information about the mapping of the registers - */ -struct mali_l2_cache_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - u32 core_id; /**< Unique core ID */ - _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */ - _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */ - u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ -}; - #define MALI400_L2_MAX_READS_DEFAULT 0x1C -static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES]; +static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES] = { NULL, }; static u32 mali_global_num_l2_cache_cores = 0; int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT; @@ -98,6 +81,13 @@ static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource) { struct mali_l2_cache_core *cache = NULL; + _mali_osk_lock_flags_t lock_flags; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#else + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#endif MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description)); @@ -113,29 +103,23 @@ struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource) cache->core_id = mali_global_num_l2_cache_cores; cache->counter_src0 = MALI_HW_CORE_NO_COUNTER; cache->counter_src1 = MALI_HW_CORE_NO_COUNTER; + cache->pm_domain = NULL; if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE)) { - cache->command_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, - 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND); + cache->command_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND); if (NULL != cache->command_lock) { - cache->counter_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, - 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER); + cache->counter_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER); if (NULL != cache->counter_lock) { - if (_MALI_OSK_ERR_OK == mali_l2_cache_reset(cache)) - { - mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache; - mali_global_num_l2_cache_cores++; - - return cache; - } - else - { - MALI_PRINT_ERROR(("Mali L2 cache: Failed to reset L2 cache core %s\n", cache->hw_core.description)); - } - - _mali_osk_lock_term(cache->counter_lock); + mali_l2_cache_reset(cache); + + cache->last_invalidated_id = 0; + + mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache; + mali_global_num_l2_cache_cores++; + + return cache; } else { @@ -180,6 +164,16 @@ void mali_l2_cache_delete(struct mali_l2_cache_core *cache) { mali_global_l2_cache_cores[i] = NULL; mali_global_num_l2_cache_cores--; + + if (i != mali_global_num_l2_cache_cores) + { + /* We removed a l2 cache from the middle of the array -- move the last + * l2 cache to the current position to close the gap */ + mali_global_l2_cache_cores[i] = mali_global_l2_cache_cores[mali_global_num_l2_cache_cores]; + mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = NULL; + } + + break; } } @@ -280,7 +274,7 @@ void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0); } - if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) + if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) { *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1); } @@ -290,7 +284,7 @@ void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index) { - if (MALI_MAX_NUMBER_OF_L2_CACHE_CORES > index) + if (mali_global_num_l2_cache_cores > index) { return mali_global_l2_cache_cores[index]; } @@ -303,15 +297,10 @@ u32 mali_l2_cache_core_get_glob_num_l2_cores(void) return mali_global_num_l2_cache_cores; } -u32 mali_l2_cache_core_get_max_num_l2_cores(void) -{ - return MALI_MAX_NUMBER_OF_L2_CACHE_CORES; -} - -_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache) +void mali_l2_cache_reset(struct mali_l2_cache_core *cache) { /* Invalidate cache (just to keep it in a known state at startup) */ - mali_l2_cache_invalidate_all(cache); + mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); /* Enable cache */ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE); @@ -331,47 +320,107 @@ _mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache) } _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW); +} + +void mali_l2_cache_reset_all(void) +{ + int i; + u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores(); - return _MALI_OSK_ERR_OK; + for (i = 0; i < num_cores; i++) + { + mali_l2_cache_reset(mali_l2_cache_core_get_glob_l2_core(i)); + } } -_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache) +void mali_l2_cache_invalidate(struct mali_l2_cache_core *cache) { - return mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + MALI_DEBUG_ASSERT_POINTER(cache); + + if (NULL != cache) + { + cache->last_invalidated_id = mali_scheduler_get_new_id(); + mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + } } -_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages) +mali_bool mali_l2_cache_invalidate_conditional(struct mali_l2_cache_core *cache, u32 id) { - u32 i; - _mali_osk_errcode_t ret1, ret = _MALI_OSK_ERR_OK; + MALI_DEBUG_ASSERT_POINTER(cache); - for (i = 0; i < num_pages; i++) + if (NULL != cache) { - ret1 = mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[i]); - if (_MALI_OSK_ERR_OK != ret1) + /* If the last cache invalidation was done by a job with a higher id we + * don't have to flush. Since user space will store jobs w/ their + * corresponding memory in sequence (first job #0, then job #1, ...), + * we don't have to flush for job n-1 if job n has already invalidated + * the cache since we know for sure that job n-1's memory was already + * written when job n was started. */ + if (((s32)id) <= ((s32)cache->last_invalidated_id)) + { + return MALI_FALSE; + } + else { - ret = ret1; + cache->last_invalidated_id = mali_scheduler_get_new_id(); } + + mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); } + return MALI_TRUE; +} - return ret; +void mali_l2_cache_invalidate_all(void) +{ + u32 i; + for (i = 0; i < mali_global_num_l2_cache_cores; i++) + { + /*additional check*/ + if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i])) + { + _mali_osk_errcode_t ret; + mali_global_l2_cache_cores[i]->last_invalidated_id = mali_scheduler_get_new_id(); + ret = mali_l2_cache_send_command(mali_global_l2_cache_cores[i], MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to invalidate cache\n")); + } + } + mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]); + } +} + +void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages) +{ + u32 i; + for (i = 0; i < mali_global_num_l2_cache_cores; i++) + { + /*additional check*/ + if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i])) + { + u32 j; + for (j = 0; j < num_pages; j++) + { + _mali_osk_errcode_t ret; + ret = mali_l2_cache_send_command(mali_global_l2_cache_cores[i], MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[j]); + if (_MALI_OSK_ERR_OK != ret) + { + MALI_PRINT_ERROR(("Failed to invalidate page cache\n")); + } + } + } + mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]); + } } mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache) { - /* - * Take PM lock and check power state. - * Returns MALI_TRUE if module is powered on. - * Power state will not change until mali_l2_cache_unlock_power_state() is called. - */ - mali_pm_lock(); - return mali_pm_is_powered_on(); + return mali_pm_domain_lock_state(cache->pm_domain); } void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache) { - /* Release PM lock */ - mali_pm_unlock(); + return mali_pm_domain_unlock_state(cache->pm_domain); } /* -------- local helper functions below -------- */ diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.h b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.h index 5a8e4da..cabed39 100644 --- a/drivers/media/video/samsung/mali/common/mali_l2_cache.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_l2_cache.h @@ -12,8 +12,31 @@ #define __MALI_KERNEL_L2_CACHE_H__ #include "mali_osk.h" +#include "mali_hw_core.h" +#include "mali_pm_domain.h" -struct mali_l2_cache_core; +#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES 3 +/* Maximum 1 GP and 4 PP for an L2 cache core (Mali-400 Quad-core) */ +#define MALI_MAX_NUMBER_OF_GROUPS_PER_L2_CACHE 5 + +struct mali_group; + +/** + * Definition of the L2 cache core struct + * Used to track a L2 cache unit in the system. + * Contains information about the mapping of the registers + */ +struct mali_l2_cache_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + u32 core_id; /**< Unique core ID */ + _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */ + _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */ + u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + u32 last_invalidated_id; + struct mali_pm_domain *pm_domain; +}; _mali_osk_errcode_t mali_l2_cache_initialize(void); void mali_l2_cache_terminate(void); @@ -21,6 +44,11 @@ void mali_l2_cache_terminate(void); struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t * resource); void mali_l2_cache_delete(struct mali_l2_cache_core *cache); +MALI_STATIC_INLINE void mali_l2_cache_set_pm_domain(struct mali_l2_cache_core *cache, struct mali_pm_domain *domain) +{ + cache->pm_domain = domain; +} + u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache); mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter); @@ -30,12 +58,16 @@ u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache); void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1); struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index); u32 mali_l2_cache_core_get_glob_num_l2_cores(void); -u32 mali_l2_cache_core_get_max_num_l2_cores(void); -_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache); +void mali_l2_cache_reset(struct mali_l2_cache_core *cache); +void mali_l2_cache_reset_all(void); + +struct mali_group *mali_l2_cache_get_group(struct mali_l2_cache_core *cache, u32 index); -_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache); -_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages); +void mali_l2_cache_invalidate(struct mali_l2_cache_core *cache); +mali_bool mali_l2_cache_invalidate_conditional(struct mali_l2_cache_core *cache, u32 id); +void mali_l2_cache_invalidate_all(void); +void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages); mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache); void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache); diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c index ea9c428..aaf9c73 100644 --- a/drivers/media/video/samsung/mali/common/mali_mem_validation.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.c @@ -11,6 +11,13 @@ #include "mali_mem_validation.h" #include "mali_osk.h" #include "mali_kernel_common.h" +/* MALI_SEC */ +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +//#define MALI_SEC_MEM_VALIDATION +#include <linux/cma.h> +#include <plat/pd.h> +#include <linux/platform_device.h> +#endif #define MALI_INVALID_MEM_ADDR 0xFFFFFFFF @@ -20,29 +27,50 @@ typedef struct u32 size; /**< size in bytes of the memory, multiple of page size */ } _mali_mem_validation_t; +/* MALI_SEC */ +#if defined(MALI_SEC_MEM_VALIDATION) +extern struct platform_device exynos4_device_pd[]; +#endif + static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR }; -_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t *resource) +_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size) { + /* MALI_SEC */ +#if defined(MALI_SEC_MEM_VALIDATION) + struct cma_info mem_info; +#endif + /* Check that no other MEM_VALIDATION resources exist */ if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base) { - MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; another range is already specified\n", resource->description)); + MALI_PRINT_ERROR(("Failed to add frame buffer memory; another range is already specified\n")); + return _MALI_OSK_ERR_FAULT; + } + + /* MALI_SEC */ +#if defined(MALI_SEC_MEM_VALIDATION) + if (cma_info(&mem_info, &exynos4_device_pd[PD_G3D].dev, "fimd")) { + MALI_PRINT_ERROR(("Failed to get framebuffer information from CMA\n")); return _MALI_OSK_ERR_FAULT; + } else { + start = mem_info.lower_bound; + size = mem_info.total_size - mem_info.free_size; } +#endif /* Check restrictions on page alignment */ - if ((0 != (resource->base & (~_MALI_OSK_CPU_PAGE_MASK))) || - (0 != (resource->size & (~_MALI_OSK_CPU_PAGE_MASK)))) + if ((0 != (start & (~_MALI_OSK_CPU_PAGE_MASK))) || + (0 != (size & (~_MALI_OSK_CPU_PAGE_MASK)))) { - MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; incorrect alignment\n", resource->description)); + MALI_PRINT_ERROR(("Failed to add frame buffer memory; incorrect alignment\n")); return _MALI_OSK_ERR_FAULT; } - mali_mem_validator.phys_base = resource->base; - mali_mem_validator.size = resource->size; - MALI_DEBUG_PRINT(2, ("Memory Validator '%s' installed for Mali physical address base=0x%08X, size=0x%08X\n", - resource->description, mali_mem_validator.phys_base, mali_mem_validator.size)); + mali_mem_validator.phys_base = start; + mali_mem_validator.size = size; + MALI_DEBUG_PRINT(2, ("Memory Validator installed for Mali physical address base=0x%08X, size=0x%08X\n", + mali_mem_validator.phys_base, mali_mem_validator.size)); return _MALI_OSK_ERR_OK; } diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.h b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.h index 2043b44..1eeab38 100644 --- a/drivers/media/video/samsung/mali/common/mali_mem_validation.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mem_validation.h @@ -13,7 +13,7 @@ #include "mali_osk.h" -_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t * resource); +_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size); _mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size); #endif /* __MALI_MEM_VALIDATION_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_memory.c b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.c index 75506ed..1654675 100644 --- a/drivers/media/video/samsung/mali/common/mali_memory.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.c @@ -18,9 +18,8 @@ #include "mali_kernel_mem_os.h" #include "mali_session.h" #include "mali_l2_cache.h" -#include "mali_cluster.h" -#include "mali_group.h" -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#include "mali_scheduler.h" +#if defined(CONFIG_MALI400_UMP) #include "ump_kernel_interface.h" #endif @@ -45,7 +44,7 @@ typedef struct dedicated_memory_info } dedicated_memory_info; /* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */ -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#if defined(CONFIG_MALI400_UMP) typedef struct ump_mem_allocation { mali_allocation_engine * engine; @@ -82,10 +81,10 @@ typedef struct external_mem_allocation */ static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ); -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#if defined(CONFIG_MALI400_UMP) static void ump_memory_release(void * ctx, void * handle); static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0*/ +#endif /* CONFIG_MALI400_UMP */ static void external_memory_release(void * ctx, void * handle); @@ -261,7 +260,7 @@ void mali_memory_session_end(struct mali_session_data *session_data) err = _MALI_OSK_ERR_OK; /* Free all memory engine allocations */ - if (0 == _mali_osk_list_empty(&session_data->memory_head)) + if (!_mali_osk_list_empty(&session_data->memory_head)) { mali_memory_allocation *descriptor; mali_memory_allocation *temp; @@ -332,14 +331,14 @@ void mali_memory_session_end(struct mali_session_data *session_data) return; } -_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource) +_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size) { mali_physical_memory_allocator * allocator; mali_physical_memory_allocator ** next_allocator_list; - u32 alloc_order = resource->alloc_order; + u32 alloc_order = 1; /* OS memory has second priority */ - allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description); + allocator = mali_os_allocator_create(size, 0 /* cpu_usage_adjust */, "Shared Mali GPU memory"); if (NULL == allocator) { MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n")); @@ -364,30 +363,30 @@ _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * r MALI_SUCCESS; } -_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource) +_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size) { mali_physical_memory_allocator * allocator; mali_physical_memory_allocator ** next_allocator_list; dedicated_memory_info * cleanup_data; - u32 alloc_order = resource->alloc_order; + u32 alloc_order = 0; /* Dedicated range has first priority */ /* do the low level linux operation first */ /* Request ownership of the memory */ - if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description)) + if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory")) { - MALI_DEBUG_PRINT(1, ("Failed to request memory region %s (0x%08X - 0x%08X)\n", resource->description, resource->base, resource->base + resource->size - 1)); + MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1)); MALI_ERROR(_MALI_OSK_ERR_FAULT); } /* create generic block allocator object to handle it */ - allocator = mali_block_allocator_create(resource->base, resource->cpu_usage_adjust, resource->size, resource->description ); + allocator = mali_block_allocator_create(start, 0 /* cpu_usage_adjust */, size, "Dedicated Mali GPU memory"); if (NULL == allocator) { MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n")); - _mali_osk_mem_unreqregion(resource->base, resource->size); + _mali_osk_mem_unreqregion(start, size); MALI_ERROR(_MALI_OSK_ERR_FAULT); } @@ -398,13 +397,13 @@ _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resourc if (NULL == cleanup_data) { - _mali_osk_mem_unreqregion(resource->base, resource->size); + _mali_osk_mem_unreqregion(start, size); allocator->destroy(allocator); MALI_ERROR(_MALI_OSK_ERR_FAULT); } - cleanup_data->base = resource->base; - cleanup_data->size = resource->size; + cleanup_data->base = start; + cleanup_data->size = size; cleanup_data->next = mem_region_registrations; mem_region_registrations = cleanup_data; @@ -425,7 +424,7 @@ _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resourc MALI_SUCCESS; } -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#if defined(CONFIG_MALI400_UMP) static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) { ump_dd_handle ump_mem; @@ -672,7 +671,7 @@ _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args MALI_SUCCESS; } -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */ +#endif /* CONFIG_MALI400_UMP */ static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) @@ -757,6 +756,20 @@ static void external_memory_release(void * ctx, void * handle) return; } +_mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + /* Return number of bytes actually copied */ + args->size = _mali_osk_mem_write_safe(args->dest, args->src, args->size); + return _MALI_OSK_ERR_OK; +} + _mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args ) { mali_physical_memory_allocator external_memory_allocator; @@ -1006,10 +1019,6 @@ static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s struct mali_session_data *session_data; mali_memory_allocation * descriptor; - u32 num_groups = mali_group_get_glob_num_groups(); - struct mali_group *group; - u32 i; - descriptor = (mali_memory_allocation *)args->cookie; MALI_DEBUG_ASSERT_POINTER(descriptor); @@ -1025,40 +1034,7 @@ static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s It is allowed to call this function severeal times, which might happen if zapping below fails. */ mali_allocation_engine_release_pt1_mali_pagetables_unmap(memory_engine, descriptor); -#ifdef MALI_UNMAP_FLUSH_ALL_MALI_L2 - { - u32 number_of_clusters = mali_cluster_get_glob_num_clusters(); - for (i = 0; i < number_of_clusters; i++) - { - struct mali_cluster *cluster; - cluster = mali_cluster_get_global_cluster(i); - if( mali_cluster_power_is_enabled_get(cluster) ) - { - mali_cluster_l2_cache_invalidate_all_force(cluster); - } - } - } -#endif - - for (i = 0; i < num_groups; i++) - { - group = mali_group_get_glob_group(i); - mali_group_lock(group); - mali_group_remove_session_if_unused(group, session_data); - if (mali_group_get_session(group) == session_data) - { - /* The Zap also does the stall and disable_stall */ - mali_bool zap_success = mali_mmu_zap_tlb(mali_group_get_mmu(group)); - if (MALI_TRUE != zap_success) - { - MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n")); - mali_group_bottom_half(group, GROUP_EVENT_MMU_PAGE_FAULT); - /* The bottom half will also do the unlock */ - continue; - } - } - mali_group_unlock(group); - } + mali_scheduler_zap_all_active(session_data); /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */ mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor); @@ -1126,7 +1102,7 @@ _mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *ma { _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); - if (0 == _mali_osk_list_empty(&page_table_cache.partial)) + if (!_mali_osk_list_empty(&page_table_cache.partial)) { mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list); int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages); @@ -1304,7 +1280,7 @@ static void mali_mmu_page_table_cache_destroy(void) _mali_osk_free(alloc); } - MALI_DEBUG_PRINT_IF(1, 0 == _mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n")); + MALI_DEBUG_PRINT_IF(1, !_mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n")); _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list) { diff --git a/drivers/media/video/samsung/mali/common/mali_memory.h b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.h index 78e2945..537c346 100644 --- a/drivers/media/video/samsung/mali/common/mali_memory.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_memory.h @@ -14,9 +14,6 @@ #include "mali_osk.h" #include "mali_session.h" -struct mali_cluster; -struct mali_group; - /** @brief Initialize Mali memory subsystem * * Allocate and initialize internal data structures. Must be called before @@ -70,12 +67,19 @@ void mali_mmu_release_table_page(u32 pa); /** @brief Parse resource and prepare the OS memory allocator + * + * @param size Maximum size to allocate for Mali GPU. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. */ -_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource); +_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size); /** @brief Parse resource and prepare the dedicated memory allocator + * + * @param start Physical start address of dedicated Mali GPU memory. + * @param size Size of dedicated Mali GPU memory. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. */ -_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource); +_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size); mali_allocation_engine mali_mem_get_memory_engine(void); diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c index 2f2fa4d..158cccf 100644 --- a/drivers/media/video/samsung/mali/common/mali_mmu.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.c @@ -25,36 +25,6 @@ #define MALI_MMU_REGISTERS_SIZE 0x24 /** - * MMU register numbers - * Used in the register read/write routines. - * See the hardware documentation for more information about each register - */ -typedef enum mali_mmu_register { - MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */ - MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */ - MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */ - MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */ - MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */ - MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */ - MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */ - MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */ - MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */ -} mali_mmu_register; - -/** - * MMU interrupt register bits - * Each cause of the interrupt is reported - * through the (raw) interrupt status registers. - * Multiple interrupts can be pending, so multiple bits - * can be set at once. - */ -typedef enum mali_mmu_interrupt -{ - MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */ - MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */ -} mali_mmu_interrupt; - -/** * MMU commands * These are the commands that can be sent * to the MMU unit. @@ -70,49 +40,6 @@ typedef enum mali_mmu_command MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */ } mali_mmu_command; -typedef enum mali_mmu_status_bits -{ - MALI_MMU_STATUS_BIT_PAGING_ENABLED = 1 << 0, - MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE = 1 << 1, - MALI_MMU_STATUS_BIT_STALL_ACTIVE = 1 << 2, - MALI_MMU_STATUS_BIT_IDLE = 1 << 3, - MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4, - MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5, -} mali_mmu_status_bits; - -/** - * Definition of the MMU struct - * Used to track a MMU unit in the system. - * Contains information about the mapping of the registers - */ -struct mali_mmu_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - struct mali_group *group; /**< Parent core group */ - _mali_osk_irq_t *irq; /**< IRQ handler */ -}; - -/** - * The MMU interrupt handler - * Upper half of the MMU interrupt processing. - * Called by the kernel when the MMU has triggered an interrupt. - * The interrupt function supports IRQ sharing. So it'll probe the MMU in question - * @param irq The irq number (not used) - * @param dev_id Points to the MMU object being handled - * @param regs Registers of interrupted process (not used) - * @return Standard Linux interrupt result. - * Subset used by the driver is IRQ_HANDLED processed - * IRQ_NONE Not processed - */ -static _mali_osk_errcode_t mali_mmu_upper_half(void * data); - -/** - * The MMU reset hander - * Bottom half of the MMU interrupt processing for page faults and bus errors - * @param work The item to operate on, NULL in our case - */ -static void mali_mmu_bottom_half(void *data); - static void mali_mmu_probe_trigger(void *data); static _mali_osk_errcode_t mali_mmu_probe_ack(void *data); @@ -159,7 +86,7 @@ void mali_mmu_terminate(void) &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page); } -struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource) +struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual) { struct mali_mmu_core* mmu = NULL; @@ -172,24 +99,38 @@ struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource) { if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) { - if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) + if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu)) { - /* Setup IRQ handlers (which will do IRQ probing if needed) */ - mmu->irq = _mali_osk_irq_init(resource->irq, - mali_mmu_upper_half, - mali_mmu_bottom_half, - mali_mmu_probe_trigger, - mali_mmu_probe_ack, - mmu, - "mali_mmu_irq_handlers"); - if (NULL != mmu->irq) + if (is_virtual) { + /* Skip reset and IRQ setup for virtual MMU */ return mmu; } - else + + if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) { - MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description)); + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + mmu->irq = _mali_osk_irq_init(resource->irq, + mali_group_upper_half_mmu, + group, + mali_mmu_probe_trigger, + mali_mmu_probe_ack, + mmu, + "mali_mmu_irq_handlers"); + if (NULL != mmu->irq) + { + return mmu; + } + else + { + MALI_PRINT_ERROR(("Mali MMU: Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description)); + } } + mali_group_remove_mmu_core(group); + } + else + { + MALI_PRINT_ERROR(("Mali MMU: Failed to add core %s to group\n", mmu->hw_core.description)); } mali_hw_core_delete(&mmu->hw_core); } @@ -206,33 +147,29 @@ struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource) void mali_mmu_delete(struct mali_mmu_core *mmu) { - _mali_osk_irq_term(mmu->irq); + if (NULL != mmu->irq) + { + _mali_osk_irq_term(mmu->irq); + } + mali_hw_core_delete(&mmu->hw_core); _mali_osk_free(mmu); } -void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group) -{ - mmu->group = group; -} - static void mali_mmu_enable_paging(struct mali_mmu_core *mmu) { - const int max_loop_count = 100; - const int delay_in_usecs = 1; int i; mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); - for (i = 0; i < max_loop_count; ++i) + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) { if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) { break; } - _mali_osk_time_ubusydelay(delay_in_usecs); } - if (max_loop_count == i) + if (MALI_REG_POLL_COUNT_FAST == i) { MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); } @@ -240,19 +177,12 @@ static void mali_mmu_enable_paging(struct mali_mmu_core *mmu) mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu) { - const int max_loop_count = 100; - const int delay_in_usecs = 999; int i; - u32 mmu_status; - - /* There are no group when it is called from mali_mmu_create */ - if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group); - - mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) ) { - MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n")); + MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enabled.\n")); return MALI_TRUE; } @@ -264,28 +194,31 @@ mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu) mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); - for (i = 0; i < max_loop_count; ++i) + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) { mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - if ( mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) + if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) { break; } - if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) + if ((mmu_status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) && (0 == (mmu_status & MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE))) + { + break; + } + if (0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) { break; } - _mali_osk_time_ubusydelay(delay_in_usecs); } - if (max_loop_count == i) + if (MALI_REG_POLL_COUNT_FAST == i) { - MALI_PRINT_ERROR(("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + MALI_DEBUG_PRINT(2, ("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); return MALI_FALSE; } if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) { - MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it has a pagefault.\n")); + MALI_DEBUG_PRINT(2, ("Aborting MMU stall request since it has a pagefault.\n")); return MALI_FALSE; } @@ -294,14 +227,8 @@ mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu) void mali_mmu_disable_stall(struct mali_mmu_core *mmu) { - const int max_loop_count = 100; - const int delay_in_usecs = 1; int i; - u32 mmu_status; - /* There are no group when it is called from mali_mmu_create */ - if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group); - - mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); + u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) { @@ -316,7 +243,7 @@ void mali_mmu_disable_stall(struct mali_mmu_core *mmu) mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); - for (i = 0; i < max_loop_count; ++i) + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) { u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) ) @@ -331,38 +258,32 @@ void mali_mmu_disable_stall(struct mali_mmu_core *mmu) { break; } - _mali_osk_time_ubusydelay(delay_in_usecs); } - if (max_loop_count == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); + if (MALI_REG_POLL_COUNT_FAST == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); } void mali_mmu_page_fault_done(struct mali_mmu_core *mmu) { - MALI_ASSERT_GROUP_LOCKED(mmu->group); MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description)); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE); } MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu) { - const int max_loop_count = 100; - const int delay_in_usecs = 1; int i; - /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */ - if (mmu->group)MALI_ASSERT_GROUP_LOCKED(mmu->group); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE); + MALI_DEBUG_ASSERT(0xCAFEB000 == mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR)); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET); - for (i = 0; i < max_loop_count; ++i) + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) { if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0) { break; } - _mali_osk_time_ubusydelay(delay_in_usecs); } - if (max_loop_count == i) + if (MALI_REG_POLL_COUNT_FAST == i) { MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); return _MALI_OSK_ERR_FAULT; @@ -376,16 +297,12 @@ _mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu) _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; mali_bool stall_success; MALI_DEBUG_ASSERT_POINTER(mmu); - /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */ - if (mmu->group) - { - MALI_ASSERT_GROUP_LOCKED(mmu->group); - } stall_success = mali_mmu_enable_stall(mmu); - - /* The stall can not fail in current hw-state */ - MALI_DEBUG_ASSERT(stall_success); + if (!stall_success) + { + err = _MALI_OSK_ERR_BUSY; + } MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description)); @@ -402,91 +319,9 @@ _mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu) return err; } - -/* ------------- interrupt handling below ------------------ */ - -static _mali_osk_errcode_t mali_mmu_upper_half(void * data) -{ - struct mali_mmu_core *mmu = (struct mali_mmu_core *)data; - u32 int_stat; - - MALI_DEBUG_ASSERT_POINTER(mmu); - - /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */ - int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); - if (0 != int_stat) - { - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0); - mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - - if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) - { - _mali_osk_irq_schedulework(mmu->irq); - } - - if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) - { - /* clear interrupt flag */ - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); - /* reenable it */ - mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, - mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR); - MALI_PRINT_ERROR(("Mali MMU: Read bus error\n")); - } - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_mmu_bottom_half(void * data) -{ - struct mali_mmu_core *mmu = (struct mali_mmu_core*)data; - u32 raw, status, fault_address; - - MALI_DEBUG_ASSERT_POINTER(mmu); - - MALI_DEBUG_PRINT(3, ("Mali MMU: Page fault bottom half: Locking subsystems\n")); - - mali_group_lock(mmu->group); /* Unlocked in mali_group_bottom_half */ - - if ( MALI_FALSE == mali_group_power_is_on(mmu->group) ) - { - MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.",mmu->hw_core.description)); - mali_group_unlock(mmu->group); - return; - } - - raw = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT); - status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); - - if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) && (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) ) - { - MALI_DEBUG_PRINT(2, ("Mali MMU: Page fault bottom half: No Irq found.\n")); - mali_group_unlock(mmu->group); - /* MALI_DEBUG_ASSERT(0); */ - return; - } - - /* An actual page fault has occurred. */ - - fault_address = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR); - - MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n", - (void*)fault_address, - (status >> 6) & 0x1F, - (status & 32) ? "write" : "read", - mmu->hw_core.description)); - - mali_group_bottom_half(mmu->group, GROUP_EVENT_MMU_PAGE_FAULT); /* Unlocks the group lock */ -} - mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu) { - mali_bool stall_success; - MALI_ASSERT_GROUP_LOCKED(mmu->group); - - stall_success = mali_mmu_enable_stall(mmu); + mali_bool stall_success = mali_mmu_enable_stall(mmu); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); @@ -502,23 +337,20 @@ mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu) void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu) { - MALI_ASSERT_GROUP_LOCKED(mmu->group); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); } void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address) { - MALI_ASSERT_GROUP_LOCKED(mmu->group); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address)); } static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory) { - MALI_ASSERT_GROUP_LOCKED(mmu->group); /* The MMU must be in stalled or page fault mode, for this writing to work */ MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) - & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) ); + & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) ); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory); mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); @@ -528,7 +360,6 @@ mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mal { mali_bool stall_success; MALI_DEBUG_ASSERT_POINTER(mmu); - MALI_ASSERT_GROUP_LOCKED(mmu->group); MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description)); stall_success = mali_mmu_enable_stall(mmu); @@ -542,13 +373,16 @@ mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mal void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu) { mali_bool stall_success; + MALI_DEBUG_ASSERT_POINTER(mmu); - MALI_ASSERT_GROUP_LOCKED(mmu->group); MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description)); stall_success = mali_mmu_enable_stall(mmu); + /* This function can only be called when the core is idle, so it could not fail. */ - MALI_DEBUG_ASSERT( stall_success ); + MALI_DEBUG_ASSERT(stall_success); + MALI_IGNORE(stall_success); + mali_mmu_activate_address_space(mmu, mali_empty_page_directory); mali_mmu_disable_stall(mmu); } @@ -557,7 +391,6 @@ void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu) { mali_bool stall_success; MALI_DEBUG_ASSERT_POINTER(mmu); - MALI_ASSERT_GROUP_LOCKED(mmu->group); MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description)); stall_success = mali_mmu_enable_stall(mmu); diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h new file mode 100644 index 0000000..59b5399 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010-2012 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_MMU_H__ +#define __MALI_MMU_H__ + +#include "mali_osk.h" +#include "mali_mmu_page_directory.h" +#include "mali_hw_core.h" + +/* Forward declaration from mali_group.h */ +struct mali_group; + +/** + * MMU register numbers + * Used in the register read/write routines. + * See the hardware documentation for more information about each register + */ +typedef enum mali_mmu_register { + MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */ + MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */ + MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */ + MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */ + MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */ + MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */ + MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */ + MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */ + MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */ +} mali_mmu_register; + +/** + * MMU interrupt register bits + * Each cause of the interrupt is reported + * through the (raw) interrupt status registers. + * Multiple interrupts can be pending, so multiple bits + * can be set at once. + */ +typedef enum mali_mmu_interrupt +{ + MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */ + MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */ +} mali_mmu_interrupt; + +typedef enum mali_mmu_status_bits +{ + MALI_MMU_STATUS_BIT_PAGING_ENABLED = 1 << 0, + MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE = 1 << 1, + MALI_MMU_STATUS_BIT_STALL_ACTIVE = 1 << 2, + MALI_MMU_STATUS_BIT_IDLE = 1 << 3, + MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4, + MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5, + MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE = 1 << 31, +} mali_mmu_status_bits; + +/** + * Definition of the MMU struct + * Used to track a MMU unit in the system. + * Contains information about the mapping of the registers + */ +struct mali_mmu_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + _mali_osk_irq_t *irq; /**< IRQ handler */ +}; + +_mali_osk_errcode_t mali_mmu_initialize(void); + +void mali_mmu_terminate(void); + +struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual); +void mali_mmu_delete(struct mali_mmu_core *mmu); + +_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu); +mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu); +void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu); +void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address); + +mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir); +void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu); +void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu); + +/** + * Issues the enable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out) + */ +mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu); + +/** + * Issues the disable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + */ +void mali_mmu_disable_stall(struct mali_mmu_core *mmu); + +void mali_mmu_page_fault_done(struct mali_mmu_core *mmu); + +/*** Register reading/writing functions ***/ +MALI_STATIC_INLINE u32 mali_mmu_get_int_status(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS); +} + +MALI_STATIC_INLINE u32 mali_mmu_get_rawstat(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT); +} + +MALI_STATIC_INLINE void mali_mmu_mask_all_interrupts(struct mali_mmu_core *mmu) +{ + mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0); +} + +MALI_STATIC_INLINE u32 mali_mmu_get_status(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS); +} + +MALI_STATIC_INLINE u32 mali_mmu_get_page_fault_addr(struct mali_mmu_core *mmu) +{ + return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR); +} + +#endif /* __MALI_MMU_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.c index cc91ae9..258fc1b 100644 --- a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.c @@ -14,8 +14,7 @@ #include "mali_uk_types.h" #include "mali_mmu_page_directory.h" #include "mali_memory.h" - -#include "mali_cluster.h" +#include "mali_l2_cache.h" #include "mali_group.h" static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data); @@ -174,11 +173,10 @@ _mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); u32 left = size; int i; -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 mali_bool pd_changed = MALI_FALSE; u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */ u32 num_pages_inv = 0; -#endif + mali_bool invalidate_all = MALI_FALSE; /* safety mechanism in case page_entries_usage_count is unreliable */ /* For all page directory entries in range. */ for (i = first_pde; i <= last_pde; i++) @@ -213,17 +211,20 @@ _mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0); mali_mmu_release_table_page(page_address); -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 pd_changed = MALI_TRUE; -#endif } else { -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 - pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i); - num_pages_inv++; - MALI_DEBUG_ASSERT(num_pages_inv<3); -#endif + MALI_DEBUG_ASSERT(num_pages_inv < 2); + if (num_pages_inv < 2) + { + pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i); + num_pages_inv++; + } + else + { + invalidate_all = MALI_TRUE; + } /* If part of the page table is still in use, zero the relevant PTEs */ mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde); @@ -234,20 +235,29 @@ _mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, } _mali_osk_write_mem_barrier(); -#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 /* L2 pages invalidation */ if (MALI_TRUE == pd_changed) { - pages_to_invalidate[num_pages_inv] = pagedir->page_directory; - num_pages_inv++; - MALI_DEBUG_ASSERT(num_pages_inv<3); + MALI_DEBUG_ASSERT(num_pages_inv < 3); + if (num_pages_inv < 3) + { + pages_to_invalidate[num_pages_inv] = pagedir->page_directory; + num_pages_inv++; + } + else + { + invalidate_all = MALI_TRUE; + } } - if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id()) + if (invalidate_all) + { + mali_l2_cache_invalidate_all(); + } + else { - mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv); + mali_l2_cache_invalidate_all_pages(pages_to_invalidate, num_pages_inv); } -#endif MALI_SUCCESS; } @@ -305,12 +315,12 @@ void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_addre switch ( cache_settings ) { case MALI_CACHE_GP_READ_ALLOCATE: - MALI_DEBUG_PRINT(3, ("Map L2 GP_Read_allocate\n")); + MALI_DEBUG_PRINT(5, ("Map L2 GP_Read_allocate\n")); permission_bits = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE; break; case MALI_CACHE_STANDARD: - MALI_DEBUG_PRINT(3, ("Map L2 Standard\n")); + MALI_DEBUG_PRINT(5, ("Map L2 Standard\n")); /*falltrough */ default: if ( MALI_CACHE_STANDARD != cache_settings) MALI_PRINT_ERROR(("Wrong cache settings\n")); diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.h index 628833a..628833a 100644 --- a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_mmu_page_directory.h diff --git a/drivers/media/video/samsung/mali/common/mali_osk.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk.h index e32d15d..6217203 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk.h @@ -63,6 +63,8 @@ extern "C" #define MALI_FALSE ((mali_bool)0) #endif +#define MALI_HW_CORE_NO_COUNTER ((u32)-1) + /** * @brief OSK Error codes * @@ -92,6 +94,25 @@ typedef enum /** @} */ /* end group _mali_osk_miscellaneous */ +/** @defgroup _mali_osk_wq OSK work queues + * @{ */ + +/** @brief Private type for work objects */ +typedef struct _mali_osk_wq_work_t_struct _mali_osk_wq_work_t; + +/** @brief Work queue handler function + * + * This function type is called when the work is scheduled by the work queue, + * e.g. as an IRQ bottom-half handler. + * + * Refer to \ref _mali_osk_wq_schedule_work() for more information on the + * work-queue and work handlers. + * + * @param arg resource-specific data + */ +typedef void (*_mali_osk_wq_work_handler_t)( void * arg ); + +/* @} */ /* end group _mali_osk_wq */ /** @defgroup _mali_osk_irq OSK IRQ handling * @{ */ @@ -127,7 +148,7 @@ typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg ); * * If an IRQ upper-half handler requires more work to be done than can be * acheived in an IRQ context, then it may defer the work with - * _mali_osk_irq_schedulework(). Refer to \ref _mali_osk_irq_schedulework() for + * _mali_osk_wq_schedule_work(). Refer to \ref _mali_osk_wq_create_work() for * more information. * * @param arg resource-specific data @@ -136,24 +157,6 @@ typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg ); */ typedef _mali_osk_errcode_t (*_mali_osk_irq_uhandler_t)( void * arg ); -/** @brief IRQ 'bottom-half' handler callback. - * - * This function is implemented by the common layer to do the deferred handling - * of a resource's IRQ. Usually, this work cannot be carried out in IRQ context - * by the IRQ upper-half handler. - * - * The IRQ bottom-half handler maps on to the concept of an IST that may - * execute some time after the actual IRQ has fired. - * - * All OSK-registered IRQ bottom-half handlers will be serialized, across all - * CPU-cores in the system. - * - * Refer to \ref _mali_osk_irq_schedulework() for more information on the - * IRQ work-queue, and the calling of the IRQ bottom-half handler. - * - * @param arg resource-specific data - */ -typedef void (*_mali_osk_irq_bhandler_t)( void * arg ); /** @} */ /* end group _mali_osk_irq */ @@ -197,21 +200,24 @@ typedef enum { _MALI_OSK_LOCK_ORDER_LAST = 0, + _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS, _MALI_OSK_LOCK_ORDER_PM_EXECUTE, _MALI_OSK_LOCK_ORDER_UTILIZATION, _MALI_OSK_LOCK_ORDER_L2_COUNTER, _MALI_OSK_LOCK_ORDER_PROFILING, _MALI_OSK_LOCK_ORDER_L2_COMMAND, _MALI_OSK_LOCK_ORDER_PM_CORE_STATE, - _MALI_OSK_LOCK_ORDER_GROUP, + _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED, _MALI_OSK_LOCK_ORDER_SCHEDULER, - + _MALI_OSK_LOCK_ORDER_GROUP, + _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE, _MALI_OSK_LOCK_ORDER_MEM_INFO, _MALI_OSK_LOCK_ORDER_MEM_SESSION, - _MALI_OSK_LOCK_ORDER_SESSIONS, + _MALI_OSK_LOCK_ORDER_PM_DOMAIN, + _MALI_OSK_LOCK_ORDER_PMU, _MALI_OSK_LOCK_ORDER_FIRST } _mali_osk_lock_order_t; @@ -311,6 +317,8 @@ typedef struct _mali_osk_lock_t_struct _mali_osk_lock_t; /** @brief returns a lock's owner (thread id) if debugging is enabled */ u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ); +#else +#define MALI_DEBUG_ASSERT_LOCK_HELD(l) do {} while(0) #endif /** @} */ /* end group _mali_osk_lock */ @@ -429,7 +437,7 @@ typedef struct _mali_osk_notification_t_struct * * If a timer requires more work to be done than can be acheived in an IRQ * context, then it may defer the work with a work-queue. For example, it may - * use \ref _mali_osk_irq_schedulework() to make use of the IRQ bottom-half handler + * use \ref _mali_osk_wq_schedule_work() to make use of a bottom-half handler * to carry out the remaining work. * * Stopping the timer with \ref _mali_osk_timer_del() blocks on compeletion of @@ -473,6 +481,10 @@ typedef struct _mali_osk_list_s * @param exp the name of the variable that the list will be defined as. */ #define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp +/** @brief Define a list variable, which is initialized. + * @param exp the name of the variable that the list will be defined as. */ +#define _MALI_OSK_LIST_HEAD_STATIC_INIT(exp) _mali_osk_list_t exp = { &exp, &exp } + /** @brief Find the containing structure of another structure * * This is the reverse of the operation 'offsetof'. This means that the @@ -557,131 +569,68 @@ typedef struct _mali_osk_list_s /** @addtogroup _mali_osk_miscellaneous * @{ */ -/** @brief The known resource types - * - * @note \b IMPORTANT: these must remain fixed, and only be extended. This is - * because not all systems use a header file for reading in their resources. - * The resources may instead come from a data file where these resources are - * 'hard-coded' in, because there's no easy way of transferring the enum values - * into such data files. E.g. the C-Pre-processor does \em not process enums. - */ -typedef enum _mali_osk_resource_type -{ - RESOURCE_TYPE_FIRST =0, /**< Duplicate resource marker for the first resource*/ - - MEMORY =0, /**< Physically contiguous memory block, not managed by the OS */ - OS_MEMORY =1, /**< Memory managed by and shared with the OS */ - - MALI_PP =2, /**< Mali Pixel Processor core */ - MALI450PP =2, /**< Compatibility option */ - MALI400PP =2, /**< Compatibility option */ - MALI300PP =2, /**< Compatibility option */ - MALI200 =2, /**< Compatibility option */ - - MALI_GP =3, /**< Mali Geometry Processor core */ - MALI450GP =3, /**< Compatibility option */ - MALI400GP =3, /**< Compatibility option */ - MALI300GP =3, /**< Compatibility option */ - MALIGP2 =3, /**< Compatibility option */ - - MMU =4, /**< Mali MMU (Memory Management Unit) */ - - FPGA_FRAMEWORK =5, /**< Mali registers specific to FPGA implementations */ - - MALI_L2 =6, /**< Mali Level 2 cache core */ - MALI450L2 =6, /**< Compatibility option */ - MALI400L2 =6, /**< Compatibility option */ - MALI300L2 =6, /**< Compatibility option */ - - MEM_VALIDATION =7, /**< External Memory Validator */ - - PMU =8, /**< Power Manangement Unit */ - - RESOURCE_TYPE_COUNT /**< The total number of known resources */ -} _mali_osk_resource_type_t; - /** @brief resource description struct * - * _mali_osk_resources_init() will enumerate objects of this type. Not all - * members have a valid meaning across all types. - * - * The mmu_id is used to group resources to a certain MMU, since there may be - * more than one MMU in the system, and each resource may be using a different - * MMU: - * - For MMU resources, the setting of mmu_id is a uniquely identifying number. - * - For Other resources, the setting of mmu_id determines which MMU the - * resource uses. + * Platform independent representation of a Mali HW resource */ typedef struct _mali_osk_resource { - _mali_osk_resource_type_t type; /**< type of the resource */ const char * description; /**< short description of the resource */ u32 base; /**< Physical base address of the resource, as seen by Mali resources. */ - s32 cpu_usage_adjust; /**< Offset added to the base address of the resource to arrive at the CPU physical address of the resource (if different from the Mali physical address) */ - u32 size; /**< Size in bytes of the resource - either the size of its register range, or the size of the memory block. */ u32 irq; /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */ - u32 flags; /**< Resources-specific flags. */ - u32 mmu_id; /**< Identifier for Mali MMU resources. */ - u32 alloc_order; /**< Order in which MEMORY/OS_MEMORY resources are used */ } _mali_osk_resource_t; /** @} */ /* end group _mali_osk_miscellaneous */ #include "mali_kernel_memory_engine.h" /* include for mali_memory_allocation and mali_physical_memory_allocation type */ -/** @addtogroup _mali_osk_irq +/** @addtogroup _mali_osk_wq * @{ */ -/** @brief Fake IRQ number for testing purposes +/** @brief Initialize work queues (for deferred work) + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. */ -#define _MALI_OSK_IRQ_NUMBER_FAKE ((u32)0xFFFFFFF1) - -/** @addtogroup _mali_osk_irq - * @{ */ +_mali_osk_errcode_t _mali_osk_wq_init(void); -/** @brief PMM Virtual IRQ number +/** @brief Terminate work queues (for deferred work) */ -#define _MALI_OSK_IRQ_NUMBER_PMM ((u32)0xFFFFFFF2) +void _mali_osk_wq_term(void); - -/** @brief Initialize IRQ handling for a resource +/** @brief Create work in the work queue * - * The _mali_osk_irq_t returned must be written into the resource-specific data - * pointed to by data. This is so that the upper and lower handlers can call - * _mali_osk_irq_schedulework(). + * Creates a work object which can be scheduled in the work queue. When + * scheduled, \a handler will be called with \a data as the argument. * - * @note The caller must ensure that the resource does not generate an - * interrupt after _mali_osk_irq_init() finishes, and before the - * _mali_osk_irq_t is written into the resource-specific data. Otherwise, - * the upper-half handler will fail to call _mali_osk_irq_schedulework(). + * Refer to \ref _mali_osk_wq_schedule_work() for details on how work + * is scheduled in the queue. * - * @param irqnum The IRQ number that the resource uses, as seen by the CPU. - * The value -1 has a special meaning which indicates the use of probing, and trigger_func and ack_func must be - * non-NULL. - * @param uhandler The upper-half handler, corresponding to a ISR handler for - * the resource - * @param bhandler The lower-half handler, corresponding to an IST handler for - * the resource - * @param trigger_func Optional: a function to trigger the resource's irq, to - * probe for the interrupt. Use NULL if irqnum != -1. - * @param ack_func Optional: a function to acknowledge the resource's irq, to - * probe for the interrupt. Use NULL if irqnum != -1. - * @param data resource-specific data, which will be passed to uhandler, - * bhandler and (if present) trigger_func and ack_funnc - * @param description textual description of the IRQ resource. - * @return on success, a pointer to a _mali_osk_irq_t object, which represents - * the IRQ handling on this resource. NULL on failure. + * The returned pointer must be freed with \ref _mali_osk_wq_delete_work() + * when no longer needed. + */ +_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data ); + +/** @brief Delete a work object + * + * This will flush the work queue to ensure that the work handler will not + * be called after deletion. + */ +void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work ); + +/** @brief Delete a work object + * + * This will NOT flush the work queue, so only call this if you are sure that the work handler will + * not be called after deletion. */ -_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 ); +void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work ); -/** @brief Cause a queued, deferred call of the IRQ bottom-half. +/** @brief Cause a queued, deferred call of the work handler * - * _mali_osk_irq_schedulework provides a mechanism for enqueuing deferred calls - * to the IRQ bottom-half handler. The queue is known as the IRQ work-queue. - * After calling _mali_osk_irq_schedulework(), the IRQ bottom-half handler will - * be scheduled to run at some point in the future. + * _mali_osk_wq_schedule_work provides a mechanism for enqueuing deferred calls + * to the work handler. After calling \ref _mali_osk_wq_schedule_work(), the + * work handler will be scheduled to run at some point in the future. * - * This is called by the IRQ upper-half to defer further processing of + * Typically this is called by the IRQ upper-half to defer further processing of * IRQ-related work to the IRQ bottom-half handler. This is necessary for work * that cannot be done in an IRQ context by the IRQ upper-half handler. Timer * callbacks also use this mechanism, because they are treated as though they @@ -694,78 +643,97 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl * IRQ bottom half to hold the same mutex, with a guarantee that they will not * deadlock just by using this mechanism. * - * _mali_osk_irq_schedulework() places deferred call requests on a queue, to + * _mali_osk_wq_schedule_work() places deferred call requests on a queue, to * allow for more than one thread to make a deferred call. Therfore, if it is * called 'K' times, then the IRQ bottom-half will be scheduled 'K' times too. * 'K' is a number that is implementation-specific. * - * _mali_osk_irq_schedulework() is guaranteed to not block on: + * _mali_osk_wq_schedule_work() is guaranteed to not block on: * - enqueuing a deferred call request. - * - the completion of the IRQ bottom-half handler. + * - the completion of the work handler. * - * This is to prevent deadlock. For example, if _mali_osk_irq_schedulework() + * This is to prevent deadlock. For example, if _mali_osk_wq_schedule_work() * blocked, then it would cause a deadlock when the following two conditions * hold: - * - The IRQ bottom-half callback (of type _mali_osk_irq_bhandler_t) locks + * - The work handler callback (of type _mali_osk_wq_work_handler_t) locks * a mutex - * - And, at the same time, the caller of _mali_osk_irq_schedulework() also + * - And, at the same time, the caller of _mali_osk_wq_schedule_work() also * holds the same mutex * * @note care must be taken to not overflow the queue that - * _mali_osk_irq_schedulework() operates on. Code must be structured to + * _mali_osk_wq_schedule_work() operates on. Code must be structured to * ensure that the number of requests made to the queue is bounded. Otherwise, - * IRQs will be lost. + * work will be lost. * - * The queue that _mali_osk_irq_schedulework implements is a FIFO of N-writer, - * 1-reader type. The writers are the callers of _mali_osk_irq_schedulework + * The queue that _mali_osk_wq_schedule_work implements is a FIFO of N-writer, + * 1-reader type. The writers are the callers of _mali_osk_wq_schedule_work * (all OSK-registered IRQ upper-half handlers in the system, watchdog timers, * callers from a Kernel-process context). The reader is a single thread that - * handles all OSK-registered IRQs. + * handles all OSK-registered work. * - * The consequence of the queue being a 1-reader type is that calling - * _mali_osk_irq_schedulework() on different _mali_osk_irq_t objects causes - * their IRQ bottom-halves to be serialized, across all CPU-cores in the - * system. - * - * @param irq a pointer to the _mali_osk_irq_t object corresponding to the - * resource whose IRQ bottom-half must begin processing. + * @param work a pointer to the _mali_osk_wq_work_t object corresponding to the + * work to begin processing. */ -void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ); +void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work ); -/** @brief Terminate IRQ handling on a resource. +/** @brief Flush the work queue + * + * This will flush the OSK work queue, ensuring all work in the queue has + * completed before returning. * - * This will disable the interrupt from the device, and then waits for the - * IRQ work-queue to finish the work that is currently in the queue. That is, - * for every deferred call currently in the IRQ work-queue, it waits for each - * of those to be processed by their respective IRQ bottom-half handler. + * Since this blocks on the completion of work in the work-queue, the + * caller of this function \b must \b not hold any mutexes that are taken by + * any registered work handler. To do so may cause a deadlock. * - * This function is used to ensure that the bottom-half handler of the supplied - * IRQ object will not be running at the completion of this function call. - * However, the caller must ensure that no other sources could call the - * _mali_osk_irq_schedulework() on the same IRQ object. For example, the - * relevant timers must be stopped. + */ +void _mali_osk_wq_flush(void); + + +/** @} */ /* end group _mali_osk_wq */ + +/** @addtogroup _mali_osk_irq + * @{ */ + +/** @brief Initialize IRQ handling for a resource * - * @note While this function is being called, other OSK-registered IRQs in the - * system may enqueue work for their respective bottom-half handlers. This - * function will not wait for those entries in the work-queue to be flushed. + * Registers an interrupt handler \a uhandler for the given IRQ number \a irqnum. + * \a data will be passed as argument to the handler when an interrupt occurs. * - * Since this blocks on the completion of work in the IRQ work-queue, the - * caller of this function \b must \b not hold any mutexes that are taken by - * any OSK-registered IRQ bottom-half handler. To do so may cause a deadlock. + * If \a irqnum is -1, _mali_osk_irq_init will probe for the IRQ number using + * the supplied \a trigger_func and \a ack_func. These functions will also + * receive \a data as their argument. * - * @param irq a pointer to the _mali_osk_irq_t object corresponding to the - * resource whose IRQ handling is to be terminated. + * @param irqnum The IRQ number that the resource uses, as seen by the CPU. + * The value -1 has a special meaning which indicates the use of probing, and + * trigger_func and ack_func must be non-NULL. + * @param uhandler The interrupt handler, corresponding to a ISR handler for + * the resource + * @param int_data resource specific data, which will be passed to uhandler + * @param trigger_func Optional: a function to trigger the resource's irq, to + * probe for the interrupt. Use NULL if irqnum != -1. + * @param ack_func Optional: a function to acknowledge the resource's irq, to + * probe for the interrupt. Use NULL if irqnum != -1. + * @param probe_data resource-specific data, which will be passed to + * (if present) trigger_func and ack_func + * @param description textual description of the IRQ resource. + * @return on success, a pointer to a _mali_osk_irq_t object, which represents + * the IRQ handling on this resource. NULL on failure. */ -void _mali_osk_irq_term( _mali_osk_irq_t *irq ); +_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description ); -/** @brief flushing workqueue. +/** @brief Terminate IRQ handling on a resource. + * + * This will disable the interrupt from the device, and then waits for any + * currently executing IRQ handlers to complete. * - * This will flush the workqueue. + * @note If work is deferred to an IRQ bottom-half handler through + * \ref _mali_osk_wq_schedule_work(), be sure to flush any remaining work + * with \ref _mali_osk_wq_flush() or (implicitly) with \ref _mali_osk_wq_delete_work() * * @param irq a pointer to the _mali_osk_irq_t object corresponding to the * resource whose IRQ handling is to be terminated. */ -void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ); +void _mali_osk_irq_term( _mali_osk_irq_t *irq ); /** @} */ /* end group _mali_osk_irq */ @@ -1422,17 +1390,6 @@ void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ); */ void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ); -#if MALI_STATE_TRACKING -/** @brief Receive a notification from a queue - * - * Check if a notification queue is empty. - * - * @param queue The queue to check. - * @return MALI_TRUE if queue is empty, otherwise MALI_FALSE. - */ -mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ); -#endif - /** @brief Receive a notification from a queue * * Receives a single notification from the given queue. @@ -1504,23 +1461,22 @@ void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire ); /** @brief Modify a timer * - * Set the absolute time at which a timer will expire, and start it if it is - * stopped. If \a expiry_tick is in the past (determined by - * _mali_osk_time_after() ), the timer fires immediately. + * Set the relative time at which a timer will expire, and start it if it is + * stopped. If \a ticks_to_expire 0 the timer fires immediately. * * It is an error to modify a timer without setting the callback via * _mali_osk_timer_setcallback(). * - * The timer will expire at absolute time \a expiry_tick, at which point, the - * callback function will be invoked with the callback-specific data, as set - * by _mali_osk_timer_setcallback(). + * The timer will expire at \a ticks_to_expire from the time of the call, at + * which point, the callback function will be invoked with the + * callback-specific data, as set by _mali_osk_timer_setcallback(). * * @param tim the timer to modify, and start if necessary - * @param expiry_tick the \em absolute time in ticks at which this timer should - * trigger. + * @param ticks_to_expire the \em absolute time in ticks at which this timer + * should trigger. * */ -void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick); +void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire); /** @brief Stop a timer, and block on its completion. * @@ -1532,9 +1488,9 @@ void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick); * occur. * * @note While the callback itself is guaranteed to not be running, work - * enqueued on the IRQ work-queue by the timer (with - * \ref _mali_osk_irq_schedulework()) may still run. The timer callback and IRQ - * bottom-half handler must take this into account. + * enqueued on the work-queue by the timer (with + * \ref _mali_osk_wq_schedule_work()) may still run. The timer callback and + * work handler must take this into account. * * It is legal to stop an already stopped timer. * @@ -1543,6 +1499,26 @@ void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick); */ void _mali_osk_timer_del( _mali_osk_timer_t *tim ); +/** @brief Stop a timer. + * + * Stop the timer. When the function returns, the timer's callback may still be + * running on any CPU core. + * + * It is legal to stop an already stopped timer. + * + * @param tim the timer to stop. + */ +void _mali_osk_timer_del_async( _mali_osk_timer_t *tim ); + +/** @brief Check if timer is pending. + * + * Check if timer is active. + * + * @param tim the timer to check + * @return MALI_TRUE if time is active, MALI_FALSE if it is not active + */ +mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim); + /** @brief Set a timer's callback parameters. * * This must be called at least once before a timer is started/modified. @@ -1765,13 +1741,51 @@ u32 _mali_osk_get_tid(void); */ void _mali_osk_pm_dev_enable(void); -/** @brief Tells the OS that device is now idle +/** @brief Disable OS controlled runtime power management + */ +void _mali_osk_pm_dev_disable(void); + + +/** @brief Take a reference to the power manager system for the Mali device. + * + * When function returns successfully, Mali is ON. + * + * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference. + */ +_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void); + + +/** @brief Release the reference to the power manger system for the Mali device. + * + * When reference count reach zero, the cores can be off. + * + * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add(). + */ +void _mali_osk_pm_dev_ref_dec(void); + + +/** @brief Take a reference to the power manager system for the Mali device. + * + * Will leave the cores powered off if they are already powered off. + * + * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference. + * + * @return MALI_TRUE if the Mali GPU is powered on, otherwise MALI_FALSE. + */ +mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void); + + +/** @brief Releasing the reference to the power manger system for the Mali device. + * + * When reference count reach zero, the cores can be off. + * + * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add_no_power_on(). */ -_mali_osk_errcode_t _mali_osk_pm_dev_idle(void); +void _mali_osk_pm_dev_ref_dec_no_power_on(void); -/** @brief Tells the OS that the device is about to become active +/** @brief Block untill pending PM operations are done */ -_mali_osk_errcode_t _mali_osk_pm_dev_activate(void); +void _mali_osk_pm_dev_barrier(void); /** @} */ /* end group _mali_osk_miscellaneous */ @@ -1779,7 +1793,6 @@ _mali_osk_errcode_t _mali_osk_pm_dev_activate(void); /** @} */ /* end group uddapi */ - #ifdef __cplusplus } #endif diff --git a/drivers/media/video/samsung/mali/common/mali_osk_bitops.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_bitops.h index ada1488..f262f7d 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk_bitops.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_bitops.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/common/mali_osk_list.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_list.h index 5987b0a..49f01b6 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk_list.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_list.h @@ -16,6 +16,8 @@ #ifndef __MALI_OSK_LIST_H__ #define __MALI_OSK_LIST_H__ +#include "mali_kernel_common.h" + #ifdef __cplusplus extern "C" { @@ -128,7 +130,7 @@ MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list ) * @param list the list to check. * @return non-zero if the list is empty, and zero otherwise. */ -MALI_STATIC_INLINE int _mali_osk_list_empty( _mali_osk_list_t *list ) +MALI_STATIC_INLINE mali_bool _mali_osk_list_empty( _mali_osk_list_t *list ) { return list->next == list; } @@ -150,30 +152,27 @@ MALI_STATIC_INLINE void _mali_osk_list_move( _mali_osk_list_t *move_entry, _mali _mali_osk_list_add(move_entry, list); } -/** @brief Join two lists +/** @brief Move an entire list * * The list element must be initialized. * - * Allows you to join a list into another list at a specific location + * Allows you to move a list from one list head to another list head * - * @param list the new list to add - * @param at the location in a list to add the new list into + * @param old_list The existing list head + * @param new_list The new list head (must be an empty list) */ -MALI_STATIC_INLINE void _mali_osk_list_splice( _mali_osk_list_t *list, _mali_osk_list_t *at ) +MALI_STATIC_INLINE void _mali_osk_list_move_list( _mali_osk_list_t *old_list, _mali_osk_list_t *new_list ) { - if (!_mali_osk_list_empty(list)) - { - /* insert all items from 'list' after 'at' */ - _mali_osk_list_t *first = list->next; - _mali_osk_list_t *last = list->prev; - _mali_osk_list_t *split = at->next; - - first->prev = at; - at->next = first; - - last->next = split; - split->prev = last; - } + MALI_DEBUG_ASSERT(_mali_osk_list_empty(new_list)); + if (!_mali_osk_list_empty(old_list)) + { + new_list->next = old_list->next; + new_list->prev = old_list->prev; + new_list->next->prev = new_list; + new_list->prev->next = new_list; + old_list->next = old_list; + old_list->prev = old_list; + } } /** @} */ /* end group _mali_osk_list */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_mali.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_mali.h index 427fcc8..2916a0d 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk_mali.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_mali.h @@ -16,6 +16,7 @@ #ifndef __MALI_OSK_MALI_H__ #define __MALI_OSK_MALI_H__ +#include <linux/mali/mali_utgard.h> #include <mali_osk.h> #ifdef __cplusplus @@ -26,33 +27,69 @@ extern "C" /** @addtogroup _mali_osk_miscellaneous * @{ */ -/** @brief Read the Mali Resource configuration - * - * Populates a _mali_arch_resource_t array from configuration settings, which - * are stored in an OS-specific way. - * - * For example, these may be compiled in to a static structure, or read from - * the filesystem at startup. +/** @brief Struct with device specific configuration data + */ +struct _mali_osk_device_data +{ + /* Dedicated GPU memory range (physical). */ + u32 dedicated_mem_start; + u32 dedicated_mem_size; + + /* Shared GPU memory */ + u32 shared_mem_size; + + /* Frame buffer memory to be accessible by Mali GPU (physical) */ + u32 fb_start; + u32 fb_size; + + /* Report GPU utilization in this interval (specified in ms) */ + u32 utilization_interval; + + /* Function that will receive periodic GPU utilization numbers */ + void (*utilization_callback)(struct mali_gpu_utilization_data *data); + + /* + * Mali PMU switch delay. + * Only needed if the power gates are connected to the PMU in a high fanout + * network. This value is the number of Mali clock cycles it takes to + * enable the power gates and turn on the power mesh. + * This value will have no effect if a daisy chain implementation is used. + */ + u32 pmu_switch_delay; +}; + +/** @brief Find Mali GPU HW resource * - * On failure, do not call _mali_osk_resources_term. + * @param addr Address of Mali GPU resource to find + * @param res Storage for resource information if resource is found. + * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if resource is not found + */ +_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res); + + +/** @brief Find Mali GPU HW base address * - * @param arch_config a pointer to the store the pointer to the resources - * @param num_resources the number of resources read - * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_NOMEM on allocation - * error. For other failures, a suitable _mali_osk_errcode_t is returned. + * @return 0 if resources are found, otherwise the Mali GPU component with lowest address. */ -_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ); +u32 _mali_osk_resource_base_address(void); -/** @brief Free resources allocated by _mali_osk_resources_init. +/** @brief Retrieve the Mali GPU specific data * - * Frees the _mali_arch_resource_t array allocated by _mali_osk_resources_init + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data); + +/** @brief Determines if Mali GPU has been configured with shared interrupts. * - * @param arch_config a pointer to the stored the pointer to the resources - * @param num_resources the number of resources in the array + * @return MALI_TRUE if shared interrupts, MALI_FALSE if not. */ -void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources); +mali_bool _mali_osk_shared_interrupts(void); + /** @} */ /* end group _mali_osk_miscellaneous */ + + + /** @addtogroup _mali_osk_low_level_memory * @{ */ @@ -212,6 +249,16 @@ _mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descri * \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR set. */ void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags ); + +/** @brief Copy as much data as possible from src to dest, do not crash if src or dest isn't available. + * + * @param dest Destination buffer (limited to user space mapped Mali memory) + * @param src Source buffer + * @param size Number of bytes to copy + * @return Number of bytes actually copied + */ +u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size); + /** @} */ /* end group _mali_osk_low_level_memory */ diff --git a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_profiling.h index fd9a8fb..c4822e2 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_osk_profiling.h @@ -11,13 +11,11 @@ #ifndef __MALI_OSK_PROFILING_H__ #define __MALI_OSK_PROFILING_H__ -#if MALI_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_PROFILING) && defined (CONFIG_TRACEPOINTS) -#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED #include "mali_linux_trace.h" -#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ - #include "mali_profiling_events.h" +#include "mali_profiling_gator_api.h" #define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 @@ -59,13 +57,8 @@ _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); * @param data4 Fifth data parameter, depending on event_id specified. * @return _MALI_OSK_ERR_OK on success, otherwise failure. */ -#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED /* Call Linux tracepoint directly */ #define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4)) -#else -/* Internal profiling is handled like a plain function call */ -void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); -#endif /** * Report a hardware counter event. @@ -74,13 +67,8 @@ void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2 * @param value The value of the counter. */ -#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED /* Call Linux tracepoint directly */ #define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value) -#else -/* Internal profiling is handled like a plain function call */ -void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value); -#endif /** * Report SW counters @@ -140,7 +128,13 @@ mali_bool _mali_osk_profiling_have_recording(void); /** @} */ /* end group _mali_osk_profiling */ -#endif /* MALI_TIMELINE_PROFILING_ENABLED */ +#else /* defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_TRACEPOINTS) */ + + /* Dummy add_event, for when profiling is disabled. */ + +#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) + +#endif /* defined(CONFIG_MALI400_PROFILING) && defined(CONFIG_TRACEPOINTS) */ #endif /* __MALI_OSK_PROFILING_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.c new file mode 100644 index 0000000..e1d6aa4 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011-2012 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 "mali_pm.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" +#include "mali_scheduler.h" +#include "mali_kernel_utilization.h" +#include "mali_group.h" +#include "mali_pm_domain.h" +#include "mali_pmu.h" + +static mali_bool mali_power_on = MALI_FALSE; + +_mali_osk_errcode_t mali_pm_initialize(void) +{ + _mali_osk_pm_dev_enable(); + return _MALI_OSK_ERR_OK; +} + +void mali_pm_terminate(void) +{ + mali_pm_domain_terminate(); + _mali_osk_pm_dev_disable(); +} + +/* Reset GPU after power up */ +static void mali_pm_reset_gpu(void) +{ + /* Reset all L2 caches */ + mali_l2_cache_reset_all(); + + /* Reset all groups */ + mali_scheduler_reset_all_groups(); +} + +void mali_pm_os_suspend(void) +{ + MALI_DEBUG_PRINT(3, ("Mali PM: OS suspend\n")); + mali_gp_scheduler_suspend(); + mali_pp_scheduler_suspend(); + mali_utilization_suspend(); +/* MALI_SEC */ +#if !defined(CONFIG_PM_RUNTIME) + mali_group_power_off(); + mali_power_on = MALI_FALSE; +#endif +} + +void mali_pm_os_resume(void) +{ +#if !defined(CONFIG_PM_RUNTIME) + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + mali_bool do_reset = MALI_FALSE; +#endif + + MALI_DEBUG_PRINT(3, ("Mali PM: OS resume\n")); +/* MALI_SEC */ +/****************************************************************** + * + * <2013. 08. 23> + * In Pegasus prime, PMU is not enabled(Power off) while + * system wake up(suspend -> resume). + * + * Because PMU power is off, GPU does not work. + * Therefore code is commented like below. + * + *****************************************************************/ +#if !defined(CONFIG_PM_RUNTIME) + if (MALI_TRUE != mali_power_on) + { + do_reset = MALI_TRUE; + } + + if (NULL != pmu) + { + mali_pmu_reset(pmu); + } + + mali_power_on = MALI_TRUE; + _mali_osk_write_mem_barrier(); + + if (do_reset) + { + mali_pm_reset_gpu(); + mali_group_power_on(); + } +#endif + mali_gp_scheduler_resume(); + mali_pp_scheduler_resume(); +} + +void mali_pm_runtime_suspend(void) +{ + MALI_DEBUG_PRINT(3, ("Mali PM: Runtime suspend\n")); + mali_group_power_off(); + mali_power_on = MALI_FALSE; +} + +void mali_pm_runtime_resume(void) +{ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + mali_bool do_reset = MALI_FALSE; + + MALI_DEBUG_PRINT(3, ("Mali PM: Runtime resume\n")); + + if (MALI_TRUE != mali_power_on) + { + do_reset = MALI_TRUE; + } + + if (NULL != pmu) + { + mali_pmu_reset(pmu); + } + + mali_power_on = MALI_TRUE; + _mali_osk_write_mem_barrier(); + + if (do_reset) + { + mali_pm_reset_gpu(); + mali_group_power_on(); + } +} + +void mali_pm_set_power_is_on(void) +{ + mali_power_on = MALI_TRUE; +} + +mali_bool mali_pm_is_power_on(void) +{ + return mali_power_on; +} diff --git a/drivers/media/video/samsung/mali/common/mali_pm.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.h index d4ccfde..36f0f50 100644 --- a/drivers/media/video/samsung/mali/common/mali_pm.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm.h @@ -13,44 +13,16 @@ #include "mali_osk.h" -enum mali_core_event -{ - MALI_CORE_EVENT_GP_START, - MALI_CORE_EVENT_GP_STOP, - MALI_CORE_EVENT_PP_START, - MALI_CORE_EVENT_PP_STOP -}; - -enum mali_pm_event -{ - MALI_PM_EVENT_CORES_WORKING, - MALI_PM_EVENT_CORES_IDLE, - MALI_PM_EVENT_TIMER_LIGHT_SLEEP, - MALI_PM_EVENT_TIMER_DEEP_SLEEP, - MALI_PM_EVENT_OS_SUSPEND, - MALI_PM_EVENT_OS_RESUME, - MALI_PM_EVENT_SCHEME_ALWAYS_ON, - MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, -}; - _mali_osk_errcode_t mali_pm_initialize(void); void mali_pm_terminate(void); -void mali_pm_always_on(mali_bool enable); - -void mali_pm_lock(void); -void mali_pm_unlock(void); -void mali_pm_execute_state_change_lock(void); - -void mali_pm_execute_state_change_unlock(void); - -mali_bool mali_pm_is_powered_on(void); - -void mali_pm_core_event(enum mali_core_event core_event); +/* Callback functions registered for the runtime PMM system */ void mali_pm_os_suspend(void); void mali_pm_os_resume(void); void mali_pm_runtime_suspend(void); void mali_pm_runtime_resume(void); +void mali_pm_set_power_is_on(void); +mali_bool mali_pm_is_power_on(void); #endif /* __MALI_PM_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c new file mode 100644 index 0000000..9193778 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2010-2012 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 "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_pm_domain.h" +#include "mali_pmu.h" +#include "mali_pm.h" +#include "mali_group.h" + +#define MALI_PM_DOMAIN_MAX_DOMAINS 7 + +static struct mali_pm_domain *mali_pm_domains[MALI_PM_DOMAIN_MAX_DOMAINS] = { NULL, }; + +static void mali_pm_domain_lock(struct mali_pm_domain *domain) +{ + _mali_osk_lock_wait(domain->lock, _MALI_OSK_LOCKMODE_RW); +} + +static void mali_pm_domain_unlock(struct mali_pm_domain *domain) +{ + _mali_osk_lock_signal(domain->lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_pm_domain_state_set(struct mali_pm_domain *domain, mali_pm_domain_state state) +{ + domain->state = state; +} + +struct mali_pm_domain *mali_pm_domain_create(u32 id, u32 pmu_mask) +{ + struct mali_pm_domain* domain; + + MALI_DEBUG_PRINT(2, ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n", pmu_mask)); + + domain = (struct mali_pm_domain *)_mali_osk_malloc(sizeof(struct mali_pm_domain)); + if (NULL != domain) + { + _mali_osk_lock_flags_t flags = _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; + domain->lock = _mali_osk_lock_init(flags, 0, _MALI_OSK_LOCK_ORDER_PM_DOMAIN); + if (NULL == domain->lock) + { + _mali_osk_free(domain); + return NULL; + } + + domain->state = MALI_PM_DOMAIN_ON; + domain->pmu_mask = pmu_mask; + domain->use_count = 0; + domain->group_list = NULL; + domain->group_count = 0; + domain->l2 = NULL; + + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_MAX_DOMAINS > id); + mali_pm_domains[id] = domain; + + return domain; + } + else + { + MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n")); + } + + return NULL; +} + +void mali_pm_domain_delete(struct mali_pm_domain *domain) +{ + if (NULL == domain) + { + return; + } + _mali_osk_lock_term(domain->lock); + + _mali_osk_free(domain); +} + +void mali_pm_domain_terminate(void) +{ + int i; + + /* Delete all domains */ + for (i = 0; i < MALI_PM_DOMAIN_MAX_DOMAINS; i++) + { + mali_pm_domain_delete(mali_pm_domains[i]); + } +} + +void mali_pm_domain_add_group(u32 id, struct mali_group *group) +{ + struct mali_pm_domain *domain = mali_pm_domain_get(id); + struct mali_group *next; + + if (NULL == domain) return; + + MALI_DEBUG_ASSERT_POINTER(group); + + /* Assume domain is on and group is enabled initially. */ + mali_pm_domain_ref_get(domain); + + ++domain->group_count; + next = domain->group_list; + + domain->group_list = group; + + group->pm_domain_list = next; + + mali_group_set_pm_domain(group, domain); +} + +void mali_pm_domain_add_l2(u32 id, struct mali_l2_cache_core *l2) +{ + struct mali_pm_domain *domain = mali_pm_domain_get(id); + + if (NULL == domain) return; + + MALI_DEBUG_ASSERT(NULL == domain->l2); + MALI_DEBUG_ASSERT(NULL != l2); + + domain->l2 = l2; + + mali_l2_cache_set_pm_domain(l2, domain); +} + +struct mali_pm_domain *mali_pm_domain_get(u32 id) +{ + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_MAX_DOMAINS > id); + + return mali_pm_domains[id]; +} + +void mali_pm_domain_ref_get(struct mali_pm_domain *domain) +{ + if (NULL == domain) return; + + mali_pm_domain_lock(domain); + ++domain->use_count; + + if (MALI_PM_DOMAIN_ON != domain->state) + { + /* Power on */ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(3, ("PM Domain: Powering on 0x%08x\n", domain->pmu_mask)); + + if (NULL != pmu) + { + _mali_osk_errcode_t err; + + err = mali_pmu_power_up(pmu, domain->pmu_mask); + + if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) + { + MALI_PRINT_ERROR(("PM Domain: Failed to power up PM domain 0x%08x\n", + domain->pmu_mask)); + } + } + mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_ON); + } + else + { + MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(domain)); + } + + mali_pm_domain_unlock(domain); +} + +void mali_pm_domain_ref_put(struct mali_pm_domain *domain) +{ + if (NULL == domain) return; + + mali_pm_domain_lock(domain); + --domain->use_count; + + if (0 == domain->use_count && MALI_PM_DOMAIN_OFF != domain->state) + { + /* Power off */ + struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core(); + + MALI_DEBUG_PRINT(3, ("PM Domain: Powering off 0x%08x\n", domain->pmu_mask)); + + mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_OFF); + + if (NULL != pmu) + { + _mali_osk_errcode_t err; + + err = mali_pmu_power_down(pmu, domain->pmu_mask); + + if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) + { + MALI_PRINT_ERROR(("PM Domain: Failed to power down PM domain 0x%08x\n", + domain->pmu_mask)); + } + } + } + mali_pm_domain_unlock(domain); +} + +mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain) +{ + mali_bool is_powered = MALI_TRUE; + + /* Take a reference without powering on */ + if (NULL != domain) + { + mali_pm_domain_lock(domain); + ++domain->use_count; + + if (MALI_PM_DOMAIN_ON != domain->state) + { + is_powered = MALI_FALSE; + } + mali_pm_domain_unlock(domain); + } + + if(!_mali_osk_pm_dev_ref_add_no_power_on()) + { + is_powered = MALI_FALSE; + } + + return is_powered; +} + +void mali_pm_domain_unlock_state(struct mali_pm_domain *domain) +{ + _mali_osk_pm_dev_ref_dec_no_power_on(); + + if (NULL != domain) + { + mali_pm_domain_ref_put(domain); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h new file mode 100644 index 0000000..3f3fa24 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pm_domain.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010-2012 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_PM_DOMAIN_H__ +#define __MALI_PM_DOMAIN_H__ + +#include "mali_kernel_common.h" +#include "mali_osk.h" + +#include "mali_l2_cache.h" +#include "mali_group.h" +#include "mali_pmu.h" + +typedef enum +{ + MALI_PM_DOMAIN_ON, + MALI_PM_DOMAIN_OFF, +} mali_pm_domain_state; + +struct mali_pm_domain +{ + mali_pm_domain_state state; + _mali_osk_lock_t *lock; + + s32 use_count; + + u32 pmu_mask; + + int group_count; + struct mali_group *group_list; + + struct mali_l2_cache_core *l2; +}; + +struct mali_pm_domain *mali_pm_domain_create(u32 id, u32 pmu_mask); +void mali_pm_domain_add_group(u32 id, struct mali_group *group); +void mali_pm_domain_add_l2(u32 id, struct mali_l2_cache_core *l2); +void mali_pm_domain_delete(struct mali_pm_domain *domain); + +void mali_pm_domain_terminate(void); + +/** Get PM domain from domain ID + */ +struct mali_pm_domain *mali_pm_domain_get(u32 id); + +/* Ref counting */ +void mali_pm_domain_ref_get(struct mali_pm_domain *domain); +void mali_pm_domain_ref_put(struct mali_pm_domain *domain); + +MALI_STATIC_INLINE struct mali_l2_cache_core *mali_pm_domain_l2_get(struct mali_pm_domain *domain) +{ + return domain->l2; +} + +MALI_STATIC_INLINE mali_pm_domain_state mali_pm_domain_state_get(struct mali_pm_domain *domain) +{ + return domain->state; +} + +mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain); +void mali_pm_domain_unlock_state(struct mali_pm_domain *domain); + +#define MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) for ((group) = (domain)->group_list;\ + NULL != (group); (group) = (group)->pm_domain_list) + +#endif /* __MALI_PM_DOMAIN_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c new file mode 100644 index 0000000..668c8e9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.c @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2010-2012 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_pmu.c + * Mali driver functions for Mali 400 PMU hardware + */ +#include "mali_hw_core.h" +#include "mali_pmu.h" +#include "mali_pp.h" +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_pm.h" +#include "mali_osk_mali.h" + +static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches); + +/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask + */ +struct mali_pmu_core +{ + struct mali_hw_core hw_core; + _mali_osk_lock_t *lock; + u32 registered_cores_mask; + u32 active_cores_mask; + u32 switch_delay; +}; + +static struct mali_pmu_core *mali_global_pmu_core = NULL; + +/** @brief Register layout for hardware PMU + */ +typedef enum { + PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */ + PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */ + PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */ + PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */ + PMU_REG_ADDR_MGMT_INT_RAWSTAT = 0x10, /*< Interrupt raw status register */ + PMU_REG_ADDR_MGMT_INT_CLEAR = 0x18, /*< Interrupt clear register */ + PMU_REG_ADDR_MGMT_SW_DELAY = 0x1C, /*< Switch delay register */ + PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x28, /*< Size of register space */ +} pmu_reg_addr_mgmt_addr; + +#define PMU_REG_VAL_IRQ 1 + +struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches) +{ + struct mali_pmu_core* pmu; + + MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core); + MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n")); + + pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core)); + if (NULL != pmu) + { + pmu->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, + 0, _MALI_OSK_LOCK_ORDER_PMU); + if (NULL != pmu->lock) + { + pmu->registered_cores_mask = mali_pmu_detect_mask(number_of_pp_cores, number_of_l2_caches); + pmu->active_cores_mask = pmu->registered_cores_mask; + + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE)) + { + _mali_osk_errcode_t err; + struct _mali_osk_device_data data = { 0, }; + + err = _mali_osk_device_data_get(&data); + if (_MALI_OSK_ERR_OK == err) + { + pmu->switch_delay = data.pmu_switch_delay; + mali_global_pmu_core = pmu; + return pmu; + } + mali_hw_core_delete(&pmu->hw_core); + } + _mali_osk_lock_term(pmu->lock); + } + _mali_osk_free(pmu); + } + + return NULL; +} + +void mali_pmu_delete(struct mali_pmu_core *pmu) +{ + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu == mali_global_pmu_core); + MALI_DEBUG_PRINT(2, ("Mali PMU: Deleting Mali PMU core\n")); + + _mali_osk_lock_term(pmu->lock); + mali_hw_core_delete(&pmu->hw_core); + _mali_osk_free(pmu); + mali_global_pmu_core = NULL; +} + +static void mali_pmu_lock(struct mali_pmu_core *pmu) +{ + _mali_osk_lock_wait(pmu->lock, _MALI_OSK_LOCKMODE_RW); +} +static void mali_pmu_unlock(struct mali_pmu_core *pmu) +{ + _mali_osk_lock_signal(pmu->lock, _MALI_OSK_LOCKMODE_RW); +} + +static _mali_osk_errcode_t mali_pmu_send_command_internal(struct mali_pmu_core *pmu, const u32 command, const u32 mask) +{ + u32 rawstat; + u32 timeout = MALI_REG_POLL_COUNT_SLOW; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(0 == (mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT) + & PMU_REG_VAL_IRQ)); + + mali_hw_core_register_write(&pmu->hw_core, command, mask); + + /* Wait for the command to complete */ + do + { + rawstat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT); + --timeout; + } while (0 == (rawstat & PMU_REG_VAL_IRQ) && 0 < timeout); + + MALI_DEBUG_ASSERT(0 < timeout); + if (0 == timeout) + { + return _MALI_OSK_ERR_TIMEOUT; + } + + mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_CLEAR, PMU_REG_VAL_IRQ); + + return _MALI_OSK_ERR_OK; +} + +static _mali_osk_errcode_t mali_pmu_send_command(struct mali_pmu_core *pmu, const u32 command, const u32 mask) +{ + u32 stat; + + if (0 == mask) return _MALI_OSK_ERR_OK; + + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->registered_cores_mask; + + switch (command) + { + case PMU_REG_ADDR_MGMT_POWER_DOWN: + if (mask == stat) return _MALI_OSK_ERR_OK; + break; + case PMU_REG_ADDR_MGMT_POWER_UP: + if (0 == (stat & mask)) return _MALI_OSK_ERR_OK; + break; + default: + MALI_DEBUG_ASSERT(0); + break; + } + + mali_pmu_send_command_internal(pmu, command, mask); + +#if defined(DEBUG) + { + /* Get power status of cores */ + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->registered_cores_mask; + + switch (command) + { + case PMU_REG_ADDR_MGMT_POWER_DOWN: + MALI_DEBUG_ASSERT(mask == (stat & mask)); + MALI_DEBUG_ASSERT(0 == (stat & pmu->active_cores_mask)); + MALI_DEBUG_ASSERT((pmu->registered_cores_mask & ~pmu->active_cores_mask) == stat); + break; + case PMU_REG_ADDR_MGMT_POWER_UP: + MALI_DEBUG_ASSERT(0 == (stat & mask)); + MALI_DEBUG_ASSERT(0 == (stat & pmu->active_cores_mask)); + break; + default: + MALI_DEBUG_ASSERT(0); + break; + } + } +#endif /* defined(DEBUG) */ + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu) +{ + _mali_osk_errcode_t err; + u32 cores_off_mask, cores_on_mask, stat; + + mali_pmu_lock(pmu); + + /* Setup the desired defaults */ + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay); + + /* Get power status of cores */ + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + + cores_off_mask = pmu->registered_cores_mask & ~(stat | pmu->active_cores_mask); + cores_on_mask = pmu->registered_cores_mask & (stat & pmu->active_cores_mask); + + if (0 != cores_off_mask) + { + err = mali_pmu_send_command_internal(pmu, PMU_REG_ADDR_MGMT_POWER_DOWN, cores_off_mask); + if (_MALI_OSK_ERR_OK != err) return err; + } + + if (0 != cores_on_mask) + { + err = mali_pmu_send_command_internal(pmu, PMU_REG_ADDR_MGMT_POWER_UP, cores_on_mask); + if (_MALI_OSK_ERR_OK != err) return err; + } + +#if defined(DEBUG) + { + stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); + stat &= pmu->registered_cores_mask; + + MALI_DEBUG_ASSERT(stat == (pmu->registered_cores_mask & ~pmu->active_cores_mask)); + } +#endif /* defined(DEBUG) */ + + mali_pmu_unlock(pmu); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pmu_power_down(struct mali_pmu_core *pmu, u32 mask) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0 ); + + /* Make sure we have a valid power domain mask */ + if (mask > pmu->registered_cores_mask) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + mali_pmu_lock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power down (0x%08X)\n", mask)); + + pmu->active_cores_mask &= ~mask; + + _mali_osk_pm_dev_ref_add_no_power_on(); + if (!mali_pm_is_power_on()) + { + /* Don't touch hardware if all of Mali is powered off. */ + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Skipping power down (0x%08X) since Mali is off\n", mask)); + + return _MALI_OSK_ERR_BUSY; + } + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_DOWN, mask); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + return err; +} + +_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0 ); + + /* Make sure we have a valid power domain mask */ + if (mask & ~pmu->registered_cores_mask) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } + + mali_pmu_lock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power up (0x%08X)\n", mask)); + + pmu->active_cores_mask |= mask; + + _mali_osk_pm_dev_ref_add_no_power_on(); + if (!mali_pm_is_power_on()) + { + /* Don't touch hardware if all of Mali is powered off. */ + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + MALI_DEBUG_PRINT(4, ("Mali PMU: Skipping power up (0x%08X) since Mali is off\n", mask)); + + return _MALI_OSK_ERR_BUSY; + } + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_UP, mask); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pmu_unlock(pmu); + + return err; +} + +_mali_osk_errcode_t mali_pmu_power_down_all(struct mali_pmu_core *pmu) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0); + + mali_pmu_lock(pmu); + + /* Setup the desired defaults in case we were called before mali_pmu_reset() */ + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay); + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_DOWN, pmu->registered_cores_mask); + + mali_pmu_unlock(pmu); + + return err; +} + +_mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu) +{ + _mali_osk_errcode_t err; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0); + + mali_pmu_lock(pmu); + + /* Setup the desired defaults in case we were called before mali_pmu_reset() */ + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); + mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay); + + err = mali_pmu_send_command(pmu, PMU_REG_ADDR_MGMT_POWER_UP, pmu->active_cores_mask); + + mali_pmu_unlock(pmu); + return err; +} + +struct mali_pmu_core *mali_pmu_get_global_pmu_core(void) +{ + return mali_global_pmu_core; +} + +static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches) +{ + u32 mask = 0; + + if (number_of_l2_caches == 1) + { + /* Mali-300 or Mali-400 */ + u32 i; + + /* GP */ + mask = 0x01; + + /* L2 cache */ + mask |= 0x01<<1; + + /* Set bit for each PP core */ + for (i = 0; i < number_of_pp_cores; i++) + { + mask |= 0x01<<(i+2); + } + } + else if (number_of_l2_caches > 1) + { + /* Mali-450 */ + + /* GP (including its L2 cache) */ + mask = 0x01; + + /* There is always at least one PP (including its L2 cache) */ + mask |= 0x01<<1; + + /* Additional PP cores in same L2 cache */ + if (number_of_pp_cores >= 2) + { + mask |= 0x01<<2; + } + + /* Additional PP cores in a third L2 cache */ + if (number_of_pp_cores >= 5) + { + mask |= 0x01<<3; + } + } + + MALI_DEBUG_PRINT(4, ("Mali PMU: Power mask is 0x%08X (%u + %u)\n", mask, number_of_pp_cores, number_of_l2_caches)); + + return mask; +} diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h index fd10c08..7e2f67c 100644 --- a/drivers/media/video/samsung/mali/common/mali_pmu.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pmu.h @@ -13,8 +13,27 @@ * Platform specific Mali driver functions */ +#ifndef __MALI_PMU_H__ +#define __MALI_PMU_H__ + #include "mali_osk.h" +#define MALI_PMU_M450_DOM1 0 +#define MALI_PMU_M450_DOM1_MASK (1 << 1) +#define MALI_PMU_M450_DOM2 1 +#define MALI_PMU_M450_DOM2_MASK (1 << 2) +#define MALI_PMU_M450_DOM3 2 +#define MALI_PMU_M450_DOM3_MASK (1 << 3) + +#define MALI_PMU_M400_PP0 0 +#define MALI_PMU_M400_PP0_MASK (1 << 2) +#define MALI_PMU_M400_PP1 1 +#define MALI_PMU_M400_PP1_MASK (1 << 3) +#define MALI_PMU_M400_PP2 2 +#define MALI_PMU_M400_PP2_MASK (1 << 4) +#define MALI_PMU_M400_PP3 3 +#define MALI_PMU_M400_PP3_MASK (1 << 5) + struct mali_pmu_core; /** @brief Initialisation of MALI PMU @@ -45,26 +64,50 @@ _mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu); /** @brief MALI GPU power down using MALI in-built PMU * - * called to power down all cores + * Called to power down the specified cores. The mask will be saved so that \a + * mali_pmu_power_up_all will bring the PMU back to the previous state set with + * this function or \a mali_pmu_power_up. * * @param pmu Pointer to PMU core object to power down + * @param mask Mask specifying which power domains to power down + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_power_down(struct mali_pmu_core *pmu, u32 mask); + +/** @brief MALI GPU power up using MALI in-built PMU + * + * Called to power up the specified cores. The mask will be saved so that \a + * mali_pmu_power_up_all will bring the PMU back to the previous state set with + * this function or \a mali_pmu_power_down. + * + * @param pmu Pointer to PMU core object to power up + * @param mask Mask specifying which power domains to power up * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. */ -_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu); +_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask); +/** @brief MALI GPU power down using MALI in-built PMU + * + * called to power down all cores + * + * @param pmu Pointer to PMU core object to power down + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmu_power_down_all(struct mali_pmu_core *pmu); /** @brief MALI GPU power up using MALI in-built PMU - * + * * called to power up all cores * * @param pmu Pointer to PMU core object to power up * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. */ -_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu); - +_mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu); /** @brief Retrieves the Mali PMU core object (if any) * * @return The Mali PMU object, or NULL if no PMU exists. */ struct mali_pmu_core *mali_pmu_get_global_pmu_core(void); + +#endif /* __MALI_PMU_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.c new file mode 100644 index 0000000..8273239 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.c @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2011-2012 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 "mali_pp_job.h" +#include "mali_pp.h" +#include "mali_hw_core.h" +#include "mali_group.h" +#include "regs/mali_200_regs.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +/* Number of frame registers on Mali-200 */ +#define MALI_PP_MALI200_NUM_FRAME_REGISTERS ((0x04C/4)+1) +/* Number of frame registers on Mali-300 and later */ +#define MALI_PP_MALI400_NUM_FRAME_REGISTERS ((0x058/4)+1) + +static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES] = { NULL }; +static u32 mali_global_num_pp_cores = 0; + +/* Interrupt handlers */ +static void mali_pp_irq_probe_trigger(void *data); +static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data); + +struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id) +{ + struct mali_pp_core* core = NULL; + + MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description)); + MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base)); + + if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) + { + MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n")); + return NULL; + } + + core = _mali_osk_malloc(sizeof(struct mali_pp_core)); + if (NULL != core) + { + core->core_id = mali_global_num_pp_cores; + core->bcast_id = bcast_id; + core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; + core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; + + if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) + { + _mali_osk_errcode_t ret; + + if (!is_virtual) + { + ret = mali_pp_reset(core); + } + else + { + ret = _MALI_OSK_ERR_OK; + } + + if (_MALI_OSK_ERR_OK == ret) + { + ret = mali_group_add_pp_core(group, core); + if (_MALI_OSK_ERR_OK == ret) + { + /* Setup IRQ handlers (which will do IRQ probing if needed) */ + MALI_DEBUG_ASSERT(!is_virtual || -1 != resource->irq); + + core->irq = _mali_osk_irq_init(resource->irq, + mali_group_upper_half_pp, + group, + mali_pp_irq_probe_trigger, + mali_pp_irq_probe_ack, + core, + "mali_pp_irq_handlers"); + if (NULL != core->irq) + { + mali_global_pp_cores[mali_global_num_pp_cores] = core; + mali_global_num_pp_cores++; + + return core; + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description)); + } + mali_group_remove_pp_core(group); + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to add core %s to group\n", core->hw_core.description)); + } + } + mali_hw_core_delete(&core->hw_core); + } + + _mali_osk_free(core); + } + else + { + MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n")); + } + + return NULL; +} + +void mali_pp_delete(struct mali_pp_core *core) +{ + u32 i; + + MALI_DEBUG_ASSERT_POINTER(core); + + _mali_osk_irq_term(core->irq); + mali_hw_core_delete(&core->hw_core); + + /* Remove core from global list */ + for (i = 0; i < mali_global_num_pp_cores; i++) + { + if (mali_global_pp_cores[i] == core) + { + mali_global_pp_cores[i] = NULL; + mali_global_num_pp_cores--; + + if (i != mali_global_num_pp_cores) + { + /* We removed a PP core from the middle of the array -- move the last + * PP core to the current position to close the gap */ + mali_global_pp_cores[i] = mali_global_pp_cores[mali_global_num_pp_cores]; + mali_global_pp_cores[mali_global_num_pp_cores] = NULL; + } + + break; + } + } + + _mali_osk_free(core); +} + +void mali_pp_stop_bus(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + /* Will only send the stop bus command, and not wait for it to complete */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); +} + +_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core) +{ + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Send the stop bus command. */ + mali_pp_stop_bus(core); + + /* Wait for bus to be stopped */ + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) + break; + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + +/* Frame register reset values. + * Taken from the Mali400 TRM, 3.6. Pixel processor control register summary */ +static const u32 mali_frame_registers_reset_values[_MALI_PP_MAX_FRAME_REGISTERS] = +{ + 0x0, /* Renderer List Address Register */ + 0x0, /* Renderer State Word Base Address Register */ + 0x0, /* Renderer Vertex Base Register */ + 0x2, /* Feature Enable Register */ + 0x0, /* Z Clear Value Register */ + 0x0, /* Stencil Clear Value Register */ + 0x0, /* ABGR Clear Value 0 Register */ + 0x0, /* ABGR Clear Value 1 Register */ + 0x0, /* ABGR Clear Value 2 Register */ + 0x0, /* ABGR Clear Value 3 Register */ + 0x0, /* Bounding Box Left Right Register */ + 0x0, /* Bounding Box Bottom Register */ + 0x0, /* FS Stack Address Register */ + 0x0, /* FS Stack Size and Initial Value Register */ + 0x0, /* Reserved */ + 0x0, /* Reserved */ + 0x0, /* Origin Offset X Register */ + 0x0, /* Origin Offset Y Register */ + 0x75, /* Subpixel Specifier Register */ + 0x0, /* Tiebreak mode Register */ + 0x0, /* Polygon List Format Register */ + 0x0, /* Scaling Register */ + 0x0 /* Tilebuffer configuration Register */ +}; + +/* WBx register reset values */ +static const u32 mali_wb_registers_reset_values[_MALI_PP_MAX_WB_REGISTERS] = +{ + 0x0, /* WBx Source Select Register */ + 0x0, /* WBx Target Address Register */ + 0x0, /* WBx Target Pixel Format Register */ + 0x0, /* WBx Target AA Format Register */ + 0x0, /* WBx Target Layout */ + 0x0, /* WBx Target Scanline Length */ + 0x0, /* WBx Target Flags Register */ + 0x0, /* WBx MRT Enable Register */ + 0x0, /* WBx MRT Offset Register */ + 0x0, /* WBx Global Test Enable Register */ + 0x0, /* WBx Global Test Reference Value Register */ + 0x0 /* WBx Global Test Compare Function Register */ +}; + +/* Performance Counter 0 Enable Register reset value */ +static const u32 mali_perf_cnt_enable_reset_value = 0; + +_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) +{ + /* Bus must be stopped before calling this function */ + const u32 reset_invalid_value = 0xC0FFE000; + const u32 reset_check_value = 0xC01A0000; + int i; + + MALI_DEBUG_ASSERT_POINTER(core); + MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description)); + + /* Set register to a bogus value. The register will be used to detect when reset is complete */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value); + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); + + /* Force core to reset */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET); + + /* Wait for reset to be complete */ + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value); + if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) + { + break; + } + } + + if (MALI_REG_POLL_COUNT_FAST == i) + { + MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n")); + } + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */ + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +void mali_pp_reset_async(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + + MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description)); + + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET); +} + +_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core) +{ + int i; + u32 rawstat = 0; + + for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) + { + if (!(mali_pp_read_status(core) & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)) + { + rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT); + if (rawstat == MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) + { + break; + } + } + } + + if (i == MALI_REG_POLL_COUNT_FAST) + { + MALI_PRINT_ERROR(("Mali PP: Failed to reset core %s, rawstat: 0x%08x\n", + core->hw_core.description, rawstat)); + return _MALI_OSK_ERR_FAULT; + } + + /* Re-enable interrupts */ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core) +{ + mali_pp_reset_async(core); + return mali_pp_reset_wait(core); +} + +void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual) +{ + u32 relative_address; + u32 start_index; + u32 nr_of_regs; + u32 *frame_registers = mali_pp_job_get_frame_registers(job); + u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); + u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); + u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); + core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); + core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); + + MALI_DEBUG_ASSERT_POINTER(core); + + /* Write frame registers */ + + /* + * There are two frame registers which are different for each sub job: + * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME) + * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK) + */ + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]); + + /* For virtual jobs, the stack address shouldn't be broadcast but written individually */ + if (!mali_pp_job_is_virtual(job) || restart_virtual) + { + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]); + } + + /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */ + relative_address = MALI200_REG_ADDR_RSW; + start_index = MALI200_REG_ADDR_RSW / sizeof(u32); + nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32); + + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, + relative_address, &frame_registers[start_index], + nr_of_regs, &mali_frame_registers_reset_values[start_index]); + + /* MALI200_REG_ADDR_STACK_SIZE */ + relative_address = MALI200_REG_ADDR_STACK_SIZE; + start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32); + + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, + relative_address, frame_registers[start_index], + mali_frame_registers_reset_values[start_index]); + + /* Skip 2 reserved registers */ + + /* Write remaining registers */ + relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X; + start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32); + nr_of_regs = MALI_PP_MALI400_NUM_FRAME_REGISTERS - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32); + + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, + relative_address, &frame_registers[start_index], + nr_of_regs, &mali_frame_registers_reset_values[start_index]); + + /* Write WBx registers */ + if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); + } + + if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); + } + + if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ + { + mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); + } + + if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) + { + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + } + if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) + { + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + } + + MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); + + /* Adding barrier to make sure all rester writes are finished */ + _mali_osk_write_mem_barrier(); + + /* This is the command that starts the core. */ + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); + + /* Adding barrier to make sure previous rester writes is finished */ + _mali_osk_write_mem_barrier(); +} + +u32 mali_pp_core_get_version(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION); +} + +struct mali_pp_core* mali_pp_get_global_pp_core(u32 index) +{ + if (mali_global_num_pp_cores > index) + { + return mali_global_pp_cores[index]; + } + + return NULL; +} + +u32 mali_pp_get_glob_num_pp_cores(void) +{ + return mali_global_num_pp_cores; +} + +/* ------------- interrupt handling below ------------------ */ +static void mali_pp_irq_probe_trigger(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); +} + +static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data) +{ + struct mali_pp_core *core = (struct mali_pp_core *)data; + u32 irq_readout; + + irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); + if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) + { + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG); + _mali_osk_mem_barrier(); + return _MALI_OSK_ERR_OK; + } + + return _MALI_OSK_ERR_FAULT; +} + + +#if 0 +static void mali_pp_print_registers(struct mali_pp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC))); + MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE))); +} +#endif + +#if 0 +void mali_pp_print_state(struct mali_pp_core *core) +{ + MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) )); +} +#endif + +void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob) +{ + u32 val0 = 0; + u32 val1 = 0; +#if defined(CONFIG_MALI400_PROFILING) + int counter_index = COUNTER_FP_0_C0 + (2 * child->core_id); +#endif + + if (MALI_HW_CORE_NO_COUNTER != parent->counter_src0_used) + { + val0 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); + mali_pp_job_set_perf_counter_value0(job, subjob, val0); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(counter_index, val0); +#endif + } + + if (MALI_HW_CORE_NO_COUNTER != parent->counter_src1_used) + { + val1 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + mali_pp_job_set_perf_counter_value1(job, subjob, val1); + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); +#endif + } +} + +#if MALI_STATE_TRACKING +u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size) +{ + int n = 0; + + n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description); + + return n; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.h new file mode 100644 index 0000000..dd8f350 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2011-2012 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_PP_H__ +#define __MALI_PP_H__ + +#include "mali_osk.h" +#include "mali_pp_job.h" +#include "mali_hw_core.h" + +struct mali_group; + +#define MALI_MAX_NUMBER_OF_PP_CORES 9 + +/** + * Definition of the PP core struct + * Used to track a PP core in the system. + */ +struct mali_pp_core +{ + struct mali_hw_core hw_core; /**< Common for all HW cores */ + _mali_osk_irq_t *irq; /**< IRQ handler */ + u32 core_id; /**< Unique core ID */ + u32 bcast_id; /**< The "flag" value used by the Mali-450 broadcast and DLBU unit */ + u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ + u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ +}; + +_mali_osk_errcode_t mali_pp_initialize(void); +void mali_pp_terminate(void); + +struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id); +void mali_pp_delete(struct mali_pp_core *core); + +void mali_pp_stop_bus(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core); +void mali_pp_reset_async(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core); +_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core); + +void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual); + +u32 mali_pp_core_get_version(struct mali_pp_core *core); + +MALI_STATIC_INLINE u32 mali_pp_core_get_id(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->core_id; +} + +MALI_STATIC_INLINE u32 mali_pp_core_get_bcast_id(struct mali_pp_core *core) +{ + MALI_DEBUG_ASSERT_POINTER(core); + return core->bcast_id; +} + +struct mali_pp_core* mali_pp_get_global_pp_core(u32 index); +u32 mali_pp_get_glob_num_pp_cores(void); + +/* Debug */ +u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size); + +/** + * Put instrumented HW counters from the core(s) to the job object (if enabled) + * + * parent and child is always the same, except for virtual jobs on Mali-450. + * In this case, the counters will be enabled on the virtual core (parent), + * but values need to be read from the child cores. + * + * @param parent The core used to see if the counters was enabled + * @param child The core to actually read the values from + * @job Job object to update with counter values (if enabled) + * @subjob Which subjob the counters are applicable for (core ID for virtual jobs) + */ +void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob); + +MALI_STATIC_INLINE const char *mali_pp_get_hw_core_desc(struct mali_pp_core *core) +{ + return core->hw_core.description; +} + +/*** Register reading/writing functions ***/ +MALI_STATIC_INLINE u32 mali_pp_get_int_stat(struct mali_pp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); +} + +MALI_STATIC_INLINE u32 mali_pp_read_rawstat(struct mali_pp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; +} + +MALI_STATIC_INLINE u32 mali_pp_read_status(struct mali_pp_core *core) +{ + return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS); +} + +MALI_STATIC_INLINE void mali_pp_mask_all_interrupts(struct mali_pp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); +} + +MALI_STATIC_INLINE void mali_pp_clear_hang_interrupt(struct mali_pp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG); +} + +MALI_STATIC_INLINE void mali_pp_enable_interrupts(struct mali_pp_core *core) +{ + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); +} + +MALI_STATIC_INLINE void mali_pp_write_addr_stack(struct mali_pp_core *core, struct mali_pp_job *job) +{ + u32 addr = mali_pp_job_get_addr_stack(job, core->core_id); + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, addr); +} + +#endif /* __MALI_PP_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c new file mode 100644 index 0000000..ca0ea05 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2012 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 "mali_pp_job.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_kernel_common.h" +#include "mali_uk_types.h" +#include "mali_pp_scheduler.h" + +static u32 pp_counter_src0 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ +static u32 pp_counter_src1 = MALI_HW_CORE_NO_COUNTER; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ + +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id) +{ + struct mali_pp_job *job; + u32 perf_counter_flag; + + job = _mali_osk_calloc(1, sizeof(struct mali_pp_job)); + if (NULL != job) + { + if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s))) + { + goto fail; + } + + if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS) + { + MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); + goto fail; + } + + if (!mali_pp_job_use_no_notification(job)) + { + job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s)); + if (NULL == job->finished_notification) goto fail; + } + + perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); + + /* case when no counters came from user space + * so pass the debugfs / DS-5 provided global ones to the job object */ + if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) || + (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) + { + mali_pp_job_set_perf_counter_src0(job, mali_pp_job_get_pp_counter_src0()); + mali_pp_job_set_perf_counter_src1(job, mali_pp_job_get_pp_counter_src1()); + } + + _mali_osk_list_init(&job->list); + job->session = session; + _mali_osk_list_init(&job->session_list); + job->id = id; + + job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1; + job->pid = _mali_osk_get_pid(); + job->tid = _mali_osk_get_tid(); + + job->num_memory_cookies = job->uargs.num_memory_cookies; + if (job->num_memory_cookies > 0) + { + u32 size; + + if (job->uargs.num_memory_cookies > session->descriptor_mapping->current_nr_mappings) + { + MALI_PRINT_ERROR(("Mali PP job: Too many memory cookies specified in job object\n")); + goto fail; + } + + size = sizeof(*job->uargs.memory_cookies) * job->num_memory_cookies; + + job->memory_cookies = _mali_osk_malloc(size); + if (NULL == job->memory_cookies) + { + MALI_PRINT_ERROR(("Mali PP job: Failed to allocate %d bytes of memory cookies!\n", size)); + goto fail; + } + + if (0 != _mali_osk_copy_from_user(job->memory_cookies, job->uargs.memory_cookies, size)) + { + MALI_PRINT_ERROR(("Mali PP job: Failed to copy %d bytes of memory cookies from user!\n", size)); + goto fail; + } + +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + job->num_dma_bufs = job->num_memory_cookies; + job->dma_bufs = _mali_osk_calloc(job->num_dma_bufs, sizeof(struct mali_dma_buf_attachment *)); + if (NULL == job->dma_bufs) + { + MALI_PRINT_ERROR(("Mali PP job: Failed to allocate dma_bufs array!\n")); + goto fail; + } +#endif + } + else + { + job->memory_cookies = NULL; + } + + return job; + } + +fail: + if (NULL != job) + { + mali_pp_job_delete(job); + } + + return NULL; +} + +void mali_pp_job_delete(struct mali_pp_job *job) +{ +#ifdef CONFIG_SYNC + /* It is safe to delete the work without flushing. */ + if (NULL != job->sync_work) _mali_osk_wq_delete_work_nonflush(job->sync_work); + if (NULL != job->pre_fence) sync_fence_put(job->pre_fence); + if (NULL != job->sync_point) sync_fence_put(job->sync_point->fence); +#endif + if (NULL != job->finished_notification) + { + _mali_osk_notification_delete(job->finished_notification); + } + + _mali_osk_free(job->memory_cookies); + +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + /* Unmap buffers attached to job */ + if (0 < job->num_dma_bufs) + { + mali_dma_buf_unmap_job(job); + } + + _mali_osk_free(job->dma_bufs); +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + _mali_osk_free(job); +} + +u32 mali_pp_job_get_pp_counter_src0(void) +{ + return pp_counter_src0; +} + +mali_bool mali_pp_job_set_pp_counter_src0(u32 counter) +{ + pp_counter_src0 = counter; + + return MALI_TRUE; +} + +u32 mali_pp_job_get_pp_counter_src1(void) +{ + return pp_counter_src1; +} + +mali_bool mali_pp_job_set_pp_counter_src1(u32 counter) +{ + pp_counter_src1 = counter; + + return MALI_TRUE; +} diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h index 4399c1d..2aed8cc 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp_job.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_job.h @@ -17,50 +17,57 @@ #include "mali_session.h" #include "mali_kernel_common.h" #include "regs/mali_200_regs.h" +#include "mali_kernel_core.h" +#ifdef CONFIG_SYNC +#include <linux/sync.h> +#endif +#include "mali_dlbu.h" +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +#include "linux/mali_dma_buf.h" +#endif /** - * The structure represends a PP job, including all sub-jobs - * (This struct unfortunatly needs to be public because of how the _mali_osk_list_* + * The structure represents a PP job, including all sub-jobs + * (This struct unfortunately needs to be public because of how the _mali_osk_list_* * mechanism works) */ struct mali_pp_job { _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ struct mali_session_data *session; /**< Session which submitted this job */ - u32 id; /**< identifier for this job in kernel space (sequencial numbering) */ - u32 user_id; /**< identifier for the job in user space */ - u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< core specific registers associated with this job, see ARM DDI0415A */ - u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_FRAME registers for sub job 1-7 */ - u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_STACK registers for sub job 1-7 */ - u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 0 registers */ - u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 1 registers */ - u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 2 registers */ - u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ - u32 perf_counter_src0; /**< Source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ - u32 perf_counter_src1; /**< Source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ + _mali_osk_list_t session_list; /**< Used to link jobs together in the session job list */ + _mali_uk_pp_start_job_s uargs; /**< Arguments from user space */ + u32 id; /**< Identifier for this job in kernel space (sequential numbering) */ u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 0 (to be returned to user space), one for each sub job */ - u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ - u32 sub_job_count; /**< Total number of sub-jobs in this superjob */ + u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ + u32 sub_jobs_num; /**< Number of subjobs; set to 1 for Mali-450 if DLBU is used, otherwise equals number of PP cores */ u32 sub_jobs_started; /**< Total number of sub-jobs started (always started in ascending order) */ u32 sub_jobs_completed; /**< Number of completed sub-jobs in this superjob */ u32 sub_job_errors; /**< Bitfield with errors (errors for each single sub-job is or'ed together) */ u32 pid; /**< Process ID of submitting process */ u32 tid; /**< Thread ID of submitting thread */ - u32 frame_builder_id; /**< id of the originating frame builder */ - u32 flush_id; /**< flush id within the originating frame builder */ - mali_bool barrier; /**< [in] MALI_TRUE means wait for all my previous jobs to complete before scheduling this one */ - mali_bool active_barrier; /**< [in] Changes from MALI_TRUE to MALI_FALSE when barrier has been resolved */ - mali_bool no_notification; /**< [in] MALI_TRUE means do not notify user space when this job has completed */ + _mali_osk_notification_t *finished_notification; /**< Notification sent back to userspace on job complete */ + u32 num_memory_cookies; /**< Number of memory cookies attached to job */ + u32 *memory_cookies; /**< Memory cookies attached to job */ +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + struct mali_dma_buf_attachment **dma_bufs; /**< Array of DMA-bufs used by job */ + u32 num_dma_bufs; /**< Number of DMA-bufs used by job */ +#endif +#ifdef CONFIG_SYNC + mali_sync_pt *sync_point; /**< Sync point to signal on completion */ + struct sync_fence_waiter sync_waiter; /**< Sync waiter for async wait */ + _mali_osk_wq_work_t *sync_work; /**< Work to schedule in callback */ + struct sync_fence *pre_fence; /**< Sync fence this job must wait for */ +#endif }; -struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id); +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id); void mali_pp_job_delete(struct mali_pp_job *job); -_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job); - -/****************************************************** - * simple utility functions for dealing with pp jobs: - *****************************************************/ +u32 mali_pp_job_get_pp_counter_src0(void); +mali_bool mali_pp_job_set_pp_counter_src0(u32 counter); +u32 mali_pp_job_get_pp_counter_src1(void); +mali_bool mali_pp_job_set_pp_counter_src1(u32 counter); MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) { @@ -69,33 +76,57 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job) { - return job->user_id; + return job->uargs.user_job_ptr; } MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job) { - return job->frame_builder_id; + return job->uargs.frame_builder_id; } MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job) { - return job->flush_id; + return job->uargs.flush_id; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_pid(struct mali_pp_job *job) +{ + return job->pid; +} + +MALI_STATIC_INLINE u32 mali_pp_job_get_tid(struct mali_pp_job *job) +{ + return job->tid; } MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job) { - return job->frame_registers; + return job->uargs.frame_registers; +} + +MALI_STATIC_INLINE u32* mali_pp_job_get_dlbu_registers(struct mali_pp_job *job) +{ + return job->uargs.dlbu_registers; +} + +MALI_STATIC_INLINE mali_bool mali_pp_job_is_virtual(struct mali_pp_job *job) +{ + return 0 == job->uargs.num_cores; } MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job) { - if (sub_job == 0) + if (mali_pp_job_is_virtual(job)) + { + return MALI_DLBU_VIRT_ADDR; + } + else if (0 == sub_job) { - return job->frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; + return job->uargs.frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) { - return job->frame_registers_addr_frame[sub_job - 1]; + return job->uargs.frame_registers_addr_frame[sub_job - 1]; } return 0; @@ -103,13 +134,13 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 s MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job) { - if (sub_job == 0) + if (0 == sub_job) { - return job->frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; + return job->uargs.frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) { - return job->frame_registers_addr_stack[sub_job - 1]; + return job->uargs.frame_registers_addr_stack[sub_job - 1]; } return 0; @@ -117,32 +148,32 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 s MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job) { - return job->wb0_registers; + return job->uargs.wb0_registers; } MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job) { - return job->wb1_registers; + return job->uargs.wb1_registers; } MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job) { - return job->wb2_registers; + return job->uargs.wb2_registers; } MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job) { - job->wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; + job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; } MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job) { - job->wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; + job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; } MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job) { - job->wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; + job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; } MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job) @@ -152,37 +183,22 @@ MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job) { - return (job->sub_jobs_started < job->sub_job_count) ? MALI_TRUE : MALI_FALSE; + return (job->sub_jobs_started < job->sub_jobs_num) ? MALI_TRUE : MALI_FALSE; } /* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job. - Makes sure that no new subjobs is started. */ -MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(struct mali_pp_job *job) + Makes sure that no new subjobs are started. */ +MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_failed(struct mali_pp_job *job) { - /* All can not be started, since then it would not be in the job queue */ - MALI_DEBUG_ASSERT( job->sub_jobs_started != job->sub_job_count ); - - /* If at least one job is started */ - if ( (job->sub_jobs_started > 0) ) - { - /* If at least one job is currently being rendered, and thus assigned to a group and core */ - if (job->sub_jobs_started > job->sub_jobs_completed ) - { - u32 jobs_remaining = job->sub_job_count - job->sub_jobs_started; - job->sub_jobs_started += jobs_remaining; - job->sub_jobs_completed += jobs_remaining; - job->sub_job_errors += jobs_remaining; - /* Returning TRUE indicating that we can not delete this job which is being redered */ - return MALI_TRUE; - } - } - /* The job is not being rendered to at the moment and can then safely be deleted */ - return MALI_FALSE; + u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started; + job->sub_jobs_started += jobs_remaining; + job->sub_jobs_completed += jobs_remaining; + job->sub_job_errors += jobs_remaining; } MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job) { - return (job->sub_job_count == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; + return (job->sub_jobs_num == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job) @@ -192,7 +208,7 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_jo MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job) { - return job->sub_job_count; + return job->sub_jobs_num; } MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job) @@ -222,32 +238,32 @@ MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job) MALI_STATIC_INLINE mali_bool mali_pp_job_has_active_barrier(struct mali_pp_job *job) { - return job->active_barrier; + return job->uargs.flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE void mali_pp_job_barrier_enforced(struct mali_pp_job *job) { - job->active_barrier = MALI_FALSE; + job->uargs.flags &= ~_MALI_PP_JOB_FLAG_BARRIER; } MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job) { - return job->no_notification; + return job->uargs.flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job) { - return job->perf_counter_flag; + return job->uargs.perf_counter_flag; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job) { - return job->perf_counter_src0; + return job->uargs.perf_counter_src0; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job) { - return job->perf_counter_src1; + return job->uargs.perf_counter_src1; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job) @@ -260,6 +276,16 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *j return job->perf_counter_value1[sub_job]; } +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_src0(struct mali_pp_job *job, u32 src) +{ + job->uargs.perf_counter_src0 = src; +} + +MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_src1(struct mali_pp_job *job, u32 src) +{ + job->uargs.perf_counter_src1 = src; +} + MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value) { job->perf_counter_value0[sub_job] = value; @@ -270,4 +296,13 @@ MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job * job->perf_counter_value1[sub_job] = value; } +MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) +{ + if (mali_pp_job_is_virtual(job) && job->sub_jobs_num != 1) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} + #endif /* __MALI_PP_JOB_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c new file mode 100644 index 0000000..3f10bdc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.c @@ -0,0 +1,1890 @@ +/* + * Copyright (C) 2012 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 "mali_pp_scheduler.h" +#include "mali_kernel_common.h" +#include "mali_kernel_core.h" +#include "mali_osk.h" +#include "mali_osk_list.h" +#include "mali_scheduler.h" +#include "mali_pp.h" +#include "mali_pp_job.h" +#include "mali_group.h" +#include "mali_pm.h" +#include "mali_kernel_utilization.h" +#include "mali_session.h" +#include "mali_pm_domain.h" +#include "linux/mali/mali_utgard.h" + +#if defined(CONFIG_DMA_SHARED_BUFFER) +#include "mali_dma_buf.h" +#endif +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) +#include <linux/sched.h> +#include <trace/events/gpu.h> +#endif + + +/* With certain configurations, job deletion involves functions which cannot be called from atomic context. + * This #if checks for those cases and enables job deletion to be deferred and run in a different context. */ +#if defined(CONFIG_SYNC) || !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +#define MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE 1 +#endif + +/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ +#define MALI_MAX_NUMBER_OF_PP_GROUPS 9 + +static mali_bool mali_pp_scheduler_is_suspended(void); +static void mali_pp_scheduler_do_schedule(void *arg); +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) +static void mali_pp_scheduler_do_job_delete(void *arg); +#endif +static void mali_pp_scheduler_job_queued(void); +static void mali_pp_scheduler_job_completed(void); + +static u32 pp_version = 0; + +/* Physical job queue */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(job_queue); /* List of physical jobs with some unscheduled work */ +static u32 job_queue_depth = 0; + +/* Physical groups */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_working); /* List of physical groups with working jobs on the pp core */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_idle); /* List of physical groups with idle jobs on the pp core */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_disabled); /* List of disabled physical groups */ + +/* Virtual job queue (Mali-450 only) */ +static _MALI_OSK_LIST_HEAD_STATIC_INIT(virtual_job_queue); /* List of unstarted jobs for the virtual group */ +static u32 virtual_job_queue_depth = 0; + +/* Virtual group (Mali-450 only) */ +static struct mali_group *virtual_group = NULL; /* Virtual group (if any) */ +static enum +{ + VIRTUAL_GROUP_IDLE, + VIRTUAL_GROUP_WORKING, + VIRTUAL_GROUP_DISABLED, +} +virtual_group_state = VIRTUAL_GROUP_IDLE; /* Flag which indicates whether the virtual group is working or idle */ + +/* Number of physical cores */ +static u32 num_cores = 0; +static u32 enabled_cores = 0; + +/* Variables to allow safe pausing of the scheduler */ +static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL; +static u32 pause_count = 0; + +static _mali_osk_lock_t *pp_scheduler_lock = NULL; +/* Contains tid of thread that locked the scheduler or 0, if not locked */ +MALI_DEBUG_CODE(static u32 pp_scheduler_lock_owner = 0); + +static _mali_osk_wq_work_t *pp_scheduler_wq_schedule = NULL; + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) +static _mali_osk_wq_work_t *pp_scheduler_wq_job_delete = NULL; +static _mali_osk_lock_t *pp_scheduler_job_delete_lock = NULL; +static _MALI_OSK_LIST_HEAD_STATIC_INIT(pp_scheduler_job_deletion_queue); +#endif + +MALI_STATIC_INLINE mali_bool mali_pp_scheduler_has_virtual_group(void) +{ + return NULL != virtual_group; +} + +_mali_osk_errcode_t mali_pp_scheduler_initialize(void) +{ + _mali_osk_lock_flags_t lock_flags; + +#if defined(MALI_UPPER_HALF_SCHEDULING) + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#else + lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE; +#endif + + pp_scheduler_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + if (NULL == pp_scheduler_lock) + { + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); + if (NULL == pp_scheduler_working_wait_queue) + { + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_wq_schedule = _mali_osk_wq_create_work(mali_pp_scheduler_do_schedule, NULL); + if (NULL == pp_scheduler_wq_schedule) + { + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + pp_scheduler_wq_job_delete = _mali_osk_wq_create_work(mali_pp_scheduler_do_job_delete, NULL); + if (NULL == pp_scheduler_wq_job_delete) + { + _mali_osk_wq_delete_work(pp_scheduler_wq_schedule); + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } + + pp_scheduler_job_delete_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED); + if (NULL == pp_scheduler_job_delete_lock) + { + _mali_osk_wq_delete_work(pp_scheduler_wq_job_delete); + _mali_osk_wq_delete_work(pp_scheduler_wq_schedule); + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); + return _MALI_OSK_ERR_NOMEM; + } +#endif + + return _MALI_OSK_ERR_OK; +} + +void mali_pp_scheduler_terminate(void) +{ +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + _mali_osk_lock_term(pp_scheduler_job_delete_lock); + _mali_osk_wq_delete_work(pp_scheduler_wq_job_delete); +#endif + + _mali_osk_wq_delete_work(pp_scheduler_wq_schedule); + _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); + _mali_osk_lock_term(pp_scheduler_lock); +} + +void mali_pp_scheduler_populate(void) +{ + struct mali_group *group; + struct mali_pp_core *pp_core; + u32 num_groups; + u32 i; + + num_groups = mali_group_get_glob_num_groups(); + + /* Do we have a virtual group? */ + for (i = 0; i < num_groups; i++) + { + group = mali_group_get_glob_group(i); + + if (mali_group_is_virtual(group)) + { + MALI_DEBUG_PRINT(3, ("Found virtual group %p\n", group)); + + virtual_group = group; + break; + } + } + + /* Find all the available PP cores */ + for (i = 0; i < num_groups; i++) + { + group = mali_group_get_glob_group(i); + pp_core = mali_group_get_pp_core(group); + + if (NULL != pp_core && !mali_group_is_virtual(group)) + { + if (0 == pp_version) + { + /* Retrieve PP version from the first available PP core */ + pp_version = mali_pp_core_get_version(pp_core); + } + + if (mali_pp_scheduler_has_virtual_group()) + { + /* Add all physical PP cores to the virtual group */ + mali_group_lock(virtual_group); + group->state = MALI_GROUP_STATE_JOINING_VIRTUAL; + mali_group_add_group(virtual_group, group, MALI_TRUE); + mali_group_unlock(virtual_group); + } + else + { + _mali_osk_list_add(&group->pp_scheduler_list, &group_list_idle); + } + + num_cores++; + } + } + enabled_cores = num_cores; +} + +void mali_pp_scheduler_depopulate(void) +{ + struct mali_group *group, *temp; + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state); + + /* Delete all groups owned by scheduler */ + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_delete(virtual_group); + } + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) + { + mali_group_delete(group); + } + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_disabled, struct mali_group, pp_scheduler_list) + { + mali_group_delete(group); + } +} + +MALI_STATIC_INLINE void mali_pp_scheduler_lock(void) +{ + if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) + { + /* Non-interruptable lock failed: this should never happen. */ + MALI_DEBUG_ASSERT(0); + } + MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken\n")); + MALI_DEBUG_ASSERT(0 == pp_scheduler_lock_owner); + MALI_DEBUG_CODE(pp_scheduler_lock_owner = _mali_osk_get_tid()); +} + +MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void) +{ + MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock\n")); + MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); + MALI_DEBUG_CODE(pp_scheduler_lock_owner = 0); + _mali_osk_lock_signal(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); +} + +MALI_STATIC_INLINE void mali_pp_scheduler_disable_empty_virtual(void) +{ + MALI_ASSERT_GROUP_LOCKED(virtual_group); + + if (mali_group_virtual_disable_if_empty(virtual_group)) + { + MALI_DEBUG_PRINT(4, ("Disabling empty virtual group\n")); + + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_IDLE == virtual_group_state); + + virtual_group_state = VIRTUAL_GROUP_DISABLED; + } +} + +MALI_STATIC_INLINE void mali_pp_scheduler_enable_empty_virtual(void) +{ + MALI_ASSERT_GROUP_LOCKED(virtual_group); + + if (mali_group_virtual_enable_if_empty(virtual_group)) + { + MALI_DEBUG_PRINT(4, ("Re-enabling empty virtual group\n")); + + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_DISABLED == virtual_group_state); + + virtual_group_state = VIRTUAL_GROUP_IDLE; + } +} + +#ifdef DEBUG +MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void) +{ + MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); +} +#define MALI_ASSERT_PP_SCHEDULER_LOCKED() mali_pp_scheduler_assert_locked() +#else +#define MALI_ASSERT_PP_SCHEDULER_LOCKED() +#endif + +/** + * Returns a physical job if a physical job is ready to run (no barrier present) + */ +MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_physical_job(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + + if (!_mali_osk_list_empty(&job_queue)) + { + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT(job_queue_depth > 0); + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); + + if (!mali_pp_job_has_active_barrier(job)) + { + return job; + } + } + + return NULL; +} + +MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_physical_job(struct mali_pp_job *job) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT(job_queue_depth > 0); + + /* Remove job from queue */ + if (!mali_pp_job_has_unstarted_sub_jobs(job)) + { + /* All sub jobs have been started: remove job from queue */ + _mali_osk_list_delinit(&job->list); + } + + --job_queue_depth; +} + +/** + * Returns a virtual job if a virtual job is ready to run (no barrier present) + */ +MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_virtual_job(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT_POINTER(virtual_group); + + if (!_mali_osk_list_empty(&virtual_job_queue)) + { + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT(virtual_job_queue_depth > 0); + job = _MALI_OSK_LIST_ENTRY(virtual_job_queue.next, struct mali_pp_job, list); + + if (!mali_pp_job_has_active_barrier(job)) + { + return job; + } + } + + return NULL; +} + +MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_virtual_job(struct mali_pp_job *job) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT(virtual_job_queue_depth > 0); + + /* Remove job from queue */ + _mali_osk_list_delinit(&job->list); + --virtual_job_queue_depth; +} + +/** + * Checks if the criteria is met for removing a physical core from virtual group + */ +MALI_STATIC_INLINE mali_bool mali_pp_scheduler_can_move_virtual_to_physical(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + MALI_DEBUG_ASSERT(mali_pp_scheduler_has_virtual_group()); + MALI_ASSERT_GROUP_LOCKED(virtual_group); + /* + * The criteria for taking out a physical group from a virtual group are the following: + * - There virtual group is idle + * - There are currently no physical groups (idle and working) + * - There are physical jobs to be scheduled (without a barrier) + */ + return (VIRTUAL_GROUP_IDLE == virtual_group_state) && + _mali_osk_list_empty(&group_list_idle) && + _mali_osk_list_empty(&group_list_working) && + (NULL != mali_pp_scheduler_get_physical_job()); +} + +MALI_STATIC_INLINE struct mali_group *mali_pp_scheduler_acquire_physical_group(void) +{ + MALI_ASSERT_PP_SCHEDULER_LOCKED(); + + if (!_mali_osk_list_empty(&group_list_idle)) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from idle list\n")); + return _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list); + } + else if (mali_pp_scheduler_has_virtual_group()) + { + MALI_ASSERT_GROUP_LOCKED(virtual_group); + if (mali_pp_scheduler_can_move_virtual_to_physical()) + { + struct mali_group *group; + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from virtual group\n")); + group = mali_group_acquire_group(virtual_group); + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_pp_scheduler_disable_empty_virtual(); + } + + return group; + } + } + + return NULL; +} + +static void mali_pp_scheduler_schedule(void) +{ + struct mali_group* physical_groups_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1]; + struct mali_pp_job* physical_jobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1]; + u32 physical_subjobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1]; + int num_physical_jobs_to_start = 0; + int i; + + if (mali_pp_scheduler_has_virtual_group()) + { + /* Need to lock the virtual group because we might need to grab a physical group from it */ + mali_group_lock(virtual_group); + } + + mali_pp_scheduler_lock(); + if (pause_count > 0) + { + /* Scheduler is suspended, don't schedule any jobs */ + mali_pp_scheduler_unlock(); + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_unlock(virtual_group); + } + return; + } + + /* Find physical job(s) to schedule first */ + while (1) + { + struct mali_group *group; + struct mali_pp_job *job; + u32 subjob; + + job = mali_pp_scheduler_get_physical_job(); + if (NULL == job) + { + break; /* No job, early out */ + } + + MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual(job)); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + MALI_DEBUG_ASSERT(1 <= mali_pp_job_get_sub_job_count(job)); + + /* Acquire a physical group, either from the idle list or from the virtual group. + * In case the group was acquired from the virtual group, it's state will be + * LEAVING_VIRTUAL and must be set to IDLE before it can be used. */ + group = mali_pp_scheduler_acquire_physical_group(); + if (NULL == group) + { + /* Could not get a group to run the job on, early out */ + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: No more physical groups available.\n")); + break; + } + + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquired physical group %p\n", group)); + + /* Mark subjob as started */ + subjob = mali_pp_job_get_first_unstarted_sub_job(job); + mali_pp_job_mark_sub_job_started(job, subjob); + + /* Remove job from queue (if we now got the last subjob) */ + mali_pp_scheduler_dequeue_physical_job(job); + + /* Move group to working list */ + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_working); + + /* Keep track of this group, so that we actually can start the job once we are done with the scheduler lock we are now holding */ + physical_groups_to_start[num_physical_jobs_to_start] = group; + physical_jobs_to_start[num_physical_jobs_to_start] = job; + physical_subjobs_to_start[num_physical_jobs_to_start] = subjob; + ++num_physical_jobs_to_start; + + MALI_DEBUG_ASSERT(num_physical_jobs_to_start < MALI_MAX_NUMBER_OF_PP_GROUPS); + } + + /* See if we have a virtual job to schedule */ + if (mali_pp_scheduler_has_virtual_group()) + { + if (VIRTUAL_GROUP_IDLE == virtual_group_state) + { + struct mali_pp_job *job = mali_pp_scheduler_get_virtual_job(); + if (NULL != job) + { + MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job)); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job)); + + /* Mark the one and only subjob as started */ + mali_pp_job_mark_sub_job_started(job, 0); + + /* Remove job from queue */ + mali_pp_scheduler_dequeue_virtual_job(job); + + /* Virtual group is now working */ + virtual_group_state = VIRTUAL_GROUP_WORKING; + + /* + * We no longer need the scheduler lock, + * but we still need the virtual lock in order to start the virtual job + */ + mali_pp_scheduler_unlock(); + + /* Start job */ + mali_group_start_pp_job(virtual_group, job, 0); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from schedule)\n", + mali_pp_job_get_id(job), job, 1, + mali_pp_job_get_sub_job_count(job))); + + /* And now we are all done with the virtual_group lock as well */ + mali_group_unlock(virtual_group); + } + else + { + /* No virtual job, release the two locks we are holding */ + mali_pp_scheduler_unlock(); + mali_group_unlock(virtual_group); + } + } + else + { + /* Virtual core busy, release the two locks we are holding */ + mali_pp_scheduler_unlock(); + mali_group_unlock(virtual_group); + } + + } + else + { + /* There is no virtual group, release the only lock we are holding */ + mali_pp_scheduler_unlock(); + } + + /* + * Now we have released the scheduler lock, and we are ready to kick of the actual starting of the + * physical jobs. + * The reason we want to wait until we have released the scheduler lock is that job start actually + * may take quite a bit of time (quite many registers needs to be written). This will allow new jobs + * from user space to come in, and post processing of other PP jobs to happen at the same time as we + * start jobs. + */ + for (i = 0; i < num_physical_jobs_to_start; i++) + { + struct mali_group *group = physical_groups_to_start[i]; + struct mali_pp_job *job = physical_jobs_to_start[i]; + u32 sub_job = physical_subjobs_to_start[i]; + + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT_POINTER(job); + + mali_group_lock(group); + + /* In case this group was acquired from a virtual core, update it's state to IDLE */ + group->state = MALI_GROUP_STATE_IDLE; + + mali_group_start_pp_job(group, job, sub_job); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from schedule)\n", + mali_pp_job_get_id(job), job, sub_job + 1, + mali_pp_job_get_sub_job_count(job))); + + mali_group_unlock(group); + + /* remove the return value from mali_group_start_xx_job, since we can't fail on Mali-300++ */ + } +} + +static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job, mali_bool deferred) +{ + if (MALI_FALSE == mali_pp_job_use_no_notification(job)) + { + u32 i; + u32 num_counters_to_copy; + mali_bool success = mali_pp_job_was_success(job); + + _mali_uk_pp_job_finished_s *jobres = job->finished_notification->result_buffer; + _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ + jobres->user_job_ptr = mali_pp_job_get_user_id(job); + if (MALI_TRUE == success) + { + jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; + } + else + { + jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; + } + + if (mali_pp_job_is_virtual(job)) + { + num_counters_to_copy = num_cores; /* Number of physical cores available */ + } + else + { + num_counters_to_copy = mali_pp_job_get_sub_job_count(job); + } + + for (i = 0; i < num_counters_to_copy; i++) + { + jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i); + jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i); + } + + mali_session_send_notification(mali_pp_job_get_session(job), job->finished_notification); + job->finished_notification = NULL; + } + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + if (MALI_TRUE == deferred) + { + /* The deletion of the job object (releasing sync refs etc) must be done in a different context */ + _mali_osk_lock_wait(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list)); /* This job object should not be on any list */ + _mali_osk_list_addtail(&job->list, &pp_scheduler_job_deletion_queue); + + _mali_osk_lock_signal(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + _mali_osk_wq_schedule_work(pp_scheduler_wq_job_delete); + } + else + { + mali_pp_job_delete(job); + } +#else + MALI_DEBUG_ASSERT(MALI_FALSE == deferred); /* no use cases need this in this configuration */ + mali_pp_job_delete(job); +#endif +} + +static void mali_pp_scheduler_do_schedule(void *arg) +{ + MALI_IGNORE(arg); + + mali_pp_scheduler_schedule(); +} + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) +static void mali_pp_scheduler_do_job_delete(void *arg) +{ + _MALI_OSK_LIST_HEAD_STATIC_INIT(list); + struct mali_pp_job *job; + struct mali_pp_job *tmp; + + MALI_IGNORE(arg); + + _mali_osk_lock_wait(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + /* + * Quickly "unhook" the jobs pending to be deleted, so we can release the lock before + * we start deleting the job objects (without any locks held + */ + _mali_osk_list_move_list(&pp_scheduler_job_deletion_queue, &list); + + _mali_osk_lock_signal(pp_scheduler_job_delete_lock, _MALI_OSK_LOCKMODE_RW); + + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &list, struct mali_pp_job, list) + { + mali_pp_job_delete(job); /* delete the job object itself */ + } +} +#endif + +void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) +{ + mali_bool job_is_done; + mali_bool barrier_enforced = MALI_FALSE; + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) part %u/%u completed (%s)\n", + mali_pp_job_is_virtual(job) ? "Virtual" : "Physical", + mali_pp_job_get_id(job), + job, sub_job + 1, + mali_pp_job_get_sub_job_count(job), + success ? "success" : "failure")); + MALI_ASSERT_GROUP_LOCKED(group); + mali_pp_scheduler_lock(); + + mali_pp_job_mark_sub_job_completed(job, success); + + MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job) == mali_group_is_virtual(group)); + + job_is_done = mali_pp_job_is_complete(job); + + if (job_is_done) + { + struct mali_session_data *session = mali_pp_job_get_session(job); + struct mali_pp_job *job_head; + + /* Remove job from session list */ + _mali_osk_list_del(&job->session_list); + + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for %s job %u (0x%08X)\n", + mali_pp_job_is_virtual(job) ? "virtual" : "physical", + mali_pp_job_get_id(job), job)); +#if defined(CONFIG_SYNC) + if (job->sync_point) + { + int error; + if (success) error = 0; + else error = -EFAULT; + MALI_DEBUG_PRINT(4, ("Sync: Signal %spoint for job %d\n", + success ? "" : "failed ", + mali_pp_job_get_id(job))); + mali_sync_signal_pt(job->sync_point, error); + } +#endif + + /* Send notification back to user space */ +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + mali_pp_scheduler_return_job_to_user(job, MALI_TRUE); +#else + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); +#endif + + mali_pp_scheduler_job_completed(); + + /* Resolve any barriers */ + if (!_mali_osk_list_empty(&session->job_list)) + { + job_head = _MALI_OSK_LIST_ENTRY(session->job_list.next, struct mali_pp_job, session_list); + if (mali_pp_job_has_active_barrier(job_head)) + { + barrier_enforced = MALI_TRUE; + mali_pp_job_barrier_enforced(job_head); + } + } + } + + /* If paused, then this was the last job, so wake up sleeping workers */ + if (pause_count > 0) + { + /* Wake up sleeping workers. Their wake-up condition is that + * num_slots == num_slots_idle, so unless we are done working, no + * threads will actually be woken up. + */ + if (mali_group_is_virtual(group)) + { + virtual_group_state = VIRTUAL_GROUP_IDLE; + } + else + { + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle); + } +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), 0, 0, 0); +#endif + _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); + mali_pp_scheduler_unlock(); + return; + } + + if (barrier_enforced) + { + /* A barrier was resolved, so schedule previously blocked jobs */ + _mali_osk_wq_schedule_work(pp_scheduler_wq_schedule); + } + + /* Recycle variables */ + job = NULL; + sub_job = 0; + + if (mali_group_is_virtual(group)) + { + /* Virtual group */ + + /* Now that the virtual group is idle, check if we should reconfigure */ + struct mali_pp_job *physical_job = NULL; + struct mali_group *physical_group = NULL; + + /* Obey the policy */ + virtual_group_state = VIRTUAL_GROUP_IDLE; + + if (mali_pp_scheduler_can_move_virtual_to_physical()) + { + /* There is a runnable physical job and we can acquire a physical group */ + physical_job = mali_pp_scheduler_get_physical_job(); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(physical_job)); + + /* Mark subjob as started */ + sub_job = mali_pp_job_get_first_unstarted_sub_job(physical_job); + mali_pp_job_mark_sub_job_started(physical_job, sub_job); + + /* Remove job from queue (if we now got the last subjob) */ + mali_pp_scheduler_dequeue_physical_job(physical_job); + + /* Acquire a physical group from the virtual group + * It's state will be LEAVING_VIRTUAL and must be set to IDLE before it can be used */ + physical_group = mali_group_acquire_group(virtual_group); + + /* Move physical group to the working list, as we will soon start a job on it */ + _mali_osk_list_move(&(physical_group->pp_scheduler_list), &group_list_working); + + mali_pp_scheduler_disable_empty_virtual(); + } + + /* Start the next virtual job */ + job = mali_pp_scheduler_get_virtual_job(); + if (NULL != job && VIRTUAL_GROUP_IDLE == virtual_group_state) + { + /* There is a runnable virtual job */ + MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job)); + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job)); + + mali_pp_job_mark_sub_job_started(job, 0); + + /* Remove job from queue */ + mali_pp_scheduler_dequeue_virtual_job(job); + + /* Virtual group is now working */ + virtual_group_state = VIRTUAL_GROUP_WORKING; + + mali_pp_scheduler_unlock(); + + /* Start job */ + mali_group_start_pp_job(group, job, 0); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from job_done)\n", + mali_pp_job_get_id(job), job, 1, + mali_pp_job_get_sub_job_count(job))); + } + else + { +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch("Mali_Virtual_PP", sched_clock(), 0, 0, 0); +#endif + mali_pp_scheduler_unlock(); + } + + /* Start a physical job (if we acquired a physical group earlier) */ + if (NULL != physical_job && NULL != physical_group) + { + mali_group_lock(physical_group); + + /* Set the group state from LEAVING_VIRTUAL to IDLE to complete the transition */ + physical_group->state = MALI_GROUP_STATE_IDLE; + + /* Start job on core */ + mali_group_start_pp_job(physical_group, physical_job, sub_job); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done)\n", + mali_pp_job_get_id(physical_job), physical_job, sub_job + 1, + mali_pp_job_get_sub_job_count(physical_job))); + + mali_group_unlock(physical_group); + } + } + else + { + /* Physical group */ + job = mali_pp_scheduler_get_physical_job(); + if (NULL != job) + { + /* There is a runnable physical job */ + MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); + + /* Mark subjob as started */ + sub_job = mali_pp_job_get_first_unstarted_sub_job(job); + mali_pp_job_mark_sub_job_started(job, sub_job); + + /* Remove job from queue (if we now got the last subjob) */ + mali_pp_scheduler_dequeue_physical_job(job); + + mali_pp_scheduler_unlock(); + + /* Group is already on the working list, so start the job */ + mali_group_start_pp_job(group, job, sub_job); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done)\n", + mali_pp_job_get_id(job), job, sub_job + 1, + mali_pp_job_get_sub_job_count(job))); + } + else if (mali_pp_scheduler_has_virtual_group()) + { + /* Rejoin virtual group */ + /* In the future, a policy check might be useful here */ + + /* We're no longer needed on the scheduler list */ + _mali_osk_list_delinit(&(group->pp_scheduler_list)); + + /* Make sure no interrupts are handled for this group during + * the transition from physical to virtual */ + group->state = MALI_GROUP_STATE_JOINING_VIRTUAL; + + mali_pp_scheduler_unlock(); + mali_group_unlock(group); + + mali_group_lock(virtual_group); + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_pp_scheduler_enable_empty_virtual(); + } + + /* We need to recheck the group state since it is possible that someone has + * modified the group before we locked the virtual group. */ + if (MALI_GROUP_STATE_JOINING_VIRTUAL == group->state) + { + mali_group_add_group(virtual_group, group, MALI_TRUE); + } + + mali_group_unlock(virtual_group); + + if (mali_pp_scheduler_has_virtual_group() && VIRTUAL_GROUP_IDLE == virtual_group_state) + { + _mali_osk_wq_schedule_work(pp_scheduler_wq_schedule); + } + + /* We need to return from this function with the group lock held */ + mali_group_lock(group); + } + else + { + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle); +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), 0, 0, 0); +#endif + mali_pp_scheduler_unlock(); + } + } +} + +void mali_pp_scheduler_suspend(void) +{ + mali_pp_scheduler_lock(); + pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ + mali_pp_scheduler_unlock(); + + /* Go to sleep. When woken up again (in mali_pp_scheduler_job_done), the + * mali_pp_scheduler_suspended() function will be called. This will return true + * iff state is idle and pause_count > 0, so if the core is active this + * will not do anything. + */ + _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended); +} + +void mali_pp_scheduler_resume(void) +{ + mali_pp_scheduler_lock(); + pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ + mali_pp_scheduler_unlock(); + if (0 == pause_count) + { + mali_pp_scheduler_schedule(); + } +} + +MALI_STATIC_INLINE void mali_pp_scheduler_queue_job(struct mali_pp_job *job, struct mali_session_data *session) +{ + MALI_DEBUG_ASSERT_POINTER(job); + +#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS) + trace_gpu_job_enqueue(mali_pp_job_get_tid(job), mali_pp_job_get_id(job), "PP"); +#endif + +#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + /* Map buffers attached to job */ + if (0 != job->num_memory_cookies) + { + mali_dma_buf_map_job(job); + } +#endif /* CONFIG_DMA_SHARED_BUFFER */ + + mali_pp_scheduler_job_queued(); + + mali_pp_scheduler_lock(); + + if (mali_pp_job_is_virtual(job)) + { + /* Virtual job */ + virtual_job_queue_depth += 1; + _mali_osk_list_addtail(&job->list, &virtual_job_queue); + } + else + { + job_queue_depth += mali_pp_job_get_sub_job_count(job); + _mali_osk_list_addtail(&job->list, &job_queue); + } + + if (mali_pp_job_has_active_barrier(job) && _mali_osk_list_empty(&session->job_list)) + { + /* No running jobs on this session, so barrier condition already met */ + mali_pp_job_barrier_enforced(job); + } + + /* Add job to session list */ + _mali_osk_list_addtail(&job->session_list, &session->job_list); + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) with %u parts queued\n", + mali_pp_job_is_virtual(job) ? "Virtual" : "Physical", + mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); + + mali_pp_scheduler_unlock(); +} + +#if defined(CONFIG_SYNC) +static void sync_callback(struct sync_fence *fence, struct sync_fence_waiter *waiter) +{ + struct mali_pp_job *job = _MALI_OSK_CONTAINER_OF(waiter, struct mali_pp_job, sync_waiter); + + /* Schedule sync_callback_work */ + _mali_osk_wq_schedule_work(job->sync_work); +} + +static void sync_callback_work(void *arg) +{ + struct mali_pp_job *job = (struct mali_pp_job *)arg; + struct mali_session_data *session; + int err; + + MALI_DEBUG_ASSERT_POINTER(job); + + session = job->session; + + /* Remove job from session pending job list */ + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_delinit(&job->list); + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + + err = sync_fence_wait(job->pre_fence, 0); + if (likely(0 == err)) + { + MALI_DEBUG_PRINT(3, ("Mali sync: Job %d ready to run\n", mali_pp_job_get_id(job))); + + mali_pp_scheduler_queue_job(job, session); + + mali_pp_scheduler_schedule(); + } + else + { + /* Fence signaled error */ + MALI_DEBUG_PRINT(3, ("Mali sync: Job %d abort due to sync error\n", mali_pp_job_get_id(job))); + + if (job->sync_point) mali_sync_signal_pt(job->sync_point, err); + + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + } +} +#endif + +_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs, int *fence) +{ + struct mali_session_data *session; + struct mali_pp_job *job; + + MALI_DEBUG_ASSERT_POINTER(uargs); + MALI_DEBUG_ASSERT_POINTER(ctx); + + session = (struct mali_session_data*)ctx; + + job = mali_pp_job_create(session, uargs, mali_scheduler_get_new_id()); + if (NULL == job) + { + MALI_PRINT_ERROR(("Failed to create job!\n")); + return _MALI_OSK_ERR_NOMEM; + } + + if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) + { + /* Not a valid job, return to user immediately */ + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + +#if PROFILING_SKIP_PP_JOBS || PROFILING_SKIP_PP_AND_GP_JOBS +#warning PP jobs will not be executed + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); + return _MALI_OSK_ERR_OK; +#endif + +#if defined(CONFIG_SYNC) + if (_MALI_PP_JOB_FLAG_FENCE & job->uargs.flags) + { + int post_fence = -1; + + job->sync_point = mali_stream_create_point(job->uargs.stream); + + if (unlikely(NULL == job->sync_point)) + { + /* Fence creation failed. */ + MALI_DEBUG_PRINT(2, ("Failed to create sync point for job %d\n", mali_pp_job_get_id(job))); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + post_fence = mali_stream_create_fence(job->sync_point); + + if (unlikely(0 > post_fence)) + { + /* Fence creation failed. */ + /* mali_stream_create_fence already freed the sync_point */ + MALI_DEBUG_PRINT(2, ("Failed to create fence for job %d\n", mali_pp_job_get_id(job))); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + /* Grab a reference to the fence. It must be around when the + * job is completed, so the point can be signalled. */ + sync_fence_fdget(post_fence); + + *fence = post_fence; + + MALI_DEBUG_PRINT(3, ("Sync: Created fence %d for job %d\n", post_fence, mali_pp_job_get_id(job))); + } + else if (_MALI_PP_JOB_FLAG_EMPTY_FENCE & job->uargs.flags) + { + int empty_fence_fd = job->uargs.stream; + struct sync_fence *empty_fence; + struct sync_pt *pt; + int ret; + + /* Grab and keep a reference to the fence. It must be around + * when the job is completed, so the point can be signalled. */ + empty_fence = sync_fence_fdget(empty_fence_fd); + + if (unlikely(NULL == empty_fence)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to accept empty fence: %d\n", empty_fence_fd)); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; + } + + if (unlikely(list_empty(&empty_fence->pt_list_head))) + { + MALI_DEBUG_PRINT_ERROR(("Failed to accept empty fence: %d\n", empty_fence_fd)); + sync_fence_put(empty_fence); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; + } + + pt = list_first_entry(&empty_fence->pt_list_head, struct sync_pt, pt_list); + + ret = mali_sync_timed_commit(pt); + + if (unlikely(0 != ret)) + { + MALI_DEBUG_PRINT_ERROR(("Empty fence not valid: %d\n", empty_fence_fd)); + sync_fence_put(empty_fence); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; + } + + job->sync_point = pt; + + *fence = empty_fence_fd; + + MALI_DEBUG_PRINT(3, ("Sync: Job %d now backs fence %d\n", mali_pp_job_get_id(job), empty_fence_fd)); + } + + if (0 < job->uargs.fence) + { + int pre_fence_fd = job->uargs.fence; + int err; + + MALI_DEBUG_PRINT(3, ("Sync: Job %d waiting for fence %d\n", mali_pp_job_get_id(job), pre_fence_fd)); + + job->pre_fence = sync_fence_fdget(pre_fence_fd); /* Reference will be released when job is deleted. */ + if (NULL == job->pre_fence) + { + MALI_DEBUG_PRINT(2, ("Failed to import fence %d\n", pre_fence_fd)); + if (job->sync_point) mali_sync_signal_pt(job->sync_point, -EINVAL); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + job->sync_work = _mali_osk_wq_create_work(sync_callback_work, (void*)job); + if (NULL == job->sync_work) + { + if (job->sync_point) mali_sync_signal_pt(job->sync_point, -ENOMEM); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + /* Add pending job to session pending job list */ + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_addtail(&job->list, &session->pending_jobs); + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + + sync_fence_waiter_init(&job->sync_waiter, sync_callback); + err = sync_fence_wait_async(job->pre_fence, &job->sync_waiter); + + if (0 != err) + { + /* No async wait started, remove job from session pending job list */ + _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_list_delinit(&job->list); + _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW); + } + + if (1 == err) + { + /* Fence has already signalled */ + mali_pp_scheduler_queue_job(job, session); + if (!_mali_osk_list_empty(&group_list_idle) || VIRTUAL_GROUP_IDLE == virtual_group_state) + { + mali_pp_scheduler_schedule(); + } + return _MALI_OSK_ERR_OK; + } + else if (0 > err) + { + /* Sync fail */ + if (job->sync_point) mali_sync_signal_pt(job->sync_point, err); + mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ + mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */ + return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ + } + + } + else +#endif /* CONFIG_SYNC */ + { + mali_pp_scheduler_queue_job(job, session); + + if (!_mali_osk_list_empty(&group_list_idle) || VIRTUAL_GROUP_IDLE == virtual_group_state) + { + mali_pp_scheduler_schedule(); + } + } + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + args->number_of_total_cores = num_cores; + args->number_of_enabled_cores = enabled_cores; + return _MALI_OSK_ERR_OK; +} + +u32 mali_pp_scheduler_get_num_cores_total(void) +{ + return num_cores; +} + +u32 mali_pp_scheduler_get_num_cores_enabled(void) +{ + return enabled_cores; +} + +_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args) +{ + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + args->version = pp_version; + return _MALI_OSK_ERR_OK; +} + +void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) +{ + struct mali_session_data *session; + struct mali_pp_job *job; + struct mali_pp_job *tmp; + + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); + + session = (struct mali_session_data*)args->ctx; + + /* Check queue for jobs that match */ + mali_pp_scheduler_lock(); + _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) + { + if (mali_pp_job_get_session(job) == session && + mali_pp_job_get_frame_builder_id(job) == (u32)args->fb_id && + mali_pp_job_get_flush_id(job) == (u32)args->flush_id) + { + if (args->wbx & _MALI_UK_PP_JOB_WB0) + { + mali_pp_job_disable_wb0(job); + } + if (args->wbx & _MALI_UK_PP_JOB_WB1) + { + mali_pp_job_disable_wb1(job); + } + if (args->wbx & _MALI_UK_PP_JOB_WB2) + { + mali_pp_job_disable_wb2(job); + } + break; + } + } + mali_pp_scheduler_unlock(); +} + +void mali_pp_scheduler_abort_session(struct mali_session_data *session) +{ + struct mali_pp_job *job, *tmp_job; + struct mali_group *group, *tmp_group; + struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS]; + s32 i = 0; +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + _MALI_OSK_LIST_HEAD_STATIC_INIT(deferred_deletion_list); +#endif + + mali_pp_scheduler_lock(); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08x\n", session)); + + _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &session->job_list, struct mali_pp_job, session_list) + { + /* Remove job from queue (if it's not queued, list_del has no effect) */ + _mali_osk_list_delinit(&job->list); + + if (mali_pp_job_is_virtual(job)) + { + MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job)); + if (0 == mali_pp_job_get_first_unstarted_sub_job(job)) + { + --virtual_job_queue_depth; + } + } + else + { + job_queue_depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job); + } + + /* Mark all unstarted jobs as failed */ + mali_pp_job_mark_unstarted_failed(job); + + if (mali_pp_job_is_complete(job)) + { + _mali_osk_list_del(&job->session_list); + + /* It is safe to delete the job, since it won't land in job_done() */ + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborted PP job 0x%08x\n", job)); + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list)); + _mali_osk_list_addtail(&job->list, &deferred_deletion_list); +#else + mali_pp_job_delete(job); +#endif + + mali_pp_scheduler_job_completed(); + } + else + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in session\n", job)); + } + } + + _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_working, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + + _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_idle, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + + mali_pp_scheduler_unlock(); + +#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) + _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &deferred_deletion_list, struct mali_pp_job, list) + { + mali_pp_job_delete(job); + } +#endif + + /* Abort running jobs from this session */ + while (i > 0) + { + mali_group_abort_session(groups[--i], session); + } + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_abort_session(virtual_group, session); + } +} + +static mali_bool mali_pp_scheduler_is_suspended(void) +{ + mali_bool ret; + + mali_pp_scheduler_lock(); + + ret = pause_count > 0 + && _mali_osk_list_empty(&group_list_working) + && VIRTUAL_GROUP_WORKING != virtual_group_state; + + mali_pp_scheduler_unlock(); + + return ret; +} + +int mali_pp_scheduler_get_queue_depth(void) +{ + return job_queue_depth; +} + +#if MALI_STATE_TRACKING +u32 mali_pp_scheduler_dump_state(char *buf, u32 size) +{ + int n = 0; + struct mali_group *group; + struct mali_group *temp; + + n += _mali_osk_snprintf(buf + n, size - n, "PP:\n"); + n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list) + { + n += mali_group_dump_state(group, buf + n, size - n); + } + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) + { + n += mali_group_dump_state(group, buf + n, size - n); + } + + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_disabled, struct mali_group, pp_scheduler_list) + { + n += mali_group_dump_state(group, buf + n, size - n); + } + + if (mali_pp_scheduler_has_virtual_group()) + { + n += mali_group_dump_state(virtual_group, buf + n, size -n); + } + + n += _mali_osk_snprintf(buf + n, size - n, "\n"); + return n; +} +#endif + +/* This function is intended for power on reset of all cores. + * No locking is done for the list iteration, which can only be safe if the + * scheduler is paused and all cores idle. That is always the case on init and + * power on. */ +void mali_pp_scheduler_reset_all_groups(void) +{ + struct mali_group *group, *temp; + struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS]; + s32 i = 0; + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_lock(virtual_group); + mali_group_reset(virtual_group); + mali_group_unlock(virtual_group); + } + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state); + mali_pp_scheduler_lock(); + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + mali_pp_scheduler_unlock(); + + while (i > 0) + { + group = groups[--i]; + + mali_group_lock(group); + mali_group_reset(group); + mali_group_unlock(group); + } +} + +void mali_pp_scheduler_zap_all_active(struct mali_session_data *session) +{ + struct mali_group *group, *temp; + struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS]; + s32 i = 0; + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_zap_session(virtual_group, session); + } + + mali_pp_scheduler_lock(); + _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list) + { + groups[i++] = group; + } + mali_pp_scheduler_unlock(); + + while (i > 0) + { + mali_group_zap_session(groups[--i], session); + } +} + +/* A pm reference must be taken with _mali_osk_pm_dev_ref_add_no_power_on + * before calling this function to avoid Mali powering down as HW is accessed. + */ +static void mali_pp_scheduler_enable_group_internal(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + + mali_group_lock(group); + + if (MALI_GROUP_STATE_DISABLED != group->state) + { + mali_group_unlock(group); + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: PP group %p already enabled\n", group)); + return; + } + + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Enabling PP group %p\n", group)); + + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + ++enabled_cores; + + if (mali_pp_scheduler_has_virtual_group()) + { + mali_bool update_hw; + + /* Add group to virtual group */ + _mali_osk_list_delinit(&(group->pp_scheduler_list)); + group->state = MALI_GROUP_STATE_JOINING_VIRTUAL; + + mali_pp_scheduler_unlock(); + mali_group_unlock(group); + + mali_group_lock(virtual_group); + + update_hw = mali_pm_is_power_on(); + + mali_pm_domain_ref_get(group->pm_domain); + MALI_DEBUG_ASSERT(NULL == group->pm_domain || + MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(group->pm_domain)); + + if (update_hw) + { + mali_group_lock(group); + mali_group_power_on_group(group); + mali_group_reset(group); + mali_group_unlock(group); + } + + mali_pp_scheduler_enable_empty_virtual(); + mali_group_add_group(virtual_group, group, update_hw); + MALI_DEBUG_PRINT(4, ("Done enabling group %p. Added to virtual group.\n", group)); + + mali_group_unlock(virtual_group); + } + else + { + mali_pm_domain_ref_get(group->pm_domain); + MALI_DEBUG_ASSERT(NULL == group->pm_domain || + MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(group->pm_domain)); + + /* Put group on idle list */ + if (mali_pm_is_power_on()) + { + mali_group_power_on_group(group); + mali_group_reset(group); + } + + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle); + group->state = MALI_GROUP_STATE_IDLE; + + MALI_DEBUG_PRINT(4, ("Done enabling group %p. Now on idle list.\n", group)); + mali_pp_scheduler_unlock(); + mali_group_unlock(group); + } +} + +void mali_pp_scheduler_enable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + + _mali_osk_pm_dev_ref_add_no_power_on(); + + mali_pp_scheduler_enable_group_internal(group); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + + /* Pick up any jobs that might have been queued if all PP groups were disabled. */ + mali_pp_scheduler_schedule(); +} + +static void mali_pp_scheduler_disable_group_internal(struct mali_group *group) +{ + if (mali_pp_scheduler_has_virtual_group()) + { + mali_group_lock(virtual_group); + + MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state); + if (MALI_GROUP_STATE_JOINING_VIRTUAL == group->state) + { + /* The group was in the process of being added to the virtual group. We + * only need to change the state to reverse this. */ + group->state = MALI_GROUP_STATE_LEAVING_VIRTUAL; + } + else if (MALI_GROUP_STATE_IN_VIRTUAL == group->state) + { + /* Remove group from virtual group. The state of the group will be + * LEAVING_VIRTUAL and the group will not be on any scheduler list. */ + mali_group_remove_group(virtual_group, group); + + mali_pp_scheduler_disable_empty_virtual(); + } + + mali_group_unlock(virtual_group); + } + + mali_group_lock(group); + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + if (MALI_GROUP_STATE_DISABLED == group->state) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: PP group %p already disabled\n", group)); + } + else + { + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Disabling PP group %p\n", group)); + + --enabled_cores; + _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_disabled); + group->state = MALI_GROUP_STATE_DISABLED; + + mali_group_power_off_group(group); + mali_pm_domain_ref_put(group->pm_domain); + } + + mali_pp_scheduler_unlock(); + mali_group_unlock(group); +} + +void mali_pp_scheduler_disable_group(struct mali_group *group) +{ + MALI_DEBUG_ASSERT_POINTER(group); + + mali_pp_scheduler_suspend(); + _mali_osk_pm_dev_ref_add_no_power_on(); + + mali_pp_scheduler_disable_group_internal(group); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + mali_pp_scheduler_resume(); +} + + +static void mali_pp_scheduler_notify_core_change(u32 num_cores) +{ + if (!mali_is_mali450()) + { + /* Notify all user space sessions about the change, so number of master tile lists can be adapter */ + struct mali_session_data *session, *tmp; + + mali_session_lock(); + MALI_SESSION_FOREACH(session, tmp, link) + { + _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_NUM_CORE_CHANGE, sizeof(_mali_uk_pp_num_cores_changed_s)); + if (NULL != notobj) + { + _mali_uk_pp_num_cores_changed_s *data = notobj->result_buffer; + data->number_of_enabled_cores = num_cores; + mali_session_send_notification(session, notobj); + } + else + { + MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change\n")); + } + } + mali_session_unlock(); + } +} + +static void mali_pp_scheduler_set_perf_level_mali400(u32 target_core_nr) +{ + struct mali_group *group; + MALI_DEBUG_ASSERT(mali_is_mali400()); + + if (target_core_nr > enabled_cores) + { + MALI_DEBUG_PRINT(2, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores)); + + _mali_osk_pm_dev_ref_add_no_power_on(); + _mali_osk_pm_dev_barrier(); + + while (target_core_nr > enabled_cores) + { + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&group_list_disabled)); + + group = _MALI_OSK_LIST_ENTRY(group_list_disabled.next, struct mali_group, pp_scheduler_list); + + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state); + + mali_pp_scheduler_unlock(); + + mali_pp_scheduler_enable_group_internal(group); + } + + _mali_osk_pm_dev_ref_dec_no_power_on(); + + mali_pp_scheduler_schedule(); + } + else if (target_core_nr < enabled_cores) + { + MALI_DEBUG_PRINT(2, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr)); + + mali_pp_scheduler_suspend(); + + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + + while (target_core_nr < enabled_cores) + { + mali_pp_scheduler_lock(); + + MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&group_list_idle)); + MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working)); + + group = _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list); + + MALI_DEBUG_ASSERT_POINTER(group); + MALI_DEBUG_ASSERT( MALI_GROUP_STATE_IDLE == group->state + || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state + || MALI_GROUP_STATE_DISABLED == group->state); + + mali_pp_scheduler_unlock(); + + mali_pp_scheduler_disable_group_internal(group); + } + + mali_pp_scheduler_resume(); + } + + mali_pp_scheduler_notify_core_change(target_core_nr); +} + +static void mali_pp_scheduler_set_perf_level_mali450(u32 target_core_nr) +{ + struct mali_group *group; + MALI_DEBUG_ASSERT(mali_is_mali450()); + + if (target_core_nr > enabled_cores) + { + /* Enable some cores */ + struct mali_pm_domain *domain; + + MALI_DEBUG_PRINT(2, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores)); + + _mali_osk_pm_dev_ref_add_no_power_on(); + _mali_osk_pm_dev_barrier(); + + domain = mali_pm_domain_get(MALI_PMU_M450_DOM2); + + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_enable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + + if (target_core_nr > enabled_cores) + { + domain = mali_pm_domain_get(MALI_PMU_M450_DOM3); + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_enable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + } + + MALI_DEBUG_ASSERT(target_core_nr == enabled_cores); + + _mali_osk_pm_dev_ref_dec_no_power_on(); + + mali_pp_scheduler_schedule(); + } + else if (target_core_nr < enabled_cores) + { + /* Disable some cores */ + struct mali_pm_domain *domain; + + MALI_DEBUG_PRINT(2, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr)); + + mali_pp_scheduler_suspend(); + + domain = mali_pm_domain_get(MALI_PMU_M450_DOM3); + if (NULL != domain) + { + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_disable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + } + + if (target_core_nr < enabled_cores) + { + domain = mali_pm_domain_get(MALI_PMU_M450_DOM2); + MALI_DEBUG_ASSERT_POINTER(domain); + MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) + { + mali_pp_scheduler_disable_group_internal(group); + if (target_core_nr == enabled_cores) break; + } + } + + MALI_DEBUG_ASSERT(target_core_nr == enabled_cores); + + mali_pp_scheduler_resume(); + } +} + +int mali_pp_scheduler_set_perf_level(unsigned int cores) +{ + if (cores == enabled_cores) return 0; + if (cores > num_cores) return -EINVAL; + if (0 == cores) return -EINVAL; + + if (!mali_pp_scheduler_has_virtual_group()) + { + /* Mali-400 */ + mali_pp_scheduler_set_perf_level_mali400(cores); + } + else + { + /* Mali-450 */ + mali_pp_scheduler_set_perf_level_mali450(cores); + } + + return 0; +} + +static void mali_pp_scheduler_job_queued(void) +{ + /* We hold a PM reference for every job we hold queued (and running) */ + _mali_osk_pm_dev_ref_add(); + + if (mali_utilization_enabled()) + { + /* + * We cheat a little bit by counting the PP as busy from the time a PP job is queued. + * This will be fine because we only loose the tiny idle gap between jobs, but + * we will instead get less utilization work to do (less locks taken) + */ + mali_utilization_pp_start(); + } +} + +static void mali_pp_scheduler_job_completed(void) +{ + /* Release the PM reference we got in the mali_pp_scheduler_job_queued() function */ + _mali_osk_pm_dev_ref_dec(); + + if (mali_utilization_enabled()) + { + mali_utilization_pp_end(); + } +} diff --git a/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h new file mode 100644 index 0000000..71ec042 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_pp_scheduler.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 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_PP_SCHEDULER_H__ +#define __MALI_PP_SCHEDULER_H__ + +#include "mali_osk.h" +#include "mali_pp_job.h" +#include "mali_group.h" +#include "linux/mali/mali_utgard.h" + +/** Initalize the HW independent parts of the PP scheduler + */ +_mali_osk_errcode_t mali_pp_scheduler_initialize(void); +void mali_pp_scheduler_terminate(void); + +/** Poplulate the PP scheduler with groups + */ +void mali_pp_scheduler_populate(void); +void mali_pp_scheduler_depopulate(void); + +void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success); + +void mali_pp_scheduler_suspend(void); +void mali_pp_scheduler_resume(void); + +/** @brief Abort all PP jobs from session running or queued + * + * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the queue and jobs + * currently running on a core will be aborted. + * + * @param session Pointer to session whose jobs should be aborted + */ +void mali_pp_scheduler_abort_session(struct mali_session_data *session); + +/** + * @brief Reset all groups + * + * This function resets all groups known by the PP scheuduler. This must be + * called after the Mali HW has been powered on in order to reset the HW. + * + * This function is intended for power on reset of all cores. + * No locking is done, which can only be safe if the scheduler is paused and + * all cores idle. That is always the case on init and power on. + */ +void mali_pp_scheduler_reset_all_groups(void); + +/** + * @brief Zap TLB on all groups with \a session active + * + * The scheculer will zap the session on all groups it owns. + */ +void mali_pp_scheduler_zap_all_active(struct mali_session_data *session); + +int mali_pp_scheduler_get_queue_depth(void); +u32 mali_pp_scheduler_dump_state(char *buf, u32 size); + +void mali_pp_scheduler_enable_group(struct mali_group *group); +void mali_pp_scheduler_disable_group(struct mali_group *group); + +int mali_pp_scheduler_set_perf_level(u32 cores); + +u32 mali_pp_scheduler_get_num_cores_total(void); +u32 mali_pp_scheduler_get_num_cores_enabled(void); + +/** + * @brief Returns the number of Pixel Processors in the system irrespective of the context + * + * @return number of physical Pixel Processor cores in the system + */ +u32 mali_pp_scheduler_get_num_cores_total(void); + +#endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.c b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.c index f360209..f360209 100644 --- a/drivers/media/video/samsung/mali/common/mali_scheduler.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.c diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.h b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.h index 74f0947..63e5be8 100644 --- a/drivers/media/video/samsung/mali/common/mali_scheduler.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_scheduler.h @@ -12,10 +12,36 @@ #define __MALI_SCHEDULER_H__ #include "mali_osk.h" +#include "mali_gp_scheduler.h" +#include "mali_pp_scheduler.h" _mali_osk_errcode_t mali_scheduler_initialize(void); void mali_scheduler_terminate(void); u32 mali_scheduler_get_new_id(void); +/** + * @brief Reset all groups + * + * This function resets all groups known by the both the PP and GP scheuduler. + * This must be called after the Mali HW has been powered on in order to reset + * the HW. + */ +MALI_STATIC_INLINE void mali_scheduler_reset_all_groups(void) +{ + mali_gp_scheduler_reset_all_groups(); + mali_pp_scheduler_reset_all_groups(); +} + +/** + * @brief Zap TLB on all active groups running \a session + * + * @param session Pointer to the session to zap + */ +MALI_STATIC_INLINE void mali_scheduler_zap_all_active(struct mali_session_data *session) +{ + mali_gp_scheduler_zap_all_active(session); + mali_pp_scheduler_zap_all_active(session); +} + #endif /* __MALI_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_session.c b/drivers/gpu/mali400/r3p2/mali/common/mali_session.c index 2394bb9..2394bb9 100644 --- a/drivers/media/video/samsung/mali/common/mali_session.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_session.c diff --git a/drivers/media/video/samsung/mali/common/mali_session.h b/drivers/gpu/mali400/r3p2/mali/common/mali_session.h index c8640b5..5c34dde 100644 --- a/drivers/media/video/samsung/mali/common/mali_session.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_session.h @@ -20,6 +20,11 @@ struct mali_session_data { _mali_osk_notification_queue_t * ioctl_queue; +#ifdef CONFIG_SYNC + _mali_osk_list_t pending_jobs; + _mali_osk_lock_t *pending_jobs_lock; +#endif + _mali_osk_lock_t *memory_lock; /**< Lock protecting the vm manipulation */ mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */ _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */ @@ -27,6 +32,8 @@ struct mali_session_data struct mali_page_directory *page_directory; /**< MMU page directory for this session */ _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */ + + _MALI_OSK_LIST_HEAD(job_list); /**< List of all jobs on this session */ }; _mali_osk_errcode_t mali_session_initialize(void); diff --git a/drivers/media/video/samsung/mali/common/mali_ukk.h b/drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h index 6b018d0..1f8a320 100644 --- a/drivers/media/video/samsung/mali/common/mali_ukk.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_ukk.h @@ -357,6 +357,12 @@ _mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu */ _mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args ); +/** @brief Write user data to specified Mali memory without causing segfaults. + * @param args see _mali_uk_mem_write_safe_s in mali_utgard_uk_types.h + * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. + */ +_mali_osk_errcode_t _mali_ukk_mem_write_safe( _mali_uk_mem_write_safe_s *args ); + /** @brief Map a physically contiguous range of memory into Mali * @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. @@ -369,7 +375,7 @@ _mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *arg */ _mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args ); -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#if defined(CONFIG_MALI400_UMP) /** @brief Map UMP memory into Mali * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. @@ -380,7 +386,7 @@ _mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ); * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. */ _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args ); -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ +#endif /* CONFIG_MALI400_UMP */ /** @brief Determine virtual-to-physical mapping of a contiguous memory range * (optional) @@ -449,10 +455,11 @@ _mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args ); * * Job completion can be awaited with _mali_ukk_wait_for_notification(). * - * @param args see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h" + * @oaram ctx user-kernel context (mali_session) + * @param uargs see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data! * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. */ -_mali_osk_errcode_t _mali_ukk_pp_start_job( _mali_uk_pp_start_job_s *args ); +_mali_osk_errcode_t _mali_ukk_pp_start_job( void *ctx, _mali_uk_pp_start_job_s *uargs, int *fence ); /** @brief Returns the number of Fragment Processors in the system * @@ -502,10 +509,11 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args); * * Job completion can be awaited with _mali_ukk_wait_for_notification(). * - * @param args see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h" + * @oaram ctx user-kernel context (mali_session) + * @param uargs see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data! * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. */ -_mali_osk_errcode_t _mali_ukk_gp_start_job( _mali_uk_gp_start_job_s *args ); +_mali_osk_errcode_t _mali_ukk_gp_start_job( void *ctx, _mali_uk_gp_start_job_s *uargs ); /** @brief Returns the number of Vertex Processors in the system. * @@ -536,7 +544,7 @@ _mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_ /** @} */ /* end group _mali_uk_gp */ -#if MALI_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_PROFILING) /** @addtogroup _mali_uk_profiling U/K Timeline profiling module * @{ */ @@ -605,6 +613,12 @@ _mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s * u32 _mali_ukk_report_memory_usage(void); +u32 _mali_ukk_utilization_gp_pp(void); + +u32 _mali_ukk_utilization_gp(void); + +u32 _mali_ukk_utilization_pp(void); + #ifdef __cplusplus } #endif diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.c index d3f1e50..8720b9a 100644 --- a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.c @@ -38,7 +38,11 @@ void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value) { mali_bool notify = MALI_FALSE; - MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0); + if (setting >= _MALI_UK_USER_SETTING_MAX || setting < 0) + { + MALI_DEBUG_PRINT_ERROR(("Invalid user setting %ud\n")); + return; + } if (mali_user_settings[setting] != value) { @@ -55,7 +59,10 @@ void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value) u32 mali_get_user_setting(_mali_uk_user_setting_t setting) { - MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0); + if (setting >= _MALI_UK_USER_SETTING_MAX || setting < 0) + { + return 0; + } return mali_user_settings[setting]; } diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.h index fbb9415..fbb9415 100644 --- a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h +++ b/drivers/gpu/mali400/r3p2/mali/common/mali_user_settings_db.h diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h new file mode 100644 index 0000000..cf3374a --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard.h @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2012 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_utgard.h + * Defines types and interface exposed by the Mali Utgard device driver + */ + +#ifndef __MALI_UTGARD_H__ +#define __MALI_UTGARD_H__ + +#define MALI_GPU_NAME_UTGARD "mali-utgard" + +/* Mali-200 */ + +#define MALI_GPU_RESOURCES_MALI200(base_addr, gp_irq, pp_irq, mmu_irq) \ + MALI_GPU_RESOURCE_PP(base_addr + 0x0000, pp_irq) \ + MALI_GPU_RESOURCE_GP(base_addr + 0x2000, gp_irq) \ + MALI_GPU_RESOURCE_MMU(base_addr + 0x3000, mmu_irq) + +/* Mali-300 */ + +#define MALI_GPU_RESOURCES_MALI300(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI300_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) + +/* Mali-400 */ + +#define MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +#define MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +#define MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +#define MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0xE000, pp3_irq, base_addr + 0x7000, pp3_mmu_irq) + +#define MALI_GPU_RESOURCES_MALI400_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \ + MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) + +/* Mali-450 */ +#define MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x28000, pp3_irq, base_addr + 0x1C000, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x2A000, pp4_irq, base_addr + 0x1D000, pp4_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2C000, pp5_irq, base_addr + 0x1E000, pp5_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP6_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \ + MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \ + MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x28000, pp4_irq, base_addr + 0x1C000, pp4_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2A000, pp5_irq, base_addr + 0x1D000, pp5_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(6, base_addr + 0x2C000, pp6_irq, base_addr + 0x1E000, pp6_mmu_irq) \ + MALI_GPU_RESOURCE_PP_WITH_MMU(7, base_addr + 0x2E000, pp7_irq, base_addr + 0x1F000, pp7_mmu_irq) \ + MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \ + MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \ + MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) + +#define MALI_GPU_RESOURCES_MALI450_MP8_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \ + MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \ + +#define MALI_GPU_RESOURCE_L2(addr) \ + { \ + .name = "Mali_L2", \ + .flags = IORESOURCE_MEM, \ + .start = addr, \ + .end = addr + 0x200, \ + }, + +#define MALI_GPU_RESOURCE_GP(gp_addr, gp_irq) \ + { \ + .name = "Mali_GP", \ + .flags = IORESOURCE_MEM, \ + .start = gp_addr, \ + .end = gp_addr + 0x100, \ + }, \ + { \ + .name = "Mali_GP_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = gp_irq, \ + .end = gp_irq, \ + }, \ + +#define MALI_GPU_RESOURCE_GP_WITH_MMU(gp_addr, gp_irq, gp_mmu_addr, gp_mmu_irq) \ + { \ + .name = "Mali_GP", \ + .flags = IORESOURCE_MEM, \ + .start = gp_addr, \ + .end = gp_addr + 0x100, \ + }, \ + { \ + .name = "Mali_GP_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = gp_irq, \ + .end = gp_irq, \ + }, \ + { \ + .name = "Mali_GP_MMU", \ + .flags = IORESOURCE_MEM, \ + .start = gp_mmu_addr, \ + .end = gp_mmu_addr + 0x100, \ + }, \ + { \ + .name = "Mali_GP_MMU_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = gp_mmu_irq, \ + .end = gp_mmu_irq, \ + }, + +#define MALI_GPU_RESOURCE_PP(pp_addr, pp_irq) \ + { \ + .name = "Mali_PP", \ + .flags = IORESOURCE_MEM, \ + .start = pp_addr, \ + .end = pp_addr + 0x1100, \ + }, \ + { \ + .name = "Mali_PP_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_irq, \ + .end = pp_irq, \ + }, \ + +#define MALI_GPU_RESOURCE_PP_WITH_MMU(id, pp_addr, pp_irq, pp_mmu_addr, pp_mmu_irq) \ + { \ + .name = "Mali_PP" #id, \ + .flags = IORESOURCE_MEM, \ + .start = pp_addr, \ + .end = pp_addr + 0x1100, \ + }, \ + { \ + .name = "Mali_PP" #id "_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_irq, \ + .end = pp_irq, \ + }, \ + { \ + .name = "Mali_PP" #id "_MMU", \ + .flags = IORESOURCE_MEM, \ + .start = pp_mmu_addr, \ + .end = pp_mmu_addr + 0x100, \ + }, \ + { \ + .name = "Mali_PP" #id "_MMU_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_mmu_irq, \ + .end = pp_mmu_irq, \ + }, + +#define MALI_GPU_RESOURCE_MMU(mmu_addr, mmu_irq) \ + { \ + .name = "Mali_MMU", \ + .flags = IORESOURCE_MEM, \ + .start = mmu_addr, \ + .end = mmu_addr + 0x100, \ + }, \ + { \ + .name = "Mali_MMU_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = mmu_irq, \ + .end = mmu_irq, \ + }, + +#define MALI_GPU_RESOURCE_PMU(pmu_addr) \ + { \ + .name = "Mali_PMU", \ + .flags = IORESOURCE_MEM, \ + .start = pmu_addr, \ + .end = pmu_addr + 0x100, \ + }, + +#define MALI_GPU_RESOURCE_DLBU(dlbu_addr) \ + { \ + .name = "Mali_DLBU", \ + .flags = IORESOURCE_MEM, \ + .start = dlbu_addr, \ + .end = dlbu_addr + 0x100, \ + }, + +#define MALI_GPU_RESOURCE_BCAST(bcast_addr) \ + { \ + .name = "Mali_Broadcast", \ + .flags = IORESOURCE_MEM, \ + .start = bcast_addr, \ + .end = bcast_addr + 0x100, \ + }, + +#define MALI_GPU_RESOURCE_PP_BCAST(pp_addr, pp_irq) \ + { \ + .name = "Mali_PP_Broadcast", \ + .flags = IORESOURCE_MEM, \ + .start = pp_addr, \ + .end = pp_addr + 0x1100, \ + }, \ + { \ + .name = "Mali_PP_Broadcast_IRQ", \ + .flags = IORESOURCE_IRQ, \ + .start = pp_irq, \ + .end = pp_irq, \ + }, \ + +#define MALI_GPU_RESOURCE_PP_MMU_BCAST(pp_mmu_bcast_addr) \ + { \ + .name = "Mali_PP_MMU_Broadcast", \ + .flags = IORESOURCE_MEM, \ + .start = pp_mmu_bcast_addr, \ + .end = pp_mmu_bcast_addr + 0x100, \ + }, + +struct mali_gpu_utilization_data +{ + unsigned int utilization_gpu; /* Utilization for GP and all PP cores combined, 0 = no utilization, 256 = full utilization */ + unsigned int utilization_gp; /* Utilization for GP core only, 0 = no utilization, 256 = full utilization */ + unsigned int utilization_pp; /* Utilization for all PP cores combined, 0 = no utilization, 256 = full utilization */ +}; + +struct mali_gpu_device_data +{ + /* Dedicated GPU memory range (physical). */ + unsigned long dedicated_mem_start; + unsigned long dedicated_mem_size; + + /* Shared GPU memory */ + unsigned long shared_mem_size; + + /* Frame buffer memory to be accessible by Mali GPU (physical) */ + unsigned long fb_start; + unsigned long fb_size; + + /* Report GPU utilization in this interval (specified in ms) */ + unsigned long utilization_interval; + + /* Function that will receive periodic GPU utilization numbers */ + void (*utilization_callback)(struct mali_gpu_utilization_data *data); + + /* + * Mali PMU switch delay. + * Only needed if the power gates are connected to the PMU in a high fanout + * network. This value is the number of Mali clock cycles it takes to + * enable the power gates and turn on the power mesh. + * This value will have no effect if a daisy chain implementation is used. + */ + unsigned long pmu_switch_delay; +}; + +/** @brief MALI GPU power down using MALI in-built PMU + * + * called to power down all cores + */ +int mali_pmu_powerdown(void); + + +/** @brief MALI GPU power up using MALI in-built PMU + * + * called to power up all cores + */ +int mali_pmu_powerup(void); + +/** + * Pause the scheduling and power state changes of Mali device driver. + * mali_dev_resume() must always be called as soon as possible after this function + * in order to resume normal operation of the Mali driver. + */ +void mali_dev_pause(void); + +/** + * Resume scheduling and allow power changes in Mali device driver. + * This must always be called after mali_dev_pause(). + */ +void mali_dev_resume(void); + +/** @brief Set the desired number of PP cores to use. + * + * The internal Mali PMU will be used, if present, to physically power off the PP cores. + * + * @param num_cores The number of desired cores + * @return 0 on success, otherwise error. -EINVAL means an invalid number of cores was specified. + */ +int mali_perf_set_num_pp_cores(unsigned int num_cores); + +#endif diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_counters.h index 40822f7..3ef9a28 100644 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_counters.h @@ -212,7 +212,7 @@ typedef enum MALI_CINSTR_PP_RSW_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 15, MALI_CINSTR_PP_VERTEX_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 16, MALI_CINSTR_PP_UNIFORM_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 17, - MALI_CINSTR_PP_PROGRAM_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, + MALI_CINSTR_PP_PROGRAM_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 18, MALI_CINSTR_PP_VARYING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19, MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 20, MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 21, diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_ioctl.h index 7935448..6043a7d 100644 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_ioctl.h @@ -44,6 +44,9 @@ extern "C" #define MALI_IOC_POST_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *) #define MALI_IOC_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *) #define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *) +#define MALI_IOC_STREAM_CREATE _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_STREAM_CREATE, _mali_uk_stream_create_s *) +#define MALI_IOC_FENCE_CREATE_EMPTY _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_CREATE_EMPTY, _mali_uk_fence_create_empty_s *) +#define MALI_IOC_FENCE_VALIDATE _IOR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_VALIDATE, _mali_uk_fence_validate_s *) #define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *) #define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *) @@ -58,6 +61,7 @@ extern "C" #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_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_WRITE_SAFE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MEM_WRITE_SAFE, _mali_uk_mem_write_safe_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 *) diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_events.h index b96596e..99864b8 100644 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_events.h @@ -66,20 +66,38 @@ typedef enum MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4, MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE = 5, MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE = 6, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_READBACK = 7, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_WRITEBACK = 8, MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC = 10, MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC = 11, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_DISCARD_ATTACHMENTS = 13, MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53, MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54, MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55, + MALI_PROFILING_EVENT_REASON_SINGLE_LOCK_CONTENDED = 56, } cinstr_profiling_event_reason_single_sw_t; /** * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel + * to inform whether the core is physical or virtual */ typedef enum { - MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0, - MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1, + MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL = 0, + MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL = 1, +} cinstr_profiling_event_reason_start_stop_hw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel + */ +typedef enum +{ + /*MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0,*/ + MALI_PROFILING_EVENT_REASON_START_STOP_SW_MALI = 1, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_CALLBACK_THREAD = 2, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_WORKER_THREAD = 3, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF = 4, + MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF = 5, } cinstr_profiling_event_reason_start_stop_sw_t; /** @@ -87,7 +105,7 @@ typedef enum */ typedef enum { - MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE = 0, /* NOT used */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE = 0, /* used */ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1, /* NOT used */ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26, /* used in some build configurations */ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT = 27, /* USED */ @@ -103,6 +121,8 @@ typedef enum MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_GLOBAL_LOCK = 37, /* Not currently used */ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_SWAP = 38, /* Not currently used */ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_MALI_EGL_IMAGE_SYNC_WAIT = 39, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GP_JOB_HANDLING =40, /* USED */ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PP_JOB_HANDLING =41, /* USED */ } cinstr_profiling_event_reason_suspend_resume_sw_t; /** @@ -122,6 +142,31 @@ typedef enum { MALI_PROFILING_EVENT_REASON_SINGLE_GPU_NONE = 0, MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS = 2, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS = 3, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS = 4, } cinstr_profiling_event_reason_single_gpu_t; +/** + * These values are applicable for the 3rd data parameter when + * the type MALI_PROFILING_EVENT_TYPE_START is used from the software channel + * with the MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF reason. + */ +typedef enum +{ + MALI_PROFILING_EVENT_DATA_CORE_GP0 = 1, + MALI_PROFILING_EVENT_DATA_CORE_PP0 = 5, + MALI_PROFILING_EVENT_DATA_CORE_PP1 = 6, + MALI_PROFILING_EVENT_DATA_CORE_PP2 = 7, + MALI_PROFILING_EVENT_DATA_CORE_PP3 = 8, + MALI_PROFILING_EVENT_DATA_CORE_PP4 = 9, + MALI_PROFILING_EVENT_DATA_CORE_PP5 = 10, + MALI_PROFILING_EVENT_DATA_CORE_PP6 = 11, + MALI_PROFILING_EVENT_DATA_CORE_PP7 = 12, +} cinstr_profiling_event_data_core_t; + +#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(num) (MALI_PROFILING_EVENT_DATA_CORE_GP0 + (num)) +#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(num) (MALI_PROFILING_EVENT_DATA_CORE_PP0 + (num)) + + #endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/ diff --git a/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h new file mode 100644 index 0000000..c449215 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_profiling_gator_api.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2010-2012 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_UTGARD_PROFILING_GATOR_API_H__ +#define __MALI_UTGARD_PROFILING_GATOR_API_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MALI_PROFILING_API_VERSION 4 + +#define MAX_NUM_L2_CACHE_CORES 3 +#define MAX_NUM_FP_CORES 8 +#define MAX_NUM_VP_CORES 1 + +/** The list of events supported by the Mali DDK. */ +typedef enum +{ + /* Vertex processor activity */ + ACTIVITY_VP_0 = 0, + + /* Fragment processor activity */ + ACTIVITY_FP_0, + ACTIVITY_FP_1, + ACTIVITY_FP_2, + ACTIVITY_FP_3, + ACTIVITY_FP_4, + ACTIVITY_FP_5, + ACTIVITY_FP_6, + ACTIVITY_FP_7, + + /* L2 cache counters */ + COUNTER_L2_0_C0, + COUNTER_L2_0_C1, + COUNTER_L2_1_C0, + COUNTER_L2_1_C1, + COUNTER_L2_2_C0, + COUNTER_L2_2_C1, + + /* Vertex processor counters */ + COUNTER_VP_0_C0, + COUNTER_VP_0_C1, + + /* Fragment processor counters */ + COUNTER_FP_0_C0, + COUNTER_FP_0_C1, + COUNTER_FP_1_C0, + COUNTER_FP_1_C1, + COUNTER_FP_2_C0, + COUNTER_FP_2_C1, + COUNTER_FP_3_C0, + COUNTER_FP_3_C1, + COUNTER_FP_4_C0, + COUNTER_FP_4_C1, + COUNTER_FP_5_C0, + COUNTER_FP_5_C1, + COUNTER_FP_6_C0, + COUNTER_FP_6_C1, + COUNTER_FP_7_C0, + COUNTER_FP_7_C1, + + /* + * If more hardware counters are added, the _mali_osk_hw_counter_table + * below should also be updated. + */ + + /* EGL software counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES software counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + /* Framebuffer capture pseudo-counter */ + COUNTER_FILMSTRIP, + + NUMBER_OF_EVENTS +} _mali_osk_counter_id; + +#define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0 +#define LAST_ACTIVITY_EVENT ACTIVITY_FP_7 + +#define FIRST_HW_COUNTER COUNTER_L2_0_C0 +#define LAST_HW_COUNTER COUNTER_FP_7_C1 + +#define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME +#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT + +#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP +#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP + +/** + * Structure to pass performance counter data of a Mali core + */ +typedef struct _mali_profiling_core_counters +{ + u32 source0; + u32 value0; + u32 source1; + u32 value1; +} _mali_profiling_core_counters; + +/** + * Structure to pass performance counter data of Mali L2 cache cores + */ +typedef struct _mali_profiling_l2_counter_values +{ + struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; +} _mali_profiling_l2_counter_values; + +/** + * Structure to pass data defining Mali instance in use: + * + * mali_product_id - Mali product id + * mali_version_major - Mali version major number + * mali_version_minor - Mali version minor number + * num_of_l2_cores - number of L2 cache cores + * num_of_fp_cores - number of fragment processor cores + * num_of_vp_cores - number of vertex processor cores + */ +typedef struct _mali_profiling_mali_version +{ + u32 mali_product_id; + u32 mali_version_major; + u32 mali_version_minor; + u32 num_of_l2_cores; + u32 num_of_fp_cores; + u32 num_of_vp_cores; +} _mali_profiling_mali_version; + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. + * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) + +void _mali_profiling_control(u32 action, u32 value); + +u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values); + +int _mali_profiling_set_event(u32 counter_id, s32 event_id); + +u32 _mali_profiling_get_api_version(void); + +void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_UTGARD_PROFILING_GATOR_API_H__ */ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_uk_types.h index b35a715..4957095 100644 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h +++ b/drivers/gpu/mali400/r3p2/mali/include/linux/mali/mali_utgard_uk_types.h @@ -68,6 +68,9 @@ typedef enum _MALI_UK_POST_NOTIFICATION, /**< _mali_ukk_post_notification() */ _MALI_UK_GET_USER_SETTING, /**< _mali_ukk_get_user_setting() *//**< [out] */ _MALI_UK_GET_USER_SETTINGS, /**< _mali_ukk_get_user_settings() *//**< [out] */ + _MALI_UK_STREAM_CREATE, /**< _mali_ukk_stream_create() */ + _MALI_UK_FENCE_CREATE_EMPTY, /**< _mali_ukk_fence_create_empty() */ + _MALI_UK_FENCE_VALIDATE, /**< _mali_ukk_fence_validate() */ /** Memory functions */ @@ -87,6 +90,7 @@ typedef enum _MALI_UK_MAP_EXT_MEM, /**< _mali_uku_map_external_mem() */ _MALI_UK_UNMAP_EXT_MEM, /**< _mali_uku_unmap_external_mem() */ _MALI_UK_VA_TO_MALI_PA, /**< _mali_uku_va_to_mali_pa() */ + _MALI_UK_MEM_WRITE_SAFE, /**< _mali_uku_mem_write_safe() */ /** Common functions for each core */ @@ -417,9 +421,13 @@ typedef struct #define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1) +#define _MALI_DLBU_MAX_REGISTERS 4 + /** Flag for _mali_uk_pp_start_job_s */ #define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0) #define _MALI_PP_JOB_FLAG_BARRIER (1<<1) +#define _MALI_PP_JOB_FLAG_FENCE (1<<2) +#define _MALI_PP_JOB_FLAG_EMPTY_FENCE (1<<3) /** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job * @{ */ @@ -476,6 +484,7 @@ typedef struct u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; + u32 dlbu_registers[_MALI_DLBU_MAX_REGISTERS]; /**< [in] Dynamic load balancing unit registers */ u32 num_cores; /**< [in] Number of cores to set up (valid range: 1-4) */ u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ @@ -483,6 +492,10 @@ typedef struct u32 frame_builder_id; /**< [in] id of the originating frame builder */ u32 flush_id; /**< [in] flush id within the originating frame builder */ u32 flags; /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */ + s32 fence; /**< [in,out] Fence to wait on / fence that will be signalled on job completion, if _MALI_PP_JOB_FLAG_FENCE is set */ + s32 stream; /**< [in] Steam identifier if _MALI_PP_JOB_FLAG_FENCE, an empty fence to use for this job if _MALI_PP_JOB_FLAG_EMPTY_FENCE is set */ + u32 num_memory_cookies; /**< [in] number of memory cookies attached to job */ + u32 *memory_cookies; /**< [in] memory cookies attached to job */ } _mali_uk_pp_start_job_s; /** @} */ /* end group _mali_uk_ppstartjob_s */ @@ -494,6 +507,13 @@ typedef struct u32 perf_counter1[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 1 (see ARM DDI0415A), one for each sub job */ } _mali_uk_pp_job_finished_s; +typedef struct +{ + u32 number_of_enabled_cores; /**< [out] the new number of enabled cores */ +} _mali_uk_pp_num_cores_changed_s; + + + /** * Flags to indicate write-back units */ @@ -543,6 +563,7 @@ typedef enum /** Fragment Processor notifications */ _MALI_NOTIFICATION_PP_FINISHED = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10, + _MALI_NOTIFICATION_PP_NUM_CORE_CHANGE = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x20, /** Vertex Processor notifications */ @@ -700,7 +721,7 @@ typedef struct * The 16bit integer is stored twice in a 32bit integer * For example, for version 1 the value would be 0x00010001 */ -#define _MALI_API_VERSION 17 +#define _MALI_API_VERSION 23 #define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION) /** @@ -869,6 +890,16 @@ typedef struct u32 size; /**< [in,out] Size of the range, in bytes. */ } _mali_uk_va_to_mali_pa_s; +/** + * @brief Arguments for _mali_uk[uk]_mem_write_safe() + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + const void *src; /**< [in] Pointer to source data */ + void *dest; /**< [in] Destination Mali buffer */ + u32 size; /**< [in,out] Number of bytes to write/copy on input, number of bytes actually written/copied on output */ +} _mali_uk_mem_write_safe_s; typedef struct { @@ -901,8 +932,9 @@ typedef struct */ typedef struct { - void *ctx; /**< [in,out] user-kernel context (trashed on output) */ - u32 number_of_cores; /**< [out] number of Fragment Processor cores in the system */ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 number_of_total_cores; /**< [out] Total number of Fragment Processor cores in the system */ + u32 number_of_enabled_cores; /**< [out] Number of enabled Fragment Processor cores */ } _mali_uk_get_pp_number_of_cores_s; /** @brief Arguments for _mali_ukk_get_pp_core_version() @@ -1084,6 +1116,44 @@ typedef struct /** @} */ /* end group _mali_uk_sw_counters_report */ +/** @defgroup _mali_uk_stream U/K Mali stream module + * @{ */ + +/** @brief Create stream + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int fd; /**< [out] file descriptor describing stream */ +} _mali_uk_stream_create_s; + +/** @brief Destroy stream +*/ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int fd; /**< [in] file descriptor describing stream */ +} _mali_uk_stream_destroy_s; + +/** @brief Create empty fence + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + s32 stream; /**< [in] stream to create fence on */ + s32 fence; /**< [out] file descriptor describing fence */ +} _mali_uk_fence_create_empty_s; + +/** @brief Check fence validity + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + int fd; /**< [in] file descriptor describing fence */ +} _mali_uk_fence_validate_s; + +/** @} */ /* end group _mali_uk_stream */ + /** @} */ /* end group u_k_api */ /** @} */ /* end group uddapi */ diff --git a/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/mali400/r3p2/mali/linux/license/gpl/mali_kernel_license.h index 52bb5e0..e9e5e55 100644 --- a/drivers/media/video/samsung/mali/linux/license/gpl/mali_kernel_license.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/license/gpl/mali_kernel_license.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_device_pause_resume.c index 6af1279..0b82cba 100644 --- a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_device_pause_resume.c @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2010-2012 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 @@ -13,34 +13,23 @@ * Implementation of the Mali pause/resume functionality */ +#include <linux/module.h> +#include <linux/mali/mali_utgard.h> #include "mali_gp_scheduler.h" #include "mali_pp_scheduler.h" -#include "mali_pm.h" -void mali_dev_pause(mali_bool *power_is_on) +void mali_dev_pause(void) { mali_gp_scheduler_suspend(); mali_pp_scheduler_suspend(); - - /* - * Take and hold the PM lock to be sure we don't change power state as well. - * (it might be unsafe to for instance change frequency if Mali GPU is powered off) - */ - mali_pm_execute_state_change_lock(); - if (NULL != power_is_on) - { - *power_is_on = mali_pm_is_powered_on(); - } } +EXPORT_SYMBOL(mali_dev_pause); + void mali_dev_resume(void) { - mali_pm_execute_state_change_unlock(); mali_gp_scheduler_resume(); mali_pp_scheduler_resume(); } -/* -EXPORT_SYMBOL(mali_dev_pause); EXPORT_SYMBOL(mali_dev_resume); -*/ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c new file mode 100644 index 0000000..c34b2c6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.c @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2012 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 <linux/dma-buf.h> +#include <linux/scatterlist.h> +#include <linux/rbtree.h> +#include <linux/platform_device.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/mutex.h> + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_session.h" +#include "mali_kernel_linux.h" + +#include "mali_kernel_memory_engine.h" +#include "mali_memory.h" +#include "mali_dma_buf.h" + + +struct mali_dma_buf_attachment { + struct dma_buf *buf; + struct dma_buf_attachment *attachment; + struct sg_table *sgt; + struct mali_session_data *session; + int map_ref; + struct mutex map_lock; + mali_bool is_mapped; + wait_queue_head_t wait_queue; +}; + +void mali_dma_buf_release(void *ctx, void *handle) +{ + struct mali_dma_buf_attachment *mem; + + mem = (struct mali_dma_buf_attachment *)handle; + + MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release attachment %p\n", mem)); + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(mem->attachment); + MALI_DEBUG_ASSERT_POINTER(mem->buf); + +#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + /* We mapped implicitly on attach, so we need to unmap on release */ + mali_dma_buf_unmap(mem); +#endif + + /* Wait for buffer to become unmapped */ + wait_event(mem->wait_queue, !mem->is_mapped); + MALI_DEBUG_ASSERT(!mem->is_mapped); + + dma_buf_detach(mem->buf, mem->attachment); + dma_buf_put(mem->buf); + + _mali_osk_free(mem); +} + +/* + * Map DMA buf attachment \a mem into \a session at virtual address \a virt. + */ +int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 *offset, u32 flags) +{ + struct mali_page_directory *pagedir; + struct scatterlist *sg; + int i; + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(session); + MALI_DEBUG_ASSERT(mem->session == session); + + mutex_lock(&mem->map_lock); + + mem->map_ref++; + + MALI_DEBUG_PRINT(5, ("Mali DMA-buf: map attachment %p, new map_ref = %d\n", mem, mem->map_ref)); + + if (1 == mem->map_ref) + { + /* First reference taken, so we need to map the dma buf */ + MALI_DEBUG_ASSERT(!mem->is_mapped); + + pagedir = mali_session_get_page_directory(session); + MALI_DEBUG_ASSERT_POINTER(pagedir); + + mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(mem->sgt)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf attachment\n")); + return -EFAULT; + } + + for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) + { + u32 size = sg_dma_len(sg); + dma_addr_t phys = sg_dma_address(sg); + + /* sg must be page aligned. */ + MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE); + + mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD); + + virt += size; + *offset += size; + } + + if (flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) + { + u32 guard_phys; + MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n")); + + guard_phys = sg_dma_address(mem->sgt->sgl); + mali_mmu_pagedir_update(pagedir, virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD); + } + + mem->is_mapped = MALI_TRUE; + mutex_unlock(&mem->map_lock); + + /* Wake up any thread waiting for buffer to become mapped */ + wake_up_all(&mem->wait_queue); + } + else + { + MALI_DEBUG_ASSERT(mem->is_mapped); + mutex_unlock(&mem->map_lock); + } + + return 0; +} + +void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem) +{ + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT_POINTER(mem->attachment); + MALI_DEBUG_ASSERT_POINTER(mem->buf); + + mutex_lock(&mem->map_lock); + + mem->map_ref--; + + MALI_DEBUG_PRINT(5, ("Mali DMA-buf: unmap attachment %p, new map_ref = %d\n", mem, mem->map_ref)); + + if (0 == mem->map_ref) + { + dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL); + + mem->is_mapped = MALI_FALSE; + } + + mutex_unlock(&mem->map_lock); + + /* Wake up any thread waiting for buffer to become unmapped */ + wake_up_all(&mem->wait_queue); +} + +#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +int mali_dma_buf_map_job(struct mali_pp_job *job) +{ + mali_memory_allocation *descriptor; + struct mali_dma_buf_attachment *mem; + _mali_osk_errcode_t err; + int i; + u32 offset = 0; + int ret = 0; + + _mali_osk_lock_wait( job->session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + for (i = 0; i < job->num_memory_cookies; i++) + { + int cookie = job->memory_cookies[i]; + + if (0 == cookie) + { + /* 0 is not a valid cookie */ + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + MALI_DEBUG_ASSERT(0 < cookie); + + err = mali_descriptor_mapping_get(job->session->descriptor_mapping, + cookie, (void**)&descriptor); + + if (_MALI_OSK_ERR_OK != err) + { + MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to get descriptor for cookie %d\n", cookie)); + ret = -EFAULT; + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + if (mali_dma_buf_release != descriptor->physical_allocation.release) + { + /* Not a DMA-buf */ + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + mem = (struct mali_dma_buf_attachment *)descriptor->physical_allocation.handle; + + MALI_DEBUG_ASSERT_POINTER(mem); + MALI_DEBUG_ASSERT(mem->session == job->session); + + err = mali_dma_buf_map(mem, mem->session, descriptor->mali_address, &offset, descriptor->flags); + if (0 != err) + { + MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to map dma-buf for cookie %d at mali address %x\b", + cookie, descriptor->mali_address)); + ret = -EFAULT; + MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]); + continue; + } + + /* Add mem to list of DMA-bufs mapped for this job */ + job->dma_bufs[i] = mem; + } + + _mali_osk_lock_signal( job->session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + return ret; +} + +void mali_dma_buf_unmap_job(struct mali_pp_job *job) +{ + int i; + for (i = 0; i < job->num_dma_bufs; i++) + { + if (NULL == job->dma_bufs[i]) continue; + + mali_dma_buf_unmap(job->dma_bufs[i]); + job->dma_bufs[i] = NULL; + } +} +#endif /* !CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH */ + +/* Callback from memory engine which will map into Mali virtual address space */ +static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) +{ + struct mali_session_data *session; + struct mali_dma_buf_attachment *mem; + + MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(engine); + MALI_DEBUG_ASSERT_POINTER(descriptor); + MALI_DEBUG_ASSERT_POINTER(offset); + MALI_DEBUG_ASSERT_POINTER(alloc_info); + + /* Mapping dma-buf with an offset is not supported. */ + MALI_DEBUG_ASSERT(0 == *offset); + + session = (struct mali_session_data *)descriptor->mali_addr_mapping_info; + MALI_DEBUG_ASSERT_POINTER(session); + + mem = (struct mali_dma_buf_attachment *)ctx; + + MALI_DEBUG_ASSERT(mem->session == session); + +#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) + if (0 == mali_dma_buf_map(mem, session, descriptor->mali_address, offset, descriptor->flags)) + { + MALI_DEBUG_ASSERT(*offset == descriptor->size); +#else + { +#endif + alloc_info->ctx = NULL; + alloc_info->handle = mem; + alloc_info->next = NULL; + alloc_info->release = mali_dma_buf_release; + + return MALI_MEM_ALLOC_FINISHED; + } + + return MALI_MEM_ALLOC_INTERNAL_FAILURE; +} + +int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg) +{ + mali_physical_memory_allocator external_memory_allocator; + struct dma_buf *buf; + struct mali_dma_buf_attachment *mem; + _mali_uk_attach_dma_buf_s args; + mali_memory_allocation *descriptor; + int md; + int fd; + + /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) + { + return -EFAULT; + } + + fd = args.mem_fd; + + buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(buf)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd)); + return PTR_RET(buf); + } + + /* Currently, mapping of the full buffer are supported. */ + if (args.size != buf->size) + { + MALI_DEBUG_PRINT_ERROR(("dma-buf size doesn't match mapping size.\n")); + dma_buf_put(buf); + return -EINVAL; + } + + mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment)); + if (NULL == mem) + { + MALI_DEBUG_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n")); + dma_buf_put(buf); + return -ENOMEM; + } + + mem->buf = buf; + mem->session = session; + mem->map_ref = 0; + mutex_init(&mem->map_lock); + init_waitqueue_head(&mem->wait_queue); + + mem->attachment = dma_buf_attach(mem->buf, &mali_platform_device->dev); + if (NULL == mem->attachment) + { + MALI_DEBUG_PRINT_ERROR(("Failed to attach to dma-buf %d\n", fd)); + dma_buf_put(mem->buf); + _mali_osk_free(mem); + return -EFAULT; + } + + /* Map dma-buf into this session's page tables */ + + /* Set up Mali memory descriptor */ + descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); + if (NULL == descriptor) + { + MALI_DEBUG_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd)); + mali_dma_buf_release(NULL, mem); + return -ENOMEM; + } + + descriptor->size = args.size; + descriptor->mapping = NULL; + descriptor->mali_address = args.mali_address; + descriptor->mali_addr_mapping_info = (void*)session; + descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->lock = session->memory_lock; + + if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) + { + descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; + } + _mali_osk_list_init( &descriptor->list ); + + /* Get descriptor mapping for memory. */ + if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd)); + _mali_osk_free(descriptor); + mali_dma_buf_release(NULL, mem); + return -EFAULT; + } + + MALI_DEBUG_ASSERT(0 < md); + + external_memory_allocator.allocate = mali_dma_buf_commit; + external_memory_allocator.allocate_page_table_block = NULL; + external_memory_allocator.ctx = mem; + external_memory_allocator.name = "DMA-BUF Memory"; + external_memory_allocator.next = NULL; + + /* Map memory into session's Mali virtual address space. */ + _mali_osk_lock_wait(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(mali_mem_get_memory_engine(), descriptor, &external_memory_allocator, NULL)) + { + _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + + MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd)); + mali_descriptor_mapping_free(session->descriptor_mapping, md); + mali_dma_buf_release(NULL, mem); + return -ENOMEM; + } + _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); + + /* Return stuff to user space */ + if (0 != put_user(md, &user_arg->cookie)) + { + /* Roll back */ + MALI_DEBUG_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd)); + mali_descriptor_mapping_free(session->descriptor_mapping, md); + mali_dma_buf_release(NULL, mem); + return -EFAULT; + } + + return 0; +} + +int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg) +{ + int ret = 0; + _mali_uk_release_dma_buf_s args; + mali_memory_allocation *descriptor; + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) + { + return -EFAULT; + } + + MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release descriptor cookie %d\n", args.cookie)); + + _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie); + + if (NULL != descriptor) + { + MALI_DEBUG_PRINT(3, ("Mali DMA-buf: Releasing dma-buf at mali address %x\n", descriptor->mali_address)); + + /* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */ + mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor); + + _mali_osk_free(descriptor); + } + else + { + MALI_DEBUG_PRINT_ERROR(("Invalid memory descriptor %d used to release dma-buf\n", args.cookie)); + ret = -EINVAL; + } + + _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); + + /* Return the error that _mali_ukk_map_external_ump_mem produced */ + return ret; +} + +int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg) +{ + _mali_uk_dma_buf_get_size_s args; + int fd; + struct dma_buf *buf; + + /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ + if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) + { + return -EFAULT; + } + + /* Do DMA-BUF stuff */ + fd = args.mem_fd; + + buf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(buf)) + { + MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd)); + return PTR_RET(buf); + } + + if (0 != put_user(buf->size, &user_arg->size)) + { + dma_buf_put(buf); + return -EFAULT; + } + + dma_buf_put(buf); + + return 0; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h index ee9a0ed..1af3efc 100644 --- a/drivers/media/video/samsung/mali/linux/mali_dma_buf.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_dma_buf.h @@ -17,10 +17,21 @@ extern "C" #endif #include "mali_osk.h" +#include "common/mali_pp_job.h" + +struct mali_dma_buf_attachment; int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *arg); int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *arg); int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *arg); +int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 *offset, u32 flags); +void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem); +void mali_dma_buf_release(void *ctx, void *handle); + +#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) +int mali_dma_buf_map_job(struct mali_pp_job *job); +void mali_dma_buf_unmap_job(struct mali_pp_job *job); +#endif #ifdef __cplusplus } diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.c index 233c0ca..f337d09 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.c @@ -17,6 +17,12 @@ #include <linux/cdev.h> /* character device definitions */ #include <linux/mm.h> /* memory manager definitions */ #include <linux/mali/mali_utgard_ioctl.h> +#include <linux/version.h> +#include <linux/device.h> +#include "mali_kernel_license.h" +#include <linux/platform_device.h> +#include <linux/miscdevice.h> +#include <linux/mali/mali_utgard.h> #include "mali_kernel_common.h" #include "mali_session.h" #include "mali_kernel_core.h" @@ -24,24 +30,27 @@ #include "mali_kernel_linux.h" #include "mali_ukk.h" #include "mali_ukk_wrappers.h" -#include "mali_kernel_pm.h" #include "mali_kernel_sysfs.h" -#include "mali_platform.h" +#include "mali_pm.h" #include "mali_kernel_license.h" #include "mali_dma_buf.h" +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) +#include "mali_profiling_internal.h" +#endif +/* MALI_SEC */ +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) || defined(CONFIG_CPU_EXYNOS4210) +#include "../platform/pegasus-m400/exynos4_pmm.h" +#elif defined(CONFIG_SOC_EXYNOS3470) +#include "../platform/exynos4270/exynos4_pmm.h" +#endif /* Streamline support for the Mali driver */ -#if defined(CONFIG_TRACEPOINTS) && MALI_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_MALI400_PROFILING) /* Ask Linux to create the tracepoints */ #define CREATE_TRACE_POINTS #include "mali_linux_trace.h" #endif /* CONFIG_TRACEPOINTS */ -static _mali_osk_errcode_t initialize_kernel_device(void); -static int initialize_sysfs(void); -static void terminate_kernel_device(void); - - /* from the __malidrv_build_info.c file that is generated during build */ extern const char *__malidrv_build_info(void); @@ -50,18 +59,6 @@ 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 */ -#if MALI_MAJOR_PREDEFINE -int mali_major = 244; -#else -int mali_major = 0; -#endif -module_param(mali_major, int, S_IRUGO); /* r--r--r-- */ -MODULE_PARM_DESC(mali_major, "Device major number"); - -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"); - 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"); @@ -69,120 +66,121 @@ 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"); -#if MALI_TIMELINE_PROFILING_ENABLED +extern unsigned int mali_dedicated_mem_start; +module_param(mali_dedicated_mem_start, uint, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory."); + +extern unsigned int mali_dedicated_mem_size; +module_param(mali_dedicated_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory."); + +extern unsigned int mali_shared_mem_size; +module_param(mali_shared_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory."); + +#if defined(CONFIG_MALI400_PROFILING) extern int mali_boot_profiling; module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH); MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization"); #endif +extern int mali_max_pp_cores_group_1; +module_param(mali_max_pp_cores_group_1, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_max_pp_cores_group_1, "Limit the number of PP cores to use from first PP group."); + +extern int mali_max_pp_cores_group_2; +module_param(mali_max_pp_cores_group_2, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_max_pp_cores_group_2, "Limit the number of PP cores to use from second PP group (Mali-450 only)."); + /* Export symbols from common code: mali_user_settings.c */ #include "mali_user_settings_db.h" EXPORT_SYMBOL(mali_set_user_setting); EXPORT_SYMBOL(mali_get_user_setting); -#if MALI_DVFS_ENABLED -extern int mali_dvfs_control; -module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS"); -#if defined(CONFIG_CPU_EXYNOS4210) -#else -extern int step0_clk; -module_param(step0_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step0_clk, "Mali Current step0_clk"); -#ifdef DEBUG -extern int step0_vol; -module_param(step0_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step0_vol, "Mali Current step0_vol"); -#endif -#if (MALI_DVFS_STEPS > 1) -extern int step1_clk; -module_param(step1_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_clk, "Mali Current step1_clk"); - -extern int step0_up; -module_param(step0_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step0_up, "Mali Current step0_up"); - -extern int step1_down; -module_param(step1_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_down, "Mali Current step1_down"); -#ifdef DEBUG -extern int step1_vol; -module_param(step1_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_vol, "Mali Current step1_vol"); -#endif +static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ -#if (MALI_DVFS_STEPS > 2) -extern int step2_clk; -module_param(step2_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_clk, "Mali Current step2_clk"); - -extern int step1_up; -module_param(step1_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step1_up, "Mali Current step1_up"); - -extern int step2_down; -module_param(step2_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_down, "Mali Current step2_down"); -#ifdef DEBUG -extern int step2_vol; -module_param(step2_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_vol, "Mali Current step2_vol"); -#endif +/* This driver only supports one Mali device, and this variable stores this single platform device */ +struct platform_device *mali_platform_device = NULL; -#if (MALI_DVFS_STEPS > 3) -extern int step3_clk; -module_param(step3_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step3_clk, "Mali Current step3_clk"); - -extern int step2_up; -module_param(step2_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step2_up, "Mali Current step2_up"); - -extern int step3_down; -module_param(step3_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step3_down, "Mali Current step3_down"); -#ifdef DEBUG -extern int step3_vol; -module_param(step3_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ -MODULE_PARM_DESC(step3_vol, "Mali Current step3_vol"); -#endif -#endif -#endif -#endif -#endif +/* This driver only supports one Mali device, and this variable stores the exposed misc device (/dev/mali) */ +static struct miscdevice mali_miscdevice = { 0, }; -extern int mali_gpu_clk; -module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ -MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock"); +static int mali_miscdevice_register(struct platform_device *pdev); +static void mali_miscdevice_unregister(void); -extern int mali_gpu_vol; -module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ -MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage"); - -extern int gpu_power_state; -module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ -MODULE_PARM_DESC(gpu_power_state, "Mali Power State"); +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); +static int mali_probe(struct platform_device *pdev); +static int mali_remove(struct platform_device *pdev); -static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ +static int mali_driver_suspend_scheduler(struct device *dev); +static int mali_driver_resume_scheduler(struct device *dev); -/* the mali device */ -static struct mali_dev device; +#ifdef CONFIG_PM_RUNTIME +static int mali_driver_runtime_suspend(struct device *dev); +static int mali_driver_runtime_resume(struct device *dev); +static int mali_driver_runtime_idle(struct device *dev); +#endif +#if defined(MALI_FAKE_PLATFORM_DEVICE) +extern int mali_platform_device_register(void); +extern int mali_platform_device_unregister(void); +#endif -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); +/* Linux power management operations provided by the Mali device driver */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) +struct pm_ext_ops mali_dev_ext_pm_ops = +{ + .base = + { + .suspend = mali_driver_suspend_scheduler, + .resume = mali_driver_resume_scheduler, + .freeze = mali_driver_suspend_scheduler, + .thaw = mali_driver_resume_scheduler, + }, +}; #else -static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +static const struct dev_pm_ops mali_dev_pm_ops = +{ +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = mali_driver_runtime_suspend, + .runtime_resume = mali_driver_runtime_resume, + .runtime_idle = mali_driver_runtime_idle, +#endif + .suspend = mali_driver_suspend_scheduler, + .resume = mali_driver_resume_scheduler, + .freeze = mali_driver_suspend_scheduler, + .thaw = mali_driver_resume_scheduler, +}; #endif -static int mali_mmap(struct file * filp, struct vm_area_struct * vma); +/* The Mali device driver struct */ +static struct platform_driver mali_platform_driver = +{ + .probe = mali_probe, + .remove = mali_remove, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) + .pm = &mali_dev_ext_pm_ops, +#endif + .driver = + { + .name = "mali_dev", /* MALI_SEC MALI_GPU_NAME_UTGARD, */ + .owner = THIS_MODULE, + .bus = &platform_bus_type, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + .pm = &mali_dev_pm_ops, +#endif + }, +}; -/* Linux char file operations provided by the Mali module */ +/* Linux misc device operations (/dev/mali) */ struct file_operations mali_fops = { .owner = THIS_MODULE, @@ -196,140 +194,204 @@ struct file_operations mali_fops = .mmap = mali_mmap }; - -int mali_driver_init(void) +int mali_module_init(void) { - int ret = 0; + int err = 0; - MALI_DEBUG_PRINT(2, ("\n")); MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION)); MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__)); MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING)); - ret = _mali_dev_platform_register(); - if (0 != ret) goto platform_register_failed; - ret = map_errcode(initialize_kernel_device()); - if (0 != ret) goto initialize_kernel_device_failed; + /* Initialize module wide settings */ + mali_osk_low_level_mem_init(); - ret = map_errcode(mali_platform_init()); - if (0 != ret) goto platform_init_failed; +#if defined(MALI_FAKE_PLATFORM_DEVICE) + MALI_DEBUG_PRINT(2, ("mali_module_init() registering device\n")); + err = mali_platform_device_register(); + if (0 != err) + { + return err; + } +#endif - mali_osk_low_level_mem_init(); + MALI_DEBUG_PRINT(2, ("mali_module_init() registering driver\n")); - ret = map_errcode(mali_initialize_subsystems()); - if (0 != ret) goto initialize_subsystems_failed; + err = platform_driver_register(&mali_platform_driver); - ret = initialize_sysfs(); - if (0 != ret) goto initialize_sysfs_failed; + if (0 != err) + { + MALI_DEBUG_PRINT(2, ("mali_module_init() Failed to register driver (%d)\n", err)); +#if defined(MALI_FAKE_PLATFORM_DEVICE) + mali_platform_device_unregister(); +#endif + mali_platform_device = NULL; + return err; + } + +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) + err = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); + if (0 != err) + { + /* No biggie if we wheren't able to initialize the profiling */ + MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); + } +#endif MALI_PRINT(("Mali device driver loaded\n")); return 0; /* Success */ - - /* Error handling */ -initialize_sysfs_failed: - mali_terminate_subsystems(); -initialize_subsystems_failed: - mali_osk_low_level_mem_term(); - mali_platform_deinit(); -platform_init_failed: - terminate_kernel_device(); -initialize_kernel_device_failed: - _mali_dev_platform_unregister(); -platform_register_failed: - return ret; } -void mali_driver_exit(void) +void mali_module_exit(void) { - MALI_DEBUG_PRINT(2, ("\n")); MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION)); - /* No need to terminate sysfs, this will be done automatically along with device termination */ - - mali_terminate_subsystems(); - - mali_osk_low_level_mem_term(); + MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering driver\n")); - mali_platform_deinit(); +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) + _mali_internal_profiling_term(); +#endif - terminate_kernel_device(); - _mali_dev_platform_unregister(); + platform_driver_unregister(&mali_platform_driver); -#if MALI_LICENSE_IS_GPL - /* @@@@ clean up the work queues! This should not be terminated here, since it isn't inited in the function above! */ - flush_workqueue(mali_wq); - destroy_workqueue(mali_wq); - mali_wq = NULL; +#if defined(MALI_FAKE_PLATFORM_DEVICE) + MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering device\n")); + mali_platform_device_unregister(); #endif + mali_osk_low_level_mem_term(); + MALI_PRINT(("Mali device driver unloaded\n")); } -static int initialize_kernel_device(void) +static int mali_probe(struct platform_device *pdev) { 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 + + MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name)); + + if (NULL != mali_platform_device) { - /* use load time defined major number */ - dev = MKDEV(mali_major, 0); - err = register_chrdev_region(dev, 1/*count*/, mali_dev_name); + /* Already connected to a device, return error */ + MALI_PRINT_ERROR(("mali_probe(): The Mali driver is already connected with a Mali device.")); + return -EEXIST; } - if (err) + mali_platform_device = pdev; + + if (_MALI_OSK_ERR_OK == _mali_osk_wq_init()) { - goto init_chrdev_err; + /* Initialize the Mali GPU HW specified by pdev */ + if (_MALI_OSK_ERR_OK == mali_initialize_subsystems()) + { + /* Register a misc device (so we are accessible from user space) */ + err = mali_miscdevice_register(pdev); + if (0 == err) + { + /* Setup sysfs entries */ + err = mali_sysfs_register(mali_dev_name); + if (0 == err) + { + MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name)); + return 0; + } + else + { + MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries")); + } + mali_miscdevice_unregister(); + } + else + { + MALI_PRINT_ERROR(("mali_probe(): failed to register Mali misc device.")); + } + mali_terminate_subsystems(); + } + else + { + MALI_PRINT_ERROR(("mali_probe(): Failed to initialize Mali device driver.")); + } + _mali_osk_wq_term(); } - memset(&device, 0, sizeof(device)); + mali_platform_device = NULL; + return -EFAULT; +} - /* initialize our char dev data */ - cdev_init(&device.cdev, &mali_fops); - device.cdev.owner = THIS_MODULE; - device.cdev.ops = &mali_fops; +static int mali_remove(struct platform_device *pdev) +{ + MALI_DEBUG_PRINT(2, ("mali_remove() called for platform device %s\n", pdev->name)); + mali_sysfs_unregister(); + mali_miscdevice_unregister(); + mali_terminate_subsystems(); + _mali_osk_wq_term(); + mali_platform_device = NULL; + return 0; +} - /* register char dev with the kernel */ - err = cdev_add(&device.cdev, dev, 1/*count*/); - if (err) +static int mali_miscdevice_register(struct platform_device *pdev) +{ + int err; + + mali_miscdevice.minor = MISC_DYNAMIC_MINOR; + mali_miscdevice.name = mali_dev_name; + mali_miscdevice.fops = &mali_fops; + mali_miscdevice.parent = get_device(&pdev->dev); + + err = misc_register(&mali_miscdevice); + if (0 != err) { - goto init_cdev_err; + MALI_PRINT_ERROR(("Failed to register misc device, misc_register() returned %d\n", err)); } - /* Success! */ - return 0; - -init_cdev_err: - unregister_chrdev_region(dev, 1/*count*/); -init_chrdev_err: return err; } -static int initialize_sysfs(void) +static void mali_miscdevice_unregister(void) { - dev_t dev = MKDEV(mali_major, 0); - return mali_sysfs_register(&device, dev, mali_dev_name); + misc_deregister(&mali_miscdevice); } -static void terminate_kernel_device(void) +static int mali_driver_suspend_scheduler(struct device *dev) { - dev_t dev = MKDEV(mali_major, 0); + mali_pm_os_suspend(); + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP); + return 0; +} - mali_sysfs_unregister(&device, dev, mali_dev_name); +static int mali_driver_resume_scheduler(struct device *dev) +{ + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON); + mali_pm_os_resume(); + return 0; +} + +#ifdef CONFIG_PM_RUNTIME +static int mali_driver_runtime_suspend(struct device *dev) +{ + mali_pm_runtime_suspend(); + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_LIGHT_SLEEP); + return 0; +} - /* unregister char device */ - cdev_del(&device.cdev); - /* free major */ - unregister_chrdev_region(dev, 1/*count*/); - return; +static int mali_driver_runtime_resume(struct device *dev) +{ + /* MALI_SEC */ + mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON); + mali_pm_runtime_resume(); + return 0; } +static int mali_driver_runtime_idle(struct device *dev) +{ + /* Nothing to do */ + return 0; +} +#endif + /** @note munmap handler is done by vma close handler */ static int mali_mmap(struct file * filp, struct vm_area_struct * vma) { @@ -376,7 +438,11 @@ static int mali_open(struct inode *inode, struct file *filp) _mali_osk_errcode_t err; /* input validation */ - if (0 != MINOR(inode->i_rdev)) return -ENODEV; + if (mali_miscdevice.minor != iminor(inode)) + { + MALI_PRINT_ERROR(("mali_open() Minor does not match\n")); + return -ENODEV; + } /* allocated struct to track this session */ err = _mali_ukk_open((void **)&session_data); @@ -395,8 +461,12 @@ 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; + /* input validation */ + if (mali_miscdevice.minor != iminor(inode)) + { + MALI_PRINT_ERROR(("mali_release() Minor does not match\n")); + return -ENODEV; + } err = _mali_ukk_close((void **)&filp->private_data); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); @@ -467,7 +537,7 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg); break; -#if MALI_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_PROFILING) case MALI_IOC_PROFILING_START: err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg); break; @@ -520,6 +590,10 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg); break; + case MALI_IOC_MEM_WRITE_SAFE: + err = mem_write_safe_wrapper(session_data, (_mali_uk_mem_write_safe_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; @@ -536,7 +610,7 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg); break; -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#if defined(CONFIG_MALI400_UMP) case MALI_IOC_MEM_ATTACH_UMP: err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg); @@ -569,6 +643,8 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, break; #else + case MALI_IOC_MEM_ATTACH_DMA_BUF: /* FALL-THROUGH */ + case MALI_IOC_MEM_RELEASE_DMA_BUF: /* FALL-THROUGH */ case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */ MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n")); err = -ENOTTY; @@ -611,6 +687,26 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg); break; + case MALI_IOC_STREAM_CREATE: +#if defined(CONFIG_SYNC) + err = stream_create_wrapper(session_data, (_mali_uk_stream_create_s __user *)arg); + break; +#endif + case MALI_IOC_FENCE_CREATE_EMPTY: +#if defined(CONFIG_SYNC) + err = sync_fence_create_empty_wrapper(session_data, (_mali_uk_fence_create_empty_s __user *)arg); + break; +#endif + case MALI_IOC_FENCE_VALIDATE: +#if defined(CONFIG_SYNC) + err = sync_fence_validate_wrapper(session_data, (_mali_uk_fence_validate_s __user *)arg); + break; +#else + MALI_DEBUG_PRINT(2, ("Sync objects not supported\n")); + err = -ENOTTY; + break; +#endif + case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */ case MALI_IOC_MEM_FREE_BIG_BLOCK: MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n")); @@ -626,8 +722,8 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, } -module_init(mali_driver_init); -module_exit(mali_driver_exit); +module_init(mali_module_init); +module_exit(mali_module_exit); MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE); MODULE_AUTHOR("ARM Ltd."); diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.h index 22dc9a4..8bc4c39 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_linux.h @@ -20,13 +20,7 @@ extern "C" #include "mali_kernel_license.h" #include "mali_osk.h" -struct mali_dev -{ - struct cdev cdev; -#if MALI_LICENSE_IS_GPL - struct class * mali_class; -#endif -}; +extern struct platform_device *mali_platform_device; #if MALI_LICENSE_IS_GPL /* Defined in mali_osk_irq.h */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.c index e2dc17b..fa1fa9c 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.c @@ -20,7 +20,6 @@ #include <linux/module.h> #include "mali_kernel_license.h" #include "mali_kernel_common.h" -#include "mali_kernel_linux.h" #include "mali_ukk.h" #if MALI_LICENSE_IS_GPL @@ -29,13 +28,16 @@ #include <linux/debugfs.h> #include <asm/uaccess.h> #include <linux/module.h> +#include <linux/mali/mali_utgard.h> #include "mali_kernel_sysfs.h" -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) #include <linux/slab.h> #include "mali_osk_profiling.h" #endif + +#include <linux/mali/mali_utgard.h> #include "mali_pm.h" -#include "mali_cluster.h" +#include "mali_pmu.h" #include "mali_group.h" #include "mali_gp.h" #include "mali_pp.h" @@ -43,11 +45,13 @@ #include "mali_hw_core.h" #include "mali_kernel_core.h" #include "mali_user_settings_db.h" -#include "mali_device_pause_resume.h" +#include "mali_profiling_internal.h" +#include "mali_gp_job.h" +#include "mali_pp_job.h" +#include "mali_pp_scheduler.h" #define POWER_BUFFER_SIZE 3 -struct device *mali_device; static struct dentry *mali_debugfs_dir = NULL; typedef enum @@ -66,8 +70,7 @@ static const char* const mali_power_events[_MALI_MAX_EVENTS] = { [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume", }; -static u32 virtual_power_status_register=0; -static char pwr_buf[POWER_BUFFER_SIZE]; +static mali_bool power_always_on_enabled = MALI_FALSE; static int open_copy_private_data(struct inode *inode, struct file *filp) { @@ -75,20 +78,104 @@ static int open_copy_private_data(struct inode *inode, struct file *filp) return 0; } +static ssize_t group_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + struct mali_group *group; + + group = (struct mali_group *)filp->private_data; + MALI_DEBUG_ASSERT_POINTER(group); + + r = sprintf(buffer, "%u\n", mali_group_is_enabled(group) ? 1 : 0); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static ssize_t group_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + unsigned long val; + struct mali_group *group; + + group = (struct mali_group *)filp->private_data; + MALI_DEBUG_ASSERT_POINTER(group); + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + r = strict_strtoul(&buffer[0], 10, &val); + if (0 != r) + { + return -EINVAL; + } + + switch (val) + { + case 1: + mali_group_enable(group); + break; + case 0: + mali_group_disable(group); + break; + default: + return -EINVAL; + break; + } + + *offp += count; + return count; +} + +static const struct file_operations group_enabled_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = group_enabled_read, + .write = group_enabled_write, +}; + +static ssize_t hw_core_base_addr_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + struct mali_hw_core *hw_core; + + hw_core = (struct mali_hw_core *)filp->private_data; + MALI_DEBUG_ASSERT_POINTER(hw_core); + + r = sprintf(buffer, "0x%08X\n", hw_core->phys_addr); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations hw_core_base_addr_fops = { + .owner = THIS_MODULE, + .open = open_copy_private_data, + .read = hw_core_base_addr_read, +}; + static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) { char buf[64]; int r; u32 val; - struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; if (0 == src_id) { - val = mali_gp_core_get_counter_src0(gp_core); + val = mali_gp_job_get_gp_counter_src0(); } else { - val = mali_gp_core_get_counter_src1(gp_core); + val = mali_gp_job_get_gp_counter_src1(); } if (MALI_HW_CORE_NO_COUNTER == val) @@ -104,7 +191,6 @@ static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, si static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id) { - struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data; char buf[64]; long val; int ret; @@ -135,14 +221,14 @@ static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *u if (0 == src_id) { - if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) + if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val)) { return 0; } } else { - if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) + if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val)) { return 0; } @@ -157,8 +243,8 @@ static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *u char buf[64]; long val; int ret; - u32 ci; - struct mali_cluster *cluster; + u32 num_groups; + int i; if (cnt >= sizeof(buf)) { @@ -184,41 +270,29 @@ static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *u val = MALI_HW_CORE_NO_COUNTER; } - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) { - struct mali_gp_core *gp_core = mali_group_get_gp_core(group); - if (NULL != gp_core) + if (0 == src_id) { - if (0 == src_id) + if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val)) { - if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val)) - { - return 0; - } + return 0; } - else + } + else + { + if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val)) { - if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val)) - { - return 0; - } - } + return 0; + } } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); } *gpos += cnt; @@ -284,15 +358,14 @@ static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, si char buf[64]; int r; u32 val; - struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; if (0 == src_id) { - val = mali_pp_core_get_counter_src0(pp_core); + val = mali_pp_job_get_pp_counter_src0(); } else { - val = mali_pp_core_get_counter_src1(pp_core); + val = mali_pp_job_get_pp_counter_src1(); } if (MALI_HW_CORE_NO_COUNTER == val) @@ -308,7 +381,6 @@ static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, si static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) { - struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data; char buf[64]; long val; int ret; @@ -339,14 +411,14 @@ static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *u if (0 == src_id) { - if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) + if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val)) { return 0; } } else { - if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) + if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val)) { return 0; } @@ -361,8 +433,8 @@ static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *u char buf[64]; long val; int ret; - u32 ci; - struct mali_cluster *cluster; + u32 num_groups; + int i; if (cnt >= sizeof(buf)) { @@ -388,41 +460,29 @@ static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *u val = MALI_HW_CORE_NO_COUNTER; } - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) { - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - if (NULL != pp_core) + if (0 == src_id) { - if (0 == src_id) + if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val)) { - if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val)) - { - return 0; - } + return 0; } - else + } + else + { + if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val)) { - if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val)) - { - return 0; - } - } + return 0; + } } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); } *ppos += cnt; @@ -483,11 +543,6 @@ static const struct file_operations pp_all_counter_src1_fops = { .write = pp_all_counter_src1_write, }; - - - - - static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id) { char buf[64]; @@ -679,71 +734,95 @@ static const struct file_operations l2_all_counter_src1_fops = { .write = l2_all_counter_src1_write, }; -static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - - memset(pwr_buf,0,POWER_BUFFER_SIZE); - virtual_power_status_register = 0; + unsigned long val; + int ret; + char buf[32]; + + cnt = min(cnt, sizeof(buf) - 1); + if (copy_from_user(buf, ubuf, cnt)) + { + return -EFAULT; + } + buf[cnt] = '\0'; + + ret = strict_strtoul(buf, 10, &val); + if (0 != ret) + { + return ret; + } + + /* Update setting (not exactly thread safe) */ + if (1 == val && MALI_FALSE == power_always_on_enabled) + { + power_always_on_enabled = MALI_TRUE; + _mali_osk_pm_dev_ref_add(); + } + else if (0 == val && MALI_TRUE == power_always_on_enabled) + { + power_always_on_enabled = MALI_FALSE; + _mali_osk_pm_dev_ref_dec(); + } + + *ppos += cnt; + return cnt; +} + +static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + if (MALI_TRUE == power_always_on_enabled) + { + return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2); + } + else + { + return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2); + } +} + +static const struct file_operations power_always_on_fops = { + .owner = THIS_MODULE, + .read = power_always_on_read, + .write = power_always_on_write, +}; + +static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND]))) { mali_pm_os_suspend(); - /* @@@@ assuming currently suspend is successful later on to tune as per previous*/ - virtual_power_status_register =1; } else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME]))) { mali_pm_os_resume(); - - /* @@@@ assuming currently resume is successful later on to tune as per previous */ - virtual_power_status_register = 1; } else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]))) { - mali_bool power_on; - mali_dev_pause(&power_on); - if (!power_on) - { - virtual_power_status_register = 2; - mali_dev_resume(); - } - else - { - /* @@@@ assuming currently resume is successful later on to tune as per previous */ - virtual_power_status_register =1; - } + mali_dev_pause(); } else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]))) { mali_dev_resume(); - /* @@@@ assuming currently resume is successful later on to tune as per previous */ - virtual_power_status_register = 1; - } *ppos += cnt; - sprintf(pwr_buf, "%d",virtual_power_status_register); return cnt; } -static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) -{ - return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE); -} - -static loff_t power_events_seek(struct file *file, loff_t offset, int orig) +static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig) { file->f_pos = offset; return 0; } -static const struct file_operations power_events_fops = { +static const struct file_operations power_power_events_fops = { .owner = THIS_MODULE, - .read = power_events_read, - .write = power_events_write, - .llseek = power_events_seek, + .write = power_power_events_write, + .llseek = power_power_events_seek, }; - #if MALI_STATE_TRACKING static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) { @@ -783,14 +862,13 @@ static const struct file_operations mali_seq_internal_state_fops = { }; #endif /* MALI_STATE_TRACKING */ - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { char buf[64]; int r; - r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0); + r = sprintf(buf, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0); return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } @@ -823,16 +901,16 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */ /* check if we are already recording */ - if (MALI_TRUE == _mali_osk_profiling_is_recording()) + if (MALI_TRUE == _mali_internal_profiling_is_recording()) { MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n")); return -EFAULT; } /* check if we need to clear out an old recording first */ - if (MALI_TRUE == _mali_osk_profiling_have_recording()) + if (MALI_TRUE == _mali_internal_profiling_have_recording()) { - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear()) + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear()) { MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n")); return -EFAULT; @@ -840,7 +918,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf } /* start recording profiling data */ - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) { MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n")); return -EFAULT; @@ -852,7 +930,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf { /* stop recording profiling data */ u32 count = 0; - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count)) + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) { MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n")); return -EFAULT; @@ -876,7 +954,7 @@ static void *profiling_events_start(struct seq_file *s, loff_t *pos) loff_t *spos; /* check if we have data avaiable */ - if (MALI_TRUE != _mali_osk_profiling_have_recording()) + if (MALI_TRUE != _mali_internal_profiling_have_recording()) { return NULL; } @@ -896,13 +974,13 @@ static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos) loff_t *spos = v; /* check if we have data avaiable */ - if (MALI_TRUE != _mali_osk_profiling_have_recording()) + if (MALI_TRUE != _mali_internal_profiling_have_recording()) { return NULL; } /* check if the next entry actually is avaiable */ - if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1)) + if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) { return NULL; } @@ -927,7 +1005,7 @@ static int profiling_events_show(struct seq_file *seq_file, void *v) index = (u32)*spos; /* Retrieve all events */ - if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, ×tamp, &event_id, data)) + if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data)) { seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); return 0; @@ -936,6 +1014,128 @@ static int profiling_events_show(struct seq_file *seq_file, void *v) return 0; } +static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v) +{ + #define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7)) + + static u64 start_time = 0; + loff_t *spos = v; + u32 index; + u64 timestamp; + u32 event_id; + u32 data[5]; + + index = (u32)*spos; + + /* Retrieve all events */ + if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data)) + { + seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); + + if (0 == index) + { + start_time = timestamp; + } + + seq_printf(seq_file, "[%06u] ", index); + + switch(event_id & 0x0F000000) + { + case MALI_PROFILING_EVENT_TYPE_SINGLE: + seq_printf(seq_file, "SINGLE | "); + break; + case MALI_PROFILING_EVENT_TYPE_START: + seq_printf(seq_file, "START | "); + break; + case MALI_PROFILING_EVENT_TYPE_STOP: + seq_printf(seq_file, "STOP | "); + break; + case MALI_PROFILING_EVENT_TYPE_SUSPEND: + seq_printf(seq_file, "SUSPEND | "); + break; + case MALI_PROFILING_EVENT_TYPE_RESUME: + seq_printf(seq_file, "RESUME | "); + break; + default: + seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24); + break; + } + + switch(event_id & 0x00FF0000) + { + case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE: + seq_printf(seq_file, "SW | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_GP0: + seq_printf(seq_file, "GP0 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP0: + seq_printf(seq_file, "PP0 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP1: + seq_printf(seq_file, "PP1 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP2: + seq_printf(seq_file, "PP2 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP3: + seq_printf(seq_file, "PP3 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP4: + seq_printf(seq_file, "PP4 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP5: + seq_printf(seq_file, "PP5 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP6: + seq_printf(seq_file, "PP6 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_PP7: + seq_printf(seq_file, "PP7 | "); + break; + case MALI_PROFILING_EVENT_CHANNEL_GPU: + seq_printf(seq_file, "GPU | "); + break; + default: + seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16); + break; + } + + if (MALI_EVENT_ID_IS_HW(event_id)) + { + if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP)) + { + switch(event_id & 0x0000FFFF) + { + case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL: + seq_printf(seq_file, "PHYSICAL | "); + break; + case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL: + seq_printf(seq_file, "VIRTUAL | "); + break; + default: + seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF); + break; + } + } + else + { + seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF); + } + } + else + { + seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF); + } + + seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time); + + return 0; + } + + return 0; +} + static const struct seq_operations profiling_events_seq_ops = { .start = profiling_events_start, .next = profiling_events_next, @@ -955,6 +1155,27 @@ static const struct file_operations profiling_events_fops = { .llseek = seq_lseek, .release = seq_release, }; + +static const struct seq_operations profiling_events_human_readable_seq_ops = { + .start = profiling_events_start, + .next = profiling_events_next, + .stop = profiling_events_stop, + .show = profiling_events_show_human_readable +}; + +static int profiling_events_human_readable_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &profiling_events_human_readable_seq_ops); +} + +static const struct file_operations profiling_events_human_readable_fops = { + .owner = THIS_MODULE, + .open = profiling_events_human_readable_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + #endif static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -972,6 +1193,51 @@ static const struct file_operations memory_usage_fops = { .read = memory_used_read, }; +static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 uval= _mali_ukk_utilization_gp_pp(); + + r = snprintf(buf, 64, "%u\n", uval); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 uval= _mali_ukk_utilization_gp(); + + r = snprintf(buf, 64, "%u\n", uval); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + +static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char buf[64]; + size_t r; + u32 uval= _mali_ukk_utilization_pp(); + + r = snprintf(buf, 64, "%u\n", uval); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); +} + + +static const struct file_operations utilization_gp_pp_fops = { + .owner = THIS_MODULE, + .read = utilization_gp_pp_read, +}; + +static const struct file_operations utilization_gp_fops = { + .owner = THIS_MODULE, + .read = utilization_gp_read, +}; + +static const struct file_operations utilization_pp_fops = { + .owner = THIS_MODULE, + .read = utilization_pp_read, +}; static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { @@ -1038,23 +1304,191 @@ static int mali_sysfs_user_settings_register(void) return 0; } -int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +static ssize_t pmu_power_down_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int ret; + char buffer[32]; + unsigned long val; + struct mali_pmu_core *pmu; + _mali_osk_errcode_t err; + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + ret = strict_strtoul(&buffer[0], 10, &val); + if (0 != ret) + { + return -EINVAL; + } + + pmu = mali_pmu_get_global_pmu_core(); + MALI_DEBUG_ASSERT_POINTER(pmu); + + err = mali_pmu_power_down(pmu, val); + if (_MALI_OSK_ERR_OK != err) + { + return -EINVAL; + } + + *offp += count; + return count; +} + +static ssize_t pmu_power_up_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) +{ + int ret; + char buffer[32]; + unsigned long val; + struct mali_pmu_core *pmu; + _mali_osk_errcode_t err; + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; + + ret = strict_strtoul(&buffer[0], 10, &val); + if (0 != ret) + { + return -EINVAL; + } + + pmu = mali_pmu_get_global_pmu_core(); + MALI_DEBUG_ASSERT_POINTER(pmu); + + err = mali_pmu_power_up(pmu, val); + if (_MALI_OSK_ERR_OK != err) + { + return -EINVAL; + } + + *offp += count; + return count; +} + +static const struct file_operations pmu_power_down_fops = { + .owner = THIS_MODULE, + .write = pmu_power_down_write, +}; + +static const struct file_operations pmu_power_up_fops = { + .owner = THIS_MODULE, + .write = pmu_power_up_write, +}; + +static ssize_t pp_num_cores_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) { - int err = 0; + int ret; + char buffer[32]; + unsigned long val; + + if (count >= sizeof(buffer)) + { + return -ENOMEM; + } + + if (copy_from_user(&buffer[0], buf, count)) + { + return -EFAULT; + } + buffer[count] = '\0'; - device->mali_class = class_create(THIS_MODULE, mali_dev_name); - if (IS_ERR(device->mali_class)) + ret = strict_strtoul(&buffer[0], 10, &val); + if (0 != ret) { - err = PTR_ERR(device->mali_class); - goto init_class_err; + return -EINVAL; } - mali_device = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name); - if (IS_ERR(mali_device)) + + ret = mali_perf_set_num_pp_cores(val); + if (ret) { - err = PTR_ERR(mali_device); - goto init_mdev_err; + return ret; } + *offp += count; + return count; +} + +static ssize_t pp_num_cores_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + + r = sprintf(buffer, "%u\n", mali_pp_scheduler_get_num_cores_enabled()); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations pp_num_cores_enabled_fops = { + .owner = THIS_MODULE, + .write = pp_num_cores_enabled_write, + .read = pp_num_cores_enabled_read, +}; + +static ssize_t pp_num_cores_total_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r; + char buffer[64]; + + r = sprintf(buffer, "%u\n", mali_pp_scheduler_get_num_cores_total()); + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations pp_num_cores_total_fops = { + .owner = THIS_MODULE, + .read = pp_num_cores_total_read, +}; + + +static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) +{ + int r = 0; + char buffer[64]; + + switch (mali_kernel_core_get_product_id()) + { + case _MALI_PRODUCT_ID_MALI200: + r = sprintf(buffer, "Mali-200\n"); + break; + case _MALI_PRODUCT_ID_MALI300: + r = sprintf(buffer, "Mali-300\n"); + break; + case _MALI_PRODUCT_ID_MALI400: + r = sprintf(buffer, "Mali-400 MP\n"); + break; + case _MALI_PRODUCT_ID_MALI450: + r = sprintf(buffer, "Mali-450 MP\n"); + break; + case _MALI_PRODUCT_ID_UNKNOWN: + return -EINVAL; + break; + }; + + return simple_read_from_buffer(buf, count, offp, buffer, r); +} + +static const struct file_operations version_fops = { + .owner = THIS_MODULE, + .read = version_read, +}; + +int mali_sysfs_register(const char *mali_dev_name) +{ mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL); if(ERR_PTR(-ENODEV) == mali_debugfs_dir) { @@ -1066,63 +1500,67 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev if(NULL != mali_debugfs_dir) { /* Debugfs directory created successfully; create files now */ + struct dentry *mali_pmu_dir; struct dentry *mali_power_dir; struct dentry *mali_gp_dir; struct dentry *mali_pp_dir; struct dentry *mali_l2_dir; -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) struct dentry *mali_profiling_dir; #endif + debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops); + + mali_pmu_dir = debugfs_create_dir("pmu", mali_debugfs_dir); + if (NULL != mali_pmu_dir) + { + debugfs_create_file("power_down", 0200, mali_pmu_dir, NULL, &pmu_power_down_fops); + debugfs_create_file("power_up", 0200, mali_pmu_dir, NULL, &pmu_power_up_fops); + } + mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir); if (mali_power_dir != NULL) { - debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops); + /* MALI_SEC : 0600 -> 0400 */ + debugfs_create_file("always_on", 0400, mali_power_dir, NULL, &power_always_on_fops); + /* MALI_SEC : 0200 -> 0400 */ + debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_power_events_fops); } mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir); if (mali_gp_dir != NULL) { struct dentry *mali_gp_all_dir; - u32 ci; - struct mali_cluster *cluster; + u32 num_groups; + int i; mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir); if (mali_gp_all_dir != NULL) { - debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops); - debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops); + debugfs_create_file("counter_src0", 0200, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0200, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops); } - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_gp_core *gp_core = mali_group_get_gp_core(group); + if (NULL != gp_core) { - struct mali_gp_core *gp_core = mali_group_get_gp_core(group); - if (NULL != gp_core) + struct dentry *mali_gp_gpx_dir; + mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir); + if (NULL != mali_gp_gpx_dir) { - struct dentry *mali_gp_gpx_dir; - mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir); - if (NULL != mali_gp_gpx_dir) - { - debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops); - debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops); - } - break; /* no need to look for any other GP cores */ + debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops); + debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops); + debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops); } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); + break; /* no need to look for any other GP cores */ } - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); } } @@ -1130,46 +1568,42 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev if (mali_pp_dir != NULL) { struct dentry *mali_pp_all_dir; - u32 ci; - struct mali_cluster *cluster; + u32 num_groups; + int i; + + debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops); + debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops); mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir); if (mali_pp_all_dir != NULL) { - debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops); - debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops); + debugfs_create_file("counter_src0", 0200, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0200, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops); } - ci = 0; - cluster = mali_cluster_get_global_cluster(ci); - while (NULL != cluster) + num_groups = mali_group_get_glob_num_groups(); + for (i = 0; i < num_groups; i++) { - u32 gi = 0; - struct mali_group *group = mali_cluster_get_group(cluster, gi); - while (NULL != group) + struct mali_group *group = mali_group_get_glob_group(i); + + struct mali_pp_core *pp_core = mali_group_get_pp_core(group); + if (NULL != pp_core) { - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - if (NULL != pp_core) + char buf[16]; + struct dentry *mali_pp_ppx_dir; + _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core)); + mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir); + if (NULL != mali_pp_ppx_dir) { - char buf[16]; - struct dentry *mali_pp_ppx_dir; - _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core)); - mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir); - if (NULL != mali_pp_ppx_dir) + debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops); + debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops); + debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops); + if (!mali_group_is_virtual(group)) { - debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops); - debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops); + debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops); } } - - /* try next group */ - gi++; - group = mali_cluster_get_group(cluster, gi); } - - /* try next cluster */ - ci++; - cluster = mali_cluster_get_global_cluster(ci); } } @@ -1183,8 +1617,8 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir); if (mali_l2_all_dir != NULL) { - debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops); - debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops); + debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops); + debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops); } l2_id = 0; @@ -1199,6 +1633,7 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev { debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops); debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops); + debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops); } /* try next L2 */ @@ -1209,7 +1644,11 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops); -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED + debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops); + debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops); + debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops); + +#if defined(CONFIG_MALI400_INTERNAL_PROFILING) mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir); if (mali_profiling_dir != NULL) { @@ -1224,6 +1663,7 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev } debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops); debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops); + debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops); } #endif @@ -1241,28 +1681,18 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev /* Success! */ return 0; - - /* Error handling */ -init_mdev_err: - class_destroy(device->mali_class); -init_class_err: - - return err; } -int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +int mali_sysfs_unregister(void) { if(NULL != mali_debugfs_dir) { debugfs_remove_recursive(mali_debugfs_dir); } - device_destroy(device->mali_class, dev); - class_destroy(device->mali_class); - return 0; } -#else +#else /* MALI_LICENSE_IS_GPL */ /* Dummy implementations for non-GPL */ @@ -1271,10 +1701,9 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev return 0; } -int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +int mali_sysfs_unregister(void) { return 0; } - -#endif +#endif /* MALI_LICENSE_IS_GPL */ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.h index 24acca9..f970f0f 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_kernel_sysfs.h @@ -20,13 +20,8 @@ extern "C" #define MALI_PROC_DIR "driver/mali" -extern struct device *mali_device; -struct mali_dev; - -int mali_sysfs_register(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); - -int mali_sysfs_unregister(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); - +int mali_sysfs_register(const char *mali_dev_name); +int mali_sysfs_unregister(void); #ifdef __cplusplus } diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_linux_trace.h index 5329ba3..5329ba3 100644 --- a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_linux_trace.h diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c index 32f8e6b..05831c5 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_atomics.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_atomics.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c new file mode 100644 index 0000000..787a145 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_irq.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010-2012 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 "mali_osk.h" +#include "mali_kernel_common.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_object_t; + +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*/ + +_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description ) +{ + mali_osk_irq_object_t *irq_object; + unsigned long irq_flags = 0; + +#if defined(CONFIG_MALI_SHARED_INTERRUPTS) + irq_flags |= IRQF_SHARED; +#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */ + + irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL); + if (NULL == irq_object) + { + return NULL; + } + + 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(probe_data); + + _mali_osk_time_ubusydelay(5); + + irq = probe_irq_off(mask); + err = ack_func(probe_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->data = int_data; + + 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, irq_flags, description, irq_object)) + { + MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description)); + kfree(irq_object); + return NULL; + } + + return irq_object; +} + +void _mali_osk_irq_term( _mali_osk_irq_t *irq ) +{ + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; + free_irq(irq_object->irqnum, irq_object); + kfree(irq_object); +} + + +/** 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*/ +{ + irqreturn_t ret = IRQ_NONE; + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id; + + if (_MALI_OSK_ERR_OK == irq_object->uhandler(irq_object->data)) + { + ret = IRQ_HANDLED; + } + + return ret; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_locks.c index ee857d5..cce946a 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_locks.c @@ -13,19 +13,12 @@ * 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/mutex.h> #include <linux/slab.h> + #include "mali_osk.h" #include "mali_kernel_common.h" @@ -34,9 +27,9 @@ 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}() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use mutex_unlock()/down_interruptable() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use mutex_unlock()/down() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {mutex_unlock,down}{read,write}() */ /* Linux supports, but we do not support: * Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off @@ -55,7 +48,7 @@ struct _mali_osk_lock_t_struct union { spinlock_t spinlock; - struct semaphore sema; + struct mutex mutex; struct rw_semaphore rw_sema; } obj; MALI_DEBUG_CODE( @@ -65,9 +58,6 @@ struct _mali_osk_lock_t_struct /* id of the thread currently holding this lock, 0 if no * threads hold it. */ u32 owner; - /* number of owners this lock currently has (can be > 1 if - * taken in R/O mode. */ - u32 nOwners; /* what mode the lock was taken in */ _mali_osk_lock_mode_t mode; ); /* MALI_DEBUG_CODE */ @@ -132,7 +122,7 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial } /* Initially unlocked */ - sema_init( &lock->obj.sema, 1 ); + mutex_init(&lock->obj.mutex); } #ifdef DEBUG @@ -141,7 +131,6 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial /* Debug tracking of lock owner */ lock->owner = 0; - lock->nOwners = 0; #endif /* DEBUG */ return lock; @@ -153,11 +142,6 @@ u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock ) return lock->owner; } -u32 _mali_osk_lock_get_number_owners( _mali_osk_lock_t *lock ) -{ - return lock->nOwners; -} - u32 _mali_osk_lock_get_mode( _mali_osk_lock_t *lock ) { return lock->mode; @@ -194,7 +178,7 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: - if ( down_interruptible(&lock->obj.sema) ) + if (mutex_lock_interruptible(&lock->obj.mutex)) { MALI_PRINT_ERROR(("Can not lock mutex\n")); err = _MALI_OSK_ERR_RESTARTSYSCALL; @@ -202,7 +186,7 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: - down(&lock->obj.sema); + mutex_lock(&lock->obj.mutex); break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: @@ -229,7 +213,6 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ { if (mode == _MALI_OSK_LOCKMODE_RW) { - /*MALI_DEBUG_ASSERT(0 == lock->owner);*/ if (0 != lock->owner) { printk(KERN_ERR "%d: ERROR: Lock %p already has owner %d\n", _mali_osk_get_tid(), lock, lock->owner); @@ -237,13 +220,10 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ } lock->owner = _mali_osk_get_tid(); lock->mode = mode; - ++lock->nOwners; } else /* mode == _MALI_OSK_LOCKMODE_RO */ { - lock->owner |= _mali_osk_get_tid(); lock->mode = mode; - ++lock->nOwners; } } #endif @@ -269,7 +249,6 @@ void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) /* make sure the thread releasing the lock actually was the owner */ if (mode == _MALI_OSK_LOCKMODE_RW) { - /*MALI_DEBUG_ASSERT(_mali_osk_get_tid() == lock->owner);*/ if (_mali_osk_get_tid() != lock->owner) { printk(KERN_ERR "%d: ERROR: Lock %p owner was %d\n", _mali_osk_get_tid(), lock, lock->owner); @@ -277,23 +256,7 @@ void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) } /* This lock now has no owner */ lock->owner = 0; - --lock->nOwners; - } - else /* mode == _MALI_OSK_LOCKMODE_RO */ - { - if ((_mali_osk_get_tid() & lock->owner) != _mali_osk_get_tid()) - { - printk(KERN_ERR "%d: ERROR: Not an owner of %p lock.\n", _mali_osk_get_tid(), lock); - dump_stack(); - } - - /* if this is the last thread holding this lock in R/O mode, set owner - * back to 0 */ - if (0 == --lock->nOwners) - { - lock->owner = 0; - } - } + } /* else if (mode == _MALI_OSK_LOCKMODE_RO) Nothing to check */ #endif /* DEBUG */ switch ( lock->type ) @@ -308,7 +271,7 @@ void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: /* FALLTHROUGH */ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: - up(&lock->obj.sema); + mutex_unlock(&lock->obj.mutex); break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_low_level_mem.c index 02558a0..8c0ef17 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_low_level_mem.c @@ -25,6 +25,9 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) #include <linux/shrinker.h> #endif +#include <linux/sched.h> +#include <linux/mm_types.h> +#include <linux/rwsem.h> #include "mali_osk.h" #include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */ @@ -48,6 +51,7 @@ typedef struct mali_vma_usage_tracker u32 cookie; } mali_vma_usage_tracker; +#define INVALID_PAGE 0xffffffff /* Linked list structure to hold details of all OS allocations in a particular * mapping @@ -188,7 +192,7 @@ static u32 _kernel_page_allocate(void) if ( NULL == new_page ) { - return 0; + return INVALID_PAGE; } /* Ensure page is flushed from CPU caches. */ @@ -234,7 +238,7 @@ static AllocationList * _allocation_list_item_get(void) } item->physaddr = _kernel_page_allocate(); - if ( 0 == item->physaddr ) + if ( INVALID_PAGE == item->physaddr ) { /* Non-fatal error condition, out of memory. Upper levels will handle this. */ _mali_osk_free( item ); @@ -261,7 +265,6 @@ static void _allocation_list_item_release(AllocationList * item) _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 @@ -280,6 +283,8 @@ static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_st 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)); + MALI_IGNORE(address); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) return VM_FAULT_SIGBUS; #else @@ -333,7 +338,6 @@ static void mali_kernel_memory_vma_close(struct vm_area_struct * vma) * 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 ) { mb(); @@ -364,7 +368,7 @@ mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 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 ); + virt = dma_alloc_writecombine(NULL, size, phys, GFP_KERNEL | GFP_DMA | __GFP_ZERO); MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys)); @@ -385,17 +389,23 @@ void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt ) MALI_DEBUG_ASSERT( 0 != size ); MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) ); - dma_free_coherent(NULL, size, virt, phys); + dma_free_writecombine(NULL, size, virt, phys); } _mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ) { +#if MALI_LICENSE_IS_GPL + return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */ +#else return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); +#endif } void inline _mali_osk_mem_unreqregion( u32 phys, u32 size ) { +#if !MALI_LICENSE_IS_GPL release_mem_region(phys, size); +#endif } void inline _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ) @@ -464,8 +474,14 @@ _mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descr 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; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + vma->vm_flags |= VM_RESERVED; +#else + vma->vm_flags |= VM_DONTDUMP; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags |= VM_PFNMAP; +#endif vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */ @@ -658,3 +674,50 @@ void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 off return; } + +u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size) +{ +#define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096 + u32 retval = 0; + void *temp_buf; + + temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL); + if (NULL != temp_buf) + { + u32 bytes_left_to_copy = size; + u32 i; + for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE) + { + u32 size_to_copy; + u32 size_copied; + u32 bytes_left; + + if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE) + { + size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE; + } + else + { + size_to_copy = bytes_left_to_copy; + } + + bytes_left = copy_from_user(temp_buf, ((char*)src) + i, size_to_copy); + size_copied = size_to_copy - bytes_left; + + bytes_left = copy_to_user(((char*)dest) + i, temp_buf, size_copied); + size_copied -= bytes_left; + + bytes_left_to_copy -= size_copied; + retval += size_copied; + + if (size_copied != size_to_copy) + { + break; /* Early out, we was not able to copy this entire block */ + } + } + + kfree(temp_buf); + } + + return retval; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c new file mode 100644 index 0000000..50d6ddf --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_mali.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2010-2012 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_mali.c + * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver + */ +#include <linux/kernel.h> +#include <asm/uaccess.h> +#include <linux/platform_device.h> +#include <linux/mali/mali_utgard.h> + +#include "mali_osk_mali.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" + +_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res) +{ + int i; + + if (NULL == mali_platform_device) + { + /* Not connected to a device */ + return _MALI_OSK_ERR_ITEM_NOT_FOUND; + } + + for (i = 0; i < mali_platform_device->num_resources; i++) + { + if (IORESOURCE_MEM == resource_type(&(mali_platform_device->resource[i])) && + mali_platform_device->resource[i].start == addr) + { + if (NULL != res) + { + res->base = addr; + res->description = mali_platform_device->resource[i].name; + + /* Any (optional) IRQ resource belonging to this resource will follow */ + if ((i + 1) < mali_platform_device->num_resources && + IORESOURCE_IRQ == resource_type(&(mali_platform_device->resource[i+1]))) + { + res->irq = mali_platform_device->resource[i+1].start; + } + else + { + res->irq = -1; + } + } + return _MALI_OSK_ERR_OK; + } + } + + return _MALI_OSK_ERR_ITEM_NOT_FOUND; +} + +u32 _mali_osk_resource_base_address(void) +{ + u32 lowest_addr = 0xFFFFFFFF; + u32 ret = 0; + + if (NULL != mali_platform_device) + { + int i; + for (i = 0; i < mali_platform_device->num_resources; i++) + { + if (mali_platform_device->resource[i].flags & IORESOURCE_MEM && + mali_platform_device->resource[i].start < lowest_addr) + { + lowest_addr = mali_platform_device->resource[i].start; + ret = lowest_addr; + } + } + } + + return ret; +} + +_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data) +{ + MALI_DEBUG_ASSERT_POINTER(data); + + if (NULL != mali_platform_device) + { + struct mali_gpu_device_data* os_data = NULL; + + os_data = (struct mali_gpu_device_data*)mali_platform_device->dev.platform_data; + if (NULL != os_data) + { + /* Copy data from OS dependant struct to Mali neutral struct (identical!) */ + data->dedicated_mem_start = os_data->dedicated_mem_start; + data->dedicated_mem_size = os_data->dedicated_mem_size; + data->shared_mem_size = os_data->shared_mem_size; + data->fb_start = os_data->fb_start; + data->fb_size = os_data->fb_size; + data->utilization_interval = os_data->utilization_interval; + data->utilization_callback = os_data->utilization_callback; + data->pmu_switch_delay = os_data->pmu_switch_delay; + return _MALI_OSK_ERR_OK; + } + } + + return _MALI_OSK_ERR_ITEM_NOT_FOUND; +} + +mali_bool _mali_osk_shared_interrupts(void) +{ + u32 irqs[128]; + u32 i, j, irq, num_irqs_found = 0; + + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources); + + for (i = 0; i < mali_platform_device->num_resources; i++) + { + if (IORESOURCE_IRQ & mali_platform_device->resource[i].flags) + { + irq = mali_platform_device->resource[i].start; + + for (j = 0; j < num_irqs_found; ++j) + { + if (irq == irqs[j]) + { + return MALI_TRUE; + } + } + + irqs[num_irqs_found++] = irq; + } + } + + return MALI_FALSE; +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_math.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_math.c index bb25e7d..3e62e51 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_math.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_math.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_memory.c index 5354e85..7bb470f 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_memory.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_misc.c index ad486db..ad486db 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_misc.c diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_notification.c index c14c0d5..c265f88 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_notification.c @@ -16,16 +16,9 @@ #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/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 +#include <linux/spinlock.h> /** * Declaration of the notification queue object type @@ -35,15 +28,15 @@ */ struct _mali_osk_notification_queue_t_struct { - struct semaphore mutex; /**< Mutex protecting the list */ + spinlock_t 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 */ + 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 ) @@ -53,7 +46,7 @@ _mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ) 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); + spin_lock_init(&result->mutex); init_waitqueue_head(&result->receive_queue); INIT_LIST_HEAD(&result->head); @@ -63,15 +56,15 @@ _mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ) _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) { /* OPT Recycling of notification objects */ - _mali_osk_notification_wrapper_t *notification; + _mali_osk_notification_wrapper_t *notification; notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT); - if (NULL == notification) - { + if (NULL == notification) + { MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n")); return NULL; - } + } /* Init the list */ INIT_LIST_HEAD(¬ification->list); @@ -90,7 +83,7 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) notification->data.result_buffer_size = size; /* all ok */ - return &(notification->data); + return &(notification->data); } void _mali_osk_notification_delete( _mali_osk_notification_t *object ) @@ -98,7 +91,7 @@ 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 ); + notification = container_of( object, _mali_osk_notification_wrapper_t, data ); /* Free the container */ kfree(notification); @@ -106,54 +99,61 @@ void _mali_osk_notification_delete( _mali_osk_notification_t *object ) void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ) { + _mali_osk_notification_t *result; MALI_DEBUG_ASSERT_POINTER( queue ); + while (_MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, &result)) + { + _mali_osk_notification_delete( result ); + } + /* 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 ) { +#if defined(MALI_UPPER_HALF_SCHEDULING) + unsigned long irq_flags; +#endif + _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 ); + notification = container_of( object, _mali_osk_notification_wrapper_t, data ); + +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_lock_irqsave(&queue->mutex, irq_flags); +#else + spin_lock(&queue->mutex); +#endif - /* lock queue access */ - down(&queue->mutex); - /* add to list */ list_add_tail(¬ification->list, &queue->head); - /* unlock the queue */ - up(&queue->mutex); + +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_unlock_irqrestore(&queue->mutex, irq_flags); +#else + spin_unlock(&queue->mutex); +#endif /* 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 ) +_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) { - return _mali_notification_queue_is_empty(queue) ? MALI_TRUE : MALI_FALSE; -} +#if defined(MALI_UPPER_HALF_SCHEDULING) + unsigned long irq_flags; #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 defined(MALI_UPPER_HALF_SCHEDULING) + spin_lock_irqsave(&queue->mutex, irq_flags); +#else + spin_lock(&queue->mutex); +#endif if (!list_empty(&queue->head)) { @@ -163,7 +163,11 @@ _mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification ret = _MALI_OSK_ERR_OK; } - up(&queue->mutex); +#if defined(MALI_UPPER_HALF_SCHEDULING) + spin_unlock_irqrestore(&queue->mutex, irq_flags); +#else + spin_unlock(&queue->mutex); +#endif return ret; } @@ -174,15 +178,13 @@ _mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification MALI_DEBUG_ASSERT_POINTER( queue ); MALI_DEBUG_ASSERT_POINTER( result ); - /* default 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_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_RESTARTSYSCALL; } return _MALI_OSK_ERR_OK; /* all ok */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c new file mode 100644 index 0000000..bc19af9 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_pm.c @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2010-2012 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 <linux/version.h> +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" + +static _mali_osk_atomic_t mali_pm_ref_count; + +void _mali_osk_pm_dev_enable(void) +{ + _mali_osk_atomic_init(&mali_pm_ref_count, 0); +} + +void _mali_osk_pm_dev_disable(void) +{ + _mali_osk_atomic_term(&mali_pm_ref_count); +} + +/* Can NOT run in atomic context */ +_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void) +{ +#ifdef CONFIG_PM_RUNTIME + int err; + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + err = pm_runtime_get_sync(&(mali_platform_device->dev)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_mark_last_busy(&(mali_platform_device->dev)); +#endif + if (0 > err) + { + MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get_sync() returned error code %d\n", err)); + return _MALI_OSK_ERR_FAULT; + } + _mali_osk_atomic_inc(&mali_pm_ref_count); + MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); +#endif + return _MALI_OSK_ERR_OK; +} + +/* Can run in atomic context */ +void _mali_osk_pm_dev_ref_dec(void) +{ +#ifdef CONFIG_PM_RUNTIME + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + _mali_osk_atomic_dec(&mali_pm_ref_count); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_mark_last_busy(&(mali_platform_device->dev)); + pm_runtime_put_autosuspend(&(mali_platform_device->dev)); +#else + pm_runtime_put(&(mali_platform_device->dev)); +#endif + MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); +#endif +} + +/* Can run in atomic context */ +mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void) +{ +#ifdef CONFIG_PM_RUNTIME + u32 ref; + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); + pm_runtime_get_noresume(&(mali_platform_device->dev)); + ref = _mali_osk_atomic_read(&mali_pm_ref_count); + MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); + return ref > 0 ? MALI_TRUE : MALI_FALSE; +#else + return MALI_TRUE; +#endif +} + +/* Can run in atomic context */ +void _mali_osk_pm_dev_ref_dec_no_power_on(void) +{ +#ifdef CONFIG_PM_RUNTIME + MALI_DEBUG_ASSERT_POINTER(mali_platform_device); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_put_autosuspend(&(mali_platform_device->dev)); +#else + pm_runtime_put(&(mali_platform_device->dev)); +#endif + MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count))); +#endif +} + +void _mali_osk_pm_dev_barrier(void) +{ +#ifdef CONFIG_PM_RUNTIME + pm_runtime_barrier(&(mali_platform_device->dev)); +#endif +} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_profiling.c index 95bee53..5429329 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_profiling.c @@ -10,6 +10,7 @@ #include <linux/module.h> +#include <mali_profiling_gator_api.h> #include "mali_kernel_common.h" #include "mali_osk.h" #include "mali_ukk.h" @@ -18,6 +19,7 @@ #include "mali_linux_trace.h" #include "mali_gp.h" #include "mali_pp.h" +#include "mali_pp_scheduler.h" #include "mali_l2_cache.h" #include "mali_user_settings_db.h" @@ -125,59 +127,46 @@ _mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s * */ int _mali_profiling_set_event(u32 counter_id, s32 event_id) { + if (COUNTER_VP_0_C0 == counter_id) + { + if (MALI_TRUE == mali_gp_job_set_gp_counter_src0(event_id)) + { + return 1; + } + } - if (COUNTER_VP_C0 == counter_id) + if (COUNTER_VP_0_C1 == counter_id) { - struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); - if (NULL != gp_core) + if (MALI_TRUE == mali_gp_job_set_gp_counter_src1(event_id)) { - if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id)) - { - return 1; - } + return 1; } } - if (COUNTER_VP_C1 == counter_id) + + if (COUNTER_FP_0_C0 == counter_id) { - struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); - if (NULL != gp_core) + if (MALI_TRUE == mali_pp_job_set_pp_counter_src0(event_id)) { - if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id)) - { - return 1; - } + return 1; } } - if (COUNTER_FP0_C0 <= counter_id && COUNTER_FP3_C1 >= counter_id) + + if (COUNTER_FP_0_C1 == counter_id) { - u32 core_id = (counter_id - COUNTER_FP0_C0) >> 1; - struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id); - if (NULL != pp_core) + if (MALI_TRUE == mali_pp_job_set_pp_counter_src1(event_id)) { - u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1; - if (0 == counter_src) - { - if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id)) - { - return 1; - } - } - else - { - if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id)) - { - return 1; - } - } + return 1; } } - if (COUNTER_L2_C0 <= counter_id && COUNTER_L2_C1 >= counter_id) + + if (COUNTER_L2_0_C0 <= counter_id && COUNTER_L2_2_C1 >= counter_id) { - u32 core_id = (counter_id - COUNTER_L2_C0) >> 1; + u32 core_id = (counter_id - COUNTER_L2_0_C0) >> 1; struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id); + if (NULL != l2_cache_core) { - u32 counter_src = (counter_id - COUNTER_L2_C0) & 1; + u32 counter_src = (counter_id - COUNTER_L2_0_C0) & 1; if (0 == counter_src) { if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id)) @@ -199,38 +188,51 @@ int _mali_profiling_set_event(u32 counter_id, s32 event_id) } /** - * Called by gator.ko to retrieve the L2 cache counter values for the first L2 cache. + * Called by gator.ko to retrieve the L2 cache counter values for all L2 cache cores. * The L2 cache counters are unique in that they are polled by gator, rather than being - * transmitted via the tracepoint mechanism. + * transmitted via the tracepoint mechanism. * - * @param src0 First L2 cache counter ID. - * @param val0 First L2 cache counter value. - * @param src1 Second L2 cache counter ID. - * @param val1 Second L2 cache counter value. + * @param values Pointer to a _mali_profiling_l2_counter_values structure where + * the counter sources and values will be output + * @return 0 if all went well; otherwise, return the mask with the bits set for the powered off cores */ -void _mali_profiling_get_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1) +u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values) { - struct mali_l2_cache_core *l2_cache = mali_l2_cache_core_get_glob_l2_core(0); - if (NULL != l2_cache) - { + struct mali_l2_cache_core *l2_cache; + u32 l2_cores_num = mali_l2_cache_core_get_glob_num_l2_cores(); + u32 i; + u32 ret = 0; + + MALI_DEBUG_ASSERT(l2_cores_num <= 3); + + for (i = 0; i < l2_cores_num; i++) + { + l2_cache = mali_l2_cache_core_get_glob_l2_core(i); + + if (NULL == l2_cache) + { + continue; + } + if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) { /* It is now safe to access the L2 cache core in order to retrieve the counters */ - mali_l2_cache_core_get_counter_values(l2_cache, src0, val0, src1, val1); + mali_l2_cache_core_get_counter_values(l2_cache, + &values->cores[i].source0, + &values->cores[i].value0, + &values->cores[i].source1, + &values->cores[i].value1); + } + else + { + /* The core was not available, set the right bit in the mask. */ + ret |= (1 << i); } mali_l2_cache_unlock_power_state(l2_cache); - } -} + } -/* - * List of possible actions to be controlled by Streamline. - * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. - * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. - */ -#define FBDUMP_CONTROL_ENABLE (1) -#define FBDUMP_CONTROL_RATE (2) -#define SW_COUNTER_ENABLE (3) -#define FBDUMP_CONTROL_RESIZE_FACTOR (4) + return ret; +} /** * Called by gator to control the production of profiling information at runtime. @@ -256,6 +258,30 @@ void _mali_profiling_control(u32 action, u32 value) } } +/** + * Called by gator to get mali api version. + */ +u32 _mali_profiling_get_api_version(void) +{ + return MALI_PROFILING_API_VERSION; +} + +/** +* Called by gator to get the data about Mali instance in use: +* product id, version, number of cores +*/ +void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values) +{ + values->mali_product_id = (u32)mali_kernel_core_get_product_id(); + values->mali_version_major = mali_kernel_core_get_gpu_major_version(); + values->mali_version_minor = mali_kernel_core_get_gpu_minor_version(); + values->num_of_l2_cores = mali_l2_cache_core_get_glob_num_l2_cores(); + values->num_of_fp_cores = mali_pp_scheduler_get_num_cores_total(); + values->num_of_vp_cores = 1; +} + EXPORT_SYMBOL(_mali_profiling_set_event); -EXPORT_SYMBOL(_mali_profiling_get_counters); +EXPORT_SYMBOL(_mali_profiling_get_l2_counters); EXPORT_SYMBOL(_mali_profiling_control); +EXPORT_SYMBOL(_mali_profiling_get_api_version); +EXPORT_SYMBOL(_mali_profiling_get_mali_version); diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h new file mode 100644 index 0000000..15d98e0 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_specific.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010, 2012 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__ + +#include <asm/uaccess.h> + +#include "mali_sync.h" + +#define MALI_STATIC_INLINE static inline +#define MALI_NON_STATIC_INLINE inline + +#ifdef CONFIG_SYNC +typedef struct sync_timeline mali_sync_tl; +typedef struct sync_pt mali_sync_pt; +#endif /* CONFIG_SYNC */ + +MALI_STATIC_INLINE u32 _mali_osk_copy_from_user(void *to, void *from, u32 n) +{ + return (u32)copy_from_user(to, from, (unsigned long)n); +} + +#endif /* __MALI_OSK_SPECIFIC_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_time.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_time.c index b399b87..2aa6588 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_time.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_time.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. - * + * Copyright (C) 2011-2012 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. */ diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_timers.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_timers.c index e5829a3..0e28b32 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_timers.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_timers.c @@ -35,14 +35,14 @@ _mali_osk_timer_t *_mali_osk_timer_init(void) 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; + tim->timer.expires = jiffies + ticks_to_expire; add_timer(&(tim->timer)); } -void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick) +void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire) { MALI_DEBUG_ASSERT_POINTER(tim); - mod_timer(&(tim->timer), expiry_tick); + mod_timer(&(tim->timer), jiffies + ticks_to_expire); } void _mali_osk_timer_del( _mali_osk_timer_t *tim ) @@ -51,6 +51,18 @@ void _mali_osk_timer_del( _mali_osk_timer_t *tim ) del_timer_sync(&(tim->timer)); } +void _mali_osk_timer_del_async( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + del_timer(&(tim->timer)); +} + +mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim ) +{ + MALI_DEBUG_ASSERT_POINTER(tim); + return 1 == timer_pending(&(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); diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wait_queue.c index ce0561d..ce0561d 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wait_queue.c diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c new file mode 100644 index 0000000..23f5720 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_osk_wq.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010-2012 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_wq.c + * Implementation of the OS abstraction layer for the kernel device driver + */ + +#include <linux/slab.h> /* For memory allocation */ +#include <linux/workqueue.h> +#include <linux/version.h> + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_kernel_license.h" +#include "mali_kernel_linux.h" + +typedef struct _mali_osk_wq_work_t_struct +{ + _mali_osk_wq_work_handler_t handler; + void *data; + struct work_struct work_handle; +} mali_osk_wq_work_object_t; + +#if MALI_LICENSE_IS_GPL +struct workqueue_struct *mali_wq = NULL; +#endif + +static void _mali_osk_wq_work_func ( struct work_struct *work ); + +_mali_osk_errcode_t _mali_osk_wq_init(void) +{ +#if MALI_LICENSE_IS_GPL + MALI_DEBUG_ASSERT(NULL == mali_wq); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) + mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0); +#else + mali_wq = create_workqueue("mali"); +#endif + if(NULL == mali_wq) + { + MALI_PRINT_ERROR(("Unable to create Mali workqueue\n")); + return _MALI_OSK_ERR_FAULT; + } +#endif + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_wq_flush(void) +{ +#if MALI_LICENSE_IS_GPL + flush_workqueue(mali_wq); +#else + flush_scheduled_work(); +#endif +} + +void _mali_osk_wq_term(void) +{ +#if MALI_LICENSE_IS_GPL + MALI_DEBUG_ASSERT(NULL != mali_wq); + + flush_workqueue(mali_wq); + destroy_workqueue(mali_wq); + mali_wq = NULL; +#else + flush_scheduled_work(); +#endif +} + +_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data ) +{ + mali_osk_wq_work_object_t *work = kmalloc(sizeof(mali_osk_wq_work_object_t), GFP_KERNEL); + + if (NULL == work) return NULL; + + work->handler = handler; + work->data = data; + + INIT_WORK( &work->work_handle, _mali_osk_wq_work_func ); + + return work; +} + +void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work ) +{ + mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work; + _mali_osk_wq_flush(); + kfree(work_object); +} + +void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work ) +{ + mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work; + kfree(work_object); +} + +void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work ) +{ + mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work; +#if MALI_LICENSE_IS_GPL + queue_work(mali_wq, &work_object->work_handle); +#else + schedule_work(&work_object->work_handle); +#endif +} + +static void _mali_osk_wq_work_func ( struct work_struct *work ) +{ + mali_osk_wq_work_object_t *work_object; + + work_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_wq_work_object_t, work_handle); + work_object->handler(work_object->data); +} + diff --git a/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_pmu_power_up_down.c index f3b0a2c..05dc291 100644 --- a/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_pmu_power_up_down.c @@ -18,6 +18,7 @@ #include "mali_osk.h" #include "mali_kernel_common.h" #include "mali_pmu.h" +#include "mali_pp_scheduler.h" #include "linux/mali/mali_utgard.h" /* Mali PMU power up/down APIs */ @@ -28,12 +29,13 @@ int mali_pmu_powerup(void) MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n")); + MALI_DEBUG_ASSERT_POINTER(pmu); if (NULL == pmu) { return -ENXIO; } - if (_MALI_OSK_ERR_OK != mali_pmu_powerup_all(pmu)) + if (_MALI_OSK_ERR_OK != mali_pmu_power_up_all(pmu)) { return -EFAULT; } @@ -49,12 +51,13 @@ int mali_pmu_powerdown(void) MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n")); + MALI_DEBUG_ASSERT_POINTER(pmu); if (NULL == pmu) { return -ENXIO; } - if (_MALI_OSK_ERR_OK != mali_pmu_powerdown_all(pmu)) + if (_MALI_OSK_ERR_OK != mali_pmu_power_down_all(pmu)) { return -EFAULT; } @@ -63,3 +66,10 @@ int mali_pmu_powerdown(void) } EXPORT_SYMBOL(mali_pmu_powerdown); + +int mali_perf_set_num_pp_cores(unsigned int num_cores) +{ + return mali_pp_scheduler_set_perf_level(num_cores); +} + +EXPORT_SYMBOL(mali_perf_set_num_pp_cores); diff --git a/drivers/media/video/samsung/mali/linux/mali_profiling_events.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_events.h index 2639a40..2639a40 100644 --- a/drivers/media/video/samsung/mali/linux/mali_profiling_events.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_events.h diff --git a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_gator_api.h index 532fc94..c111cfd 100644 --- a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_gator_api.h @@ -8,11 +8,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ +#ifndef __MALI_PROFILING_GATOR_API_H__ +#define __MALI_PROFILING_GATOR_API_H__ -#define ARCH_UMP_BACKEND_DEFAULT 0 -#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0xCE000000 -#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL +/* Simple wrapper in order to find the OS specific location of this file */ +#include <linux/mali/mali_utgard_profiling_gator_api.h> -#endif /* __ARCH_CONFIG_H__ */ +#endif /* __MALI_PROFILING_GATOR_API_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c new file mode 100644 index 0000000..e40a800 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2010-2012 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 "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_timestamp.h" +#include "mali_osk_profiling.h" +#include "mali_user_settings_db.h" +#include "mali_profiling_internal.h" + +typedef struct mali_profiling_entry +{ + u64 timestamp; + u32 event_id; + u32 data[5]; +} mali_profiling_entry; + + +typedef enum mali_profiling_state +{ + MALI_PROFILING_STATE_UNINITIALIZED, + MALI_PROFILING_STATE_IDLE, + MALI_PROFILING_STATE_RUNNING, + MALI_PROFILING_STATE_RETURN, +} mali_profiling_state; + +static _mali_osk_lock_t *lock = NULL; +static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; +static mali_profiling_entry* profile_entries = NULL; +static _mali_osk_atomic_t profile_insert_index; +static u32 profile_mask = 0; +static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); + +void probe_mali_timeline_event(void *data, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned + int d2, unsigned int d3, unsigned int d4)) +{ + add_event(event_id, d0, d1, d2, d3, d4); +} + +_mali_osk_errcode_t _mali_internal_profiling_init(mali_bool auto_start) +{ + profile_entries = NULL; + profile_mask = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + + lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); + if (NULL == lock) + { + return _MALI_OSK_ERR_FAULT; + } + + prof_state = MALI_PROFILING_STATE_IDLE; + + if (MALI_TRUE == auto_start) + { + u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ + + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) + { + return _MALI_OSK_ERR_FAULT; + } + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_internal_profiling_term(void) +{ + u32 count; + + /* Ensure profiling is stopped */ + _mali_internal_profiling_stop(&count); + + prof_state = MALI_PROFILING_STATE_UNINITIALIZED; + + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + if (NULL != lock) + { + _mali_osk_lock_term(lock); + lock = NULL; + } +} + +_mali_osk_errcode_t _mali_internal_profiling_start(u32 * limit) +{ + _mali_osk_errcode_t ret; + mali_profiling_entry *new_profile_entries; + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (MALI_PROFILING_STATE_RUNNING == prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_BUSY; + } + + new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); + + if (NULL == new_profile_entries) + { + _mali_osk_vfree(new_profile_entries); + return _MALI_OSK_ERR_NOMEM; + } + + if (MALI_PROFILING_MAX_BUFFER_ENTRIES < *limit) + { + *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; + } + + profile_mask = 1; + while (profile_mask <= *limit) + { + profile_mask <<= 1; + } + profile_mask >>= 1; + + *limit = profile_mask; + + profile_mask--; /* turns the power of two into a mask of one less */ + + if (MALI_PROFILING_STATE_IDLE != prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_vfree(new_profile_entries); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + profile_entries = new_profile_entries; + + ret = _mali_timestamp_reset(); + + if (_MALI_OSK_ERR_OK == ret) + { + prof_state = MALI_PROFILING_STATE_RUNNING; + } + else + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + register_trace_mali_timeline_event(probe_mali_timeline_event, NULL); + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return ret; +} + +static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) +{ + u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) & profile_mask; + + profile_entries[cur_index].timestamp = _mali_timestamp_get(); + profile_entries[cur_index].event_id = event_id; + profile_entries[cur_index].data[0] = data0; + profile_entries[cur_index].data[1] = data1; + profile_entries[cur_index].data[2] = data2; + profile_entries[cur_index].data[3] = data3; + profile_entries[cur_index].data[4] = data4; + + /* If event is "leave API function", add current memory usage to the event + * as data point 4. This is used in timeline profiling to indicate how + * much memory was used when leaving a function. */ + if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) + { + profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); + } +} + +_mali_osk_errcode_t _mali_internal_profiling_stop(u32 * count) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (MALI_PROFILING_STATE_RUNNING != prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + /* go into return state (user to retreive events), no more events will be added after this */ + prof_state = MALI_PROFILING_STATE_RETURN; + + unregister_trace_mali_timeline_event(probe_mali_timeline_event, NULL); + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + tracepoint_synchronize_unregister(); + + *count = _mali_osk_atomic_read(&profile_insert_index); + if (*count > profile_mask) *count = profile_mask; + + return _MALI_OSK_ERR_OK; +} + +u32 _mali_internal_profiling_get_count(void) +{ + u32 retval = 0; + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + if (MALI_PROFILING_STATE_RETURN == prof_state) + { + retval = _mali_osk_atomic_read(&profile_insert_index); + if (retval > profile_mask) retval = profile_mask; + } + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + return retval; +} + +_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + u32 raw_index = _mali_osk_atomic_read(&profile_insert_index); + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (index < profile_mask) + { + if ((raw_index & ~profile_mask) != 0) + { + index += raw_index; + index &= profile_mask; + } + + if (prof_state != MALI_PROFILING_STATE_RETURN) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + if(index >= raw_index) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + *timestamp = profile_entries[index].timestamp; + *event_id = profile_entries[index].event_id; + data[0] = profile_entries[index].data[0]; + data[1] = profile_entries[index].data[1]; + data[2] = profile_entries[index].data[2]; + data[3] = profile_entries[index].data[3]; + data[4] = profile_entries[index].data[4]; + } + else + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_internal_profiling_clear(void) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (MALI_PROFILING_STATE_RETURN != prof_state) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + prof_state = MALI_PROFILING_STATE_IDLE; + profile_mask = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_internal_profiling_is_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; +} + +mali_bool _mali_internal_profiling_have_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h new file mode 100644 index 0000000..092b9b0 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_profiling_internal.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 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_PROFILING_INTERNAL_H__ +#define __MALI_PROFILING_INTERNAL_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "mali_osk.h" + +int _mali_internal_profiling_init(mali_bool auto_start); +void _mali_internal_profiling_term(void); + +mali_bool _mali_internal_profiling_is_recording(void); +mali_bool _mali_internal_profiling_have_recording(void); +_mali_osk_errcode_t _mali_internal_profiling_clear(void); +_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); +u32 _mali_internal_profiling_get_count(void); +int _mali_internal_profiling_stop(u32 * count); +int _mali_internal_profiling_start(u32 * limit); + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_PROFILING_INTERNAL_H__ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c new file mode 100644 index 0000000..6293610 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2012 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_sync.c + * + */ + +#include <linux/seq_file.h> +#include <linux/sync.h> +#include <linux/timer.h> + +#include "mali_osk.h" +#include "mali_kernel_common.h" + +struct mali_sync_timeline +{ + struct sync_timeline timeline; + atomic_t counter; + atomic_t signalled; +}; + +struct mali_sync_pt +{ + struct sync_pt pt; + u32 order; + s32 error; + struct timer_list timer; +}; + +static void mali_sync_timed_pt_timeout(unsigned long data); + +static inline struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline) +{ + return container_of(timeline, struct mali_sync_timeline, timeline); +} + +static inline struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) +{ + return container_of(pt, struct mali_sync_pt, pt); +} + +static struct sync_pt *timeline_dup(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_pt *new_mpt; + struct sync_pt *new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt)); + + if (!new_pt) + { + return NULL; + } + + new_mpt = to_mali_sync_pt(new_pt); + new_mpt->order = mpt->order; + + return new_pt; + +} + +static int timeline_has_signaled(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + long diff; + + if (0 != mpt->error) + { + return mpt->error; + } + + diff = atomic_read(&mtl->signalled) - mpt->order; + + return diff >= 0; +} + +static int timeline_compare(struct sync_pt *a, struct sync_pt *b) +{ + struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt); + struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt); + + long diff = ma->order - mb->order; + + if (diff < 0) + { + return -1; + } + else if (diff == 0) + { + return 0; + } + else + { + return 1; + } +} + +static void timeline_free_pt(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + + if (mpt->timer.function == mali_sync_timed_pt_timeout) + { + del_timer_sync(&mpt->timer); + } +} + +static void timeline_print_tl(struct seq_file *s, struct sync_timeline *sync_timeline) +{ + struct mali_sync_timeline *mtl = to_mali_sync_timeline(sync_timeline); + + seq_printf(s, "%u, %u", atomic_read(&mtl->signalled), atomic_read(&mtl->counter)); +} + +static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(sync_pt); + + seq_printf(s, "%u", mpt->order); + +} + +static struct sync_timeline_ops mali_timeline_ops = { + .driver_name = "Mali", + .dup = timeline_dup, + .has_signaled = timeline_has_signaled, + .compare = timeline_compare, + .free_pt = timeline_free_pt, + .print_obj = timeline_print_tl, + .print_pt = timeline_print_pt +}; + +int mali_sync_timeline_is_ours(struct sync_timeline *timeline) +{ + return (timeline->ops == &mali_timeline_ops); +} + +struct sync_timeline *mali_sync_timeline_alloc(const char * name) +{ + struct sync_timeline *tl; + struct mali_sync_timeline *mtl; + + tl = sync_timeline_create(&mali_timeline_ops, + sizeof(struct mali_sync_timeline), name); + if (!tl) + { + return NULL; + } + + /* Set the counter in our private struct */ + mtl = to_mali_sync_timeline(tl); + atomic_set(&mtl->counter, 0); + atomic_set(&mtl->signalled, 0); + + return tl; +} + +struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt = sync_pt_create(parent, sizeof(struct mali_sync_pt)); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent); + struct mali_sync_pt *mpt; + + if (!pt) + { + return NULL; + } + + mpt = to_mali_sync_pt(pt); + mpt->order = atomic_inc_return(&mtl->counter); + mpt->error = 0; + + return pt; +} + +static void mali_sync_timed_pt_timeout(unsigned long data) +{ + struct sync_pt *pt = (struct sync_pt *)data; + + MALI_DEBUG_ASSERT_POINTER(pt); + + mali_sync_signal_pt(pt, -ETIME); +} + +struct sync_pt *mali_sync_timed_pt_alloc(struct sync_timeline *parent) +{ + struct sync_pt *pt; + struct mali_sync_pt *mpt; + const u32 timeout = msecs_to_jiffies(MALI_SYNC_TIMED_FENCE_TIMEOUT); + + pt = mali_sync_pt_alloc(parent); + if (NULL == pt) return NULL; + mpt = to_mali_sync_pt(pt); + + init_timer(&mpt->timer); + + mpt->timer.function = mali_sync_timed_pt_timeout; + mpt->timer.data = (unsigned long)pt; + mpt->timer.expires = jiffies + timeout; + + add_timer(&mpt->timer); + + return pt; +} + +/* + * Returns 0 if sync_pt has been committed and are ready for use, -ETIME if + * timeout already happened and the fence has been signalled. + * + * If an error occurs the sync point can not be used. + */ +int mali_sync_timed_commit(struct sync_pt *pt) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + int ret; + + if (!mali_sync_timeline_is_ours(pt->parent)) + { + return -EINVAL; + } + + /* Stop timer */ + ret = del_timer_sync(&mpt->timer); + + if (0 == ret) + { + return -ETIME; + } + + MALI_DEBUG_ASSERT(0 == timeline_has_signaled(pt)); + + return 0; +} + +void mali_sync_signal_pt(struct sync_pt *pt, int error) +{ + struct mali_sync_pt *mpt = to_mali_sync_pt(pt); + struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent); + int signalled; + long diff; + + if (0 != error) + { + MALI_DEBUG_ASSERT(0 > error); + mpt->error = error; + } + + do { + + signalled = atomic_read(&mtl->signalled); + + diff = signalled - mpt->order; + + if (diff > 0) + { + /* The timeline is already at or ahead of this point. This should not happen unless userspace + * has been signalling fences out of order, so warn but don't violate the sync_pt API. + * The warning is only in debug builds to prevent a malicious user being able to spam dmesg. + */ + MALI_DEBUG_PRINT_ERROR(("Sync points were triggerd in a different order to allocation!\n")); + return; + } + } while (atomic_cmpxchg(&mtl->signalled, signalled, mpt->order) != signalled); + + sync_timeline_signal(pt->parent); +} diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h new file mode 100644 index 0000000..4415ec6 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012 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_sync.h + * + */ + +#ifndef _MALI_SYNC_H_ +#define _MALI_SYNC_H_ + +#ifdef CONFIG_SYNC + +#include <linux/seq_file.h> +#include <linux/sync.h> + +#define MALI_SYNC_TIMED_FENCE_TIMEOUT 4000 /* 4s */ + +/* + * Create a stream object. + * Built on top of timeline object. + * Exposed as a file descriptor. + * Life-time controlled via the file descriptor: + * - dup to add a ref + * - close to remove a ref + */ +_mali_osk_errcode_t mali_stream_create(const char * name, int * out_fd); + +/* + * Create a fence in a stream object + */ +struct sync_pt *mali_stream_create_point(int tl_fd); +int mali_stream_create_fence(struct sync_pt *pt); +int mali_stream_create_empty_fence(int tl_fd); + +/** + * Commit an empty timed fence + * + * This stops the timer of the empty fence and returns wether or not the fence + * is still suitable for use. + * + * Returns -ETIME if fence is already signalled, in which case it can not be + * used, or 0 when the timer was stopped and the fence is OK to use. + */ +int mali_sync_timed_commit(struct sync_pt *pt); + +/* + * Validate a fd to be a valid fence + * No reference is taken. + * + * This function is only usable to catch unintentional user errors early, + * it does not stop malicious code changing the fd after this function returns. + */ +_mali_osk_errcode_t mali_fence_validate(int fd); + + +/* Returns true if the specified timeline is allocated by Mali */ +int mali_sync_timeline_is_ours(struct sync_timeline *timeline); + +/* Allocates a timeline for Mali + * + * One timeline should be allocated per API context. + */ +struct sync_timeline *mali_sync_timeline_alloc(const char *name); + +/* Allocates a sync point within the timeline. + * + * The timeline must be the one allocated by mali_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + */ +struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent); + +/* Allocates a timed sync point within the timeline. + * + * The timeline must be the one allocated by mali_sync_timeline_alloc + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + * + * Timed sync points should be backed by a proper event before reaching the + * timeout. If timeout is reached the fence will be signalled with an error (-ETIME). + */ +struct sync_pt *mali_sync_timed_pt_alloc(struct sync_timeline *parent); + +/* Signals a particular sync point + * + * Sync points must be triggered in *exactly* the same order as they are allocated. + * + * If they are signalled in the wrong order then a message will be printed in debug + * builds and otherwise attempts to signal order sync_pts will be ignored. + */ +void mali_sync_signal_pt(struct sync_pt *pt, int error); + +#endif /* CONFIG_SYNC */ +#endif /* _MALI_SYNC_H_ */ diff --git a/drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c new file mode 100644 index 0000000..7f0fddfc --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_sync_user.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2012 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_sync_user.c + * + */ + +#ifdef CONFIG_SYNC + +#include <linux/sched.h> +#include <linux/fdtable.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/anon_inodes.h> +#include <linux/version.h> +#include <asm/uaccess.h> + +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_sync.h" + +static int mali_stream_close(struct inode * inode, struct file * file) +{ + struct sync_timeline * tl; + tl = (struct sync_timeline*)file->private_data; + BUG_ON(!tl); + sync_timeline_destroy(tl); + return 0; +} + +static struct file_operations stream_fops = +{ + .owner = THIS_MODULE, + .release = mali_stream_close, +}; + +_mali_osk_errcode_t mali_stream_create(const char * name, int *out_fd) +{ + struct sync_timeline * tl; + BUG_ON(!out_fd); + + tl = mali_sync_timeline_alloc(name); + if (!tl) + { + return _MALI_OSK_ERR_FAULT; + } + + *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC); + + if (*out_fd < 0) + { + sync_timeline_destroy(tl); + return _MALI_OSK_ERR_FAULT; + } + else + { + return _MALI_OSK_ERR_OK; + } +} + +static mali_sync_pt *mali_stream_create_point_internal(int tl_fd, mali_bool timed) +{ + struct sync_timeline *tl; + struct sync_pt * pt; + struct file *tl_file; + + tl_file = fget(tl_fd); + if (tl_file == NULL) + return NULL; + + if (tl_file->f_op != &stream_fops) + { + pt = NULL; + goto out; + } + + tl = tl_file->private_data; + + if (unlikely(timed)) + { + pt = mali_sync_timed_pt_alloc(tl); + } + else + { + pt = mali_sync_pt_alloc(tl); + } + + if (!pt) + { + pt = NULL; + goto out; + } + +out: + fput(tl_file); + + return pt; +} + +mali_sync_pt *mali_stream_create_point(int tl_fd) +{ + return mali_stream_create_point_internal(tl_fd, MALI_FALSE); +} + +int mali_stream_create_fence(mali_sync_pt *pt) +{ + struct sync_fence *fence; + struct fdtable * fdt; + struct files_struct * files; + int fd = -1; + + fence = sync_fence_create("mali_fence", pt); + if (!fence) + { + sync_pt_free(pt); + fd = -EFAULT; + goto out; + } + + /* create a fd representing the fence */ + fd = get_unused_fd(); + if (fd < 0) + { + sync_fence_put(fence); + goto out; + } + + files = current->files; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + __set_close_on_exec(fd, fdt); +#else + FD_SET(fd, fdt->close_on_exec); +#endif + spin_unlock(&files->file_lock); + + /* bind fence to the new fd */ + sync_fence_install(fence, fd); + +out: + return fd; +} + +int mali_stream_create_empty_fence(int tl_fd) +{ + int fd; + mali_sync_pt *pt; + + pt = mali_stream_create_point_internal(tl_fd, MALI_TRUE); + + if (NULL == pt) return -ENOMEM; + + fd = mali_stream_create_fence(pt); + + return fd; +} + +_mali_osk_errcode_t mali_fence_validate(int fd) +{ + struct sync_fence * fence; + fence = sync_fence_fdget(fd); + if (NULL != fence) + { + sync_fence_put(fence); + return _MALI_OSK_ERR_OK; + } + else + { + return _MALI_OSK_ERR_FAULT; + } +} + +#endif /* CONFIG_SYNC */ diff --git a/drivers/media/video/samsung/mali/linux/mali_uk_types.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_uk_types.h index 1a81246..fbe902a 100644 --- a/drivers/media/video/samsung/mali/linux/mali_uk_types.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_uk_types.h @@ -12,7 +12,6 @@ #define __MALI_UK_TYPES_H__ /* Simple wrapper in order to find the OS specific location of this file */ -//#include <linux/mali/mali_utgard_uk_types.h> -#include "../include/linux/mali/mali_utgard_uk_types.h" +#include <linux/mali/mali_utgard_uk_types.h> #endif /* __MALI_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_core.c index 22262fe..1768ff2 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_core.c @@ -10,18 +10,23 @@ #include <linux/fs.h> /* file system operations */ #include <linux/slab.h> /* memort allocation functions */ #include <asm/uaccess.h> /* user space access */ +#include <linux/pid.h> #include "mali_ukk.h" #include "mali_osk.h" #include "mali_kernel_common.h" #include "mali_session.h" #include "mali_ukk_wrappers.h" +#include "mali_sync.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; + u32 mem = _mali_ukk_report_memory_usage(); + printk("Mali: mem_usage before %d : %u\n", _mali_osk_get_pid(), mem); + MALI_CHECK_NON_NULL(uargs, -EINVAL); if (0 != get_user(kargs.version, &uargs->version)) return -EFAULT; @@ -102,3 +107,68 @@ int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_g return 0; } + +#ifdef CONFIG_SYNC +int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs) +{ + _mali_uk_stream_create_s kargs; + _mali_osk_errcode_t err; + char name[32]; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + snprintf(name, 32, "mali-%u", _mali_osk_get_pid()); + + kargs.ctx = session_data; + err = mali_stream_create(name, &kargs.fd); + 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_stream_create_s))) return -EFAULT; + + return 0; +} + +int sync_fence_create_empty_wrapper(struct mali_session_data *session_data, _mali_uk_fence_create_empty_s __user *uargs) +{ + _mali_uk_fence_create_empty_s kargs; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != get_user(kargs.stream, &uargs->stream)) return -EFAULT; + + kargs.fence = mali_stream_create_empty_fence(kargs.stream); + if (0 > kargs.fence) + { + return kargs.fence; + } + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_fence_create_empty_s))) return -EFAULT; + + return 0; +} + +int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs) +{ + int fd; + _mali_osk_errcode_t err; + + if (0 != get_user(fd, &uargs->fd)) + { + return -EFAULT; + } + + err = mali_fence_validate(fd); + + if (_MALI_OSK_ERR_OK == err) + { + return 0; + } + + return -EINVAL; +} +#endif diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c index 7070016..4ee4a81 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_gp.c @@ -18,40 +18,15 @@ 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_osk_errcode_t err; - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); + 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; - } + err = _mali_ukk_gp_start_job(session_data, uargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - 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; + return 0; } int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs) diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c index 260f257..7d1d23d 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_mem.c @@ -65,6 +65,49 @@ int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s return 0; } +int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs) +{ + _mali_uk_mem_write_safe_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_mem_write_safe_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + + /* Check if we can access the buffers */ + if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size) + || !access_ok(VERIFY_READ, kargs.src, kargs.size)) + { + return -EINVAL; + } + + /* Check if size wraps */ + if ((kargs.size + kargs.dest) <= kargs.dest + || (kargs.size + kargs.src) <= kargs.src) + { + return -EINVAL; + } + + err = _mali_ukk_mem_write_safe(&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_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; @@ -127,7 +170,7 @@ int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap return map_errcode(err_code); } -#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 +#if defined(CONFIG_MALI400_UMP) 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; @@ -189,7 +232,7 @@ int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_atta /* Return the error that _mali_ukk_map_external_ump_mem produced */ return map_errcode(err_code); } -#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */ +#endif /* CONFIG_MALI400_UMP */ 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) { @@ -230,6 +273,7 @@ int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mal if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit; /* allocate temporary buffer (kernel side) to store mmu page table info */ + MALI_CHECK(kargs.size > 0, -ENOMEM); kargs.buffer = _mali_osk_valloc(kargs.size); if (NULL == kargs.buffer) { diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c index c11c61b..6663e7f 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_pp.c @@ -18,41 +18,48 @@ 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; + int fence = -1; 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))) + err = _mali_ukk_pp_start_job(session_data, uargs, &fence); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + +#if defined(CONFIG_SYNC) + if (0 != put_user(fence, &uargs->fence)) { - return -EFAULT; + /* Since the job has started we can't return an error. */ } +#endif /* CONFIG_SYNC */ - 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); - - return 0; + 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_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); + 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); + 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; + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_pp_number_of_cores_s))) + { + return -EFAULT; + } - return 0; + return 0; } int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs) diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_profiling.c index f4e31c9..f4e31c9 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_profiling.c diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c index f9b5a3e..f9b5a3e 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_vsync.c diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_wrappers.h index 65857fd..08bdae4 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h +++ b/drivers/gpu/mali400/r3p2/mali/linux/mali_ukk_wrappers.h @@ -27,18 +27,24 @@ extern "C" 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 get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs); +#if defined(CONFIG_SYNC) +int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs); +int sync_fence_create_empty_wrapper(struct mali_session_data *session_data, _mali_uk_fence_create_empty_s __user *uargs); +int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs); +#endif 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_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_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 +#if defined(CONFIG_MALI400_UMP) 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 */ +#endif int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_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); diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c new file mode 100644 index 0000000..bf83249 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4.c @@ -0,0 +1,405 @@ +/* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4.c + * + * Copyright 2011 by S.LSI. Samsung Electronics Inc. + * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea + * + * Samsung SoC Mali400 DVFS driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software FoundatIon. + */ + +/** + * @file exynos4.c + * Platform specific Mali driver functions for the exynos 4XXX based platforms + */ +#include <linux/platform_device.h> +#include <linux/version.h> +#include <linux/pm.h> +#include <linux/suspend.h> + +#ifdef CONFIG_PM_RUNTIME +#include <linux/pm_runtime.h> +#endif + +#ifdef CONFIG_MALI_DVFS +#include "mali_kernel_utilization.h" +#endif /* CONFIG_MALI_DVFS */ + +#include <linux/mali/mali_utgard.h> +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" +#include "mali_pm.h" + +#include <plat/pd.h> + +#include "exynos4_pmm.h" + +#if defined(CONFIG_PM_RUNTIME) +/* We does not need PM NOTIFIER in r3p2 DDK */ +//#define USE_PM_NOTIFIER +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) +struct exynos_pm_domain; +extern struct exynos_pm_domain exynos4_pd_g3d; +void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) +extern struct platform_device exynos4_device_pd[]; +#else +extern struct platform_device s5pv310_device_pd[]; +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */ + +static void mali_platform_device_release(struct device *device); + +#if defined(CONFIG_PM_RUNTIME) +#if defined(USE_PM_NOTIFIER) +static int mali_os_suspend(struct device *device); +static int mali_os_resume(struct device *device); +static int mali_os_freeze(struct device *device); +static int mali_os_thaw(struct device *device); + +static int mali_runtime_suspend(struct device *device); +static int mali_runtime_resume(struct device *device); +static int mali_runtime_idle(struct device *device); +#endif +#endif + +#if defined(CONFIG_ARCH_S5PV310) && !defined(CONFIG_BOARD_HKDKC210) + +/* This is for other SMDK boards */ +#define MALI_BASE_IRQ 232 + +#else + +/* This is for the Odroid boards */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) +#define MALI_BASE_IRQ 182 +#else +#define MALI_BASE_IRQ 150 +#endif + +#endif + +#define MALI_GP_IRQ MALI_BASE_IRQ + 9 +#define MALI_PP0_IRQ MALI_BASE_IRQ + 5 +#define MALI_PP1_IRQ MALI_BASE_IRQ + 6 +#define MALI_PP2_IRQ MALI_BASE_IRQ + 7 +#define MALI_PP3_IRQ MALI_BASE_IRQ + 8 +#define MALI_GP_MMU_IRQ MALI_BASE_IRQ + 4 +#define MALI_PP0_MMU_IRQ MALI_BASE_IRQ + 0 +#define MALI_PP1_MMU_IRQ MALI_BASE_IRQ + 1 +#define MALI_PP2_MMU_IRQ MALI_BASE_IRQ + 2 +#define MALI_PP3_MMU_IRQ MALI_BASE_IRQ + 3 + +static struct resource mali_gpu_resources[] = +{ + MALI_GPU_RESOURCES_MALI400_MP4(0x13000000, + MALI_GP_IRQ, MALI_GP_MMU_IRQ, + MALI_PP0_IRQ, MALI_PP0_MMU_IRQ, + MALI_PP1_IRQ, MALI_PP1_MMU_IRQ, + MALI_PP2_IRQ, MALI_PP2_MMU_IRQ, + MALI_PP3_IRQ, MALI_PP3_MMU_IRQ) +}; + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) +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 +#endif /* CONFIG_PM_RUNTIME */ + +#if 0 +static struct dev_pm_ops mali_gpu_device_type_pm_ops = +{ +#ifndef CONFIG_PM_RUNTIME + .suspend = mali_os_suspend, + .resume = mali_os_resume, +#endif + .freeze = mali_os_freeze, + .thaw = mali_os_thaw, +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = mali_runtime_suspend, + .runtime_resume = mali_runtime_resume, + .runtime_idle = mali_runtime_idle, +#endif +}; +#endif + +#if defined(USE_PM_NOTIFIER) +static struct device_type mali_gpu_device_device_type = +{ + .pm = &mali_gpu_device_type_pm_ops, +}; +#endif + +static struct platform_device mali_gpu_device = +{ + .name = "mali_dev", /* MALI_SEC MALI_GPU_NAME_UTGARD, */ + .id = 0, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + /* Set in mali_platform_device_register() for these kernels */ +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) + .dev.parent = &exynos4_device_pd[PD_G3D].dev, +#else + .dev.parent = &s5pv310_device_pd[PD_G3D].dev, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */ + .dev.release = mali_platform_device_release, +#if 0 + /* + * We temporarily make use of a device type so that we can control the Mali power + * from within the mali.ko (since the default platform bus implementation will not do that). + * Ideally .dev.pm_domain should be used instead, as this is the new framework designed + * to control the power of devices. + */ + .dev.type = &mali_gpu_device_device_type, /* We should probably use the pm_domain instead of type on newer kernels */ +#endif +}; + +static struct mali_gpu_device_data mali_gpu_data = +{ + .shared_mem_size = 256 * 1024 * 1024, /* 256MB */ + .fb_start = 0x40000000, + .fb_size = 0xb1000000, + .utilization_interval = 100, /* 100ms */ + .utilization_callback = mali_gpu_utilization_handler, +}; + +int mali_platform_device_register(void) +{ + int err; + + MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n")); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + exynos_pm_add_dev_to_genpd(&mali_gpu_device, &exynos4_pd_g3d); +#endif + + /* Connect resources to the device */ + err = platform_device_add_resources(&mali_gpu_device, mali_gpu_resources, sizeof(mali_gpu_resources) / sizeof(mali_gpu_resources[0])); + if (0 == err) + { + err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data)); + if (0 == err) + { +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) + err = register_pm_notifier(&mali_pwr_notif_block); + if (err) + { + goto plat_init_err; + } +#endif +#endif /* CONFIG_PM_RUNTIME */ + + /* Register the platform device */ + err = platform_device_register(&mali_gpu_device); + if (0 == err) + { + mali_platform_init(&(mali_gpu_device.dev)); + +#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) + pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000); + pm_runtime_use_autosuspend(&(mali_gpu_device.dev)); +#endif + pm_runtime_enable(&(mali_gpu_device.dev)); +#endif + + return 0; + } + } + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) +plat_init_err: + unregister_pm_notifier(&mali_pwr_notif_block); +#endif +#endif /* CONFIG_PM_RUNTIME */ + platform_device_unregister(&mali_gpu_device); + } + + return err; +} + +void mali_platform_device_unregister(void) +{ + MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n")); + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) + unregister_pm_notifier(&mali_pwr_notif_block); +#endif +#endif /* CONFIG_PM_RUNTIME */ + + mali_platform_deinit(&(mali_gpu_device.dev)); + + platform_device_unregister(&mali_gpu_device); +} + +static void mali_platform_device_release(struct device *device) +{ + MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n")); +} + +#ifdef CONFIG_PM_RUNTIME +#if defined(USE_PM_NOTIFIER) +static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy) +{ + int err = 0; + switch (event) + { + case PM_SUSPEND_PREPARE: + mali_pm_os_suspend(); + err = mali_os_suspend(&(mali_platform_device->dev)); + break; + + case PM_POST_SUSPEND: + err = mali_os_resume(&(mali_platform_device->dev)); + mali_pm_os_resume(); + break; + default: + break; + } + return err; +} + +static int mali_os_suspend(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n")); + +#ifdef CONFIG_MALI_DVFS + mali_utilization_suspend(); +#endif + + if (NULL != device && + NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->suspend) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->suspend(device); + } + + mali_platform_power_mode_change(device, MALI_POWER_MODE_DEEP_SLEEP); + + return ret; +} + +static int mali_os_resume(struct device *device) +{ + int ret = 0; + + MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n")); +#ifdef CONFIG_REGULATOR + mali_regulator_enable(); + g3d_power_domain_control(1); +#endif + mali_platform_power_mode_change(device, MALI_POWER_MODE_ON); + + if (NULL != device && + NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->resume) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->resume(device); + } + + return ret; +} + +static int mali_os_freeze(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n")); + + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->freeze) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->freeze(device); + } + + return ret; +} + +static int mali_os_thaw(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n")); + + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->thaw) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->thaw(device); + } + + return ret; +} + +static int mali_runtime_suspend(struct device *device) +{ + int ret = 0; + + MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n")); + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->runtime_suspend) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->runtime_suspend(device); + } + + mali_platform_power_mode_change(device, MALI_POWER_MODE_LIGHT_SLEEP); + + return ret; +} + +static int mali_runtime_resume(struct device *device) +{ + int ret = 0; + MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n")); + + mali_platform_power_mode_change(device, MALI_POWER_MODE_ON); + + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->runtime_resume) + { + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->runtime_resume(device); + } + + return ret; +} + +static int mali_runtime_idle(struct device *device) +{ + MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n")); + if (NULL != device->driver && + NULL != device->driver->pm && + NULL != device->driver->pm->runtime_idle) + { + int ret = 0; + /* Need to notify Mali driver about this event */ + ret = device->driver->pm->runtime_idle(device); + if (0 != ret) + { + return ret; + } + } + + return 1; +} + +#endif /* USE_PM_NOTIFIER */ +#endif /* CONFIG_PM_RUNTIME */ diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c new file mode 100644 index 0000000..346ad7f --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.c @@ -0,0 +1,1373 @@ +/* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4_pmm.c + * + * Copyright 2011 by S.LSI. Samsung Electronics Inc. + * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea + * + * Samsung SoC Mali400 DVFS driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software FoundatIon. + */ + +/** + * @file exynos4_pmm.c + * Platform specific Mali driver functions for the exynos 4XXX based platforms + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "exynos4_pmm.h" +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> + +#if defined(CONFIG_MALI400_PROFILING) +#include "mali_osk_profiling.h" +#endif + +#if defined(CONFIG_PM_RUNTIME) +#include <plat/pd.h> +#endif + +#include <asm/io.h> +#include <mach/regs-pmu.h> + +#include <linux/workqueue.h> + +#ifdef CONFIG_CPU_EXYNOS4210 +#define MALI_DVFS_STEPS 2 +#define MALI_DVFS_WATING 10 /* msec */ +#define MALI_DVFS_DEFAULT_STEP 0 +#else +#define MALI_DVFS_STEPS 5 +#define MALI_DVFS_WATING 10 /* msec */ +#define MALI_DVFS_DEFAULT_STEP 1 +#define PD_G3D_LOCK_FLAG 2 +#endif + +#ifdef CONFIG_CPU_FREQ +#include <mach/asv.h> +#define EXYNOS4_ASV_ENABLED +#endif + +#define MALI_DVFS_CLK_DEBUG 0 +#define SEC_THRESHOLD 1 + +#define CPUFREQ_LOCK_DURING_440 0 +#define CHIPID_REG (S5P_VA_CHIPID + 0x4) + +static int bMaliDvfsRun = 0; + +typedef struct mali_dvfs_tableTag{ + unsigned int clock; + unsigned int freq; + unsigned int vol; +#if SEC_THRESHOLD + unsigned int downthreshold; + unsigned int upthreshold; +#endif +}mali_dvfs_table; + +typedef struct mali_dvfs_statusTag{ + unsigned int currentStep; + mali_dvfs_table * pCurrentDvfs; + +} mali_dvfs_status_t; + +/* dvfs status */ +mali_dvfs_status_t maliDvfsStatus; +int mali_dvfs_control; + +typedef struct mali_runtime_resumeTag{ + int clk; + int vol; + unsigned int step; +}mali_runtime_resume_table; + +mali_runtime_resume_table mali_runtime_resume = {266, 900000, 1}; + +/* dvfs table */ +mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + /* step 0 */{160 ,1000000 ,875000 , 0 , 70}, + /* step 1 */{266 ,1000000 ,900000 ,62 , 90}, + /* step 2 */{350 ,1000000 ,950000 ,85 , 90}, + /* step 3 */{440 ,1000000 ,1025000 ,85 , 90}, + /* step 4 */{533 ,1000000 ,1075000 ,95 ,100} }; +#else + /* step 0 */{134 ,1000000 , 950000 ,85 , 90}, + /* step 1 */{267 ,1000000 ,1050000 ,85 ,100} }; +#endif + +#ifdef EXYNOS4_ASV_ENABLED +#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ +#define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ +#define ASV_LEVEL_PD 13 +#define ASV_LEVEL_4210_12 8 +#define ASV_LEVEL_4210_14 5 + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { + { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; +static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = { + { 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; + +static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = { + { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000, 850000}, /* L4(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 875000, 875000}, /* L3(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 912500, 900000, 887500}, /* L2(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 975000, 962500, 950000}, /* L1(440Mhz) */ +#if (MALI_DVFS_STEPS > 4) + { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1037500, 1025000, 1012500}, /* L0(533Mhz) */ +#endif +#endif +#endif +#endif +}; + +static unsigned int asv_3d_volt_4212_9_table[MALI_DVFS_STEPS][ASV_LEVEL_PD] = { + { 950000, 925000, 900000, 900000, 900000, 900000, 900000, 900000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 975000, 950000, 925000, 925000, 925000, 925000, 925000, 900000, 900000, 900000, 875000, 875000, 875000}, /* L2(266Mhz) */ +#if (MALI_DVFS_STEPS > 2) + { 1025000, 1000000, 975000, 975000, 975000, 950000, 950000, 925000, 925000, 925000, 925000, 900000, 875000}, /* L1(350Mhz) */ +#if (MALI_DVFS_STEPS > 3) + { 1100000, 1075000, 1050000, 1050000, 1050000, 1050000, 1025000, 1000000, 1000000, 975000, 975000, 950000, 925000}, /* L0(440Mhz) */ +#endif +#endif +#endif +}; + +#else + +static unsigned int asv_3d_volt_4210_12_table[MALI_DVFS_STEPS][ASV_LEVEL_4210_12] = { + { 1000000, 1000000, 1000000, 950000, 950000, 950000, 950000, 950000}, /* L1(134Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1100000, 1100000, 1100000, 1000000, 1000000, 1000000, 1000000, 950000}, /* L0(266Mhz) */ +#endif +}; + +static unsigned int asv_3d_volt_4210_14_table[MALI_DVFS_STEPS][ASV_LEVEL_4210_14] = { + { 1000000, 1000000, 950000, 950000, 950000}, /* L1(134Mhz) */ +#if (MALI_DVFS_STEPS > 1) + { 1100000, 1100000, 1000000, 1000000, 950000}, /* L0(266Mhz) */ +#endif +}; +#endif +#endif /* ASV_LEVEL */ + +#define EXTXTALCLK_NAME "ext_xtal" +#define VPLLSRCCLK_NAME "vpll_src" +#define FOUTVPLLCLK_NAME "fout_vpll" +#define SCLVPLLCLK_NAME "sclk_vpll" +#define GPUMOUT1CLK_NAME "mout_g3d1" + +#define MPLLCLK_NAME "mout_mpll" +#define GPUMOUT0CLK_NAME "mout_g3d0" +#define GPUCLK_NAME "sclk_g3d" +#define CLK_DIV_STAT_G3D 0x1003C62C +#define CLK_DESC "clk-divider-status" + +static struct clk *ext_xtal_clock = NULL; +static struct clk *vpll_src_clock = NULL; +static struct clk *fout_vpll_clock = NULL; +static struct clk *sclk_vpll_clock = NULL; + +static struct clk *mpll_clock = NULL; +static struct clk *mali_parent_clock = NULL; +static struct clk *mali_mout0_clock = NULL; +static struct clk *mali_clock = NULL; + +#if defined(CONFIG_CPU_EXYNOS4412) || defined(CONFIG_CPU_EXYNOS4212) +/* Pegasus */ +static const mali_bool bis_vpll = MALI_TRUE; +int mali_gpu_clk = 440; +int mali_gpu_vol = 1025000; +#else +/* Orion */ +static const mali_bool bis_vpll = MALI_FALSE; +int mali_gpu_clk = 267; +int mali_gpu_vol = 1050000; +#endif + +static unsigned int GPU_MHZ = 1000000; + +int gpu_power_state; +static int bPoweroff; +atomic_t clk_active; + +#define MAX_MALI_DVFS_STEPS 5 +static _mali_osk_atomic_t bottomlock_status; +int bottom_lock_step = 0; + +#if MALI_VOLTAGE_LOCK +int mali_lock_vol = 0; +static _mali_osk_atomic_t voltage_lock_status; +static mali_bool mali_vol_lock_flag = 0; +#endif + +/* Declare for sysfs */ +#ifdef CONFIG_MALI_DVFS +module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS"); + +DEVICE_ATTR(time_in_state, S_IRUGO|S_IWUSR, show_time_in_state, set_time_in_state); +MODULE_PARM_DESC(time_in_state, "Time-in-state of Mali DVFS"); +#endif + +module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock"); + +module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage"); + +module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(gpu_power_state, "Mali Power State"); + +#ifdef CONFIG_REGULATOR +struct regulator *g3d_regulator = NULL; +#endif + +mali_io_address clk_register_map = 0; + +/* DVFS */ +static unsigned int mali_dvfs_utilization = 255; +u64 mali_dvfs_time[MALI_DVFS_STEPS]; +#ifdef CONFIG_MALI_DVFS +static void update_time_in_state(int level); +#endif +static void mali_dvfs_work_handler(struct work_struct *w); +static struct workqueue_struct *mali_dvfs_wq = 0; +extern mali_io_address clk_register_map; +_mali_osk_lock_t *mali_dvfs_lock; +int mali_runtime_resumed = -1; +static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); + +#ifdef CONFIG_REGULATOR +void mali_regulator_disable(void) +{ + if(IS_ERR_OR_NULL(g3d_regulator)) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); + return; + } + regulator_disable(g3d_regulator); +} + +void mali_regulator_enable(void) +{ + if(IS_ERR_OR_NULL(g3d_regulator)) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); + return; + } + regulator_enable(g3d_regulator); +} + +void mali_regulator_set_voltage(int min_uV, int max_uV) +{ + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + if(IS_ERR_OR_NULL(g3d_regulator)) + { + MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return; + } + MALI_PRINT(("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); + regulator_set_voltage(g3d_regulator, min_uV, max_uV); + mali_gpu_vol = regulator_get_voltage(g3d_regulator); + MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol)); + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); +} +#endif + +unsigned long mali_clk_get_rate(void) +{ + return clk_get_rate(mali_clock); +} + + +static unsigned int get_mali_dvfs_status(void) +{ + return maliDvfsStatus.currentStep; +} + +mali_bool mali_clk_get(void) +{ + if (bis_vpll) + { + if (ext_xtal_clock == NULL) + { + ext_xtal_clock = clk_get(NULL, EXTXTALCLK_NAME); + if (IS_ERR(ext_xtal_clock)) { + MALI_PRINT(("MALI Error : failed to get source ext_xtal_clock\n")); + return MALI_FALSE; + } + } + + if (vpll_src_clock == NULL) + { + vpll_src_clock = clk_get(NULL, VPLLSRCCLK_NAME); + if (IS_ERR(vpll_src_clock)) { + MALI_PRINT(("MALI Error : failed to get source vpll_src_clock\n")); + return MALI_FALSE; + } + } + + if (fout_vpll_clock == NULL) + { + fout_vpll_clock = clk_get(NULL, FOUTVPLLCLK_NAME); + if (IS_ERR(fout_vpll_clock)) { + MALI_PRINT(("MALI Error : failed to get source fout_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (sclk_vpll_clock == NULL) + { + sclk_vpll_clock = clk_get(NULL, SCLVPLLCLK_NAME); + if (IS_ERR(sclk_vpll_clock)) { + MALI_PRINT(("MALI Error : failed to get source sclk_vpll_clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT(( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + + if (mali_mout0_clock == NULL) + { + mali_mout0_clock = clk_get(NULL, GPUMOUT0CLK_NAME); + + if (IS_ERR(mali_mout0_clock)) { + MALI_PRINT( ( "MALI Error : failed to get source mali mout0 clock\n")); + return MALI_FALSE; + } + } + } + else /* mpll */ + { + if (mpll_clock == NULL) + { + mpll_clock = clk_get(NULL, MPLLCLK_NAME); + + if (IS_ERR(mpll_clock)) { + MALI_PRINT(("MALI Error : failed to get source mpll clock\n")); + return MALI_FALSE; + } + } + + if (mali_parent_clock == NULL) + { + mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); + + if (IS_ERR(mali_parent_clock)) { + MALI_PRINT(( "MALI Error : failed to get source mali parent clock\n")); + return MALI_FALSE; + } + } + } + + /* mali clock get always. */ + if (mali_clock == NULL) + { + mali_clock = clk_get(NULL, GPUCLK_NAME); + + if (IS_ERR(mali_clock)) { + MALI_PRINT(("MALI Error : failed to get source mali clock\n")); + return MALI_FALSE; + } + } + + return MALI_TRUE; +} + +void mali_clk_put(mali_bool binc_mali_clock) +{ + if (mali_parent_clock) + { + clk_put(mali_parent_clock); + mali_parent_clock = NULL; + } + + if (mali_mout0_clock) + { + clk_put(mali_mout0_clock); + mali_mout0_clock = NULL; + } + + if (mpll_clock) + { + clk_put(mpll_clock); + mpll_clock = NULL; + } + + if (sclk_vpll_clock) + { + clk_put(sclk_vpll_clock); + sclk_vpll_clock = NULL; + } + + if (binc_mali_clock && fout_vpll_clock) + { + clk_put(fout_vpll_clock); + fout_vpll_clock = NULL; + } + + if (vpll_src_clock) + { + clk_put(vpll_src_clock); + vpll_src_clock = NULL; + } + + if (ext_xtal_clock) + { + clk_put(ext_xtal_clock); + ext_xtal_clock = NULL; + } + + if (binc_mali_clock && mali_clock) + { + clk_put(mali_clock); + mali_clock = NULL; + } +} + +void mali_clk_set_rate(unsigned int clk, unsigned int mhz) +{ + int err; + unsigned long rate = (unsigned long)clk * (unsigned long)mhz; + + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk)); + + if (mali_clk_get() == MALI_FALSE) { + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return; + } + + if (bis_vpll) + { + clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); + clk_set_parent(vpll_src_clock, ext_xtal_clock); + clk_set_parent(sclk_vpll_clock, fout_vpll_clock); + + clk_set_parent(mali_parent_clock, sclk_vpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + else + { + clk_set_parent(mali_parent_clock, mpll_clock); + clk_set_parent(mali_clock, mali_parent_clock); + } + + if (atomic_read(&clk_active) == 0) { + if (clk_enable(mali_clock) < 0) { + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return; + } + atomic_set(&clk_active, 1); + } + + err = clk_set_rate(mali_clock, rate); + if (err > 0) + MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err)); + + rate = mali_clk_get_rate(); + + MALI_PRINT(("Mali frequency %d\n", rate / mhz)); + GPU_MHZ = mhz; + mali_gpu_clk = (int)(rate / mhz); + + mali_clk_put(MALI_FALSE); + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); +} + +int get_mali_dvfs_control_status(void) +{ + return mali_dvfs_control; +} + +mali_bool set_mali_dvfs_current_step(unsigned int step) +{ + _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + maliDvfsStatus.currentStep = step % MALI_DVFS_STEPS; + if (step >= MALI_DVFS_STEPS) + mali_runtime_resumed = maliDvfsStatus.currentStep; + + _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); + return MALI_TRUE; +} + + +static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) +{ + u32 validatedStep=step; +#if MALI_DVFS_CLK_DEBUG + unsigned int *pRegMaliClkDiv; + unsigned int *pRegMaliMpll; +#endif + + if(boostup) { +#ifdef CONFIG_REGULATOR + /* change the voltage */ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + /* change the clock */ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); + } else { + /* change the clock */ + mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); +#ifdef CONFIG_REGULATOR + /* change the voltage */ + mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); +#endif + } + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_EVENT_CHANNEL_GPU| + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); +#endif + mali_clk_put(MALI_FALSE); + +#if MALI_DVFS_CLK_DEBUG + pRegMaliClkDiv = ioremap(0x1003c52c,32); + pRegMaliMpll = ioremap(0x1003c22c,32); + MALI_PRINT(("Mali MPLL reg:%d, CLK DIV: %d \n",*pRegMaliMpll, *pRegMaliClkDiv)); +#endif + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_dvfs[step].clock == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif + + set_mali_dvfs_current_step(validatedStep); + /* for future use */ + maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; + +#if CPUFREQ_LOCK_DURING_440 + /* lock/unlock CPU freq by Mali */ + if (mali_dvfs[step].clock >= 440) + err = cpufreq_lock_by_mali(400); + else + cpufreq_unlock_by_mali(); +#endif + + + return MALI_TRUE; +} + +static void mali_platform_wating(u32 msec) +{ + /* + * sample wating + * change this in the future with proper check routine. + */ + unsigned int read_val; + while(1) { + read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); + if ((read_val & 0x8000)==0x0000) break; + + _mali_osk_time_ubusydelay(100); /* 1000 -> 100 : 20101218 */ + } +} + +static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) +{ + MALI_DEBUG_PRINT(4, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); + + if (!set_mali_dvfs_status(step, boostup)) { + MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); + return MALI_FALSE; + } + + /* wait until clock and voltage is stablized */ + mali_platform_wating(MALI_DVFS_WATING); /* msec */ + + return MALI_TRUE; +} + +#ifdef EXYNOS4_ASV_ENABLED +extern unsigned int exynos_result_of_asv; + +static mali_bool mali_dvfs_table_update(void) +{ + unsigned int step_num = MALI_DVFS_STEPS; + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + unsigned int i, tmp, g3d_lock_volt = 0; + bool lock_flag_g3d = false; + + if(samsung_rev() < EXYNOS4412_REV_2_0) + step_num = MALI_DVFS_STEPS - 1; + + if(soc_is_exynos4412()) { + if (exynos_armclk_max == 1000000) { + MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) { + MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } else if (samsung_rev() >= EXYNOS4412_REV_2_0) { + MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } else { + MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv]; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } + } + else if(soc_is_exynos4212()) { + tmp = __raw_readl(CHIPID_REG); + lock_flag_g3d = (tmp >> PD_G3D_LOCK_FLAG) & 0x1; + if (lock_flag_g3d) + g3d_lock_volt = 25000; + + for (i = 0; i < step_num; i++) { + MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + mali_dvfs[i].vol = asv_3d_volt_4212_9_table[i][exynos_result_of_asv] + g3d_lock_volt; + MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } + } +#else + unsigned int i, exynos_result_of_asv_group, target_asv; + + exynos_result_of_asv_group = exynos_result_of_asv & 0xf; + target_asv = exynos_result_of_asv >> 28; + MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv)); + + for (i = 0; i < step_num; i++) { + if (target_asv == 0x8) { //SUPPORT_1400MHZ + mali_dvfs[i].vol = asv_3d_volt_4210_14_table[i][exynos_result_of_asv_group]; + } else if (target_asv == 0x4){ //SUPPORT_1200MHZ + mali_dvfs[i].vol = asv_3d_volt_4210_12_table[i][exynos_result_of_asv_group]; + } + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + + // Update voltage using for resume + if (mali_runtime_resume.clk == mali_dvfs[i].clock) { + mali_runtime_resume.vol = mali_dvfs[i].vol; + + MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol)); + } + + // update voltage using for init timing + if (mali_gpu_clk == mali_dvfs[i].clock) { + mali_gpu_vol = mali_dvfs[i].vol; + + MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol)); + } + } +#endif + + return MALI_TRUE; +} +#endif + +static unsigned int decideNextStatus(unsigned int utilization) +{ + static unsigned int level = 0; + int iStepCount = 0; + if (mali_runtime_resumed >= 0) { + level = mali_runtime_resumed; + mali_runtime_resumed = -1; + } + + if (mali_dvfs_control == 0 && level == get_mali_dvfs_status()) { + if (utilization > (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].upthreshold / 100) && + level < MALI_DVFS_STEPS - 1) { + level++; + if ((samsung_rev() < EXYNOS4412_REV_2_0) && 3 == get_mali_dvfs_status()) { + level=get_mali_dvfs_status(); + } + } + else if (utilization < (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].downthreshold / 100) && + level > 0) { + level--; + } + + if (_mali_osk_atomic_read(&bottomlock_status) > 0) { + if (level < bottom_lock_step) + level = bottom_lock_step; + } + } else { + for (iStepCount = MALI_DVFS_STEPS-1; iStepCount >= 0; iStepCount--) { + if ( mali_dvfs_control >= mali_dvfs[iStepCount].clock ) { + level = iStepCount; + break; + } + } + } + + return level; +} + + +static mali_bool mali_dvfs_status(unsigned int utilization) +{ + unsigned int nextStatus = 0; + unsigned int curStatus = 0; + mali_bool boostup = MALI_FALSE; + static int stay_count = 5; + + MALI_DEBUG_PRINT(4, ("> mali_dvfs_status: %d \n",utilization)); + + /* decide next step */ + curStatus = get_mali_dvfs_status(); + nextStatus = decideNextStatus(utilization); + + MALI_DEBUG_PRINT(4, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); + /* if next status is same with current status, don't change anything */ + if(curStatus != nextStatus) { + /*check if boost up or not*/ + if(maliDvfsStatus.currentStep < nextStatus) { + boostup = 1; + stay_count = 5; + } else if (maliDvfsStatus.currentStep > nextStatus){ + stay_count--; + } + if( boostup == 1 || stay_count <= 0){ + /*change mali dvfs status*/ +#ifdef CONFIG_MALI_DVFS + update_time_in_state(curStatus); +#endif + if (!change_mali_dvfs_status(nextStatus,boostup)) { + MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); + return MALI_FALSE; + } + boostup = 0; + stay_count = 5; + } + } + else + stay_count = 5; + return MALI_TRUE; +} + + +int mali_dvfs_is_running(void) +{ + return bMaliDvfsRun; +} + + +static void mali_dvfs_work_handler(struct work_struct *w) +{ + bMaliDvfsRun=1; + + MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); + + if(!mali_dvfs_status(mali_dvfs_utilization)) + MALI_DEBUG_PRINT(1, ( "error on mali dvfs status in mali_dvfs_work_handler")); + + bMaliDvfsRun=0; +} + +mali_bool init_mali_dvfs_status(void) +{ + /* + * default status + * add here with the right function to get initilization value. + */ + + if (!mali_dvfs_wq) + mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); + + _mali_osk_atomic_init(&bottomlock_status, 0); + + /* add a error handling here */ + maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP; + + return MALI_TRUE; +} + +void deinit_mali_dvfs_status(void) +{ + if (mali_dvfs_wq) + destroy_workqueue(mali_dvfs_wq); + + _mali_osk_atomic_term(&bottomlock_status); + + mali_dvfs_wq = NULL; +} + +mali_bool mali_dvfs_handler(unsigned int utilization) +{ + mali_dvfs_utilization = utilization; + queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work); + + return MALI_TRUE; +} + +static mali_bool init_mali_clock(void) +{ + mali_bool ret = MALI_TRUE; + gpu_power_state = 1; + bPoweroff = 1; + + if (mali_clock != 0) + return ret; /* already initialized */ + + mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE + | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); + if (mali_dvfs_lock == NULL) + return _MALI_OSK_ERR_FAULT; + + if (!mali_clk_get()) + { + MALI_PRINT(("Error: Failed to get Mali clock\n")); + goto err_clk; + } + + mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ); + + MALI_PRINT(("init_mali_clock mali_clock %x\n", mali_clock)); + +#ifdef CONFIG_REGULATOR + g3d_regulator = regulator_get(NULL, "vdd_g3d"); + + if (IS_ERR(g3d_regulator)) + { + MALI_PRINT(("MALI Error : failed to get vdd_g3d\n")); + ret = MALI_FALSE; + goto err_regulator; + } + + regulator_enable(g3d_regulator); + mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_gpu_clk == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif +#endif + +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| + MALI_PROFILING_EVENT_CHANNEL_GPU| + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); +#endif + + mali_clk_put(MALI_FALSE); + + return MALI_TRUE; + +#ifdef CONFIG_REGULATOR +err_regulator: + regulator_put(g3d_regulator); +#endif +err_clk: + mali_clk_put(MALI_TRUE); + + return ret; +} + +static mali_bool deinit_mali_clock(void) +{ + if (mali_clock == 0) + return MALI_TRUE; + +#ifdef CONFIG_REGULATOR + if (g3d_regulator) + { + regulator_put(g3d_regulator); + g3d_regulator = NULL; + } +#endif + + mali_clk_put(MALI_TRUE); + + return MALI_TRUE; +} + + +static _mali_osk_errcode_t enable_mali_clocks(void) +{ + int err; + + if (atomic_read(&clk_active) == 0) { + err = clk_enable(mali_clock); + MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); + atomic_set(&clk_active, 1); + gpu_power_state = 1; + } + + /* set clock rate */ +#ifdef CONFIG_MALI_DVFS + if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) { + mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); + } else { +#ifdef CONFIG_REGULATOR + mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); + +#ifdef EXYNOS4_ASV_ENABLED + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_runtime_resume.clk == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } +#endif +#endif + mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); + set_mali_dvfs_current_step(mali_runtime_resume.step); + } +#else + mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ); + maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP; +#endif + + + MALI_SUCCESS; +} + +static _mali_osk_errcode_t disable_mali_clocks(void) +{ + if (atomic_read(&clk_active) == 1) { + clk_disable(mali_clock); + atomic_set(&clk_active, 0); + gpu_power_state = 0; + } + MALI_DEBUG_PRINT(3, ("disable_mali_clocks mali_clock %p \n", mali_clock)); + + MALI_SUCCESS; +} + +/* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */ +#ifndef S5P_G3D_CONFIGURATION +#define S5P_G3D_CONFIGURATION S5P_PMU_G3D_CONF +#endif +#ifndef S5P_G3D_STATUS +#define S5P_G3D_STATUS S5P_PMU_G3D_CONF + 0x4 +#endif + +_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) +{ + if (bpower_on) + { + void __iomem *status; + u32 timeout; + __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_G3D_CONFIGURATION); + status = S5P_G3D_STATUS; + + timeout = 10; + while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + != S5P_INT_LOCAL_PWR_EN) { + if (timeout == 0) { + MALI_PRINTF(("Power domain enable failed.\n")); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay(100); + } + } + else + { + void __iomem *status; + u32 timeout; + __raw_writel(0, S5P_G3D_CONFIGURATION); + + status = S5P_G3D_STATUS; + /* Wait max 1ms */ + timeout = 10; + while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) + { + if (timeout == 0) { + MALI_PRINTF(("Power domain disable failed.\n" )); + return -ETIMEDOUT; + } + timeout--; + _mali_osk_time_ubusydelay(100); + } + } + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_init(struct device *dev) +{ +#ifdef EXYNOS4_ASV_ENABLED + mali_dvfs_table_update(); +#endif + + MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); + + atomic_set(&clk_active, 0); + +#ifdef CONFIG_MALI_DVFS + /* Create sysfs for time-in-state */ + if (device_create_file(dev, &dev_attr_time_in_state)) { + dev_err(dev, "Couldn't create sysfs file [time_in_state]\n"); + } + + if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); + if (!init_mali_dvfs_status()) + MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); +#endif + + mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON); + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_deinit(struct device *dev) +{ + + mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP); + deinit_mali_clock(); + +#ifdef CONFIG_MALI_DVFS + deinit_mali_dvfs_status(); + if (clk_register_map ) + { + _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); + clk_register_map = NULL; + } +#endif + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode) +{ + switch (power_mode) + { + case MALI_POWER_MODE_ON: + MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", + bPoweroff ? "powering on" : "already on")); + if (bPoweroff == 1) + { +#if !defined(CONFIG_PM_RUNTIME) + g3d_power_domain_control(1); +#endif + MALI_DEBUG_PRINT(4, ("enable clock \n")); + enable_mali_clocks(); +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); + +#endif + bPoweroff=0; + } + break; + case MALI_POWER_MODE_LIGHT_SLEEP: + case MALI_POWER_MODE_DEEP_SLEEP: + MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode == + MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : + "MALI_POWER_MODE_DEEP_SLEEP", bPoweroff ? "already off" : "powering off")); + if (bPoweroff == 0) + { + disable_mali_clocks(); +#if defined(CONFIG_MALI400_PROFILING) + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + 0, 0, 0, 0, 0); +#endif + +#if !defined(CONFIG_PM_RUNTIME) + g3d_power_domain_control(0); +#endif + bPoweroff=1; + } + + break; + } + MALI_SUCCESS; +} + +void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data) +{ + if (bPoweroff==0) + { +#ifdef CONFIG_MALI_DVFS + if(!mali_dvfs_handler(data->utilization_gpu)) + MALI_DEBUG_PRINT(1, ("error on mali dvfs status in utilization\n")); +#endif + } +} + +#ifdef CONFIG_CPU_EXYNOS4210 +int mali_dvfs_bottom_lock_push() +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu bottom lock status is not valid for push\n")); + return -1; + } + if (prev_status == 0) { + mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol); + mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq); + set_mali_dvfs_current_step(1); + } + return _mali_osk_atomic_inc_return(&bottomlock_status); +} +#else +int mali_dvfs_bottom_lock_push(int lock_step) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu bottom lock status is not valid for push\n")); + return -1; + } + if (bottom_lock_step < lock_step) { + bottom_lock_step = lock_step; + if (get_mali_dvfs_status() < lock_step) { + mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol); + mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq); + set_mali_dvfs_current_step(lock_step); + } + } + return _mali_osk_atomic_inc_return(&bottomlock_status); +} +#endif + +int mali_dvfs_bottom_lock_pop(void) +{ + int prev_status = _mali_osk_atomic_read(&bottomlock_status); + if (prev_status <= 0) { + MALI_PRINT(("gpu bottom lock status is not valid for pop\n")); + return -1; + } else if (prev_status == 1) { + bottom_lock_step = 0; + MALI_PRINT(("gpu bottom lock release\n")); + } + + return _mali_osk_atomic_dec_return(&bottomlock_status); +} + +int mali_dvfs_get_vol(int step) +{ + step = step % MAX_MALI_DVFS_STEPS; + MALI_DEBUG_ASSERT(step<MAX_MALI_DVFS_STEPS); + return mali_dvfs[step].vol; +} + +#if MALI_VOLTAGE_LOCK +int mali_voltage_lock_push(int lock_vol) +{ + int prev_status = _mali_osk_atomic_read(&voltage_lock_status); + + if (prev_status < 0) { + MALI_PRINT(("gpu voltage lock status is not valid for push\n")); + return -1; + } + if (prev_status == 0) { + mali_lock_vol = lock_vol; + if (mali_gpu_vol < mali_lock_vol) + mali_regulator_set_voltage(mali_lock_vol, mali_lock_vol); + } else { + MALI_PRINT(("gpu voltage lock status is already pushed, current lock voltage : %d\n", mali_lock_vol)); + return -1; + } + + return _mali_osk_atomic_inc_return(&voltage_lock_status); +} + +int mali_voltage_lock_pop(void) +{ + if (_mali_osk_atomic_read(&voltage_lock_status) <= 0) { + MALI_PRINT(("gpu voltage lock status is not valid for pop\n")); + return -1; + } + return _mali_osk_atomic_dec_return(&voltage_lock_status); +} + +int mali_voltage_lock_init(void) +{ + mali_vol_lock_flag = MALI_TRUE; + + MALI_SUCCESS; +} + +int mali_vol_get_from_table(int vol) +{ + int i; + for (i = 0; i < MALI_DVFS_STEPS; i++) { + if (mali_dvfs[i].vol >= vol) + return mali_dvfs[i].vol; + } + MALI_PRINT(("Failed to get voltage from mali_dvfs table, maximum voltage is %d uV\n", mali_dvfs[MALI_DVFS_STEPS-1].vol)); + return 0; +} +#endif + +#ifdef CONFIG_MALI_DVFS +static void update_time_in_state(int level) +{ + u64 current_time; + static u64 prev_time=0; + + if (prev_time ==0) + prev_time=get_jiffies_64(); + + current_time = get_jiffies_64(); + mali_dvfs_time[level] += current_time-prev_time; + prev_time = current_time; +} + +ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int i; + + update_time_in_state(maliDvfsStatus.currentStep); + + for (i = 0; i < MALI_DVFS_STEPS; i++) { + ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d %llu\n", + mali_dvfs[i].clock, + mali_dvfs_time[i]); + } + + if (ret < PAGE_SIZE - 1) { + ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n"); + } else { + buf[PAGE_SIZE-2] = '\n'; + buf[PAGE_SIZE-1] = '\0'; + ret = PAGE_SIZE-1; + } + + return ret; +} + +ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int i; + + for (i = 0; i < MALI_DVFS_STEPS; i++) { + mali_dvfs_time[i] = 0; + } + + return count; +} +#endif diff --git a/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h new file mode 100644 index 0000000..1b9cf57 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/mali/platform/pegasus-m400/exynos4_pmm.h @@ -0,0 +1,121 @@ +/* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4_pmm.h + * + * Copyright 2011 by S.LSI. Samsung Electronics Inc. + * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea + * + * Samsung SoC Mali400 DVFS driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software FoundatIon. + */ + +/** + * @file exynos4_pmm.h + * Platform specific Mali driver functions for the exynos 4XXX based platforms + */ + +#ifndef __EXYNOS4_PMM_H__ +#define __EXYNOS4_PMM_H__ + +#include "mali_utgard.h" +#include "mali_osk.h" +#include <linux/platform_device.h> +/* @Enable or Disable Mali GPU Bottom Lock feature */ +#define MALI_GPU_BOTTOM_LOCK 1 +#define MALI_VOLTAGE_LOCK 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief description of power change reasons + */ +typedef enum mali_power_mode_tag +{ + MALI_POWER_MODE_ON, + MALI_POWER_MODE_LIGHT_SLEEP, + MALI_POWER_MODE_DEEP_SLEEP, +} mali_power_mode; + +/** @brief Platform specific setup and initialisation of MALI + * + * This is called from the entrypoint of the driver to initialize the platform + * + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_init(struct device *dev); + +/** @brief Platform specific deinitialisation of MALI + * + * This is called on the exit of the driver to terminate the platform + * + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_deinit(struct device *dev); + +/** @brief Platform specific powerdown sequence of MALI + * + * Call as part of platform init if there is no PMM support, else the + * PMM will call it. + * There are three power modes defined: + * 1) MALI_POWER_MODE_ON + * 2) MALI_POWER_MODE_LIGHT_SLEEP + * 3) MALI_POWER_MODE_DEEP_SLEEP + * MALI power management module transitions to MALI_POWER_MODE_LIGHT_SLEEP mode when MALI is idle + * for idle timer (software timer defined in mali_pmm_policy_jobcontrol.h) duration, MALI transitions + * to MALI_POWER_MODE_LIGHT_SLEEP mode during timeout if there are no more jobs queued. + * MALI power management module transitions to MALI_POWER_MODE_DEEP_SLEEP mode when OS does system power + * off. + * Customer has to add power down code when MALI transitions to MALI_POWER_MODE_LIGHT_SLEEP or MALI_POWER_MODE_DEEP_SLEEP + * mode. + * MALI_POWER_MODE_ON mode is entered when the MALI is to powered up. Some customers want to control voltage regulators during + * the whole system powers on/off. Customer can track in this function whether the MALI is powered up from + * MALI_POWER_MODE_LIGHT_SLEEP or MALI_POWER_MODE_DEEP_SLEEP mode and manage the voltage regulators as well. + * @param power_mode defines the power modes + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode); + + +/** @brief Platform specific handling of GPU utilization data + * + * When GPU utilization data is enabled, this function will be + * periodically called. + * + * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. + */ +void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data); + +_mali_osk_errcode_t g3d_power_domain_control(int bpower_on); + +#ifdef CONFIG_REGULATOR +void mali_regulator_disable(void); +void mali_regulator_enable(void); +void mali_regulator_set_voltage(int min_uV, int max_uV); +#endif + +#ifdef CONFIG_MALI_DVFS +ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf); +ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +#ifdef CONFIG_CPU_EXYNOS4210 +#if MALI_GPU_BOTTOM_LOCK +int mali_dvfs_bottom_lock_push(void); +int mali_dvfs_bottom_lock_pop(void); +#endif +#else +int mali_dvfs_bottom_lock_push(int lock_step); +int mali_dvfs_bottom_lock_pop(void); +#endif +#endif + +#if MALI_VOLTAGE_LOCK +int mali_voltage_lock_push(int lock_vol); +int mali_voltage_lock_pop(void); +int mali_voltage_lock_init(void); +int mali_vol_get_from_table(int vol); +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/drivers/media/video/samsung/mali/regs/mali_200_regs.h b/drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h index 59e92c8..dd75149 100644 --- a/drivers/media/video/samsung/mali/regs/mali_200_regs.h +++ b/drivers/gpu/mali400/r3p2/mali/regs/mali_200_regs.h @@ -46,14 +46,10 @@ enum mali200_mgmt_reg enum mali200_mgmt_ctrl_mgmt { MALI200_REG_VAL_CTRL_MGMT_STOP_BUS = (1<<0), -#if defined(USING_MALI200) MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES = (1<<3), -#endif MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET = (1<<5), MALI200_REG_VAL_CTRL_MGMT_START_RENDERING = (1<<6), -#if defined(USING_MALI400) || defined(USING_MALI450) - MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7), -#endif + MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7), /* Only valid for Mali-300 and later */ }; enum mali200_mgmt_irq { @@ -72,18 +68,6 @@ enum mali200_mgmt_irq { MALI400PP_REG_VAL_IRQ_RESET_COMPLETED = (1<<12), }; -#if defined(USING_MALI200) -#define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ - MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_END_OF_TILE |\ - MALI200_REG_VAL_IRQ_HANG |\ - MALI200_REG_VAL_IRQ_FORCE_HANG |\ - MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_BUS_STOP |\ - MALI200_REG_VAL_IRQ_CNT_0_LIMIT |\ - MALI200_REG_VAL_IRQ_CNT_1_LIMIT |\ - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR)) -#elif defined(USING_MALI400) || defined(USING_MALI450) #define MALI200_REG_VAL_IRQ_MASK_ALL ((enum mali200_mgmt_irq) (\ MALI200_REG_VAL_IRQ_END_OF_FRAME |\ MALI200_REG_VAL_IRQ_END_OF_TILE |\ @@ -98,31 +82,15 @@ enum mali200_mgmt_irq { MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW |\ MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)) -#else -#error "No supported mali core defined" -#endif -#if defined(USING_MALI200) #define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_HANG |\ MALI200_REG_VAL_IRQ_FORCE_HANG |\ MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR)) -#elif defined(USING_MALI400) || defined(USING_MALI450) -#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\ - MALI200_REG_VAL_IRQ_END_OF_FRAME |\ - MALI200_REG_VAL_IRQ_HANG |\ - MALI200_REG_VAL_IRQ_FORCE_HANG |\ - MALI200_REG_VAL_IRQ_BUS_ERROR |\ - MALI200_REG_VAL_IRQ_BUS_STOP |\ MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR |\ MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\ MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\ MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW)) -#else -#error "No supported mali core defined" -#endif #define MALI200_REG_VAL_IRQ_MASK_NONE ((enum mali200_mgmt_irq)(0)) @@ -134,19 +102,12 @@ enum mali200_mgmt_status { enum mali200_render_unit { MALI200_REG_ADDR_FRAME = 0x0000, - MALI200_REG_ADDR_STACK = 0x0030 + MALI200_REG_ADDR_RSW = 0x0004, + MALI200_REG_ADDR_STACK = 0x0030, + MALI200_REG_ADDR_STACK_SIZE = 0x0034, + MALI200_REG_ADDR_ORIGIN_OFFSET_X = 0x0040 }; -#if defined(USING_MALI200) -#define MALI200_NUM_REGS_FRAME ((0x04C/4)+1) -#elif defined(USING_MALI400) -#define MALI200_NUM_REGS_FRAME ((0x058/4)+1) -#elif defined(USING_MALI450) -#define MALI200_NUM_REGS_FRAME ((0x058/4)+1) -#else -#error "No supported mali core defined" -#endif - enum mali200_wb_unit { MALI200_REG_ADDR_WB0 = 0x0100, MALI200_REG_ADDR_WB1 = 0x0200, @@ -157,11 +118,6 @@ enum mali200_wb_unit_regs { MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000, }; -/** The number of registers in one single writeback unit */ -#ifndef MALI200_NUM_REGS_WBx -#define MALI200_NUM_REGS_WBx ((0x02C/4)+1) -#endif - /* This should be in the top 16 bit of the version register of Mali PP */ #define MALI200_PP_PRODUCT_ID 0xC807 #define MALI300_PP_PRODUCT_ID 0xCE07 diff --git a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h b/drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h index 21c83c0..c204901 100644 --- a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h +++ b/drivers/gpu/mali400/r3p2/mali/regs/mali_gp_regs.h @@ -60,9 +60,7 @@ typedef enum MALIGP2_REG_VAL_CMD_RESET = (1<< 5), MALIGP2_REG_VAL_CMD_FORCE_HANG = (1<< 6), MALIGP2_REG_VAL_CMD_STOP_BUS = (1<< 9), -#if defined(USING_MALI400) || defined(USING_MALI450) - MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10), -#endif + MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10), /* only valid for Mali-300 and later */ } mgp_contr_reg_val_cmd; @@ -84,7 +82,6 @@ typedef enum #define MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR (1 << 9) #define MALIGP2_REG_VAL_IRQ_SYNC_ERROR (1 << 10) #define MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR (1 << 11) -#if defined(USING_MALI400) || defined(USING_MALI450) #define MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED (1 << 12) #define MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD (1 << 13) #define MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD (1 << 14) @@ -92,27 +89,8 @@ typedef enum #define MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW (1 << 20) #define MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW (1 << 21) #define MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS (1 << 22) -#elif !defined USING_MALI200 -#error "No supported mali core defined" -#endif -/* Mask defining all IRQs in MaliGP2 */ -#if defined(USING_MALI200) -#define MALIGP2_REG_VAL_IRQ_MASK_ALL \ - (\ - MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ | \ - MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ | \ - MALIGP2_REG_VAL_IRQ_HANG | \ - MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ - MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT | \ - MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT | \ - MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ - MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR) -#elif defined(USING_MALI400) || defined(USING_MALI450) +/* Mask defining all IRQs in Mali GP */ #define MALIGP2_REG_VAL_IRQ_MASK_ALL \ (\ MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ @@ -134,41 +112,22 @@ typedef enum MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) -#else -#error "No supported mali core defined" -#endif -/* Mask defining the IRQs in MaliGP2 which we use*/ -#if defined(USING_MALI200) +/* Mask defining the IRQs in Mali GP which we use */ #define MALIGP2_REG_VAL_IRQ_MASK_USED \ (\ MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_HANG | \ MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ - MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR) -#elif defined(USING_MALI400) || defined(USING_MALI450) -#define MALIGP2_REG_VAL_IRQ_MASK_USED \ - (\ - MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ - MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ - MALIGP2_REG_VAL_IRQ_HANG | \ - MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ - MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ - MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ + MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR | \ MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD | \ MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD | \ MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \ MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW | \ MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) -#else -#error "No supported mali core defined" -#endif /* Mask defining non IRQs on MaliGP2*/ #define MALIGP2_REG_VAL_IRQ_MASK_NONE 0 diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.c index 2426853..a6b1d76 100644 --- a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.h index 0551726..3279dae 100644 --- a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-arm11-cc/mali_timestamp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.c index 2426853..a6b1d76 100644 --- a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.h index e6d3f2a..94b842a 100644 --- a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h +++ b/drivers/gpu/mali400/r3p2/mali/timestamp-default/mali_timestamp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/gpu/mali400/r3p2/ump/Kbuild b/drivers/gpu/mali400/r3p2/ump/Kbuild new file mode 100644 index 0000000..4ca1aae --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Kbuild @@ -0,0 +1,78 @@ +# +# Copyright (C) 2010-2012 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. +# + +# Set default configuration to use, if Makefile didn't provide one. +# Change this to use a different config.h +# MALI_SEC +# CONFIG ?= os_memory_64m +CONFIG ?= pegasus-m400 + +# Validate selected config +ifneq ($(shell [ -d $(srctree)/$(src)/arch-$(CONFIG) ] && [ -f $(srctree)/$(src)/arch-$(CONFIG)/config.h ] && echo "OK"), OK) +$(warning Current directory is $(srctree)/$(src)) +$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) +else +# Link arch to the selected arch-config directory +$(shell [ -L $(srctree)/$(src)/arch ] && rm $(srctree)/$(src)/arch) +$(shell ln -sf arch-$(CONFIG) $(srctree)/$(src)/arch) +$(shell touch $(srctree)/$(src)/arch/config.h) +endif + +UDD_FILE_PREFIX = ../mali/ + +# Get subversion revision number, fall back to 0000 if no svn info is available +SVN_REV := 0000 + +ccflags-y += -DSVN_REV=$(SVN_REV) +ccflags-y += -DSVN_REV_STRING=\"$(SVN_REV)\" + +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/../mali/common -I$(srctree)/$(src)/../mali/linux -I$(srctree)/$(src)/../../ump/include/ump + +# MALI_SEC +ccflags-y += -I$(srctree)/$(src)/include +ccflags-y += -DUSING_MEMORY=1 -DUMP_MEM_SIZE=512 + +ccflags-y += -DMALI_STATE_TRACKING=0 +ccflags-$(CONFIG_UMP_DEBUG) += -DDEBUG + +# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: +# The ARM proprietary product will only include the license/proprietary directory +# The GPL product will only include the license/gpl directory + +ifeq ($(wildcard $(srctree)/$(src)/linux/license/gpl/*),) +ccflags-y += -I$(srctree)/$(src)/linux/license/proprietary +else +ccflags-y += -I$(srctree)/$(src)/linux/license/gpl +endif + +ump-y = common/ump_kernel_common.o \ + common/ump_kernel_descriptor_mapping.o \ + common/ump_kernel_api.o \ + common/ump_kernel_ref_drv.o \ + linux/ump_kernel_linux.o \ + linux/ump_kernel_memory_backend_os.o \ + linux/ump_kernel_memory_backend_dedicated.o \ + linux/ump_memory_backend.o \ + linux/ump_ukk_wrappers.o \ + linux/ump_ukk_ref_wrappers.o \ + linux/ump_osk_atomics.o \ + linux/ump_osk_low_level_mem.o \ + linux/ump_osk_misc.o + +# MALI_SEC +# $(UDD_FILE_PREFIX)linux/mali_osk_atomics.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_locks.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_memory.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_math.o \ +# $(UDD_FILE_PREFIX)linux/mali_osk_misc.o + +# MALI_SEC +obj-$(CONFIG_MALI400_UMP) := ump.o + diff --git a/drivers/gpu/mali400/r3p2/ump/Kconfig b/drivers/gpu/mali400/r3p2/ump/Kconfig new file mode 100644 index 0000000..13785e2 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Kconfig @@ -0,0 +1,7 @@ +config UMP_DEBUG + bool "Enable extra debug in UMP" + depends on MALI400_UMP + default n + ---help--- + This enabled extra debug checks and messages in UMP. + diff --git a/drivers/gpu/mali400/r3p2/ump/Makefile b/drivers/gpu/mali400/r3p2/ump/Makefile new file mode 100644 index 0000000..e2aa8e5 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/Makefile @@ -0,0 +1,67 @@ +# +# Copyright (C) 2010-2012 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. +# + +# For each arch check: CROSS_COMPILE , KDIR , CFLAGS += -DARCH + +export ARCH ?= arm +BUILD ?= debug + +check_cc2 = \ + $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then \ + echo "$(2)"; \ + else \ + echo "$(3)"; \ + fi ;) + +# Check that required parameters are supplied. +ifeq ($(CONFIG),) +$(error "CONFIG must be specified.") +endif +ifeq ($(CPU)$(KDIR),) +$(error "KDIR or CPU must be specified.") +endif + +# Get any user defined KDIR-<names> or maybe even a hardcoded KDIR +-include KDIR_CONFIGURATION + +# Define host system directory +KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build + +ifeq ($(ARCH), arm) +# when compiling for ARM we're cross compiling +export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) +endif + +# look up KDIR based om CPU selection +KDIR ?= $(KDIR-$(CPU)) + +export CONFIG + +export CONFIG_UMP := m +ifeq ($(BUILD),debug) +export CONFIG_UMP_DEBUG := y +else +export CONFIG_UMP_DEBUG := n +endif + +ifeq ($(KDIR),) +$(error No KDIR found for platform $(CPU)) +endif + +all: + $(MAKE) -C $(KDIR) M=$(CURDIR) modules + +kernelrelease: + $(MAKE) -C $(KDIR) kernelrelease + +clean: + $(MAKE) -C $(KDIR) M=$(CURDIR) clean + $(MAKE) -C $(KDIR) M=$(CURDIR)/../mali clean diff --git a/drivers/media/video/samsung/ump/Makefile.common b/drivers/gpu/mali400/r3p2/ump/Makefile.common index 26a3d6c..c6aa633 100644 --- a/drivers/media/video/samsung/ump/Makefile.common +++ b/drivers/gpu/mali400/r3p2/ump/Makefile.common @@ -1,9 +1,9 @@ # -# Copyright (C) 2010-2012 ARM Limited. All rights reserved. -# +# 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. # @@ -14,7 +14,7 @@ SRC = $(UMP_FILE_PREFIX)common/ump_kernel_common.c \ $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.c # Get subversion revision number, fall back to 0000 if no svn info is available -SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') +SVN_REV:=$(shell ((svnversion | grep -qv exported && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" diff --git a/drivers/media/video/samsung/ump/arch-orion-m400/config.h b/drivers/gpu/mali400/r3p2/ump/arch-pegasus-m400/config.h index 7afbca6..7afbca6 100644 --- a/drivers/media/video/samsung/ump/arch-orion-m400/config.h +++ b/drivers/gpu/mali400/r3p2/ump/arch-pegasus-m400/config.h diff --git a/drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 b/drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 new file mode 120000 index 0000000..4006f31 --- /dev/null +++ b/drivers/gpu/mali400/r3p2/ump/arch/arch-pegasus-m400 @@ -0,0 +1 @@ +arch-pegasus-m400
\ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h b/drivers/gpu/mali400/r3p2/ump/arch/config.h index 7afbca6..7afbca6 100644 --- a/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h +++ b/drivers/gpu/mali400/r3p2/ump/arch/config.h diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_api.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_api.c index 83f0d30..013f4c6 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_api.c +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_api.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -55,6 +55,7 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secu return (ump_dd_handle)mem; } +/* MALI_SEC */ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id) { ump_dd_mem * mem; @@ -277,7 +278,7 @@ _mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ) } _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); + DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret)); return ret; @@ -520,8 +521,6 @@ void _ump_ukk_lock(_ump_uk_lock_s *args ) mem->lock_usage = (ump_lock_usage) args->lock_usage; - /** TODO: TAKE LOCK HERE */ - ump_dd_reference_release(mem); } @@ -545,7 +544,5 @@ void _ump_ukk_unlock(_ump_uk_unlock_s *args ) mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED; - /** TODO: RELEASE LOCK HERE */ - ump_dd_reference_release(mem); } diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c index a27bc77..306ea3d 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_common.c +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.c @@ -233,6 +233,7 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); return _MALI_OSK_ERR_INVALID_ARGS; } + /* MALI_SEC */ /* SEC kernel stability 2012-02-17 */ if (NULL == session_data->cookies_map) { @@ -288,6 +289,7 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) args->is_cached = 1; DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id)); } + /* MALI_SEC */ else if ( args->is_cached) { mem->is_cached = 1; @@ -371,6 +373,7 @@ void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ) MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); return; } + /* MALI_SEC */ /* SEC kernel stability 2012-02-17 */ if (NULL == session_data->cookies_map) { diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.h index 6e3a2e9..6e3a2e9 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_common.h +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_common.h diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.c index cc7b8be..2531f80 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * + * 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. */ @@ -65,9 +65,9 @@ void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map) int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target) { - int descriptor = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + int descriptor = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); if (descriptor == map->current_nr_mappings) { int nr_mappings_new; @@ -89,8 +89,8 @@ int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * goto unlock_and_exit; } - _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); - _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); map->table = new_table; map->current_nr_mappings = nr_mappings_new; descriptor_table_free(old_table); @@ -107,10 +107,10 @@ unlock_and_exit: int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target) { - int result = -1;/*-EFAULT;*/ - DEBUG_ASSERT(map); - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + int result = -1;/*-EFAULT;*/ + DEBUG_ASSERT(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { *target = map->table->mappings[descriptor]; result = 0; @@ -122,9 +122,9 @@ int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, voi int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target) { - int result = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + int result = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { map->table->mappings[descriptor] = target; result = 0; @@ -135,8 +135,8 @@ int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, voi void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor) { - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { map->table->mappings[descriptor] = NULL; _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); @@ -163,3 +163,4 @@ static void descriptor_table_free(ump_descriptor_table * table) { _mali_osk_free(table); } + diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.h index 05b3982..92bbe54 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_descriptor_mapping.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_memory_backend.h index 73915ee..8b11452 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_memory_backend.h @@ -1,9 +1,9 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * + * 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. */ @@ -40,6 +40,7 @@ typedef struct ump_memory_backend u32 (*stat)(struct ump_memory_backend *backend); int (*pre_allocate_physical_check)(void *ctx, u32 size); u32 (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys); + /* MALI_SEC */ void *(*get)(ump_dd_mem *mem, void *args); void (*set)(ump_dd_mem *mem, void *args); void * ctx; @@ -49,3 +50,4 @@ ump_memory_backend * ump_memory_backend_create ( void ); void ump_memory_backend_destroy( void ); #endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */ + diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_ref_drv.c index cb13232..6335bf6 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_ref_drv.c @@ -196,7 +196,7 @@ _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ) return _MALI_OSK_ERR_OK; } - +/* MALI_SEC */ UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args) { ump_dd_mem * mem; @@ -257,4 +257,3 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long v return (ump_dd_handle)mem; } - diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_types.h b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_types.h index 19a9755..19a9755 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_types.h +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_kernel_types.h diff --git a/drivers/media/video/samsung/ump/common/ump_osk.h b/drivers/gpu/mali400/r3p2/ump/common/ump_osk.h index dabdc7f..d9d182a 100644 --- a/drivers/media/video/samsung/ump/common/ump_osk.h +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_osk.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -42,6 +42,7 @@ void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ); +/* MALI_SEC */ void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr); #ifdef __cplusplus diff --git a/drivers/media/video/samsung/ump/common/ump_ukk.h b/drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h index 56e4be3..56e4be3 100644 --- a/drivers/media/video/samsung/ump/common/ump_ukk.h +++ b/drivers/gpu/mali400/r3p2/ump/common/ump_ukk.h diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface.h index 042c8b1..042c8b1 100644 --- a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface.h diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface_ref_drv.h index 36c5c9d..b253de5 100644 --- a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_interface_ref_drv.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010, 2012 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. */ diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_platform.h index 4349605..4349605 100644 --- a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_kernel_platform.h diff --git a/drivers/media/video/samsung/ump/common/ump_uk_types.h b/drivers/gpu/mali400/r3p2/ump/include/ump_uk_types.h index 143588d..2f87272 100644 --- a/drivers/media/video/samsung/ump/common/ump_uk_types.h +++ b/drivers/gpu/mali400/r3p2/ump/include/ump_uk_types.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010, 2012 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. */ @@ -49,9 +49,7 @@ typedef enum _UMP_IOC_SWITCH_HW_USAGE, _UMP_IOC_LOCK, _UMP_IOC_UNLOCK, -#ifdef CONFIG_ION_EXYNOS _UMP_IOC_ION_IMPORT, -#endif }_ump_uk_functions; typedef enum @@ -110,7 +108,6 @@ typedef struct _ump_uk_allocate_s ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ } _ump_uk_allocate_s; -#ifdef CONFIG_ION_EXYNOS typedef struct _ump_uk_ion_import_s { void *ctx; /**< [in,out] user-kernel context (trashed on output) */ @@ -119,7 +116,6 @@ typedef struct _ump_uk_ion_import_s u32 size; /**< Input and output. Requested size; input. Returned size; output */ ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ } _ump_uk_ion_import_s; -#endif /** * SIZE_GET ([in] u32 secure_id, [out]size ) diff --git a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h b/drivers/gpu/mali400/r3p2/ump/linux/license/gpl/ump_kernel_license.h index 187e33b..187e33b 100644 --- a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/license/gpl/ump_kernel_license.h diff --git a/drivers/media/video/samsung/ump/linux/ump_ioctl.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h index 83bb2a4..dcc343a 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ioctl.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ioctl.h @@ -40,13 +40,11 @@ extern "C" #define UMP_IOC_RELEASE _IOR(UMP_IOCTL_NR, _UMP_IOC_RELEASE, _ump_uk_release_s) #define UMP_IOC_SIZE_GET _IOWR(UMP_IOCTL_NR, _UMP_IOC_SIZE_GET, _ump_uk_size_get_s) #define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_msync_s) -#ifdef CONFIG_ION_EXYNOS +/* MALI_SEC */ #define UMP_IOC_ION_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_ION_IMPORT, _ump_uk_ion_import_s) -#endif -#ifdef CONFIG_DMA_SHARED_BUFFER +/* MALI_SEC */ #define UMP_IOC_DMABUF_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_DMABUF_IMPORT,\ struct ump_uk_dmabuf) -#endif #define UMP_IOC_CACHE_OPERATIONS_CONTROL _IOW(UMP_IOCTL_NR, _UMP_IOC_CACHE_OPERATIONS_CONTROL, _ump_uk_cache_operations_control_s) #define UMP_IOC_SWITCH_HW_USAGE _IOW(UMP_IOCTL_NR, _UMP_IOC_SWITCH_HW_USAGE, _ump_uk_switch_hw_usage_s) diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c index a358a3c..b509f43 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.c @@ -35,19 +35,25 @@ #include "ump_ukk_wrappers.h" #include "ump_ukk_ref_wrappers.h" +/* MALI_SEC */ #ifdef CONFIG_ION_EXYNOS #include <linux/ion.h> extern struct ion_device *ion_exynos; struct ion_client *ion_client_ump = NULL; #endif +/* MALI_SEC */ +#if defined(CONFIG_MALI400) +extern int map_errcode( _mali_osk_errcode_t err ); +#endif + /* Module parameter to control log level */ int ump_debug_level = 2; module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */ MODULE_PARM_DESC(ump_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 ump_major = 243; +int ump_major = 0; module_param(ump_major, int, S_IRUGO); /* r--r--r-- */ MODULE_PARM_DESC(ump_major, "Device major number"); @@ -92,9 +98,6 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c #endif static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma); -#if defined(CONFIG_VIDEO_UMP) -extern int map_errcode( _mali_osk_errcode_t err ); -#endif /* This variable defines the file operations this UMP device driver offer */ static struct file_operations ump_fops = @@ -139,6 +142,7 @@ static int ump_initialize_module(void) */ static void ump_cleanup_module(void) { +/* MALI_SEC */ #ifdef CONFIG_ION_EXYNOS if (ion_client_ump) ion_client_destroy(ion_client_ump); @@ -352,6 +356,7 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c case UMP_IOC_ALLOCATE : err = ump_allocate_wrapper((u32 __user *)argument, session_data); break; +/* MALI_SEC */ #ifdef CONFIG_ION_EXYNOS case UMP_IOC_ION_IMPORT: err = ump_ion_import_wrapper((u32 __user *)argument, session_data); @@ -400,7 +405,8 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c return err; } -#ifndef CONFIG_VIDEO_UMP +/* MALI_SEC */ +#if !defined(CONFIG_MALI400) int map_errcode( _mali_osk_errcode_t err ) { switch(err) @@ -429,6 +435,8 @@ static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma) /* Validate the session data */ session_data = (struct ump_session_data *)filp->private_data; + /* MALI_SEC */ + // original : if (NULL == session_data) if (NULL == session_data || NULL == session_data->cookies_map->table->mappings) { MSG_ERR(("mmap() called without any session data available\n")); @@ -474,6 +482,7 @@ EXPORT_SYMBOL(ump_dd_phys_blocks_get); EXPORT_SYMBOL(ump_dd_size_get); EXPORT_SYMBOL(ump_dd_reference_add); EXPORT_SYMBOL(ump_dd_reference_release); +/* MALI_SEC */ EXPORT_SYMBOL(ump_dd_meminfo_get); EXPORT_SYMBOL(ump_dd_meminfo_set); EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); @@ -482,8 +491,7 @@ EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); /* Setup init and exit functions for this module */ -//module_init(ump_initialize_module); -arch_initcall(ump_initialize_module); +module_init(ump_initialize_module); module_exit(ump_cleanup_module); /* And some module informatio */ diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h index 4985bb7..4985bb7 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_linux.h diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.c index 82c16cc..f42a320 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * + * 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. */ @@ -108,6 +108,7 @@ ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size) backend->stat = block_allocator_stat; backend->pre_allocate_physical_check = NULL; backend->adjust_to_mali_phys = NULL; + /* MALI_SEC */ backend->get = NULL; backend->set = NULL; diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.h index ca8faae..fa4bdcc 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_dedicated.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c index 8f6a9b3..0cee2c8 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * 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. @@ -77,6 +77,7 @@ ump_memory_backend * ump_os_memory_backend_create(const int max_allocation) backend->stat = os_stat; backend->pre_allocate_physical_check = NULL; backend->adjust_to_mali_phys = NULL; + /* MALI_SEC */ backend->get = NULL; backend->set = NULL; @@ -136,20 +137,21 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) return 0; /* failure */ } - while (left > 0) + while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max)) { struct page * new_page; if (is_cached) { - new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN); } else { - new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); } if (NULL == new_page) { - MSG_ERR(("UMP memory allocated: Out of Memory !!\n")); + /* MALI_SEC */ + DBG_MSG(1, ("UMP memory allocated: Out of Memory !!\n")); break; } @@ -183,6 +185,7 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) if (left) { DBG_MSG(1, ("Failed to allocate needed pages\n")); + /* MALI_SEC */ DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.h index 6f7e610..f924705 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_kernel_memory_backend_os.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_memory_backend.c index d067cfe..fd1f555 100644 --- a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_memory_backend.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. @@ -56,6 +56,7 @@ ump_memory_backend* ump_memory_backend_create ( void ) DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); backend = ump_os_memory_backend_create(ump_memory_size); } +/* MALI_SEC */ #ifdef CONFIG_UMP_VCM_ALLOC else if (2 == ump_backend) { diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c index b117d99..ef1902e 100644 --- a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_atomics.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_low_level_mem.c index 8ae169a..5fd85a6 100644 --- a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_low_level_mem.c @@ -23,6 +23,7 @@ #include <linux/module.h> /* kernel module definitions */ #include <linux/kernel.h> #include <linux/mm.h> +/* MALI_SEC */ #include <linux/sched.h> #include <linux/slab.h> @@ -149,7 +150,14 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation * descrip vma->vm_private_data = vma_usage_tracker; vma->vm_flags |= VM_IO; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) vma->vm_flags |= VM_RESERVED; +#else + vma->vm_flags |= VM_DONTDUMP; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags |= VM_PFNMAP; +#endif + if (0==descriptor->is_cached) { @@ -211,6 +219,7 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descript return retval; } +/* MALI_SEC */ static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, int *index) { int i; @@ -231,6 +240,7 @@ static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, return _MALI_OSK_ERR_FAULT; } +/* MALI_SEC */ static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, int *index) { int i; @@ -251,6 +261,7 @@ static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, i return _MALI_OSK_ERR_FAULT; } +/* MALI_SEC */ static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size) { int start_index, end_index; @@ -299,6 +310,7 @@ static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 s } return; } +/* The end of MALI_SEC */ static void level1_cache_flush_all(void) { @@ -309,12 +321,14 @@ static void level1_cache_flush_all(void) void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ) { int i; + /* MALI_SEC */ const void *start_v, *end_v; /* Flush L1 using virtual address, the entire range in one go. * Only flush if user space process has a valid write mapping on given address. */ if( (mem) && (virt!=NULL) && (access_ok(VERIFY_WRITE, virt, size)) ) { + /* MALI_SEC */ start_v = (void *)virt; end_v = (void *)(start_v + size - 1); /* There is no dmac_clean_range, so the L1 is always flushed, @@ -324,6 +338,9 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk else dmac_flush_range(start_v, end_v); + /* MALI ORIGINAL CODE */ + //__cpuc_flush_dcache_area(virt, size); + DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v)); } else @@ -372,9 +389,14 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk /* Flush L2 using physical addresses, block for block. */ + /* MALI_SEC */ if ((virt!=NULL) && (mem->size_bytes >= SZ_1M)) { if (op == _UMP_UK_MSYNC_CLEAN) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) outer_clean_all(); +#else + outer_sync(); +#endif else if ((op == _UMP_UK_MSYNC_INVALIDATE) || (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) outer_flush_all(); return; @@ -447,6 +469,7 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk return; } +/* MALI_SEC */ void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) { struct mm_struct *mm = current->mm; @@ -482,4 +505,3 @@ void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) DBG_MSG(3, ("Get handle: 0x%08lx\n", handle)); *mem = (ump_dd_mem*)handle; } - diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c index 3be6fed..12066eb 100644 --- a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_osk_misc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c index a6691ed..977db9a 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. @@ -21,13 +21,14 @@ #include "ump_ukk.h" #include "ump_kernel_common.h" +/* MALI_SEC */ #if defined(CONFIG_ION_EXYNOS) || defined(CONFIG_DMA_SHARED_BUFFER) #include <linux/scatterlist.h> #include "ump_kernel_interface_ref_drv.h" #include "mali_osk_list.h" #ifdef CONFIG_ION_EXYNOS #include <linux/ion.h> -#include "../../../../../gpu/ion/ion_priv.h" +#include "../../../../gpu/ion/ion_priv.h" extern struct ion_device *ion_exynos; extern struct ion_client *ion_client_ump; #endif @@ -89,6 +90,8 @@ int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * sessi return 0; /* success */ } + +/* MALI_SEC */ #ifdef CONFIG_ION_EXYNOS /* * IOCTL operation; Import fd to UMP memory @@ -256,6 +259,13 @@ int ump_dmabuf_import_wrapper(u32 __user *argument, block_size = sizeof(ump_dd_physical_block) * npages; blocks = (ump_dd_physical_block *)_mali_osk_malloc(block_size); + + if (NULL == blocks) { + MSG_ERR(("Failed to allocate blocks\n")); + ret = -ENOMEM; + goto err_dmu_buf_unmap; + } + sgl = sgt->sgl; while (i < npages) { @@ -310,6 +320,7 @@ err_free_session: _mali_osk_free(session); err_free_block: _mali_osk_free(blocks); +err_dmu_buf_unmap: dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); err_dma_buf_detach: dma_buf_detach(dma_buf, attach); diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h index 416a584..63ee98c 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_ref_wrappers.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 ARM Limited. All rights reserved. + * 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. @@ -27,10 +27,11 @@ extern "C" int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * session_data); +/* MALI_SEC */ #ifdef CONFIG_ION_EXYNOS int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * session_data); #endif - +/* MALI_SEC */ #ifdef CONFIG_DMA_SHARED_BUFFER int ump_dmabuf_import_wrapper(u32 __user *argument, struct ump_session_data *session_data); diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c index 780f311..780f311 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.c diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h index e87a903..e87a903 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h +++ b/drivers/gpu/mali400/r3p2/ump/linux/ump_ukk_wrappers.h diff --git a/drivers/media/video/samsung/Kconfig b/drivers/media/video/samsung/Kconfig index 7ae9e6a..4824144 100644 --- a/drivers/media/video/samsung/Kconfig +++ b/drivers/media/video/samsung/Kconfig @@ -17,8 +17,6 @@ if CPU_EXYNOS4210 || CPU_EXYNOS4212 || CPU_EXYNOS4412 source "drivers/media/video/samsung/fimc/Kconfig" source "drivers/media/video/samsung/tvout/Kconfig" source "drivers/media/video/samsung/mfc5x/Kconfig" - source "drivers/media/video/samsung/mali/Kconfig" - source "drivers/media/video/samsung/ump/Kconfig" endif config VIDEO_FIMG2D diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile index e9905d2..5a46253 100644 --- a/drivers/media/video/samsung/Makefile +++ b/drivers/media/video/samsung/Makefile @@ -12,8 +12,6 @@ obj-$(CONFIG_VIDEO_FIMG2D3X) += fimg2d3x/ obj-$(CONFIG_VIDEO_FIMG2D4X) += fimg2d4x/ endif -obj-$(CONFIG_VIDEO_UMP) += ump/ obj-$(CONFIG_VIDEO_TSI) += tsi/ -obj-$(CONFIG_VIDEO_MALI400MP) += mali/ EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/media/video/samsung/mali/Kbuild_module b/drivers/media/video/samsung/mali/Kbuild_module deleted file mode 100644 index e865954..0000000 --- a/drivers/media/video/samsung/mali/Kbuild_module +++ /dev/null @@ -1,295 +0,0 @@ -# -# 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. -# - -# This file is called by the Linux build system. - -OSKOS=linux - -# set up defaults if not defined by the user -USING_UMP ?= 0 -USING_OS_MEMORY ?= 0 -USING_MALI_PMM_TESTSUITE ?= 0 -OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 -USING_PROFILING ?= 1 -USING_INTERNAL_PROFILING ?= 0 -DISABLE_PP0 ?= 0 -DISABLE_PP1 ?= 0 -DISABLE_PP2 ?= 0 -DISABLE_PP3 ?= 0 -PROFILING_SKIP_PP_JOBS ?= 0 -PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 -PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 -TIMESTAMP ?= default -BUILD ?= debug -TARGET_PLATFORM ?= default -KERNEL_RUNTIME_PM_ENABLED ?= 0 -CONFIG ?= pb-virtex5-m200 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 -MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 - -DEFINES := $(EXTRA_DEFINES) - -# Get path to driver source from Linux build system -DRIVER_DIR=$(src) - -# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: -# The ARM proprietary product will only include the license/proprietary directory -# The GPL product will only include the license/gpl directory - -ifeq ($(wildcard $(DRIVER_DIR)/linux/license/gpl/*),) -ccflags-y += -I$(DRIVER_DIR)/linux/license/proprietary -# Disable profiling for proprietary -override USING_PROFILING := 0 -$(warning "USING_PROFILING not supported, disabling.") -else -ccflags-y += -I$(DRIVER_DIR)/linux/license/gpl -endif - - -ifeq ($(USING_PROFILING),1) -ifeq ($(USING_INTERNAL_PROFILING),0) -ifndef CONFIG_TRACEPOINTS -# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling -override USING_PROFILING = 0 -$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING") -endif -endif -endif - -ifeq ($(USING_PROFILING),0) -# make sure user hasnt selected incompatible flags -override USING_INTERNAL_PROFILING = 0 -endif - -MALI_RELEASE_NAME=$(shell cat $(DRIVER_DIR)/.version 2> /dev/null) - -# Check if a Mali Core sub module should be enabled, true or false returned -submodule_enabled = $(shell gcc $(DEFINES) -E $1/arch/config.h | grep type | grep -c $(2)) - -OSKFILES = \ - $(OSKOS)/mali_osk_atomics.c \ - $(OSKOS)/mali_osk_irq.c \ - $(OSKOS)/mali_osk_locks.c \ - $(OSKOS)/mali_osk_wait_queue.c \ - $(OSKOS)/mali_osk_low_level_mem.c \ - $(OSKOS)/mali_osk_math.c \ - $(OSKOS)/mali_osk_memory.c \ - $(OSKOS)/mali_osk_misc.c \ - $(OSKOS)/mali_osk_mali.c \ - $(OSKOS)/mali_osk_notification.c \ - $(OSKOS)/mali_osk_time.c \ - $(OSKOS)/mali_osk_timers.c - -UKKFILES = \ - $(OSKOS)/mali_ukk_mem.c \ - $(OSKOS)/mali_ukk_gp.c \ - $(OSKOS)/mali_ukk_pp.c \ - $(OSKOS)/mali_ukk_core.c - -ifeq ($(USING_PROFILING),1) -UKKFILES += \ - $(OSKOS)/mali_ukk_profiling.c -endif - -ifeq ($(MALI_PLATFORM_FILE),) -MALI_PLATFORM_FILE = platform/default/mali_platform.c -endif - -# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available -SVN_REV := $(shell (cd $(DRIVER_DIR); (svnversion | grep -E "^[0-9]+" && svnversion) || git svn info | grep '^Revision: '| sed -e 's/^Revision: //' ) 2>/dev/null ) -ifeq ($(SVN_REV),) -SVN_REV := $(MALI_RELEASE_NAME) -else -SVN_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) -endif - -# Validate selected config -ifneq ($(shell [ -d $(DRIVER_DIR)/arch-$(CONFIG) ] && [ -f $(DRIVER_DIR)/arch-$(CONFIG)/config.h ] && echo "OK"), OK) -$(warning Current directory is $(shell pwd)) -$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists) -else -# Link arch to the selected arch-config directory -$(shell [ -L $(DRIVER_DIR)/arch ] && rm $(DRIVER_DIR)/arch) -$(shell ln -sf arch-$(CONFIG) $(DRIVER_DIR)/arch) -$(shell touch $(DRIVER_DIR)/arch/config.h) -endif - -# Set up our defines, which will be passed to gcc -DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) -DEFINES += -DUSING_MMU=1 -DEFINES += -DUSING_UMP=$(USING_UMP) -DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP -DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING) -DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) -DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) -DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) -DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) -DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) -DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) -DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) - -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) -DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) -DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) -DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) -ifeq ($(shell test $(SUBLEVEL) -gt 32 -a $(PATCHLEVEL) = 6 -a $(VERSION) = 2 -o $(VERSION) -gt 2 && echo "OK"),OK) -# MALI_STATE_TRACKING is only supported on Linux kernels from version 2.6.32. -DEFINES += -DMALI_STATE_TRACKING=1 -else -DEFINES += -DMALI_STATE_TRACKING=0 -endif -DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) - -MALI_PLATFORM_FILE = platform/$(TARGET_PLATFORM)/mali_platform.c - - -ifdef CONFIG_PM -ifdef CONFIG_PM_RUNTIME - KERNEL_RUNTIME_PM_ENABLED = 1 -endif -endif - -DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED) - -ifeq ($(BUILD), debug) -DEFINES += -DDEBUG -endif -DEFINES += -DSVN_REV=$(SVN_REV) -DEFINES += -DSVN_REV_STRING=\"$(SVN_REV)\" - -# Linux has its own mmap cleanup handlers (see mali_kernel_memory.c) -DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP - -ifeq ($(USING_UMP),1) - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 - ccflags-y += -I$(DRIVER_DIR)/../../ump/include/ump -else - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0 -endif - -# Use our defines when compiling -ccflags-y += $(DEFINES) -I$(DRIVER_DIR) -I$(DRIVER_DIR)/include -I$(DRIVER_DIR)/common -I$(DRIVER_DIR)/linux -I$(DRIVER_DIR)/platform - -# Source files which always are included in a build -SRC = \ - common/mali_kernel_core.c \ - linux/mali_kernel_linux.c \ - common/mali_kernel_descriptor_mapping.c \ - common/mali_session.c \ - common/mali_device_pause_resume.c \ - common/mali_kernel_vsync.c \ - linux/mali_ukk_vsync.c \ - linux/mali_kernel_sysfs.c \ - common/mali_mmu.c \ - common/mali_mmu_page_directory.c \ - common/mali_memory.c \ - common/mali_kernel_memory_engine.c \ - common/mali_block_allocator.c \ - common/mali_kernel_mem_os.c \ - common/mali_mem_validation.c \ - common/mali_hw_core.c \ - common/mali_gp.c \ - common/mali_pp.c \ - common/mali_pp_job.c \ - common/mali_gp_job.c \ - common/mali_scheduler.c \ - common/mali_gp_scheduler.c \ - common/mali_pp_scheduler.c \ - common/mali_cluster.c \ - common/mali_group.c \ - common/mali_dlbu.c \ - common/mali_pm.c \ - common/mali_pmu.c \ - common/mali_user_settings_db.c \ - $(OSKOS)/mali_osk_pm.c \ - linux/mali_kernel_pm.c \ - linux/mali_pmu_power_up_down.c \ - $(MALI_PLATFORM_FILE) \ - $(OSKFILES) \ - $(UKKFILES) \ - __malidrv_build_info.c - -# Selecting files to compile by parsing the config file - -ifeq ($(USING_INTERNAL_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_internal.c \ - timestamp-$(TIMESTAMP)/mali_timestamp.c -ccflags-y += -I$(DRIVER_DIR)/timestamp-$(TIMESTAMP) -else -ifeq ($(USING_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_gator.c -endif -endif - -# Add the profiling sources -SRC += $(PROFILING_BACKEND_SOURCES) - -ifeq ($(USING_MALI_PMM_TESTSUITE),1) -ccflags-y += -I$(DRIVER_DIR)/platform/mali_pmu_testing -endif - -mali-$(CONFIG_MALI400_GPU_UTILIZATION) += common/mali_kernel_utilization.o -mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o - -ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI400PP),0) - # Mali-400 PP in use - ccflags-y += -DUSING_MALI400 -endif - -ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI300PP),0) - # Mali-400 PP in use - ccflags-y += -DUSING_MALI400 -endif - -ifneq ($(call submodule_enabled, $(DRIVER_DIR), MALI200),0) - # Mali200 in use - ccflags-y += -DUSING_MALI200 -endif - -# Always build in support for Mali L2 cache -SRC += common/mali_l2_cache.c - -# Tell the Linux build system to enable building of our .c files -mali-y += $(SRC:.c=.o) -# Tell the Linux build system from which .o file to create the kernel module -obj-$(CONFIG_MALI400) := mali.o - - -VERSION_STRINGS := -VERSION_STRINGS += CONFIG=$(CONFIG) -VERSION_STRINGS += USING_OS_MEMORY=$(USING_OS_MEMORY) -VERSION_STRINGS += API_VERSION=$(shell cd $(DRIVER_DIR); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) -VERSION_STRINGS += REPO_URL=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'URL: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^URL: ' | cut -d: -f2- | cut -b2-) -VERSION_STRINGS += REVISION=$(SVN_REV) -VERSION_STRINGS += CHANGED_REVISION=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Rev: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) -VERSION_STRINGS += CHANGE_DATE=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Date: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) -VERSION_STRINGS += BUILD_DATE=$(shell date) - -VERSION_STRINGS += BUILD=$(shell echo $(BUILD) | tr a-z A-Z) -VERSION_STRINGS += CPU=$(CPU) -VERSION_STRINGS += USING_UMP=$(USING_UMP) -VERSION_STRINGS += USING_MALI200=$(call submodule_enabled, $(DRIVER_DIR), MALI200) -VERSION_STRINGS += USING_MALI400=$(call submodule_enabled, $(DRIVER_DIR), MALI400) -VERSION_STRINGS += USING_MALI400_L2_CACHE=$(call submodule_enabled, $(DRIVER_DIR), MALI400L2) -VERSION_STRINGS += USING_GP2=$(call submodule_enabled, $(DRIVER_DIR), MALIGP2) -VERSION_STRINGS += KDIR=$(KDIR) -VERSION_STRINGS += MALI_PLATFORM_FILE=$(MALI_PLATFORM_FILE) -VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) -VERSION_STRINGS += USING_PROFILING=$(USING_PROFILING) -VERSION_STRINGS += USING_INTERNAL_PROFILING=$(USING_INTERNAL_PROFILING) -VERSION_STRINGS += USING_GPU_UTILIZATION=$(CONFIG_MALI400_GPU_UTILIZATION) - -# Create file with Mali driver configuration -$(DRIVER_DIR)/__malidrv_build_info.c: - @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(DRIVER_DIR)/__malidrv_build_info.c diff --git a/drivers/media/video/samsung/mali/Kconfig b/drivers/media/video/samsung/mali/Kconfig deleted file mode 100644 index 1736eed..0000000 --- a/drivers/media/video/samsung/mali/Kconfig +++ /dev/null @@ -1,63 +0,0 @@ -# -## S3C Multimedia Mali configuration -## -# -# For Mali -config VIDEO_MALI400MP - bool "Enable MALI integration" - depends on VIDEO_SAMSUNG - default y - ---help--- - This enables MALI integration in the multimedia device driver - -choice -depends on VIDEO_MALI400MP -prompt "MALI MEMORY OPTION" -default MALI_OSMEM_ONLY -config MALI_DED_ONLY - bool "mali dedicated memory only" - ---help--- - This enables MALI dedicated memory only option -config MALI_DED_MMU - bool "mali dedicated memory with mmu enable" - ---help--- - This enables MALI dedicated memory with mmu enable option -config MALI_OSMEM_ONLY - bool "mali OS memory only" - ---help--- - This enables MALI OS memory only option -config MALI_DED_OSMEM - bool "mali dedicated memory and OS memory" - ---help--- - This enables MALI dedicated memory and OS memory option - -endchoice -config MALI_MEM_SIZE -int "Dedicated Memory Size" - depends on VIDEO_MALI400MP && (MALI_DED_ONLY || MALI_DED_MMU || MALI_DED_OSMEM) - default "128" - ---help--- - This value is dedicated memory size of Mali GPU(unit is MByte). - -config MALI_R3P1_LSI - bool "Uses the R3P1 as a kernel module" - depends on VIDEO_MALI400MP - default n - ---help--- - This uses the r3p1 as a MALI kernel module - - -# For DEBUG -config VIDEO_MALI400MP_DEBUG - bool "Enables debug messages" - depends on VIDEO_MALI400MP - default n - help - This enables Mali driver debug messages. - -config VIDEO_MALI400MP_DVFS - bool "Enables DVFS" - depends on VIDEO_MALI400MP && PM - default y - help - This enables Mali driver DVFS. diff --git a/drivers/media/video/samsung/mali/Kconfig_module b/drivers/media/video/samsung/mali/Kconfig_module deleted file mode 100644 index dabb36e..0000000 --- a/drivers/media/video/samsung/mali/Kconfig_module +++ /dev/null @@ -1,30 +0,0 @@ -config MALI400 - tristate "Mali-300/400/450 support" - depends on ARM - select FB - ---help--- - This enables support for the Mali-300, Mali-400, and Mali-450 GPUs. - - To compile this driver as a module, choose M here: the module will be - called mali. - -config MALI400_DEBUG - bool "Enable debug in Mali driver" - depends on MALI400 - ---help--- - This enabled extra debug checks and messages in the Mali-300/400/450 - driver. - -config MALI400_PROFILING - bool "Enable Mali profiling" - depends on MALI400 && TRACEPOINTS - ---help--- - This enables gator profiling of Mali GPU events. - -config MALI400_GPU_UTILIZATION - bool "Enable Mali GPU utilization tracking" - depends on MALI400 - ---help--- - This enables gathering and processing of the utilization of Mali GPU. - This data can be used as a basis to change GPU operating frequency. - diff --git a/drivers/media/video/samsung/mali/Makefile b/drivers/media/video/samsung/mali/Makefile deleted file mode 100644 index 3e25b61..0000000 --- a/drivers/media/video/samsung/mali/Makefile +++ /dev/null @@ -1,337 +0,0 @@ -# -# Copyright (C) 2010-2012 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. -# - -OSKOS :=linux -FILES_PREFIX= -MALI_INCLUDE_PREFIX := drivers/media/video/samsung/mali/ -KBUILDROOT = - -ifeq ($(CONFIG_MALI_DED_ONLY),y) -USING_OS_MEMORY=0 -USING_MMU=0 -USING_DED=1 -endif - -ifeq ($(CONFIG_MALI_DED_MMU),y) -USING_OS_MEMORY=0 -USING_MMU=1 -USING_DED=1 -endif - -ifeq ($(CONFIG_MALI_OSMEM_ONLY),y) -USING_MMU=1 -USING_DED=0 -USING_OS_MEMORY=1 -endif - -ifeq ($(CONFIG_MALI_DED_OSMEM),y) -USING_MMU=1 -USING_DED=1 -USING_OS_MEMORY=1 -endif - -ifeq ($(CONFIG_PM),y) - USING_PMM = 1 -ifeq ($(CONFIG_PM_RUNTIME),y) - KERNEL_RUNTIME_PM_ENABLED = 1 -endif -endif - -ifeq ($(CONFIG_VIDEO_MALI400MP_DVFS),y) -USING_GPU_UTILIZATION=1 -USING_MALI_DVFS_ENABLED=1 -endif - -ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) -BUILD=debug -endif - -ifeq ($(CONFIG_VIDEO_MALI400MP_STREAMLINE_PROFILING),y) -USING_PROFILING=1 -USING_TRACEPOINTS=1 -endif - -# set up defaults if not defined by the user -USE_UMPV2 ?= 0 -PANIC_ON_WATCHDOG_TIMEOUT ?= 1 -USING_MALI400 ?= 1 -USING_MMU ?= 1 -USING_DED ?= 0 -USING_UMP ?= 0 -ONLY_ZBT ?= 0 -USING_ZBT ?= 0 -USING_OS_MEMORY ?= 1 -USING_PMM ?= 0 -USING_MALI_RUN_TIME_PM ?= 0 -USING_MALI_PMM_TESTSUITE ?= 0 -USING_MALI_PMU ?= 0 -USING_GPU_UTILIZATION ?= 0 -OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 -USING_PROFILING ?= 0 -USING_INTERNAL_PROFILING ?= 0 -USING_TRACEPOINTS ?= 0 -USING_MALI_MAJOR_PREDEFINE = 1 -USING_MALI_DVFS_ENABLED ?= 1 -USING_MALI_PMM_EARLYSUSPEND ?= 0 -#USING_KERNEL_WITH_DMA_ALLOC_PHYS_PAGE ?= 0 -#CONFIG_MALI_MEM_SIZE ?= 512 -DISABLE_PP0 ?= 0 -DISABLE_PP1 ?= 0 -DISABLE_PP2 ?= 0 -DISABLE_PP3 ?= 0 -PROFILING_SKIP_PP_JOBS ?= 0 -PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 -PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 -TIMESTAMP ?= default -BUILD ?= release -TARGET_PLATFORM ?= default -KERNEL_RUNTIME_PM_ENABLED ?= 0 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 -MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 -MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 - -# Get path to driver source from Linux build system -ifeq ($(USING_PROFILING),1) -ifeq ($(USING_INTERNAL_PROFILING),0) -ifndef CONFIG_TRACEPOINTS -# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling -override USING_PROFILING = 0 -$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING") -endif -endif -endif - -ifeq ($(USING_PROFILING),0) -# make sure user hasnt selected incompatible flags -override USING_INTERNAL_PROFILING = 0 -endif - -USING_MALI_SLP_GLOBAL_LOCK ?= 0 - -#config validtion check -ifeq ($(USING_OS_MEMORY),1) - USING_MMU = 1 -endif - -# Check if a Mali Core sub module should be enabled, true or false returned -#submodule_enabled = $(shell gcc $(DEFINES) -E $(FILES_PREFIX)/arch/config.h | grep type | grep -c $(2)) - -# Inside the kernel build system - -# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak --include ../../../arm_internal.mak - -# Set up our defines, which will be passed to gcc -DEFINES += -DONLY_ZBT=$(ONLY_ZBT) -DEFINES += -DUSING_ZBT=$(USING_ZBT) -DEFINES += -DUSING_MMU=$(USING_MMU) -DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) -DEFINES += -DUSING_DED=$(USING_DED) -DEFINES += -DUSING_UMP=$(USING_UMP) -DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP -DEFINES += -DUSING_MALI_PMU=$(USING_MALI_PMU) -DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED) -DEFINES += -DUSING_MALI_PMM=$(USING_PMM) -DEFINES += -DMALI_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) -DEFINES += -DCONFIG_MALI_MEM_SIZE=$(CONFIG_MALI_MEM_SIZE) -DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP -DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING) -DEFINES += -DMALI_MAJOR_PREDEFINE=$(USING_MALI_MAJOR_PREDEFINE) -DEFINES += -DMALI_DVFS_ENABLED=$(USING_MALI_DVFS_ENABLED) -DEFINES += -DUSING_MALI_PMM_EARLYSUSPEND=$(USING_MALI_PMM_EARLYSUSPEND) -DEFINES += -DMALI_STATE_TRACKING=0 -DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) -DEFINES += -DMALI_TRACEPOINTS_ENABLED=$(USING_TRACEPOINTS) -DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) -DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) -DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) -DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) -DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) -DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) -DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) -DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) -DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) -DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) -DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) -DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) - -ifeq ($(BUILD),debug) -DEFINES += -DDEBUG -endif - -# Linux has its own mmap cleanup handlers (see mali_kernel_mem_mmu.o) -DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP - -# UMP -ifeq ($(CONFIG_VIDEO_UMP),y) - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 - EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)../ump/include -else - DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0 -endif - -# Target build file -obj-$(CONFIG_VIDEO_UMP) += mali.o - -# Use our defines when compiling -# MALI -INCLUDES = \ - -I$(MALI_INCLUDE_PREFIX)\ - -I$(MALI_INCLUDE_PREFIX)include \ - -I$(MALI_INCLUDE_PREFIX)common \ - -I$(MALI_INCLUDE_PREFIX)linux \ - -I$(MALI_INCLUDE_PREFIX)platform\ - -I$(MALI_INCLUDE_PREFIX)regs - -EXTRA_CFLAGS += $(INCLUDES)\ - $(DEFINES) - -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)linux/license/gpl -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)common/pmm - -# Source files which always are included in a build -ifeq ($(CONFIG_VIDEO_UMP),y) -OSKFILES=\ - $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_wait_queue.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o -else -OSKFILES=\ - $(FILES_PREFIX)$(OSKOS)/mali_osk_atomics.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_locks.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_wait_queue.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_math.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_memory.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_misc.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \ - $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o -endif #($(CONFIG_VIDEO_UMP),y) - -ifeq ($(CONFIG_CPU_EXYNOS4210),y) - MALI_PLATFORM_DIR = platform/orion-m400 -else - MALI_PLATFORM_DIR = platform/pegasus-m400 -endif #($(CONFIG_CPU_EXYNOS4210),y) - -MALI_PLATFORM_FILE=$(MALI_PLATFORM_DIR)/mali_platform.o -UKKFILES=\ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_mem.o \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_gp.o \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_pp.o \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_core.o - -ifeq ($(USING_PROFILING),1) -UKKFILES += \ - $(FILES_PREFIX)$(OSKOS)/mali_ukk_profiling.o -endif - -mali-y := \ - common/mali_kernel_core.o \ - linux/mali_kernel_linux.o \ - common/mali_kernel_descriptor_mapping.o \ - common/mali_session.o \ - common/mali_device_pause_resume.o \ - common/mali_kernel_vsync.o \ - linux/mali_ukk_vsync.o \ - linux/mali_kernel_sysfs.o \ - common/mali_mmu.o \ - common/mali_mmu_page_directory.o \ - common/mali_memory.o \ - common/mali_kernel_memory_engine.o \ - common/mali_block_allocator.o \ - common/mali_kernel_mem_os.o \ - common/mali_mem_validation.o \ - common/mali_hw_core.o \ - common/mali_gp.o \ - common/mali_pp.o \ - common/mali_pp_job.o \ - common/mali_gp_job.o \ - common/mali_scheduler.o \ - common/mali_gp_scheduler.o \ - common/mali_pp_scheduler.o \ - common/mali_cluster.o \ - common/mali_group.o \ - common/mali_dlbu.o \ - common/mali_pm.o \ - common/mali_pmu.o \ - common/mali_user_settings_db.o \ - $(OSKOS)/mali_osk_pm.o \ - linux/mali_kernel_pm.o \ - linux/mali_pmu_power_up_down.o \ - $(MALI_PLATFORM_FILE) \ - $(OSKFILES) \ - $(UKKFILES) -# __malidrv_build_info.c - -# Selecting files to compile by parsing the config file - -ifeq ($(USING_INTERNAL_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_internal.o \ - timestamp-$(TIMESTAMP)/mali_timestamp.o -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)timestamp-$(TIMESTAMP) -else -ifeq ($(USING_PROFILING),1) -PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling_gator.o -endif -endif - -# Add the profiling sources -mali-y += $(PROFILING_BACKEND_SOURCES) - -# Mali-400 PP in use -ifeq ($(USING_MALI_PMM_TESTSUITE),1) -EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)platform/mali_pmu_testing -endif - -ifeq ($(USING_GPU_UTILIZATION),1) -EXTRA_CFLAGS += -DCONFIG_MALI400_GPU_UTILIZATION=1 - -mali-y += \ - common/mali_kernel_utilization.o -endif - -ifeq ($(USING_MALI_DVFS_ENABLED),1) -mali-y += $(MALI_PLATFORM_DIR)/mali_platform_dvfs.o -endif #($(USING_MALI_DVFS_ENABLED),1) - -EXTRA_CFLAGS += -DUSING_MALI400 - -# Mali Level2 cache in use -EXTRA_CFLAGS += -DUSING_MALI400_L2_CACHE -mali-y += common/mali_l2_cache.o - -# Mali SLP Global lock feature -ifeq ($(USING_MALI_SLP_GLOBAL_LOCK),1) -mali-y += \ - linux/mali_slp_global_lock.o -endif - - -ifeq ($(PANIC_ON_WATCHDOG_TIMEOUT),1) - EXTRA_CFLAGS += -DUSING_KERNEL_PANIC -endif - -# Get subversion revision number, fall back to 0000 if no svn info is available -SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') - -EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) -EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" - diff --git a/drivers/media/video/samsung/mali/arch b/drivers/media/video/samsung/mali/arch deleted file mode 120000 index 58ffbe7..0000000 --- a/drivers/media/video/samsung/mali/arch +++ /dev/null @@ -1 +0,0 @@ -arch-release
\ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-debug b/drivers/media/video/samsung/mali/arch-debug deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/mali/arch-debug +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/
\ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-orion-m400/config.h b/drivers/media/video/samsung/mali/arch-orion-m400/config.h deleted file mode 100644 index 73502a2..0000000 --- a/drivers/media/video/samsung/mali/arch-orion-m400/config.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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. - */ - -#ifndef __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the EB platform with ZBT memory enabled */ -/*zepplin added 2010.08.17 for orion configuration*/ -#define MALI_BASE_ADDR 0x13000000 -#define GP_ADDR MALI_BASE_ADDR -#define L2_ADDR MALI_BASE_ADDR+0x1000 -#define PMU_ADDR MALI_BASE_ADDR+0x2000 -#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 -#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 -#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 -#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 -#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 -#define PP0_ADDR MALI_BASE_ADDR+0x8000 -#define PP1_ADDR MALI_BASE_ADDR+0xA000 -#define PP2_ADDR MALI_BASE_ADDR+0xC000 -#define PP3_ADDR MALI_BASE_ADDR+0xE000 - -/*for mmu and os memory*/ -#define MEM_BASE_ADDR 0x40000000 -#define MEM_TOTAL_SIZE 0x40000000 -#define MEM_MALI_OS_SIZE 0x40000000 - -/*for dedicated memory*/ -//#define MEM_MALI_BASE 0x58000000 -//#define MEM_MALI_SIZE 0x08000000 -#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 -#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = GP_ADDR, - .irq = IRQ_GP_3D, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = PP0_ADDR, - .irq = IRQ_PP0_3D, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = PP1_ADDR, - .irq = IRQ_PP1_3D, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = PP2_ADDR, - .irq = IRQ_PP2_3D, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MALI400PP, - .base = PP3_ADDR, - .irq = IRQ_PP3_3D, - .description = "Mali-400 PP 3", - .mmu_id = 5 - }, -#if USING_MMU - { - .type = MMU, - .base = GP_MMU_ADDR, - .irq = IRQ_GPMMU_3D, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = PP0_MMU_ADDR, - .irq = IRQ_PPMMU0_3D, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = PP1_MMU_ADDR, - .irq = IRQ_PPMMU1_3D, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = PP2_MMU_ADDR, - .irq = IRQ_PPMMU2_3D, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = PP3_MMU_ADDR, - .irq = IRQ_PPMMU3_3D, - .description = "Mali-400 MMU for PP 3", - .mmu_id = 5 - }, -#if USING_OS_MEMORY - { - .type = OS_MEMORY, - .description = "System Memory", - .size = MEM_MALI_OS_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, -#endif -#if USING_DED /* Dedicated Memory */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif/* if USING_OS_MEMORY*/ - { - .type = MEM_VALIDATION, - .description = "Framebuffer Memory", - .base = MEM_BASE_ADDR, - .size = MEM_TOTAL_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#else /* Not using MMU */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif - { - .type = MALI400L2, - .base = L2_ADDR, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h deleted file mode 100644 index e579526..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = PMU, - .description = "Mali-300 PMU", - .base = 0xC0002000, - .irq = -1, - .mmu_id = 0 - - }, - { - .type = MALI300GP, - .description = "Mali-300 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI300PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-300 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-300 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-300 MMU for PP", - .mmu_id = 2 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI300L2, - .base = 0xC0001000, - .description = "Mali-300 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h deleted file mode 100644 index 3893d72..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - - { - .type = PMU, - .description = "Mali-400 PMU", - .base = 0xC0002000, - .irq = -1, - .mmu_id = 0 - }, - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP", - .mmu_id = 2 - }, - { - .type = OS_MEMORY, - .description = "OS Memory", - .alloc_order = 10, /* Lowest preference for this memory */ - .size = 96 * 1024 * 1024, /* 96 MB */ - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = 0, - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0x80000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h deleted file mode 100644 index 6d84ab1..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = PMU, - .description = "Mali-400 PMU", - .base = 0xC0002000, - .irq = -1, - .mmu_id = 0 - - }, - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP", - .mmu_id = 2 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h deleted file mode 100644 index 568ac0a..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP", - .mmu_id = 2 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h deleted file mode 100644 index 98b8059..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = 0xc000A000, - .irq = -1, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = -1, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = -1, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0005000, - .irq = -1, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h deleted file mode 100644 index 7b10925..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the PB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = 0xc000A000, - .irq = -1, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = 0xc000C000, - .irq = -1, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = 102, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = 102, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0005000, - .irq = 102, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = 0xC0006000, - .irq = 102, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h deleted file mode 100644 index a15a6bd..0000000 --- a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the EB platform with ZBT memory enabled */ - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = 0xC0000000, - .irq = -1, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = 0xc0008000, - .irq = -1, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = 0xc000A000, - .irq = -1, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = 0xc000C000, - .irq = -1, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MALI400PP, - .base = 0xc000E000, - .irq = -1, - .description = "Mali-400 PP 3", - .mmu_id = 5 - }, - { - .type = MMU, - .base = 0xC0003000, - .irq = 102, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = 0xC0004000, - .irq = 102, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = 0xC0005000, - .irq = 102, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = 0xC0006000, - .irq = 102, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = 0xC0007000, - .irq = 102, - .description = "Mali-400 MMU for PP 3", - .mmu_id = 5 - }, - { - .type = MEMORY, - .description = "Mali SDRAM remapped to baseboard", - .cpu_usage_adjust = -0x50000000, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0xD0000000, - .size = 0x10000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEMORY, - .description = "Mali ZBT", - .alloc_order = 5, /* Medium preference for this memory */ - .base = 0xe1000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, - { - .type = MALI400L2, - .base = 0xC0001000, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h b/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h deleted file mode 100644 index d5196c3..0000000 --- a/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the EB platform with ZBT memory enabled */ -/*zepplin added 2010.08.17 for orion configuration*/ -#define MALI_BASE_ADDR 0x13000000 -#define GP_ADDR MALI_BASE_ADDR -#define L2_ADDR MALI_BASE_ADDR+0x1000 -#define PMU_ADDR MALI_BASE_ADDR+0x2000 -#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 -#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 -#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 -#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 -#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 -#define PP0_ADDR MALI_BASE_ADDR+0x8000 -#define PP1_ADDR MALI_BASE_ADDR+0xA000 -#define PP2_ADDR MALI_BASE_ADDR+0xC000 -#define PP3_ADDR MALI_BASE_ADDR+0xE000 - -/*for mmu and os memory*/ -#define MEM_BASE_ADDR 0x40000000 -#define MEM_TOTAL_SIZE 0x40000000 -#define MEM_MALI_OS_SIZE 0x40000000 - -/*for dedicated memory*/ -//#define MEM_MALI_BASE 0x58000000 -//#define MEM_MALI_SIZE 0x08000000 -#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 -#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE - -static _mali_osk_resource_t arch_configuration [] = -{ - { - .type = MALI400GP, - .description = "Mali-400 GP", - .base = GP_ADDR, - .irq = IRQ_GP_3D, - .mmu_id = 1 - }, - { - .type = MALI400PP, - .base = PP0_ADDR, - .irq = IRQ_PP0_3D, - .description = "Mali-400 PP 0", - .mmu_id = 2 - }, - { - .type = MALI400PP, - .base = PP1_ADDR, - .irq = IRQ_PP1_3D, - .description = "Mali-400 PP 1", - .mmu_id = 3 - }, - { - .type = MALI400PP, - .base = PP2_ADDR, - .irq = IRQ_PP2_3D, - .description = "Mali-400 PP 2", - .mmu_id = 4 - }, - { - .type = MALI400PP, - .base = PP3_ADDR, - .irq = IRQ_PP3_3D, - .description = "Mali-400 PP 3", - .mmu_id = 5 - }, -#if USING_MMU - { - .type = MMU, - .base = GP_MMU_ADDR, - .irq = IRQ_GPMMU_3D, - .description = "Mali-400 MMU for GP", - .mmu_id = 1 - }, - { - .type = MMU, - .base = PP0_MMU_ADDR, - .irq = IRQ_PPMMU0_3D, - .description = "Mali-400 MMU for PP 0", - .mmu_id = 2 - }, - { - .type = MMU, - .base = PP1_MMU_ADDR, - .irq = IRQ_PPMMU1_3D, - .description = "Mali-400 MMU for PP 1", - .mmu_id = 3 - }, - { - .type = MMU, - .base = PP2_MMU_ADDR, - .irq = IRQ_PPMMU2_3D, - .description = "Mali-400 MMU for PP 2", - .mmu_id = 4 - }, - { - .type = MMU, - .base = PP3_MMU_ADDR, - .irq = IRQ_PPMMU3_3D, - .description = "Mali-400 MMU for PP 3", - .mmu_id = 5 - }, -#if USING_OS_MEMORY - { - .type = OS_MEMORY, - .description = "System Memory", - .size = MEM_MALI_OS_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, -#endif -#if USING_DED /* Dedicated Memory */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif/* if USING_OS_MEMORY*/ - { - .type = MEM_VALIDATION, - .description = "memory validation", - .base = MEM_BASE_ADDR, - .size = MEM_TOTAL_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#else /* Not using MMU */ - { - .type = MEMORY, - .description = "Dedicated Memory", - .base = MEM_MALI_BASE, - .size = MEM_MALI_SIZE, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE - }, -#endif - { - .type = MALI400L2, - .base = L2_ADDR, - .description = "Mali-400 L2 cache" - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/arch-release b/drivers/media/video/samsung/mali/arch-release deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/mali/arch-release +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/
\ No newline at end of file diff --git a/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h b/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h deleted file mode 100644 index eb5da50..0000000 --- a/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2010, 2012 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 __ARCH_CONFIG_H__ -#define __ARCH_CONFIG_H__ - -/* Configuration for the Versatile Express platform */ - -#define MALI_BASE_ADDRESS 0xFC040000 - -static _mali_osk_resource_t arch_configuration [] = -{ - /* PMU */ - { - .type = PMU, - .base = MALI_BASE_ADDRESS + 0x02000, - .description = "MALI PMU" - }, - /* GP cluster */ - { - .type = MALI400L2, - .base = MALI_BASE_ADDRESS + 0x10000, - .description = "Mali-450 L2 cache for GP" - }, - { - .type = MALI400GP, - .description = "Mali-450 GP", - .base = MALI_BASE_ADDRESS, - .irq = -1, - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x3000, - .irq = 70, - .description = "Mali-450 MMU for GP", - }, - - /* PP0-3 cluster */ - { - .type = MALI400L2, - .base = MALI_BASE_ADDRESS + 0x1000, - .description = "Mali-450 L2 cache for PP0-3" - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x8000, - .irq = 70, - .description = "Mali-450 PP0", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x4000, - .irq = 70, - .description = "Mali-450 MMU for PP0", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0xA000, - .irq = 70, - .description = "Mali-450 PP1", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x5000, - .irq = 70, - .description = "Mali-450 MMU for PP1", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0xC000, - .irq = 70, - .description = "Mali-450 PP2", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x6000, - .irq = 70, - .description = "Mali-450 MMU for PP2", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0xE000, - .irq = 70, - .description = "Mali-450 PP3", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x7000, - .irq = 70, - .description = "Mali-450 MMU for PP3", - }, - - /* PP4-7 cluster */ - { - .type = MALI400L2, - .base = MALI_BASE_ADDRESS + 0x11000, - .description = "Mali-450 L2 cache for PP4-7" - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x28000, - .irq = 70, - .description = "Mali-450 PP4", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1C000, - .irq = 70, - .description = "Mali-450 MMU for PP4", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x2A000, - .irq = 70, - .description = "Mali-450 PP5", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1D000, - .irq = 70, - .description = "Mali-450 MMU for PP5", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x2C000, - .irq = 70, - .description = "Mali-450 PP6", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1E000, - .irq = 70, - .description = "Mali-450 MMU for PP6", - }, - { - .type = MALI400PP, - .base = MALI_BASE_ADDRESS + 0x2E000, - .irq = 70, - .description = "Mali-450 PP7", - }, - { - .type = MMU, - .base = MALI_BASE_ADDRESS + 0x1F000, - .irq = 70, - .description = "Mali-450 MMU for PP7", - }, - - /* Memory */ - { - .type = OS_MEMORY, - .description = "Mali OS memory", - .cpu_usage_adjust = 0, - .alloc_order = 0, /* Highest preference for this memory */ - .base = 0x0, - .size = 256 * 1024 * 1024, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE - }, - { - .type = MEM_VALIDATION, - .description = "Framebuffer", - .base = 0xe0000000, - .size = 0x01000000, - .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE - }, -}; - -#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.c b/drivers/media/video/samsung/mali/common/mali_cluster.c deleted file mode 100644 index f0fb2b6..0000000 --- a/drivers/media/video/samsung/mali/common/mali_cluster.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_kernel_common.h" -#include "mali_cluster.h" -#include "mali_osk.h" -#include "mali_group.h" -#include "mali_l2_cache.h" -#include "mali_scheduler.h" - -static struct mali_cluster *mali_global_clusters[MALI_MAX_NUMBER_OF_CLUSTERS] = { NULL, NULL, NULL }; -static u32 mali_global_num_clusters = 0; - -/** - * The structure represents a render cluster - * A render cluster is defined by all the cores that share the same Mali L2 cache - */ -struct mali_cluster -{ - struct mali_l2_cache_core *l2; - u32 number_of_groups; - struct mali_group* groups[MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER]; - u32 last_invalidated_id; - mali_bool power_is_enabled; -}; - -struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache) -{ - struct mali_cluster *cluster = NULL; - - if (mali_global_num_clusters >= MALI_MAX_NUMBER_OF_CLUSTERS) - { - MALI_PRINT_ERROR(("Mali cluster: Too many cluster objects created\n")); - return NULL; - } - - cluster = _mali_osk_malloc(sizeof(struct mali_cluster)); - if (NULL != cluster) - { - _mali_osk_memset(cluster, 0, sizeof(struct mali_cluster)); - cluster->l2 = l2_cache; /* This cluster now owns this L2 cache object */ - cluster->last_invalidated_id = 0; - cluster->power_is_enabled = MALI_TRUE; - - mali_global_clusters[mali_global_num_clusters] = cluster; - mali_global_num_clusters++; - - return cluster; - } - - return NULL; -} - -void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled) -{ - cluster->power_is_enabled = power_is_enabled; -} - -mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster) -{ - return cluster->power_is_enabled; -} - - -void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (cluster->number_of_groups < MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER) - { - /* This cluster now owns the group object */ - cluster->groups[cluster->number_of_groups] = group; - cluster->number_of_groups++; - } -} - -void mali_cluster_delete(struct mali_cluster *cluster) -{ - u32 i; - - MALI_DEBUG_ASSERT_POINTER(cluster); - - /* Free all the resources we own */ - for (i = 0; i < cluster->number_of_groups; i++) - { - mali_group_delete(cluster->groups[i]); - } - - if (NULL != cluster->l2) - { - mali_l2_cache_delete(cluster->l2); - } - - for (i = 0; i < mali_global_num_clusters; i++) - { - if (mali_global_clusters[i] == cluster) - { - mali_global_clusters[i] = NULL; - mali_global_num_clusters--; - break; - } - } - - _mali_osk_free(cluster); -} - -void mali_cluster_reset(struct mali_cluster *cluster) -{ - u32 i; - - MALI_DEBUG_ASSERT_POINTER(cluster); - - /* Free all the resources we own */ - for (i = 0; i < cluster->number_of_groups; i++) - { - struct mali_group *group = cluster->groups[i]; - - mali_group_reset(group); - } - - if (NULL != cluster->l2) - { - mali_l2_cache_reset(cluster->l2); - } -} - -struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - return cluster->l2; -} - -struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (index < cluster->number_of_groups) - { - return cluster->groups[index]; - } - - return NULL; -} - -struct mali_cluster *mali_cluster_get_global_cluster(u32 index) -{ - if (MALI_MAX_NUMBER_OF_CLUSTERS > index) - { - return mali_global_clusters[index]; - } - - return NULL; -} - -u32 mali_cluster_get_glob_num_clusters(void) -{ - return mali_global_num_clusters; -} - -mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (NULL != cluster->l2) - { - /* If the last cache invalidation was done by a job with a higher id we - * don't have to flush. Since user space will store jobs w/ their - * corresponding memory in sequence (first job #0, then job #1, ...), - * we don't have to flush for job n-1 if job n has already invalidated - * the cache since we know for sure that job n-1's memory was already - * written when job n was started. */ - if (((s32)id) <= ((s32)cluster->last_invalidated_id)) - { - return MALI_FALSE; - } - else - { - cluster->last_invalidated_id = mali_scheduler_get_new_id(); - } - - mali_l2_cache_invalidate_all(cluster->l2); - } - return MALI_TRUE; -} - -void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster) -{ - MALI_DEBUG_ASSERT_POINTER(cluster); - - if (NULL != cluster->l2) - { - cluster->last_invalidated_id = mali_scheduler_get_new_id(); - mali_l2_cache_invalidate_all(cluster->l2); - } -} - -void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages) -{ - u32 i; - - for (i = 0; i < mali_global_num_clusters; i++) - { - /*additional check for cluster*/ - if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_clusters[i]->l2)) - { - mali_l2_cache_invalidate_pages(mali_global_clusters[i]->l2, pages, num_pages); - } - mali_l2_cache_unlock_power_state(mali_global_clusters[i]->l2); - /*check for failed power locking???*/ - } -} diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.h b/drivers/media/video/samsung/mali/common/mali_cluster.h deleted file mode 100644 index 33debdb..0000000 --- a/drivers/media/video/samsung/mali/common/mali_cluster.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2011-2012 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_CLUSTER_H__ -#define __MALI_CLUSTER_H__ - -#include "mali_osk.h" -#include "mali_l2_cache.h" - -/* Maximum 1 GP and 4 PP for a cluster (Mali-400 Quad-core) */ -#define MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER 5 -#define MALI_MAX_NUMBER_OF_CLUSTERS 3 - -struct mali_cluster; -struct mali_group; - -struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache); -void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group); -void mali_cluster_delete(struct mali_cluster *cluster); - -void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled); -mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster); - -void mali_cluster_reset(struct mali_cluster *cluster); - -struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster); -struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index); - -struct mali_cluster *mali_cluster_get_global_cluster(u32 index); -u32 mali_cluster_get_glob_num_clusters(void); - -/* Returns MALI_TRUE if it did the flush */ -mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id); -void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster); -void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages); - -#endif /* __MALI_CLUSTER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h deleted file mode 100644 index 6be75b0..0000000 --- a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2010-2012 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__ - -#include "mali_osk.h" - -/** - * Pause the scheduling and power state changes of Mali device driver. - * mali_dev_resume() must always be called as soon as possible after this function - * in order to resume normal operation of the Mali driver. - * - * @param power_is_on Receives the power current status of Mali GPU. MALI_TRUE if GPU is powered on - */ -void mali_dev_pause(mali_bool *power_is_on); - -/** - * Resume scheduling and allow power changes in Mali device driver. - * This must always be called after mali_dev_pause(). - */ -void mali_dev_resume(void); - -#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp.c b/drivers/media/video/samsung/mali/common/mali_gp.c deleted file mode 100644 index 1624e46..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_gp.h" -#include "mali_hw_core.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "regs/mali_gp_regs.h" -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -/** - * Definition of the GP core struct - * Used to track a GP core in the system. - */ -struct mali_gp_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - struct mali_group *group; /**< Parent group for this core */ - _mali_osk_irq_t *irq; /**< IRQ handler */ - struct mali_gp_job *running_job; /**< Current running job */ - _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */ - u32 timeout_job_id; /**< job id for the timed out job - relevant only if gp_core_timed_out == MALI_TRUE */ - mali_bool core_timed_out; /**< if MALI_TRUE, this gp core has timed out; if MALI_FALSE, no timeout on this gp core */ - u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ - u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ -}; - -static struct mali_gp_core *mali_global_gp_core = NULL; - -/* Interrupt handlers */ -static _mali_osk_errcode_t mali_gp_upper_half(void *data); -static void mali_gp_bottom_half(void *data); -static void mali_gp_irq_probe_trigger(void *data); -static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data); -static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend); -static void mali_gp_timeout(void *data); - -struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group) -{ - struct mali_gp_core* core = NULL; - - MALI_DEBUG_ASSERT(NULL == mali_global_gp_core); - MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description)); - - core = _mali_osk_malloc(sizeof(struct mali_gp_core)); - if (NULL != core) - { - core->group = group; - core->running_job = NULL; - core->counter_src0 = MALI_HW_CORE_NO_COUNTER; - core->counter_src1 = MALI_HW_CORE_NO_COUNTER; - core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; - core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE)) - { - _mali_osk_errcode_t ret; - - mali_group_lock(group); - ret = mali_gp_reset(core); - mali_group_unlock(group); - - if (_MALI_OSK_ERR_OK == ret) - { - /* Setup IRQ handlers (which will do IRQ probing if needed) */ - core->irq = _mali_osk_irq_init(resource->irq, - mali_gp_upper_half, - mali_gp_bottom_half, - mali_gp_irq_probe_trigger, - mali_gp_irq_probe_ack, - core, - "mali_gp_irq_handlers"); - if (NULL != core->irq) - { - /* Initialise the timeout timer */ - core->timeout_timer = _mali_osk_timer_init(); - if(NULL != core->timeout_timer) - { - _mali_osk_timer_setcallback(core->timeout_timer, mali_gp_timeout, (void *)core); - MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core)); - mali_global_gp_core = core; - - return core; - } - else - { - MALI_PRINT_ERROR(("Failed to setup timeout timer for GP core %s\n", core->hw_core.description)); - /* Release IRQ handlers */ - _mali_osk_irq_term(core->irq); - } - } - else - { - MALI_PRINT_ERROR(("Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description)); - } - } - mali_hw_core_delete(&core->hw_core); - } - - _mali_osk_free(core); - } - else - { - MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n")); - } - - return NULL; -} - -void mali_gp_delete(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - _mali_osk_timer_term(core->timeout_timer); - _mali_osk_irq_term(core->irq); - mali_hw_core_delete(&core->hw_core); - mali_global_gp_core = NULL; - _mali_osk_free(core); -} - -void mali_gp_stop_bus(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); -} - -_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - - /* Send the stop bus command. */ - mali_gp_stop_bus(core); - - /* Wait for bus to be stopped */ - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} - -void mali_gp_hard_reset(struct mali_gp_core *core) -{ - const int reset_finished_loop_count = 15; - const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW; - const u32 reset_invalid_value = 0xC0FFE000; - const u32 reset_check_value = 0xC01A0000; - const u32 reset_default_value = 0; - int i; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_gp_post_process_job(core, MALI_FALSE); - - mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET); - - for (i = 0; i < reset_finished_loop_count; i++) - { - mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value); - if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register)) - { - break; - } - } - - if (i == reset_finished_loop_count) - { - MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n")); - } - - mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */ - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); - -} - -_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_gp_post_process_job(core, MALI_FALSE); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ - -#if defined(USING_MALI200) - - /* On Mali-200, stop the bus, then do a hard reset of the core */ - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali GP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT; - } - - /* the bus was stopped OK, do the hard reset */ - mali_gp_hard_reset(core); - -#elif defined(USING_MALI400) - - /* Mali-300 and Mali-400 have a safe reset command which we use */ - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, unable to recover\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT; - } -#else -#error "no supported mali core defined" -#endif - - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); - - return _MALI_OSK_ERR_OK; -} - -void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) -{ - u32 startcmd = 0; - u32 *frame_registers = mali_gp_job_get_frame_registers(job); - core->counter_src0_used = core->counter_src0; - core->counter_src1_used = core->counter_src1; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (mali_gp_job_has_vs_job(job)) - { - startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS; - } - - if (mali_gp_job_has_plbu_job(job)) - { - startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU; - } - - MALI_DEBUG_ASSERT(0 != startcmd); - - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME); - -#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH - { - /* Read hits and Read misses*/ - mali_l2_cache_core_set_counter_src0(mali_l2_cache_core_get_glob_l2_core(0), 20); - mali_l2_cache_core_set_counter_src1(mali_l2_cache_core_get_glob_l2_core(0), 21); - } -#endif - - /* This selects which performance counters we are reading */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - /* global_config has enabled HW counters, this will override anything specified by user space */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - } - else - { - /* Use HW counters from job object, if any */ - u32 perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); - if (0 != perf_counter_flag) - { - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) - { - core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) - { - core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); - } - } - } - - MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd)); - - /* Barrier to make sure the previous register write is finished */ - _mali_osk_write_mem_barrier(); - - /* This is the command that starts the core. */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); - - /* Barrier to make sure the previous register write is finished */ - _mali_osk_write_mem_barrier(); - - /* Setup the timeout timer value and save the job id for the job running on the gp core */ - - _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); - core->timeout_job_id = mali_gp_job_get_id(job); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, - job->frame_builder_id, job->flush_id, 0, 0, 0); - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), job->pid, job->tid, 0, 0, 0); -#endif - - core->running_job = job; -} - -void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr) -{ - u32 irq_readout; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT); - - if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr); - mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr); - - MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n")); - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); - _mali_osk_write_mem_barrier(); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0); -#endif - } - /* - * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response. - * A timeout or a page fault on Mali-200 PP core can cause this behaviour. - */ -} - -void mali_gp_abort_job(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (_MALI_OSK_ERR_FAULT != mali_gp_reset(core)) - { - _mali_osk_timer_del(core->timeout_timer); - } -} - -u32 mali_gp_core_get_version(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION); -} - -mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src0 = counter; - return MALI_TRUE; -} - -mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src1 = counter; - return MALI_TRUE; -} - -u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src0; -} - -u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src1; -} - -struct mali_gp_core *mali_gp_get_global_gp_core(void) -{ - return mali_global_gp_core; -} - -/* ------------- interrupt handling below ------------------ */ -static _mali_osk_errcode_t mali_gp_upper_half(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); - if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) - { - /* Mask out all IRQs from this core until IRQ is handled */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); -#endif - - /* We do need to handle this in a bottom half */ - _mali_osk_irq_schedulework(core->irq); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_gp_bottom_half(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - u32 irq_readout; - u32 irq_errors; - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); -#endif -#endif - - mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ - - if ( MALI_FALSE == mali_group_power_is_on(core->group) ) - { - MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); - mali_group_unlock(core->group); - return; - } - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED; - MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); - - if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) - { - u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS); - if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) - { - mali_gp_post_process_job(core, MALI_FALSE); - MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n")); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); /* Will release group lock */ - return; - } - } - - /* - * Now lets look at the possible error cases (IRQ indicating error or timeout) - * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error. - */ - irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM); - if (0 != irq_errors) - { - mali_gp_post_process_job(core, MALI_FALSE); - MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); /* Will release group lock */ - return; - } - else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ - { - if (core->timeout_job_id == mali_gp_job_get_id(core->running_job)) - { - mali_gp_post_process_job(core, MALI_FALSE); - MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job))); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT); - } - core->core_timed_out = MALI_FALSE; - return; - } - else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) - { - /* GP wants more memory in order to continue. - * - * This must be handled prior to HANG because this actually can - * generate a HANG while waiting for more memory. - * And it must be handled before the completion interrupts, - * since the PLBU can run out of memory after VS is complete; - * in which case the OOM must be handled before to complete the - * PLBU work. - */ - mali_gp_post_process_job(core, MALI_TRUE); - MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n")); - mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); /* Will release group lock */ - return; - } - else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG) - { - /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG); - } - - /* - * The only way to get here is if we got a HANG interrupt, which we ignore, or only one of two needed END_CMD_LST interrupts. - * Re-enable interrupts and let core continue to run. - */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); - mali_group_unlock(core->group); - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); -#endif -#endif -} - -static void mali_gp_irq_probe_trigger(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG); - _mali_osk_mem_barrier(); -} - -static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data) -{ - struct mali_gp_core *core = (struct mali_gp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT); - if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout) - { - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG); - _mali_osk_mem_barrier(); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -/* ------ local helper functions below --------- */ - -static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend) -{ - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (NULL != core->running_job) - { - u32 val0 = 0; - u32 val1 = 0; -#if MALI_TIMELINE_PROFILING_ENABLED - u32 event_id; -#endif - -#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH - { - u32 src0, value0, src1, value1, sum, per_thousand, per_thousand_now, diff0, diff1; - static u32 print_nr=0; - static u32 prev0=0; - static u32 prev1=0; - if ( !(++print_nr&511) ) - { - mali_l2_cache_core_get_counter_values(mali_l2_cache_core_get_glob_l2_core(0), &src0, &value0, &src1, &value1); - MALI_DEBUG_ASSERT( src0==20 ); /* Read hits */ - MALI_DEBUG_ASSERT( src1==21 ); /* Read misses */ - - sum = value0+value1; - if ( sum > 1000000 ) - { - per_thousand = value0 / (sum/1000); - } - else - { - per_thousand = (value0*1000) / (sum); - } - diff0 = value0-prev0; - diff1 = value1-prev1; - - sum = diff0 + diff1 ; - if ( sum > 1000000 ) - { - per_thousand_now = diff0 / (sum/1000); - } - else - { - per_thousand_now = (diff0*1000) / (sum); - } - - prev0=value0; - prev1=value1; - if (per_thousand_now<=1000) - { - MALI_DEBUG_PRINT(2, ("Mali L2: Read hits/misses: %d/%d = %d thousand_parts total, since previous: %d\n", value0, value1, per_thousand, per_thousand_now)); - } - - } - } -#endif - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); - if (mali_gp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_gp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_gp_job_set_perf_counter_value0(core->running_job, val0); - } - else - { - /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ - mali_gp_job_set_perf_counter_value0(core->running_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0); -#endif - - } - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); - if (mali_gp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_gp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_gp_job_set_perf_counter_value1(core->running_job, val1); - } - else - { - /* User space asked for a counter, but this is not what we retrieved (overridden by counter src set on core) */ - mali_gp_job_set_perf_counter_value1(core->running_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1); -#endif - } - -#if MALI_TIMELINE_PROFILING_ENABLED - if (MALI_TRUE == suspend) - { - event_id = MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); - } - else - { - event_id = MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0); - } - _mali_osk_profiling_add_event(event_id, val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); -#endif - - mali_gp_job_set_current_heap_addr(core->running_job, - mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR)); - - if (MALI_TRUE != suspend) - { - /* We are no longer running a job... */ - core->running_job = NULL; - _mali_osk_timer_del(core->timeout_timer); - } - } -} - -/* callback function for gp core timeout */ -static void mali_gp_timeout(void *data) -{ - struct mali_gp_core * core = ((struct mali_gp_core *)data); - - MALI_DEBUG_PRINT(3, ("Mali GP: TIMEOUT callback \n")); - core->core_timed_out = MALI_TRUE; - _mali_osk_irq_schedulework(core->irq); -} - -#if 0 -void mali_gp_print_state(struct mali_gp_core *core) -{ - MALI_DEBUG_PRINT(2, ("Mali GP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) )); -} -#endif - -#if MALI_STATE_TRACKING -u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_gp.h b/drivers/media/video/samsung/mali/common/mali_gp.h deleted file mode 100644 index 3175b75..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011-2012 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_GP_H__ -#define __MALI_GP_H__ - -#include "mali_osk.h" -#include "mali_gp_job.h" - -struct mali_gp_core; -struct mali_group; - -_mali_osk_errcode_t mali_gp_initialize(void); -void mali_gp_terminate(void); - -struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group); -void mali_gp_delete(struct mali_gp_core *core); - -void mali_gp_stop_bus(struct mali_gp_core *core); -_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core); -void mali_gp_hard_reset(struct mali_gp_core *core); -_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core); - -void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job); -void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr); - -void mali_gp_abort_job(struct mali_gp_core *core); - -u32 mali_gp_core_get_version(struct mali_gp_core *core); - -mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter); -mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter); -u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core); -u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core); -struct mali_gp_core *mali_gp_get_global_gp_core(void); - -u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size); - -#endif /* __MALI_GP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.c b/drivers/media/video/samsung/mali/common/mali_gp_job.c deleted file mode 100644 index abe1d93..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp_job.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_gp_job.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_uk_types.h" - -struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id) -{ - struct mali_gp_job *job; - - job = _mali_osk_malloc(sizeof(struct mali_gp_job)); - if (NULL != job) - { - _mali_osk_list_init(&job->list); - job->session = session; - job->id = id; - job->user_id = args->user_job_ptr; - _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); - job->heap_current_addr = args->frame_registers[4]; - job->perf_counter_flag = args->perf_counter_flag; - job->perf_counter_src0 = args->perf_counter_src0; - job->perf_counter_src1 = args->perf_counter_src1; - job->perf_counter_value0 = 0; - job->perf_counter_value1 = 0; - - job->pid = _mali_osk_get_pid(); - job->tid = _mali_osk_get_tid(); - job->frame_builder_id = args->frame_builder_id; - job->flush_id = args->flush_id; - - return job; - } - - return NULL; -} - -void mali_gp_job_delete(struct mali_gp_job *job) -{ - _mali_osk_free(job); -} diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c deleted file mode 100644 index f06d899..0000000 --- a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (C) 2012 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 "mali_gp_scheduler.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_scheduler.h" -#include "mali_gp.h" -#include "mali_gp_job.h" -#include "mali_group.h" -#include "mali_cluster.h" - -enum mali_gp_slot_state -{ - MALI_GP_SLOT_STATE_IDLE, - MALI_GP_SLOT_STATE_WORKING, -}; - -/* A render slot is an entity which jobs can be scheduled onto */ -struct mali_gp_slot -{ - struct mali_group *group; - /* - * We keep track of the state here as well as in the group object - * so we don't need to take the group lock so often (and also avoid clutter with the working lock) - */ - enum mali_gp_slot_state state; - u32 returned_cookie; -}; - -static u32 gp_version = 0; -static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ -static struct mali_gp_slot slot; - -/* Variables to allow safe pausing of the scheduler */ -static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL; -static u32 pause_count = 0; - -static mali_bool mali_gp_scheduler_is_suspended(void); - -static _mali_osk_lock_t *gp_scheduler_lock = NULL; -/* Contains tid of thread that locked the scheduler or 0, if not locked */ - -_mali_osk_errcode_t mali_gp_scheduler_initialize(void) -{ - u32 i; - - _MALI_OSK_INIT_LIST_HEAD(&job_queue); - - gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); - if (NULL == gp_scheduler_lock) - { - return _MALI_OSK_ERR_NOMEM; - } - - gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); - if (NULL == gp_scheduler_working_wait_queue) - { - _mali_osk_lock_term(gp_scheduler_lock); - return _MALI_OSK_ERR_NOMEM; - } - - /* Find all the available GP cores */ - for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++) - { - u32 group_id = 0; - struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i); - struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id); - while (NULL != group) - { - struct mali_gp_core *gp_core = mali_group_get_gp_core(group); - if (NULL != gp_core) - { - if (0 == gp_version) - { - /* Retrieve GP version */ - gp_version = mali_gp_core_get_version(gp_core); - } - slot.group = group; - slot.state = MALI_GP_SLOT_STATE_IDLE; - break; /* There are only one GP, no point in looking for more */ - } - group_id++; - group = mali_cluster_get_group(curr_cluster, group_id); - } - } - - return _MALI_OSK_ERR_OK; -} - -void mali_gp_scheduler_terminate(void) -{ - _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue); - _mali_osk_lock_term(gp_scheduler_lock); -} - -MALI_STATIC_INLINE void mali_gp_scheduler_lock(void) -{ - if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) - { - /* Non-interruptable lock failed: this should never happen. */ - MALI_DEBUG_ASSERT(0); - } - MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n")); -} - -MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void) -{ - MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n")); - _mali_osk_lock_signal(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); -} - -#ifdef DEBUG -MALI_STATIC_INLINE void mali_gp_scheduler_assert_locked(void) -{ - MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock); -} -#define MALI_ASSERT_GP_SCHEDULER_LOCKED() mali_gp_scheduler_assert_locked() -#else -#define MALI_ASSERT_GP_SCHEDULER_LOCKED() -#endif - -static void mali_gp_scheduler_schedule(void) -{ - struct mali_gp_job *job; - - MALI_ASSERT_GP_SCHEDULER_LOCKED(); - - if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue)) - { - MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", - pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0)); - return; /* Nothing to do, so early out */ - } - - job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list); - - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job)); - if (_MALI_OSK_ERR_OK == mali_group_start_gp_job(slot.group, job)) - { - /* Mark slot as busy */ - slot.state = MALI_GP_SLOT_STATE_WORKING; - - /* Remove from queue of unscheduled jobs */ - _mali_osk_list_del(&job->list); - } - else - { - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n")); - } -} - -static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) -{ - _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); - if (NULL != notobj) - { - _mali_uk_gp_job_finished_s *jobres = notobj->result_buffer; - _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ - jobres->user_job_ptr = mali_gp_job_get_user_id(job); - if (MALI_TRUE == success) - { - jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; - } - else - { - jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; - } - - jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); - jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); - jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); - - mali_session_send_notification(mali_gp_job_get_session(job), notobj); - } - else - { - MALI_PRINT_ERROR(("Mali GP scheduler: Unable to allocate notification object\n")); - } - - mali_gp_job_delete(job); -} - - -void mali_gp_scheduler_do_schedule(void) -{ - mali_gp_scheduler_lock(); - - mali_gp_scheduler_schedule(); - - mali_gp_scheduler_unlock(); -} - -void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success) -{ - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure")); - - mali_gp_scheduler_lock(); - - /* Mark slot as idle again */ - slot.state = MALI_GP_SLOT_STATE_IDLE; - - /* If paused, then this was the last job, so wake up sleeping workers */ - if (pause_count > 0) - { - _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue); - } - else - { - mali_gp_scheduler_schedule(); - } - - mali_gp_scheduler_unlock(); - - mali_gp_scheduler_return_job_to_user(job, success); -} - -void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) -{ - _mali_osk_notification_t *notobj; - - notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); - - if (NULL != notobj) - { - _mali_uk_gp_job_suspended_s * jobres; - - mali_gp_scheduler_lock(); - - jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer; - - jobres->user_job_ptr = mali_gp_job_get_user_id(job); - jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; - jobres->cookie = mali_gp_job_get_id(job); - slot.returned_cookie = jobres->cookie; - - mali_session_send_notification(mali_gp_job_get_session(job), notobj); - - mali_gp_scheduler_unlock(); - } - - /* - * If this function failed, then we could return the job to user space right away, - * but there is a job timer anyway that will do that eventually. - * This is not exactly a common case anyway. - */ -} - -void mali_gp_scheduler_suspend(void) -{ - mali_gp_scheduler_lock(); - pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ - mali_gp_scheduler_unlock(); - - _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended); -} - -void mali_gp_scheduler_resume(void) -{ - mali_gp_scheduler_lock(); - pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ - if (0 == pause_count) - { - mali_gp_scheduler_schedule(); - } - mali_gp_scheduler_unlock(); -} - -_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args) -{ - struct mali_session_data *session; - struct mali_gp_job *job; - - MALI_DEBUG_ASSERT_POINTER(args); - - if (NULL == args->ctx) - { - return _MALI_OSK_ERR_INVALID_ARGS; - } - - session = (struct mali_session_data*)args->ctx; - if (NULL == session) - { - return _MALI_OSK_ERR_FAULT; - } - - job = mali_gp_job_create(session, args, mali_scheduler_get_new_id()); - if (NULL == job) - { - return _MALI_OSK_ERR_NOMEM; - } - -#if PROFILING_SKIP_PP_AND_GP_JOBS -#warning GP jobs will not be executed - mali_gp_scheduler_return_job_to_user(job, MALI_TRUE); - return _MALI_OSK_ERR_OK; -#endif - - mali_gp_scheduler_lock(); - - _mali_osk_list_addtail(&job->list, &job_queue); - - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job)); - - mali_gp_scheduler_schedule(); - - mali_gp_scheduler_unlock(); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - args->number_of_cores = 1; - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - args->version = gp_version; - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args) -{ - struct mali_session_data *session; - _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; - - MALI_DEBUG_ASSERT_POINTER(args); - - if (NULL == args->ctx) - { - return _MALI_OSK_ERR_INVALID_ARGS; - } - - session = (struct mali_session_data*)args->ctx; - if (NULL == session) - { - return _MALI_OSK_ERR_FAULT; - } - - mali_gp_scheduler_lock(); - - /* Make sure that the cookie returned by user space is the same as we provided in the first place */ - if (args->cookie != slot.returned_cookie) - { - MALI_DEBUG_PRINT(2, ("Mali GP scheduler: Got an illegal cookie from user space, expected %u but got %u (job id)\n", slot.returned_cookie, args->cookie)) ; - mali_gp_scheduler_unlock(); - return _MALI_OSK_ERR_FAULT; - } - - mali_gp_scheduler_unlock(); - - switch (args->code) - { - case _MALIGP_JOB_RESUME_WITH_NEW_HEAP: - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1])); - mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]); - ret = _MALI_OSK_ERR_OK; - break; - - case _MALIGP_JOB_ABORT: - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie)); - mali_group_abort_gp_job(slot.group, args->cookie); - ret = _MALI_OSK_ERR_OK; - break; - - default: - MALI_PRINT_ERROR(("Mali GP scheduler: Wrong suspend response from user space\n")); - ret = _MALI_OSK_ERR_FAULT; - break; - } - - return ret; - -} - -void mali_gp_scheduler_abort_session(struct mali_session_data *session) -{ - struct mali_gp_job *job, *tmp; - - mali_gp_scheduler_lock(); - MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session)); - - /* Check queue for jobs and remove */ - _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) - { - if (mali_gp_job_get_session(job) == session) - { - MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job)); - _mali_osk_list_del(&(job->list)); - mali_gp_job_delete(job); - } - } - - mali_gp_scheduler_unlock(); - - /* Abort running jobs from this session. It is safe to do this outside - * the scheduler lock as there is only one GP core, and the queue has - * already been emptied, as long as there are no new jobs coming in - * from user space. */ - mali_group_abort_session(slot.group, session); -} - -static mali_bool mali_gp_scheduler_is_suspended(void) -{ - mali_bool ret; - - mali_gp_scheduler_lock(); - ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE; - mali_gp_scheduler_unlock(); - - return ret; -} - - -#if MALI_STATE_TRACKING -u32 mali_gp_scheduler_dump_state(char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "GP\n"); - n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); - - n += mali_group_dump_state(slot.group, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", mali_group_gp_state(slot.group)); - n += _mali_osk_snprintf(buf + n, size - n, "\n"); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_group.c b/drivers/media/video/samsung/mali/common/mali_group.c deleted file mode 100644 index 94bf774..0000000 --- a/drivers/media/video/samsung/mali/common/mali_group.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_kernel_common.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_mmu.h" -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_pm.h" - -/* - * The group object is the most important object in the device driver, - * and acts as the center of many HW operations. - * The reason for this is that operations on the MMU will affect all - * cores connected to this MMU (a group is defined by the MMU and the - * cores which are connected to this). - * The group lock is thus the most important lock, followed by the - * GP and PP scheduler locks. They must be taken in the following - * order: - * GP/PP lock first, then group lock(s). - */ - -/** - * The structure represents a render group - * A render group is defined by all the cores that share the same Mali MMU - */ - -struct mali_group -{ - struct mali_cluster *cluster; - - struct mali_mmu_core *mmu; - struct mali_session_data *session; - int page_dir_ref_count; - mali_bool power_is_on; -#if defined(USING_MALI200) - mali_bool pagedir_activation_failed; -#endif - - struct mali_gp_core *gp_core; - enum mali_group_core_state gp_state; - struct mali_gp_job *gp_running_job; - - struct mali_pp_core *pp_core; - enum mali_group_core_state pp_state; - struct mali_pp_job *pp_running_job; - u32 pp_running_sub_job; - - _mali_osk_lock_t *lock; -}; - -static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS]; -static u32 mali_global_num_groups = 0; - -enum mali_group_activate_pd_status -{ - MALI_GROUP_ACTIVATE_PD_STATUS_FAILED, - MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD, - MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD, -}; - -/* local helper functions */ -static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session); -static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session); -static void mali_group_recovery_reset(struct mali_group *group); -static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success); - -void mali_group_lock(struct mali_group *group) -{ - if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW)) - { - /* Non-interruptable lock failed: this should never happen. */ - MALI_DEBUG_ASSERT(0); - } - MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group)); -} - -void mali_group_unlock(struct mali_group *group) -{ - MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group)); - _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW); -} - -#ifdef DEBUG -void mali_group_assert_locked(struct mali_group *group) -{ - MALI_DEBUG_ASSERT_LOCK_HELD(group->lock); -} -#endif - - -struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu) -{ - struct mali_group *group = NULL; - - if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS) - { - MALI_PRINT_ERROR(("Mali group: Too many group objects created\n")); - return NULL; - } - - group = _mali_osk_malloc(sizeof(struct mali_group)); - if (NULL != group) - { - _mali_osk_memset(group, 0, sizeof(struct mali_group)); - group->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_GROUP); - if (NULL != group->lock) - { - group->cluster = cluster; - group->mmu = mmu; /* This group object now owns the MMU object */ - group->session = NULL; - group->page_dir_ref_count = 0; - group->power_is_on = MALI_TRUE; - - group->gp_state = MALI_GROUP_CORE_STATE_IDLE; - group->pp_state = MALI_GROUP_CORE_STATE_IDLE; -#if defined(USING_MALI200) - group->pagedir_activation_failed = MALI_FALSE; -#endif - mali_global_groups[mali_global_num_groups] = group; - mali_global_num_groups++; - - return group; - } - _mali_osk_free(group); - } - - return NULL; -} - -void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core) -{ - /* This group object now owns the GP core object */ - group->gp_core = gp_core; -} - -void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core) -{ - /* This group object now owns the PP core object */ - group->pp_core = pp_core; -} - -void mali_group_delete(struct mali_group *group) -{ - u32 i; - - /* Delete the resources that this group owns */ - if (NULL != group->gp_core) - { - mali_gp_delete(group->gp_core); - } - - if (NULL != group->pp_core) - { - mali_pp_delete(group->pp_core); - } - - if (NULL != group->mmu) - { - mali_mmu_delete(group->mmu); - } - - for (i = 0; i < mali_global_num_groups; i++) - { - if (mali_global_groups[i] == group) - { - mali_global_groups[i] = NULL; - mali_global_num_groups--; - break; - } - } - - _mali_osk_lock_term(group->lock); - - _mali_osk_free(group); -} - -/* Called from mali_cluster_reset() when the system is re-turned on */ -void mali_group_reset(struct mali_group *group) -{ - mali_group_lock(group); - - group->session = NULL; - - if (NULL != group->mmu) - { - mali_mmu_reset(group->mmu); - } - - if (NULL != group->gp_core) - { - mali_gp_reset(group->gp_core); - } - - if (NULL != group->pp_core) - { - mali_pp_reset(group->pp_core); - } - - mali_group_unlock(group); -} - -struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group) -{ - return group->gp_core; -} - -struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group) -{ - return group->pp_core; -} - -_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job) -{ - struct mali_session_data *session; - enum mali_group_activate_pd_status activate_status; - - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - - mali_pm_core_event(MALI_CORE_EVENT_GP_START); - - session = mali_gp_job_get_session(job); - - mali_group_lock(group); - - mali_cluster_l2_cache_invalidate_all(group->cluster, mali_gp_job_get_id(job)); - - activate_status = mali_group_activate_page_directory(group, session); - if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) - { - /* if session is NOT kept Zapping is done as part of session switch */ - if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) - { - mali_mmu_zap_tlb_without_stall(group->mmu); - } - mali_gp_job_start(group->gp_core, job); - group->gp_running_job = job; - group->gp_state = MALI_GROUP_CORE_STATE_WORKING; - - mali_group_unlock(group); - - return _MALI_OSK_ERR_OK; - } - -#if defined(USING_MALI200) - group->pagedir_activation_failed = MALI_TRUE; -#endif - - mali_group_unlock(group); - - mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_GP_START */ - return _MALI_OSK_ERR_FAULT; -} - -_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job) -{ - struct mali_session_data *session; - enum mali_group_activate_pd_status activate_status; - - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - - mali_pm_core_event(MALI_CORE_EVENT_PP_START); - - session = mali_pp_job_get_session(job); - - mali_group_lock(group); - - mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job)); - - activate_status = mali_group_activate_page_directory(group, session); - if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) - { - /* if session is NOT kept Zapping is done as part of session switch */ - if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) - { - MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n")); - mali_mmu_zap_tlb_without_stall(group->mmu); - } - mali_pp_job_start(group->pp_core, job, sub_job); - group->pp_running_job = job; - group->pp_running_sub_job = sub_job; - group->pp_state = MALI_GROUP_CORE_STATE_WORKING; - - mali_group_unlock(group); - - return _MALI_OSK_ERR_OK; - } - -#if defined(USING_MALI200) - group->pagedir_activation_failed = MALI_TRUE; -#endif - - mali_group_unlock(group); - - mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_PP_START */ - return _MALI_OSK_ERR_FAULT; -} - -void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr) -{ - mali_group_lock(group); - - if (group->gp_state != MALI_GROUP_CORE_STATE_OOM || - mali_gp_job_get_id(group->gp_running_job) != job_id) - { - mali_group_unlock(group); - return; /* Illegal request or job has already been aborted */ - } - - mali_cluster_l2_cache_invalidate_all_force(group->cluster); - mali_mmu_zap_tlb_without_stall(group->mmu); - - mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr); - group->gp_state = MALI_GROUP_CORE_STATE_WORKING; - - mali_group_unlock(group); -} - -void mali_group_abort_gp_job(struct mali_group *group, u32 job_id) -{ - mali_group_lock(group); - - if (group->gp_state == MALI_GROUP_CORE_STATE_IDLE || - mali_gp_job_get_id(group->gp_running_job) != job_id) - { - mali_group_unlock(group); - return; /* No need to cancel or job has already been aborted or completed */ - } - - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* Will release group lock */ -} - -void mali_group_abort_pp_job(struct mali_group *group, u32 job_id) -{ - mali_group_lock(group); - - if (group->pp_state == MALI_GROUP_CORE_STATE_IDLE || - mali_pp_job_get_id(group->pp_running_job) != job_id) - { - mali_group_unlock(group); - return; /* No need to cancel or job has already been aborted or completed */ - } - - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* Will release group lock */ -} - -void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session) -{ - struct mali_gp_job *gp_job; - struct mali_pp_job *pp_job; - u32 gp_job_id = 0; - u32 pp_job_id = 0; - mali_bool abort_pp = MALI_FALSE; - mali_bool abort_gp = MALI_FALSE; - - mali_group_lock(group); - - gp_job = group->gp_running_job; - pp_job = group->pp_running_job; - - if (gp_job && mali_gp_job_get_session(gp_job) == session) - { - MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session)); - - gp_job_id = mali_gp_job_get_id(gp_job); - abort_gp = MALI_TRUE; - } - - if (pp_job && mali_pp_job_get_session(pp_job) == session) - { - MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session)); - - pp_job_id = mali_pp_job_get_id(pp_job); - abort_pp = MALI_TRUE; - } - - mali_group_unlock(group); - - /* These functions takes and releases the group lock */ - if (0 != abort_gp) - { - mali_group_abort_gp_job(group, gp_job_id); - } - if (0 != abort_pp) - { - mali_group_abort_pp_job(group, pp_job_id); - } - - mali_group_lock(group); - mali_group_remove_session_if_unused(group, session); - mali_group_unlock(group); -} - -enum mali_group_core_state mali_group_gp_state(struct mali_group *group) -{ - return group->gp_state; -} - -enum mali_group_core_state mali_group_pp_state(struct mali_group *group) -{ - return group->pp_state; -} - -/* group lock need to be taken before calling mali_group_bottom_half */ -void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - switch (event) - { - case GROUP_EVENT_PP_JOB_COMPLETED: - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_TRUE); /* PP job SUCCESS */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_PP_JOB_FAILED: - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job FAIL */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_PP_JOB_TIMED_OUT: - mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job TIMEOUT */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_JOB_COMPLETED: - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_TRUE); /* GP job SUCCESS */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_JOB_FAILED: - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job FAIL */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_JOB_TIMED_OUT: - mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job TIMEOUT */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - case GROUP_EVENT_GP_OOM: - group->gp_state = MALI_GROUP_CORE_STATE_OOM; - mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */ - mali_gp_scheduler_oom(group, group->gp_running_job); - break; - case GROUP_EVENT_MMU_PAGE_FAULT: - mali_group_complete_jobs(group, MALI_TRUE, MALI_TRUE, MALI_FALSE); /* GP and PP job FAIL */ - /* group lock is released by mali_group_complete_jobs() call above */ - break; - default: - break; - } -} - -struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group) -{ - return group->mmu; -} - -struct mali_session_data *mali_group_get_session(struct mali_group *group) -{ - return group->session; -} - -struct mali_group *mali_group_get_glob_group(u32 index) -{ - if(mali_global_num_groups > index) - { - return mali_global_groups[index]; - } - - return NULL; -} - -u32 mali_group_get_glob_num_groups(void) -{ - return mali_global_num_groups; -} - -/* Used to check if scheduler for the other core type needs to be called on job completion. - * - * Used only for Mali-200, where job start may fail if the only MMU is busy - * with another session's address space. - */ -static inline mali_bool mali_group_other_reschedule_needed(struct mali_group *group) -{ - MALI_ASSERT_GROUP_LOCKED(group); - -#if defined(USING_MALI200) - if (group->pagedir_activation_failed) - { - group->pagedir_activation_failed = MALI_FALSE; - return MALI_TRUE; - } - else -#endif - { - return MALI_FALSE; - } -} - -static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session) -{ - enum mali_group_activate_pd_status retval; - MALI_ASSERT_GROUP_LOCKED(group); - - MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group)); - MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); - - if (0 != group->page_dir_ref_count) - { - if (group->session != session) - { - MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session)); - return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; - } - else - { - MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count)); - retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; - - } - } - else - { - /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */ - if (group->session != session) - { - mali_bool activate_success; - MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count)); - - activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session)); - MALI_DEBUG_ASSERT(activate_success); - if ( MALI_FALSE== activate_success ) return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED; - group->session = session; - retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD; - } - else - { - MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count)); - retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD; - } - } - - group->page_dir_ref_count++; - return retval; -} - -static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count); - MALI_DEBUG_ASSERT(session == group->session); - - group->page_dir_ref_count--; - - /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count), - and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */ - MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count); -} - -void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - if (0 == group->page_dir_ref_count) - { - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - - if (group->session == session) - { - MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); - MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group)); - mali_mmu_activate_empty_page_directory(group->mmu); - group->session = NULL; - } - } -} - -void mali_group_power_on(void) -{ - int i; - for (i = 0; i < mali_global_num_groups; i++) - { - struct mali_group *group = mali_global_groups[i]; - mali_group_lock(group); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - MALI_DEBUG_ASSERT_POINTER(group->cluster); - group->power_is_on = MALI_TRUE; - mali_cluster_power_is_enabled_set(group->cluster, MALI_TRUE); - mali_group_unlock(group); - } - MALI_DEBUG_PRINT(3,("group: POWER ON\n")); -} - -mali_bool mali_group_power_is_on(struct mali_group *group) -{ - MALI_ASSERT_GROUP_LOCKED(group); - return group->power_is_on; -} - -void mali_group_power_off(void) -{ - int i; - /* It is necessary to set group->session = NULL; so that the powered off MMU is not written to on map /unmap */ - /* It is necessary to set group->power_is_on=MALI_FALSE so that pending bottom_halves does not access powered off cores. */ - for (i = 0; i < mali_global_num_groups; i++) - { - struct mali_group *group = mali_global_groups[i]; - mali_group_lock(group); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); - MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); - MALI_DEBUG_ASSERT_POINTER(group->cluster); - group->session = NULL; - MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on); - group->power_is_on = MALI_FALSE; - mali_cluster_power_is_enabled_set(group->cluster, MALI_FALSE); - mali_group_unlock(group); - } - MALI_DEBUG_PRINT(3,("group: POWER OFF\n")); -} - - -static void mali_group_recovery_reset(struct mali_group *group) -{ - MALI_ASSERT_GROUP_LOCKED(group); - - /* Stop cores, bus stop */ - if (NULL != group->pp_core) - { - mali_pp_stop_bus(group->pp_core); - } - if (NULL != group->gp_core) - { - mali_gp_stop_bus(group->gp_core); - } - - /* Flush MMU */ - mali_mmu_activate_fault_flush_page_directory(group->mmu); - mali_mmu_page_fault_done(group->mmu); - - /* Wait for cores to stop bus */ - if (NULL != group->pp_core) - { - mali_pp_stop_bus_wait(group->pp_core); - } - if (NULL != group->gp_core) - { - mali_gp_stop_bus_wait(group->gp_core); - } - - /* Reset cores */ - if (NULL != group->pp_core) - { - mali_pp_hard_reset(group->pp_core); - } - if (NULL != group->gp_core) - { - mali_gp_hard_reset(group->gp_core); - } - - /* Reset MMU */ - mali_mmu_reset(group->mmu); - group->session = NULL; -} - -/* Group lock need to be taken before calling mali_group_complete_jobs. Will release the lock here. */ -static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success) -{ - mali_bool need_group_reset = MALI_FALSE; - mali_bool gp_success = success; - mali_bool pp_success = success; - - MALI_ASSERT_GROUP_LOCKED(group); - - if (complete_gp && !complete_pp) - { - MALI_DEBUG_ASSERT_POINTER(group->gp_core); - if (_MALI_OSK_ERR_OK == mali_gp_reset(group->gp_core)) - { - struct mali_gp_job *gp_job_to_return = group->gp_running_job; - group->gp_state = MALI_GROUP_CORE_STATE_IDLE; - group->gp_running_job = NULL; - - MALI_DEBUG_ASSERT_POINTER(gp_job_to_return); - - mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); - - if(mali_group_other_reschedule_needed(group)) - { - mali_group_unlock(group); - mali_pp_scheduler_do_schedule(); - } - else - { - mali_group_unlock(group); - } - - mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); - mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - - return; - } - else - { - need_group_reset = MALI_TRUE; - MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n")); - pp_success = MALI_FALSE; /* This might kill PP as well, so this should fail */ - } - } - if (complete_pp && !complete_gp) - { - MALI_DEBUG_ASSERT_POINTER(group->pp_core); - if (_MALI_OSK_ERR_OK == mali_pp_reset(group->pp_core)) - { - struct mali_pp_job *pp_job_to_return = group->pp_running_job; - u32 pp_sub_job_to_return = group->pp_running_sub_job; - group->pp_state = MALI_GROUP_CORE_STATE_IDLE; - group->pp_running_job = NULL; - - MALI_DEBUG_ASSERT_POINTER(pp_job_to_return); - - mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); - - if(mali_group_other_reschedule_needed(group)) - { - mali_group_unlock(group); - mali_gp_scheduler_do_schedule(); - } - else - { - mali_group_unlock(group); - } - - mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); - mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - - return; - } - else - { - need_group_reset = MALI_TRUE; - MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n")); - gp_success = MALI_FALSE; /* This might kill GP as well, so this should fail */ - } - } - else if (complete_gp && complete_pp) - { - need_group_reset = MALI_TRUE; - } - - if (MALI_TRUE == need_group_reset) - { - struct mali_gp_job *gp_job_to_return = group->gp_running_job; - struct mali_pp_job *pp_job_to_return = group->pp_running_job; - u32 pp_sub_job_to_return = group->pp_running_sub_job; - mali_bool schedule_other = MALI_FALSE; - - MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n")); - - group->gp_state = MALI_GROUP_CORE_STATE_IDLE; - group->gp_running_job = NULL; - if (NULL != gp_job_to_return) - { - mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); - } - - group->pp_state = MALI_GROUP_CORE_STATE_IDLE; - group->pp_running_job = NULL; - if (NULL != pp_job_to_return) - { - mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); - } - - /* The reset has to be done after mali_group_deactivate_page_directory() */ - mali_group_recovery_reset(group); - - if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return)) - { - schedule_other = MALI_TRUE; - } - - mali_group_unlock(group); - - if (NULL != gp_job_to_return) - { - mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); - mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - } - else if (schedule_other) - { - mali_pp_scheduler_do_schedule(); - } - - if (NULL != pp_job_to_return) - { - mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); - mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ - } - else if (schedule_other) - { - mali_gp_scheduler_do_schedule(); - } - - return; - } - - mali_group_unlock(group); -} - -#if MALI_STATE_TRACKING -u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group); - if (group->gp_core) - { - n += mali_gp_dump_state(group->gp_core, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\tGP state: %d\n", group->gp_state); - n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job); - } - if (group->pp_core) - { - n += mali_pp_dump_state(group->pp_core, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\tPP state: %d\n", group->pp_state); - n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n", - group->pp_running_job, group->pp_running_sub_job); - } - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_group.h b/drivers/media/video/samsung/mali/common/mali_group.h deleted file mode 100644 index 3533d13..0000000 --- a/drivers/media/video/samsung/mali/common/mali_group.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2011-2012 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_GROUP_H__ -#define __MALI_GROUP_H__ - -#include "linux/jiffies.h" -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_mmu.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_session.h" - -/* max runtime [ms] for a core job - used by timeout timers */ -#define MAX_RUNTIME 5000 -/** @brief A mali group object represents a MMU and a PP and/or a GP core. - * - */ -#define MALI_MAX_NUMBER_OF_GROUPS 9 - -struct mali_group; - -enum mali_group_event_t -{ - GROUP_EVENT_PP_JOB_COMPLETED, /**< PP job completed successfully */ - GROUP_EVENT_PP_JOB_FAILED, /**< PP job completed with failure */ - GROUP_EVENT_PP_JOB_TIMED_OUT, /**< PP job reached max runtime */ - GROUP_EVENT_GP_JOB_COMPLETED, /**< GP job completed successfully */ - GROUP_EVENT_GP_JOB_FAILED, /**< GP job completed with failure */ - GROUP_EVENT_GP_JOB_TIMED_OUT, /**< GP job reached max runtime */ - GROUP_EVENT_GP_OOM, /**< GP job ran out of heap memory */ - GROUP_EVENT_MMU_PAGE_FAULT, /**< MMU page fault */ -}; - -enum mali_group_core_state -{ - MALI_GROUP_CORE_STATE_IDLE, - MALI_GROUP_CORE_STATE_WORKING, - MALI_GROUP_CORE_STATE_OOM -}; - -/** @brief Create a new Mali group object - * - * @param cluster Pointer to the cluster to which the group is connected. - * @param mmu Pointer to the MMU that defines this group - * @return A pointer to a new group object - */ -struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu); -void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core); -void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core); -void mali_group_delete(struct mali_group *group); - -/** @brief Reset group - * - * This function will reset the entire group, including all the cores present in the group. - * - * @param group Pointer to the group to reset - */ -void mali_group_reset(struct mali_group *group); - -/** @brief Get pointer to GP core object - */ -struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group); - -/** @brief Get pointer to PP core object - */ -struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group); - -/** @brief Lock group object - * - * Most group functions will lock the group object themselves. The expection is - * the group_bottom_half which requires the group to be locked on entry. - * - * @param group Pointer to group to lock - */ -void mali_group_lock(struct mali_group *group); - -/** @brief Unlock group object - * - * @param group Pointer to group to unlock - */ -void mali_group_unlock(struct mali_group *group); -#ifdef DEBUG -void mali_group_assert_locked(struct mali_group *group); -#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group) -#else -#define MALI_ASSERT_GROUP_LOCKED(group) -#endif - -/** @brief Start GP job - */ -_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job); -/** @brief Start fragment of PP job - */ -_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job); - -/** @brief Resume GP job that suspended waiting for more heap memory - */ -void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr); -/** @brief Abort GP job - * - * Used to abort suspended OOM jobs when user space failed to allocte more memory. - */ -void mali_group_abort_gp_job(struct mali_group *group, u32 job_id); -/** @brief Abort all GP jobs from \a session - * - * Used on session close when terminating all running and queued jobs from \a session. - */ -void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session); - -enum mali_group_core_state mali_group_gp_state(struct mali_group *group); -enum mali_group_core_state mali_group_pp_state(struct mali_group *group); - -/** @brief The common group bottom half interrupt handler - * - * This is only called from the GP and PP bottom halves. - * - * The action taken is dictated by the \a event. - * - * @param event The event code - */ -void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event); - -struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group); -struct mali_session_data *mali_group_get_session(struct mali_group *group); - -void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session_data); - -void mali_group_power_on(void); -void mali_group_power_off(void); -mali_bool mali_group_power_is_on(struct mali_group *group); - -struct mali_group *mali_group_get_glob_group(u32 index); -u32 mali_group_get_glob_num_groups(void); - -u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size); - -#endif /* __MALI_GROUP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.c b/drivers/media/video/samsung/mali/common/mali_kernel_core.c deleted file mode 100644 index 45e86d2..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_core.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_kernel_core.h" -#include "mali_memory.h" -#include "mali_mem_validation.h" -#include "mali_mmu.h" -#include "mali_mmu_page_directory.h" -#include "mali_dlbu.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_cluster.h" -#include "mali_group.h" -#include "mali_pm.h" -#include "mali_pmu.h" -#include "mali_scheduler.h" -#ifdef CONFIG_MALI400_GPU_UTILIZATION -#include "mali_kernel_utilization.h" -#endif -#include "mali_l2_cache.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -/** Pointer to table of resource definitions available to the Mali driver. - * _mali_osk_resources_init() sets up the pointer to this table. - */ -static _mali_osk_resource_t *arch_configuration = NULL; - -/** Start profiling from module load? */ -int mali_boot_profiling = 0; - -/** Number of resources initialized by _mali_osk_resources_init() */ -static u32 num_resources; - -static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN; -static u32 global_gpu_base_address = 0; -static u32 global_gpu_major_version = 0; -static u32 global_gpu_minor_version = 0; - -static u32 first_pp_offset = 0; - -#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */ -#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */ - -/* timer related */ -int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; -int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT; - -static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset) -{ - int i; - u32 addr = global_gpu_base_address + offset; - - for (i = 0; i < num_resources; i++) - { - if (type == arch_configuration[i].type && arch_configuration[i].base == addr) - { - return &(arch_configuration[i]); - } - } - - return NULL; -} - -static u32 mali_count_resources(_mali_osk_resource_type_t type) -{ - int i; - u32 retval = 0; - - for (i = 0; i < num_resources; i++) - { - if (type == arch_configuration[i].type) - { - retval++; - } - } - - return retval; -} - - -static _mali_osk_errcode_t mali_parse_gpu_base_and_first_pp_offset_address(void) -{ - int i; - _mali_osk_resource_t *first_gp_resource = NULL; - _mali_osk_resource_t *first_pp_resource = NULL; - - for (i = 0; i < num_resources; i++) - { - if (MALI_GP == arch_configuration[i].type) - { - if (NULL == first_gp_resource || first_gp_resource->base > arch_configuration[i].base) - { - first_gp_resource = &(arch_configuration[i]); - } - } - if (MALI_PP == arch_configuration[i].type) - { - if (NULL == first_pp_resource || first_pp_resource->base > arch_configuration[i].base) - { - first_pp_resource = &(arch_configuration[i]); - } - } - } - - if (NULL == first_gp_resource || NULL == first_pp_resource) - { - MALI_PRINT_ERROR(("No GP+PP core specified in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - if (first_gp_resource->base < first_pp_resource->base) - { - /* GP is first, so we are dealing with Mali-300, Mali-400 or Mali-450 */ - global_gpu_base_address = first_gp_resource->base; - first_pp_offset = 0x8000; - } - else - { - /* PP is first, so we are dealing with Mali-200 */ - global_gpu_base_address = first_pp_resource->base; - first_pp_offset = 0x0; - } - MALI_SUCCESS; -} - -static _mali_osk_errcode_t mali_parse_product_info(void) -{ - _mali_osk_resource_t *first_pp_resource = NULL; - - /* Find the first PP core */ - first_pp_resource = mali_find_resource(MALI_PP, first_pp_offset); - if (NULL != first_pp_resource) - { - /* Create a dummy PP object for this core so that we can read the version register */ - struct mali_group *group = mali_group_create(NULL, NULL); - if (NULL != group) - { - /*struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group, 0);*/ - struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group); - if (NULL != pp_core) - { - u32 pp_version = mali_pp_core_get_version(pp_core); - mali_pp_delete(pp_core); - mali_group_delete(group); - - global_gpu_major_version = (pp_version >> 8) & 0xFF; - global_gpu_minor_version = pp_version & 0xFF; - - switch (pp_version >> 16) - { - case MALI200_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI200; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - case MALI300_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI300; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - case MALI400_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI400; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - case MALI450_PP_PRODUCT_ID: - global_product_id = _MALI_PRODUCT_ID_MALI450; - MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version)); - break; - default: - MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version)); - return _MALI_OSK_ERR_FAULT; - } - - return _MALI_OSK_ERR_OK; - } - else - { - MALI_PRINT_ERROR(("Failed to create initial PP object\n")); - } - } - else - { - MALI_PRINT_ERROR(("Failed to create initial group object\n")); - } - } - else - { - MALI_PRINT_ERROR(("First PP core not specified in config file\n")); - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_delete_clusters(void) -{ - u32 i; - u32 number_of_clusters = mali_cluster_get_glob_num_clusters(); - - for (i = 0; i < number_of_clusters; i++) - { - mali_cluster_delete(mali_cluster_get_global_cluster(i)); - } -} - -static _mali_osk_errcode_t mali_create_cluster(_mali_osk_resource_t *resource) -{ - if (NULL != resource) - { - struct mali_l2_cache_core *l2_cache; - - if (mali_l2_cache_core_get_glob_num_l2_cores() >= mali_l2_cache_core_get_max_num_l2_cores()) - { - MALI_PRINT_ERROR(("Found too many L2 cache core objects, max %u is supported\n", mali_l2_cache_core_get_max_num_l2_cores())); - return _MALI_OSK_ERR_FAULT; - } - - MALI_DEBUG_PRINT(3, ("Found L2 cache %s, starting new cluster\n", resource->description)); - - /*l2_cache = mali_l2_cache_create(resource, global_num_l2_cache_cores);*/ - l2_cache = mali_l2_cache_create(resource); - if (NULL == l2_cache) - { - MALI_PRINT_ERROR(("Failed to create L2 cache object\n")); - return _MALI_OSK_ERR_FAULT; - } - - if (NULL == mali_cluster_create(l2_cache)) - { - MALI_PRINT_ERROR(("Failed to create cluster object\n")); - mali_l2_cache_delete(l2_cache); - return _MALI_OSK_ERR_FAULT; - } - } - else - { - mali_cluster_create(NULL); - if (NULL == mali_cluster_get_global_cluster(0)) - { - MALI_PRINT_ERROR(("Failed to create cluster object\n")); - return _MALI_OSK_ERR_FAULT; - } - } - - MALI_DEBUG_PRINT(3, ("Created cluster object\n")); - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_parse_config_cluster(void) -{ - if (_MALI_PRODUCT_ID_MALI200 == global_product_id) - { - /* Create dummy cluster without L2 cache */ - return mali_create_cluster(NULL); - } - else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || _MALI_PRODUCT_ID_MALI400 == global_product_id) - { - _mali_osk_resource_t *l2_resource = mali_find_resource(MALI_L2, 0x1000); - if (NULL == l2_resource) - { - MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - return mali_create_cluster(l2_resource); - } - else if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - /* - * L2 for GP at 0x10000 - * L2 for PP0-3 at 0x01000 - * L2 for PP4-7 at 0x11000 (optional) - */ - - _mali_osk_resource_t *l2_gp_resource; - _mali_osk_resource_t *l2_pp_grp0_resource; - _mali_osk_resource_t *l2_pp_grp1_resource; - - /* Make cluster for GP's L2 */ - l2_gp_resource = mali_find_resource(MALI_L2, 0x10000); - if (NULL != l2_gp_resource) - { - _mali_osk_errcode_t ret; - MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for GP\n")); - ret = mali_create_cluster(l2_gp_resource); - if (_MALI_OSK_ERR_OK != ret) - { - return ret; - } - } - else - { - MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Make cluster for first PP core group */ - l2_pp_grp0_resource = mali_find_resource(MALI_L2, 0x1000); - if (NULL != l2_pp_grp0_resource) - { - _mali_osk_errcode_t ret; - MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n")); - ret = mali_create_cluster(l2_pp_grp0_resource); - if (_MALI_OSK_ERR_OK != ret) - { - return ret; - } - } - else - { - MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Second PP core group is optional, don't fail if we don't find it */ - l2_pp_grp1_resource = mali_find_resource(MALI_L2, 0x11000); - if (NULL != l2_pp_grp1_resource) - { - _mali_osk_errcode_t ret; - MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n")); - ret = mali_create_cluster(l2_pp_grp1_resource); - if (_MALI_OSK_ERR_OK != ret) - { - return ret; - } - } - } - - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_create_group(struct mali_cluster *cluster, - _mali_osk_resource_t *resource_mmu, - _mali_osk_resource_t *resource_gp, - _mali_osk_resource_t *resource_pp) -{ - struct mali_mmu_core *mmu; - struct mali_group *group; - struct mali_pp_core *pp; - - MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description)); - - /* Create the MMU object */ - mmu = mali_mmu_create(resource_mmu); - if (NULL == mmu) - { - MALI_PRINT_ERROR(("Failed to create MMU object\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Create the group object */ - group = mali_group_create(cluster, mmu); - if (NULL == group) - { - MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description)); - mali_mmu_delete(mmu); - return _MALI_OSK_ERR_FAULT; - } - - /* Set pointer back to group in mmu.*/ - mali_mmu_set_group(mmu, group); - - /* Add this group to current cluster */ - mali_cluster_add_group(cluster, group); - - if (NULL != resource_gp) - { - /* Create the GP core object inside this group */ - /* global_gp_core = mali_gp_create(resource_gp, group); */ - if (NULL == mali_gp_create(resource_gp, group)) - { - /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ - MALI_PRINT_ERROR(("Failed to create GP object\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Add GP object to this group */ - MALI_DEBUG_PRINT(3, ("Adding GP %s to group\n", resource_gp->description)); - mali_group_add_gp_core(group, mali_gp_get_global_gp_core()); - } - - if (NULL != resource_pp) - { - /* Create the PP core object inside this group */ - pp = mali_pp_create(resource_pp, group); - - if (NULL == pp) - { - /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */ - MALI_PRINT_ERROR(("Failed to create PP object\n")); - return _MALI_OSK_ERR_FAULT; - } - - /* Add PP object to this group */ - MALI_DEBUG_PRINT(3, ("Adding PP %s to group\n", resource_pp->description)); - mali_group_add_pp_core(group, pp); - } - - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_parse_config_groups(void) -{ - if (_MALI_PRODUCT_ID_MALI200 == global_product_id) - { - _mali_osk_resource_t *resource_gp; - _mali_osk_resource_t *resource_pp; - _mali_osk_resource_t *resource_mmu; - - MALI_DEBUG_ASSERT(1 == mali_cluster_get_glob_num_clusters()); - - resource_gp = mali_find_resource(MALI_GP, 0x02000); - resource_pp = mali_find_resource(MALI_PP, 0x00000); - resource_mmu = mali_find_resource(MMU, 0x03000); - - if (NULL == resource_mmu || NULL == resource_gp || NULL == resource_pp) - { - /* Missing mandatory core(s) */ - return _MALI_OSK_ERR_FAULT; - } - - /*return mali_create_group(global_clusters[0], resource_mmu, resource_gp, resource_pp);*/ - return mali_create_group(mali_cluster_get_global_cluster(0), resource_mmu, resource_gp, resource_pp); - } - else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || - _MALI_PRODUCT_ID_MALI400 == global_product_id || - _MALI_PRODUCT_ID_MALI450 == global_product_id) - { - _mali_osk_errcode_t err; - int cluster_id_gp = 0; - int cluster_id_pp_grp0 = 0; - int cluster_id_pp_grp1 = 0; - int i; - _mali_osk_resource_t *resource_gp; - _mali_osk_resource_t *resource_gp_mmu; - _mali_osk_resource_t *resource_pp[mali_pp_get_max_num_pp_cores()]; - _mali_osk_resource_t *resource_pp_mmu[mali_pp_get_max_num_pp_cores()]; - u32 max_num_pp_cores = mali_pp_get_max_num_pp_cores(); - - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - /* Mali-450 has separate L2s for GP, and PP core group(s) */ - cluster_id_pp_grp0 = 1; - cluster_id_pp_grp1 = 2; - } - - resource_gp = mali_find_resource(MALI_GP, 0x00000); - resource_gp_mmu = mali_find_resource(MMU, 0x03000); - resource_pp[0] = mali_find_resource(MALI_PP, 0x08000); - resource_pp[1] = mali_find_resource(MALI_PP, 0x0A000); - resource_pp[2] = mali_find_resource(MALI_PP, 0x0C000); - resource_pp[3] = mali_find_resource(MALI_PP, 0x0E000); - resource_pp[4] = mali_find_resource(MALI_PP, 0x28000); - resource_pp[5] = mali_find_resource(MALI_PP, 0x2A000); - resource_pp[6] = mali_find_resource(MALI_PP, 0x2C000); - resource_pp[7] = mali_find_resource(MALI_PP, 0x2E000); - resource_pp_mmu[0] = mali_find_resource(MMU, 0x04000); - resource_pp_mmu[1] = mali_find_resource(MMU, 0x05000); - resource_pp_mmu[2] = mali_find_resource(MMU, 0x06000); - resource_pp_mmu[3] = mali_find_resource(MMU, 0x07000); - resource_pp_mmu[4] = mali_find_resource(MMU, 0x1C000); - resource_pp_mmu[5] = mali_find_resource(MMU, 0x1D000); - resource_pp_mmu[6] = mali_find_resource(MMU, 0x1E000); - resource_pp_mmu[7] = mali_find_resource(MMU, 0x1F000); - - if (NULL == resource_gp || NULL == resource_gp_mmu || NULL == resource_pp[0] || NULL == resource_pp_mmu[0]) - { - /* Missing mandatory core(s) */ - MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU (0x%08X, 0x%08X, 0x%08X, 0x%08X)\n", - resource_gp, resource_gp_mmu, resource_pp[0], resource_pp_mmu[0])); - return _MALI_OSK_ERR_FAULT; - } - - MALI_DEBUG_ASSERT(1 <= mali_cluster_get_glob_num_clusters()); - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_gp), resource_gp_mmu, resource_gp, NULL); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - - /* Create group for first (and mandatory) PP core */ - MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */ - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[0], NULL, resource_pp[0]); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - - /* Create groups for rest of the cores in the first PP core group */ - for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */ - { - if (NULL != resource_pp[i]) - { - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[i], NULL, resource_pp[i]); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - } - } - - /* Create groups for cores in the second PP core group */ - for (i = 4; i < max_num_pp_cores; i++) /* Second half of the PP cores belong to second core group */ - { - if (NULL != resource_pp[i]) - { - MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= 2); /* Only Mali-450 have more than 4 PPs, and these cores belong to second core group */ - err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp1), resource_pp_mmu[i], NULL, resource_pp[i]); - if (err != _MALI_OSK_ERR_OK) - { - return err; - } - } - } - } - - return _MALI_OSK_ERR_OK; -} - -static _mali_osk_errcode_t mali_parse_config_pmu(void) -{ - _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; - _mali_osk_resource_t *resource_pmu; - u32 number_of_pp_cores; - u32 number_of_l2_caches; - - resource_pmu = mali_find_resource(PMU, 0x02000); - number_of_pp_cores = mali_count_resources(MALI_PP); - number_of_l2_caches = mali_count_resources(MALI_L2); - - if (NULL != resource_pmu) - { - if (NULL == mali_pmu_create(resource_pmu, number_of_pp_cores, number_of_l2_caches)) - { - err = _MALI_OSK_ERR_FAULT; - } - } - return err; -} - -static _mali_osk_errcode_t mali_parse_config_memory(void) -{ - int i; - _mali_osk_errcode_t ret; - - for(i = 0; i < num_resources; i++) - { - switch(arch_configuration[i].type) - { - case OS_MEMORY: - ret = mali_memory_core_resource_os_memory(&arch_configuration[i]); - if (_MALI_OSK_ERR_OK != ret) - { - MALI_PRINT_ERROR(("Failed to register OS_MEMORY\n")); - mali_memory_terminate(); - return ret; - } - break; - case MEMORY: - ret = mali_memory_core_resource_dedicated_memory(&arch_configuration[i]); - if (_MALI_OSK_ERR_OK != ret) - { - MALI_PRINT_ERROR(("Failed to register MEMORY\n")); - mali_memory_terminate(); - return ret; - } - break; - case MEM_VALIDATION: - ret = mali_mem_validation_add_range(&arch_configuration[i]); - if (_MALI_OSK_ERR_OK != ret) - { - MALI_PRINT_ERROR(("Failed to register MEM_VALIDATION\n")); - mali_memory_terminate(); - return ret; - } - break; - default: - break; - } - } - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_initialize_subsystems(void) -{ - _mali_osk_errcode_t err; - mali_bool is_pmu_enabled; - - err = mali_session_initialize(); - if (_MALI_OSK_ERR_OK != err) goto session_init_failed; - -#if MALI_TIMELINE_PROFILING_ENABLED - err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); - if (_MALI_OSK_ERR_OK != err) - { - /* No biggie if we wheren't able to initialize the profiling */ - MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); - } -#endif - - /* Get data from config.h */ - err = _mali_osk_resources_init(&arch_configuration, &num_resources); - if (_MALI_OSK_ERR_OK != err) goto osk_resources_init_failed; - - /* Initialize driver subsystems */ - err = mali_memory_initialize(); - if (_MALI_OSK_ERR_OK != err) goto memory_init_failed; - - /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */ - err = mali_parse_config_memory(); - if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed; - - /* Parsing the GPU base address and first pp offset */ - err = mali_parse_gpu_base_and_first_pp_offset_address(); - if (_MALI_OSK_ERR_OK != err) goto parse_gpu_base_address_failed; - - /* Initialize the MALI PMU */ - err = mali_parse_config_pmu(); - if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed; - - is_pmu_enabled = mali_pmu_get_global_pmu_core() != NULL ? MALI_TRUE : MALI_FALSE; - - /* Initialize the power management module */ - err = mali_pm_initialize(); - if (_MALI_OSK_ERR_OK != err) goto pm_init_failed; - - /* Make sure the power stays on for the rest of this function */ - mali_pm_always_on(MALI_TRUE); - - /* Detect which Mali GPU we are dealing with */ - err = mali_parse_product_info(); - if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed; - - /* The global_product_id is now populated with the correct Mali GPU */ - - /* Initialize MMU module */ - err = mali_mmu_initialize(); - if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed; - - /* Initialize the DLBU module for Mali-450 */ - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - err = mali_dlbu_initialize(); - if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed; - } - - /* Start configuring the actual Mali hardware. */ - err = mali_parse_config_cluster(); - if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; - err = mali_parse_config_groups(); - if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed; - - /* Initialize the schedulers */ - err = mali_scheduler_initialize(); - if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed; - err = mali_gp_scheduler_initialize(); - if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed; - err = mali_pp_scheduler_initialize(); - if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed; - -#ifdef CONFIG_MALI400_GPU_UTILIZATION - /* Initialize the GPU utilization tracking */ - err = mali_utilization_init(); - if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed; -#endif - - /* We no longer need to stay */ - mali_pm_always_on(MALI_FALSE); - MALI_SUCCESS; /* all ok */ - - /* Error handling */ -#ifdef CONFIG_MALI400_GPU_UTILIZATION -utilization_init_failed: - mali_pp_scheduler_terminate(); -#endif -pp_scheduler_init_failed: - mali_gp_scheduler_terminate(); -gp_scheduler_init_failed: - mali_scheduler_terminate(); -scheduler_init_failed: -config_parsing_failed: - mali_delete_clusters(); /* Delete clusters even if config parsing failed. */ - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - mali_dlbu_terminate(); - } -dlbu_init_failed: - mali_mmu_terminate(); -mmu_init_failed: - /* Nothing to roll back */ -product_info_parsing_failed: - mali_pm_terminate(); -pm_init_failed: - if (is_pmu_enabled) - { - mali_pmu_delete(mali_pmu_get_global_pmu_core()); - } -parse_pmu_config_failed: -parse_gpu_base_address_failed: -parse_memory_config_failed: - mali_memory_terminate(); -memory_init_failed: - _mali_osk_resources_term(&arch_configuration, num_resources); -osk_resources_init_failed: -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_term(); -#endif - mali_session_terminate(); -session_init_failed: - return err; -} - -void mali_terminate_subsystems(void) -{ - struct mali_pmu_core *pmu; - - MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n")); - - /* shut down subsystems in reverse order from startup */ - - mali_pm_always_on(MALI_TRUE); /* Mali will be powered off once PM subsystem terminates */ - -#ifdef CONFIG_MALI400_GPU_UTILIZATION - mali_utilization_term(); -#endif - - mali_pp_scheduler_terminate(); - mali_gp_scheduler_terminate(); - mali_scheduler_terminate(); - - mali_delete_clusters(); /* Delete clusters even if config parsing failed. */ - - if (_MALI_PRODUCT_ID_MALI450 == global_product_id) - { - mali_dlbu_terminate(); - } - - mali_mmu_terminate(); - - pmu = mali_pmu_get_global_pmu_core(); - if (NULL != pmu) - { - mali_pmu_delete(pmu); - } - - mali_pm_terminate(); - - mali_memory_terminate(); - - _mali_osk_resources_term(&arch_configuration, num_resources); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_term(); -#endif - - mali_session_terminate(); -} - -_mali_product_id_t mali_kernel_core_get_product_id(void) -{ - return global_product_id; -} - -void mali_kernel_core_wakeup(void) -{ - u32 i; - u32 glob_num_clusters = mali_cluster_get_glob_num_clusters(); - struct mali_cluster *cluster; - - for (i = 0; i < glob_num_clusters; i++) - { - cluster = mali_cluster_get_global_cluster(i); - mali_cluster_reset(cluster); - } -} - -_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args ) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - /* check compatability */ - if ( args->version == _MALI_UK_API_VERSION ) - { - args->compatible = 1; - } - else - { - args->compatible = 0; - } - - args->version = _MALI_UK_API_VERSION; /* report our version */ - - /* success regardless of being compatible or not */ - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ) -{ - _mali_osk_errcode_t err; - _mali_osk_notification_t *notification; - _mali_osk_notification_queue_t *queue; - - /* check input */ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; - - /* if the queue does not exist we're currently shutting down */ - if (NULL == queue) - { - MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); - args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS; - MALI_SUCCESS; - } - - /* receive a notification, might sleep */ - err = _mali_osk_notification_queue_receive(queue, ¬ification); - if (_MALI_OSK_ERR_OK != err) - { - MALI_ERROR(err); /* errcode returned, pass on to caller */ - } - - /* copy the buffer to the user */ - args->type = (_mali_uk_notification_type)notification->notification_type; - _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size); - - /* finished with the notification */ - _mali_osk_notification_delete( notification ); - - MALI_SUCCESS; /* all ok */ -} - -_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args ) -{ - _mali_osk_notification_t * notification; - _mali_osk_notification_queue_t *queue; - - /* check input */ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); - - queue = ((struct mali_session_data *)args->ctx)->ioctl_queue; - - /* if the queue does not exist we're currently shutting down */ - if (NULL == queue) - { - MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); - MALI_SUCCESS; - } - - notification = _mali_osk_notification_create(args->type, 0); - if ( NULL == notification) - { - MALI_PRINT_ERROR( ("Failed to create notification object\n")); - return _MALI_OSK_ERR_NOMEM; - } - - _mali_osk_notification_queue_send(queue, notification); - - MALI_SUCCESS; /* all ok */ -} - -_mali_osk_errcode_t _mali_ukk_open(void **context) -{ - struct mali_session_data *session_data; - - /* allocated struct to track this session */ - session_data = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data)); - MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM); - - MALI_DEBUG_PRINT(2, ("Session starting\n")); - - /* create a response queue for this session */ - session_data->ioctl_queue = _mali_osk_notification_queue_init(); - if (NULL == session_data->ioctl_queue) - { - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - session_data->page_directory = mali_mmu_pagedir_alloc(); - if (NULL == session_data->page_directory) - { - _mali_osk_notification_queue_term(session_data->ioctl_queue); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session_data->page_directory, MALI_DLB_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) - { - MALI_PRINT_ERROR(("Failed to map DLB page into session\n")); - _mali_osk_notification_queue_term(session_data->ioctl_queue); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - if (0 != mali_dlbu_phys_addr) - { - mali_mmu_pagedir_update(session_data->page_directory, MALI_DLB_VIRT_ADDR, mali_dlbu_phys_addr, _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD); - } - - if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session_data)) - { - mali_mmu_pagedir_free(session_data->page_directory); - _mali_osk_notification_queue_term(session_data->ioctl_queue); - _mali_osk_free(session_data); - MALI_ERROR(_MALI_OSK_ERR_NOMEM); - } - - *context = (void*)session_data; - - /* Add session to the list of all sessions. */ - mali_session_add(session_data); - - MALI_DEBUG_PRINT(3, ("Session started\n")); - MALI_SUCCESS; -} - -_mali_osk_errcode_t _mali_ukk_close(void **context) -{ - struct mali_session_data *session; - MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS); - session = (struct mali_session_data *)*context; - - MALI_DEBUG_PRINT(3, ("Session ending\n")); - - /* Remove session from list of all sessions. */ - mali_session_remove(session); - - /* Abort queued and running jobs */ - mali_gp_scheduler_abort_session(session); - mali_pp_scheduler_abort_session(session); - - /* Flush pending work. - * Needed to make sure all bottom half processing related to this - * session has been completed, before we free internal data structures. - */ - _mali_osk_flush_workqueue(NULL); - - /* Free remaining memory allocated to this session */ - mali_memory_session_end(session); - - /* Free session data structures */ - mali_mmu_pagedir_free(session->page_directory); - _mali_osk_notification_queue_term(session->ioctl_queue); - _mali_osk_free(session); - - *context = NULL; - - MALI_DEBUG_PRINT(2, ("Session has ended\n")); - - MALI_SUCCESS; -} - -#if MALI_STATE_TRACKING -u32 _mali_kernel_core_dump_state(char* buf, u32 size) -{ - int n = 0; /* Number of bytes written to buf */ - - n += mali_gp_scheduler_dump_state(buf + n, size - n); - n += mali_pp_scheduler_dump_state(buf + n, size - n); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c deleted file mode 100644 index a374dbf..0000000 --- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 "mali_kernel_utilization.h" -#include "mali_osk.h" -#include "mali_platform.h" - -/* Define how often to calculate and report GPU utilization, in milliseconds */ -#define MALI_GPU_UTILIZATION_TIMEOUT 1000 - -static _mali_osk_lock_t *time_data_lock; - -static _mali_osk_atomic_t num_running_cores; - -static u64 period_start_time = 0; -static u64 work_start_time = 0; -static u64 accumulated_work_time = 0; - -static _mali_osk_timer_t *utilization_timer = NULL; -static mali_bool timer_running = MALI_FALSE; - - -static void calculate_gpu_utilization(void* arg) -{ - u64 time_now; - u64 time_period; - u32 leading_zeroes; - u32 shift_val; - u32 work_normalized; - u32 period_normalized; - u32 utilization; - - _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - if (accumulated_work_time == 0 && work_start_time == 0) - { - /* Don't reschedule timer, this will be started if new work arrives */ - timer_running = MALI_FALSE; - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - /* No work done for this period, report zero usage */ - mali_gpu_utilization_handler(0); - - return; - } - - time_now = _mali_osk_time_get_ns(); - time_period = time_now - period_start_time; - - /* If we are currently busy, update working period up to now */ - if (work_start_time != 0) - { - accumulated_work_time += (time_now - work_start_time); - work_start_time = time_now; - } - - /* - * We have two 64-bit values, a dividend and a divisor. - * To avoid dependencies to a 64-bit divider, we shift down the two values - * equally first. - * We shift the dividend up and possibly the divisor down, making the result X in 256. - */ - - /* Shift the 64-bit values down so they fit inside a 32-bit integer */ - leading_zeroes = _mali_osk_clz((u32)(time_period >> 32)); - shift_val = 32 - leading_zeroes; - work_normalized = (u32)(accumulated_work_time >> shift_val); - period_normalized = (u32)(time_period >> shift_val); - - /* - * Now, we should report the usage in parts of 256 - * this means we must shift up the dividend or down the divisor by 8 - * (we could do a combination, but we just use one for simplicity, - * but the end result should be good enough anyway) - */ - if (period_normalized > 0x00FFFFFF) - { - /* The divisor is so big that it is safe to shift it down */ - period_normalized >>= 8; - } - else - { - /* - * The divisor is so small that we can shift up the dividend, without loosing any data. - * (dividend is always smaller than the divisor) - */ - work_normalized <<= 8; - } - - utilization = work_normalized / period_normalized; - - accumulated_work_time = 0; - period_start_time = time_now; /* starting a new period */ - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT)); - - - mali_gpu_utilization_handler(utilization); -} - -_mali_osk_errcode_t mali_utilization_init(void) -{ - time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | - _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION); - - if (NULL == time_data_lock) - { - return _MALI_OSK_ERR_FAULT; - } - - _mali_osk_atomic_init(&num_running_cores, 0); - - utilization_timer = _mali_osk_timer_init(); - if (NULL == utilization_timer) - { - _mali_osk_lock_term(time_data_lock); - return _MALI_OSK_ERR_FAULT; - } - _mali_osk_timer_setcallback(utilization_timer, calculate_gpu_utilization, NULL); - - return _MALI_OSK_ERR_OK; -} - -void mali_utilization_suspend(void) -{ - if (NULL != utilization_timer) - { - _mali_osk_timer_del(utilization_timer); - timer_running = MALI_FALSE; - } -} - -void mali_utilization_term(void) -{ - if (NULL != utilization_timer) - { - _mali_osk_timer_del(utilization_timer); - timer_running = MALI_FALSE; - _mali_osk_timer_term(utilization_timer); - utilization_timer = NULL; - } - - _mali_osk_atomic_term(&num_running_cores); - - _mali_osk_lock_term(time_data_lock); -} - -void mali_utilization_core_start(u64 time_now) -{ - if (_mali_osk_atomic_inc_return(&num_running_cores) == 1) - { - /* - * We went from zero cores working, to one core working, - * we now consider the entire GPU for being busy - */ - - _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - if (time_now < period_start_time) - { - /* - * This might happen if the calculate_gpu_utilization() was able - * to run between the sampling of time_now and us grabbing the lock above - */ - time_now = period_start_time; - } - - work_start_time = time_now; - if (timer_running != MALI_TRUE) - { - timer_running = MALI_TRUE; - period_start_time = work_start_time; /* starting a new period */ - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT)); - } - else - { - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - } - } -} - -void mali_utilization_core_end(u64 time_now) -{ - if (_mali_osk_atomic_dec_return(&num_running_cores) == 0) - { - /* - * No more cores are working, so accumulate the time we was busy. - */ - _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - - if (time_now < work_start_time) - { - /* - * This might happen if the calculate_gpu_utilization() was able - * to run between the sampling of time_now and us grabbing the lock above - */ - time_now = work_start_time; - } - - accumulated_work_time += (time_now - work_start_time); - work_start_time = 0; - - _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); - } -} diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.h b/drivers/media/video/samsung/mali/common/mali_mmu.h deleted file mode 100644 index c7274b8..0000000 --- a/drivers/media/video/samsung/mali/common/mali_mmu.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_MMU_H__ -#define __MALI_MMU_H__ - -#include "mali_osk.h" -#include "mali_mmu_page_directory.h" - -/* Forward declaration from mali_group.h */ -struct mali_group; - -struct mali_mmu_core; - -_mali_osk_errcode_t mali_mmu_initialize(void); - -void mali_mmu_terminate(void); - -struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource); -void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group); -void mali_mmu_delete(struct mali_mmu_core *mmu); - -_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu); -mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu); -void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu); -void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address); - -mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir); -void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu); -void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu); - -/** - * Issues the enable stall command to the MMU and waits for HW to complete the request - * @param mmu The MMU to enable paging for - * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out) - */ -mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu); - -/** - * Issues the disable stall command to the MMU and waits for HW to complete the request - * @param mmu The MMU to enable paging for - */ -void mali_mmu_disable_stall(struct mali_mmu_core *mmu); - -void mali_mmu_page_fault_done(struct mali_mmu_core *mmu); - - -#endif /* __MALI_MMU_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pm.c b/drivers/media/video/samsung/mali/common/mali_pm.c deleted file mode 100644 index 933e54e..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pm.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_pm.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_gp_scheduler.h" -#include "mali_pp_scheduler.h" -#include "mali_platform.h" -#include "mali_kernel_utilization.h" -#include "mali_kernel_core.h" -#include "mali_group.h" - -#define MALI_PM_LIGHT_SLEEP_TIMEOUT 1000 - -enum mali_pm_scheme -{ - MALI_PM_SCHEME_DYNAMIC, - MALI_PM_SCHEME_OS_SUSPENDED, - MALI_PM_SCHEME_ALWAYS_ON -}; - -enum mali_pm_level -{ - MALI_PM_LEVEL_1_ON, - MALI_PM_LEVEL_2_STANDBY, - MALI_PM_LEVEL_3_LIGHT_SLEEP, - MALI_PM_LEVEL_4_DEEP_SLEEP -}; -static _mali_osk_lock_t *mali_pm_lock_set_next_state; -static _mali_osk_lock_t *mali_pm_lock_set_core_states; -static _mali_osk_lock_t *mali_pm_lock_execute_state_change; -static _mali_osk_irq_t *wq_irq; - -static _mali_osk_timer_t *idle_timer = NULL; -static mali_bool idle_timer_running = MALI_FALSE; -static u32 mali_pm_event_number = 0; - -static u32 num_active_gps = 0; -static u32 num_active_pps = 0; - -static enum mali_pm_scheme current_scheme = MALI_PM_SCHEME_DYNAMIC; -static enum mali_pm_level current_level = MALI_PM_LEVEL_1_ON; -static enum mali_pm_level next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; /* Should be the state we go to when we go out of MALI_PM_SCHEME_ALWAYS_ON during init */ - - - -static _mali_osk_errcode_t mali_pm_upper_half(void *data); -static void mali_pm_bottom_half(void *data); -static void mali_pm_powerup(void); -static void mali_pm_powerdown(mali_power_mode power_mode); - -static void timeout_light_sleep(void* arg); -#if 0 -/* Deep sleep timout not supported */ -static void timeout_deep_sleep(void* arg); -#endif -static u32 mali_pm_event_number_get(void); -static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time ); - -_mali_osk_errcode_t mali_pm_initialize(void) -{ - mali_pm_lock_execute_state_change = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_EXECUTE); - - if (NULL != mali_pm_lock_execute_state_change ) - { - mali_pm_lock_set_next_state = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ONELOCK| _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_LAST); - - if (NULL != mali_pm_lock_set_next_state) - { - mali_pm_lock_set_core_states = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_CORE_STATE); - - if (NULL != mali_pm_lock_set_core_states) - { - idle_timer = _mali_osk_timer_init(); - if (NULL != idle_timer) - { - wq_irq = _mali_osk_irq_init(_MALI_OSK_IRQ_NUMBER_PMM, - mali_pm_upper_half, - mali_pm_bottom_half, - NULL, - NULL, - (void *)NULL, - "Mali PM deferred work"); - if (NULL != wq_irq) - { - if (_MALI_OSK_ERR_OK == mali_platform_init()) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - _mali_osk_pm_dev_enable(); - mali_pm_powerup(); -#endif - return _MALI_OSK_ERR_OK; - } - - _mali_osk_irq_term(wq_irq); - } - - _mali_osk_timer_del(idle_timer); - _mali_osk_timer_term(idle_timer); - } - _mali_osk_lock_term(mali_pm_lock_set_core_states); - } - _mali_osk_lock_term(mali_pm_lock_set_next_state); - } - _mali_osk_lock_term(mali_pm_lock_execute_state_change); - } - - return _MALI_OSK_ERR_FAULT; -} - -void mali_pm_terminate(void) -{ - mali_platform_deinit(); - _mali_osk_irq_term(wq_irq); - _mali_osk_timer_del(idle_timer); - _mali_osk_timer_term(idle_timer); - _mali_osk_lock_term(mali_pm_lock_execute_state_change); - _mali_osk_lock_term(mali_pm_lock_set_next_state); - _mali_osk_lock_term(mali_pm_lock_set_core_states); -} - - -inline void mali_pm_lock(void) -{ - _mali_osk_lock_wait(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW); -} - -inline void mali_pm_unlock(void) -{ - _mali_osk_lock_signal(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW); -} - -inline void mali_pm_execute_state_change_lock(void) -{ - _mali_osk_lock_wait(mali_pm_lock_execute_state_change,_MALI_OSK_LOCKMODE_RW); -} - -inline void mali_pm_execute_state_change_unlock(void) -{ - _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); -} - -static void mali_pm_powerup(void) -{ -#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_ON); -#else - /* Aquire our reference */ - _mali_osk_pm_dev_activate(); -#endif - mali_group_power_on(); -} - -static void mali_pm_powerdown(mali_power_mode power_mode) -{ - if ( (MALI_PM_LEVEL_1_ON == current_level) || (MALI_PM_LEVEL_2_STANDBY == current_level) ) - { - mali_group_power_off(); - } - -#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON - mali_platform_power_mode_change(power_mode); -#else - _mali_osk_pm_dev_idle(); - - if (MALI_POWER_MODE_DEEP_SLEEP == power_mode) - { - mali_platform_power_mode_change(power_mode); - } -#endif -} - -mali_bool mali_pm_is_powered_on(void) -{ - mali_bool is_on = MALI_TRUE; - - if( ! (MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme) ) - { - is_on = MALI_FALSE; - } - else if ( ! (MALI_PM_LEVEL_1_ON == current_level || MALI_PM_LEVEL_2_STANDBY == current_level)) - { - is_on = MALI_FALSE; - } - else if ( ! (MALI_PM_LEVEL_1_ON == next_level_dynamic || MALI_PM_LEVEL_2_STANDBY == next_level_dynamic)) - { - is_on = MALI_FALSE; - } - - return is_on; -} - -MALI_DEBUG_CODE( -static const char *state_as_string(enum mali_pm_level level) -{ - switch(level) - { - case MALI_PM_LEVEL_1_ON: - return "MALI_PM_LEVEL_1_ON"; - case MALI_PM_LEVEL_2_STANDBY: - return "MALI_PM_LEVEL_2_STANDBY"; - case MALI_PM_LEVEL_3_LIGHT_SLEEP: - return "MALI_PM_LEVEL_3_LIGHT_SLEEP"; - case MALI_PM_LEVEL_4_DEEP_SLEEP: - return "MALI_PM_LEVEL_4_DEEP_SLEEP"; - default: - return "UNKNOWN LEVEL"; - } -}); - -/* This could be used from another thread (work queue), if we need that */ -static void mali_pm_process_next(void) -{ - enum mali_pm_level pm_level_to_set; - - _mali_osk_lock_wait(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); - - pm_level_to_set = current_level; - - if (MALI_PM_SCHEME_DYNAMIC == current_scheme) - { - pm_level_to_set = next_level_dynamic; - - MALI_DEBUG_PRINT(4, ("Mali PM: Dynamic scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(pm_level_to_set))); - - if (current_level == pm_level_to_set) - { - goto end_function; /* early out, no change in power level */ - } - - /* Start timers according to new state, so we get STANDBY -> LIGHT_SLEEP -> DEEP_SLEEP */ - - if (MALI_TRUE == idle_timer_running) - { - /* There is an existing timeout, so delete it */ - _mali_osk_timer_del(idle_timer); - idle_timer_running = MALI_FALSE; - } - - /* Making sure that we turn on through the platform file - Since it was turned OFF directly through the platform file. - This might lead to double turn-on, but the plaform file supports that.*/ - if ( current_level == MALI_PM_LEVEL_4_DEEP_SLEEP) - { - mali_pm_powerup(); - mali_kernel_core_wakeup(); - - } - if (MALI_PM_LEVEL_1_ON == pm_level_to_set) - { - if (MALI_PM_LEVEL_2_STANDBY != current_level) - { - /* We only need to do anything if we came from one of the sleeping states */ - mali_pm_powerup(); - - /* Wake up Mali cores since we came from a sleep state */ - mali_kernel_core_wakeup(); - } - } - else if (MALI_PM_LEVEL_2_STANDBY == pm_level_to_set) - { - /* This is just an internal state, so we don't bother to report it to the platform file */ - idle_timer_running = MALI_TRUE; - _mali_osk_timer_setcallback(idle_timer, timeout_light_sleep, (void*) mali_pm_event_number_get()); - _mali_osk_timer_add(idle_timer, _mali_osk_time_mstoticks(MALI_PM_LIGHT_SLEEP_TIMEOUT)); - } - else if (MALI_PM_LEVEL_3_LIGHT_SLEEP == pm_level_to_set) - { - mali_pm_powerdown(MALI_POWER_MODE_LIGHT_SLEEP); - } - else if (MALI_PM_LEVEL_4_DEEP_SLEEP == pm_level_to_set) - { - MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n")); - mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP); - } - } - else if (MALI_PM_SCHEME_OS_SUSPENDED == current_scheme) - { - MALI_DEBUG_PRINT(4, ("Mali PM: OS scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_4_DEEP_SLEEP))); - - pm_level_to_set = MALI_PM_LEVEL_4_DEEP_SLEEP; - - if (current_level == pm_level_to_set) - { - goto end_function; /* early out, no change in power level */ - } - - /* Cancel any timers */ - if (MALI_TRUE == idle_timer_running) - { - /* There is an existing timeout, so delete it */ - _mali_osk_timer_del(idle_timer); - idle_timer_running = MALI_FALSE; - } - - MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n")); - mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP); - next_level_dynamic = current_level; - } - else if (MALI_PM_SCHEME_ALWAYS_ON == current_scheme) - { - MALI_DEBUG_PRINT(4, ("Mali PM: Always on scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_1_ON))); - - pm_level_to_set = MALI_PM_LEVEL_1_ON; - if (current_level == pm_level_to_set) - { - goto end_function; /* early out, no change in power level */ - } - - MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n")); - mali_pm_powerup(); - if (MALI_PM_LEVEL_2_STANDBY != current_level) - { - /* Wake up Mali cores since we came from a sleep state */ - mali_kernel_core_wakeup(); - } - } - else - { - MALI_PRINT_ERROR(("MALI PM: Illegal scheme")); - } - - current_level = pm_level_to_set; - -end_function: - _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW); - -} - -void mali_pm_always_on(mali_bool enable) -{ - if (MALI_TRUE == enable) - { - /* The event is processed in current thread synchronously */ - mali_pm_event(MALI_PM_EVENT_SCHEME_ALWAYS_ON, MALI_FALSE, 0 ); - } - else - { - /* The event is processed in current thread synchronously */ - mali_pm_event(MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, MALI_FALSE, 0 ); - } -} - -static _mali_osk_errcode_t mali_pm_upper_half(void *data) -{ - /* not used */ - return _MALI_OSK_ERR_OK; -} - -static void mali_pm_bottom_half(void *data) -{ - mali_pm_process_next(); -} - -static u32 mali_pm_event_number_get(void) -{ - u32 retval; - - mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */ - retval = ++mali_pm_event_number; - if (0==retval ) retval = ++mali_pm_event_number; - mali_pm_unlock(); - - return retval; -} - -static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time ) -{ - mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */ - /* Only timer events should set this variable, all other events must set it to zero. */ - if ( 0 != timer_time ) - { - MALI_DEBUG_ASSERT( (pm_event==MALI_PM_EVENT_TIMER_LIGHT_SLEEP) || (pm_event==MALI_PM_EVENT_TIMER_DEEP_SLEEP) ); - if ( mali_pm_event_number != timer_time ) - { - /* In this case there have been processed newer events since the timer event was set up. - If so we always ignore the timing event */ - mali_pm_unlock(); - return; - } - } - else - { - /* Delete possible ongoing timers - if ( (MALI_PM_LEVEL_2_STANDBY==current_level) || (MALI_PM_LEVEL_3_LIGHT_SLEEP==current_level) ) - { - _mali_osk_timer_del(idle_timer); - } - */ - } - mali_pm_event_number++; - switch (pm_event) - { - case MALI_PM_EVENT_CORES_WORKING: - next_level_dynamic = MALI_PM_LEVEL_1_ON; - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - break; - case MALI_PM_EVENT_CORES_IDLE: - next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; - /*MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );*/ - break; - case MALI_PM_EVENT_TIMER_LIGHT_SLEEP: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - next_level_dynamic = MALI_PM_LEVEL_3_LIGHT_SLEEP; - break; - case MALI_PM_EVENT_TIMER_DEEP_SLEEP: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; - break; - case MALI_PM_EVENT_OS_SUSPEND: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme ); - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - current_scheme = MALI_PM_SCHEME_OS_SUSPENDED; - next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; /* Dynamic scheme will go into level when we are resumed */ - break; - case MALI_PM_EVENT_OS_RESUME: - MALI_DEBUG_ASSERT(MALI_PM_SCHEME_OS_SUSPENDED == current_scheme ); - current_scheme = MALI_PM_SCHEME_DYNAMIC; - break; - case MALI_PM_EVENT_SCHEME_ALWAYS_ON: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme ); - current_scheme = MALI_PM_SCHEME_ALWAYS_ON; - break; - case MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL: - MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme ); - current_scheme = MALI_PM_SCHEME_DYNAMIC; - break; - default: - MALI_DEBUG_PRINT_ERROR(("Unknown next state.")); - mali_pm_unlock(); - return; - } - mali_pm_unlock(); - - if (MALI_TRUE == schedule_work) - { - _mali_osk_irq_schedulework(wq_irq); - } - else - { - mali_pm_process_next(); - } -} - -static void timeout_light_sleep(void* arg) -{ - /* State change only if no newer power events have happend from the time in arg. - Actual work will be scheduled on worker thread. */ - mali_pm_event(MALI_PM_EVENT_TIMER_LIGHT_SLEEP, MALI_TRUE, (u32) arg); -} - -void mali_pm_core_event(enum mali_core_event core_event) -{ - mali_bool transition_working = MALI_FALSE; - mali_bool transition_idle = MALI_FALSE; - - _mali_osk_lock_wait(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW); - - switch (core_event) - { - case MALI_CORE_EVENT_GP_START: - if (num_active_pps + num_active_gps == 0) - { - transition_working = MALI_TRUE; - } - num_active_gps++; - break; - case MALI_CORE_EVENT_GP_STOP: - if (num_active_pps + num_active_gps == 1) - { - transition_idle = MALI_TRUE; - } - num_active_gps--; - break; - case MALI_CORE_EVENT_PP_START: - if (num_active_pps + num_active_gps == 0) - { - transition_working = MALI_TRUE; - } - num_active_pps++; - break; - case MALI_CORE_EVENT_PP_STOP: - if (num_active_pps + num_active_gps == 1) - { - transition_idle = MALI_TRUE; - } - num_active_pps--; - break; - } - - if (transition_working == MALI_TRUE) - { -#ifdef CONFIG_MALI400_GPU_UTILIZATION - mali_utilization_core_start(_mali_osk_time_get_ns()); -#endif - mali_pm_event(MALI_PM_EVENT_CORES_WORKING, MALI_FALSE, 0); /* process event in same thread */ - } - else if (transition_idle == MALI_TRUE) - { -#ifdef CONFIG_MALI400_GPU_UTILIZATION - mali_utilization_core_end(_mali_osk_time_get_ns()); -#endif - mali_pm_event(MALI_PM_EVENT_CORES_IDLE, MALI_FALSE, 0); /* process event in same thread */ - } - - _mali_osk_lock_signal(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW); -} - -void mali_pm_os_suspend(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS suspending...\n")); - - mali_gp_scheduler_suspend(); - mali_pp_scheduler_suspend(); - mali_pm_event(MALI_PM_EVENT_OS_SUSPEND, MALI_FALSE, 0); /* process event in same thread */ - - MALI_DEBUG_PRINT(2, ("Mali PM: OS suspend completed\n")); -} - -void mali_pm_os_resume(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS resuming...\n")); - - mali_pm_event(MALI_PM_EVENT_OS_RESUME, MALI_FALSE, 0); /* process event in same thread */ - mali_gp_scheduler_resume(); - mali_pp_scheduler_resume(); - - MALI_DEBUG_PRINT(2, ("Mali PM: OS resume completed\n")); -} - -void mali_pm_runtime_suspend(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime suspended\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP); -} - -void mali_pm_runtime_resume(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime resumed\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_ON); -} diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.c b/drivers/media/video/samsung/mali/common/mali_pmu.c deleted file mode 100644 index 348b5dc..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pmu.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_pmu.c - * Mali driver functions for Mali 400 PMU hardware - */ -#include "mali_hw_core.h" -#include "mali_pmu.h" -#include "mali_pp.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" - -static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches); - -/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask - */ -struct mali_pmu_core -{ - struct mali_hw_core hw_core; - u32 mali_registered_cores_power_mask; -}; - -static struct mali_pmu_core *mali_global_pmu_core = NULL; - -/** @brief Register layout for hardware PMU - */ -typedef enum { - PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */ - PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */ - PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */ - PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */ - PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x10, /*< Size of register space */ -} pmu_reg_addr_mgmt_addr; - -struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches) -{ - struct mali_pmu_core* pmu; - - MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core); - MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n")); - - pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core)); - if (NULL != pmu) - { - pmu->mali_registered_cores_power_mask = mali_pmu_detect_mask(number_of_pp_cores, number_of_l2_caches); - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE)) - { - if (_MALI_OSK_ERR_OK == mali_pmu_reset(pmu)) - { - mali_global_pmu_core = pmu; - return pmu; - } - mali_hw_core_delete(&pmu->hw_core); - } - _mali_osk_free(pmu); - } - - return NULL; -} - -void mali_pmu_delete(struct mali_pmu_core *pmu) -{ - MALI_DEBUG_ASSERT_POINTER(pmu); - - mali_hw_core_delete(&pmu->hw_core); - _mali_osk_free(pmu); - pmu = NULL; -} - -_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu) -{ - /* Don't use interrupts - just poll status */ - mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0); - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu) -{ - u32 stat; - u32 timeout; - - MALI_DEBUG_ASSERT_POINTER(pmu); - MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); - MALI_DEBUG_PRINT( 4, ("Mali PMU: power down (0x%08X)\n", pmu->mali_registered_cores_power_mask) ); - - mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_DOWN, pmu->mali_registered_cores_power_mask); - - /* Wait for cores to be powered down (100 x 100us = 100ms) */ - timeout = 100; - do - { - /* Get status of sleeping cores */ - stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS); - stat &= pmu->mali_registered_cores_power_mask; - if( stat == pmu->mali_registered_cores_power_mask ) break; /* All cores we wanted are now asleep */ - _mali_osk_time_ubusydelay(100); - timeout--; - } while( timeout > 0 ); - - if( timeout == 0 ) - { - return _MALI_OSK_ERR_TIMEOUT; - } - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu) -{ - u32 stat; - u32 timeout; - - MALI_DEBUG_ASSERT_POINTER(pmu); - MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); /* Shouldn't be zero */ - MALI_DEBUG_PRINT( 4, ("Mali PMU: power up (0x%08X)\n", pmu->mali_registered_cores_power_mask) ); - - mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_UP, pmu->mali_registered_cores_power_mask); - - /* Wait for cores to be powered up (100 x 100us = 100ms) */ - timeout = 100; - do - { - /* Get status of sleeping cores */ - stat = mali_hw_core_register_read(&pmu->hw_core,PMU_REG_ADDR_MGMT_STATUS); - stat &= pmu->mali_registered_cores_power_mask; - if( stat == 0 ) break; /* All cores we wanted are now awake */ - _mali_osk_time_ubusydelay(100); - timeout--; - } while( timeout > 0 ); - - if( timeout == 0 ) - { - return _MALI_OSK_ERR_TIMEOUT; - } - - return _MALI_OSK_ERR_OK; -} - -struct mali_pmu_core *mali_pmu_get_global_pmu_core(void) -{ - return mali_global_pmu_core; -} - -static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches) -{ - u32 mask = 0; - - if (number_of_l2_caches == 1) - { - /* Mali-300 or Mali-400 */ - u32 i; - - /* GP */ - mask = 0x01; - - /* L2 cache */ - mask |= 0x01<<1; - - /* Set bit for each PP core */ - for (i = 0; i < number_of_pp_cores; i++) - { - mask |= 0x01<<(i+2); - } - } - else if (number_of_l2_caches > 1) - { - /* Mali-450 */ - - /* GP (including its L2 cache) */ - mask = 0x01; - - /* There is always at least one PP (including its L2 cache) */ - mask |= 0x01<<1; - - /* Additional PP cores in same L2 cache */ - if (number_of_pp_cores >= 2) - { - mask |= 0x01<<2; - } - - /* Additional PP cores in a third L2 cache */ - if (number_of_pp_cores >= 5) - { - mask |= 0x01<<3; - } - } - - MALI_DEBUG_PRINT(4, ("Mali PMU: Power mask is 0x%08X (%u + %u)\n", mask, number_of_pp_cores, number_of_l2_caches)); - - return mask; -} diff --git a/drivers/media/video/samsung/mali/common/mali_pp.c b/drivers/media/video/samsung/mali/common/mali_pp.c deleted file mode 100644 index 5549f82..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_pp.h" -#include "mali_hw_core.h" -#include "mali_group.h" -#include "mali_osk.h" -#include "regs/mali_200_regs.h" -#include "mali_kernel_common.h" -#include "mali_kernel_core.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -#endif - -/* See mali_gp.c file for description on how to handle the interrupt mask. - * This is how to do it on PP: mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - */ - -#define MALI_MAX_NUMBER_OF_PP_CORES 8 - -/** - * Definition of the PP core struct - * Used to track a PP core in the system. - */ -struct mali_pp_core -{ - struct mali_hw_core hw_core; /**< Common for all HW cores */ - struct mali_group *group; /**< Parent group for this core */ - _mali_osk_irq_t *irq; /**< IRQ handler */ - u32 core_id; /**< Unique core ID */ - struct mali_pp_job *running_job; /**< Current running (super) job */ - u32 running_sub_job; /**< Current running sub job */ - _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */ - u32 timeout_job_id; /**< job id for the timed out job - relevant only if pp_core_timed_out == MALI_TRUE */ - mali_bool core_timed_out; /**< if MALI_TRUE, this pp core has timed out; if MALI_FALSE, no timeout on this pp core */ - u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */ - u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */ - u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */ -}; - -static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES]; -static u32 mali_global_num_pp_cores = 0; - -/* Interrupt handlers */ -static _mali_osk_errcode_t mali_pp_upper_half(void *data); -static void mali_pp_bottom_half(void *data); -static void mali_pp_irq_probe_trigger(void *data); -static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data); -static void mali_pp_post_process_job(struct mali_pp_core *core); -static void mali_pp_timeout(void *data); - -struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group) -{ - struct mali_pp_core* core = NULL; - - MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description)); - MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base)); - - if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) - { - MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n")); - return NULL; - } - - core = _mali_osk_malloc(sizeof(struct mali_pp_core)); - if (NULL != core) - { - core->group = group; - core->core_id = mali_global_num_pp_cores; - core->running_job = NULL; - core->counter_src0 = MALI_HW_CORE_NO_COUNTER; - core->counter_src1 = MALI_HW_CORE_NO_COUNTER; - core->counter_src0_used = MALI_HW_CORE_NO_COUNTER; - core->counter_src1_used = MALI_HW_CORE_NO_COUNTER; - if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) - { - _mali_osk_errcode_t ret; - - mali_group_lock(group); - ret = mali_pp_reset(core); - mali_group_unlock(group); - - if (_MALI_OSK_ERR_OK == ret) - { - /* Setup IRQ handlers (which will do IRQ probing if needed) */ - core->irq = _mali_osk_irq_init(resource->irq, - mali_pp_upper_half, - mali_pp_bottom_half, - mali_pp_irq_probe_trigger, - mali_pp_irq_probe_ack, - core, - "mali_pp_irq_handlers"); - if (NULL != core->irq) - { - /* Initialise the timeout timer */ - core->timeout_timer = _mali_osk_timer_init(); - if(NULL != core->timeout_timer) - { - _mali_osk_timer_setcallback(core->timeout_timer, mali_pp_timeout, (void *)core); - - mali_global_pp_cores[mali_global_num_pp_cores] = core; - mali_global_num_pp_cores++; - - return core; - } - else - { - MALI_PRINT_ERROR(("Failed to setup timeout timer for PP core %s\n", core->hw_core.description)); - /* Release IRQ handlers */ - _mali_osk_irq_term(core->irq); - } - } - else - { - MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description)); - } - } - mali_hw_core_delete(&core->hw_core); - } - - _mali_osk_free(core); - } - else - { - MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n")); - } - - return NULL; -} - -void mali_pp_delete(struct mali_pp_core *core) -{ - u32 i; - - MALI_DEBUG_ASSERT_POINTER(core); - - _mali_osk_timer_term(core->timeout_timer); - _mali_osk_irq_term(core->irq); - mali_hw_core_delete(&core->hw_core); - - /* Remove core from global list */ - for (i = 0; i < mali_global_num_pp_cores; i++) - { - if (mali_global_pp_cores[i] == core) - { - mali_global_pp_cores[i] = NULL; - mali_global_num_pp_cores--; - break; - } - } - - _mali_osk_free(core); -} - -void mali_pp_stop_bus(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - /* Will only send the stop bus command, and not wait for it to complete */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); -} - -_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - /* Send the stop bus command. */ - mali_pp_stop_bus(core); - - /* Wait for bus to be stopped */ - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) - break; - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) -{ - /* Bus must be stopped before calling this function */ - const int reset_finished_loop_count = 15; - const u32 reset_invalid_value = 0xC0FFE000; - const u32 reset_check_value = 0xC01A0000; - int i; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ - - /* Set register to a bogus value. The register will be used to detect when reset is complete */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value); - - /* Force core to reset */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET); - - /* Wait for reset to be complete */ - for (i = 0; i < reset_finished_loop_count; i++) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value); - if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (i == reset_finished_loop_count) - { - MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n")); - } - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */ - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core) -{ - int i; - const int request_loop_count = 20; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description)); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ - -#if defined(USING_MALI200) - - /* On Mali-200, stop the bus, then do a hard reset of the core */ - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_PRINT_ERROR(("Mali PP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description)); - return _MALI_OSK_ERR_FAULT ; - } - - /* the bus was stopped OK, do the hard reset */ - mali_pp_hard_reset(core); - -#elif defined(USING_MALI400) - - /* Mali-300 and Mali-400 have a safe reset command which we use */ - - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET); - - for (i = 0; i < request_loop_count; i++) - { - if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) - { - break; - } - _mali_osk_time_ubusydelay(10); - } - - if (request_loop_count == i) - { - MALI_DEBUG_PRINT(2, ("Mali PP: Failed to reset core %s, Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); - return _MALI_OSK_ERR_FAULT; - } -#else -#error "no supported mali core defined" -#endif - - /* Re-enable interrupts */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - - return _MALI_OSK_ERR_OK; -} - -void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job) -{ - u32 *frame_registers = mali_pp_job_get_frame_registers(job); - u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); - u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); - u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); - core->counter_src0_used = core->counter_src0; - core->counter_src1_used = core->counter_src1; - - MALI_DEBUG_ASSERT_POINTER(core); - MALI_ASSERT_GROUP_LOCKED(core->group); - - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME); - if (0 != sub_job) - { - /* - * There are two frame registers which are different for each sub job. - * For the first sub job, these are correctly represented in the frame register array, - * but we need to patch these for all other sub jobs - */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job)); - } - - if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ - { - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx); - } - - if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ - { - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx); - } - - if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ - { - mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx); - } - - /* This selects which performance counters we are reading */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - /* global_config has enabled HW counters, this will override anything specified by user space */ - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - } - else - { - /* Use HW counters from job object, if any */ - u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); - if (0 != perf_counter_flag) - { - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) - { - core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - - if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) - { - core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - } - } - } - - MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); - - /* Adding barrier to make sure all rester writes are finished */ - _mali_osk_write_mem_barrier(); - - /* This is the command that starts the core. */ - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); - - /* Adding barrier to make sure previous rester writes is finished */ - _mali_osk_write_mem_barrier(); - - /* Setup the timeout timer value and save the job id for the job running on the pp core */ - _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); - core->timeout_job_id = mali_pp_job_get_id(job); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0); - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), job->pid, job->tid, 0, 0, 0); -#endif - - core->running_job = job; - core->running_sub_job = sub_job; -} - -u32 mali_pp_core_get_version(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION); -} - -u32 mali_pp_core_get_id(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->core_id; -} - -mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src0 = counter; - return MALI_TRUE; -} - -mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter) -{ - MALI_DEBUG_ASSERT_POINTER(core); - - core->counter_src1 = counter; - return MALI_TRUE; -} - -u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src0; -} - -u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core) -{ - MALI_DEBUG_ASSERT_POINTER(core); - return core->counter_src1; -} - -struct mali_pp_core* mali_pp_get_global_pp_core(u32 index) -{ - if (MALI_MAX_NUMBER_OF_PP_CORES > index) - { - return mali_global_pp_cores[index]; - } - - return NULL; -} - -u32 mali_pp_get_glob_num_pp_cores(void) -{ - return mali_global_num_pp_cores; -} - -u32 mali_pp_get_max_num_pp_cores(void) -{ - return MALI_MAX_NUMBER_OF_PP_CORES; -} - -/* ------------- interrupt handling below ------------------ */ -static _mali_osk_errcode_t mali_pp_upper_half(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); - if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) - { - /* Mask out all IRQs from this core until IRQ is handled */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); -#endif - - /* We do need to handle this in a bottom half */ - _mali_osk_irq_schedulework(core->irq); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - -static void mali_pp_bottom_half(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - u32 irq_readout; - u32 irq_errors; - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); -#endif -#endif - - mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ - - if ( MALI_FALSE == mali_group_power_is_on(core->group) ) - { - MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); - mali_group_unlock(core->group); - return; - } - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; - - MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description)); - - if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME) - { - mali_pp_post_process_job(core); - MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); - mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */ - return; - } - - /* - * Now lets look at the possible error cases (IRQ indicating error or timeout) - * END_OF_FRAME and HANG interrupts are not considered error. - */ - irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG); - if (0 != irq_errors) - { - mali_pp_post_process_job(core); - MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n", - irq_readout, core->hw_core.description)); - mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */ - return; - } - else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ - { - if (core->timeout_job_id == mali_pp_job_get_id(core->running_job)) - { - mali_pp_post_process_job(core); - MALI_DEBUG_PRINT(2, ("Mali PP: Job %d timed out on core %s\n", - mali_pp_job_get_id(core->running_job), core->hw_core.description)); - mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_TIMED_OUT); /* Will release group lock */ - } - else - { - mali_group_unlock(core->group); - } - core->core_timed_out = MALI_FALSE; - return; - } - else if (irq_readout & MALI200_REG_VAL_IRQ_HANG) - { - /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG); - } - - /* - * The only way to get here is if we got a HANG interrupt, which we ignore. - * Re-enable interrupts and let core continue to run - */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); - mali_group_unlock(core->group); - -#if MALI_TIMELINE_PROFILING_ENABLED -#if 0 /* Bottom half TLP logging is currently not supported */ - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); -#endif -#endif -} - -static void mali_pp_irq_probe_trigger(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */ - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG); - _mali_osk_mem_barrier(); -} - -static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data) -{ - struct mali_pp_core *core = (struct mali_pp_core *)data; - u32 irq_readout; - - irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); - if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) - { - mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG); - _mali_osk_mem_barrier(); - return _MALI_OSK_ERR_OK; - } - - return _MALI_OSK_ERR_FAULT; -} - - -/* ------ local helper functions below --------- */ -static void mali_pp_post_process_job(struct mali_pp_core *core) -{ - MALI_ASSERT_GROUP_LOCKED(core->group); - - if (NULL != core->running_job) - { - u32 val0 = 0; - u32 val1 = 0; -#if MALI_TIMELINE_PROFILING_ENABLED - int counter_index = COUNTER_FP0_C0 + (2 * core->core_id); -#endif - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) - { - val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); - if (mali_pp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0); - } - else - { - /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ - mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(counter_index, val0); -#endif - } - - if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) - { - val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); - if (mali_pp_job_get_perf_counter_flag(core->running_job) && - _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) - { - /* We retrieved the counter that user space asked for, so return the value through the job object */ - mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1); - } - else - { - /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ - mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); -#endif - } - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), - val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); -#endif - - /* We are no longer running a job... */ - core->running_job = NULL; - _mali_osk_timer_del(core->timeout_timer); - } -} - -/* callback function for pp core timeout */ -static void mali_pp_timeout(void *data) -{ - struct mali_pp_core * core = ((struct mali_pp_core *)data); - - MALI_DEBUG_PRINT(3, ("Mali PP: TIMEOUT callback \n")); - core->core_timed_out = MALI_TRUE; - _mali_osk_irq_schedulework(core->irq); -} - -#if 0 -static void mali_pp_print_registers(struct mali_pp_core *core) -{ - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC))); - MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE))); -} -#endif - -#if 0 -void mali_pp_print_state(struct mali_pp_core *core) -{ - MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) )); -} -#endif - -#if MALI_STATE_TRACKING -u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size) -{ - int n = 0; - - n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description); - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_pp.h b/drivers/media/video/samsung/mali/common/mali_pp.h deleted file mode 100644 index 9b425a0..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011-2012 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_PP_H__ -#define __MALI_PP_H__ - -#include "mali_osk.h" -#include "mali_pp_job.h" - -struct mali_pp_core; -struct mali_group; - -_mali_osk_errcode_t mali_pp_initialize(void); -void mali_pp_terminate(void); - -struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group); -void mali_pp_delete(struct mali_pp_core *core); - -void mali_pp_stop_bus(struct mali_pp_core *core); -_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core); -_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core); -_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core); - -void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job); - -u32 mali_pp_core_get_version(struct mali_pp_core *core); - -u32 mali_pp_core_get_id(struct mali_pp_core *core); - -mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter); -mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter); -u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core); -u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core); -struct mali_pp_core* mali_pp_get_global_pp_core(u32 index); -u32 mali_pp_get_glob_num_pp_cores(void); -u32 mali_pp_get_max_num_pp_cores(void); -/* Debug */ -u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size); - -#endif /* __MALI_PP_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.c b/drivers/media/video/samsung/mali/common/mali_pp_job.c deleted file mode 100644 index 47b8a0a..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_job.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2011-2012 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 "mali_pp_job.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_kernel_common.h" -#include "mali_uk_types.h" - -struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id) -{ - struct mali_pp_job *job; - - if (args->num_cores > _MALI_PP_MAX_SUB_JOBS) - { - MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); - return NULL; - } - - job = _mali_osk_malloc(sizeof(struct mali_pp_job)); - if (NULL != job) - { - u32 i; - _mali_osk_list_init(&job->list); - job->session = session; - job->id = id; - job->user_id = args->user_job_ptr; - job->barrier = args->flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; - job->active_barrier = job->barrier; - job->no_notification = args->flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; - _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); - _mali_osk_memcpy(job->frame_registers_addr_frame, args->frame_registers_addr_frame, sizeof(job->frame_registers_addr_frame)); - _mali_osk_memcpy(job->frame_registers_addr_stack, args->frame_registers_addr_stack, sizeof(job->frame_registers_addr_stack)); - - /* Only copy write back registers for the units that are enabled */ - job->wb0_registers[0] = 0; - job->wb1_registers[0] = 0; - job->wb2_registers[0] = 0; - if (args->wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ - { - _mali_osk_memcpy(job->wb0_registers, args->wb0_registers, sizeof(job->wb0_registers)); - } - if (args->wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ - { - _mali_osk_memcpy(job->wb1_registers, args->wb1_registers, sizeof(job->wb1_registers)); - } - if (args->wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ - { - _mali_osk_memcpy(job->wb2_registers, args->wb2_registers, sizeof(job->wb2_registers)); - } - - job->perf_counter_flag = args->perf_counter_flag; - job->perf_counter_src0 = args->perf_counter_src0; - job->perf_counter_src1 = args->perf_counter_src1; - for (i = 0; i < args->num_cores; i++) - { - job->perf_counter_value0[i] = 0; - job->perf_counter_value1[i] = 0; - } - job->sub_job_count = args->num_cores; - job->sub_jobs_started = 0; - job->sub_jobs_completed = 0; - job->sub_job_errors = 0; - - job->pid = _mali_osk_get_pid(); - job->tid = _mali_osk_get_tid(); - job->frame_builder_id = args->frame_builder_id; - job->flush_id = args->flush_id; - - return job; - } - - return NULL; -} - -void mali_pp_job_delete(struct mali_pp_job *job) -{ - _mali_osk_free(job); -} - -_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) -{ - if ((0 == job->frame_registers[0]) || (0 == job->frame_registers[1])) - { - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c deleted file mode 100644 index a944055..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright (C) 2012 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 "mali_pp_scheduler.h" -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_list.h" -#include "mali_scheduler.h" -#include "mali_pp.h" -#include "mali_pp_job.h" -#include "mali_group.h" -#include "mali_cluster.h" - -/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ -#define MALI_MAX_NUMBER_OF_PP_GROUPS 8 - -static mali_bool mali_pp_scheduler_is_suspended(void); - -enum mali_pp_slot_state -{ - MALI_PP_SLOT_STATE_IDLE, - MALI_PP_SLOT_STATE_WORKING, -}; - -/* A render slot is an entity which jobs can be scheduled onto */ -struct mali_pp_slot -{ - struct mali_group *group; - /* - * We keep track of the state here as well as in the group object - * so we don't need to take the group lock so often (and also avoid clutter with the working lock) - */ - enum mali_pp_slot_state state; - struct mali_session_data *session; -}; - -static u32 pp_version = 0; -static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ -static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS]; -static u32 num_slots = 0; -static u32 num_slots_idle = 0; - -/* Variables to allow safe pausing of the scheduler */ -static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL; -static u32 pause_count = 0; - -static _mali_osk_lock_t *pp_scheduler_lock = NULL; -/* Contains tid of thread that locked the scheduler or 0, if not locked */ -MALI_DEBUG_CODE(static u32 pp_scheduler_lock_owner = 0); - -_mali_osk_errcode_t mali_pp_scheduler_initialize(void) -{ - u32 i; - - _MALI_OSK_INIT_LIST_HEAD(&job_queue); - - pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); - if (NULL == pp_scheduler_lock) - { - return _MALI_OSK_ERR_NOMEM; - } - - pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init(); - if (NULL == pp_scheduler_working_wait_queue) - { - _mali_osk_lock_term(pp_scheduler_lock); - return _MALI_OSK_ERR_NOMEM; - } - - /* Find all the available PP cores */ - for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++) - { - u32 group_id = 0; - struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i); - struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id); - while (NULL != group) - { - struct mali_pp_core *pp_core = mali_group_get_pp_core(group); - if (NULL != pp_core) - { - if (0 == pp_version) - { - /* Retrieve PP version from first avaiable PP core */ - pp_version = mali_pp_core_get_version(pp_core); - } - slots[num_slots].group = group; - slots[num_slots].state = MALI_PP_SLOT_STATE_IDLE; - slots[num_slots].session = NULL; - num_slots++; - num_slots_idle++; - } - group_id++; - group = mali_cluster_get_group(curr_cluster, group_id); - } - } - - return _MALI_OSK_ERR_OK; -} - -void mali_pp_scheduler_terminate(void) -{ - _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue); - _mali_osk_lock_term(pp_scheduler_lock); -} - -MALI_STATIC_INLINE void mali_pp_scheduler_lock(void) -{ - if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW)) - { - /* Non-interruptable lock failed: this should never happen. */ - MALI_DEBUG_ASSERT(0); - } - MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken\n")); - MALI_DEBUG_ASSERT(0 == pp_scheduler_lock_owner); - MALI_DEBUG_CODE(pp_scheduler_lock_owner = _mali_osk_get_tid()); -} - -MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void) -{ - MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock\n")); - MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); - MALI_DEBUG_CODE(pp_scheduler_lock_owner = 0); - _mali_osk_lock_signal(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW); -} - -#ifdef DEBUG -MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void) -{ - MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner); -} -#define MALI_ASSERT_PP_SCHEDULER_LOCKED() mali_pp_scheduler_assert_locked() -#else -#define MALI_ASSERT_PP_SCHEDULER_LOCKED() -#endif - -static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_data *session) -{ - u32 i; - - MALI_ASSERT_PP_SCHEDULER_LOCKED(); - - if (num_slots_idle == num_slots) - { - return MALI_FALSE; - } - - for (i = 0; i < num_slots; i++) - { - if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) - { - if (slots[i].session == session) - { - return MALI_TRUE; - } - } - } - - return MALI_FALSE; -} - -static void mali_pp_scheduler_schedule(void) -{ - u32 i; - struct mali_pp_job *job; -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS - struct mali_session_data * session; -#endif - - MALI_ASSERT_PP_SCHEDULER_LOCKED(); - - if (0 < pause_count || 0 == num_slots_idle || _mali_osk_list_empty(&job_queue)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", - pause_count, num_slots_idle)); - return; /* Nothing to do, so early out */ - } - - -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP - if ( num_slots_idle < num_slots ) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started, since only %d/%d cores are available\n", num_slots_idle,num_slots)); - return; - } -#endif - -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS - /* Finding initial session for the PP cores */ - job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); - session = job->session; - if ( num_slots != num_slots_idle ) - { - for (i = 0; (i < num_slots) ; i++) - { - if ( slots[i].state == MALI_PP_SLOT_STATE_IDLE ) - { - continue; - } - session = mali_group_get_session(slots[i].group); - break; - } - } -#endif - - for (i = 0; (i < num_slots) && (0 < num_slots_idle); i++) - { - u32 sub_job; - - if (_mali_osk_list_empty(&job_queue)) /* move this check down to where we know we have started all sub jobs for this job??? */ - { - break; /* No more jobs to schedule, so early out */ - } - - if (MALI_PP_SLOT_STATE_IDLE != slots[i].state) - { - continue; - } - - job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); - MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); /* All jobs on the job_queue should have unstarted sub jobs */ - - if (MALI_TRUE == mali_pp_job_has_active_barrier(job)) - { - if (MALI_TRUE == mali_pp_scheduler_session_has_running_jobs(mali_pp_job_get_session(job))) - { - /* There is already a running job from this session, so we need to enforce the barrier */ - return; - } - else - { - /* Barrier is now enforced, update job object so we don't delay execution of sub-jobs */ - mali_pp_job_barrier_enforced(job); - } - } - - #if MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED - if ( (0==job->sub_jobs_started) && (num_slots_idle < num_slots) && (job->sub_job_count > num_slots_idle)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job with %d subjobs not started, since only %d/%d cores are available\n", job->sub_job_count, num_slots_idle,num_slots)); - return; - } - #endif - - #if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS - if ( job->session != session ) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started since existing job is from another application\n")); - return; - } - #endif - - sub_job = mali_pp_job_get_first_unstarted_sub_job(job); - - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Starting job %u (0x%08X) part %u/%u\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); - if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slots[i].group, job, sub_job)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); - - /* Mark this sub job as started */ - mali_pp_job_mark_sub_job_started(job, sub_job); - - /* Mark slot as busy */ - slots[i].state = MALI_PP_SLOT_STATE_WORKING; - slots[i].session = mali_pp_job_get_session(job); - num_slots_idle--; - - if (!mali_pp_job_has_unstarted_sub_jobs(job)) - { - /* - * All sub jobs have now started for this job, remove this job from the job queue. - * The job will now only be referred to by the slots which are running it. - * The last slot to complete will make sure it is returned to user space. - */ - _mali_osk_list_del(&job->list); -#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP - MALI_DEBUG_PRINT(6, ("Mali PP scheduler: Skip scheduling more jobs when MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP is set.\n")); - return; -#endif - } - } - else - { - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); - return; - } - } -} - -static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job) -{ - if (MALI_FALSE == mali_pp_job_use_no_notification(job)) - { - _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s)); - if (NULL != notobj) - { - u32 i; - u32 sub_jobs = mali_pp_job_get_sub_job_count(job); - mali_bool success = mali_pp_job_was_success(job); - - _mali_uk_pp_job_finished_s *jobres = notobj->result_buffer; - _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ - jobres->user_job_ptr = mali_pp_job_get_user_id(job); - if (MALI_TRUE == success) - { - jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; - } - else - { - jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; - } - - for (i = 0; i < sub_jobs; i++) - { - jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i); - jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i); - } - - mali_session_send_notification(mali_pp_job_get_session(job), notobj); - } - else - { - MALI_PRINT_ERROR(("Mali PP scheduler: Unable to allocate notification object\n")); - } - } - - mali_pp_job_delete(job); -} - -void mali_pp_scheduler_do_schedule(void) -{ - mali_pp_scheduler_lock(); - - mali_pp_scheduler_schedule(); - - mali_pp_scheduler_unlock(); -} - -void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) -{ - u32 i; - mali_bool job_is_done; - - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job), success ? "success" : "failure")); - - mali_pp_scheduler_lock(); - - /* Find slot which was running this job */ - for (i = 0; i < num_slots; i++) - { - if (slots[i].group == group) - { - MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slots[i].state); - slots[i].state = MALI_PP_SLOT_STATE_IDLE; - slots[i].session = NULL; - num_slots_idle++; - mali_pp_job_mark_sub_job_completed(job, success); - } - } - - /* If paused, then this was the last job, so wake up sleeping workers */ - if (pause_count > 0) - { - /* Wake up sleeping workers. Their wake-up condition is that - * num_slots == num_slots_idle, so unless we are done working, no - * threads will actually be woken up. - */ - _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); - } - else - { - mali_pp_scheduler_schedule(); - } - - job_is_done = mali_pp_job_is_complete(job); - - mali_pp_scheduler_unlock(); - - if (job_is_done) - { - /* Send notification back to user space */ - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for job %u (0x%08X)\n", mali_pp_job_get_id(job), job)); - mali_pp_scheduler_return_job_to_user(job); - } -} - -void mali_pp_scheduler_suspend(void) -{ - mali_pp_scheduler_lock(); - pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ - mali_pp_scheduler_unlock(); - - /*mali_pp_scheduler_working_lock();*/ - /* We have now aquired the working lock, which means that we have successfully paused the scheduler */ - /*mali_pp_scheduler_working_unlock();*/ - - /* go to sleep. When woken up again (in mali_pp_scheduler_job_done), the - * mali_pp_scheduler_suspended() function will be called. This will return true - * iff state is idle and pause_count > 0, so if the core is active this - * will not do anything. - */ - _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended); -} - -void mali_pp_scheduler_resume(void) -{ - mali_pp_scheduler_lock(); - pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */ - if (0 == pause_count) - { - mali_pp_scheduler_schedule(); - } - mali_pp_scheduler_unlock(); -} - -_mali_osk_errcode_t _mali_ukk_pp_start_job(_mali_uk_pp_start_job_s *args) -{ - struct mali_session_data *session; - struct mali_pp_job *job; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - - session = (struct mali_session_data*)args->ctx; - - job = mali_pp_job_create(session, args, mali_scheduler_get_new_id()); - if (NULL == job) - { - return _MALI_OSK_ERR_NOMEM; - } - - if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) - { - /* Not a valid job, return to user immediately */ - mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */ - mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */ - return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */ - } - -#if PROFILING_SKIP_PP_JOBS || PROFILING_SKIP_PP_AND_GP_JOBS -#warning PP jobs will not be executed - mali_pp_scheduler_return_job_to_user(job); - return _MALI_OSK_ERR_OK; -#endif - - mali_pp_scheduler_lock(); - - _mali_osk_list_addtail(&job->list, &job_queue); - - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); - - mali_pp_scheduler_schedule(); - - mali_pp_scheduler_unlock(); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - args->number_of_cores = num_slots; - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args) -{ - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - args->version = pp_version; - return _MALI_OSK_ERR_OK; -} - -void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) -{ - struct mali_session_data *session; - struct mali_pp_job *job; - struct mali_pp_job *tmp; - - MALI_DEBUG_ASSERT_POINTER(args); - MALI_DEBUG_ASSERT_POINTER(args->ctx); - - session = (struct mali_session_data*)args->ctx; - - mali_pp_scheduler_lock(); - - /* Check queue for jobs that match */ - _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) - { - if (mali_pp_job_get_session(job) == session && - mali_pp_job_get_frame_builder_id(job) == (u32)args->fb_id && - mali_pp_job_get_flush_id(job) == (u32)args->flush_id) - { - if (args->wbx & _MALI_UK_PP_JOB_WB0) - { - mali_pp_job_disable_wb0(job); - } - if (args->wbx & _MALI_UK_PP_JOB_WB1) - { - mali_pp_job_disable_wb1(job); - } - if (args->wbx & _MALI_UK_PP_JOB_WB2) - { - mali_pp_job_disable_wb2(job); - } - break; - } - } - - mali_pp_scheduler_unlock(); -} - -void mali_pp_scheduler_abort_session(struct mali_session_data *session) -{ - struct mali_pp_job *job, *tmp; - int i; - - mali_pp_scheduler_lock(); - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08x\n", session)); - - /* Check queue for jobs and remove */ - _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) - { - if (mali_pp_job_get_session(job) == session) - { - _mali_osk_list_del(&(job->list)); - - if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) ) - { - /* The job is in the render pipeline, we can not delete it yet. */ - /* It will be deleted in the mali_group_abort_session() call below */ - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in queue\n", job)); - continue; - } - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Removing PP job 0x%08x from queue\n", job)); - mali_pp_job_delete(job); - } - } - - mali_pp_scheduler_unlock(); - - /* Abort running jobs from this session */ - for (i = 0; i < num_slots; i++) - { - struct mali_group *group = slots[i].group; - - MALI_DEBUG_PRINT(5, ("PP sched abort: Looking at group 0x%08x\n", group)); - - if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborting session 0x%08x from group 0x%08x\n", session, group)); - - mali_group_abort_session(group, session); - } - } -} - -static mali_bool mali_pp_scheduler_is_suspended(void) -{ - mali_bool ret; - - mali_pp_scheduler_lock(); - ret = pause_count > 0 && num_slots == num_slots_idle; - mali_pp_scheduler_unlock(); - - return ret; -} - -#if MALI_STATE_TRACKING -u32 mali_pp_scheduler_dump_state(char *buf, u32 size) -{ - int n = 0; - int i; - - n += _mali_osk_snprintf(buf + n, size - n, "PP:\n"); - n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty"); - n += _mali_osk_snprintf(buf + n, size - n, "\n"); - - for (i = 0; i < num_slots; i++) - { - n += mali_group_dump_state(slots[i].group, buf + n, size - n); - n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", slots[i].state); - } - - return n; -} -#endif diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h deleted file mode 100644 index 48eb3bd..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2012 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_PP_SCHEDULER_H__ -#define __MALI_PP_SCHEDULER_H__ - -#include "mali_osk.h" -#include "mali_cluster.h" -#include "mali_pp_job.h" - -_mali_osk_errcode_t mali_pp_scheduler_initialize(void); -void mali_pp_scheduler_terminate(void); - -void mali_pp_scheduler_do_schedule(void); -void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success); - -void mali_pp_scheduler_suspend(void); -void mali_pp_scheduler_resume(void); - -/** @brief Abort all PP jobs from session running or queued - * - * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the queue and jobs - * currently running on a core will be aborted. - * - * @param session Pointer to session whose jobs should be aborted - */ -void mali_pp_scheduler_abort_session(struct mali_session_data *session); - -u32 mali_pp_scheduler_dump_state(char *buf, u32 size); - -#endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h deleted file mode 100644 index 7c78947..0000000 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2010, 2012 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_UTGARD_H__ -#define __MALI_UTGARD_H__ - -/** @brief MALI GPU power down using MALI in-built PMU - * - * called to power down all cores - */ -int mali_pmu_powerdown(void); - - -/** @brief MALI GPU power up using MALI in-built PMU - * - * called to power up all cores - */ -int mali_pmu_powerup(void); - -#endif /* __MALI_UTGARD_H__ */ - diff --git a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c b/drivers/media/video/samsung/mali/linux/mali_dma_buf.c deleted file mode 100644 index 4dd711f..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_dma_buf.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2012 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 <linux/dma-buf.h> -#include <linux/scatterlist.h> -#include <linux/rbtree.h> - -#include "mali_ukk.h" -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_session.h" -#include "mali_kernel_linux.h" - -#include "mali_kernel_memory_engine.h" -#include "mali_memory.h" - -#include "mali_kernel_sysfs.h" - - -struct mali_dma_buf_attachment { - struct dma_buf *buf; - struct dma_buf_attachment *attachment; - struct sg_table *sgt; - _mali_osk_atomic_t ref; - struct rb_node rb_node; -}; - -static struct rb_root mali_dma_bufs = RB_ROOT; -static DEFINE_SPINLOCK(mali_dma_bufs_lock); - -static inline struct mali_dma_buf_attachment *mali_dma_buf_lookup(struct rb_root *root, struct dma_buf *target) -{ - struct rb_node *node = root->rb_node; - struct mali_dma_buf_attachment *res; - - spin_lock(&mali_dma_bufs_lock); - while (node) - { - res = rb_entry(node, struct mali_dma_buf_attachment, rb_node); - - if (target < res->buf) node = node->rb_left; - else if (target > res->buf) node = node->rb_right; - else - { - _mali_osk_atomic_inc(&res->ref); - spin_unlock(&mali_dma_bufs_lock); - return res; - } - } - spin_unlock(&mali_dma_bufs_lock); - - return NULL; -} - -static void mali_dma_buf_add(struct rb_root *root, struct mali_dma_buf_attachment *new) -{ - struct rb_node **node = &root->rb_node; - struct rb_node *parent = NULL; - struct mali_dma_buf_attachment *res; - - spin_lock(&mali_dma_bufs_lock); - while (*node) - { - parent = *node; - res = rb_entry(*node, struct mali_dma_buf_attachment, rb_node); - - if (new->buf < res->buf) node = &(*node)->rb_left; - else node = &(*node)->rb_right; - } - - rb_link_node(&new->rb_node, parent, node); - rb_insert_color(&new->rb_node, &mali_dma_bufs); - - spin_unlock(&mali_dma_bufs_lock); - - return; -} - - -static void mali_dma_buf_release(void *ctx, void *handle) -{ - struct mali_dma_buf_attachment *mem; - u32 ref; - - mem = (struct mali_dma_buf_attachment *)handle; - - MALI_DEBUG_ASSERT_POINTER(mem); - MALI_DEBUG_ASSERT_POINTER(mem->attachment); - MALI_DEBUG_ASSERT_POINTER(mem->buf); - - spin_lock(&mali_dma_bufs_lock); - ref = _mali_osk_atomic_dec_return(&mem->ref); - - MALI_DEBUG_ASSERT(ref >= 0); - - if (0 == ref) - { - rb_erase(&mem->rb_node, &mali_dma_bufs); - spin_unlock(&mali_dma_bufs_lock); - - MALI_DEBUG_ASSERT(0 == _mali_osk_atomic_read(&mem->ref)); - - dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL); - - dma_buf_detach(mem->buf, mem->attachment); - dma_buf_put(mem->buf); - - _mali_osk_free(mem); - } - else - { - spin_unlock(&mali_dma_bufs_lock); - } -} - -/* Callback from memory engine which will map into Mali virtual address space */ -static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) -{ - struct mali_session_data *session; - struct mali_page_directory *pagedir; - struct mali_dma_buf_attachment *mem; - struct scatterlist *sg; - int i; - u32 virt; - - MALI_DEBUG_ASSERT_POINTER(ctx); - MALI_DEBUG_ASSERT_POINTER(engine); - MALI_DEBUG_ASSERT_POINTER(descriptor); - MALI_DEBUG_ASSERT_POINTER(offset); - MALI_DEBUG_ASSERT_POINTER(alloc_info); - - /* Mapping dma-buf with an offset is not supported. */ - MALI_DEBUG_ASSERT(0 == *offset); - - virt = descriptor->mali_address; - session = (struct mali_session_data *)descriptor->mali_addr_mapping_info; - pagedir = mali_session_get_page_directory(session); - - MALI_DEBUG_ASSERT_POINTER(session); - - mem = (struct mali_dma_buf_attachment *)ctx; - - MALI_DEBUG_ASSERT_POINTER(mem); - - mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL); - if (IS_ERR_OR_NULL(mem->sgt)) - { - MALI_PRINT_ERROR(("Failed to map dma-buf attachment\n")); - return MALI_MEM_ALLOC_INTERNAL_FAILURE; - } - - for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) - { - u32 size = sg_dma_len(sg); - dma_addr_t phys = sg_dma_address(sg); - - /* sg must be page aligned. */ - MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE); - - mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD); - - virt += size; - *offset += size; - } - - if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE) - { - u32 guard_phys; - MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n")); - - guard_phys = sg_dma_address(mem->sgt->sgl); - mali_mmu_pagedir_update(mali_session_get_page_directory(session), virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD); - } - - MALI_DEBUG_ASSERT(*offset == descriptor->size); - - alloc_info->ctx = NULL; - alloc_info->handle = mem; - alloc_info->next = NULL; - alloc_info->release = mali_dma_buf_release; - - return MALI_MEM_ALLOC_FINISHED; -} - -int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg) -{ - mali_physical_memory_allocator external_memory_allocator; - struct dma_buf *buf; - struct mali_dma_buf_attachment *mem; - _mali_uk_attach_dma_buf_s args; - mali_memory_allocation *descriptor; - int md; - int fd; - - /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) - { - return -EFAULT; - } - - - fd = args.mem_fd; - - buf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(buf)) - { - MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); - return PTR_RET(buf); - } - - /* Currently, mapping of the full buffer are supported. */ - if (args.size != buf->size) - { - MALI_DEBUG_PRINT(2, ("dma-buf size doesn't match mapping size.\n")); - dma_buf_put(buf); - return -EINVAL; - } - - - mem = mali_dma_buf_lookup(&mali_dma_bufs, buf); - if (NULL == mem) - { - /* dma-buf is not already attached to Mali */ - mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment)); - if (NULL == mem) - { - MALI_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n")); - dma_buf_put(mem->buf); - return -ENOMEM; - } - _mali_osk_atomic_init(&mem->ref, 1); - mem->buf = buf; - - mem->attachment = dma_buf_attach(mem->buf, mali_device); - if (NULL == mem->attachment) - { - MALI_DEBUG_PRINT(2, ("Failed to attach to dma-buf %d\n", fd)); - dma_buf_put(mem->buf); - _mali_osk_free(mem); - return -EFAULT; - } - - mali_dma_buf_add(&mali_dma_bufs, mem); - } - else - { - /* dma-buf is already attached to Mali */ - /* Give back the reference we just took, mali_dma_buf_lookup grabbed a new reference for us. */ - dma_buf_put(buf); - } - - /* Map dma-buf into this session's page tables */ - - /* Set up Mali memory descriptor */ - descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation)); - if (NULL == descriptor) - { - MALI_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd)); - mali_dma_buf_release(NULL, mem); - return -ENOMEM; - } - - descriptor->size = args.size; - descriptor->mapping = NULL; - descriptor->mali_address = args.mali_address; - descriptor->mali_addr_mapping_info = (void*)session; - descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ - descriptor->lock = session->memory_lock; - - if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) - { - descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; - } - _mali_osk_list_init( &descriptor->list ); - - /* Get descriptor mapping for memory. */ - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) - { - MALI_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd)); - _mali_osk_free(descriptor); - mali_dma_buf_release(NULL, mem); - return -EFAULT; - } - - external_memory_allocator.allocate = mali_dma_buf_commit; - external_memory_allocator.allocate_page_table_block = NULL; - external_memory_allocator.ctx = mem; - external_memory_allocator.name = "DMA-BUF Memory"; - external_memory_allocator.next = NULL; - - /* Map memory into session's Mali virtual address space. */ - _mali_osk_lock_wait(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(mali_mem_get_memory_engine(), descriptor, &external_memory_allocator, NULL)) - { - _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - - MALI_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd)); - mali_descriptor_mapping_free(session->descriptor_mapping, md); - mali_dma_buf_release(NULL, mem); - return -ENOMEM; - } - _mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW); - - /* Return stuff to user space */ - if (0 != put_user(md, &user_arg->cookie)) - { - /* Roll back */ - MALI_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd)); - mali_descriptor_mapping_free(session->descriptor_mapping, md); - mali_dma_buf_release(NULL, mem); - return -EFAULT; - } - - return 0; -} - -int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg) -{ - _mali_uk_release_dma_buf_s args; - mali_memory_allocation *descriptor; - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) - { - return -EFAULT; - } - - if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args.cookie, (void**)&descriptor)) - { - MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release dma-buf\n", args.cookie)); - return -EINVAL; - } - - descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie); - - if (NULL != descriptor) - { - _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - /* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */ - mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor); - - _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW ); - - _mali_osk_free(descriptor); - } - - /* Return the error that _mali_ukk_map_external_ump_mem produced */ - return 0; -} - -int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg) -{ - _mali_uk_dma_buf_get_size_s args; - int fd; - struct dma_buf *buf; - - /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */ - if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) - { - return -EFAULT; - } - - /* Do DMA-BUF stuff */ - fd = args.mem_fd; - - buf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(buf)) - { - MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd)); - return PTR_RET(buf); - } - - if (0 != put_user(buf->size, &user_arg->size)) - { - dma_buf_put(buf); - return -EFAULT; - } - - dma_buf_put(buf); - - return 0; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c deleted file mode 100644 index 4639d55..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c +++ /dev/null @@ -1,268 +0,0 @@ -/** - * Copyright (C) 2010-2012 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_pm.c - * Linux Power Management integration - */ - -#include <linux/sched.h> -#include <linux/platform_device.h> -#include <linux/version.h> -#include <asm/current.h> -#include <linux/suspend.h> -#include <linux/module.h> -#ifdef CONFIG_PM_RUNTIME -#include <linux/pm_runtime.h> -#endif -#include "mali_osk.h" -#include "mali_uk_types.h" -#include "mali_kernel_common.h" -#include "mali_kernel_license.h" -#include "mali_linux_pm.h" -#include "mali_pm.h" -#include "mali_platform.h" - -#if ! MALI_LICENSE_IS_GPL -#undef CONFIG_PM_RUNTIME -#endif - -#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 */ -static int mali_probe(struct platform_device *pdev); -static int mali_remove(struct platform_device *pdev); - -#ifdef CONFIG_PM_RUNTIME -static int mali_runtime_suspend(struct device *dev); -static int mali_runtime_resume(struct device *dev); -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -static int mali_os_suspend(struct platform_device *pdev, pm_message_t state); -static int mali_os_resume(struct platform_device *pdev); -#else -static int mali_os_suspend(struct device *dev); -static int mali_os_resume(struct device *dev); -#endif - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) -static const struct dev_pm_ops mali_dev_pm_ops = -{ -#ifdef CONFIG_PM_RUNTIME - .runtime_suspend = mali_runtime_suspend, - .runtime_resume = mali_runtime_resume, - .runtime_idle = NULL, -#else - .suspend = mali_os_suspend, - .resume = mali_os_resume, -#endif - .freeze = mali_os_suspend, - .poweroff = mali_os_suspend, - .thaw = mali_os_resume, - .restore = mali_os_resume, -}; -#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) -struct pm_ext_ops mali_ext_pm_operations = -{ - .base = - { - .freeze = mali_os_suspend, - .thaw = mali_os_resume, - .poweroff = mali_os_suspend, - .restore = mali_os_resume, - }, -}; -#endif - - -static struct platform_driver mali_plat_driver = -{ - .probe = mali_probe, - .remove = mali_remove, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) - .suspend = mali_os_suspend, - .resume = mali_os_resume, - .pm = &mali_ext_pm_operations, -#endif - - .driver = - { - .name = "mali_dev", - .owner = THIS_MODULE, -#if MALI_LICENSE_IS_GPL - .bus = &platform_bus_type, -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) - .pm = &mali_dev_pm_ops, -#endif - }, -}; - -#ifdef CONFIG_PM_RUNTIME -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 - -/** 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) -{ -} -struct platform_device mali_gpu_device = -{ - .name = "mali_dev", - .id = 0, - .dev.release = _mali_release_pm -}; - -/** This function is called when the device is probed */ -static int mali_probe(struct platform_device *pdev) -{ - return 0; -} - -static int mali_remove(struct platform_device *pdev) -{ -#ifdef CONFIG_PM_RUNTIME - pm_runtime_disable(&pdev->dev); -#endif - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy) -{ - switch (event) - { - case PM_SUSPEND_PREPARE: - MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n")); - mali_pm_os_suspend(); - break; - case PM_POST_SUSPEND: - MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n")); - mali_pm_os_resume(); - break; - default: - break; - } - return 0; -} -#endif - - -#ifdef CONFIG_PM_RUNTIME - -static int mali_runtime_suspend(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_runtime_suspend() called\n")); - mali_pm_runtime_suspend(); - return 0; /* all ok */ -} - -static int mali_runtime_resume(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_runtime_resume() called\n")); - mali_pm_runtime_resume(); - return 0; /* all ok */ -} - -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) - -static int mali_os_suspend(struct platform_device *pdev, pm_message_t state) -{ - MALI_DEBUG_PRINT(3, ("mali_os_suspend(old) called\n")); - mali_pm_os_suspend(); - return 0; /* all ok */ -} - -static int mali_os_resume(struct platform_device *pdev) -{ - MALI_DEBUG_PRINT(3, ("mali_os_resume(old) called\n")); - mali_pm_os_resume(); - return 0; /* all ok */ -} - -#else - -static int mali_os_suspend(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_os_suspend(new) called\n")); - mali_pm_os_suspend(); - return 0; /* all ok */ -} - -static int mali_os_resume(struct device *dev) -{ - MALI_DEBUG_PRINT(3, ("mali_os_resume(new) called\n")); - mali_pm_os_resume(); - return 0; /* all ok */ -} - -#endif - -/** This function is called when Mali GPU device is initialized - */ -int _mali_dev_platform_register(void) -{ - int err; - -#ifdef CONFIG_PM_RUNTIME - set_mali_parent_power_domain((void *)&mali_gpu_device); -#endif - -#ifdef CONFIG_PM_RUNTIME - err = register_pm_notifier(&mali_pwr_notif_block); - if (err) - { - return err; - } -#endif - -#if MALI_LICENSE_IS_GPL - err = platform_device_register(&mali_gpu_device); - if (!err) - { - err = platform_driver_register(&mali_plat_driver); - if (err) - { -#ifdef CONFIG_PM_RUNTIME - unregister_pm_notifier(&mali_pwr_notif_block); -#endif - platform_device_unregister(&mali_gpu_device); - } - } -#endif - - return err; -} - -/** This function is called when Mali GPU device is unloaded - */ -void _mali_dev_platform_unregister(void) -{ -#ifdef CONFIG_PM_RUNTIME - unregister_pm_notifier(&mali_pwr_notif_block); -#endif - -#if MALI_LICENSE_IS_GPL - platform_driver_unregister(&mali_plat_driver); - platform_device_unregister(&mali_gpu_device); -#endif -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h deleted file mode 100644 index 6ef7270..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2010, 2012 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__ - -int _mali_dev_platform_register(void); -void _mali_dev_platform_unregister(void); - -#endif /* __MALI_KERNEL_PM_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm.h deleted file mode 100644 index 10f633e..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h +++ /dev/null @@ -1,50 +0,0 @@ - -/* - * Copyright (C) 2010-2012 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__ - -#ifdef CONFIG_PM -/* Number of power states supported for making power up and down */ -typedef enum -{ - _MALI_DEVICE_SUSPEND, /* Suspend */ - _MALI_DEVICE_RESUME, /* Resume */ - _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, /* 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); -int mali_get_ospmm_thread_state(void); - -#endif /* CONFIG_PM */ -#endif /* __MALI_LINUX_PM_H___ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h deleted file mode 100644 index 7d811bd..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 MALI_POWER_MGMT_TEST_SUITE && defined(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 /* MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) */ - -#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c b/drivers/media/video/samsung/mali/linux/mali_osk_irq.c deleted file mode 100644 index ddfe564..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 <linux/version.h> - -#include "mali_osk.h" -#include "mali_kernel_common.h" -#include "mali_kernel_license.h" -#include "mali_kernel_linux.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; -struct workqueue_struct *mali_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; - -#if MALI_LICENSE_IS_GPL - if (NULL == mali_wq) - { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) - mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0); -#else - mali_wq = create_workqueue("mali"); -#endif - if(NULL == mali_wq) - { - MALI_PRINT_ERROR(("Unable to create Mali workqueue\n")); - kfree(irq_object); - return NULL; - } - } -#endif - - /* 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 (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 - { - queue_work(mali_wq, &irq_object->work_queue_irq_handle); - } -#else - schedule_work(&irq_object->work_queue_irq_handle); -#endif -} - -void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ) -{ -#if MALI_LICENSE_IS_GPL - if (NULL != irq) - { - 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); - } - else - { - flush_workqueue(mali_wq); - } - } - else - { - flush_workqueue(mali_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 - 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); -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c deleted file mode 100644 index 06cb215..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_mali.c - * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver - */ -#include <linux/kernel.h> -#include <asm/uaccess.h> -#include <mach/irqs.h> - -#include "mali_kernel_common.h" /* MALI_xxx macros */ -#include "mali_osk.h" /* kernel side OS functions */ -#include "mali_uk_types.h" -#include "arch/config.h" /* contains the configuration of the arch we are compiling for */ - -_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ) -{ - *num_resources = sizeof(arch_configuration) / sizeof(arch_configuration[0]); - *arch_config = arch_configuration; - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources ) -{ - /* Nothing to do */ -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c b/drivers/media/video/samsung/mali/linux/mali_osk_pm.c deleted file mode 100644 index 491a603..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (C) 2010-2012 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_kernel_common.h" -#include "mali_kernel_license.h" -#include "mali_linux_pm.h" -#include "mali_kernel_license.h" - -#if ! MALI_LICENSE_IS_GPL -#undef CONFIG_PM_RUNTIME -#endif - -extern struct platform_device mali_gpu_device; - -#ifdef CONFIG_PM_RUNTIME -static mali_bool have_runtime_reference = MALI_FALSE; -#endif - -void _mali_osk_pm_dev_enable(void) -{ -#ifdef CONFIG_PM_RUNTIME - pm_runtime_enable(&(mali_gpu_device.dev)); -#endif -} - -/* NB: Function is not thread safe */ -_mali_osk_errcode_t _mali_osk_pm_dev_idle(void) -{ -#ifdef CONFIG_PM_RUNTIME - if (MALI_TRUE == have_runtime_reference) - { - int err; - err = pm_runtime_put_sync(&(mali_gpu_device.dev)); - if (0 > err) - { - MALI_PRINT_ERROR(("OSK PM: pm_runtime_put_sync() returned error code %d\n", err)); - return _MALI_OSK_ERR_FAULT; - } - have_runtime_reference = MALI_FALSE; - } -#endif - return _MALI_OSK_ERR_OK; -} - -/* NB: Function is not thread safe */ -_mali_osk_errcode_t _mali_osk_pm_dev_activate(void) -{ -#ifdef CONFIG_PM_RUNTIME - if (MALI_TRUE != have_runtime_reference) - { - int err; - err = pm_runtime_get_sync(&(mali_gpu_device.dev)); - if (0 > err) - { - MALI_PRINT_ERROR(("OSK PM: pm_runtime_get_sync() returned error code %d\n", err)); - return _MALI_OSK_ERR_FAULT; - } - have_runtime_reference = MALI_TRUE; - } -#endif - return _MALI_OSK_ERR_OK; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c deleted file mode 100644 index 2df935d..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_timestamp.h" -#include "mali_osk_profiling.h" -#include "mali_user_settings_db.h" - -typedef struct mali_profiling_entry -{ - u64 timestamp; - u32 event_id; - u32 data[5]; -} mali_profiling_entry; - - -typedef enum mali_profiling_state -{ - MALI_PROFILING_STATE_UNINITIALIZED, - MALI_PROFILING_STATE_IDLE, - MALI_PROFILING_STATE_RUNNING, - MALI_PROFILING_STATE_RETURN, -} mali_profiling_state; - -static _mali_osk_lock_t *lock = NULL; -static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; -static mali_profiling_entry* profile_entries = NULL; -static u32 profile_entry_count = 0; -static _mali_osk_atomic_t profile_insert_index; -static _mali_osk_atomic_t profile_entries_written; - -_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) -{ - profile_entries = NULL; - profile_entry_count = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - _mali_osk_atomic_init(&profile_entries_written, 0); - - lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); - if (NULL == lock) - { - return _MALI_OSK_ERR_FAULT; - } - - prof_state = MALI_PROFILING_STATE_IDLE; - - if (MALI_TRUE == auto_start) - { - u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ - - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); - if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) - { - return _MALI_OSK_ERR_FAULT; - } - } - - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_profiling_term(void) -{ - prof_state = MALI_PROFILING_STATE_UNINITIALIZED; - - /* wait for all elements to be completely inserted into array */ - while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) - { - /* do nothing */; - } - - if (NULL != profile_entries) - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - if (NULL != lock) - { - _mali_osk_lock_term(lock); - lock = NULL; - } -} - -inline _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) -{ - _mali_osk_errcode_t ret; - - mali_profiling_entry *new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); - - if(NULL == new_profile_entries) - { - return _MALI_OSK_ERR_NOMEM; - } - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_IDLE) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_vfree(new_profile_entries); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if (*limit > MALI_PROFILING_MAX_BUFFER_ENTRIES) - { - *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; - } - - profile_entries = new_profile_entries; - profile_entry_count = *limit; - - ret = _mali_timestamp_reset(); - - if (ret == _MALI_OSK_ERR_OK) - { - prof_state = MALI_PROFILING_STATE_RUNNING; - } - else - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return ret; -} - -inline void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) -{ - if (prof_state == MALI_PROFILING_STATE_RUNNING) - { - u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) % profile_entry_count; - - profile_entries[cur_index].timestamp = _mali_timestamp_get(); - profile_entries[cur_index].event_id = event_id; - profile_entries[cur_index].data[0] = data0; - profile_entries[cur_index].data[1] = data1; - profile_entries[cur_index].data[2] = data2; - profile_entries[cur_index].data[3] = data3; - profile_entries[cur_index].data[4] = data4; - - /* If event is "leave API function", add current memory usage to the event - * as data point 4. This is used in timeline profiling to indicate how - * much memory was used when leaving a function. */ - if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) - { - profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); - } - - _mali_osk_atomic_inc(&profile_entries_written); - } -} - -inline void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value) -{ - /* Not implemented */ -} - -void _mali_osk_profiling_report_sw_counters(u32 *counters) -{ - /* Not implemented */ -} - -inline _mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RUNNING) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - /* go into return state (user to retreive events), no more events will be added after this */ - prof_state = MALI_PROFILING_STATE_RETURN; - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - /* wait for all elements to be completely inserted into array */ - while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) - { - /* do nothing */; - } - - *count = _mali_osk_atomic_read(&profile_insert_index); - if(*count>profile_entry_count) *count=profile_entry_count; - - return _MALI_OSK_ERR_OK; -} - -inline u32 _mali_osk_profiling_get_count(void) -{ - u32 retval = 0; - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - if (prof_state == MALI_PROFILING_STATE_RETURN) - { - retval = _mali_osk_atomic_read(&profile_entries_written); - if(retval>profile_entry_count) retval = profile_entry_count; - } - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - return retval; -} - -inline _mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if(index<profile_entry_count) - { - u32 idx = index; - if(_mali_osk_atomic_read(&profile_insert_index)>=profile_entry_count) - { - idx = (index + _mali_osk_atomic_read(&profile_insert_index)) % profile_entry_count; - } - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if (idx >= _mali_osk_atomic_read(&profile_entries_written)) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - *timestamp = profile_entries[idx].timestamp; - *event_id = profile_entries[idx].event_id; - data[0] = profile_entries[idx].data[0]; - data[1] = profile_entries[idx].data[1]; - data[2] = profile_entries[idx].data[2]; - data[3] = profile_entries[idx].data[3]; - data[4] = profile_entries[idx].data[4]; - } - else - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -inline _mali_osk_errcode_t _mali_osk_profiling_clear(void) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - prof_state = MALI_PROFILING_STATE_IDLE; - profile_entry_count = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - _mali_osk_atomic_init(&profile_entries_written, 0); - if (NULL != profile_entries) - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -mali_bool _mali_osk_profiling_is_recording(void) -{ - return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; -} - -mali_bool _mali_osk_profiling_have_recording(void) -{ - return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; -} - -_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) -{ - return _mali_osk_profiling_start(&args->limit); -} - -_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) -{ - /* Always add process and thread identificator in the first two data elements for events from user space */ - _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) -{ - return _mali_osk_profiling_stop(&args->count); -} - -_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) -{ - return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); -} - -_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) -{ - return _mali_osk_profiling_clear(); -} - -_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) -{ - _mali_osk_profiling_report_sw_counters(args->counters); - return _MALI_OSK_ERR_OK; -} - diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h deleted file mode 100644 index 83ee906..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2010, 2012 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 - -/** The list of events supported by the Mali DDK. */ -typedef enum -{ - /* Vertex processor activity */ - ACTIVITY_VP = 0, - - /* Fragment processor activity */ - ACTIVITY_FP0, - ACTIVITY_FP1, - ACTIVITY_FP2, - ACTIVITY_FP3, - - /* L2 cache counters */ - COUNTER_L2_C0, - COUNTER_L2_C1, - - /* Vertex processor counters */ - COUNTER_VP_C0, - COUNTER_VP_C1, - - /* Fragment processor counters */ - COUNTER_FP0_C0, - COUNTER_FP0_C1, - COUNTER_FP1_C0, - COUNTER_FP1_C1, - COUNTER_FP2_C0, - COUNTER_FP2_C1, - COUNTER_FP3_C0, - COUNTER_FP3_C1, - - /* - * If more hardware counters are added, the _mali_osk_hw_counter_table - * below should also be updated. - */ - - /* EGL software counters */ - COUNTER_EGL_BLIT_TIME, - - /* GLES software counters */ - COUNTER_GLES_DRAW_ELEMENTS_CALLS, - COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, - COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_ARRAYS_CALLS, - COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_POINTS, - COUNTER_GLES_DRAW_LINES, - COUNTER_GLES_DRAW_LINE_LOOP, - COUNTER_GLES_DRAW_LINE_STRIP, - COUNTER_GLES_DRAW_TRIANGLES, - COUNTER_GLES_DRAW_TRIANGLE_STRIP, - COUNTER_GLES_DRAW_TRIANGLE_FAN, - COUNTER_GLES_NON_VBO_DATA_COPY_TIME, - COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, - COUNTER_GLES_UPLOAD_TEXTURE_TIME, - COUNTER_GLES_UPLOAD_VBO_TIME, - COUNTER_GLES_NUM_FLUSHES, - COUNTER_GLES_NUM_VSHADERS_GENERATED, - COUNTER_GLES_NUM_FSHADERS_GENERATED, - COUNTER_GLES_VSHADER_GEN_TIME, - COUNTER_GLES_FSHADER_GEN_TIME, - COUNTER_GLES_INPUT_TRIANGLES, - COUNTER_GLES_VXCACHE_HIT, - COUNTER_GLES_VXCACHE_MISS, - COUNTER_GLES_VXCACHE_COLLISION, - COUNTER_GLES_CULLED_TRIANGLES, - COUNTER_GLES_CULLED_LINES, - COUNTER_GLES_BACKFACE_TRIANGLES, - COUNTER_GLES_GBCLIP_TRIANGLES, - COUNTER_GLES_GBCLIP_LINES, - COUNTER_GLES_TRIANGLES_DRAWN, - COUNTER_GLES_DRAWCALL_TIME, - COUNTER_GLES_TRIANGLES_COUNT, - COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, - COUNTER_GLES_STRIP_TRIANGLES_COUNT, - COUNTER_GLES_FAN_TRIANGLES_COUNT, - COUNTER_GLES_LINES_COUNT, - COUNTER_GLES_INDEPENDENT_LINES_COUNT, - COUNTER_GLES_STRIP_LINES_COUNT, - COUNTER_GLES_LOOP_LINES_COUNT, - - /* Framebuffer capture pseudo-counter */ - COUNTER_FILMSTRIP, - - NUMBER_OF_EVENTS -} _mali_osk_counter_id; - -#define FIRST_ACTIVITY_EVENT ACTIVITY_VP -#define LAST_ACTIVITY_EVENT ACTIVITY_FP3 - -#define FIRST_HW_COUNTER COUNTER_L2_C0 -#define LAST_HW_COUNTER COUNTER_FP3_C1 - -#define FIRST_SW_COUNTER COUNTER_EGL_BLIT_TIME -#define LAST_SW_COUNTER COUNTER_GLES_LOOP_LINES_COUNT - -#define FIRST_SPECIAL_COUNTER COUNTER_FILMSTRIP -#define LAST_SPECIAL_COUNTER COUNTER_FILMSTRIP - -#endif /* __MALI_OSK_SPECIFIC_H__ */ diff --git a/drivers/media/video/samsung/mali/platform/default/mali_platform.c b/drivers/media/video/samsung/mali/platform/default/mali_platform.c deleted file mode 100644 index d966f25..0000000 --- a/drivers/media/video/samsung/mali/platform/default/mali_platform.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" - - -_mali_osk_errcode_t mali_platform_init(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ -} - -void set_mali_parent_power_domain(void* dev) -{ -} - - diff --git a/drivers/media/video/samsung/mali/platform/mali_platform.h b/drivers/media/video/samsung/mali/platform/mali_platform.h deleted file mode 100644 index 888f57a..0000000 --- a/drivers/media/video/samsung/mali/platform/mali_platform.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_platform.h - * Platform specific Mali driver functions - */ - -#ifndef __MALI_PLATFORM_H__ -#define __MALI_PLATFORM_H__ - -#include "mali_osk.h" - -#ifdef CONFIG_CPU_EXYNOS4210 -#define MALI_DVFS_STEPS 3 -#else -#define MALI_DVFS_STEPS 5 -#endif - -/* @Enable or Disable Mali GPU Bottom Lock feature */ -#define MALI_GPU_BOTTOM_LOCK 1 - -#define MALI_VOLTAGE_LOCK 1 - -/* @Enable or Disable the CPU frequency lock when the GPU clock is 440 Mhz */ -#define CPUFREQ_LOCK_DURING_440 0 - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief description of power change reasons - */ -typedef enum mali_power_mode_tag -{ - MALI_POWER_MODE_ON, /**< Power Mali on */ - MALI_POWER_MODE_LIGHT_SLEEP, /**< Mali has been idle for a short time, or runtime PM suspend */ - MALI_POWER_MODE_DEEP_SLEEP, /**< Mali has been idle for a long time, or OS suspend */ -} mali_power_mode; - -/** @brief Platform specific setup and initialisation of MALI - * - * This is called from the entrypoint of the driver to initialize the platform - * - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_platform_init(void); - -/** @brief Platform specific deinitialisation of MALI - * - * This is called on the exit of the driver to terminate the platform - * - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_platform_deinit(void); - -/** @brief Platform specific powerdown sequence of MALI - * - * Notification from the Mali device driver stating the new desired power mode. - * MALI_POWER_MODE_ON must be obeyed, while the other modes are optional. - * @param power_mode defines the power modes - * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. - */ -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode); - - -/** @brief Platform specific handling of GPU utilization data - * - * When GPU utilization data is enabled, this function will be - * periodically called. - * - * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. - */ -void mali_gpu_utilization_handler(u32 utilization); - -/** @brief Setting the power domain of MALI - * - * This function sets the power domain of MALI if Linux run time power management is enabled - * - * @param dev Reference to struct platform_device (defined in linux) used by MALI GPU - */ -//void set_mali_parent_power_domain(void* dev); -void mali_utilization_suspend(void); - -#ifdef CONFIG_REGULATOR -int mali_regulator_get_usecount(void); -void mali_regulator_disable(void); -void mali_regulator_enable(void); -void mali_regulator_set_voltage(int min_uV, int max_uV); -#endif -mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz); -unsigned long mali_clk_get_rate(void); -void mali_clk_put(mali_bool binc_mali_clk); - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -_mali_osk_errcode_t mali_platform_powerdown(u32 cores); -_mali_osk_errcode_t mali_platform_powerup(u32 cores); -#endif - - -#if USING_MALI_PMM -#if MALI_POWER_MGMT_TEST_SUITE -/** @brief function to get status of individual cores - * - * This function is used by power management test suite to get the status of powered up/down the number - * of cores - * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. - */ -u32 pmu_get_power_up_down_info(void); -#endif -#endif - -#if MALI_DVFS_ENABLED -mali_bool init_mali_dvfs_status(int step); -void deinit_mali_dvfs_status(void); -mali_bool mali_dvfs_handler(u32 utilization); -int mali_dvfs_is_running(void); -void mali_dvfs_late_resume(void); -int get_mali_dvfs_control_status(void); -mali_bool set_mali_dvfs_current_step(unsigned int step); -void mali_default_step_set(int step, mali_bool boostup); -int change_dvfs_tableset(int change_clk, int change_step); -#ifdef CONFIG_CPU_EXYNOS4210 -#if MALI_GPU_BOTTOM_LOCK -int mali_dvfs_bottom_lock_push(void); -int mali_dvfs_bottom_lock_pop(void); -#endif -#else -int mali_dvfs_bottom_lock_push(int lock_step); -int mali_dvfs_bottom_lock_pop(void); -#endif -#endif - -int mali_dvfs_get_vol(int step); - -#if MALI_VOLTAGE_LOCK -int mali_voltage_lock_push(int lock_vol); -int mali_voltage_lock_pop(void); -int mali_voltage_lock_init(void); -int mali_vol_get_from_table(int vol); -#endif - -#ifdef __cplusplus -} -#endif -#endif diff --git a/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c b/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c deleted file mode 100644 index cb95dc6..0000000 --- a/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" -#include "mali_pmu.h" -#include "linux/mali/mali_utgard.h" - -static u32 bPowerOff = 1; - -_mali_osk_errcode_t mali_platform_init(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit(void) -{ - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - switch (power_mode) - { - case MALI_POWER_MODE_ON: - if (bPowerOff == 1) - { - mali_pmu_powerup(); - bPowerOff = 0; - } - break; - case MALI_POWER_MODE_LIGHT_SLEEP: - case MALI_POWER_MODE_DEEP_SLEEP: - - if (bPowerOff == 0) - { - mali_pmu_powerdown(); - bPowerOff = 1; - } - - break; - } - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ -} - -void set_mali_parent_power_domain(void* dev) -{ -} - - diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c deleted file mode 100644 index 119831d..0000000 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include <linux/version.h> -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" -#include "mali_linux_pm.h" - -#if USING_MALI_PMM -#include "mali_pm.h" -#endif - -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/regulator/consumer.h> -#include <linux/regulator/driver.h> - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#include <plat/pd.h> -#endif - -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_kernel_profiling.h" -#endif - -#include <asm/io.h> -#include <mach/regs-pmu.h> - -#define EXTXTALCLK_NAME "ext_xtal" -#define VPLLSRCCLK_NAME "vpll_src" -#define FOUTVPLLCLK_NAME "fout_vpll" -#define SCLVPLLCLK_NAME "sclk_vpll" -#define GPUMOUT1CLK_NAME "mout_g3d1" - -#define MPLLCLK_NAME "mout_mpll" -#define GPUMOUT0CLK_NAME "mout_g3d0" -#define GPUCLK_NAME "sclk_g3d" -#define CLK_DIV_STAT_G3D 0x1003C62C -#define CLK_DESC "clk-divider-status" - -static struct clk *ext_xtal_clock = 0; -static struct clk *vpll_src_clock = 0; -static struct clk *fout_vpll_clock = 0; -static struct clk *sclk_vpll_clock = 0; - -static struct clk *mpll_clock = 0; -static struct clk *mali_parent_clock = 0; -static struct clk *mali_clock = 0; - -int mali_gpu_clk = 160; -static unsigned int GPU_MHZ = 1000000; -#ifdef CONFIG_S5PV310_ASV -int mali_gpu_vol = 1100000; /* 1.10V for ASV */ -#else -int mali_gpu_vol = 1100000; /* 1.10V */ -#endif - -#if MALI_DVFS_ENABLED -#define MALI_DVFS_DEFAULT_STEP 0 // 134Mhz default -#endif - -int gpu_power_state; -static int bPoweroff; - -#ifdef CONFIG_REGULATOR -struct regulator { - struct device *dev; - struct list_head list; - int uA_load; - int min_uV; - int max_uV; - char *supply_name; - struct device_attribute dev_attr; - struct regulator_dev *rdev; -}; - -struct regulator *g3d_regulator=NULL; -#endif - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) -extern struct platform_device s5pv310_device_pd[]; -#else -extern struct platform_device exynos4_device_pd[]; -#endif -#endif - -mali_io_address clk_register_map=0; - -#if MALI_GPU_BOTTOM_LOCK -_mali_osk_lock_t *mali_dvfs_lock; -#else -static _mali_osk_lock_t *mali_dvfs_lock; -#endif - -#ifdef CONFIG_REGULATOR -int mali_regulator_get_usecount(void) -{ - struct regulator_dev *rdev; - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n")); - return 0; - } - rdev = g3d_regulator->rdev; - return rdev->use_count; -} - -void mali_regulator_disable(void) -{ - bPoweroff = 1; - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); - return; - } - regulator_disable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount())); -} - -void mali_regulator_enable(void) -{ - bPoweroff = 0; - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); - return; - } - regulator_enable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); -} - -void mali_regulator_set_voltage(int min_uV, int max_uV) -{ - int voltage; - - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); - return; - } - MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, - min_uV, max_uV, 0, 0, 0); -#endif - - regulator_set_voltage(g3d_regulator,min_uV,max_uV); - voltage = regulator_get_voltage(g3d_regulator); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, - voltage, 0, 1, 0, 0); -#endif - mali_gpu_vol = voltage; - MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); -} -#endif - -unsigned long mali_clk_get_rate(void) -{ - return clk_get_rate(mali_clock); -} - -mali_bool mali_clk_get(mali_bool bis_vpll) -{ - if (bis_vpll == MALI_TRUE) - { - if (ext_xtal_clock == NULL) - { - ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME); - if (IS_ERR(ext_xtal_clock)) { - MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n")); - return MALI_FALSE; - } - } - - if (vpll_src_clock == NULL) - { - vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME); - if (IS_ERR(vpll_src_clock)) { - MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n")); - return MALI_FALSE; - } - } - - if (fout_vpll_clock == NULL) - { - fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME); - if (IS_ERR(fout_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (sclk_vpll_clock == NULL) - { - sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME); - if (IS_ERR(sclk_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - else // mpll - { - if (mpll_clock == NULL) - { - mpll_clock = clk_get(NULL,MPLLCLK_NAME); - - if (IS_ERR(mpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mpll clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - - // mali clock get always. - if (mali_clock == NULL) - { - mali_clock = clk_get(NULL, GPUCLK_NAME); - - if (IS_ERR(mali_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mali clock\n")); - return MALI_FALSE; - } - } - - return MALI_TRUE; -} - -void mali_clk_put(mali_bool binc_mali_clock) -{ - if (mali_parent_clock) - { - clk_put(mali_parent_clock); - mali_parent_clock = 0; - } - - if (mpll_clock) - { - clk_put(mpll_clock); - mpll_clock = 0; - } - - if (sclk_vpll_clock) - { - clk_put(sclk_vpll_clock); - sclk_vpll_clock = 0; - } - - if (fout_vpll_clock) - { - clk_put(fout_vpll_clock); - fout_vpll_clock = 0; - } - - if (vpll_src_clock) - { - clk_put(vpll_src_clock); - vpll_src_clock = 0; - } - - if (ext_xtal_clock) - { - clk_put(ext_xtal_clock); - ext_xtal_clock = 0; - } - - if (binc_mali_clock == MALI_TRUE && mali_clock) - { - clk_put(mali_clock); - mali_clock = 0; - } - -} - - -mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) -{ - unsigned long rate = 0; - mali_bool bis_vpll = MALI_FALSE; - -#ifdef CONFIG_VPLL_USE_FOR_TVENC - bis_vpll = MALI_TRUE; -#endif - - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if (mali_clk_get(bis_vpll) == MALI_FALSE) - return MALI_FALSE; - - rate = (unsigned long)clk * (unsigned long)mhz; - MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); - - if (bis_vpll) - { - clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); - clk_set_parent(vpll_src_clock, ext_xtal_clock); - clk_set_parent(sclk_vpll_clock, fout_vpll_clock); - - clk_set_parent(mali_parent_clock, sclk_vpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - else - { - clk_set_parent(mali_parent_clock, mpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - - if (clk_enable(mali_clock) < 0) - return MALI_FALSE; - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, - rate, 0, 0, 0, 0); -#endif - - clk_set_rate(mali_clock, rate); - rate = clk_get_rate(mali_clock); - -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, - rate, 0, 0, 0, 0); -#endif - - if (bis_vpll) - mali_gpu_clk = (int)(rate / mhz); - else - mali_gpu_clk = (int)((rate + 500000) / mhz); - - GPU_MHZ = mhz; - MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); - - mali_clk_put(MALI_FALSE); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - return MALI_TRUE; -} - -static mali_bool init_mali_clock(void) -{ - mali_bool ret = MALI_TRUE; - - gpu_power_state = 0; - - if (mali_clock != 0) - return ret; // already initialized - - mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE - | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); - if (mali_dvfs_lock == NULL) - return _MALI_OSK_ERR_FAULT; - - if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE) - { - ret = MALI_FALSE; - goto err_clock_get; - } - - MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock)); - - -#ifdef CONFIG_REGULATOR -#if USING_MALI_PMM - g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d"); -#else - g3d_regulator = regulator_get(NULL, "vdd_g3d"); -#endif - - if (IS_ERR(g3d_regulator)) - { - MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); - ret = MALI_FALSE; - goto err_regulator; - } - - regulator_enable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); - mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); -#endif - - MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); - MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); - MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); - - mali_clk_put(MALI_FALSE); - - return MALI_TRUE; - - -#ifdef CONFIG_REGULATOR -err_regulator: - regulator_put(g3d_regulator); -#endif - -err_clock_get: - mali_clk_put(MALI_TRUE); - - return ret; -} - -static mali_bool deinit_mali_clock(void) -{ - if (mali_clock == 0) - return MALI_TRUE; - -#ifdef CONFIG_REGULATOR - if (g3d_regulator) - { - regulator_put(g3d_regulator); - g3d_regulator=NULL; - } -#endif - - mali_clk_put(MALI_TRUE); - - return MALI_TRUE; -} - - -static _mali_osk_errcode_t enable_mali_clocks(void) -{ - int err; - err = clk_enable(mali_clock); - MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); - - // set clock rate - mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); - - MALI_SUCCESS; -} - -static _mali_osk_errcode_t disable_mali_clocks(void) -{ - clk_disable(mali_clock); - MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); - - MALI_SUCCESS; -} - -void set_mali_parent_power_domain(struct platform_device* dev) -{ -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) - dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev; -#else - dev->dev.parent = &exynos4_device_pd[PD_G3D].dev; -#endif - -#endif -} - -_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) -{ - if (bpower_on) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3,("_mali_osk_pm_dev_activate \n")); - _mali_osk_pm_dev_activate(); -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF); - status = S5P_PMU_G3D_CONF + 0x4; - - timeout = 10; - while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - != S5P_INT_LOCAL_PWR_EN) { - if (timeout == 0) { - MALI_PRINTF(("Power domain enable failed.\n")); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay(100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - else - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT( 4,("_mali_osk_pm_dev_idle\n")); - _mali_osk_pm_dev_idle(); - -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(0, S5P_PMU_G3D_CONF); - - status = S5P_PMU_G3D_CONF + 0x4; - /* Wait max 1ms */ - timeout = 10; - while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - { - if (timeout == 0) { - MALI_PRINTF(("Power domain disable failed.\n" )); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay( 100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_init() -{ - MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); -#if MALI_DVFS_ENABLED - if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); - if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) - MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit() -{ - deinit_mali_clock(); - -#if MALI_DVFS_ENABLED - deinit_mali_dvfs_status(); - if (clk_register_map ) - { - _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); - clk_register_map=0; - } -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerdown(u32 cores) -{ - MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state != 0) // power down after state is 0 - { - gpu_power_state = gpu_power_state & (~cores); - if (gpu_power_state == 0) - { - MALI_DEBUG_PRINT( 3,("disable clock\n")); - disable_mali_clocks(); - } - } - else - { - MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores)); - } - - bPoweroff=1; - - - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerup(u32 cores) -{ - MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state == 0) // power up only before state is 0 - { - gpu_power_state = gpu_power_state | cores; - - if (gpu_power_state != 0) - { - MALI_DEBUG_PRINT(4,("enable clock \n")); - enable_mali_clocks(); - } - } - else - { - gpu_power_state = gpu_power_state | cores; - } - - bPoweroff=0; - - - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ - if (bPoweroff==0) - { -#if MALI_DVFS_ENABLED - if(!mali_dvfs_handler(utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n")); -#endif - } -} - -#if MALI_POWER_MGMT_TEST_SUITE -u32 pmu_get_power_up_down_info(void) -{ - return 4095; -} - -#endif -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - MALI_SUCCESS; -} - diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c deleted file mode 100644 index 4efa759..0000000 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c +++ /dev/null @@ -1,448 +0,0 @@ -/* * Copyright (C) 2010-2012 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_platform_dvfs.c - * Platform specific Mali driver dvfs functions - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" - -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/regulator/consumer.h> -#include <linux/regulator/driver.h> - -#include <asm/io.h> - -#ifdef CONFIG_CPU_FREQ -#include <mach/asv.h> -#include <mach/regs-pmu.h> -#define EXYNOS4_ASV_ENABLED -#endif - -#include "mali_device_pause_resume.h" -#include <linux/workqueue.h> - -#define MALI_DVFS_WATING 10 // msec - -static int bMaliDvfsRun=0; - -#if MALI_GPU_BOTTOM_LOCK -static _mali_osk_atomic_t bottomlock_status; -#endif - -typedef struct mali_dvfs_tableTag{ - unsigned int clock; - unsigned int freq; - unsigned int vol; -}mali_dvfs_table; - -typedef struct mali_dvfs_statusTag{ - unsigned int currentStep; - mali_dvfs_table * pCurrentDvfs; - -}mali_dvfs_currentstatus; - -typedef struct mali_dvfs_thresholdTag{ - unsigned int downthreshold; - unsigned int upthreshold; -}mali_dvfs_threshold_table; - -typedef struct mali_dvfs_staycount{ - unsigned int staycount; -}mali_dvfs_staycount_table; - -mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ - /*step 0*/{1}, - /*step 1*/{1}, - /*step 2*/{1} }; - -/*dvfs threshold*/ -mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ - /*step 0*/{((int)((255*0)/100)) ,((int)((255*85)/100))}, - /*step 1*/{((int)((255*75)/100)) ,((int)((255*85)/100))}, - /*step 2*/{((int)((255*75)/100)) ,((int)((255*100)/100))} }; - -/*dvfs status*/ -mali_dvfs_currentstatus maliDvfsStatus; -int mali_dvfs_control=0; - -/*dvfs table*/ -mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ -#ifdef CONFIG_EXYNOS4210_1400MHZ_SUPPORT - /*step 0*/{134 ,1000000 , 950000}, -#else - /*step 0*/{100 ,1000000 , 950000}, -#endif - /*step 1*/{160 ,1000000 , 950000}, - /*step 2*/{267 ,1000000 ,1000000} }; - -#ifdef EXYNOS4_ASV_ENABLED - -#define ASV_8_LEVEL 8 -#define ASV_5_LEVEL 5 - -static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { - /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ - {1000000, 1000000, 1100000}, /* S */ - {1000000, 1000000, 1100000}, /* A */ - { 950000, 950000, 1000000}, /* B */ - { 950000, 950000, 1000000}, /* C */ - { 950000, 950000, 950000}, /* D */ -}; - -static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = { - /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */ - {1000000, 1000000, 1100000}, /* SS */ - {1000000, 1000000, 1100000}, /* A1 */ - {1000000, 1000000, 1100000}, /* A2 */ - { 950000, 950000, 1000000}, /* B1 */ - { 950000, 950000, 1000000}, /* B2 */ - { 950000, 950000, 1000000}, /* C1 */ - { 950000, 950000, 1000000}, /* C2 */ - { 950000, 950000, 950000}, /* D1 */ -}; -#endif - -static u32 mali_dvfs_utilization = 255; - -static void mali_dvfs_work_handler(struct work_struct *w); - -static struct workqueue_struct *mali_dvfs_wq = 0; -extern mali_io_address clk_register_map; - -#if MALI_GPU_BOTTOM_LOCK -extern _mali_osk_lock_t *mali_dvfs_lock; -#endif - -static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); - -static unsigned int get_mali_dvfs_status(void) -{ - return maliDvfsStatus.currentStep; -} - -#if MALI_GPU_BOTTOM_LOCK -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -int get_mali_dvfs_control_status(void) -{ - return mali_dvfs_control; -} - -mali_bool set_mali_dvfs_current_step(unsigned int step) -{ - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - maliDvfsStatus.currentStep = step; - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - return MALI_TRUE; -} -#endif -#endif - -static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) -{ - u32 validatedStep=step; - -#ifdef CONFIG_REGULATOR - if (mali_regulator_get_usecount()==0) { - MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); - return MALI_FALSE; - } -#endif - - if (boostup) { -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - } else { - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - } - - maliDvfsStatus.currentStep = validatedStep; - /*for future use*/ - maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; - - return MALI_TRUE; -} - -static void mali_platform_wating(u32 msec) -{ - /*sample wating - change this in the future with proper check routine. - */ - unsigned int read_val; - while(1) { - read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); - if ((read_val & 0x8000)==0x0000) break; - - _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 - } - /* _mali_osk_time_ubusydelay(msec*1000);*/ -} - -static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) -{ - - MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); - - if (!set_mali_dvfs_status(step, boostup)) { - MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); - return MALI_FALSE; - } - - /*wait until clock and voltage is stablized*/ - mali_platform_wating(MALI_DVFS_WATING); /*msec*/ - - return MALI_TRUE; -} - -static unsigned int decideNextStatus(unsigned int utilization) -{ - unsigned int level=0; // 0:stay, 1:up - - if (!mali_dvfs_control) { -#if MALI_GPU_BOTTOM_LOCK - if (_mali_osk_atomic_read(&bottomlock_status) > 0) - level = 1; /* or bigger */ - else -#endif - switch(maliDvfsStatus.currentStep) - { - case 0: - if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) - level=1; - else - level = maliDvfsStatus.currentStep; - break; - case 1: - if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) - level=2; - else if( utilization < - (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/ - mali_dvfs[maliDvfsStatus.currentStep].clock) - level=0; - else - level = maliDvfsStatus.currentStep; - break; - case 2: - if( utilization < - (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/ - mali_dvfs[maliDvfsStatus.currentStep].clock) - level=1; - else - level = maliDvfsStatus.currentStep; - break; - } - } - else - { - if((mali_dvfs_control == 1)||(( mali_dvfs_control > 3) && (mali_dvfs_control < mali_dvfs[0].clock+1))) - { - level=0; - } - else if((mali_dvfs_control == 2)||(( mali_dvfs_control > mali_dvfs[0].clock) && (mali_dvfs_control < mali_dvfs[1].clock+1))) - { - level=1; - } - else - { - level=2; - } - } - - return level; -} - -#ifdef EXYNOS4_ASV_ENABLED -static mali_bool mali_dvfs_table_update(void) -{ - unsigned int exynos_result_of_asv_group; - unsigned int target_asv; - unsigned int i; - exynos_result_of_asv_group = exynos_result_of_asv & 0xf; - target_asv = exynos_result_of_asv >> 28; - MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv)); - - if (target_asv == 0x8) { //SUPPORT_1400MHZ - for (i = 0; i < MALI_DVFS_STEPS; i++) { - mali_dvfs[i].vol = asv_3d_volt_5_table[exynos_result_of_asv_group][i]; - MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); - } - } else if (target_asv == 0x4){ //SUPPORT_1200MHZ - for (i = 0; i < MALI_DVFS_STEPS; i++) { - mali_dvfs[i].vol = asv_3d_volt_8_table[exynos_result_of_asv_group][i]; - MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); - } - } - - return MALI_TRUE; - -} -#endif - -static mali_bool mali_dvfs_status(u32 utilization) -{ - unsigned int nextStatus = 0; - unsigned int curStatus = 0; - mali_bool boostup = MALI_FALSE; -#ifdef EXYNOS4_ASV_ENABLED - static mali_bool asv_applied = MALI_FALSE; -#endif - static int stay_count = 0; // to prevent frequent switch - - MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); -#ifdef EXYNOS4_ASV_ENABLED - if (asv_applied == MALI_FALSE) { - mali_dvfs_table_update(); - change_mali_dvfs_status(0,0); - asv_applied = MALI_TRUE; - - return MALI_TRUE; - } -#endif - - /*decide next step*/ - curStatus = get_mali_dvfs_status(); - nextStatus = decideNextStatus(utilization); - - MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); - - /*if next status is same with current status, don't change anything*/ - if ((curStatus!=nextStatus && stay_count==0)) { - /*check if boost up or not*/ - if (nextStatus > maliDvfsStatus.currentStep) - boostup = 1; - - /*change mali dvfs status*/ - if (!change_mali_dvfs_status(nextStatus,boostup)) { - MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); - return MALI_FALSE; - } - stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; - } else { - if (stay_count>0) - stay_count--; - } - - return MALI_TRUE; -} - - - -int mali_dvfs_is_running(void) -{ - return bMaliDvfsRun; -} - - - -void mali_dvfs_late_resume(void) -{ - // set the init clock as low when resume - set_mali_dvfs_status(0,0); -} - - -static void mali_dvfs_work_handler(struct work_struct *w) -{ - bMaliDvfsRun=1; - - MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); - - if (!mali_dvfs_status(mali_dvfs_utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); - - bMaliDvfsRun=0; -} - - -mali_bool init_mali_dvfs_status(int step) -{ - /*default status - add here with the right function to get initilization value. - */ - if (!mali_dvfs_wq) - mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); - -#if MALI_GPU_BOTTOM_LOCK - _mali_osk_atomic_init(&bottomlock_status, 0); -#endif - - /*add a error handling here*/ - maliDvfsStatus.currentStep = step; - - return MALI_TRUE; -} - -void deinit_mali_dvfs_status(void) -{ -#if MALI_GPU_BOTTOM_LOCK - _mali_osk_atomic_term(&bottomlock_status); -#endif - - if (mali_dvfs_wq) - destroy_workqueue(mali_dvfs_wq); - mali_dvfs_wq = NULL; -} - -mali_bool mali_dvfs_handler(u32 utilization) -{ - mali_dvfs_utilization = utilization; - queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); - - /*add error handle here*/ - return MALI_TRUE; -} - -void mali_default_step_set(int step, mali_bool boostup) -{ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - - if (maliDvfsStatus.currentStep == 1) - set_mali_dvfs_status(step, boostup); -} - -#if MALI_GPU_BOTTOM_LOCK -int mali_dvfs_bottom_lock_push(void) -{ - int prev_status = _mali_osk_atomic_read(&bottomlock_status); - - if (prev_status < 0) { - MALI_PRINT(("gpu bottom lock status is not valid for push")); - return -1; - } - - if (prev_status == 0) { - mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol); - mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq); - set_mali_dvfs_current_step(1); - } - - return _mali_osk_atomic_inc_return(&bottomlock_status); -} - -int mali_dvfs_bottom_lock_pop(void) -{ - if (_mali_osk_atomic_read(&bottomlock_status) <= 0) { - MALI_PRINT(("gpu bottom lock status is not valid for pop")); - return -1; - } - - return _mali_osk_atomic_dec_return(&bottomlock_status); -} -#endif diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c deleted file mode 100644 index a08bc97..0000000 --- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c +++ /dev/null @@ -1,801 +0,0 @@ -/* Copyright (C) 2010-2012 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_platform.c - * Platform specific Mali driver functions for a default platform - */ -#include <linux/version.h> -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" -#include "mali_linux_pm.h" - -#if USING_MALI_PMM -#include "mali_pm.h" -#endif - -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/regulator/consumer.h> -#include <linux/regulator/driver.h> - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#include <plat/pd.h> -#endif - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -#include "mali_osk_profiling.h" -unsigned long gFreq = 366; -int gVolt = 5000; -#endif - -#include <asm/io.h> -#include <mach/regs-pmu.h> - -#define EXTXTALCLK_NAME "ext_xtal" -#define VPLLSRCCLK_NAME "vpll_src" -#define FOUTVPLLCLK_NAME "fout_vpll" -#define SCLVPLLCLK_NAME "sclk_vpll" -#define GPUMOUT1CLK_NAME "mout_g3d1" - -#define MPLLCLK_NAME "mout_mpll" -#define GPUMOUT0CLK_NAME "mout_g3d0" -#define GPUCLK_NAME "sclk_g3d" -#define CLK_DIV_STAT_G3D 0x1003C62C -#define CLK_DESC "clk-divider-status" - -#define MALI_BOTTOMLOCK_VOL 900000 - -typedef struct mali_runtime_resumeTag{ - int clk; - int vol; -}mali_runtime_resume_table; - -mali_runtime_resume_table mali_runtime_resume = {266, 900000}; - -/* lock/unlock CPU freq by Mali */ -extern int cpufreq_lock_by_mali(unsigned int freq); -extern void cpufreq_unlock_by_mali(void); - -/* start of modification by skkim */ -extern mali_bool init_mali_dvfs_status(int step); -extern void deinit_mali_dvfs_status(void); -extern mali_bool mali_dvfs_handler(u32 utilization); -extern int get_mali_dvfs_control_status(void); -extern mali_bool set_mali_dvfs_current_step(unsigned int step); -/* end of modification by skkim */ - -static struct clk *ext_xtal_clock = 0; -static struct clk *vpll_src_clock = 0; -static struct clk *fout_vpll_clock = 0; -static struct clk *sclk_vpll_clock = 0; - -static struct clk *mpll_clock = 0; -static struct clk *mali_parent_clock = 0; -static struct clk *mali_clock = 0; - - -static unsigned int GPU_MHZ = 1000000; - -int mali_gpu_clk = 266; -int mali_gpu_vol = 900000; - -#if MALI_DVFS_ENABLED -#define MALI_DVFS_DEFAULT_STEP 1 -#endif -#if MALI_VOLTAGE_LOCK -int mali_lock_vol = 0; -static _mali_osk_atomic_t voltage_lock_status; -static mali_bool mali_vol_lock_flag = 0; -#endif - -int gpu_power_state; -static int bPoweroff; - -#ifdef CONFIG_REGULATOR -struct regulator { - struct device *dev; - struct list_head list; - int uA_load; - int min_uV; - int max_uV; - char *supply_name; - struct device_attribute dev_attr; - struct regulator_dev *rdev; -}; - -struct regulator *g3d_regulator=NULL; -#endif - -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) -extern struct platform_device s5pv310_device_pd[]; -#else -extern struct platform_device exynos4_device_pd[]; -#endif -#endif - -mali_io_address clk_register_map=0; - -_mali_osk_lock_t *mali_dvfs_lock = 0; - -#ifdef CONFIG_REGULATOR -int mali_regulator_get_usecount(void) -{ - struct regulator_dev *rdev; - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n")); - return 0; - } - rdev = g3d_regulator->rdev; - return rdev->use_count; -} - -void mali_regulator_disable(void) -{ - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n")); - return; - } - regulator_disable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount())); - bPoweroff = 1; -} - -void mali_regulator_enable(void) -{ - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n")); - return; - } - regulator_enable(g3d_regulator); - MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); - bPoweroff = 0; -} - -void mali_regulator_set_voltage(int min_uV, int max_uV) -{ - int voltage; -#if !MALI_DVFS_ENABLED - min_uV = mali_gpu_vol; - max_uV = mali_gpu_vol; -#endif -#if MALI_VOLTAGE_LOCK - if (mali_vol_lock_flag == MALI_FALSE) { - if (min_uV < MALI_BOTTOMLOCK_VOL || max_uV < MALI_BOTTOMLOCK_VOL) { - min_uV = MALI_BOTTOMLOCK_VOL; - max_uV = MALI_BOTTOMLOCK_VOL; - } - } else if (_mali_osk_atomic_read(&voltage_lock_status) > 0 ) { - if (min_uV < mali_lock_vol || max_uV < mali_lock_vol) { -#if MALI_DVFS_ENABLED - int mali_vol_get; - mali_vol_get = mali_vol_get_from_table(mali_lock_vol); - if (mali_vol_get) { - min_uV = mali_vol_get; - max_uV = mali_vol_get; - } -#else - min_uV = mali_lock_vol; - max_uV = mali_lock_vol; -#endif - } - } -#endif - - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if( IS_ERR_OR_NULL(g3d_regulator) ) - { - MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n")); - return; - } - - MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); - - regulator_set_voltage(g3d_regulator,min_uV,max_uV); - voltage = regulator_get_voltage(g3d_regulator); - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - gVolt = voltage/1000; - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_GPU | - MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, gFreq, gVolt, - 0, 0, 0); -#endif - - mali_gpu_vol = voltage; - MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol)); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); -} -#endif - -unsigned long mali_clk_get_rate(void) -{ - return clk_get_rate(mali_clock); -} - -mali_bool mali_clk_get(mali_bool bis_vpll) -{ - if (bis_vpll == MALI_TRUE) - { - if (ext_xtal_clock == NULL) - { - ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME); - if (IS_ERR(ext_xtal_clock)) { - MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n")); - return MALI_FALSE; - } - } - - if (vpll_src_clock == NULL) - { - vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME); - if (IS_ERR(vpll_src_clock)) { - MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n")); - return MALI_FALSE; - } - } - - if (fout_vpll_clock == NULL) - { - fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME); - if (IS_ERR(fout_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (sclk_vpll_clock == NULL) - { - sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME); - if (IS_ERR(sclk_vpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - else // mpll - { - if (mpll_clock == NULL) - { - mpll_clock = clk_get(NULL,MPLLCLK_NAME); - - if (IS_ERR(mpll_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mpll clock\n")); - return MALI_FALSE; - } - } - - if (mali_parent_clock == NULL) - { - mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME); - - if (IS_ERR(mali_parent_clock)) { - MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); - return MALI_FALSE; - } - } - } - - // mali clock get always. - if (mali_clock == NULL) - { - mali_clock = clk_get(NULL, GPUCLK_NAME); - - if (IS_ERR(mali_clock)) { - MALI_PRINT( ("MALI Error : failed to get source mali clock\n")); - return MALI_FALSE; - } - } - - return MALI_TRUE; -} - -void mali_clk_put(mali_bool binc_mali_clock) -{ - if (mali_parent_clock) - { - clk_put(mali_parent_clock); - mali_parent_clock = 0; - } - - if (mpll_clock) - { - clk_put(mpll_clock); - mpll_clock = 0; - } - - if (sclk_vpll_clock) - { - clk_put(sclk_vpll_clock); - sclk_vpll_clock = 0; - } - - if (fout_vpll_clock) - { - clk_put(fout_vpll_clock); - fout_vpll_clock = 0; - } - - if (vpll_src_clock) - { - clk_put(vpll_src_clock); - vpll_src_clock = 0; - } - - if (ext_xtal_clock) - { - clk_put(ext_xtal_clock); - ext_xtal_clock = 0; - } - - if (binc_mali_clock == MALI_TRUE && mali_clock) - { - clk_put(mali_clock); - mali_clock = 0; - } - -} - - -mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) -{ - unsigned long rate = 0; - mali_bool bis_vpll = MALI_TRUE; - -#ifndef CONFIG_VPLL_USE_FOR_TVENC - bis_vpll = MALI_TRUE; -#endif - -#if !MALI_DVFS_ENABLED - clk = mali_gpu_clk; -#endif - trace_printk("SPI_GPUFREQ_%uMHz\n", mali_gpu_clk); - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - if (mali_clk_get(bis_vpll) == MALI_FALSE) - return MALI_FALSE; - - rate = (unsigned long)clk * (unsigned long)mhz; - MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz )); - - if (bis_vpll) - { - clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ); - clk_set_parent(vpll_src_clock, ext_xtal_clock); - clk_set_parent(sclk_vpll_clock, fout_vpll_clock); - - clk_set_parent(mali_parent_clock, sclk_vpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - else - { - clk_set_parent(mali_parent_clock, mpll_clock); - clk_set_parent(mali_clock, mali_parent_clock); - } - - if (clk_enable(mali_clock) < 0) - return MALI_FALSE; - - - clk_set_rate(mali_clock, rate); - rate = clk_get_rate(mali_clock); - -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - gFreq = rate/1000000; - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_GPU | - MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, - gFreq, gVolt, 0, 0, 0); -#endif - - if (bis_vpll) - mali_gpu_clk = (int)(rate / mhz); - else - mali_gpu_clk = (int)((rate + 500000) / mhz); - - GPU_MHZ = mhz; - MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk)); - - mali_clk_put(MALI_FALSE); - - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - - return MALI_TRUE; -} - -static mali_bool init_mali_clock(void) -{ - mali_bool ret = MALI_TRUE; - - if (mali_clock != 0) - return ret; // already initialized - - mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE - | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0); - if (mali_dvfs_lock == NULL) - return _MALI_OSK_ERR_FAULT; - - if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE) - { - ret = MALI_FALSE; - goto err_clock_get; - } - - MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock)); - - -#ifdef CONFIG_REGULATOR -#if USING_MALI_PMM - g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d"); -#else - g3d_regulator = regulator_get(NULL, "vdd_g3d"); -#endif - - if (IS_ERR(g3d_regulator)) - { - MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); - ret = MALI_FALSE; - goto err_regulator; - } - - regulator_enable(g3d_regulator); - - MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount())); - mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol); -#endif - - MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); - - MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); - MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); - - mali_clk_put(MALI_FALSE); - - gpu_power_state=0; - bPoweroff=1; - - return MALI_TRUE; -#ifdef CONFIG_REGULATOR -err_regulator: - regulator_put(g3d_regulator); -#endif - -err_clock_get: - mali_clk_put(MALI_TRUE); - - return ret; -} - -static mali_bool deinit_mali_clock(void) -{ - if (mali_clock == 0) - return MALI_TRUE; - -#ifdef CONFIG_REGULATOR - if (g3d_regulator) - { - regulator_put(g3d_regulator); - g3d_regulator=NULL; - } -#endif - - mali_clk_put(MALI_TRUE); - - return MALI_TRUE; -} -static _mali_osk_errcode_t enable_mali_clocks(void) -{ - int err; - err = clk_enable(mali_clock); - MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err)); - - mali_runtime_resume.vol = mali_dvfs_get_vol(MALI_DVFS_DEFAULT_STEP); -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if MALI_DVFS_ENABLED - // set clock rate - if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) - mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); - else { - mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); - mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); - set_mali_dvfs_current_step(MALI_DVFS_DEFAULT_STEP); - } -#if CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - if (mali_gpu_clk >= 440) - err = cpufreq_lock_by_mali(1200); -#endif -#else - mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol); - mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ); -#endif -#else - mali_clk_set_rate(mali_gpu_clk, GPU_MHZ); -#endif - MALI_SUCCESS; -} - -static _mali_osk_errcode_t disable_mali_clocks(void) -{ - clk_disable(mali_clock); - MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); - -#if MALI_DVFS_ENABLED && CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - cpufreq_unlock_by_mali(); -#endif - MALI_SUCCESS; -} - -void set_mali_parent_power_domain(struct platform_device* dev) -{ -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) - dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev; -#else - dev->dev.parent = &exynos4_device_pd[PD_G3D].dev; -#endif -#endif -} - -_mali_osk_errcode_t g3d_power_domain_control(int bpower_on) -{ - if (bpower_on) - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3,("_mali_osk_pmm_dev_activate \n")); - _mali_osk_pm_dev_activate(); -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF); - status = S5P_PMU_G3D_CONF + 0x4; - - timeout = 10; - while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - != S5P_INT_LOCAL_PWR_EN) { - if (timeout == 0) { - MALI_PRINTF(("Power domain enable failed.\n")); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay(100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - else - { -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT( 4,("_mali_osk_pmm_dev_idle\n")); - _mali_osk_pm_dev_idle(); -#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON - void __iomem *status; - u32 timeout; - __raw_writel(0, S5P_PMU_G3D_CONF); - - status = S5P_PMU_G3D_CONF + 0x4; - /* Wait max 1ms */ - timeout = 10; - while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN) - { - if (timeout == 0) { - MALI_PRINTF(("Power domain disable failed.\n" )); - return -ETIMEDOUT; - } - timeout--; - _mali_osk_time_ubusydelay( 100); - } -#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_init() -{ - MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT); -#if MALI_VOLTAGE_LOCK - _mali_osk_atomic_init(&voltage_lock_status, 0); -#endif -#if MALI_DVFS_ENABLED - if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); - if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) - MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_deinit() -{ - deinit_mali_clock(); -#if MALI_VOLTAGE_LOCK - _mali_osk_atomic_term(&voltage_lock_status); -#endif -#if MALI_DVFS_ENABLED - deinit_mali_dvfs_status(); - if (clk_register_map ) - { - _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map); - clk_register_map=0; - } -#endif - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerdown(u32 cores) -{ - trace_printk("SPI_GPU_PWR Idle\n"); - MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state != 0) // power down after state is 0 - { - gpu_power_state = gpu_power_state & (~cores); - if (gpu_power_state == 0) - { - MALI_DEBUG_PRINT( 3,("disable clock\n")); - disable_mali_clocks(); - } - } - else - { - MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores)); - } - - MALI_SUCCESS; -} - -_mali_osk_errcode_t mali_platform_powerup(u32 cores) -{ - trace_printk("SPI_GPU_PWR Start\n"); - MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); - - if (gpu_power_state == 0) // power up only before state is 0 - { - gpu_power_state = gpu_power_state | cores; - - if (gpu_power_state != 0) - { - MALI_DEBUG_PRINT(4,("enable clock \n")); - enable_mali_clocks(); - } - } - else - { - gpu_power_state = gpu_power_state | cores; - } - - MALI_SUCCESS; -} - -void mali_gpu_utilization_handler(u32 utilization) -{ - if (bPoweroff==0) - { -#if MALI_DVFS_ENABLED - if(!mali_dvfs_handler(utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n")); -#endif - } -} - -#if MALI_POWER_MGMT_TEST_SUITE -u32 pmu_get_power_up_down_info(void) -{ - return 4095; -} - -#endif - -_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode) -{ - switch (power_mode) - { - case MALI_POWER_MODE_ON: - MALI_DEBUG_PRINT(1, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", bPoweroff ? "powering on" : "already on")); - if (bPoweroff == 1) - { - /** If run time power management is used, donot call this function */ -#ifndef CONFIG_PM_RUNTIME - g3d_power_domain_control(1); -#endif - - MALI_DEBUG_PRINT(4,("enable clock \n")); - enable_mali_clocks(); -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0); -#endif - //MALI_PRINTF(("Mali Platform powered up")); - gpu_power_state=1; - bPoweroff=0; - } - break; - case MALI_POWER_MODE_LIGHT_SLEEP: - case MALI_POWER_MODE_DEEP_SLEEP: - MALI_DEBUG_PRINT(1, ("Mali platform: Got %s event, %s\n", - power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP", - bPoweroff ? "already off" : "powering off")); - if (bPoweroff == 0) - { - disable_mali_clocks(); -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0); -#endif - -#ifndef CONFIG_PM_RUNTIME - g3d_power_domain_control(0); -#endif - - //MALI_PRINTF(("Mali Platform powered down")); - gpu_power_state=0; - bPoweroff=1; - } - - break; - } - MALI_SUCCESS; -} - -#if MALI_VOLTAGE_LOCK -int mali_voltage_lock_push(int lock_vol) -{ - int prev_status = _mali_osk_atomic_read(&voltage_lock_status); - - if (prev_status < 0) { - MALI_PRINT(("gpu voltage lock status is not valid for push\n")); - return -1; - } - if (prev_status == 0) { - mali_lock_vol = lock_vol; - if (mali_gpu_vol < mali_lock_vol) - mali_regulator_set_voltage(mali_lock_vol, mali_lock_vol); - } else { - MALI_PRINT(("gpu voltage lock status is already pushed, current lock voltage : %d\n", mali_lock_vol)); - return -1; - } - - return _mali_osk_atomic_inc_return(&voltage_lock_status); -} - -int mali_voltage_lock_pop(void) -{ - if (_mali_osk_atomic_read(&voltage_lock_status) <= 0) { - MALI_PRINT(("gpu voltage lock status is not valid for pop\n")); - return -1; - } - return _mali_osk_atomic_dec_return(&voltage_lock_status); -} - -int mali_voltage_lock_init(void) -{ - mali_vol_lock_flag = MALI_TRUE; - - MALI_SUCCESS; -} -#endif diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c deleted file mode 100644 index cc1164e..0000000 --- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c +++ /dev/null @@ -1,847 +0,0 @@ -/* - * Copyright (C) 2010-2012 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_platform_dvfs.c - * Platform specific Mali driver dvfs functions - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_platform.h" - -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/regulator/consumer.h> -#include <linux/regulator/driver.h> - -#include <asm/io.h> - -#include "mali_device_pause_resume.h" -#include <linux/workqueue.h> - -#define MAX_MALI_DVFS_STEPS 5 -#define MALI_DVFS_WATING 10 // msec - -#ifdef CONFIG_CPU_FREQ -#include <mach/asv.h> -#define EXYNOS4_ASV_ENABLED -#endif - -#include <plat/cpu.h> - -static int bMaliDvfsRun=0; - -static _mali_osk_atomic_t bottomlock_status; -int bottom_lock_step = 0; - -typedef struct mali_dvfs_tableTag{ - unsigned int clock; - unsigned int freq; - unsigned int vol; -}mali_dvfs_table; - -typedef struct mali_dvfs_statusTag{ - unsigned int currentStep; - mali_dvfs_table * pCurrentDvfs; - -}mali_dvfs_currentstatus; - -typedef struct mali_dvfs_thresholdTag{ - unsigned int downthreshold; - unsigned int upthreshold; -}mali_dvfs_threshold_table; - -typedef struct mali_dvfs_staycount{ - unsigned int staycount; -}mali_dvfs_staycount_table; - -typedef struct mali_dvfs_stepTag{ - int clk; - int vol; -}mali_dvfs_step; - -mali_dvfs_step step[MALI_DVFS_STEPS]={ - /*step 0 clk*/ {160, 875000}, -#if (MALI_DVFS_STEPS > 1) - /*step 1 clk*/ {266, 900000}, -#if (MALI_DVFS_STEPS > 2) - /*step 2 clk*/ {350, 950000}, -#if (MALI_DVFS_STEPS > 3) - /*step 3 clk*/ {440, 1025000}, -#if (MALI_DVFS_STEPS > 4) - /*step 4 clk*/ {533, 1075000} -#endif -#endif -#endif -#endif -}; - -mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ - /*step 0*/{0}, -#if (MALI_DVFS_STEPS > 1) - /*step 1*/{0}, -#if (MALI_DVFS_STEPS > 2) - /*step 2*/{0}, -#if (MALI_DVFS_STEPS > 3) - /*step 3*/{0}, -#if (MALI_DVFS_STEPS > 4) - /*step 4*/{0} -#endif -#endif -#endif -#endif -}; - -/* dvfs information */ -// L0 = 533Mhz, 1.075V -// L1 = 440Mhz, 1.025V -// L2 = 350Mhz, 0.95V -// L3 = 266Mhz, 0.90V -// L4 = 160Mhz, 0.875V - -int step0_clk = 160; -int step0_vol = 875000; -#if (MALI_DVFS_STEPS > 1) -int step1_clk = 266; -int step1_vol = 900000; -int step0_up = 70; -int step1_down = 62; -#if (MALI_DVFS_STEPS > 2) -int step2_clk = 350; -int step2_vol = 950000; -int step1_up = 90; -int step2_down = 85; -#if (MALI_DVFS_STEPS > 3) -int step3_clk = 440; -int step3_vol = 1025000; -int step2_up = 90; -int step3_down = 85; -#if (MALI_DVFS_STEPS > 4) -int step4_clk = 533; -int step4_vol = 1075000; -int step3_up = 90; -int step4_down = 95; -#endif -#endif -#endif -#endif - -mali_dvfs_table mali_dvfs_all[MAX_MALI_DVFS_STEPS]={ - {160 ,1000000 , 875000}, - {266 ,1000000 , 900000}, - {350 ,1000000 , 950000}, - {440 ,1000000 , 1025000}, - {533 ,1000000 , 1075000} }; - -mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ - {160 ,1000000 , 875000}, -#if (MALI_DVFS_STEPS > 1) - {266 ,1000000 , 900000}, -#if (MALI_DVFS_STEPS > 2) - {350 ,1000000 , 950000}, -#if (MALI_DVFS_STEPS > 3) - {440 ,1000000 ,1025000}, -#if (MALI_DVFS_STEPS > 4) - {533 ,1000000 ,1075000} -#endif -#endif -#endif -#endif -}; - -mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ - {0 , 70}, -#if (MALI_DVFS_STEPS > 1) - {62 , 90}, -#if (MALI_DVFS_STEPS > 2) - {85 , 90}, -#if (MALI_DVFS_STEPS > 3) - {85 ,90}, -#if (MALI_DVFS_STEPS > 4) - {95 ,100} -#endif -#endif -#endif -#endif -}; - -#ifdef EXYNOS4_ASV_ENABLED -#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ -#define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ - -static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { - { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */ -#if (MALI_DVFS_STEPS > 1) - { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */ -#if (MALI_DVFS_STEPS > 2) - { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */ -#if (MALI_DVFS_STEPS > 3) - { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */ -#endif -#endif -#endif -}; - -static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = { - { 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */ -#if (MALI_DVFS_STEPS > 1) - { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */ -#if (MALI_DVFS_STEPS > 2) - { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */ -#if (MALI_DVFS_STEPS > 3) - { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */ -#endif -#endif -#endif -}; - -static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = { - { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000}, /* L4(160Mhz) */ -#if (MALI_DVFS_STEPS > 1) - { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 862500}, /* L3(266Mhz) */ -#if (MALI_DVFS_STEPS > 2) - { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500}, /* L2(350Mhz) */ -#if (MALI_DVFS_STEPS > 3) - { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000}, /* L1(440Mhz) */ -#if (MALI_DVFS_STEPS > 4) - { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(600Mhz) */ -#endif -#endif -#endif -#endif -}; -#endif /* ASV_LEVEL */ - -/*dvfs status*/ -mali_dvfs_currentstatus maliDvfsStatus; -int mali_dvfs_control=0; - -static u32 mali_dvfs_utilization = 255; - -static void mali_dvfs_work_handler(struct work_struct *w); - -static struct workqueue_struct *mali_dvfs_wq = 0; -extern mali_io_address clk_register_map; -extern _mali_osk_lock_t *mali_dvfs_lock; - -int mali_runtime_resumed = -1; - -static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); - -/* lock/unlock CPU freq by Mali */ -#include <linux/types.h> -#include <mach/cpufreq.h> - -atomic_t mali_cpufreq_lock; - -int cpufreq_lock_by_mali(unsigned int freq) -{ -#ifdef CONFIG_EXYNOS4_CPUFREQ -/* #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_ARCH_EXYNOS4) */ - unsigned int level; - - if (atomic_read(&mali_cpufreq_lock) == 0) { - if (exynos_cpufreq_get_level(freq * 1000, &level)) { - printk(KERN_ERR - "Mali: failed to get cpufreq level for %dMHz", - freq); - return -EINVAL; - } - - if (exynos_cpufreq_lock(DVFS_LOCK_ID_G3D, level)) { - printk(KERN_ERR - "Mali: failed to cpufreq lock for L%d", level); - return -EINVAL; - } - - atomic_set(&mali_cpufreq_lock, 1); - printk(KERN_DEBUG "Mali: cpufreq locked on <%d>%dMHz\n", level, - freq); - } -#endif - return 0; -} - -void cpufreq_unlock_by_mali(void) -{ -#ifdef CONFIG_EXYNOS4_CPUFREQ -/* #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_ARCH_EXYNOS4) */ - if (atomic_read(&mali_cpufreq_lock) == 1) { - exynos_cpufreq_lock_free(DVFS_LOCK_ID_G3D); - atomic_set(&mali_cpufreq_lock, 0); - printk(KERN_DEBUG "Mali: cpufreq locked off\n"); - } -#endif -} - -static unsigned int get_mali_dvfs_status(void) -{ - return maliDvfsStatus.currentStep; -} -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON -int get_mali_dvfs_control_status(void) -{ - return mali_dvfs_control; -} - -mali_bool set_mali_dvfs_current_step(unsigned int step) -{ - _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - maliDvfsStatus.currentStep = step % MAX_MALI_DVFS_STEPS; - if (step >= MAX_MALI_DVFS_STEPS) - mali_runtime_resumed = maliDvfsStatus.currentStep; - _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - return MALI_TRUE; -} -#endif -static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) -{ - u32 validatedStep=step; - int err; - -#ifdef CONFIG_REGULATOR - if (mali_regulator_get_usecount() == 0) { - MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); - return MALI_FALSE; - } -#endif - - if (boostup) { -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - } else { - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); -#endif - } - -#ifdef EXYNOS4_ASV_ENABLED - if (samsung_rev() < EXYNOS4412_REV_2_0) { - if (mali_dvfs[step].clock == 160) - exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); - else - exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); - } -#endif - - - set_mali_dvfs_current_step(validatedStep); - /*for future use*/ - maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; - -#if CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - if (mali_dvfs[step].clock == 440) - err = cpufreq_lock_by_mali(1200); - else - cpufreq_unlock_by_mali(); -#endif - - return MALI_TRUE; -} - -static void mali_platform_wating(u32 msec) -{ - /*sample wating - change this in the future with proper check routine. - */ - unsigned int read_val; - while(1) { - read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); - if ((read_val & 0x8000)==0x0000) break; - _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 - } - /* _mali_osk_time_ubusydelay(msec*1000);*/ -} - -static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) -{ - - MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); - - if (!set_mali_dvfs_status(step, boostup)) { - MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); - return MALI_FALSE; - } - - /*wait until clock and voltage is stablized*/ - mali_platform_wating(MALI_DVFS_WATING); /*msec*/ - - return MALI_TRUE; -} - -#ifdef EXYNOS4_ASV_ENABLED -extern unsigned int exynos_result_of_asv; - -static mali_bool mali_dvfs_table_update(void) -{ - unsigned int i; - unsigned int step_num = MALI_DVFS_STEPS; - - if(samsung_rev() < EXYNOS4412_REV_2_0) - step_num = MALI_DVFS_STEPS - 1; - - if(soc_is_exynos4412()) { - if (exynos_armclk_max == 1000000) { - MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); - } - } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) { - MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol)); - } - } else if (samsung_rev() >= EXYNOS4412_REV_2_0) { - MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); - } - } else { - MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv)); - for (i = 0; i < step_num; i++) { - mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); - } - } - } - - return MALI_TRUE; -} -#endif - -static unsigned int decideNextStatus(unsigned int utilization) -{ - static unsigned int level = 0; // 0:stay, 1:up - static int mali_dvfs_clk = 0; - - if (mali_runtime_resumed >= 0) { - level = mali_runtime_resumed; - mali_runtime_resumed = -1; - } - - if (mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold - <= mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold) { - MALI_PRINT(("upthreadshold is smaller than downthreshold: %d < %d\n", - mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold, - mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold)); - return level; - } - - if (!mali_dvfs_control && level == maliDvfsStatus.currentStep) { - if (utilization > (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold / 100) && - level < MALI_DVFS_STEPS - 1) { - level++; - if ((samsung_rev() < EXYNOS4412_REV_2_0) && (maliDvfsStatus.currentStep == 3)) { - level=get_mali_dvfs_status(); - } - } - if (utilization < (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold / 100) && - level > 0) { - level--; - } - } else if (mali_dvfs_control == 999) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[i].clock; - } -#ifdef EXYNOS4_ASV_ENABLED - mali_dvfs_table_update(); -#endif - i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - mali_dvfs[i].clock = step[i].clk; - } - mali_dvfs_control = 0; - level = 0; - - step0_clk = step[0].clk; - change_dvfs_tableset(step0_clk, 0); -#if (MALI_DVFS_STEPS > 1) - step1_clk = step[1].clk; - change_dvfs_tableset(step1_clk, 1); -#if (MALI_DVFS_STEPS > 2) - step2_clk = step[2].clk; - change_dvfs_tableset(step2_clk, 2); -#if (MALI_DVFS_STEPS > 3) - step3_clk = step[3].clk; - change_dvfs_tableset(step3_clk, 3); -#if (MALI_DVFS_STEPS > 4) - step4_clk = step[4].clk; - change_dvfs_tableset(step4_clk, 4); -#endif -#endif -#endif -#endif - } else if (mali_dvfs_control != mali_dvfs_clk && mali_dvfs_control != 999) { - if (mali_dvfs_control < mali_dvfs_all[1].clock && mali_dvfs_control > 0) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[0].clock; - } - maliDvfsStatus.currentStep = 0; - } else if (mali_dvfs_control < mali_dvfs_all[2].clock && mali_dvfs_control >= mali_dvfs_all[1].clock) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[1].clock; - } - maliDvfsStatus.currentStep = 1; - } else if (mali_dvfs_control < mali_dvfs_all[3].clock && mali_dvfs_control >= mali_dvfs_all[2].clock) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[2].clock; - } - maliDvfsStatus.currentStep = 2; - } else if (mali_dvfs_control < mali_dvfs_all[4].clock && mali_dvfs_control >= mali_dvfs_all[3].clock) { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[3].clock; - } - maliDvfsStatus.currentStep = 3; - } else { - int i = 0; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - step[i].clk = mali_dvfs_all[4].clock; - } - maliDvfsStatus.currentStep = 4; - } - step0_clk = step[0].clk; - change_dvfs_tableset(step0_clk, 0); -#if (MALI_DVFS_STEPS > 1) - step1_clk = step[1].clk; - change_dvfs_tableset(step1_clk, 1); -#if (MALI_DVFS_STEPS > 2) - step2_clk = step[2].clk; - change_dvfs_tableset(step2_clk, 2); -#if (MALI_DVFS_STEPS > 3) - step3_clk = step[3].clk; - change_dvfs_tableset(step3_clk, 3); -#if (MALI_DVFS_STEPS > 4) - step4_clk = step[4].clk; - change_dvfs_tableset(step4_clk, 4); -#endif -#endif -#endif -#endif - level = maliDvfsStatus.currentStep; - } - - mali_dvfs_clk = mali_dvfs_control; - - if (_mali_osk_atomic_read(&bottomlock_status) > 0) { - if (level < bottom_lock_step) - level = bottom_lock_step; - } - - return level; -} - -static mali_bool mali_dvfs_status(u32 utilization) -{ - unsigned int nextStatus = 0; - unsigned int curStatus = 0; - mali_bool boostup = MALI_FALSE; - static int stay_count = 0; -#ifdef EXYNOS4_ASV_ENABLED - static mali_bool asv_applied = MALI_FALSE; -#endif - - MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); -#ifdef EXYNOS4_ASV_ENABLED - if (asv_applied == MALI_FALSE) { - mali_dvfs_table_update(); - change_mali_dvfs_status(1, 0); - asv_applied = MALI_TRUE; - - return MALI_TRUE; - } -#endif - - /*decide next step*/ - curStatus = get_mali_dvfs_status(); - nextStatus = decideNextStatus(utilization); - - MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); - - /*if next status is same with current status, don't change anything*/ - if ((curStatus != nextStatus && stay_count == 0)) { - /*check if boost up or not*/ - if (nextStatus > maliDvfsStatus.currentStep) boostup = 1; - - /*change mali dvfs status*/ - if (!change_mali_dvfs_status(nextStatus,boostup)) { - MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); - return MALI_FALSE; - } - stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; - } else { - if (stay_count > 0) - stay_count--; - } - - return MALI_TRUE; -} - - - -int mali_dvfs_is_running(void) -{ - return bMaliDvfsRun; - -} - - - -void mali_dvfs_late_resume(void) -{ - // set the init clock as low when resume - set_mali_dvfs_status(0,0); -} - - -static void mali_dvfs_work_handler(struct work_struct *w) -{ - int change_clk = 0; - int change_step = 0; - bMaliDvfsRun=1; - - /* dvfs table change when clock was changed */ - if (step0_clk != mali_dvfs[0].clock) { - MALI_PRINT(("::: step0_clk change to %d Mhz\n", step0_clk)); - change_clk = step0_clk; - change_step = 0; - step0_clk = change_dvfs_tableset(change_clk, change_step); - } -#if (MALI_DVFS_STEPS > 1) - if (step1_clk != mali_dvfs[1].clock) { - MALI_PRINT(("::: step1_clk change to %d Mhz\n", step1_clk)); - change_clk = step1_clk; - change_step = 1; - step1_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step0_up != mali_dvfs_threshold[0].upthreshold) { - MALI_PRINT(("::: step0_up change to %d %\n", step0_up)); - mali_dvfs_threshold[0].upthreshold = step0_up; - } - if (step1_down != mali_dvfs_threshold[1].downthreshold) { - MALI_PRINT((":::step1_down change to %d %\n", step1_down)); - mali_dvfs_threshold[1].downthreshold = step1_down; - } -#if (MALI_DVFS_STEPS > 2) - if (step2_clk != mali_dvfs[2].clock) { - MALI_PRINT(("::: step2_clk change to %d Mhz\n", step2_clk)); - change_clk = step2_clk; - change_step = 2; - step2_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step1_up != mali_dvfs_threshold[1].upthreshold) { - MALI_PRINT((":::step1_up change to %d %\n", step1_up)); - mali_dvfs_threshold[1].upthreshold = step1_up; - } - if (step2_down != mali_dvfs_threshold[2].downthreshold) { - MALI_PRINT((":::step2_down change to %d %\n", step2_down)); - mali_dvfs_threshold[2].downthreshold = step2_down; - } -#if (MALI_DVFS_STEPS > 3) - if (step3_clk != mali_dvfs[3].clock) { - MALI_PRINT(("::: step3_clk change to %d Mhz\n", step3_clk)); - change_clk = step3_clk; - change_step = 3; - step3_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step2_up != mali_dvfs_threshold[2].upthreshold) { - MALI_PRINT((":::step2_up change to %d %\n", step2_up)); - mali_dvfs_threshold[2].upthreshold = step2_up; - } - if (step3_down != mali_dvfs_threshold[3].downthreshold) { - MALI_PRINT((":::step3_down change to %d %\n", step3_down)); - mali_dvfs_threshold[3].downthreshold = step3_down; - } -#if (MALI_DVFS_STEPS > 4) - if (step4_clk != mali_dvfs[4].clock) { - MALI_PRINT(("::: step4_clk change to %d Mhz\n", step4_clk)); - change_clk = step4_clk; - change_step = 4; - step4_clk = change_dvfs_tableset(change_clk, change_step); - } - if (step3_up != mali_dvfs_threshold[3].upthreshold) { - MALI_PRINT((":::step3_up change to %d %\n", step3_up)); - mali_dvfs_threshold[3].upthreshold = step3_up; - } - if (step4_down != mali_dvfs_threshold[4].downthreshold) { - MALI_PRINT((":::step4_down change to %d %\n", step4_down)); - mali_dvfs_threshold[4].downthreshold = step4_down; - } -#endif -#endif -#endif -#endif - - -#ifdef DEBUG - mali_dvfs[0].vol = step0_vol; - mali_dvfs[1].vol = step1_vol; - mali_dvfs[2].vol = step2_vol; - mali_dvfs[3].vol = step3_vol; - mali_dvfs[4].vol = step4_vol; -#endif - MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); - - if (!mali_dvfs_status(mali_dvfs_utilization)) - MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); - - bMaliDvfsRun=0; -} - -mali_bool init_mali_dvfs_status(int step) -{ - /*default status - add here with the right function to get initilization value. - */ - if (!mali_dvfs_wq) - mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); - - _mali_osk_atomic_init(&bottomlock_status, 0); - - /*add a error handling here*/ - set_mali_dvfs_current_step(step); - - return MALI_TRUE; -} - -void deinit_mali_dvfs_status(void) -{ - if (mali_dvfs_wq) - destroy_workqueue(mali_dvfs_wq); - - _mali_osk_atomic_term(&bottomlock_status); - - mali_dvfs_wq = NULL; -} - -mali_bool mali_dvfs_handler(u32 utilization) -{ - mali_dvfs_utilization = utilization; - queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); - - /*add error handle here*/ - return MALI_TRUE; -} - -int change_dvfs_tableset(int change_clk, int change_step) -{ - int err; - - if (change_clk < mali_dvfs_all[1].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[0].clock; - } else if (change_clk < mali_dvfs_all[2].clock && change_clk >= mali_dvfs_all[1].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[1].clock; - } else if (change_clk < mali_dvfs_all[3].clock && change_clk >= mali_dvfs_all[2].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[2].clock; - } else if (change_clk < mali_dvfs_all[4].clock && change_clk >= mali_dvfs_all[3].clock) { - mali_dvfs[change_step].clock = mali_dvfs_all[3].clock; - } else { - mali_dvfs[change_step].clock = mali_dvfs_all[4].clock; - } - - MALI_PRINT((":::mali dvfs step %d clock and voltage = %d Mhz, %d V\n",change_step, mali_dvfs[change_step].clock, mali_dvfs[change_step].vol)); - - if (maliDvfsStatus.currentStep == change_step) { -#ifdef CONFIG_REGULATOR - /*change the voltage*/ - mali_regulator_set_voltage(mali_dvfs[change_step].vol, mali_dvfs[change_step].vol); -#endif - /*change the clock*/ - mali_clk_set_rate(mali_dvfs[change_step].clock, mali_dvfs[change_step].freq); - -#if CPUFREQ_LOCK_DURING_440 - /* lock/unlock CPU freq by Mali */ - if (mali_dvfs[change_step].clock == 440) - err = cpufreq_lock_by_mali(1200); - else - cpufreq_unlock_by_mali(); -#endif - } - - return mali_dvfs[change_step].clock; -} - -void mali_default_step_set(int step, mali_bool boostup) -{ - mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); - - if (maliDvfsStatus.currentStep == 1) - set_mali_dvfs_status(step, boostup); -} - -int mali_dvfs_bottom_lock_push(int lock_step) -{ - int prev_status = _mali_osk_atomic_read(&bottomlock_status); - - if (prev_status < 0) { - MALI_PRINT(("gpu bottom lock status is not valid for push\n")); - return -1; - } - if (bottom_lock_step < lock_step) { - bottom_lock_step = lock_step; - if (get_mali_dvfs_status() < lock_step) { - mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol); - mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq); - set_mali_dvfs_current_step(lock_step); - } - } - return _mali_osk_atomic_inc_return(&bottomlock_status); -} - -int mali_dvfs_bottom_lock_pop(void) -{ - int prev_status = _mali_osk_atomic_read(&bottomlock_status); - if (prev_status <= 0) { - MALI_PRINT(("gpu bottom lock status is not valid for pop\n")); - return -1; - } else if (prev_status == 1) { - bottom_lock_step = 0; - MALI_PRINT(("gpu bottom lock release\n")); - } - - return _mali_osk_atomic_dec_return(&bottomlock_status); -} - -int mali_dvfs_get_vol(int step) -{ - step = step % MAX_MALI_DVFS_STEPS; - MALI_DEBUG_ASSERT(step<MAX_MALI_DVFS_STEPS); - - return mali_dvfs[step].vol; -} - -#if MALI_VOLTAGE_LOCK -int mali_vol_get_from_table(int vol) -{ - int i; - for (i = 0; i < MALI_DVFS_STEPS; i++) { - if (mali_dvfs[i].vol >= vol) - return mali_dvfs[i].vol; - } - MALI_PRINT(("Failed to get voltage from mali_dvfs table, maximum voltage is %d uV\n", mali_dvfs[MALI_DVFS_STEPS-1].vol)); - return 0; -} -#endif diff --git a/drivers/media/video/samsung/ump/Kconfig b/drivers/media/video/samsung/ump/Kconfig deleted file mode 100644 index 9d8e5e6..0000000 --- a/drivers/media/video/samsung/ump/Kconfig +++ /dev/null @@ -1,58 +0,0 @@ - -# -## S3C Multimedia Mali configuration -## -# -# For UMP -config VIDEO_UMP - bool "Enable UMP(Unified Memory Provider)" - default y - ---help--- - This enables UMP memory provider - -config UMP_VCM_ALLOC - depends on VIDEO_UMP && VCM - default y - bool "Enable ump-vcm(virtual contiguous memory) memory" - help - Use VCM(virtual-contiguous-memory) to allocate physical memory. - - -config UMP_R3P1_LSI - bool "Uses the R3P1 as a ump module" - depends on VIDEO_UMP - default n - ---help--- - This uses the r3p1 as a UMP kernel module - -choice -depends on VIDEO_UMP -prompt "UMP MEMEMORY OPTION" -default UMP_OSMEM_ONLY -config UMP_DED_ONLY - bool "ump dedicated memory only" - ---help--- - This enables UMP dedicated memory only option -config UMP_OSMEM_ONLY - bool "ump OS memory only" - ---help--- - This enables UMP OS memory only option -config UMP_VCM_ONLY - bool "ump VCM memory" - ---help--- - This enables UMP VCM memory only option - -endchoice -config UMP_MEM_SIZE -int "UMP Memory Size" - depends on VIDEO_UMP - default "512" - ---help--- - This value is dedicated memory size of UMP (unit is MByte). -# For UMP_DEBUG -config VIDEO_UMP_DEBUG - bool "Enables debug messages" - depends on VIDEO_UMP - default n - help - This enables UMP driver debug messages. diff --git a/drivers/media/video/samsung/ump/Kconfig_module b/drivers/media/video/samsung/ump/Kconfig_module deleted file mode 100644 index 3ae316c..0000000 --- a/drivers/media/video/samsung/ump/Kconfig_module +++ /dev/null @@ -1,16 +0,0 @@ -config UMP - tristate "UMP support" - depends on ARM - ---help--- - This enables support for the UMP memory allocation and sharing API. - - To compile this driver as a module, choose M here: the module will be - called ump. - -config UMP_DEBUG - bool "Enable extra debug in UMP" - depends on UMP - default y - ---help--- - This enabled extra debug checks and messages in UMP. - diff --git a/drivers/media/video/samsung/ump/Makefile b/drivers/media/video/samsung/ump/Makefile deleted file mode 100644 index 3a1aac0..0000000 --- a/drivers/media/video/samsung/ump/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (C) 2010-2012 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. -# - -ifeq ($(CONFIG_UMP_DED_ONLY),y) -UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) -USING_MEMORY=0 -endif - -ifeq ($(CONFIG_UMP_OSMEM_ONLY),y) -UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) -USING_MEMORY=1 -endif - -ifeq ($(CONFIG_UMP_VCM_ONLY),y) -UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) -USING_MEMORY=2 -endif - - -# For UMP Debug -ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) -DEFINES += -DDEBUG -endif - -# Set up our defines, which will be passed to gcc -DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER -DEFINES += -DUSING_MEMORY=$(USING_MEMORY) -DEFINES += -DUMP_MEM_SIZE=$(UMP_MEM_SIZE) -DEFINES += -DMALI_STATE_TRACKING=1 - -UDD_FILE_PREFIX := drivers/media/video/samsung/ump/ -KBUILDROOT = - -# linux build system integration - -obj-$(CONFIG_VIDEO_UMP) += ump.o - -# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: -# The ARM proprietary product will only include the license/proprietary directory -# The GPL product will only include the license/gpl directory - -INCLUDES += \ - -I$(UDD_FILE_PREFIX)\ - -I$(UDD_FILE_PREFIX)common\ - -I$(UDD_FILE_PREFIX)linux\ - -I$(UDD_FILE_PREFIX)include\ - -I$(UDD_FILE_PREFIX)linux/license/gpl/\ - -I$(UDD_FILE_PREFIX)../mali/common\ - -I$(UDD_FILE_PREFIX)../mali/linux - -OSKFILES+=\ - $(KBUILDROOT)../mali/linux/mali_osk_atomics.o \ - $(KBUILDROOT)../mali/linux/mali_osk_locks.o \ - $(KBUILDROOT)../mali/linux/mali_osk_math.o \ - $(KBUILDROOT)../mali/linux/mali_osk_memory.o \ - $(KBUILDROOT)../mali/linux/mali_osk_misc.o - -ump-y := \ - $(KBUILDROOT)linux/ump_kernel_linux.o \ - $(KBUILDROOT)linux/ump_kernel_memory_backend_os.o \ - $(KBUILDROOT)linux/ump_kernel_memory_backend_dedicated.o \ - $(KBUILDROOT)linux/ump_memory_backend.o \ - $(KBUILDROOT)linux/ump_ukk_wrappers.o \ - $(KBUILDROOT)linux/ump_ukk_ref_wrappers.o \ - $(KBUILDROOT)linux/ump_osk_atomics.o \ - $(KBUILDROOT)linux/ump_osk_low_level_mem.o \ - $(KBUILDROOT)linux/ump_osk_misc.o \ - $(KBUILDROOT)common/ump_kernel_common.o \ - $(KBUILDROOT)common/ump_kernel_descriptor_mapping.o \ - $(KBUILDROOT)common/ump_kernel_api.o \ - $(KBUILDROOT)common/ump_kernel_ref_drv.o\ - $(OSKFILES) - -ump-$(CONFIG_UMP_VCM_ALLOC) += \ - $(KBUILDROOT)linux/ump_kernel_memory_backend_vcm.o \ - -EXTRA_CFLAGS += $(INCLUDES) \ - $(DEFINES) - - -# Get subversion revision number, fall back to 0000 if no svn info is available -SVN_REV:=$(shell ((svnversion | grep -E "^[0-9]+" && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //') - -EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV) -EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\" - diff --git a/drivers/media/video/samsung/ump/arch b/drivers/media/video/samsung/ump/arch deleted file mode 120000 index 58ffbe7..0000000 --- a/drivers/media/video/samsung/ump/arch +++ /dev/null @@ -1 +0,0 @@ -arch-release
\ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-debug b/drivers/media/video/samsung/ump/arch-debug deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/ump/arch-debug +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/
\ No newline at end of file diff --git a/drivers/media/video/samsung/ump/arch-release b/drivers/media/video/samsung/ump/arch-release deleted file mode 120000 index 0ed0909..0000000 --- a/drivers/media/video/samsung/ump/arch-release +++ /dev/null @@ -1 +0,0 @@ -arch-pegasus-m400/
\ No newline at end of file diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c deleted file mode 100644 index 46797ea..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2010-2012 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. - */ - -/* create by boojin.kim@samsung.com */ -/* needed to detect kernel version specific code */ -#include <linux/version.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/mm.h> -#include <linux/slab.h> -#include <asm/atomic.h> -#include <linux/vmalloc.h> -#include <asm/cacheflush.h> -#include "ump_kernel_common.h" -#include "ump_kernel_memory_backend.h" -#include "ump_kernel_interface_ref_drv.h" -#include "ump_kernel_memory_backend_vcm.h" -#include "../common/ump_uk_types.h" -#include <linux/vcm-drv.h> -#include <plat/s5p-vcm.h> -#include <linux/dma-mapping.h> - -#define UMP_REF_DRV_UK_VCM_DEV_G2D 12 - -typedef struct ump_vcm { - struct vcm *vcm; - struct vcm_res *vcm_res; - unsigned int dev_id; -} ump_vcm; - -typedef struct vcm_allocator { - struct semaphore mutex; - u32 num_vcm_blocks; -} vcm_allocator; - -static void ump_vcm_free(void* ctx, ump_dd_mem * descriptor); -static int ump_vcm_allocate(void* ctx, ump_dd_mem * descriptor); -static void *vcm_res_get(ump_dd_mem *mem, void* args); -static void vcm_attr_set(ump_dd_mem *mem, void* args); -static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor); -static void vcm_memory_backend_destroy(ump_memory_backend * backend); - - -/* - * Create VCM memory backend - */ -ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation) -{ - ump_memory_backend * backend; - vcm_allocator * info; - - info = kmalloc(sizeof(vcm_allocator), GFP_KERNEL); - if (NULL == info) - { - return NULL; - } - - info->num_vcm_blocks = 0; - - - sema_init(&info->mutex, 1); - - backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); - if (NULL == backend) - { - kfree(info); - return NULL; - } - - backend->ctx = info; - backend->allocate = ump_vcm_allocate; - backend->release = ump_vcm_free; - backend->shutdown = vcm_memory_backend_destroy; - backend->pre_allocate_physical_check = NULL; - backend->adjust_to_mali_phys = NULL; - - backend->get = vcm_res_get; - backend->set = vcm_attr_set; - - - return backend; -} - -/* - * Destroy specified VCM memory backend - */ -static void vcm_memory_backend_destroy(ump_memory_backend * backend) -{ - vcm_allocator * info = (vcm_allocator*)backend->ctx; -#if 0 - DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); -#endif - kfree(info); - kfree(backend); -} - -/* - * Allocate UMP memory - */ -static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor) -{ - int ret; /* success */ - vcm_allocator *info; - struct ump_vcm *ump_vcm; - - BUG_ON(!descriptor); - BUG_ON(!ctx); - - info = (vcm_allocator*)ctx; - - ump_vcm = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); - if (NULL == ump_vcm) - { - return 0; - } - - ump_vcm->dev_id = (int)descriptor->backend_info & ~UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE; - - if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */ - ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */ - } - else if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR) { /* Physical Linear */ - return 0; - } - else { /* Other VCM */ - ump_vcm->dev_id -= 2; - } - - DBG_MSG(5, ("Device ID for VCM : %d\n", ump_vcm->dev_id)); - ump_vcm->vcm = vcm_find_vcm(ump_vcm->dev_id); - - if (!ump_vcm->vcm) - { - return 0; - } - descriptor->backend_info = (void*)ump_vcm; - - if (down_interruptible(&info->mutex)) { - DBG_MSG(1, ("Failed to get mutex in ump_vcm_allocate\n")); - return 0; /* failure */ - } - - ret = vcm_mem_allocator(info, descriptor); - up(&info->mutex); - - return ret; /* success */ -} - -static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor) -{ - unsigned long num_blocks; - int i; - struct vcm_phys *phys; - struct vcm_phys_part *part; - int size_total = 0; - struct ump_vcm *ump_vcm; - - ump_vcm = (struct ump_vcm*)descriptor->backend_info; - - ump_vcm->vcm_res = - vcm_make_binding(ump_vcm->vcm, descriptor->size_bytes, - ump_vcm->dev_id, 0); - - phys = ump_vcm->vcm_res->phys; - part = phys->parts; - num_blocks = phys->count; - - DBG_MSG(5, - ("Allocating page array. Size: %lu, VCM Reservation : 0x%x\n", - phys->count * sizeof(ump_dd_physical_block), - ump_vcm->vcm_res->start)); - - /* Now, make a copy of the block information supplied by the user */ - descriptor->block_array = - (ump_dd_physical_block *) vmalloc(sizeof(ump_dd_physical_block) * - num_blocks); - - if (NULL == descriptor->block_array) { - vfree(descriptor->block_array); - DBG_MSG(1, ("Could not allocate a mem handle for function.\n")); - return 0; /* failure */ - } - - for (i = 0; i < num_blocks; i++) { - descriptor->block_array[i].addr = part->start; - descriptor->block_array[i].size = part->size; - - dmac_unmap_area(phys_to_virt(part->start), part->size, DMA_FROM_DEVICE); - outer_inv_range(part->start, part->start + part->size); - - ++part; - size_total += descriptor->block_array[i].size; - DBG_MSG(6, - ("UMP memory created with VCM. addr 0x%x, size: 0x%x\n", - descriptor->block_array[i].addr, - descriptor->block_array[i].size)); - } - - descriptor->size_bytes = size_total; - descriptor->nr_blocks = num_blocks; - descriptor->ctx = NULL; - - info->num_vcm_blocks += num_blocks; - return 1; -} - -/* - * Free specified UMP memory - */ -static void ump_vcm_free(void *ctx, ump_dd_mem * descriptor) -{ - struct ump_vcm *ump_vcm; - vcm_allocator *info; - - BUG_ON(!descriptor); - BUG_ON(!ctx); - - ump_vcm = (struct ump_vcm*)descriptor->backend_info; - info = (vcm_allocator*)ctx; - - BUG_ON(descriptor->nr_blocks > info->num_vcm_blocks); - - if (down_interruptible(&info->mutex)) { - DBG_MSG(1, ("Failed to get mutex in ump_vcm_free\n")); - return; - } - - DBG_MSG(5, ("Releasing %lu VCM pages\n", descriptor->nr_blocks)); - - info->num_vcm_blocks -= descriptor->nr_blocks; - - up(&info->mutex); - - DBG_MSG(6, ("Freeing physical page by VCM\n")); - vcm_destroy_binding(ump_vcm->vcm_res); - ump_vcm->vcm = NULL; - ump_vcm->vcm_res = NULL; - - kfree(ump_vcm); - vfree(descriptor->block_array); -} - -static void *vcm_res_get(ump_dd_mem *mem, void *args) -{ - struct ump_vcm *ump_vcm; - enum vcm_dev_id vcm_id; - - ump_vcm = (struct ump_vcm*)mem->backend_info; - vcm_id = (enum vcm_dev_id)args; - - if (vcm_reservation_in_vcm - (vcm_find_vcm(vcm_id), ump_vcm->vcm_res) - == S5PVCM_RES_NOT_IN_VCM) - return NULL; - else - return ump_vcm->vcm_res; -} - -static void vcm_attr_set(ump_dd_mem *mem, void *args) -{ - struct ump_vcm *ump_vcm, *ump_vcmh; - - ump_vcm = (struct ump_vcm*)args; - - ump_vcmh = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); - if (NULL == ump_vcmh) - { - return; - } - - ump_vcmh->dev_id = ump_vcm->dev_id; - ump_vcmh->vcm = ump_vcm->vcm; - ump_vcmh->vcm_res = ump_vcm->vcm_res; - - mem->backend_info= (void*)ump_vcmh; - - return; -} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h deleted file mode 100644 index c1ead0d..0000000 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010-2012 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 ump_kernel_memory_backend_vcm.h - */ - -#ifndef __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ -#define __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ - -#include "ump_kernel_memory_backend.h" - -ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation); - -#endif /* __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ */ diff --git a/include/linux/sync.h b/include/linux/sync.h index 4f19938..5f49363 100644 --- a/include/linux/sync.h +++ b/include/linux/sync.h @@ -16,8 +16,10 @@ #include <linux/types.h> #ifdef __KERNEL__ +#include <linux/kref.h> #include <linux/ktime.h> #include <linux/list.h> +#include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/wait.h> @@ -39,14 +41,14 @@ struct sync_fence; * -1 if a will signabl before b * @free_pt: called before sync_pt is freed * @release_obj: called before sync_timeline is freed - * @print_obj: print aditional debug information about sync_timeline. - * should not print a newline - * @print_pt: print aditional debug information about sync_pt. - * should not print a newline + * @print_obj: deprecated + * @print_pt: deprecated * @fill_driver_data: write implmentation specific driver data to data. * should return an error if there is not enough room * as specified by size. This information is returned * to userspace by SYNC_IOC_FENCE_INFO. + * @timeline_value_str: fill str with the value of the sync_timeline's counter + * @pt_value_str: fill str with the value of the sync_pt */ struct sync_timeline_ops { const char *driver_name; @@ -66,19 +68,27 @@ struct sync_timeline_ops { /* optional */ void (*release_obj)(struct sync_timeline *sync_timeline); - /* optional */ + /* deprecated */ void (*print_obj)(struct seq_file *s, struct sync_timeline *sync_timeline); - /* optional */ + /* deprecated */ void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt); /* optional */ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); + + /* optional */ + void (*timeline_value_str)(struct sync_timeline *timeline, char *str, + int size); + + /* optional */ + void (*pt_value_str)(struct sync_pt *pt, char *str, int size); }; /** * struct sync_timeline - sync object + * @kref: reference count on fence. * @ops: ops that define the implementaiton of the sync_timeline * @name: name of the sync_timeline. Useful for debugging * @destoryed: set when sync_timeline is destroyed @@ -89,6 +99,7 @@ struct sync_timeline_ops { * @sync_timeline_list: membership in global sync_timeline_list */ struct sync_timeline { + struct kref kref; const struct sync_timeline_ops *ops; char name[32]; @@ -109,6 +120,7 @@ struct sync_timeline { * @parent: sync_timeline to which this sync_pt belongs * @child_list: membership in sync_timeline.child_list_head * @active_list: membership in sync_timeline.active_list_head + * @signaled_list: membership in temorary signaled_list on stack * @fence: sync_fence to which the sync_pt belongs * @pt_list: membership in sync_fence.pt_list_head * @status: 1: signaled, 0:active, <0: error @@ -120,6 +132,7 @@ struct sync_pt { struct list_head child_list; struct list_head active_list; + struct list_head signaled_list; struct sync_fence *fence; struct list_head pt_list; @@ -133,6 +146,7 @@ struct sync_pt { /** * struct sync_fence - sync fence * @file: file representing this fence + * @kref: referenace count on fence. * @name: name of sync_fence. Useful for debugging * @pt_list_head: list of sync_pts in ths fence. immutable once fence * is created @@ -145,6 +159,7 @@ struct sync_pt { */ struct sync_fence { struct file *file; + struct kref kref; char name[32]; /* this list is immutable once the fence is created */ @@ -159,6 +174,10 @@ struct sync_fence { struct list_head sync_fence_list; }; +struct sync_fence_waiter; +typedef void (*sync_callback_t)(struct sync_fence *fence, + struct sync_fence_waiter *waiter); + /** * struct sync_fence_waiter - metadata for asynchronous waiter on a fence * @waiter_list: membership in sync_fence.waiter_list_head @@ -168,10 +187,15 @@ struct sync_fence { struct sync_fence_waiter { struct list_head waiter_list; - void (*callback)(struct sync_fence *fence, void *data); - void *callback_data; + sync_callback_t callback; }; +static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, + sync_callback_t callback) +{ + waiter->callback = callback; +} + /* * API for sync_timeline implementers */ @@ -284,24 +308,37 @@ void sync_fence_install(struct sync_fence *fence, int fd); /** * sync_fence_wait_async() - registers and async wait on the fence * @fence: fence to wait on - * @callback: callback - * @callback_data data to pass to the callback + * @waiter: waiter callback struck * * Returns 1 if @fence has already signaled. * - * Registers a callback to be called when @fence signals or has an error + * Registers a callback to be called when @fence signals or has an error. + * @waiter should be initialized with sync_fence_waiter_init(). */ int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data); + struct sync_fence_waiter *waiter); + +/** + * sync_fence_cancel_async() - cancels an async wait + * @fence: fence to wait on + * @waiter: waiter callback struck + * + * returns 0 if waiter was removed from fence's async waiter list. + * returns -ENOENT if waiter was not found on fence's async waiter list. + * + * Cancels a previously registered async wait. Will fail gracefully if + * @waiter was never registered or if @fence has already signaled @waiter. + */ +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter); /** * sync_fence_wait() - wait on fence * @fence: fence to wait on * @tiemout: timeout in ms * - * Wait for @fence to be signaled or have an error. Waits indefintly - * if @timeout = 0 + * Wait for @fence to be signaled or have an error. Waits indefinitely + * if @timeout < 0 */ int sync_fence_wait(struct sync_fence *fence, long timeout); @@ -360,9 +397,9 @@ struct sync_fence_info_data { /** * DOC: SYNC_IOC_WAIT - wait for a fence to signal * - * pass timeout in milliseconds. + * pass timeout in milliseconds. Waits indefinitely timeout < 0. */ -#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __u32) +#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32) /** * DOC: SYNC_IOC_MERGE - merge two fences diff --git a/include/trace/events/sync.h b/include/trace/events/sync.h new file mode 100644 index 0000000..f31bc63 --- /dev/null +++ b/include/trace/events/sync.h @@ -0,0 +1,82 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM sync + +#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SYNC_H + +#include <linux/sync.h> +#include <linux/tracepoint.h> + +TRACE_EVENT(sync_timeline, + TP_PROTO(struct sync_timeline *timeline), + + TP_ARGS(timeline), + + TP_STRUCT__entry( + __string(name, timeline->name) + __array(char, value, 32) + ), + + TP_fast_assign( + __assign_str(name, timeline->name); + if (timeline->ops->timeline_value_str) { + timeline->ops->timeline_value_str(timeline, + __entry->value, + sizeof(__entry->value)); + } else { + __entry->value[0] = '\0'; + } + ), + + TP_printk("name=%s value=%s", __get_str(name), __entry->value) +); + +TRACE_EVENT(sync_wait, + TP_PROTO(struct sync_fence *fence, int begin), + + TP_ARGS(fence, begin), + + TP_STRUCT__entry( + __string(name, fence->name) + __field(s32, status) + __field(u32, begin) + ), + + TP_fast_assign( + __assign_str(name, fence->name); + __entry->status = fence->status; + __entry->begin = begin; + ), + + TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end", + __get_str(name), __entry->status) +); + +TRACE_EVENT(sync_pt, + TP_PROTO(struct sync_pt *pt), + + TP_ARGS(pt), + + TP_STRUCT__entry( + __string(timeline, pt->parent->name) + __array(char, value, 32) + ), + + TP_fast_assign( + __assign_str(timeline, pt->parent->name); + if (pt->parent->ops->pt_value_str) { + pt->parent->ops->pt_value_str(pt, + __entry->value, + sizeof(__entry->value)); + } else { + __entry->value[0] = '\0'; + } + ), + + TP_printk("name=%s value=%s", __get_str(timeline), __entry->value) + ); + +#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> |