aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/mali/common
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/mali/common')
-rw-r--r--drivers/media/video/samsung/mali/common/mali_block_allocator.c6
-rw-r--r--drivers/media/video/samsung/mali/common/mali_cluster.c218
-rw-r--r--drivers/media/video/samsung/mali/common/mali_cluster.h44
-rw-r--r--drivers/media/video/samsung/mali/common/mali_device_pause_resume.c46
-rw-r--r--drivers/media/video/samsung/mali/common/mali_device_pause_resume.h31
-rw-r--r--drivers/media/video/samsung/mali/common/mali_dlbu.c285
-rw-r--r--drivers/media/video/samsung/mali/common/mali_dlbu.h45
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp.c693
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp.h46
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_job.c49
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_job.h131
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_scheduler.c438
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_scheduler.h30
-rw-r--r--drivers/media/video/samsung/mali/common/mali_group.c841
-rw-r--r--drivers/media/video/samsung/mali/common/mali_group.h146
-rw-r--r--drivers/media/video/samsung/mali/common/mali_hw_core.c46
-rw-r--r--drivers/media/video/samsung/mali/common/mali_hw_core.h71
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_GP2.c1493
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c1304
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_common.h5
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_core.c1359
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_core.h127
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c15
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h6
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_gp.h21
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c517
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h25
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c1427
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c3157
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h75
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c26
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c26
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h5
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_pp.h21
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_profiling.c364
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c2031
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h565
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h107
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_utilization.c56
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_utilization.h2
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_vsync.c32
-rw-r--r--drivers/media/video/samsung/mali/common/mali_l2_cache.c398
-rw-r--r--drivers/media/video/samsung/mali/common/mali_l2_cache.h43
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mem_validation.c71
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mem_validation.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_session_manager.h)14
-rw-r--r--drivers/media/video/samsung/mali/common/mali_memory.c1321
-rw-r--r--drivers/media/video/samsung/mali/common/mali_memory.h80
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu.c619
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu.h55
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c459
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h83
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk.h158
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk_list.h2
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk_mali.h32
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk_profiling.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_profiling.h)88
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pm.c547
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pm.h56
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pmu.c199
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pmu.h70
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp.c710
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp.h47
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_job.c92
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_job.h255
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_scheduler.c542
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_scheduler.h38
-rw-r--r--drivers/media/video/samsung/mali/common/mali_scheduler.c36
-rw-r--r--drivers/media/video/samsung/mali/common/mali_scheduler.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_mem.h)16
-rw-r--r--drivers/media/video/samsung/mali/common/mali_session.c47
-rw-r--r--drivers/media/video/samsung/mali/common/mali_session.h65
-rw-r--r--drivers/media/video/samsung/mali/common/mali_uk_types.h1176
-rw-r--r--drivers/media/video/samsung/mali/common/mali_ukk.h184
-rw-r--r--drivers/media/video/samsung/mali/common/mali_user_settings_db.c88
-rw-r--r--drivers/media/video/samsung/mali/common/mali_user_settings_db.h40
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm.c1024
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm.h348
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c350
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h86
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c243
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h155
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c80
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h62
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c470
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h80
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c716
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h290
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h61
86 files changed, 10312 insertions, 17216 deletions
diff --git a/drivers/media/video/samsung/mali/common/mali_block_allocator.c b/drivers/media/video/samsung/mali/common/mali_block_allocator.c
index 5f421f0..269e662 100644
--- a/drivers/media/video/samsung/mali/common/mali_block_allocator.c
+++ b/drivers/media/video/samsung/mali/common/mali_block_allocator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -76,7 +76,7 @@ mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u
info = _mali_osk_malloc(sizeof(block_allocator));
if (NULL != info)
{
- info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, 105);
+ info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO);
if (NULL != info->mutex)
{
info->all_blocks = _mali_osk_malloc(sizeof(block_info) * num_blocks);
@@ -355,7 +355,7 @@ static void block_allocator_release_page_table_block( mali_page_table_block *pag
_mali_osk_mem_unmapioregion( page_table_block->phys_base, page_table_block->size, page_table_block->mapping );
/** @note This loop handles the case where more than one block_info was linked.
- * Probably unnecssary for page table block releasing. */
+ * Probably unnecessary for page table block releasing. */
while (block)
{
next = block->next;
diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.c b/drivers/media/video/samsung/mali/common/mali_cluster.c
new file mode 100644
index 0000000..f0fb2b6
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_cluster.c
@@ -0,0 +1,218 @@
+/*
+ * 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
new file mode 100644
index 0000000..33debdb
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_cluster.h
@@ -0,0 +1,44 @@
+/*
+ * 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.c b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c
new file mode 100644
index 0000000..6af1279
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c
@@ -0,0 +1,46 @@
+/**
+ * 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_device_pause_resume.c
+ * Implementation of the Mali pause/resume functionality
+ */
+
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_pm.h"
+
+void mali_dev_pause(mali_bool *power_is_on)
+{
+ 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();
+ }
+}
+
+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/media/video/samsung/mali/common/mali_device_pause_resume.h b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h
new file mode 100644
index 0000000..6be75b0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h
@@ -0,0 +1,31 @@
+/*
+ * 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_dlbu.c b/drivers/media/video/samsung/mali/common/mali_dlbu.c
new file mode 100644
index 0000000..fcc51fa
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_dlbu.c
@@ -0,0 +1,285 @@
+/*
+ * 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_dlbu.h"
+#include "mali_memory.h"
+#include "mali_pp.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "mali_hw_core.h"
+
+/**
+ * Size of DLBU registers in bytes
+ */
+#define MALI_DLBU_SIZE 0x400
+
+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.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_dlbu_register {
+ MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address;
+ 31:12 Physical address to the page used for the DLBU
+ 0 DLBU enable - set this bit to 1 enables the AXI bus
+ between PPs and L2s, setting to 0 disables the router and
+ no further transactions are sent to DLBU */
+ MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address;
+ 31:12 Virtual address to the page used for the DLBU */
+ MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address;
+ 31:12 Virtual address to the tile list. This address is used when
+ calculating the call address sent to PP.*/
+ MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension;
+ 23:16 Number of tiles in Y direction-1
+ 7:0 Number of tiles in X direction-1 */
+ MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration;
+ 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024
+ 21:16 2^n number of tiles to be binned to one tile list in Y direction
+ 5:0 2^n number of tiles to be binned to one tile list in X direction */
+ MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions;
+ 31:24 start position in Y direction for group 1
+ 23:16 start position in X direction for group 1
+ 15:8 start position in Y direction for group 0
+ 7:0 start position in X direction for group 0 */
+ MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask;
+ 7 enable PP7 for load balancing
+ 6 enable PP6 for load balancing
+ 5 enable PP5 for load balancing
+ 4 enable PP4 for load balancing
+ 3 enable PP3 for load balancing
+ 2 enable PP2 for load balancing
+ 1 enable PP1 for load balancing
+ 0 enable PP0 for load balancing */
+} mali_dlbu_register;
+
+typedef enum
+{
+ PP0ENABLE = 0,
+ PP1ENABLE,
+ PP2ENABLE,
+ PP3ENABLE,
+ PP4ENABLE,
+ PP5ENABLE,
+ PP6ENABLE,
+ PP7ENABLE
+} mali_dlbu_pp_enable;
+
+struct mali_dlbu_core
+{
+ struct mali_hw_core hw_core; /**< Common for all HW cores */
+ u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU
+ see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */
+};
+
+_mali_osk_errcode_t mali_dlbu_initialize(void)
+{
+
+ MALI_DEBUG_PRINT(2, ("Dynamic Load Balancing Unit initializing\n"));
+
+ if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr))
+ {
+ MALI_SUCCESS;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_dlbu_terminate(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n"));
+
+ mali_mmu_release_table_page(mali_dlbu_phys_addr);
+}
+
+struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
+{
+ struct mali_dlbu_core *core = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description));
+
+ core = _mali_osk_malloc(sizeof(struct mali_dlbu_core));
+ if (NULL != core)
+ {
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE))
+ {
+ 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));
+ mali_hw_core_delete(&core->hw_core);
+ }
+
+ _mali_osk_free(core);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n"));
+ }
+
+ return NULL;
+}
+
+void mali_dlbu_delete(struct mali_dlbu_core *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)
+{
+ _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);
+
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
+
+ err = _MALI_OSK_ERR_OK;
+
+ return err;
+}
+
+_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
+{
+ _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;
+ }
+
+ return err;
+}
+
+void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val)
+{
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, val);
+}
+
+void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu)
+{
+ /* 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!!! */
+
+ /* 1) */
+ mali_dlbu_disable_all_pp_cores(dlbu);
+
+ /* 3) */
+ mali_dlbu_tile_position = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS);
+}
+
+void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu)
+{
+ /* 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 */
+
+ /* 1) */
+ mali_dlbu_reset(dlbu);
+ /* ++ setup the needed values - see this */
+
+ /* 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/media/video/samsung/mali/common/mali_dlbu.h
new file mode 100644
index 0000000..e3c3b9d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_dlbu.h
@@ -0,0 +1,45 @@
+/*
+ * 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_DLBU_H__
+#define __MALI_DLBU_H__
+
+#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 */
+
+extern u32 mali_dlbu_phys_addr;
+
+struct mali_dlbu_core;
+
+_mali_osk_errcode_t mali_dlbu_initialize(void);
+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_pp_jobs_stop(struct mali_dlbu_core *dlbu);
+void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu);
+
+#endif /* __MALI_DLBU_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_gp.c b/drivers/media/video/samsung/mali/common/mali_gp.c
new file mode 100644
index 0000000..d03721c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp.c
@@ -0,0 +1,693 @@
+/*
+ * 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);
+
+ /* 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 (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
new file mode 100644
index 0000000..3175b75
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp.h
@@ -0,0 +1,46 @@
+/*
+ * 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
new file mode 100644
index 0000000..abe1d93
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_job.c
@@ -0,0 +1,49 @@
+/*
+ * 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_job.h b/drivers/media/video/samsung/mali/common/mali_gp_job.h
new file mode 100644
index 0000000..9c29f1c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_job.h
@@ -0,0 +1,131 @@
+/*
+ * 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_JOB_H__
+#define __MALI_GP_JOB_H__
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+#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_*
+ * 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 */
+ 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 */
+};
+
+struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id);
+void mali_gp_job_delete(struct mali_gp_job *job);
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job)
+{
+ return (NULL == job) ? 0 : job->id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job)
+{
+ return job->user_id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job)
+{
+ return job->frame_builder_id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job)
+{
+ return job->flush_id;
+}
+
+MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job)
+{
+ return job->frame_registers;
+}
+
+MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job)
+{
+ return job->session;
+}
+
+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;
+}
+
+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;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job)
+{
+ return job->heap_current_addr;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *job, u32 heap_addr)
+{
+ job->heap_current_addr = heap_addr;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job)
+{
+ return job->perf_counter_flag;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job)
+{
+ return job->perf_counter_src0;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job)
+{
+ return job->perf_counter_src1;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job)
+{
+ return job->perf_counter_value0;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *job)
+{
+ return job->perf_counter_value1;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value)
+{
+ job->perf_counter_value0 = value;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value1(struct mali_gp_job *job, u32 value)
+{
+ job->perf_counter_value1 = value;
+}
+
+#endif /* __MALI_GP_JOB_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c
new file mode 100644
index 0000000..05f00fc
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c
@@ -0,0 +1,438 @@
+/*
+ * 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);
+ gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init();
+
+ if (NULL == gp_scheduler_lock)
+ {
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ 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;
+ }
+
+ 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_gp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h
new file mode 100644
index 0000000..ef58509
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h
@@ -0,0 +1,30 @@
+/*
+ * 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_GP_SCHEDULER_H__
+#define __MALI_GP_SCHEDULER_H__
+
+#include "mali_osk.h"
+#include "mali_cluster.h"
+#include "mali_gp_job.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);
+u32 mali_gp_scheduler_dump_state(char *buf, u32 size);
+
+void mali_gp_scheduler_suspend(void);
+void mali_gp_scheduler_resume(void);
+
+#endif /* __MALI_GP_SCHEDULER_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_group.c b/drivers/media/video/samsung/mali/common/mali_group.c
new file mode 100644
index 0000000..9202bc1
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_group.c
@@ -0,0 +1,841 @@
+/*
+ * 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_FALSE;
+ 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
new file mode 100644
index 0000000..3533d13
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_group.h
@@ -0,0 +1,146 @@
+/*
+ * 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_hw_core.c b/drivers/media/video/samsung/mali/common/mali_hw_core.c
new file mode 100644
index 0000000..0b08622
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_hw_core.c
@@ -0,0 +1,46 @@
+/*
+ * 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_hw_core.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size)
+{
+ 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);
+ if (NULL != core->mapped_registers)
+ {
+ return _MALI_OSK_ERR_OK;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to map memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr));
+ }
+ _mali_osk_mem_unreqregion(core->phys_addr, core->size);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to request memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr));
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_hw_core_delete(struct mali_hw_core *core)
+{
+ _mali_osk_mem_unmapioregion(core->phys_addr, core->size, core->mapped_registers);
+ core->mapped_registers = NULL;
+ _mali_osk_mem_unreqregion(core->phys_addr, core->size);
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.h b/drivers/media/video/samsung/mali/common/mali_hw_core.h
new file mode 100644
index 0000000..c797804
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_hw_core.h
@@ -0,0 +1,71 @@
+/*
+ * 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_HW_CORE_H__
+#define __MALI_HW_CORE_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+/**
+ * The common parts for all Mali HW cores (GP, PP, MMU, L2 and PMU)
+ * This struct is embedded inside all core specific structs.
+ */
+struct mali_hw_core
+{
+ u32 phys_addr; /**< Physical address of the registers */
+ u32 size; /**< Size of registers */
+ mali_io_address mapped_registers; /**< Virtual mapping of the registers */
+ 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)
+
+_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);
+
+MALI_STATIC_INLINE u32 mali_hw_core_register_read(struct mali_hw_core *core, u32 relative_address)
+{
+ u32 read_val;
+ read_val = _mali_osk_mem_ioread32(core->mapped_registers, relative_address);
+ MALI_DEBUG_PRINT(6, ("register_read for core %s, relative addr=0x%04X, val=0x%08X\n",
+ core->description, relative_address, read_val));
+ return read_val;
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core *core, u32 relative_address, u32 new_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));
+ _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",
+ core->description, relative_address, new_val));
+ _mali_osk_mem_iowrite32(core->mapped_registers, relative_address, new_val);
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs)
+{
+ 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++)
+ {
+ 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_GP2.c b/drivers/media/video/samsung/mali/common/mali_kernel_GP2.c
deleted file mode 100644
index cfd70f4..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_GP2.c
+++ /dev/null
@@ -1,1493 +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.
- */
-//added for SPI
-#include <linux/kernel.h>
-
-#include "mali_kernel_common.h"
-#include "mali_kernel_core.h"
-#include "mali_kernel_subsystem.h"
-#include "regs/mali_gp_regs.h"
-#include "mali_kernel_rendercore.h"
-#include "mali_osk.h"
-#include "mali_osk_list.h"
-#if MALI_TIMELINE_PROFILING_ENABLED
-#include "mali_kernel_profiling.h"
-#endif
-#if defined(USING_MALI400_L2_CACHE)
-#include "mali_kernel_l2_cache.h"
-#endif
-#if USING_MMU
-#include "mali_kernel_mem_mmu.h" /* Needed for mali_kernel_mmu_force_bus_reset() */
-#endif
-
-#if defined(USING_MALI200)
-#define MALI_GP_SUBSYSTEM_NAME "MaliGP2"
-#define MALI_GP_CORE_TYPE _MALI_GP2
-#elif defined(USING_MALI400)
-#define MALI_GP_SUBSYSTEM_NAME "Mali-400 GP"
-#define MALI_GP_CORE_TYPE _MALI_400_GP
-#else
-#error "No supported mali core defined"
-#endif
-
-#define GET_JOB_EMBEDDED_PTR(job) (&((job)->embedded_core_job))
-#define GET_JOBGP2_PTR(job_extern) _MALI_OSK_CONTAINER_OF(job_extern, maligp_job, embedded_core_job)
-
-/* Initialized when this subsystem is initialized. This is determined by the
- * position in subsystems[], and so the value used to initialize this is
- * determined at compile time */
-static mali_kernel_subsystem_identifier mali_subsystem_gp_id = -1;
-
-static mali_core_renderunit * last_gp_core_cookie = NULL;
-
-/* Describing a maligp job settings */
-typedef struct maligp_job
-{
- /* The general job struct common for all mali cores */
- mali_core_job embedded_core_job;
- _mali_uk_gp_start_job_s user_input;
-
- u32 irq_status;
- u32 status_reg_on_stop;
- u32 perf_counter0;
- u32 perf_counter1;
- u32 vscl_stop_addr;
- u32 plbcl_stop_addr;
- u32 heap_current_addr;
-
- /* The data we will return back to the user */
- _mali_osk_notification_t *notification_obj;
-
- int is_stalled_waiting_for_more_memory;
-
- u32 active_mask;
- /* progress checking */
- u32 last_vscl;
- u32 last_plbcl;
- /* extended progress checking, only enabled when we can use one of the performance counters */
- u32 have_extended_progress_checking;
- u32 vertices;
-
-#if defined(USING_MALI400_L2_CACHE)
- u32 perf_counter_l2_src0;
- u32 perf_counter_l2_src1;
- u32 perf_counter_l2_val0;
- u32 perf_counter_l2_val1;
-#endif
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- u32 pid;
- u32 tid;
-#endif
-} maligp_job;
-
-/*Functions Exposed to the General External System through
- function pointers.*/
-
-static _mali_osk_errcode_t maligp_subsystem_startup(mali_kernel_subsystem_identifier id);
-#if USING_MMU
-static _mali_osk_errcode_t maligp_subsystem_mmu_connect(mali_kernel_subsystem_identifier id);
-#endif
-static void maligp_subsystem_terminate(mali_kernel_subsystem_identifier id);
-static _mali_osk_errcode_t maligp_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
-static void maligp_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
-static _mali_osk_errcode_t maligp_subsystem_core_system_info_fill(_mali_system_info* info);
-static _mali_osk_errcode_t maligp_renderunit_create(_mali_osk_resource_t * resource);
-#if USING_MMU
-static void maligp_subsystem_broadcast_notification(mali_core_notification_message message, u32 data);
-#endif
-#if MALI_STATE_TRACKING
-u32 maligp_subsystem_dump_state(char *buf, u32 size);
-#endif
-
-/* Internal support functions */
-static _mali_osk_errcode_t maligp_core_version_legal( mali_core_renderunit *core );
-static void maligp_raw_reset( mali_core_renderunit *core);
-static void maligp_reset_hard(struct mali_core_renderunit * core);
-static void maligp_reset(mali_core_renderunit *core);
-static void maligp_initialize_registers_mgmt(mali_core_renderunit *core );
-
-#ifdef DEBUG
-static void maligp_print_regs(int debug_level, mali_core_renderunit *core);
-#endif
-
-/* Functions exposed to mali_core system through functionpointers
- in the subsystem struct. */
-static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_core_renderunit * core);
-static u32 subsystem_maligp_irq_handler_upper_half(mali_core_renderunit * core);
-static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core);
-static _mali_osk_errcode_t subsystem_maligp_get_new_job_from_user(struct mali_core_session * session, void * argument);
-static _mali_osk_errcode_t subsystem_maligp_suspend_response(struct mali_core_session * session, void * argument);
-static void subsystem_maligp_return_job_to_user(mali_core_job * job, mali_subsystem_job_end_code end_status);
-static void subsystem_maligp_renderunit_delete(mali_core_renderunit * core);
-static void subsystem_maligp_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style );
-static void subsystem_maligp_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core);
-static _mali_osk_errcode_t subsystem_maligp_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core);
-static void subsystem_maligp_renderunit_stop_bus(struct mali_core_renderunit* core);
-
-/* Variables */
-static register_address_and_value default_mgmt_regs[] =
-{
- { MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED }
-};
-
-
-/* This will be one of the subsystems in the array of subsystems:
- static struct mali_kernel_subsystem * subsystems[];
- found in file: mali_kernel_core.c
-*/
-
-struct mali_kernel_subsystem mali_subsystem_gp2=
-{
- maligp_subsystem_startup, /* startup */
- NULL, /*maligp_subsystem_terminate,*/ /* shutdown */
-#if USING_MMU
- maligp_subsystem_mmu_connect, /* load_complete */
-#else
- NULL,
-#endif
- maligp_subsystem_core_system_info_fill, /* system_info_fill */
- maligp_subsystem_session_begin, /* session_begin */
- maligp_subsystem_session_end, /* session_end */
-#if USING_MMU
- maligp_subsystem_broadcast_notification, /* broadcast_notification */
-#else
- NULL,
-#endif
-#if MALI_STATE_TRACKING
- maligp_subsystem_dump_state, /* dump_state */
-#endif
-} ;
-
-static mali_core_subsystem subsystem_maligp ;
-
-static _mali_osk_errcode_t maligp_subsystem_startup(mali_kernel_subsystem_identifier id)
-{
- mali_core_subsystem * subsystem;
-
- MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_startup\n") ) ;
-
- mali_subsystem_gp_id = id;
-
- /* All values get 0 as default */
- _mali_osk_memset(&subsystem_maligp, 0, sizeof(*subsystem));
-
- subsystem = &subsystem_maligp;
- subsystem->start_job = &subsystem_maligp_start_job;
- subsystem->irq_handler_upper_half = &subsystem_maligp_irq_handler_upper_half;
- subsystem->irq_handler_bottom_half = &subsystem_maligp_irq_handler_bottom_half;
- subsystem->get_new_job_from_user = &subsystem_maligp_get_new_job_from_user;
- subsystem->suspend_response = &subsystem_maligp_suspend_response;
- subsystem->return_job_to_user = &subsystem_maligp_return_job_to_user;
- subsystem->renderunit_delete = &subsystem_maligp_renderunit_delete;
- subsystem->reset_core = &subsystem_maligp_renderunit_reset_core;
- subsystem->stop_bus = &subsystem_maligp_renderunit_stop_bus;
- subsystem->probe_core_irq_trigger = &subsystem_maligp_renderunit_probe_core_irq_trigger;
- subsystem->probe_core_irq_acknowledge = &subsystem_maligp_renderunit_probe_core_irq_finished;
-
- /* Setting variables in the general core part of the subsystem.*/
- subsystem->name = MALI_GP_SUBSYSTEM_NAME;
- subsystem->core_type = MALI_GP_CORE_TYPE;
- subsystem->id = id;
-
- /* Initiates the rest of the general core part of the subsystem */
- MALI_CHECK_NO_ERROR(mali_core_subsystem_init( subsystem ));
-
- /* This will register the function for adding MALIGP2 cores to the subsystem */
-#if defined(USING_MALI200)
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALIGP2, maligp_renderunit_create));
-#endif
-#if defined(USING_MALI400)
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALI400GP, maligp_renderunit_create));
-#endif
-
- MALI_DEBUG_PRINT(6, ("Mali GP: maligp_subsystem_startup\n") ) ;
-
- MALI_SUCCESS;
-}
-
-#if USING_MMU
-static _mali_osk_errcode_t maligp_subsystem_mmu_connect(mali_kernel_subsystem_identifier id)
-{
- mali_core_subsystem_attach_mmu(&subsystem_maligp);
- MALI_SUCCESS; /* OK */
-}
-#endif
-
-static void maligp_subsystem_terminate(mali_kernel_subsystem_identifier id)
-{
- MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_terminate\n") ) ;
- mali_core_subsystem_cleanup(&subsystem_maligp);
-}
-
-static _mali_osk_errcode_t maligp_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
-{
- mali_core_session * session;
-
- MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_session_begin\n") ) ;
- MALI_CHECK_NON_NULL(session = _mali_osk_malloc( sizeof(*session) ), _MALI_OSK_ERR_FAULT);
-
- _mali_osk_memset(session, 0, sizeof(*session) );
- *slot = (mali_kernel_subsystem_session_slot)session;
-
- session->subsystem = &subsystem_maligp;
-
- session->notification_queue = queue;
-
-#if USING_MMU
- session->mmu_session = mali_session_data;
-#endif
-
- mali_core_session_begin(session);
-
- MALI_DEBUG_PRINT(6, ("Mali GP: maligp_subsystem_session_begin\n") ) ;
-
- MALI_SUCCESS;
-}
-
-static void maligp_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
-{
- mali_core_session * session;
- /** @note mali_session_data not needed here */
-
- MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_session_end\n") ) ;
- if ( NULL==slot || NULL==*slot)
- {
- MALI_PRINT_ERROR(("Input slot==NULL"));
- return;
- }
- session = (mali_core_session *)*slot;
- mali_core_session_close(session);
-
- _mali_osk_free(session);
- *slot = NULL;
-
- MALI_DEBUG_PRINT(6, ("Mali GP: maligp_subsystem_session_end\n") ) ;
-}
-
-/**
- * We fill in info about all the cores we have
- * @param info Pointer to system info struct to update
- * @return _MALI_OSK_ERR_OK on success, or another _mali_osk_errcode_t for errors.
- */
-static _mali_osk_errcode_t maligp_subsystem_core_system_info_fill(_mali_system_info* info)
-{
- return mali_core_subsystem_system_info_fill(&subsystem_maligp, info);
-}
-
-static _mali_osk_errcode_t maligp_renderunit_create(_mali_osk_resource_t * resource)
-{
- mali_core_renderunit *core;
- int err;
-
- MALI_DEBUG_PRINT(3, ("Mali GP: maligp_renderunit_create\n") ) ;
- /* Checking that the resource settings are correct */
-#if defined(USING_MALI200)
- if(MALIGP2 != resource->type)
- {
- MALI_PRINT_ERROR(("Can not register this resource as a " MALI_GP_SUBSYSTEM_NAME " core."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#elif defined(USING_MALI400)
- if(MALI400GP != resource->type)
- {
- MALI_PRINT_ERROR(("Can not register this resource as a " MALI_GP_SUBSYSTEM_NAME " core."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#endif
- if ( 0 != resource->size )
- {
- MALI_PRINT_ERROR(("Memory size set to " MALI_GP_SUBSYSTEM_NAME " core should be zero."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- if ( NULL == resource->description )
- {
- MALI_PRINT_ERROR(("A " MALI_GP_SUBSYSTEM_NAME " core needs a unique description field"));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* Create a new core object */
- core = (mali_core_renderunit*) _mali_osk_malloc(sizeof(*core));
- if ( NULL == core )
- {
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* Variables set to be able to open and register the core */
- core->subsystem = &subsystem_maligp ;
- core->registers_base_addr = resource->base ;
- core->size = MALIGP2_REGISTER_ADDRESS_SPACE_SIZE ;
- core->description = resource->description;
- core->irq_nr = resource->irq ;
-#if USING_MMU
- core->mmu_id = resource->mmu_id;
- core->mmu = NULL;
-#endif
-#if USING_MALI_PMM
- /* Set up core's PMM id */
- core->pmm_id = MALI_PMM_CORE_GP;
-#endif
-
- err = mali_core_renderunit_init( core );
- if (_MALI_OSK_ERR_OK != err)
- {
- MALI_DEBUG_PRINT(1, ("Failed to initialize renderunit\n"));
- goto exit_on_error0;
- }
-
- /* Map the new core object, setting: core->registers_mapped */
- err = mali_core_renderunit_map_registers(core);
- if (_MALI_OSK_ERR_OK != err) goto exit_on_error1;
-
- /* Check that the register mapping of the core works.
- Return 0 if maligp core is present and accessible. */
- if (mali_benchmark) {
- core->core_version = MALI_GP_PRODUCT_ID << 16;
- } else {
- core->core_version = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VERSION);
- }
-
- err = maligp_core_version_legal(core);
- if (_MALI_OSK_ERR_OK != err) goto exit_on_error2;
-
- /* Reset the core. Put the core into a state where it can start to render. */
- maligp_reset(core);
-
- /* Registering IRQ, init the work_queue_irq_handle */
- /* Adding this core as an available renderunit in the subsystem. */
- err = mali_core_subsystem_register_renderunit(&subsystem_maligp, core);
- if (_MALI_OSK_ERR_OK != err) goto exit_on_error2;
-
-#ifdef DEBUG
- MALI_DEBUG_PRINT(4, ("Mali GP: Initial Register settings:\n"));
- maligp_print_regs(4, core);
-#endif
-
- MALI_DEBUG_PRINT(6, ("Mali GP: maligp_renderunit_create\n") ) ;
-
- MALI_SUCCESS;
-
-exit_on_error2:
- mali_core_renderunit_unmap_registers(core);
-exit_on_error1:
- mali_core_renderunit_term(core);
-exit_on_error0:
- _mali_osk_free( core ) ;
- MALI_PRINT_ERROR(("Renderunit NOT created."));
- MALI_ERROR((_mali_osk_errcode_t)err);
-}
-
-#if USING_MMU
-/* Used currently only for signalling when MMU has a pagefault */
-static void maligp_subsystem_broadcast_notification(mali_core_notification_message message, u32 data)
-{
- mali_core_subsystem_broadcast_notification(&subsystem_maligp, message, data);
-}
-#endif
-
-#ifdef DEBUG
-static void maligp_print_regs(int debug_level, mali_core_renderunit *core)
-{
- if (debug_level <= mali_debug_level)
- {
- MALI_DEBUG_PRINT(1, (" VS 0x%08X 0x%08X, PLBU 0x%08X 0x%08X ALLOC 0x%08X 0x%08X\n",
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_END_ADDR),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBUCL_END_ADDR),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR))
- );
- MALI_DEBUG_PRINT(1, (" IntRaw 0x%08X IntMask 0x%08X, Status 0x%02X Ver: 0x%08X \n",
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_MASK),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_STATUS),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VERSION)));
-
- MALI_DEBUG_PRINT(1, (" PERF_CNT Enbl:%d %d Src: %02d %02d VAL: 0x%08X 0x%08X\n",
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE)));
-
- MALI_DEBUG_PRINT(1, (" VS_START 0x%08X PLBU_START 0x%08X AXI_ERR 0x%08X\n",
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR_READ),
- mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBCL_START_ADDR_READ),
- mali_core_renderunit_register_read(core, MALIGP2_CONTR_AXI_BUS_ERROR_STAT)));
- }
-}
-#endif
-
-static _mali_osk_errcode_t maligp_core_version_legal( mali_core_renderunit *core )
-{
- u32 mali_type;
-
- mali_type = core->core_version >> 16;
-
-#if defined(USING_MALI400)
- if ( MALI400_GP_PRODUCT_ID != mali_type && MALI300_GP_PRODUCT_ID != mali_type )
-#else
- if ( MALI_GP_PRODUCT_ID != mali_type )
-#endif
- {
- MALI_PRINT_ERROR(("Error: reading this from maligp version register: 0x%x\n", core->core_version));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- MALI_DEBUG_PRINT(3, ("Mali GP: core_version_legal: Reads correct mali version: %d\n", core->core_version )) ;
- MALI_SUCCESS;
-}
-
-static void subsystem_maligp_renderunit_stop_bus(struct mali_core_renderunit* core)
-{
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
-}
-
-static void maligp_reset( mali_core_renderunit *core )
-{
- if (!mali_benchmark) {
- maligp_raw_reset(core);
- maligp_initialize_registers_mgmt(core);
- }
-}
-
-
-static void maligp_reset_hard( mali_core_renderunit *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_core_renderunit_register_write(core, reset_wait_target_register, reset_invalid_value);
-
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET);
-
- for (i = 0; i < reset_finished_loop_count; i++)
- {
- mali_core_renderunit_register_write(core, reset_wait_target_register, reset_check_value);
- if (reset_check_value == mali_core_renderunit_register_read(core, reset_wait_target_register))
- {
- MALI_DEBUG_PRINT(5, ("Reset loop exiting after %d iterations\n", i));
- break;
- }
- }
-
- if (i == reset_finished_loop_count)
- {
- MALI_DEBUG_PRINT(1, ("The reset loop didn't work\n"));
- }
-
- mali_core_renderunit_register_write(core, reset_wait_target_register, reset_default_value); /* set it back to the default */
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
-
-
-}
-
-static void maligp_raw_reset( mali_core_renderunit *core )
-{
- int i;
- const int request_loop_count = 20;
-
- MALI_DEBUG_PRINT(4, ("Mali GP: maligp_raw_reset: %s\n", core->description)) ;
- if (mali_benchmark) return;
-
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
-
-#if defined(USING_MALI200)
-
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
-
- for (i = 0; i < request_loop_count; i++)
- {
- if (mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) break;
- _mali_osk_time_ubusydelay(10);
- }
-
- MALI_DEBUG_PRINT_IF(1, request_loop_count == i, ("Mali GP: Bus was never stopped during core reset\n"));
-
- if (request_loop_count==i)
- {
- /* Could not stop bus connections from core, probably because some of the already pending
- bus request has had a page fault, and therefore can not complete before the MMU does PageFault
- handling. This can be treated as a heavier reset function - which unfortunately reset all
- the cores on this MMU in addition to the MMU itself */
-#if USING_MMU
- if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
- {
- MALI_DEBUG_PRINT(1, ("Mali GP: Forcing MMU bus reset\n"));
- mali_kernel_mmu_force_bus_reset(core->mmu);
- return;
- }
-#endif
- MALI_PRINT(("A MMU reset did not allow GP to stop its bus, system failure, unable to recover\n"));
- return;
- }
-
- /* the bus was stopped OK, complete the reset */
- /* use the hard reset routine to do the actual reset */
- maligp_reset_hard(core);
-
-#elif defined(USING_MALI400)
-
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
-
- for (i = 0; i < request_loop_count; i++)
- {
- if (mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & /*Bitwise OR*/
- MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) break;
- _mali_osk_time_ubusydelay(10);
- }
-
- if ( request_loop_count==i )
- {
-#if USING_MMU
- /* Could not stop bus connections from core, probably because some of the already pending
- bus request has had a page fault, and therefore can not complete before the MMU does PageFault
- handling. This can be treated as a heavier reset function - which unfortunately reset all
- the cores on this MMU in addition to the MMU itself */
- if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
- {
- MALI_DEBUG_PRINT(1, ("Mali GP: Forcing Bus reset\n"));
- mali_kernel_mmu_force_bus_reset(core->mmu);
- return;
- }
-#endif
- MALI_PRINT(("A MMU reset did not allow GP to stop its bus, system failure, unable to recover\n"));
- }
- else
- {
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
- }
-
-#else
-#error "no supported mali core defined"
-#endif
-}
-
-/* Sets the registers on maligp according to the const default_mgmt_regs array. */
-static void maligp_initialize_registers_mgmt(mali_core_renderunit *core )
-{
- int i;
-
- MALI_DEBUG_PRINT(6, ("Mali GP: maligp_initialize_registers_mgmt: %s\n", core->description)) ;
- for(i=0 ; i< (sizeof(default_mgmt_regs)/sizeof(*default_mgmt_regs)) ; ++i)
- {
- mali_core_renderunit_register_write_relaxed(core, default_mgmt_regs[i].address, default_mgmt_regs[i].value);
- }
- _mali_osk_write_mem_barrier();
-}
-
-
-/* Start this job on this core. Return MALI_TRUE if the job was started. */
-static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_core_renderunit * core)
-{
- maligp_job *jobgp;
- u32 startcmd;
- /* The local extended version of the general structs */
- jobgp = _MALI_OSK_CONTAINER_OF(job, maligp_job, embedded_core_job);
-
- startcmd = 0;
- if ( jobgp->user_input.frame_registers[0] != jobgp->user_input.frame_registers[1] )
- {
- startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS;
- }
-
- if ( jobgp->user_input.frame_registers[2] != jobgp->user_input.frame_registers[3] )
- {
- startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU;
- }
-
- if(0 == startcmd)
- {
- MALI_DEBUG_PRINT(4, ("Mali GP: Job: 0x%08x WILL NOT START SINCE JOB HAS ILLEGAL ADDRESSES\n",
- (u32)jobgp->user_input.user_job_ptr));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
-
-#ifdef DEBUG
- MALI_DEBUG_PRINT(4, ("Mali GP: Registers Start\n"));
- maligp_print_regs(4, core);
-#endif
-
-
- mali_core_renderunit_register_write_array(
- core,
- MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR,
- &(jobgp->user_input.frame_registers[0]),
- sizeof(jobgp->user_input.frame_registers)/sizeof(jobgp->user_input.frame_registers[0]));
-
-#if MALI_TRACEPOINTS_ENABLED
- jobgp->user_input.perf_counter_flag = 0;
-
- if( counter_table[7] != 0xFFFFFFFF ) {
- jobgp->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE;
- jobgp->user_input.perf_counter_src0 = counter_table[7];
- }
- if( counter_table[8] != 0xFFFFFFFF ) {
- jobgp->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE;
- jobgp->user_input.perf_counter_src1 = counter_table[8];
- }
-#endif
-
- /* This selects which performance counters we are reading */
- if ( 0 != jobgp->user_input.perf_counter_flag )
- {
- if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
- {
- mali_core_renderunit_register_write_relaxed(
- core,
- MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC,
- jobgp->user_input.perf_counter_src0);
-
- mali_core_renderunit_register_write_relaxed(
- core,
- MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE,
- MALIGP2_REG_VAL_PERF_CNT_ENABLE);
- }
-
- if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
- {
- mali_core_renderunit_register_write_relaxed(
- core,
- MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC,
- jobgp->user_input.perf_counter_src1);
-
- mali_core_renderunit_register_write_relaxed(
- core,
- MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE,
- MALIGP2_REG_VAL_PERF_CNT_ENABLE);
- }
-
-#if defined(USING_MALI400_L2_CACHE)
- if ( jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
- {
- int force_reset = ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET ) ? 1 : 0;
- u32 src0 = 0;
- u32 src1 = 0;
-
- if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE )
- {
- src0 = jobgp->user_input.perf_counter_l2_src0;
- }
- if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE )
- {
- src1 = jobgp->user_input.perf_counter_l2_src1;
- }
-
- mali_kernel_l2_cache_set_perf_counters(src0, src1, force_reset); /* will activate and possibly reset counters */
-
- /* Now, retrieve the current values, so we can substract them when the job has completed */
- mali_kernel_l2_cache_get_perf_counters(&jobgp->perf_counter_l2_src0,
- &jobgp->perf_counter_l2_val0,
- &jobgp->perf_counter_l2_src1,
- &jobgp->perf_counter_l2_val1);
- }
-#endif
- }
-
- if ( 0 == (jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))
- {
- /* extended progress checking can be enabled */
-
- jobgp->have_extended_progress_checking = 1;
-
- mali_core_renderunit_register_write_relaxed(
- core,
- MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC,
- MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED
- );
-
- mali_core_renderunit_register_write_relaxed(
- core,
- MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE,
- MALIGP2_REG_VAL_PERF_CNT_ENABLE);
- }
-
- subsystem_flush_mapped_mem_cache();
-
- MALI_DEBUG_PRINT(4, ("Mali GP: STARTING GP WITH CMD: 0x%x\n", startcmd));
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_started);
-#endif
-
- /* This is the command that starts the Core */
- mali_core_renderunit_register_write(core,
- MALIGP2_REG_ADDR_MGMT_CMD,
- startcmd);
- _mali_osk_write_mem_barrier();
-
- pr_debug("SPI_GPU_GP Start\n");
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
- jobgp->user_input.frame_builder_id, jobgp->user_input.flush_id, 0, 0, 0);
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), jobgp->pid, jobgp->tid, 0, 0, 0);
-#endif
-
- MALI_SUCCESS;
-}
-
-/* Check if given core has an interrupt pending. Return MALI_TRUE and set mask to 0 if pending */
-
-static u32 subsystem_maligp_irq_handler_upper_half(mali_core_renderunit * core)
-{
- u32 irq_readout;
-
- if (mali_benchmark) {
- return (core->current_job ? 1 : 0); /* simulate irq is pending when a job is pending */
- }
-
- irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
-
- MALI_DEBUG_PRINT(5, ("Mali GP: IRQ: %04x\n", irq_readout)) ;
-
- if ( MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout )
- {
- /* Mask out all IRQs from this core until IRQ is handled */
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE);
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
-#endif
-
- /* We do need to handle this in a bottom half, return 1 */
- return 1;
- }
- return 0;
-}
-
-/* This function should check if the interrupt indicates that job was finished.
-If so it should update the job-struct, reset the core registers, and return MALI_TRUE, .
-If the job is still working after this function it should return MALI_FALSE.
-The function must also enable the bits in the interrupt mask for the core.
-Called by the bottom half interrupt function. */
-static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core)
-{
- mali_core_job * job;
- maligp_job * jobgp;
- u32 irq_readout;
- u32 core_status;
- u32 vscl;
- u32 plbcl;
-
- job = core->current_job;
-
- if (mali_benchmark) {
- MALI_DEBUG_PRINT(3, ("MaliGP: Job: Benchmark\n") );
- irq_readout = MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST;
- core_status = 0;
- } else {
- irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
- core_status = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_STATUS);
- }
-
- if (NULL == job)
- {
- MALI_DEBUG_ASSERT(CORE_IDLE==core->state);
- if ( 0 != irq_readout )
- {
- MALI_PRINT_ERROR(("Interrupt from a core not running a job. IRQ: 0x%04x Status: 0x%04x", irq_readout, core_status));
- }
- return JOB_STATUS_END_UNKNOWN_ERR;
- }
- MALI_DEBUG_ASSERT(CORE_IDLE!=core->state);
-
- jobgp = GET_JOBGP2_PTR(job);
-
- jobgp->heap_current_addr = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR);
-
- vscl = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR);
- plbcl = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR);
-
- MALI_DEBUG_PRINT(3, ("Mali GP: Job: 0x%08x IRQ RECEIVED Rawstat: 0x%x Status: 0x%x\n",
- (u32)jobgp->user_input.user_job_ptr, irq_readout , core_status )) ;
-
- jobgp->irq_status |= irq_readout;
- jobgp->status_reg_on_stop = core_status;
-
- if ( 0 != jobgp->is_stalled_waiting_for_more_memory )
- {
- /* Readback the performance counters */
- if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
- {
- jobgp->perf_counter0 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
- jobgp->perf_counter1 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
-
-#if MALI_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- _mali_profiling_add_counter(7, jobgp->perf_counter0);
- _mali_profiling_add_counter(8, jobgp->perf_counter1);
-#endif
- }
-
-#if defined(USING_MALI400_L2_CACHE)
- if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
- {
- u32 src0;
- u32 val0;
- u32 src1;
- u32 val1;
- mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);
-
- if (jobgp->perf_counter_l2_src0 == src0)
- {
- jobgp->perf_counter_l2_val0 = val0 - jobgp->perf_counter_l2_val0;
- }
- else
- {
- jobgp->perf_counter_l2_val0 = 0;
- }
-
- if (jobgp->perf_counter_l2_src1 == src1)
- {
- jobgp->perf_counter_l2_val1 = val1 - jobgp->perf_counter_l2_val1;
- }
- else
- {
- jobgp->perf_counter_l2_val1 = 0;
- }
- }
-#endif
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
-#endif
-
- MALI_DEBUG_PRINT(2, ("Mali GP: Job aborted - userspace would not provide more heap memory.\n"));
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
- return JOB_STATUS_END_OOM; /* Core is ready for more jobs.*/
- }
- /* finished ? */
- else if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
- {
-#ifdef DEBUG
- MALI_DEBUG_PRINT(4, ("Mali GP: Registers On job end:\n"));
- maligp_print_regs(4, core);
-#endif
- MALI_DEBUG_PRINT_IF(5, irq_readout & 0x04, ("OOM when done, ignoring (reg.current = 0x%x, reg.end = 0x%x)\n",
- (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR),
- (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR))
- );
-
-
- if (0 != jobgp->user_input.perf_counter_flag )
- {
- /* Readback the performance counters */
- if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
- {
- jobgp->perf_counter0 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
- jobgp->perf_counter1 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
-
-#if MALI_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- _mali_profiling_add_counter(7, jobgp->perf_counter0);
- _mali_profiling_add_counter(8, jobgp->perf_counter1);
-#endif
- }
-
-#if defined(USING_MALI400_L2_CACHE)
- if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
- {
- u32 src0;
- u32 val0;
- u32 src1;
- u32 val1;
- mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);
-
- if (jobgp->perf_counter_l2_src0 == src0)
- {
- jobgp->perf_counter_l2_val0 = val0 - jobgp->perf_counter_l2_val0;
- }
- else
- {
- jobgp->perf_counter_l2_val0 = 0;
- }
-
- if (jobgp->perf_counter_l2_src1 == src1)
- {
- jobgp->perf_counter_l2_val1 = val1 - jobgp->perf_counter_l2_val1;
- }
- else
- {
- jobgp->perf_counter_l2_val1 = 0;
- }
- }
-#endif
- }
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number),
- jobgp->perf_counter0, jobgp->perf_counter1,
- jobgp->user_input.perf_counter_src0 | (jobgp->user_input.perf_counter_src1 << 8)
-#if defined(USING_MALI400_L2_CACHE)
- | (jobgp->user_input.perf_counter_l2_src0 << 16) | (jobgp->user_input.perf_counter_l2_src1 << 24),
- jobgp->perf_counter_l2_val0,
- jobgp->perf_counter_l2_val1
-#else
- ,0, 0
-#endif
- );
-#endif
-
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
- pr_debug("SPI_GPU_GP Idle\n");
- return JOB_STATUS_END_SUCCESS; /* core idle */
- }
- /* sw watchdog timeout handling or time to do hang checking ? */
- else if (
- (CORE_WATCHDOG_TIMEOUT == core->state) ||
- (
- (CORE_HANG_CHECK_TIMEOUT == core->state) &&
- (
- (jobgp->have_extended_progress_checking ? (mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE) == jobgp->vertices) : 1/*TRUE*/) &&
- ((core_status & MALIGP2_REG_VAL_STATUS_VS_ACTIVE) ? (vscl == jobgp->last_vscl) : 1/*TRUE*/) &&
- ((core_status & MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) ? (plbcl == jobgp->last_plbcl) : 1/*TRUE*/)
- )
- )
- )
- {
- /* no progress detected, killed by the watchdog */
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
-#endif
-
- MALI_PRINT( ("Mali GP: SW-Timeout.\n"));
- if (core_status & MALIGP2_REG_VAL_STATUS_VS_ACTIVE) MALI_DEBUG_PRINT(1, ("vscl current = 0x%x last = 0x%x\n", (void*)vscl, (void*)jobgp->last_vscl));
- if (core_status & MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) MALI_DEBUG_PRINT(1, ("plbcl current = 0x%x last = 0x%x\n", (void*)plbcl, (void*)jobgp->last_plbcl));
- if (jobgp->have_extended_progress_checking) MALI_DEBUG_PRINT(1, ("vertices processed = %d, last = %d\n", mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE),
- jobgp->vertices));
-#ifdef DEBUG
- maligp_print_regs(2, core);
-#endif
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
- MALI_PANIC("%s Watchdog timeout\n", MALI_GP_SUBSYSTEM_NAME);
- return JOB_STATUS_END_HANG;
- }
- /* if hang timeout checking was enabled and we detected progress, will be fall down to this check */
- /* check for PLBU OOM before the hang check to avoid the race condition of the hw wd trigging while waiting for us to handle the OOM interrupt */
- else if ( 0 != (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM))
- {
- mali_core_session *session;
- _mali_osk_notification_t *notific;
- _mali_uk_gp_job_suspended_s * suspended_job;
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
-#endif
-
- session = job->session;
-
- MALI_DEBUG_PRINT(4, ("OOM, new heap requested by GP\n"));
- MALI_DEBUG_PRINT(4, ("Status when OOM: current = 0x%x, end = 0x%x\n",
- (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR),
- (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR))
- );
-
- notific = _mali_osk_notification_create(
-
- _MALI_NOTIFICATION_GP_STALLED,
- sizeof( _mali_uk_gp_job_suspended_s )
- );
- if ( NULL == notific)
- {
- MALI_PRINT_ERROR( ("Mali GP: Could not get notification object\n")) ;
- return JOB_STATUS_END_OOM; /* Core is ready for more jobs.*/
- }
-
- core->state = CORE_WORKING;
- jobgp->is_stalled_waiting_for_more_memory = 1;
- suspended_job = (_mali_uk_gp_job_suspended_s *)notific->result_buffer; /* this is ok - result_buffer was malloc'd */
-
- suspended_job->user_job_ptr = jobgp->user_input.user_job_ptr;
- suspended_job->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY ;
- suspended_job->cookie = (u32) core;
- last_gp_core_cookie = core;
-
- _mali_osk_notification_queue_send( session->notification_queue, notific);
-
-#ifdef DEBUG
- maligp_print_regs(4, core);
-#endif
-
- /* stop all active timers */
- _mali_osk_timer_del( core->timer);
- _mali_osk_timer_del( core->timer_hang_detection);
- MALI_DEBUG_PRINT(4, ("Mali GP: PLBU heap empty, sending memory request to userspace\n"));
- /* save to watchdog_jiffies what was remaining WD timeout value when OOM was triggered */
- job->watchdog_jiffies = (long)job->watchdog_jiffies - (long)_mali_osk_time_tickcount();
- /* reuse core->timer as the userspace response timeout handler */
- _mali_osk_timer_add( core->timer, _mali_osk_time_mstoticks(1000) ); /* wait max 1 sec for userspace to respond */
- return JOB_STATUS_CONTINUE_RUN; /* The core is NOT available for new jobs. */
- }
- /* hw watchdog is reporting a new hang or an existing progress-during-hang check passed? */
- else if ((CORE_HANG_CHECK_TIMEOUT == core->state) || (irq_readout & jobgp->active_mask & MALIGP2_REG_VAL_IRQ_HANG))
- {
- /* check interval in ms */
- u32 timeout = mali_core_hang_check_timeout_get();
- MALI_DEBUG_PRINT(3, ("Mali GP: HW/SW Watchdog triggered, checking for progress in %d ms\n", timeout));
- core->state = CORE_WORKING;
-
- /* save state for the progress checking */
- jobgp->last_vscl = vscl;
- jobgp->last_plbcl = plbcl;
- if (jobgp->have_extended_progress_checking)
- {
- jobgp->vertices = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
- }
- /* hw watchdog triggered, set up a progress checker every HANGCHECK ms */
- _mali_osk_timer_add( core->timer_hang_detection, _mali_osk_time_mstoticks(timeout));
- jobgp->active_mask &= ~MALIGP2_REG_VAL_IRQ_HANG; /* ignore the hw watchdog from now on */
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask);
- return JOB_STATUS_CONTINUE_RUN; /* not finihsed */ }
- /* no errors, but still working */
- else if ( ( 0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ERROR)) &&
- ( 0 != (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE ))
- )
- {
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask);
- return JOB_STATUS_CONTINUE_RUN;
- }
- /* Else there must be some error */
- else
- {
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
-#endif
-
- MALI_PRINT( ("Mali GP: Core crashed? *IRQ: 0x%x Status: 0x%x\n", irq_readout, core_status ));
- #ifdef DEBUG
- MALI_DEBUG_PRINT(1, ("Mali GP: Registers Before reset:\n"));
- maligp_print_regs(1, core);
- #endif
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
- return JOB_STATUS_END_UNKNOWN_ERR;
- }
-}
-
-
-/* This function is called from the ioctl function and should return a mali_core_job pointer
-to a created mali_core_job object with the data given from userspace */
-static _mali_osk_errcode_t subsystem_maligp_get_new_job_from_user(struct mali_core_session * session, void * argument)
-{
- maligp_job *jobgp;
- mali_core_job *job = NULL;
- mali_core_job *previous_replaced_job;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
- _mali_uk_gp_start_job_s * user_ptr_job_input;
-
- user_ptr_job_input = (_mali_uk_gp_start_job_s *)argument;
-
- MALI_CHECK_NON_NULL(jobgp = (maligp_job *) _mali_osk_calloc(1, sizeof(maligp_job)), _MALI_OSK_ERR_FAULT);
-
- /* Copy the job data from the U/K interface */
- if ( NULL == _mali_osk_memcpy(&jobgp->user_input, user_ptr_job_input, sizeof(_mali_uk_gp_start_job_s) ) )
- {
- MALI_PRINT_ERROR( ("Mali GP: Could not copy data from U/K interface.\n")) ;
- err = _MALI_OSK_ERR_FAULT;
- goto function_exit;
- }
-
- MALI_DEBUG_PRINT(3, ("Mali GP: subsystem_maligp_get_new_job_from_user 0x%x\n", (void*)jobgp->user_input.user_job_ptr));
-
- MALI_DEBUG_PRINT(3, ("Mali GP: Job Regs: 0x%08X 0x%08X, 0x%08X 0x%08X 0x%08X 0x%08X\n",
- jobgp->user_input.frame_registers[0],
- jobgp->user_input.frame_registers[1],
- jobgp->user_input.frame_registers[2],
- jobgp->user_input.frame_registers[3],
- jobgp->user_input.frame_registers[4],
- jobgp->user_input.frame_registers[5]) );
-
-
- job = GET_JOB_EMBEDDED_PTR(jobgp);
-
- job->session = session;
- job->flags = MALI_UK_START_JOB_FLAG_DEFAULT; /* Current flags only make sence for PP jobs */
- job_priority_set(job, jobgp->user_input.priority);
- job_watchdog_set(job, jobgp->user_input.watchdog_msecs );
- jobgp->heap_current_addr = jobgp->user_input.frame_registers[4];
-
- job->abort_id = jobgp->user_input.abort_id;
-
- jobgp->is_stalled_waiting_for_more_memory = 0;
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- jobgp->pid = _mali_osk_get_pid();
- jobgp->tid = _mali_osk_get_tid();
-#endif
-
- if (mali_job_queue_full(session))
- {
- /* Cause jobgp to free: */
- user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
- goto function_exit;
- }
-
- /* We now know that we have a job, and a slot to put it in */
-
- jobgp->active_mask = MALIGP2_REG_VAL_IRQ_MASK_USED;
-
- /* Allocating User Return Data */
- jobgp->notification_obj = _mali_osk_notification_create(
- _MALI_NOTIFICATION_GP_FINISHED,
- sizeof(_mali_uk_gp_job_finished_s) );
-
- if ( NULL == jobgp->notification_obj )
- {
- MALI_PRINT_ERROR( ("Mali GP: Could not get notification_obj.\n")) ;
- err = _MALI_OSK_ERR_NOMEM;
- goto function_exit;
- }
-
- _MALI_OSK_INIT_LIST_HEAD( &(job->list) ) ;
-
- MALI_DEBUG_PRINT(4, ("Mali GP: Job: 0x%08x INPUT from user.\n", (u32)jobgp->user_input.user_job_ptr)) ;
-
- /* This should not happen since we have the checking of priority above */
- err = mali_core_session_add_job(session, job, &previous_replaced_job);
- if ( _MALI_OSK_ERR_OK != err )
- {
- MALI_PRINT_ERROR( ("Mali GP: Internal error\n")) ;
- /* Cause jobgp to free: */
- user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
- _mali_osk_notification_delete( jobgp->notification_obj );
- goto function_exit;
- }
-
- /* If MALI_TRUE: This session had a job with lower priority which were removed.
- This replaced job is given back to userspace. */
- if ( NULL != previous_replaced_job )
- {
- maligp_job *previous_replaced_jobgp;
-
- previous_replaced_jobgp = GET_JOBGP2_PTR(previous_replaced_job);
-
- MALI_DEBUG_PRINT(4, ("Mali GP: Replacing job: 0x%08x\n", (u32)previous_replaced_jobgp->user_input.user_job_ptr)) ;
-
- /* Copy to the input data (which also is output data) the
- pointer to the job that were replaced, so that the userspace
- driver can put this job in the front of its job-queue */
- user_ptr_job_input->returned_user_job_ptr = previous_replaced_jobgp->user_input.user_job_ptr;
-
- /** @note failure to 'copy to user' at this point must not free jobgp,
- * and so no transaction rollback required in the U/K interface */
-
- /* This does not cause jobgp to free: */
- user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED;
- MALI_DEBUG_PRINT(5, ("subsystem_maligp_get_new_job_from_user: Job added, prev returned\n")) ;
- }
- else
- {
- /* This does not cause jobgp to free: */
- user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED;
- MALI_DEBUG_PRINT(5, ("subsystem_maligp_get_new_job_from_user: Job added\n")) ;
- }
-
-function_exit:
- if ( _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE == user_ptr_job_input->status
- || _MALI_OSK_ERR_OK != err )
- {
- _mali_osk_free(jobgp);
- }
-#if MALI_STATE_TRACKING
- if (_MALI_UK_START_JOB_STARTED==user_ptr_job_input->status)
- {
- if(job)
- {
- job->job_nr=_mali_osk_atomic_inc_return(&session->jobs_received);
- }
- }
-#endif
-
- MALI_ERROR(err);
-}
-
-
-static _mali_osk_errcode_t subsystem_maligp_suspend_response(struct mali_core_session * session, void * argument)
-{
- mali_core_renderunit *core;
- maligp_job *jobgp;
- mali_core_job *job;
-
- _mali_uk_gp_suspend_response_s * suspend_response;
-
- MALI_DEBUG_PRINT(5, ("subsystem_maligp_suspend_response\n"));
-
- suspend_response = (_mali_uk_gp_suspend_response_s *)argument;
-
- /* We read job data from User */
- /* On a single mali_gp system we can only have one Stalled GP,
- and therefore one stalled request with a cookie. This checks
- that we get the correct cookie */
- if ( last_gp_core_cookie != (mali_core_renderunit *)suspend_response->cookie )
- {
- MALI_DEBUG_PRINT(2, ("Mali GP: Got an illegal cookie from Userspace.\n")) ;
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- core = (mali_core_renderunit *)suspend_response->cookie;
- last_gp_core_cookie = NULL;
- job = core->current_job;
- jobgp = GET_JOBGP2_PTR(job);
-
- switch( suspend_response->code )
- {
- case _MALIGP_JOB_RESUME_WITH_NEW_HEAP :
- MALI_DEBUG_PRINT(5, ("MALIGP_JOB_RESUME_WITH_NEW_HEAP jiffies: %li\n", _mali_osk_time_tickcount()));
- MALI_DEBUG_PRINT(4, ("New Heap addr 0x%08x - 0x%08x\n", suspend_response->arguments[0], suspend_response->arguments[1]));
-
- jobgp->is_stalled_waiting_for_more_memory = 0;
- job->watchdog_jiffies += _mali_osk_time_tickcount(); /* convert to absolute time again */
- _mali_osk_timer_mod( core->timer, job->watchdog_jiffies); /* update the timer */
-
-
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG));
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask);
- mali_core_renderunit_register_write_relaxed(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, suspend_response->arguments[0]);
- mali_core_renderunit_register_write_relaxed(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, suspend_response->arguments[1]);
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC);
- _mali_osk_write_mem_barrier();
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0);
-#endif
-
- MALI_DEBUG_PRINT(4, ("GP resumed with new heap\n"));
-
- break;
-
- case _MALIGP_JOB_ABORT:
- MALI_DEBUG_PRINT(3, ("MALIGP_JOB_ABORT on heap extend request\n"));
- _mali_osk_irq_schedulework( core->irq );
- break;
-
- default:
- MALI_PRINT_ERROR(("Wrong Suspend response from userspace\n"));
- }
- MALI_SUCCESS;
-}
-
-/* This function is called from the ioctl function and should write the necessary data
-to userspace telling which job was finished and the status and debuginfo for this job.
-The function must also free and cleanup the input job object. */
-static void subsystem_maligp_return_job_to_user( mali_core_job * job, mali_subsystem_job_end_code end_status )
-{
- maligp_job *jobgp;
- _mali_uk_gp_job_finished_s * job_out;
- _mali_uk_gp_start_job_s* job_input;
- mali_core_session *session;
-
-
- jobgp = _MALI_OSK_CONTAINER_OF(job, maligp_job, embedded_core_job);
- job_out = (_mali_uk_gp_job_finished_s *)jobgp->notification_obj->result_buffer; /* OK - this should've been malloc'd */
- job_input= &(jobgp->user_input);
- session = job->session;
-
- MALI_DEBUG_PRINT(5, ("Mali GP: Job: 0x%08x OUTPUT to user. Runtime: %d us, irq readout %x\n",
- (u32)jobgp->user_input.user_job_ptr,
- job->render_time_usecs,
- jobgp->irq_status)) ;
-
- _mali_osk_memset(job_out, 0 , sizeof(_mali_uk_gp_job_finished_s));
-
- job_out->user_job_ptr = job_input->user_job_ptr;
-
- switch( end_status )
- {
- case JOB_STATUS_CONTINUE_RUN:
- case JOB_STATUS_END_SUCCESS:
- case JOB_STATUS_END_OOM:
- case JOB_STATUS_END_ABORT:
- case JOB_STATUS_END_TIMEOUT_SW:
- case JOB_STATUS_END_HANG:
- case JOB_STATUS_END_SEG_FAULT:
- case JOB_STATUS_END_ILLEGAL_JOB:
- case JOB_STATUS_END_UNKNOWN_ERR:
- case JOB_STATUS_END_SHUTDOWN:
- case JOB_STATUS_END_SYSTEM_UNUSABLE:
- job_out->status = (mali_subsystem_job_end_code) end_status;
- break;
- default:
- job_out->status = JOB_STATUS_END_UNKNOWN_ERR ;
- }
-
- job_out->irq_status = jobgp->irq_status;
- job_out->status_reg_on_stop = jobgp->status_reg_on_stop;
- job_out->vscl_stop_addr = 0;
- job_out->plbcl_stop_addr = 0;
- job_out->heap_current_addr = jobgp->heap_current_addr;
- job_out->perf_counter0 = jobgp->perf_counter0;
- job_out->perf_counter1 = jobgp->perf_counter1;
- job_out->perf_counter_src0 = jobgp->user_input.perf_counter_src0 ;
- job_out->perf_counter_src1 = jobgp->user_input.perf_counter_src1 ;
- job_out->render_time = job->render_time_usecs;
-#if defined(USING_MALI400_L2_CACHE)
- job_out->perf_counter_l2_src0 = jobgp->perf_counter_l2_src0;
- job_out->perf_counter_l2_src1 = jobgp->perf_counter_l2_src1;
- job_out->perf_counter_l2_val0 = jobgp->perf_counter_l2_val0;
- job_out->perf_counter_l2_val1 = jobgp->perf_counter_l2_val1;
-#endif
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&session->jobs_returned);
-#endif
- _mali_osk_notification_queue_send( session->notification_queue, jobgp->notification_obj);
- jobgp->notification_obj = NULL;
-
- _mali_osk_free(jobgp);
-
- last_gp_core_cookie = NULL;
-}
-
-static void subsystem_maligp_renderunit_delete(mali_core_renderunit * core)
-{
- MALI_DEBUG_PRINT(5, ("Mali GP: maligp_renderunit_delete\n"));
- _mali_osk_free(core);
-}
-
-static void subsystem_maligp_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style)
-{
- MALI_DEBUG_PRINT(5, ("Mali GP: renderunit_reset_core\n"));
-
- switch (style)
- {
- case MALI_CORE_RESET_STYLE_RUNABLE:
- maligp_reset(core);
- break;
- case MALI_CORE_RESET_STYLE_DISABLE:
- maligp_raw_reset(core); /* do the raw reset */
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* then disable the IRQs */
- break;
- case MALI_CORE_RESET_STYLE_HARD:
- maligp_reset_hard(core);
- maligp_initialize_registers_mgmt(core);
- break;
- default:
- MALI_DEBUG_PRINT(1, ("Unknown reset type %d\n", style));
- break;
- }
-}
-
-static void subsystem_maligp_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core)
-{
- mali_core_renderunit_register_write(core , MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
- mali_core_renderunit_register_write(core , MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG );
- _mali_osk_mem_barrier();
-}
-
-static _mali_osk_errcode_t subsystem_maligp_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core)
-{
- u32 irq_readout;
-
- irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
-
- if ( MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout )
- {
- mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG);
- _mali_osk_mem_barrier();
- MALI_SUCCESS;
- }
-
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
-}
-
-_mali_osk_errcode_t _mali_ukk_gp_start_job( _mali_uk_gp_start_job_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_start_job(session, args);
-}
-
-_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_number_of_cores_get(session, &args->number_of_cores);
-}
-
-_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_core_version_get(session, &args->version);
-}
-
-_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_suspend_response(session, args);
-}
-
-void _mali_ukk_gp_abort_job( _mali_uk_gp_abort_job_s * args)
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- if (NULL == args->ctx) return;
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
- if (NULL == session) return;
- mali_core_subsystem_ioctl_abort_job(session, args->abort_id);
-
-}
-
-#if USING_MALI_PMM
-
-_mali_osk_errcode_t maligp_signal_power_up( mali_bool queue_only )
-{
- MALI_DEBUG_PRINT(4, ("Mali GP: signal power up core - queue_only: %d\n", queue_only ));
-
- return( mali_core_subsystem_signal_power_up( &subsystem_maligp, 0, queue_only ) );
-}
-
-_mali_osk_errcode_t maligp_signal_power_down( mali_bool immediate_only )
-{
- MALI_DEBUG_PRINT(4, ("Mali GP: signal power down core - immediate_only: %d\n", immediate_only ));
-
- return( mali_core_subsystem_signal_power_down( &subsystem_maligp, 0, immediate_only ) );
-}
-
-#endif
-
-#if MALI_STATE_TRACKING
-u32 maligp_subsystem_dump_state(char *buf, u32 size)
-{
- return mali_core_renderunit_dump_state(&subsystem_maligp, buf, size);
-}
-#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c b/drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c
deleted file mode 100644
index 0f5ebd0..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c
+++ /dev/null
@@ -1,1304 +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.
- */
-
-//added for SPI
-#include <linux/kernel.h>
-
-#include "mali_kernel_common.h"
-#include "mali_osk.h"
-#include "mali_kernel_pp.h"
-#include "mali_kernel_subsystem.h"
-#include "mali_kernel_core.h"
-#include "regs/mali_200_regs.h"
-#include "mali_kernel_rendercore.h"
-#if MALI_TIMELINE_PROFILING_ENABLED
-#include "mali_kernel_profiling.h"
-#endif
-#ifdef USING_MALI400_L2_CACHE
-#include "mali_kernel_l2_cache.h"
-#endif
-#if USING_MMU
-#include "mali_kernel_mem_mmu.h" /* Needed for mali_kernel_mmu_force_bus_reset() */
-#endif
-
-#include "mali_osk_list.h"
-
-#if defined(USING_MALI200)
-#define MALI_PP_SUBSYSTEM_NAME "Mali200"
-#define MALI_PP_CORE_TYPE _MALI_200
-#elif defined(USING_MALI400)
-#define MALI_PP_SUBSYSTEM_NAME "Mali-400 PP"
-#define MALI_PP_CORE_TYPE _MALI_400_PP
-#else
-#error "No supported mali core defined"
-#endif
-
-#define GET_JOB_EMBEDDED_PTR(job) (&((job)->embedded_core_job))
-#define GET_JOB200_PTR(job_extern) _MALI_OSK_CONTAINER_OF(job_extern, mali200_job, embedded_core_job)
-
-/* Initialized when this subsystem is initialized. This is determined by the
- * position in subsystems[], and so the value used to initialize this is
- * determined at compile time */
-static mali_kernel_subsystem_identifier mali_subsystem_mali200_id = -1;
-
-/* Describing a mali200 job settings */
-typedef struct mali200_job
-{
- /* The general job struct common for all mali cores */
- mali_core_job embedded_core_job;
- _mali_uk_pp_start_job_s user_input;
-
- u32 irq_status;
- u32 perf_counter0;
- u32 perf_counter1;
- u32 last_tile_list_addr; /* Neccessary to continue a stopped job */
-
- u32 active_mask;
-
- /* The data we will return back to the user */
- _mali_osk_notification_t *notification_obj;
-
-#if defined(USING_MALI400_L2_CACHE)
- u32 perf_counter_l2_src0;
- u32 perf_counter_l2_src1;
- u32 perf_counter_l2_val0;
- u32 perf_counter_l2_val1;
- u32 perf_counter_l2_val0_raw;
- u32 perf_counter_l2_val1_raw;
-#endif
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- u32 pid;
- u32 tid;
-#endif
-} mali200_job;
-
-
-/*Functions Exposed to the General External System through
- funciont pointers.*/
-
-static _mali_osk_errcode_t mali200_subsystem_startup(mali_kernel_subsystem_identifier id);
-#if USING_MMU
-static _mali_osk_errcode_t mali200_subsystem_mmu_connect(mali_kernel_subsystem_identifier id);
-#endif
-static void mali200_subsystem_terminate(mali_kernel_subsystem_identifier id);
-static _mali_osk_errcode_t mali200_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
-static void mali200_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
-static _mali_osk_errcode_t mali200_subsystem_core_system_info_fill(_mali_system_info* info);
-static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * resource);
-#if USING_MMU
-static void mali200_subsystem_broadcast_notification(mali_core_notification_message message, u32 data);
-#endif
-#if MALI_STATE_TRACKING
-u32 mali200_subsystem_dump_state(char *buf, u32 size);
-#endif
-
-/* Internal support functions */
-static _mali_osk_errcode_t mali200_core_version_legal( mali_core_renderunit *core );
-static void mali200_reset(mali_core_renderunit *core);
-static void mali200_reset_hard(struct mali_core_renderunit * core);
-static void mali200_raw_reset(mali_core_renderunit * core);
-static void mali200_initialize_registers_mgmt(mali_core_renderunit *core );
-
-/* Functions exposed to mali_core system through functionpointers
- in the subsystem struct. */
-static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali_core_renderunit * core);
-static _mali_osk_errcode_t subsystem_mali200_get_new_job_from_user(struct mali_core_session * session, void * argument);
-static void subsystem_mali200_return_job_to_user( mali_core_job * job, mali_subsystem_job_end_code end_status);
-static void subsystem_mali200_renderunit_delete(mali_core_renderunit * core);
-static void subsystem_mali200_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style);
-static void subsystem_mali200_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core);
-static _mali_osk_errcode_t subsystem_mali200_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core);
-
-static void subsystem_mali200_renderunit_stop_bus(struct mali_core_renderunit* core);
-static u32 subsystem_mali200_irq_handler_upper_half(struct mali_core_renderunit * core);
-static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit* core);
-
-/* This will be one of the subsystems in the array of subsystems:
- static struct mali_kernel_subsystem * subsystems[];
- found in file: mali_kernel_core.c
-*/
-
-struct mali_kernel_subsystem mali_subsystem_mali200=
-{
- mali200_subsystem_startup, /* startup */
- NULL, /*mali200_subsystem_terminate,*/ /* shutdown */
-#if USING_MMU
- mali200_subsystem_mmu_connect, /* load_complete */
-#else
- NULL,
-#endif
- mali200_subsystem_core_system_info_fill, /* system_info_fill */
- mali200_subsystem_session_begin, /* session_begin */
- mali200_subsystem_session_end, /* session_end */
-#if USING_MMU
- mali200_subsystem_broadcast_notification, /* broadcast_notification */
-#else
- NULL,
-#endif
-#if MALI_STATE_TRACKING
- mali200_subsystem_dump_state, /* dump_state */
-#endif
-} ;
-
-static mali_core_subsystem subsystem_mali200 ;
-
-static _mali_osk_errcode_t mali200_subsystem_startup(mali_kernel_subsystem_identifier id)
-{
- mali_core_subsystem * subsystem;
-
- MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_startup\n") ) ;
-
- mali_subsystem_mali200_id = id;
-
- /* All values get 0 as default */
- _mali_osk_memset(&subsystem_mali200, 0, sizeof(subsystem_mali200));
-
- subsystem = &subsystem_mali200;
- subsystem->start_job = &subsystem_mali200_start_job;
- subsystem->irq_handler_upper_half = &subsystem_mali200_irq_handler_upper_half;
- subsystem->irq_handler_bottom_half = &subsystem_mali200_irq_handler_bottom_half;
- subsystem->get_new_job_from_user = &subsystem_mali200_get_new_job_from_user;
- subsystem->return_job_to_user = &subsystem_mali200_return_job_to_user;
- subsystem->renderunit_delete = &subsystem_mali200_renderunit_delete;
- subsystem->reset_core = &subsystem_mali200_renderunit_reset_core;
- subsystem->stop_bus = &subsystem_mali200_renderunit_stop_bus;
- subsystem->probe_core_irq_trigger = &subsystem_mali200_renderunit_probe_core_irq_trigger;
- subsystem->probe_core_irq_acknowledge = &subsystem_mali200_renderunit_probe_core_irq_finished;
-
- /* Setting variables in the general core part of the subsystem.*/
- subsystem->name = MALI_PP_SUBSYSTEM_NAME;
- subsystem->core_type = MALI_PP_CORE_TYPE;
- subsystem->id = id;
-
- /* Initiates the rest of the general core part of the subsystem */
- MALI_CHECK_NO_ERROR(mali_core_subsystem_init( subsystem ));
-
- /* This will register the function for adding MALI200 cores to the subsystem */
-#if defined(USING_MALI200)
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALI200, mali200_renderunit_create));
-#endif
-#if defined(USING_MALI400)
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALI400PP, mali200_renderunit_create));
-#endif
-
- MALI_DEBUG_PRINT(6, ("Mali PP: mali200_subsystem_startup\n") ) ;
-
- MALI_SUCCESS;
-}
-
-#if USING_MMU
-static _mali_osk_errcode_t mali200_subsystem_mmu_connect(mali_kernel_subsystem_identifier id)
-{
- mali_core_subsystem_attach_mmu(&subsystem_mali200);
- MALI_SUCCESS; /* OK */
-}
-#endif
-
-static void mali200_subsystem_terminate(mali_kernel_subsystem_identifier id)
-{
- MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_terminate\n") ) ;
- mali_core_subsystem_cleanup(&subsystem_mali200);
-}
-
-static _mali_osk_errcode_t mali200_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
-{
- mali_core_session * session;
-
- MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_session_begin\n") ) ;
- MALI_CHECK_NON_NULL(session = _mali_osk_malloc( sizeof(mali_core_session) ), _MALI_OSK_ERR_NOMEM);
-
- _mali_osk_memset(session, 0, sizeof(*session) );
- *slot = (mali_kernel_subsystem_session_slot)session;
-
- session->subsystem = &subsystem_mali200;
-
- session->notification_queue = queue;
-
-#if USING_MMU
- session->mmu_session = mali_session_data;
-#endif
-
- mali_core_session_begin(session);
-
- MALI_DEBUG_PRINT(6, ("Mali PP: mali200_subsystem_session_begin\n") ) ;
-
- MALI_SUCCESS;
-}
-
-static void mali200_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
-{
- mali_core_session * session;
-
- MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_session_end\n") ) ;
- if ( NULL==slot || NULL==*slot)
- {
- MALI_PRINT_ERROR(("Input slot==NULL"));
- return;
- }
- session = (mali_core_session*) *slot;
- mali_core_session_close(session);
-
- _mali_osk_free(session);
- *slot = NULL;
-
- MALI_DEBUG_PRINT(6, ("Mali PP: mali200_subsystem_session_end\n") ) ;
-}
-
-/**
- * We fill in info about all the cores we have
- * @param info Pointer to system info struct to update
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali200_subsystem_core_system_info_fill(_mali_system_info* info)
-{
- return mali_core_subsystem_system_info_fill(&subsystem_mali200, info);
-}
-
-
-static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * resource)
-{
- mali_core_renderunit *core;
- _mali_osk_errcode_t err;
-
- MALI_DEBUG_PRINT(3, ("Mali PP: mali200_renderunit_create\n") ) ;
- /* Checking that the resource settings are correct */
-#if defined(USING_MALI200)
- if(MALI200 != resource->type)
- {
- MALI_PRINT_ERROR(("Can not register this resource as a " MALI_PP_SUBSYSTEM_NAME " core."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#elif defined(USING_MALI400)
- if(MALI400PP != resource->type)
- {
- MALI_PRINT_ERROR(("Can not register this resource as a " MALI_PP_SUBSYSTEM_NAME " core."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#endif
- if ( 0 != resource->size )
- {
- MALI_PRINT_ERROR(("Memory size set to " MALI_PP_SUBSYSTEM_NAME " core should be zero."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- if ( NULL == resource->description )
- {
- MALI_PRINT_ERROR(("A " MALI_PP_SUBSYSTEM_NAME " core needs a unique description field"));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* Create a new core object */
- core = (mali_core_renderunit*) _mali_osk_malloc(sizeof(*core));
- if ( NULL == core )
- {
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- /* Variables set to be able to open and register the core */
- core->subsystem = &subsystem_mali200 ;
- core->registers_base_addr = resource->base ;
- core->size = MALI200_REG_SIZEOF_REGISTER_BANK ;
- core->irq_nr = resource->irq ;
- core->description = resource->description;
-#if USING_MMU
- core->mmu_id = resource->mmu_id;
- core->mmu = NULL;
-#endif
-#if USING_MALI_PMM
- /* Set up core's PMM id */
- switch( subsystem_mali200.number_of_cores )
- {
- case 0:
- core->pmm_id = MALI_PMM_CORE_PP0;
- break;
- case 1:
- core->pmm_id = MALI_PMM_CORE_PP1;
- break;
- case 2:
- core->pmm_id = MALI_PMM_CORE_PP2;
- break;
- case 3:
- core->pmm_id = MALI_PMM_CORE_PP3;
- break;
- default:
- MALI_DEBUG_PRINT(1, ("Unknown supported core for PMM\n"));
- err = _MALI_OSK_ERR_FAULT;
- goto exit_on_error0;
- }
-#endif
-
- err = mali_core_renderunit_init( core );
- if (_MALI_OSK_ERR_OK != err)
- {
- MALI_DEBUG_PRINT(1, ("Failed to initialize renderunit\n"));
- goto exit_on_error0;
- }
-
- /* Map the new core object, setting: core->registers_mapped */
- err = mali_core_renderunit_map_registers(core);
- if (_MALI_OSK_ERR_OK != err)
- {
- MALI_DEBUG_PRINT(1, ("Failed to map register\n"));
- goto exit_on_error1;
- }
-
- /* Check that the register mapping of the core works.
- Return 0 if Mali PP core is present and accessible. */
- if (mali_benchmark) {
-#if defined(USING_MALI200)
- core->core_version = (((u32)MALI_PP_PRODUCT_ID) << 16) | 5 /* Fake Mali200-r0p5 */;
-#elif defined(USING_MALI400)
- core->core_version = (((u32)MALI_PP_PRODUCT_ID) << 16) | 0x0101 /* Fake Mali400-r1p1 */;
-#else
-#error "No supported mali core defined"
-#endif
- } else {
- core->core_version = mali_core_renderunit_register_read(
- core,
- MALI200_REG_ADDR_MGMT_VERSION);
- }
-
- err = mali200_core_version_legal(core);
- if (_MALI_OSK_ERR_OK != err)
- {
- MALI_DEBUG_PRINT(1, ("Invalid core\n"));
- goto exit_on_error2;
- }
-
- /* Reset the core. Put the core into a state where it can start to render. */
- mali200_reset(core);
-
- /* Registering IRQ, init the work_queue_irq_handle */
- /* Adding this core as an available renderunit in the subsystem. */
- err = mali_core_subsystem_register_renderunit(&subsystem_mali200, core);
- if (_MALI_OSK_ERR_OK != err)
- {
- MALI_DEBUG_PRINT(1, ("Failed to register with core\n"));
- goto exit_on_error2;
- }
- MALI_DEBUG_PRINT(6, ("Mali PP: mali200_renderunit_create\n") ) ;
-
- MALI_SUCCESS;
-
-exit_on_error2:
- mali_core_renderunit_unmap_registers(core);
-exit_on_error1:
- mali_core_renderunit_term(core);
-exit_on_error0:
- _mali_osk_free( core ) ;
- MALI_PRINT_ERROR(("Renderunit NOT created."));
- MALI_ERROR(err);
-}
-
-#if USING_MMU
-/* Used currently only for signalling when MMU has a pagefault */
-static void mali200_subsystem_broadcast_notification(mali_core_notification_message message, u32 data)
-{
- mali_core_subsystem_broadcast_notification(&subsystem_mali200, message, data);
-}
-#endif
-
-static _mali_osk_errcode_t mali200_core_version_legal( mali_core_renderunit *core )
-{
- u32 mali_type;
-
- mali_type = core->core_version >> 16;
-#if defined(USING_MALI400)
- /* Mali300 and Mali400 is compatible, accept either core. */
- if (MALI400_PP_PRODUCT_ID != mali_type && MALI300_PP_PRODUCT_ID != mali_type)
-#else
- if (MALI_PP_PRODUCT_ID != mali_type)
-#endif
- {
- MALI_PRINT_ERROR(("Error: reading this from " MALI_PP_SUBSYSTEM_NAME " version register: 0x%x\n", core->core_version));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- MALI_DEBUG_PRINT(3, ("Mali PP: core_version_legal: Reads correct mali version: %d\n", mali_type) ) ;
- MALI_SUCCESS;
-}
-
-static void subsystem_mali200_renderunit_stop_bus(struct mali_core_renderunit* core)
-{
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
-}
-
-static void mali200_raw_reset( mali_core_renderunit *core )
-{
- int i;
- const int request_loop_count = 20;
-
- MALI_DEBUG_PRINT(4, ("Mali PP: mali200_raw_reset: %s\n", core->description));
- if (mali_benchmark) return;
-
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable IRQs */
-
-#if defined(USING_MALI200)
-
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
-
- for (i = 0; i < request_loop_count; i++)
- {
- if (mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) break;
- _mali_osk_time_ubusydelay(10);
- }
-
- MALI_DEBUG_PRINT_IF(1, request_loop_count == i, ("Mali PP: Bus was never stopped during core reset\n"));
-
-
- if (request_loop_count==i)
- {
-#if USING_MMU
- if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
- {
- /* Could not stop bus connections from core, probably because some of the already pending
- bus request has had a page fault, and therefore can not complete before the MMU does PageFault
- handling. This can be treated as a heavier reset function - which unfortunately reset all
- the cores on this MMU in addition to the MMU itself */
- MALI_DEBUG_PRINT(1, ("Mali PP: Forcing Bus reset\n"));
- mali_kernel_mmu_force_bus_reset(core->mmu);
- return;
- }
-#endif
- MALI_PRINT(("A MMU reset did not allow PP to stop its bus, system failure, unable to recover\n"));
- return;
- }
-
- /* use the hard reset routine to do the actual reset */
- mali200_reset_hard(core);
-
-#elif defined(USING_MALI400)
-
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED);
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);
-
- for (i = 0; i < request_loop_count; i++)
- {
- if (mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) break;
- _mali_osk_time_ubusydelay(10);
- }
-
- if (request_loop_count==i)
- {
-#if USING_MMU
- if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
- {
- /* Could not stop bus connections from core, probably because some of the already pending
- bus request has had a page fault, and therefore can not complete before the MMU does PageFault
- handling. This can be treated as a heavier reset function - which unfortunately reset all
- the cores on this MMU in addition to the MMU itself */
- MALI_DEBUG_PRINT(1, ("Mali PP: Forcing Bus reset\n"));
- mali_kernel_mmu_force_bus_reset(core->mmu);
- return;
- }
-#endif
- MALI_PRINT(("A MMU reset did not allow PP to stop its bus, system failure, unable to recover\n"));
- return;
- }
- else
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
-
-#else
-#error "no supported mali core defined"
-#endif
-}
-
-static void mali200_reset( mali_core_renderunit *core )
-{
- if (!mali_benchmark) {
- mali200_raw_reset(core);
- mali200_initialize_registers_mgmt(core);
- }
-}
-
-/* Sets the registers on mali200 according to the const default_mgmt_regs array. */
-static void mali200_initialize_registers_mgmt(mali_core_renderunit *core )
-{
- MALI_DEBUG_PRINT(6, ("Mali PP: mali200_initialize_registers_mgmt: %s\n", core->description)) ;
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
-}
-
-/* Start this job on this core. Return MALI_TRUE if the job was started. */
-static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali_core_renderunit * core)
-{
- mali200_job *job200;
-
- /* The local extended version of the general structs */
- job200 = _MALI_OSK_CONTAINER_OF(job, mali200_job, embedded_core_job);
-
- if ( (0 == job200->user_input.frame_registers[0]) ||
- (0 == job200->user_input.frame_registers[1]) )
- {
- MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x WILL NOT START SINCE JOB HAS ILLEGAL ADDRESSES\n",
- (u32)job200->user_input.user_job_ptr));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x START_RENDER Tile_list: 0x%08x\n",
- (u32)job200->user_input.user_job_ptr,
- job200->user_input.frame_registers[0]));
- MALI_DEBUG_PRINT(6, ("Mali PP: RSW base addr: 0x%08x Vertex base addr: 0x%08x\n",
- job200->user_input.frame_registers[1], job200->user_input.frame_registers[2]));
-
- /* Frame registers. Copy from mem to physical registers */
- mali_core_renderunit_register_write_array(
- core,
- MALI200_REG_ADDR_FRAME,
- &(job200->user_input.frame_registers[0]),
- MALI200_NUM_REGS_FRAME);
-
- /* Write Back unit 0. Copy from mem to physical registers only if the WB unit will be used. */
- if (job200->user_input.wb0_registers[0])
- {
- mali_core_renderunit_register_write_array(
- core,
- MALI200_REG_ADDR_WB0,
- &(job200->user_input.wb0_registers[0]),
- MALI200_NUM_REGS_WBx);
- }
-
- /* Write Back unit 1. Copy from mem to physical registers only if the WB unit will be used. */
- if (job200->user_input.wb1_registers[0])
- {
- mali_core_renderunit_register_write_array(
- core,
- MALI200_REG_ADDR_WB1,
- &(job200->user_input.wb1_registers[0]),
- MALI200_NUM_REGS_WBx);
- }
-
- /* Write Back unit 2. Copy from mem to physical registers only if the WB unit will be used. */
- if (job200->user_input.wb2_registers[0])
- {
- mali_core_renderunit_register_write_array(
- core,
- MALI200_REG_ADDR_WB2,
- &(job200->user_input.wb2_registers[0]),
- MALI200_NUM_REGS_WBx);
- }
-
-#if MALI_TRACEPOINTS_ENABLED
- {
- int counter = ((core->core_number)*2)+9; /* magic numbers for FP0 are 9 & 10 */
-
- //printk("FP core->number = %d\n", core->core_number);
- //TODO we are using magic numbers again... these are from gator_events_mali.c
- job200->user_input.perf_counter_flag = 0;
-
- if( counter>=9 && counter<=16) {
-
- if( counter_table[counter] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE;
- job200->user_input.perf_counter_src0 = counter_table[counter];
- }
- if( counter_table[counter+1] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE;
- job200->user_input.perf_counter_src1 = counter_table[counter+1];
- }
-
- } else {
- MALI_DEBUG_PRINT(2, ("core->core_number out of the range (0-3) (%d)\n", core->core_number));
- }
- }
-#if defined(USING_MALI400_L2_CACHE)
- if( counter_table[5] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE | _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET;
- job200->user_input.perf_counter_l2_src0 = counter_table[5];
- }
- if( counter_table[6] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE | _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET;
- job200->user_input.perf_counter_l2_src1 = counter_table[6];
- }
-#endif
-#endif
-
- /* This selects which performance counters we are reading */
- if ( 0 != job200->user_input.perf_counter_flag )
- {
- if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
- {
- mali_core_renderunit_register_write_relaxed(
- core,
- MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE,
- MALI200_REG_VAL_PERF_CNT_ENABLE);
- mali_core_renderunit_register_write_relaxed(
- core,
- MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC,
- job200->user_input.perf_counter_src0);
-
- }
-
- if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
- {
- mali_core_renderunit_register_write_relaxed(
- core,
- MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE,
- MALI200_REG_VAL_PERF_CNT_ENABLE);
- mali_core_renderunit_register_write_relaxed(
- core,
- MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC,
- job200->user_input.perf_counter_src1);
-
- }
-
-#if defined(USING_MALI400_L2_CACHE)
- if ( job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
- {
- int force_reset = ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET ) ? 1 : 0;
- u32 src0 = 0;
- u32 src1 = 0;
-
- if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE )
- {
- src0 = job200->user_input.perf_counter_l2_src0;
- }
- if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE )
- {
- src1 = job200->user_input.perf_counter_l2_src1;
- }
-
- mali_kernel_l2_cache_set_perf_counters(src0, src1, force_reset); /* will activate and possibly reset counters */
-
- /* Now, retrieve the current values, so we can substract them when the job has completed */
- mali_kernel_l2_cache_get_perf_counters(&job200->perf_counter_l2_src0,
- &job200->perf_counter_l2_val0,
- &job200->perf_counter_l2_src1,
- &job200->perf_counter_l2_val1);
- }
-#endif
- }
-
- subsystem_flush_mapped_mem_cache();
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_started);
-#endif
-
- /* This is the command that starts the Core */
- mali_core_renderunit_register_write(
- core,
- MALI200_REG_ADDR_MGMT_CTRL_MGMT,
- MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
- _mali_osk_write_mem_barrier();
-
-
- pr_debug("SPI_GPU_PP%u Start\n", core->core_number);
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job200->user_input.frame_builder_id, job200->user_input.flush_id, 0, 0, 0);
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), job200->pid, job200->tid,
-#if defined(USING_MALI400_L2_CACHE)
- (job200->user_input.perf_counter_l2_src0 << 16) | (job200->user_input.perf_counter_l2_src1 << 24),
- job200->perf_counter_l2_val0, job200->perf_counter_l2_val1
-#else
- 0, 0, 0
-#endif
- );
-#endif
-
- MALI_SUCCESS;
-}
-
-static u32 subsystem_mali200_irq_handler_upper_half(mali_core_renderunit * core)
-{
- u32 irq_readout;
-
- if (mali_benchmark) {
- return (core->current_job ? 1 : 0); /* simulate irq is pending when a job is pending */
- }
-
- MALI_DEBUG_PRINT(5, ("Mali PP: subsystem_mali200_irq_handler_upper_half: %s\n", core->description)) ;
- irq_readout = mali_core_renderunit_register_read(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_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
-#endif
-
- return 1;
- }
- return 0;
-}
-
-static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit* core)
-{
- u32 irq_readout;
- u32 current_tile_addr;
- u32 core_status;
- mali_core_job * job;
- mali200_job * job200;
-
- job = core->current_job;
- job200 = GET_JOB200_PTR(job);
-
-
- if (mali_benchmark) {
- irq_readout = MALI200_REG_VAL_IRQ_END_OF_FRAME;
- current_tile_addr = 0;
- core_status = 0;
- } else {
- irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
- current_tile_addr = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR);
- core_status = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_STATUS);
- }
-
- if (NULL == job)
- {
- MALI_DEBUG_ASSERT(CORE_IDLE==core->state);
- if ( 0 != irq_readout )
- {
- MALI_PRINT_ERROR(("Interrupt from a core not running a job. IRQ: 0x%04x Status: 0x%04x", irq_readout, core_status));
- }
- return JOB_STATUS_END_UNKNOWN_ERR;
- }
- MALI_DEBUG_ASSERT(CORE_IDLE!=core->state);
-
- job200->irq_status |= irq_readout;
-
- MALI_DEBUG_PRINT_IF( 3, ( 0 != irq_readout ),
- ("Mali PP: Job: 0x%08x IRQ RECEIVED Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n",
- (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status));
-
- if ( MALI200_REG_VAL_IRQ_END_OF_FRAME & irq_readout)
- {
-#if defined(USING_MALI200)
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES);
-#endif
-
- if (0 != job200->user_input.perf_counter_flag )
- {
- if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
- {
-#if MALI_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- unsigned int counter = (core->core_number * 2) + 9;
-#endif
-
- job200->perf_counter0 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
- job200->perf_counter1 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
-
-#if MALI_TRACEPOINTS_ENABLED
- _mali_profiling_add_counter(counter, job200->perf_counter0);
- _mali_profiling_add_counter(counter + 1, job200->perf_counter1);
-#endif
-
- }
-
-#if defined(USING_MALI400_L2_CACHE)
- if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
- {
- u32 src0;
- u32 val0;
- u32 src1;
- u32 val1;
- mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);
-
- if (job200->perf_counter_l2_src0 == src0)
- {
- job200->perf_counter_l2_val0_raw = val0;
- job200->perf_counter_l2_val0 = val0 - job200->perf_counter_l2_val0;
- }
- else
- {
- job200->perf_counter_l2_val0_raw = 0;
- job200->perf_counter_l2_val0 = 0;
- }
-
- if (job200->perf_counter_l2_src1 == src1)
- {
- job200->perf_counter_l2_val1_raw = val1;
- job200->perf_counter_l2_val1 = val1 - job200->perf_counter_l2_val1;
- }
- else
- {
- job200->perf_counter_l2_val1_raw = 0;
- job200->perf_counter_l2_val1 = 0;
- }
-
-#if MALI_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- _mali_profiling_add_counter(5, val0);
- _mali_profiling_add_counter(6, val1);
-#endif
- }
-#endif
-
- }
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number),
- job200->perf_counter0, job200->perf_counter1,
- job200->user_input.perf_counter_src0 | (job200->user_input.perf_counter_src1 << 8)
-#if defined(USING_MALI400_L2_CACHE)
- | (job200->user_input.perf_counter_l2_src0 << 16) | (job200->user_input.perf_counter_l2_src1 << 24),
- job200->perf_counter_l2_val0, job200->perf_counter_l2_val1
-#else
- , 0, 0
-#endif
- );
-#endif
-
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
-
- pr_debug("SPI_GPU_PP%u Idle\n", core->core_number);
-
- return JOB_STATUS_END_SUCCESS; /* reschedule */
- }
- /* Overall SW watchdog timeout or (time to do hang checking and progress detected)? */
- else if (
- (CORE_WATCHDOG_TIMEOUT == core->state) ||
- ((CORE_HANG_CHECK_TIMEOUT == core->state) && (current_tile_addr == job200->last_tile_list_addr))
- )
- {
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */
-#endif
- /* no progress detected, killed by the watchdog */
- MALI_PRINT( ("M200: SW-Timeout Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x.\n", irq_readout ,current_tile_addr ,core_status) );
- /* In this case will the system outside cleanup and reset the core */
-
- MALI_PANIC("%s Watchdog timeout (rawstat: 0x%x tile_addr: 0x%x status: 0x%x)\n", MALI_PP_SUBSYSTEM_NAME, irq_readout, current_tile_addr, core_status);
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
-
- return JOB_STATUS_END_HANG;
- }
- /* HW watchdog triggered or an existing hang check passed? */
- else if ((CORE_HANG_CHECK_TIMEOUT == core->state) || (irq_readout & job200->active_mask & MALI200_REG_VAL_IRQ_HANG))
- {
- /* check interval in ms */
- u32 timeout = mali_core_hang_check_timeout_get();
- MALI_PRINT( ("M200: HW/SW Watchdog triggered, checking for progress in %d ms\n", timeout));
- job200->last_tile_list_addr = current_tile_addr;
- /* hw watchdog triggered, set up a progress checker every HANGCHECK ms */
- _mali_osk_timer_add(core->timer_hang_detection, _mali_osk_time_mstoticks(timeout));
- job200->active_mask &= ~MALI200_REG_VAL_IRQ_HANG; /* ignore the hw watchdoig from now on */
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout & ~MALI200_REG_VAL_IRQ_HANG);
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask);
- return JOB_STATUS_CONTINUE_RUN; /* not finished */
- }
- /* No irq pending, core still busy */
- else if ((0 == (irq_readout & MALI200_REG_VAL_IRQ_MASK_USED)) && ( 0 != (core_status & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)))
- {
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask);
- return JOB_STATUS_CONTINUE_RUN; /* Not finished */
- }
- else
- {
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */
-#endif
-
- MALI_PRINT( ("Mali PP: Job: 0x%08x CRASH? Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n",
- (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status) ) ;
-
- if (irq_readout & MALI200_REG_VAL_IRQ_BUS_ERROR)
- {
- u32 bus_error = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS);
-
- MALI_PRINT(("Bus error status: 0x%08X\n", bus_error));
- MALI_DEBUG_PRINT_IF(1, (bus_error & 0x01), ("Bus write error from id 0x%02x\n", (bus_error>>2) & 0x0F));
- MALI_DEBUG_PRINT_IF(1, (bus_error & 0x02), ("Bus read error from id 0x%02x\n", (bus_error>>6) & 0x0F));
- MALI_DEBUG_PRINT_IF(1, (0 == (bus_error & 0x03)), ("Bus error but neither read or write was set as the error reason\n"));
- (void)bus_error;
- }
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
- return JOB_STATUS_END_UNKNOWN_ERR; /* reschedule */
- }
-}
-
-
-/* This function is called from the ioctl function and should return a mali_core_job pointer
-to a created mali_core_job object with the data given from userspace */
-static _mali_osk_errcode_t subsystem_mali200_get_new_job_from_user(struct mali_core_session * session, void * argument)
-{
- mali200_job *job200;
- mali_core_job *job = NULL;
- mali_core_job *previous_replaced_job;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
- _mali_uk_pp_start_job_s * user_ptr_job_input;
-
- user_ptr_job_input = (_mali_uk_pp_start_job_s *)argument;
-
- MALI_CHECK_NON_NULL(job200 = (mali200_job *) _mali_osk_malloc(sizeof(mali200_job)), _MALI_OSK_ERR_NOMEM);
- _mali_osk_memset(job200, 0 , sizeof(mali200_job) );
-
- /* We read job data from Userspace pointer */
- if ( NULL == _mali_osk_memcpy((void*)&job200->user_input, user_ptr_job_input, sizeof(job200->user_input)) )
- {
- MALI_PRINT_ERROR( ("Mali PP: Could not copy data from U/K interface.\n")) ;
- err = _MALI_OSK_ERR_FAULT;
- goto function_exit;
- }
-
- MALI_DEBUG_PRINT(5, ("Mali PP: subsystem_mali200_get_new_job_from_user 0x%x\n", (void*)job200->user_input.user_job_ptr));
-
- MALI_DEBUG_PRINT(5, ("Mali PP: Frameregs: 0x%x 0x%x 0x%x Writeback[1] 0x%x, Pri:%d; Watchd:%d\n",
- job200->user_input.frame_registers[0], job200->user_input.frame_registers[1], job200->user_input.frame_registers[2],
- job200->user_input.wb0_registers[1], job200->user_input.priority,
- job200->user_input.watchdog_msecs));
-
- if ( job200->user_input.perf_counter_flag)
- {
-#if defined(USING_MALI400_L2_CACHE)
- MALI_DEBUG_PRINT(5, ("Mali PP: Performance counters: flag:0x%x src0:0x%x src1:0x%x l2_src0:0x%x l2_src1:0x%x\n",
- job200->user_input.perf_counter_flag,
- job200->user_input.perf_counter_src0,
- job200->user_input.perf_counter_src1,
- job200->user_input.perf_counter_l2_src0,
- job200->user_input.perf_counter_l2_src1));
-#else
- MALI_DEBUG_PRINT(5, ("Mali PP: Performance counters: flag:0x%x src0:0x%x src1:0x%x\n",
- job200->user_input.perf_counter_flag,
- job200->user_input.perf_counter_src0,
- job200->user_input.perf_counter_src1));
-#endif
- }
-
- job = GET_JOB_EMBEDDED_PTR(job200);
-
- job->session = session;
- job->flags = user_ptr_job_input->flags;
- job_priority_set(job, job200->user_input.priority);
- job_watchdog_set(job, job200->user_input.watchdog_msecs );
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- job200->pid = _mali_osk_get_pid();
- job200->tid = _mali_osk_get_tid();
-#endif
-
- job->abort_id = job200->user_input.abort_id;
- if (mali_job_queue_full(session))
- {
- user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
- goto function_exit;
- }
-
- /* We now know that we has a job, and a empty session slot to put it in */
-
- job200->active_mask = MALI200_REG_VAL_IRQ_MASK_USED;
-
- /* Allocating User Return Data */
- job200->notification_obj = _mali_osk_notification_create(
- _MALI_NOTIFICATION_PP_FINISHED,
- sizeof(_mali_uk_pp_job_finished_s) );
-
- if ( NULL == job200->notification_obj )
- {
- MALI_PRINT_ERROR( ("Mali PP: Could not get notification_obj.\n")) ;
- err = _MALI_OSK_ERR_NOMEM;
- goto function_exit;
- }
-
- _MALI_OSK_INIT_LIST_HEAD( &(job->list) ) ;
-
- MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x INPUT from user.\n", (u32)job200->user_input.user_job_ptr)) ;
-
- /* This should not happen since we have the checking of priority above */
- if ( _MALI_OSK_ERR_OK != mali_core_session_add_job(session, job, &previous_replaced_job))
- {
- MALI_PRINT_ERROR( ("Mali PP: Internal error\n")) ;
- user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
- _mali_osk_notification_delete( job200->notification_obj );
- goto function_exit;
- }
-
- /* If MALI_TRUE: This session had a job with lower priority which were removed.
- This replaced job is given back to userspace. */
- if ( NULL != previous_replaced_job )
- {
- mali200_job *previous_replaced_job200;
-
- previous_replaced_job200 = GET_JOB200_PTR(previous_replaced_job);
-
- MALI_DEBUG_PRINT(4, ("Mali PP: Replacing job: 0x%08x\n", (u32)previous_replaced_job200->user_input.user_job_ptr)) ;
-
- /* Copy to the input data (which also is output data) the
- pointer to the job that were replaced, so that the userspace
- driver can put this job in the front of its job-queue */
-
- user_ptr_job_input->returned_user_job_ptr = previous_replaced_job200->user_input.user_job_ptr;
-
- /** @note failure to 'copy to user' at this point must not free job200,
- * and so no transaction rollback required in the U/K interface */
-
- /* This does not cause job200 to free: */
- user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED;
- MALI_DEBUG_PRINT(5, ("subsystem_mali200_get_new_job_from_user: Job added, prev returned\n")) ;
- }
- else
- {
- /* This does not cause job200 to free: */
- user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED;
- MALI_DEBUG_PRINT(5, ("subsystem_mali200_get_new_job_from_user: Job added\n")) ;
- }
-
-function_exit:
- if (_MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE == user_ptr_job_input->status
- || _MALI_OSK_ERR_OK != err )
- {
- _mali_osk_free(job200);
- }
-#if MALI_STATE_TRACKING
- if (_MALI_UK_START_JOB_STARTED==user_ptr_job_input->status)
- {
- if(job)
- {
- job->job_nr=_mali_osk_atomic_inc_return(&session->jobs_received);
- }
- }
-#endif
-
- MALI_ERROR(err);
-}
-
-/* This function is called from the ioctl function and should write the necessary data
-to userspace telling which job was finished and the status and debuginfo for this job.
-The function must also free and cleanup the input job object. */
-static void subsystem_mali200_return_job_to_user( mali_core_job * job, mali_subsystem_job_end_code end_status)
-{
- mali200_job *job200;
- _mali_uk_pp_job_finished_s * job_out;
- _mali_uk_pp_start_job_s * job_input;
- mali_core_session *session;
-
- if (NULL == job)
- {
- MALI_DEBUG_PRINT(1, ("subsystem_mali200_return_job_to_user received a NULL ptr\n"));
- return;
- }
-
- job200 = _MALI_OSK_CONTAINER_OF(job, mali200_job, embedded_core_job);
-
- if (NULL == job200->notification_obj)
- {
- MALI_DEBUG_PRINT(1, ("Found job200 with NULL notification object, abandoning userspace sending\n"));
- return;
- }
-
- job_out = job200->notification_obj->result_buffer;
- job_input= &(job200->user_input);
- session = job->session;
-
- MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x OUTPUT to user. Runtime: %dus\n",
- (u32)job200->user_input.user_job_ptr,
- job->render_time_usecs)) ;
-
- _mali_osk_memset(job_out, 0 , sizeof(_mali_uk_pp_job_finished_s));
-
- job_out->user_job_ptr = job_input->user_job_ptr;
-
- switch( end_status )
- {
- case JOB_STATUS_CONTINUE_RUN:
- case JOB_STATUS_END_SUCCESS:
- case JOB_STATUS_END_OOM:
- case JOB_STATUS_END_ABORT:
- case JOB_STATUS_END_TIMEOUT_SW:
- case JOB_STATUS_END_HANG:
- case JOB_STATUS_END_SEG_FAULT:
- case JOB_STATUS_END_ILLEGAL_JOB:
- case JOB_STATUS_END_UNKNOWN_ERR:
- case JOB_STATUS_END_SHUTDOWN:
- case JOB_STATUS_END_SYSTEM_UNUSABLE:
- job_out->status = (mali_subsystem_job_end_code) end_status;
- break;
-
- default:
- job_out->status = JOB_STATUS_END_UNKNOWN_ERR ;
- }
- job_out->irq_status = job200->irq_status;
- job_out->perf_counter0 = job200->perf_counter0;
- job_out->perf_counter1 = job200->perf_counter1;
- job_out->render_time = job->render_time_usecs;
-
-#if defined(USING_MALI400_L2_CACHE)
- job_out->perf_counter_l2_src0 = job200->perf_counter_l2_src0;
- job_out->perf_counter_l2_src1 = job200->perf_counter_l2_src1;
- job_out->perf_counter_l2_val0 = job200->perf_counter_l2_val0;
- job_out->perf_counter_l2_val1 = job200->perf_counter_l2_val1;
- job_out->perf_counter_l2_val0_raw = job200->perf_counter_l2_val0_raw;
- job_out->perf_counter_l2_val1_raw = job200->perf_counter_l2_val1_raw;
-#endif
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&session->jobs_returned);
-#endif
- _mali_osk_notification_queue_send( session->notification_queue, job200->notification_obj);
- job200->notification_obj = NULL;
-
- _mali_osk_free(job200);
-}
-
-static void subsystem_mali200_renderunit_delete(mali_core_renderunit * core)
-{
- MALI_DEBUG_PRINT(5, ("Mali PP: mali200_renderunit_delete\n"));
- _mali_osk_free(core);
-}
-
-static void mali200_reset_hard(struct mali_core_renderunit * core)
-{
- const int reset_finished_loop_count = 15;
- const u32 reset_wait_target_register = MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW;
- const u32 reset_invalid_value = 0xC0FFE000;
- const u32 reset_check_value = 0xC01A0000;
- const u32 reset_default_value = 0;
- int i;
-
- MALI_DEBUG_PRINT(5, ("subsystem_mali200_renderunit_reset_core_hard called for core %s\n", core->description));
-
- mali_core_renderunit_register_write(core, reset_wait_target_register, reset_invalid_value);
-
- mali_core_renderunit_register_write(
- core,
- MALI200_REG_ADDR_MGMT_CTRL_MGMT,
- MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);
-
- for (i = 0; i < reset_finished_loop_count; i++)
- {
- mali_core_renderunit_register_write(core, reset_wait_target_register, reset_check_value);
- if (reset_check_value == mali_core_renderunit_register_read(core, reset_wait_target_register))
- {
- MALI_DEBUG_PRINT(5, ("Reset loop exiting after %d iterations\n", i));
- break;
- }
- _mali_osk_time_ubusydelay(10);
- }
-
- if (i == reset_finished_loop_count)
- {
- MALI_DEBUG_PRINT(1, ("The reset loop didn't work\n"));
- }
-
- mali_core_renderunit_register_write(core, reset_wait_target_register, reset_default_value); /* set it back to the default */
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
-}
-
-static void subsystem_mali200_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style)
-{
- MALI_DEBUG_PRINT(5, ("Mali PP: renderunit_reset_core\n"));
-
- switch (style)
- {
- case MALI_CORE_RESET_STYLE_RUNABLE:
- mali200_reset(core);
- break;
- case MALI_CORE_RESET_STYLE_DISABLE:
- mali200_raw_reset(core); /* do the raw reset */
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* then disable the IRQs */
- break;
- case MALI_CORE_RESET_STYLE_HARD:
- mali200_reset_hard(core);
- break;
- default:
- MALI_DEBUG_PRINT(1, ("Unknown reset type %d\n", style));
- }
-}
-
-static void subsystem_mali200_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core)
-{
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG);
- _mali_osk_mem_barrier();
-}
-
-static _mali_osk_errcode_t subsystem_mali200_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core)
-{
- u32 irq_readout;
-
- irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_STATUS);
-
- if ( MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout )
- {
- mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG);
- _mali_osk_mem_barrier();
- MALI_SUCCESS;
- }
-
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
-}
-
-_mali_osk_errcode_t _mali_ukk_pp_start_job( _mali_uk_pp_start_job_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_start_job(session, args);
-}
-
-_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_number_of_cores_get(session, &args->number_of_cores);
-}
-
-_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args )
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
- MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
- return mali_core_subsystem_ioctl_core_version_get(session, &args->version);
-}
-
-void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_s * args)
-{
- mali_core_session * session;
- MALI_DEBUG_ASSERT_POINTER(args);
- if (NULL == args->ctx) return;
- session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
- if (NULL == session) return;
- mali_core_subsystem_ioctl_abort_job(session, args->abort_id);
-
-}
-
-#if USING_MALI_PMM
-
-_mali_osk_errcode_t malipp_signal_power_up( u32 core_num, mali_bool queue_only )
-{
- MALI_DEBUG_PRINT(4, ("Mali PP: signal power up core: %d - queue_only: %d\n", core_num, queue_only ));
-
- return( mali_core_subsystem_signal_power_up( &subsystem_mali200, core_num, queue_only ) );
-}
-
-_mali_osk_errcode_t malipp_signal_power_down( u32 core_num, mali_bool immediate_only )
-{
- MALI_DEBUG_PRINT(4, ("Mali PP: signal power down core: %d - immediate_only: %d\n", core_num, immediate_only ));
-
- return( mali_core_subsystem_signal_power_down( &subsystem_mali200, core_num, immediate_only ) );
-}
-
-#endif
-
-#if MALI_STATE_TRACKING
-u32 mali200_subsystem_dump_state(char *buf, u32 size)
-{
- return mali_core_renderunit_dump_state(&subsystem_mali200, buf, size);
-}
-#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_common.h b/drivers/media/video/samsung/mali/common/mali_kernel_common.h
index ab6f143..b354f92 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_common.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -28,7 +28,6 @@
#define MALI_PANIC(fmt, args...)
#endif
-
/* The file include several useful macros for error checking, debugging and printing.
* - MALI_PRINTF(...) Do not use this function: Will be included in Release builds.
* - MALI_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=MALI_DEBUG_LEVEL.
@@ -129,7 +128,9 @@
} while (0)
#ifdef DEBUG
+#ifndef mali_debug_level
extern int mali_debug_level;
+#endif
#define MALI_DEBUG_CODE(code) code
#define MALI_DEBUG_PRINT(level, args) do { \
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.c b/drivers/media/video/samsung/mali/common/mali_kernel_core.c
index be1889d..0155dfc 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_core.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,344 +8,805 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "mali_kernel_subsystem.h"
-#include "mali_kernel_mem.h"
-#include "mali_kernel_session_manager.h"
-#include "mali_kernel_pp.h"
-#include "mali_kernel_gp.h"
+#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_kernel_rendercore.h"
-#if defined USING_MALI400_L2_CACHE
-#include "mali_kernel_l2_cache.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
-#if USING_MALI_PMM
-#include "mali_pmm.h"
-#endif /* USING_MALI_PMM */
-
-/* platform specific set up */
-#include "mali_platform.h"
-
-/* Initialized when this subsystem is initialized. This is determined by the
- * position in subsystems[], and so the value used to initialize this is
- * determined at compile time */
-static mali_kernel_subsystem_identifier mali_subsystem_core_id = -1;
/** 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_osk_errcode_t register_resources( _mali_osk_resource_t **arch_configuration, u32 num_resources );
-
-static _mali_osk_errcode_t initialize_subsystems(void);
-static void terminate_subsystems(void);
-
-static _mali_osk_errcode_t mali_kernel_subsystem_core_setup(mali_kernel_subsystem_identifier id);
-static void mali_kernel_subsystem_core_cleanup(mali_kernel_subsystem_identifier id);
-static _mali_osk_errcode_t mali_kernel_subsystem_core_system_info_fill(_mali_system_info* info);
-static _mali_osk_errcode_t mali_kernel_subsystem_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+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 _mali_osk_errcode_t build_system_info(void);
static void cleanup_system_info(_mali_system_info *cleanup);
-/**
- * @brief handler for MEM_VALIDATION resources
- *
- * This resource handler is common to all memory systems. It provides a default
- * means for validating requests to map in external memory via
- * _mali_ukk_map_external_mem. In addition, if _mali_ukk_va_to_pa is
- * implemented, then _mali_ukk_va_to_pa can make use of this MEM_VALIDATION
- * resource.
- *
- * MEM_VALIDATION also provide a CPU physical to Mali physical address
- * translation, for use by _mali_ukk_map_external_mem.
- *
- * @note MEM_VALIDATION resources are only to handle simple cases where a
- * certain physical address range is allowed to be mapped in by any process,
- * e.g. a framebuffer at a fixed location. If the implementor has more complex
- * mapping requirements, then they must either:
- * - implement their own memory validation function
- * - or, integrate with UMP.
- *
- * @param resource The resource to handle (type MEM_VALIDATION)
- * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
- */
-static _mali_osk_errcode_t mali_kernel_core_resource_mem_validation(_mali_osk_resource_t * resource);
-
-/* MEM_VALIDATION handler state */
-typedef struct
-{
- u32 phys_base; /**< Mali physical base of the memory, page aligned */
- u32 size; /**< size in bytes of the memory, multiple of page size */
- s32 cpu_usage_adjust; /**< Offset to add to Mali Physical address to obtain CPU physical address */
-} _mali_mem_validation_t;
+/* system info variables */
+static _mali_osk_lock_t *system_info_lock = NULL;
+static _mali_system_info *system_info = NULL;
+static u32 system_info_size = 0;
+static u32 first_pp_offset = 0;
-#define INVALID_MEM 0xffffffff
+#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */
+#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */
-static _mali_mem_validation_t mem_validator = { INVALID_MEM, INVALID_MEM, -1 };
+/* timer related */
+int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
+int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT;
-static struct mali_kernel_subsystem mali_subsystem_core =
+static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset)
{
- mali_kernel_subsystem_core_setup, /* startup */
- mali_kernel_subsystem_core_cleanup, /* shutdown */
- NULL, /* load_complete */
- mali_kernel_subsystem_core_system_info_fill, /* system_info_fill */
- mali_kernel_subsystem_core_session_begin, /* session_begin */
- NULL, /* session_end */
- NULL, /* broadcast_notification */
-#if MALI_STATE_TRACKING
- NULL, /* dump_state */
-#endif
-};
+ int i;
+ u32 addr = global_gpu_base_address + offset;
-static struct mali_kernel_subsystem * subsystems[] =
-{
+ for (i = 0; i < num_resources; i++)
+ {
+ if (type == arch_configuration[i].type && arch_configuration[i].base == addr)
+ {
+ return &(arch_configuration[i]);
+ }
+ }
-#if USING_MALI_PMM
- /* The PMM must be initialized before any cores - including L2 cache */
- &mali_subsystem_pmm,
-#endif
+ return NULL;
+}
- /* always included */
- &mali_subsystem_memory,
+static u32 mali_count_resources(_mali_osk_resource_type_t type)
+{
+ int i;
+ u32 retval = 0;
- /* The rendercore subsystem must be initialized before any subsystem based on the
- * rendercores is started e.g. mali_subsystem_mali200 and mali_subsystem_gp2 */
- &mali_subsystem_rendercore,
+ for (i = 0; i < num_resources; i++)
+ {
+ if (type == arch_configuration[i].type)
+ {
+ retval++;
+ }
+ }
- /* add reference to the subsystem */
- &mali_subsystem_mali200,
+ return retval;
+}
- /* add reference to the subsystem */
- &mali_subsystem_gp2,
-#if defined USING_MALI400_L2_CACHE
- &mali_subsystem_l2_cache,
-#endif
+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]);
+ }
+ }
+ }
- /* always included */
- /* NOTE Keep the core entry at the tail of the list */
- &mali_subsystem_core
-};
+ 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;
+ }
-#define SUBSYSTEMS_COUNT ( sizeof(subsystems) / sizeof(subsystems[0]) )
+ 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;
+}
-/* Pointers to this type available as incomplete struct in mali_kernel_session_manager.h */
-struct mali_session_data
+static _mali_osk_errcode_t mali_parse_product_info(void)
{
- void * subsystem_data[SUBSYSTEMS_COUNT];
- _mali_osk_notification_queue_t * ioctl_queue;
-};
+ _mali_osk_resource_t *first_pp_resource = NULL;
-static mali_kernel_resource_registrator resource_handler[RESOURCE_TYPE_COUNT] = { 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"));
+ }
-/* system info variables */
-static _mali_osk_lock_t *system_info_lock = NULL;
-static _mali_system_info * system_info = NULL;
-static u32 system_info_size = 0;
+ return _MALI_OSK_ERR_FAULT;
+}
-/* is called from OS specific driver entry point */
-_mali_osk_errcode_t mali_kernel_constructor( void )
+static void mali_delete_clusters(void)
{
- _mali_osk_errcode_t err;
-
- err = mali_platform_init();
- if (_MALI_OSK_ERR_OK != err) goto error1;
+ u32 i;
+ u32 number_of_clusters = mali_cluster_get_glob_num_clusters();
- err = _mali_osk_init();
- if (_MALI_OSK_ERR_OK != err) goto error2;
+ for (i = 0; i < number_of_clusters; i++)
+ {
+ mali_cluster_delete(mali_cluster_get_global_cluster(i));
+ }
+}
- 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, ("Svn revision: %s\n", SVN_REV_STRING));
+static _mali_osk_errcode_t mali_create_cluster(_mali_osk_resource_t *resource)
+{
+ if (NULL != resource)
+ {
+ struct mali_l2_cache_core *l2_cache;
- err = initialize_subsystems();
- if (_MALI_OSK_ERR_OK != err) goto error3;
+ 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_PRINT(("Mali device driver %s loaded\n", SVN_REV_STRING));
+ MALI_DEBUG_PRINT(3, ("Found L2 cache %s, starting new cluster\n", resource->description));
- MALI_SUCCESS;
+ /*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;
+ }
-error3:
- MALI_PRINT(("Mali subsystems failed\n"));
- _mali_osk_term();
-error2:
- MALI_PRINT(("Mali device driver init failed\n"));
- if (_MALI_OSK_ERR_OK != mali_platform_deinit())
+ 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_PRINT(("Failed to deinit platform\n"));
+ 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;
+ }
}
-error1:
- MALI_PRINT(("Failed to init platform\n"));
- MALI_ERROR(err);
+
+ MALI_DEBUG_PRINT(3, ("Created cluster object\n"));
+ return _MALI_OSK_ERR_OK;
}
-/* is called from OS specific driver exit point */
-void mali_kernel_destructor( void )
+static _mali_osk_errcode_t mali_parse_config_cluster(void)
{
- MALI_DEBUG_PRINT(2, ("\n"));
- MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION));
-#if USING_MALI_PMM
- malipmm_force_powerup();
-#endif
- terminate_subsystems(); /* subsystems are responsible for their registered resources */
- _mali_osk_term();
-
- if (_MALI_OSK_ERR_OK != mali_platform_deinit())
+ if (_MALI_PRODUCT_ID_MALI200 == global_product_id)
{
- MALI_PRINT(("Failed to deinit platform\n"));
+ /* Create dummy cluster without L2 cache */
+ return mali_create_cluster(NULL);
}
- MALI_DEBUG_PRINT(2, ("Module unloaded.\n"));
-}
+ 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;
+ }
-_mali_osk_errcode_t register_resources( _mali_osk_resource_t **arch_configuration, u32 num_resources )
-{
- _mali_osk_resource_t *arch_resource = *arch_configuration;
- u32 i;
-#if USING_MALI_PMM
- u32 is_pmu_first_resource = 1;
-#endif /* USING_MALI_PMM */
-
- /* loop over arch configuration */
- for (i = 0; i < num_resources; ++i, arch_resource++)
- {
- if ( (arch_resource->type >= RESOURCE_TYPE_FIRST) &&
- (arch_resource->type < RESOURCE_TYPE_COUNT) &&
- (NULL != resource_handler[arch_resource->type])
- )
- {
-#if USING_MALI_PMM
- if((arch_resource->type != PMU) && (is_pmu_first_resource == 1))
+ 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)
{
- _mali_osk_resource_t mali_pmu_virtual_resource;
- mali_pmu_virtual_resource.type = PMU;
- mali_pmu_virtual_resource.description = "Virtual PMU";
- mali_pmu_virtual_resource.base = 0x00000000;
- mali_pmu_virtual_resource.cpu_usage_adjust = 0;
- mali_pmu_virtual_resource.size = 0;
- mali_pmu_virtual_resource.irq = 0;
- mali_pmu_virtual_resource.flags = 0;
- mali_pmu_virtual_resource.mmu_id = 0;
- mali_pmu_virtual_resource.alloc_order = 0;
- MALI_CHECK_NO_ERROR(resource_handler[mali_pmu_virtual_resource.type](&mali_pmu_virtual_resource));
+ return ret;
}
- is_pmu_first_resource = 0;
-#endif /* USING_MALI_PMM */
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
- MALI_CHECK_NO_ERROR(resource_handler[arch_resource->type](arch_resource));
- /* the subsystem shutdown process will release all the resources already registered */
+ /* 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(1, ("No handler installed for resource %s, type %d\n", arch_resource->description, arch_resource->type));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ 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;
+ }
}
}
- MALI_SUCCESS;
+ return _MALI_OSK_ERR_OK;
}
-static _mali_osk_errcode_t initialize_subsystems(void)
+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)
{
- int i, j;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; /* default error code */
+ struct mali_mmu_core *mmu;
+ struct mali_group *group;
+ struct mali_pp_core *pp;
- MALI_CHECK_NON_NULL(system_info_lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0 ), _MALI_OSK_ERR_FAULT);
+ MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
- for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ /* Create the MMU object */
+ mmu = mali_mmu_create(resource_mmu);
+ if (NULL == mmu)
{
- if (NULL != subsystems[i]->startup)
+ 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))
{
- /* the subsystem has a startup function defined */
- err = subsystems[i]->startup(i); /* the subsystem identifier is the offset in our subsystems array */
- if (_MALI_OSK_ERR_OK != err) goto cleanup;
+ /* 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());
}
- for (j = 0; j < (int)SUBSYSTEMS_COUNT; ++j)
+ if (NULL != resource_pp)
{
- if (NULL != subsystems[j]->load_complete)
+ /* Create the PP core object inside this group */
+ pp = mali_pp_create(resource_pp, group);
+
+ if (NULL == pp)
{
- /* the subsystem has a load_complete function defined */
- err = subsystems[j]->load_complete(j);
- if (_MALI_OSK_ERR_OK != err) goto cleanup;
+ /* 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);
}
- /* All systems loaded and resources registered */
- /* Build system info */
- if (_MALI_OSK_ERR_OK != build_system_info()) goto cleanup;
+ 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());
- MALI_SUCCESS; /* all ok */
+ resource_gp = mali_find_resource(MALI_GP, 0x02000);
+ resource_pp = mali_find_resource(MALI_PP, 0x00000);
+ resource_mmu = mali_find_resource(MMU, 0x03000);
-cleanup:
- /* i is index of subsystem which failed to start, all indices before that has to be shut down */
- for (i = i - 1; i >= 0; --i)
+ 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)
{
- /* the subsystem identifier is the offset in our subsystems array */
- /* Call possible shutdown notficiation functions */
- if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i);
+ _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;
+ }
+ }
+ }
}
- _mali_osk_lock_term( system_info_lock );
- MALI_ERROR(err); /* err is what the module which failed its startup returned, or the default */
+ return _MALI_OSK_ERR_OK;
}
-static void terminate_subsystems(void)
+static _mali_osk_errcode_t mali_parse_config_pmu(void)
{
- int i;
- /* shut down subsystems in reverse order from startup */
- for (i = SUBSYSTEMS_COUNT - 1; i >= 0; --i)
+ _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)
{
- /* the subsystem identifier is the offset in our subsystems array */
- if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i);
+ if (NULL == mali_pmu_create(resource_pmu, number_of_pp_cores, number_of_l2_caches))
+ {
+ err = _MALI_OSK_ERR_FAULT;
+ }
}
- if (system_info_lock) _mali_osk_lock_term( system_info_lock );
-
- /* Free _mali_system_info struct */
- cleanup_system_info(system_info);
+ return err;
}
-void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data)
+static _mali_osk_errcode_t mali_parse_config_memory(void)
{
int i;
+ _mali_osk_errcode_t ret;
- for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ for(i = 0; i < num_resources; i++)
{
- if (NULL != subsystems[i]->broadcast_notification)
+ switch(arch_configuration[i].type)
{
- subsystems[i]->broadcast_notification(message, data);
+ 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;
}
-static _mali_osk_errcode_t mali_kernel_subsystem_core_setup(mali_kernel_subsystem_identifier id)
+_mali_osk_errcode_t mali_initialize_subsystems(void)
{
- mali_subsystem_core_id = id;
+ _mali_osk_errcode_t err;
+ mali_bool is_pmu_enabled;
- /* Register our own resources */
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MEM_VALIDATION, mali_kernel_core_resource_mem_validation));
+ MALI_CHECK_NON_NULL(system_info_lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_SPINLOCK
+ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0 ), _MALI_OSK_ERR_FAULT);
- /* parse the arch resource definition and tell all the subsystems */
- /* this is why the core subsystem has to be specified last in the subsystem array */
- MALI_CHECK_NO_ERROR(_mali_osk_resources_init(&arch_configuration, &num_resources));
+ err = mali_session_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto session_init_failed;
- MALI_CHECK_NO_ERROR(register_resources(&arch_configuration, num_resources));
+#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
- /* resource parsing succeeded and the subsystem have corretly accepted their resources */
- MALI_SUCCESS;
+ /* Build dummy system info. Will be removed in the future. */
+ err = build_system_info();
+ if (_MALI_OSK_ERR_OK != err) goto build_system_info_failed;
+
+ /* 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:
+ cleanup_system_info(system_info);
+build_system_info_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);
+
+ cleanup_system_info(system_info);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_term();
+#endif
+
+ mali_session_terminate();
+
+ if (NULL != system_info_lock)
+ {
+ _mali_osk_lock_term( system_info_lock );
+ }
+}
+
+_mali_product_id_t mali_kernel_core_get_product_id(void)
+{
+ return global_product_id;
}
-static void mali_kernel_subsystem_core_cleanup(mali_kernel_subsystem_identifier id)
+void mali_kernel_core_wakeup(void)
{
- _mali_osk_resources_term(&arch_configuration, num_resources);
+ 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);
+ }
}
static void cleanup_system_info(_mali_system_info *cleanup)
@@ -373,11 +834,10 @@ static void cleanup_system_info(_mali_system_info *cleanup)
_mali_osk_free(cleanup);
}
+/* Build a dummy system info struct. User space still need this. */
static _mali_osk_errcode_t build_system_info(void)
{
- unsigned int i;
- int err = _MALI_OSK_ERR_FAULT;
- _mali_system_info * new_info, * cleanup;
+ _mali_system_info * new_info;
_mali_core_info * current_core;
_mali_mem_info * current_mem;
u32 new_size = 0;
@@ -387,19 +847,25 @@ static _mali_osk_errcode_t build_system_info(void)
_mali_osk_memset(new_info, 0, sizeof(_mali_system_info));
- /* if an error happens during any of the system_info_fill calls cleanup the new info structs */
- cleanup = new_info;
+ /* fill in the info */
+ new_info->has_mmu = 1;
+ new_info->drivermode = _MALI_DRIVER_MODE_NORMAL;
- /* ask each subsystems to fill in their info */
- for (i = 0; i < SUBSYSTEMS_COUNT; ++i)
+ new_info->core_info = NULL; /* Not used by user space */
+
+ new_info->mem_info = _mali_osk_calloc(1, sizeof(_mali_mem_info));
+ if(NULL == new_info->mem_info)
{
- if (NULL != subsystems[i]->system_info_fill)
- {
- err = subsystems[i]->system_info_fill(new_info);
- if (_MALI_OSK_ERR_OK != err) goto error_exit;
- }
+ _mali_osk_free(new_info);
+ return _MALI_OSK_ERR_NOMEM;
}
+ new_info->mem_info->size = 1024 * 1024 * 1024; /* 1GiB */
+ new_info->mem_info->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;
+ new_info->mem_info->maximum_order_supported = 30;
+ new_info->mem_info->identifier = 0;
+ new_info->mem_info->next = NULL;
+
/* building succeeded, calculate the size */
/* size needed of the system info struct itself */
@@ -420,8 +886,6 @@ static _mali_osk_errcode_t build_system_info(void)
/* lock system info access so a user wont't get a corrupted version */
_mali_osk_lock_wait( system_info_lock, _MALI_OSK_LOCKMODE_RW );
- /* cleanup the old one */
- cleanup = system_info;
/* set new info */
system_info = new_info;
system_info_size = new_size;
@@ -430,25 +894,15 @@ static _mali_osk_errcode_t build_system_info(void)
_mali_osk_lock_signal( system_info_lock, _MALI_OSK_LOCKMODE_RW );
/* ok result */
- err = _MALI_OSK_ERR_OK;
-
- /* we share the cleanup routine with the error case */
-error_exit:
- if (NULL == cleanup) MALI_ERROR((_mali_osk_errcode_t)err); /* no cleanup needed, return what err contains */
-
- /* cleanup */
- cleanup_system_info(cleanup);
-
- /* return whatever err is, we could end up here in both the error and success cases */
- MALI_ERROR((_mali_osk_errcode_t)err);
+ return _MALI_OSK_ERR_OK;
}
_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);
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- /* check compatability */
+ /* check compatability */
if ( args->version == _MALI_UK_API_VERSION )
{
args->compatible = 1;
@@ -461,14 +915,14 @@ _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args
args->version = _MALI_UK_API_VERSION; /* report our version */
/* success regardless of being compatible or not */
- MALI_SUCCESS;
+ MALI_SUCCESS;
}
_mali_osk_errcode_t _mali_ukk_get_system_info_size(_mali_uk_get_system_info_size_s *args)
{
- MALI_DEBUG_ASSERT_POINTER(args);
- args->size = system_info_size;
- MALI_SUCCESS;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ args->size = system_info_size;
+ MALI_SUCCESS;
}
_mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args )
@@ -477,12 +931,12 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
_mali_mem_info * current_mem;
_mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
void * current_write_pos, ** current_patch_pos;
- u32 adjust_ptr_base;
+ u32 adjust_ptr_base;
/* check input */
MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- MALI_CHECK_NON_NULL(args->system_info, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->system_info, _MALI_OSK_ERR_INVALID_ARGS);
/* lock the system info */
_mali_osk_lock_wait( system_info_lock, _MALI_OSK_LOCKMODE_RW );
@@ -491,20 +945,20 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
if (args->size < system_info_size) goto exit_when_locked;
/* we build a copy of system_info in the user space buffer specified by the user and
- * patch up the pointers. The ukk_private members of _mali_uk_get_system_info_s may
- * indicate a different base address for patching the pointers (normally the
- * address of the provided system_info buffer would be used). This is helpful when
- * the system_info buffer needs to get copied to user space and the pointers need
- * to be in user space.
- */
- if (0 == args->ukk_private)
- {
- adjust_ptr_base = (u32)args->system_info;
- }
- else
- {
- adjust_ptr_base = args->ukk_private;
- }
+ * patch up the pointers. The ukk_private members of _mali_uk_get_system_info_s may
+ * indicate a different base address for patching the pointers (normally the
+ * address of the provided system_info buffer would be used). This is helpful when
+ * the system_info buffer needs to get copied to user space and the pointers need
+ * to be in user space.
+ */
+ if (0 == args->ukk_private)
+ {
+ adjust_ptr_base = (u32)args->system_info;
+ }
+ else
+ {
+ adjust_ptr_base = args->ukk_private;
+ }
/* copy each struct into the buffer, and update its pointers */
current_write_pos = (void *)args->system_info;
@@ -557,56 +1011,56 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
err = _MALI_OSK_ERR_OK;
exit_when_locked:
_mali_osk_lock_signal( system_info_lock, _MALI_OSK_LOCKMODE_RW );
- MALI_ERROR(err);
+ MALI_ERROR(err);
}
_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;
+ _mali_osk_notification_t *notification;
+ _mali_osk_notification_queue_t *queue;
- /* check input */
+ /* check input */
MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- queue = (_mali_osk_notification_queue_t *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_core_id);
+ 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;
+ args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
MALI_SUCCESS;
}
- /* receive a notification, might sleep */
+ /* receive a notification, might sleep */
err = _mali_osk_notification_queue_receive(queue, &notification);
if (_MALI_OSK_ERR_OK != err)
{
- MALI_ERROR(err); /* errcode returned, pass on to caller */
- }
+ 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);
+ 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_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;
+ _mali_osk_notification_queue_t *queue;
- /* check input */
+ /* check input */
MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- queue = (_mali_osk_notification_queue_t *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_core_id);
+ queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
/* if the queue does not exist we're currently shutting down */
if (NULL == queue)
@@ -618,294 +1072,115 @@ _mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *a
notification = _mali_osk_notification_create(args->type, 0);
if ( NULL == notification)
{
- MALI_PRINT_ERROR( ("Failed to create notification object\n")) ;
+ 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 */
-}
-
-static _mali_osk_errcode_t mali_kernel_subsystem_core_system_info_fill(_mali_system_info* info)
-{
- MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS);
-
- info->drivermode = _MALI_DRIVER_MODE_NORMAL;
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_kernel_subsystem_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
-{
- MALI_CHECK_NON_NULL(slot, _MALI_OSK_ERR_INVALID_ARGS);
- *slot = queue;
- MALI_SUCCESS;
-}
-
-/* MEM_VALIDATION resource handler */
-static _mali_osk_errcode_t mali_kernel_core_resource_mem_validation(_mali_osk_resource_t * resource)
-{
- /* Check that no other MEM_VALIDATION resources exist */
- MALI_CHECK( ((u32)-1) == mem_validator.phys_base, _MALI_OSK_ERR_FAULT );
-
- /* Check restrictions on page alignment */
- MALI_CHECK( 0 == (resource->base & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
- MALI_CHECK( 0 == (resource->size & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
- MALI_CHECK( 0 == (resource->cpu_usage_adjust & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
-
- mem_validator.phys_base = resource->base;
- mem_validator.size = resource->size;
- mem_validator.cpu_usage_adjust = resource->cpu_usage_adjust;
- MALI_DEBUG_PRINT( 2, ("Memory Validator '%s' installed for Mali physical address base==0x%08X, size==0x%08X, cpu_adjust==0x%08X\n",
- resource->description, mem_validator.phys_base, mem_validator.size, mem_validator.cpu_usage_adjust ));
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_kernel_core_translate_cpu_to_mali_phys_range( u32 *phys_base, u32 size )
-{
- u32 mali_phys_base;
-
- mali_phys_base = *phys_base - mem_validator.cpu_usage_adjust;
-
- MALI_CHECK( 0 == ( mali_phys_base & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
- MALI_CHECK( 0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
-
- MALI_CHECK_NO_ERROR( mali_kernel_core_validate_mali_phys_range( mali_phys_base, size ) );
-
- *phys_base = mali_phys_base;
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_kernel_core_validate_mali_phys_range( u32 phys_base, u32 size )
-{
- MALI_CHECK_GOTO( 0 == ( phys_base & (~_MALI_OSK_CPU_PAGE_MASK)), failure );
- MALI_CHECK_GOTO( 0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)), failure );
-
- if ( phys_base >= mem_validator.phys_base
- && (phys_base + size) >= mem_validator.phys_base
- && phys_base <= (mem_validator.phys_base + mem_validator.size)
- && (phys_base + size) <= (mem_validator.phys_base + mem_validator.size) )
- {
- MALI_SUCCESS;
- }
-
- failure:
- MALI_PRINTF( ("*******************************************************************************\n") );
- MALI_PRINTF( ("MALI PHYSICAL RANGE VALIDATION ERROR!\n") );
- MALI_PRINTF( ("\n") );
- MALI_PRINTF( ("We failed to validate a Mali-Physical range that the user-side wished to map in\n") );
- MALI_PRINTF( ("\n") );
- MALI_PRINTF( ("It is likely that the user-side wished to do Direct Rendering, but a suitable\n") );
- MALI_PRINTF( ("address range validation mechanism has not been correctly setup\n") );
- MALI_PRINTF( ("\n") );
- MALI_PRINTF( ("The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_base, size) );
- MALI_PRINTF( ("\n") );
- MALI_PRINTF( ("Please refer to the ARM Mali Software Integration Guide for more information.\n") );
- MALI_PRINTF( ("\n") );
- MALI_PRINTF( ("*******************************************************************************\n") );
-
- MALI_ERROR( _MALI_OSK_ERR_FAULT );
-}
-
-
-_mali_osk_errcode_t _mali_kernel_core_register_resource_handler(_mali_osk_resource_type_t type, mali_kernel_resource_registrator handler)
-{
- MALI_CHECK(type < RESOURCE_TYPE_COUNT, _MALI_OSK_ERR_INVALID_ARGS);
- MALI_DEBUG_ASSERT(NULL == resource_handler[type]); /* A handler for resource already exists */
- resource_handler[type] = handler;
- MALI_SUCCESS;
-}
-
-void * mali_kernel_session_manager_slot_get(struct mali_session_data * session_data, int id)
-{
- MALI_DEBUG_ASSERT_POINTER(session_data);
- if(id >= SUBSYSTEMS_COUNT) { MALI_DEBUG_PRINT(3, ("mali_kernel_session_manager_slot_get: id %d out of range\n", id)); return NULL; }
-
- if (NULL == session_data) { MALI_DEBUG_PRINT(3, ("mali_kernel_session_manager_slot_get: got NULL session data\n")); return NULL; }
- return session_data->subsystem_data[id];
+ MALI_SUCCESS; /* all ok */
}
_mali_osk_errcode_t _mali_ukk_open(void **context)
{
- int i;
- _mali_osk_errcode_t err;
- struct mali_session_data * session_data;
+ struct mali_session_data *session_data;
/* allocated struct to track this session */
- session_data = (struct mali_session_data *)_mali_osk_malloc(sizeof(struct mali_session_data));
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM);
+ 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_osk_memset(session_data->subsystem_data, 0, sizeof(session_data->subsystem_data));
+ 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);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
}
- MALI_DEBUG_PRINT(3, ("Session starting\n"));
-
- /* call session_begin on all subsystems */
- for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ session_data->page_directory = mali_mmu_pagedir_alloc();
+ if (NULL == session_data->page_directory)
{
- if (NULL != subsystems[i]->session_begin)
- {
- /* subsystem has a session_begin */
- err = subsystems[i]->session_begin(session_data, &session_data->subsystem_data[i], session_data->ioctl_queue);
- MALI_CHECK_GOTO(err == _MALI_OSK_ERR_OK, cleanup);
- }
+ _mali_osk_notification_queue_term(session_data->ioctl_queue);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
}
- *context = (void*)session_data;
+ 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);
+ }
- MALI_DEBUG_PRINT(3, ("Session started\n"));
- MALI_SUCCESS;
+ 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);
+ }
-cleanup:
- MALI_DEBUG_PRINT(2, ("Session startup failed\n"));
- /* i is index of subsystem which failed session begin, all indices before that has to be ended */
- /* end subsystem sessions in the reverse order they where started in */
- for (i = i - 1; i >= 0; --i)
+ if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session_data))
{
- if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]);
+ 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);
}
- _mali_osk_notification_queue_term(session_data->ioctl_queue);
- _mali_osk_free(session_data);
+ *context = (void*)session_data;
- /* return what the subsystem which failed session start returned */
- MALI_ERROR(err);
+ /* 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)
{
- int i;
- struct mali_session_data * session_data;
+ struct mali_session_data *session;
+ MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (struct mali_session_data *)*context;
- MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_DEBUG_PRINT(3, ("Session ending\n"));
- session_data = (struct mali_session_data *)*context;
+ /* Remove session from list of all sessions. */
+ mali_session_remove(session);
- MALI_DEBUG_PRINT(2, ("Session ending\n"));
+ /* Abort queued and running jobs */
+ mali_gp_scheduler_abort_session(session);
+ mali_pp_scheduler_abort_session(session);
- /* end subsystem sessions in the reverse order they where started in */
- for (i = SUBSYSTEMS_COUNT - 1; i >= 0; --i)
- {
- if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]);
- }
+ /* 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);
- _mali_osk_notification_queue_term(session_data->ioctl_queue);
- _mali_osk_free(session_data);
+ /* Free remaining memory allocated to this session */
+ mali_memory_session_end(session);
- *context = NULL;
+ /* Free session data structures */
+ mali_mmu_pagedir_free(session->page_directory);
+ _mali_osk_notification_queue_term(session->ioctl_queue);
+ _mali_osk_free(session);
- MALI_DEBUG_PRINT(2, ("Session has ended\n"));
-
- MALI_SUCCESS;
-}
+ *context = NULL;
-#if USING_MALI_PMM
-
-_mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool queue_only )
-{
- switch( core )
- {
- case MALI_PMM_CORE_GP:
- MALI_CHECK_NO_ERROR(maligp_signal_power_up(queue_only));
- break;
-#if defined USING_MALI400_L2_CACHE
- case MALI_PMM_CORE_L2:
- if( !queue_only )
- {
- /* Enable L2 cache due to power up */
- mali_kernel_l2_cache_do_enable();
+ MALI_DEBUG_PRINT(2, ("Session has ended\n"));
- /* Invalidate the cache on power up */
- MALI_DEBUG_PRINT(5, ("L2 Cache: Invalidate all\n"));
- MALI_CHECK_NO_ERROR(mali_kernel_l2_cache_invalidate_all());
- }
- break;
-#endif
- case MALI_PMM_CORE_PP0:
- MALI_CHECK_NO_ERROR(malipp_signal_power_up(0, queue_only));
- break;
- case MALI_PMM_CORE_PP1:
- MALI_CHECK_NO_ERROR(malipp_signal_power_up(1, queue_only));
- break;
- case MALI_PMM_CORE_PP2:
- MALI_CHECK_NO_ERROR(malipp_signal_power_up(2, queue_only));
- break;
- case MALI_PMM_CORE_PP3:
- MALI_CHECK_NO_ERROR(malipp_signal_power_up(3, queue_only));
- break;
- default:
- /* Unknown core */
- MALI_DEBUG_PRINT_ERROR( ("Unknown core signalled with power up: %d\n", core) );
- MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS );
- }
-
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_bool immediate_only )
-{
- switch( core )
- {
- case MALI_PMM_CORE_GP:
- MALI_CHECK_NO_ERROR(maligp_signal_power_down(immediate_only));
- break;
-#if defined USING_MALI400_L2_CACHE
- case MALI_PMM_CORE_L2:
- /* Nothing to do */
- break;
-#endif
- case MALI_PMM_CORE_PP0:
- MALI_CHECK_NO_ERROR(malipp_signal_power_down(0, immediate_only));
- break;
- case MALI_PMM_CORE_PP1:
- MALI_CHECK_NO_ERROR(malipp_signal_power_down(1, immediate_only));
- break;
- case MALI_PMM_CORE_PP2:
- MALI_CHECK_NO_ERROR(malipp_signal_power_down(2, immediate_only));
- break;
- case MALI_PMM_CORE_PP3:
- MALI_CHECK_NO_ERROR(malipp_signal_power_down(3, immediate_only));
- break;
- default:
- /* Unknown core */
- MALI_DEBUG_PRINT_ERROR( ("Unknown core signalled with power down: %d\n", core) );
- MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS );
- }
-
MALI_SUCCESS;
}
-#endif
-
-
#if MALI_STATE_TRACKING
u32 _mali_kernel_core_dump_state(char* buf, u32 size)
{
- int i, n;
- char *original_buf = buf;
- for (i = 0; i < SUBSYSTEMS_COUNT; ++i)
- {
- if (NULL != subsystems[i]->dump_state)
- {
- n = subsystems[i]->dump_state(buf, size);
- size -= n;
- buf += n;
- }
- }
-#if USING_MALI_PMM
- n = mali_pmm_dump_os_thread_state(buf, size);
- size -= n;
- buf += n;
-#endif
- /* Return number of bytes written to buf */
- return (u32)(buf - original_buf);
+ 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/media/video/samsung/mali/common/mali_kernel_core.h
index 715c1cd..d424c48 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_core.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,122 +13,27 @@
#include "mali_osk.h"
-#if USING_MALI_PMM
-#include "mali_ukk.h"
-#include "mali_pmm.h"
-#include "mali_pmm_system.h"
-#endif
+extern int mali_hang_check_interval;
+extern int mali_max_job_runtime;
-_mali_osk_errcode_t mali_kernel_constructor( void );
-void mali_kernel_destructor( void );
+typedef enum
+{
+ _MALI_PRODUCT_ID_UNKNOWN,
+ _MALI_PRODUCT_ID_MALI200,
+ _MALI_PRODUCT_ID_MALI300,
+ _MALI_PRODUCT_ID_MALI400,
+ _MALI_PRODUCT_ID_MALI450,
+} _mali_product_id_t;
-/**
- * @brief Tranlate CPU physical to Mali physical addresses.
- *
- * This function is used to convert CPU physical addresses to Mali Physical
- * addresses, such that _mali_ukk_map_external_mem may be used to map them
- * into Mali. This will be used by _mali_ukk_va_to_mali_pa.
- *
- * This function only supports physically contiguous regions.
- *
- * A default implementation is provided, which uses a registered MEM_VALIDATION
- * resource to do a static translation. Only an address range which will lie
- * in the range specified by MEM_VALIDATION will be successfully translated.
- *
- * If a more complex, or non-static translation is required, then the
- * implementor has the following options:
- * - Rewrite this function to provide such a translation
- * - Integrate the provider of the memory with UMP.
- *
- * @param[in,out] phys_base pointer to the page-aligned base address of the
- * physical range to be translated
- *
- * @param[in] size size of the address range to be translated, which must be a
- * multiple of the physical page size.
- *
- * @return on success, _MALI_OSK_ERR_OK and *phys_base is translated. If the
- * cpu physical address range is not in the valid range, then a suitable
- * _mali_osk_errcode_t error.
- *
- */
-_mali_osk_errcode_t mali_kernel_core_translate_cpu_to_mali_phys_range( u32 *phys_base, u32 size );
-
-
-/**
- * @brief Validate a Mali physical address range.
- *
- * This function is used to ensure that an address range passed to
- * _mali_ukk_map_external_mem is allowed to be mapped into Mali.
- *
- * This function only supports physically contiguous regions.
- *
- * A default implementation is provided, which uses a registered MEM_VALIDATION
- * resource to do a static translation. Only an address range which will lie
- * in the range specified by MEM_VALIDATION will be successfully validated.
- *
- * If a more complex, or non-static validation is required, then the
- * implementor has the following options:
- * - Rewrite this function to provide such a validation
- * - Integrate the provider of the memory with UMP.
- *
- * @param phys_base page-aligned base address of the Mali physical range to be
- * validated.
- *
- * @param size size of the address range to be validated, which must be a
- * multiple of the physical page size.
- *
- * @return _MALI_OSK_ERR_OK if the Mali physical range is valid. Otherwise, a
- * suitable _mali_osk_errcode_t error.
- *
- */
-_mali_osk_errcode_t mali_kernel_core_validate_mali_phys_range( u32 phys_base, u32 size );
+_mali_osk_errcode_t mali_initialize_subsystems(void);
-#if USING_MALI_PMM
-/**
- * @brief Signal a power up on a Mali core.
- *
- * This function flags a core as powered up.
- * For PP and GP cores it calls functions that move the core from a power off
- * queue into the idle queue ready to run jobs. It also tries to schedule any
- * pending jobs to run on it.
- *
- * This function will fail if the core is not powered off - either running or
- * already idle.
- *
- * @param core The PMM core id to power up.
- * @param queue_only When MALI_TRUE only re-queue the core - do not reset.
- *
- * @return _MALI_OSK_ERR_OK if the core has been powered up. Otherwise a
- * suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool queue_only );
-
-/**
- * @brief Signal a power down on a Mali core.
- *
- * This function flags a core as powered down.
- * For PP and GP cores it calls functions that move the core from an idle
- * queue into the power off queue.
- *
- * This function will fail if the core is not idle - either running or
- * already powered down.
- *
- * @param core The PMM core id to power up.
- * @param immediate_only Do not set the core to pending power down if it can't
- * power down immediately
- *
- * @return _MALI_OSK_ERR_OK if the core has been powered up. Otherwise a
- * suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_bool immediate_only );
+void mali_terminate_subsystems(void);
-#endif
+void mali_kernel_core_wakeup(void);
-/**
- * Flag to indicate whether or not mali_benchmark is turned on.
- */
-extern int mali_benchmark;
+_mali_product_id_t mali_kernel_core_get_product_id(void);
+u32 _mali_kernel_core_dump_state(char* buf, u32 size);
#endif /* __MALI_KERNEL_CORE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c
index 8b2a97d..b9f05ca 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -40,11 +40,7 @@ mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int m
map->table = descriptor_table_alloc(init_entries);
if (NULL != map->table)
{
-#if !USING_MMU
- map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 20);
-#else
- map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 116);
-#endif
+ map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP);
if (NULL != map->lock)
{
_mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
@@ -151,15 +147,20 @@ _mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, i
MALI_ERROR(result);
}
-void mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor)
+void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor)
{
+ void *old_value = NULL;
+
_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) )
{
+ old_value = map->table->mappings[descriptor];
map->table->mappings[descriptor] = NULL;
_mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
}
_mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+
+ return old_value;
}
static mali_descriptor_table * descriptor_table_alloc(int count)
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h
index 745be92..82ed94d 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -93,7 +93,9 @@ void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (
* For the descriptor to be reused it has to be freed
* @param map The map to free the descriptor from
* @param descriptor The descriptor ID to free
+ *
+ * @return old value of descriptor mapping
*/
-void mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor);
+void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor);
#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_gp.h b/drivers/media/video/samsung/mali/common/mali_kernel_gp.h
deleted file mode 100644
index efd3b43..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_gp.h
+++ /dev/null
@@ -1,21 +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 __MALI_KERNEL_GP2_H__
-#define __MALI_KERNEL_GP2_H__
-
-extern struct mali_kernel_subsystem mali_subsystem_gp2;
-
-#if USING_MALI_PMM
-_mali_osk_errcode_t maligp_signal_power_up( mali_bool queue_only );
-_mali_osk_errcode_t maligp_signal_power_down( mali_bool immediate_only );
-#endif
-
-#endif /* __MALI_KERNEL_GP2_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c b/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c
deleted file mode 100644
index e4d4ab1..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c
+++ /dev/null
@@ -1,517 +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.
- */
-#include "mali_kernel_common.h"
-#include "mali_osk.h"
-#include "mali_osk_list.h"
-
-#include "mali_kernel_core.h"
-#include "mali_kernel_pp.h"
-#include "mali_kernel_subsystem.h"
-#include "regs/mali_200_regs.h"
-#include "mali_kernel_rendercore.h"
-#include "mali_kernel_l2_cache.h"
-
-/**
- * Size of the Mali L2 cache registers in bytes
- */
-#define MALI400_L2_CACHE_REGISTERS_SIZE 0x30
-
-/**
- * Mali L2 cache register numbers
- * Used in the register read/write routines.
- * See the hardware documentation for more information about each register
- */
-typedef enum mali_l2_cache_register {
- MALI400_L2_CACHE_REGISTER_STATUS = 0x0002,
- /*unused = 0x0003 */
- MALI400_L2_CACHE_REGISTER_COMMAND = 0x0004, /**< Misc cache commands, e.g. clear */
- MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0005,
- MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0006, /**< Limit of outstanding read requests */
- MALI400_L2_CACHE_REGISTER_ENABLE = 0x0007, /**< Enable misc cache features */
- MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0008,
- MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0009,
- MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x000A,
- MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x000B,
-} mali_l2_cache_register;
-
-
-/**
- * Mali L2 cache commands
- * These are the commands that can be sent to the Mali L2 cache unit
- */
-typedef enum mali_l2_cache_command
-{
- MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */
- /* Read HW TRM carefully before adding/using other commands than the clear above */
-} mali_l2_cache_command;
-
-/**
- * Mali L2 cache commands
- * These are the commands that can be sent to the Mali L2 cache unit
- */
-typedef enum mali_l2_cache_enable
-{
- MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */
- MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */
- MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */
-} mali_l2_cache_enable;
-
-/**
- * Mali L2 cache status bits
- */
-typedef enum mali_l2_cache_status
-{
- MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */
- 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
- */
-typedef struct mali_kernel_l2_cache_core
-{
- unsigned long base; /**< Physical address of the registers */
- mali_io_address mapped_registers; /**< Virtual mapping of the registers */
- u32 mapping_size; /**< Size of registers in bytes */
- _mali_osk_list_t list; /**< Used to link multiple cache cores into a list */
- _mali_osk_lock_t *lock; /**< Serialize all L2 cache commands */
-} mali_kernel_l2_cache_core;
-
-
-#define MALI400_L2_MAX_READS_DEFAULT 0x1C
-
-int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT;
-
-
-/**
- * Mali L2 cache subsystem startup function
- * Called by the driver core when the driver is loaded.
- *
- * @param id Identifier assigned by the core to the L2 cache subsystem
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_l2_cache_initialize(mali_kernel_subsystem_identifier id);
-
-/**
- * Mali L2 cache subsystem shutdown function
- * Called by the driver core when the driver is unloaded.
- * Cleans up
- * @param id Identifier assigned by the core to the L2 cache subsystem
- */
-static void mali_l2_cache_terminate(mali_kernel_subsystem_identifier id);
-
-/**
- * L2 cache subsystem complete notification function.
- * Called by the driver core when all drivers have loaded and all resources has been registered
- * @param id Identifier assigned by the core to the L2 cache subsystem
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_l2_cache_load_complete(mali_kernel_subsystem_identifier id);
-
-/**
- * Mali L2 cache subsystem's notification handler for a Mali L2 cache resource instances.
- * Registered with the core during startup.
- * Called by the core for each Mali L2 cache described in the active architecture's config.h file.
- * @param resource The resource to handle (type MALI400L2)
- * @return 0 if the Mali L2 cache was found and initialized, negative on error
- */
-static _mali_osk_errcode_t mali_l2_cache_core_create(_mali_osk_resource_t * resource);
-
-/**
- * Write to a L2 cache register
- * Writes the given value to the specified register
- * @param unit The L2 cache to write to
- * @param reg The register to write to
- * @param val The value to write to the register
- */
-static void mali_l2_cache_register_write(mali_kernel_l2_cache_core * unit, mali_l2_cache_register reg, u32 val);
-
-
-
-/**
- * Invalidate specified L2 cache
- * @param cache The L2 cache to invalidate
- * @return 0 if Mali L2 cache was successfully invalidated, otherwise error
- */
-static _mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all_cache(mali_kernel_l2_cache_core *cache);
-
-
-/*
- The fixed Mali L2 cache system's mali subsystem interface implementation.
- We currently handle module and session life-time management.
-*/
-struct mali_kernel_subsystem mali_subsystem_l2_cache =
-{
- mali_l2_cache_initialize, /**< startup */
- NULL, /*mali_l2_cache_terminate,*/ /**< shutdown */
- mali_l2_cache_load_complete, /**< load_complete */
- NULL, /**< system_info_fill */
- NULL, /**< session_begin */
- NULL, /**< session_end */
- NULL, /**< broadcast_notification */
-#if MALI_STATE_TRACKING
- NULL, /**< dump_state */
-#endif
-};
-
-
-
-static _MALI_OSK_LIST_HEAD(caches_head);
-
-
-
-
-/* called during module init */
-static _mali_osk_errcode_t mali_l2_cache_initialize(mali_kernel_subsystem_identifier id)
-{
- _mali_osk_errcode_t err;
-
- MALI_IGNORE( id );
-
- MALI_DEBUG_PRINT(2, ( "Mali L2 cache system initializing\n"));
-
- _MALI_OSK_INIT_LIST_HEAD(&caches_head);
-
- /* This will register the function for adding Mali L2 cache cores to the subsystem */
- err = _mali_kernel_core_register_resource_handler(MALI400L2, mali_l2_cache_core_create);
-
- MALI_ERROR(err);
-}
-
-
-
-/* called if/when our module is unloaded */
-static void mali_l2_cache_terminate(mali_kernel_subsystem_identifier id)
-{
- mali_kernel_l2_cache_core * cache, *temp_cache;
-
- MALI_DEBUG_PRINT(2, ( "Mali L2 cache system terminating\n"));
-
- /* loop over all L2 cache units and shut them down */
- _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list )
- {
- /* reset to defaults */
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT);
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT);
-
- /* remove from the list of cacges on the system */
- _mali_osk_list_del( &cache->list );
-
- /* release resources */
- _mali_osk_mem_unmapioregion( cache->base, cache->mapping_size, cache->mapped_registers );
- _mali_osk_mem_unreqregion( cache->base, cache->mapping_size );
- _mali_osk_lock_term( cache->lock );
- _mali_osk_free( cache );
-
- #if USING_MALI_PMM
- /* Unregister the L2 cache with the PMM */
- malipmm_core_unregister( MALI_PMM_CORE_L2 );
- #endif
- }
-}
-
-static _mali_osk_errcode_t mali_l2_cache_core_create(_mali_osk_resource_t * resource)
-{
- _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT ;
- mali_kernel_l2_cache_core * cache = NULL;
-
- MALI_DEBUG_PRINT(2, ( "Creating Mali L2 cache: %s\n", resource->description));
-
-#if USING_MALI_PMM
- /* Register the L2 cache with the PMM */
- err = malipmm_core_register( MALI_PMM_CORE_L2 );
- if( _MALI_OSK_ERR_OK != err )
- {
- MALI_DEBUG_PRINT(1, ( "Failed to register L2 cache unit with PMM"));
- return err;
- }
-#endif
-
- err = _mali_osk_mem_reqregion( resource->base, MALI400_L2_CACHE_REGISTERS_SIZE, resource->description);
-
- MALI_CHECK_GOTO( _MALI_OSK_ERR_OK == err, err_cleanup_requestmem_failed);
-
- /* Reset error that might be passed out */
- err = _MALI_OSK_ERR_FAULT;
-
- cache = _mali_osk_malloc(sizeof(mali_kernel_l2_cache_core));
-
- MALI_CHECK_GOTO( NULL != cache, err_cleanup);
-
- cache->lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 104 );
-
- MALI_CHECK_GOTO( NULL != cache->lock, err_cleanup);
-
- /* basic setup */
- _MALI_OSK_INIT_LIST_HEAD(&cache->list);
-
- cache->base = resource->base;
- cache->mapping_size = MALI400_L2_CACHE_REGISTERS_SIZE;
-
- /* map the registers */
- cache->mapped_registers = _mali_osk_mem_mapioregion( cache->base, cache->mapping_size, resource->description );
-
- MALI_CHECK_GOTO( NULL != cache->mapped_registers, err_cleanup);
-
- /* Invalidate cache (just to keep it in a known state at startup) */
- err = mali_kernel_l2_cache_invalidate_all_cache(cache);
-
- MALI_CHECK_GOTO( _MALI_OSK_ERR_OK == err, err_cleanup);
-
- /* add to our list of L2 caches */
- _mali_osk_list_add( &cache->list, &caches_head );
-
- MALI_SUCCESS;
-
-err_cleanup:
- /* This cleanup used when resources have been requested successfully */
-
- if ( NULL != cache )
- {
- if (NULL != cache->mapped_registers)
- {
- _mali_osk_mem_unmapioregion( cache->base, cache->mapping_size, cache->mapped_registers);
- }
- else
- {
- MALI_DEBUG_PRINT(1, ( "Failed to map Mali L2 cache registers at 0x%08lX\n", cache->base));
- }
-
- if( NULL != cache->lock )
- {
- _mali_osk_lock_term( cache->lock );
- }
- else
- {
- MALI_DEBUG_PRINT(1, ( "Failed to allocate a lock for handling a L2 cache unit"));
- }
-
- _mali_osk_free( cache );
- }
- else
- {
- MALI_DEBUG_PRINT(1, ( "Failed to allocate memory for handling a L2 cache unit"));
- }
-
- /* A call is to request region, so this must always be reversed */
- _mali_osk_mem_unreqregion( resource->base, MALI400_L2_CACHE_REGISTERS_SIZE);
-#if USING_MALI_PMM
- malipmm_core_unregister( MALI_PMM_CORE_L2 );
-#endif
- return err;
-
-err_cleanup_requestmem_failed:
- MALI_DEBUG_PRINT(1, ("Failed to request Mali L2 cache '%s' register address space at (0x%08X - 0x%08X)\n",
- resource->description, resource->base, resource->base + MALI400_L2_CACHE_REGISTERS_SIZE - 1) );
-#if USING_MALI_PMM
- malipmm_core_unregister( MALI_PMM_CORE_L2 );
-#endif
- return err;
-
-}
-
-
-static void mali_l2_cache_register_write(mali_kernel_l2_cache_core * unit, mali_l2_cache_register reg, u32 val)
-{
- _mali_osk_mem_iowrite32(unit->mapped_registers, (u32)reg * sizeof(u32), val);
-}
-
-
-static u32 mali_l2_cache_register_read(mali_kernel_l2_cache_core * unit, mali_l2_cache_register reg)
-{
- return _mali_osk_mem_ioread32(unit->mapped_registers, (u32)reg * sizeof(u32));
-}
-
-void mali_kernel_l2_cache_do_enable(void)
-{
- mali_kernel_l2_cache_core * cache, *temp_cache;
-
- /* loop over all L2 cache units and enable them*/
- _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
- {
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE);
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads);
- }
-}
-
-
-static _mali_osk_errcode_t mali_l2_cache_load_complete(mali_kernel_subsystem_identifier id)
-{
- mali_kernel_l2_cache_do_enable();
- MALI_DEBUG_PRINT(2, ( "Mali L2 cache system load complete\n"));
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_kernel_l2_cache_send_command(mali_kernel_l2_cache_core *cache, u32 reg, u32 val)
-{
- int i = 0;
- const int loop_count = 100000;
-
- /*
- * Grab lock in order to send commands to the L2 cache in a serialized fashion.
- * The L2 cache will ignore commands if it is busy.
- */
- _mali_osk_lock_wait(cache->lock, _MALI_OSK_LOCKMODE_RW);
-
- /* First, wait for L2 cache command handler to go idle */
-
- for (i = 0; i < loop_count; i++)
- {
- if (!(_mali_osk_mem_ioread32(cache->mapped_registers , (u32)MALI400_L2_CACHE_REGISTER_STATUS * sizeof(u32)) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY))
- {
- break;
- }
- }
-
- if (i == loop_count)
- {
- _mali_osk_lock_signal(cache->lock, _MALI_OSK_LOCKMODE_RW);
- MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n"));
- MALI_ERROR( _MALI_OSK_ERR_FAULT );
- }
-
- /* then issue the command */
- mali_l2_cache_register_write(cache, reg, val);
-
- _mali_osk_lock_signal(cache->lock, _MALI_OSK_LOCKMODE_RW);
- MALI_SUCCESS;
-}
-
-
-static _mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all_cache(mali_kernel_l2_cache_core *cache)
-{
- return mali_kernel_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
-}
-
-_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all(void)
-{
- mali_kernel_l2_cache_core * cache, *temp_cache;
-
- /* loop over all L2 cache units and invalidate them */
-
- _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
- {
- MALI_CHECK_NO_ERROR( mali_kernel_l2_cache_invalidate_all_cache(cache) );
- }
-
- MALI_SUCCESS;
-}
-
-
-static _mali_osk_errcode_t mali_kernel_l2_cache_invalidate_page_cache(mali_kernel_l2_cache_core *cache, u32 page)
-{
- return mali_kernel_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, page);
-}
-
-_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_page(u32 page)
-{
- mali_kernel_l2_cache_core * cache, *temp_cache;
-
- /* loop over all L2 cache units and invalidate them */
-
- _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
- {
- MALI_CHECK_NO_ERROR( mali_kernel_l2_cache_invalidate_page_cache(cache, page) );
- }
-
- MALI_SUCCESS;
-}
-
-
-void mali_kernel_l2_cache_set_perf_counters(u32 src0, u32 src1, int force_reset)
-{
- mali_kernel_l2_cache_core * cache, *temp_cache;
- int reset0 = force_reset;
- int reset1 = force_reset;
- MALI_DEBUG_CODE(
- int changed0 = 0;
- int changed1 = 0;
- )
-
- /* loop over all L2 cache units and activate the counters on them */
- _MALI_OSK_LIST_FOREACHENTRY(cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
- {
- u32 cur_src0 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0);
- u32 cur_src1 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1);
-
- if (src0 != cur_src0)
- {
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, src0);
- MALI_DEBUG_CODE(changed0 = 1;)
- reset0 = 1;
- }
-
- if (src1 != cur_src1)
- {
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, src1);
- MALI_DEBUG_CODE(changed1 = 1;)
- reset1 = 1;
- }
-
- if (reset0)
- {
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0, 0);
- }
-
- if (reset1)
- {
- mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1, 0);
- }
-
- MALI_DEBUG_PRINT(5, ("L2 cache counters set: SRC0=%u, CHANGED0=%d, RESET0=%d, SRC1=%u, CHANGED1=%d, RESET1=%d\n",
- src0, changed0, reset0,
- src1, changed1, reset1));
- }
-}
-
-
-void mali_kernel_l2_cache_get_perf_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1)
-{
- mali_kernel_l2_cache_core * cache, *temp_cache;
- int first_time = 1;
- *src0 = 0;
- *src1 = 0;
- *val0 = 0;
- *val1 = 0;
-
- /* loop over all L2 cache units and read the counters */
- _MALI_OSK_LIST_FOREACHENTRY(cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
- {
- u32 cur_src0 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0);
- u32 cur_src1 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1);
- u32 cur_val0 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0);
- u32 cur_val1 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1);
-
- MALI_DEBUG_PRINT(5, ("L2 cache counters get: SRC0=%u, VAL0=%u, SRC1=%u, VAL1=%u\n", cur_src0, cur_val0, cur_src1, cur_val1));
-
- /* Only update the counter source once, with the value from the first L2 cache unit. */
- if (first_time)
- {
- *src0 = cur_src0;
- *src1 = cur_src1;
- first_time = 0;
- }
-
- /* Bail out if the L2 cache units have different counters set. */
- if (*src0 == cur_src0 && *src1 == cur_src1)
- {
- *val0 += cur_val0;
- *val1 += cur_val1;
- }
- else
- {
- MALI_DEBUG_PRINT(1, ("Warning: Mali L2 caches has different performance counters set, not retrieving data\n"));
- }
- }
-}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h b/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h
deleted file mode 100644
index 8c12b50..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h
+++ /dev/null
@@ -1,25 +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 __MALI_KERNEL_L2_CACHE_H__
-#define __MALI_KERNEL_L2_CACHE_H__
-
-#include "mali_osk.h"
-#include "mali_kernel_subsystem.h"
-extern struct mali_kernel_subsystem mali_subsystem_l2_cache;
-
-_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all(void);
-_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_page(u32 page);
-
-void mali_kernel_l2_cache_do_enable(void);
-void mali_kernel_l2_cache_set_perf_counters(u32 src0, u32 src1, int force_reset);
-void mali_kernel_l2_cache_get_perf_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1);
-
-#endif /* __MALI_KERNEL_L2_CACHE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c
deleted file mode 100644
index e378f03..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c
+++ /dev/null
@@ -1,1427 +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.
- */
-
-#include "mali_kernel_core.h"
-#include "mali_kernel_subsystem.h"
-#include "mali_kernel_mem.h"
-#include "mali_kernel_descriptor_mapping.h"
-#include "mali_kernel_session_manager.h"
-
-/* kernel side OS functions and user-kernel interface */
-#include "mali_osk.h"
-#include "mali_osk_mali.h"
-#include "mali_osk_list.h"
-#include "mali_ukk.h"
-
-#ifdef _MALI_OSK_SPECIFIC_INDIRECT_MMAP
-#include "mali_osk_indir_mmap.h"
-#endif
-
-#error Support for non-MMU builds is no longer supported and is planned for removal.
-
-/**
- * Minimum memory allocation size
- */
-#define MIN_BLOCK_SIZE (1024*1024UL)
-
-/**
- * Per-session memory descriptor mapping table sizes
- */
-#define MALI_MEM_DESCRIPTORS_INIT 64
-#define MALI_MEM_DESCRIPTORS_MAX 4096
-
-/**
- * Enum uses to store multiple fields in one u32 to keep the memory block struct small
- */
-enum MISC_SHIFT { MISC_SHIFT_FREE = 0, MISC_SHIFT_ORDER = 1, MISC_SHIFT_TOPLEVEL = 6 };
-enum MISC_MASK { MISC_MASK_FREE = 0x01, MISC_MASK_ORDER = 0x1F, MISC_MASK_TOPLEVEL = 0x1F };
-
-/* forward declaration of the block struct */
-struct mali_memory_block;
-
-/**
- * Definition of memory bank type.
- * Represents a memory bank (separate address space)
- * Each bank keeps track of its block usage.
- * A buddy system used to track the usage
-*/
-typedef struct mali_memory_bank
-{
- _mali_osk_list_t list; /* links multiple banks together */
- _mali_osk_lock_t *lock;
- u32 base_addr; /* Mali seen address of bank */
- u32 cpu_usage_adjust; /* Adjustment factor for what the CPU sees */
- u32 size; /* the effective size */
- u32 real_size; /* the real size of the bank, as given by to the subsystem */
- int min_order;
- int max_order;
- struct mali_memory_block * blocklist;
- _mali_osk_list_t *freelist;
- _mali_osk_atomic_t num_active_allocations;
- u32 used_for_flags;
- u32 alloc_order; /**< Order in which the bank will be used for allocations */
- const char *name; /**< Descriptive name of the bank */
-} mali_memory_bank;
-
-/**
- * Definition of the memory block type
- * Represents a memory block, which is the smallest memory unit operated on.
- * A block keeps info about its mapping, if in use by a user process
- */
-typedef struct mali_memory_block
-{
- _mali_osk_list_t link; /* used for freelist and process usage list*/
- mali_memory_bank * bank; /* the bank it belongs to */
- void __user * mapping; /* possible user space mapping of this block */
- u32 misc; /* used while a block is free to track the number blocks it represents */
- int descriptor;
- u32 mmap_cookie; /**< necessary for interaction with _mali_ukk_mem_mmap/munmap */
-} mali_memory_block;
-
-/**
- * Defintion of the type used to represent memory used by a session.
- * Containts the head of the list of memory currently in use by a session.
- */
-typedef struct memory_session
-{
- _mali_osk_lock_t *lock;
- _mali_osk_list_t memory_head; /* List of the memory blocks used by this session. */
- mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
-} memory_session;
-
-/*
- Subsystem interface implementation
-*/
-/**
- * Buddy block memory subsystem startup function
- * Called by the driver core when the driver is loaded.
- * Registers the memory systems ioctl handler, resource handlers and memory map function with the core.
- *
- * @param id Identifier assigned by the core to the memory subsystem
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id);
-
-/**
- * Buddy block memory subsystem shutdown function
- * Called by the driver core when the driver is unloaded.
- * Cleans up
- * @param id Identifier assigned by the core to the memory subsystem
- */
-static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id);
-
-/**
- * Buddy block memory load complete notification function.
- * Called by the driver core when all drivers have loaded and all resources has been registered
- * Reports on the memory resources registered
- * @param id Identifier assigned by the core to the memory subsystem
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id);
-
-
-/**
- * Buddy block memory subsystem session begin notification
- * Called by the core when a new session to the driver is started.
- * Creates a memory session object and sets it as the subsystem slot data for this session
- * @param slot Pointer to the slot to use for storing per-session data
- * @param queue The user space event sink
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
-
-/**
- * Buddy block memory subsystem session end notification
- * Called by the core when a session to the driver has ended.
- * Cleans up per session data, which includes checking and fixing memory leaks
- *
- * @param slot Pointer to the slot to use for storing per-session data
- */
-static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
-
-/**
- * Buddy block memory subsystem system info filler
- * Called by the core when a system info update is needed
- * We fill in info about all the memory types we have
- * @param info Pointer to system info struct to update
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info);
-
-/* our registered resource handlers */
-/**
- * Buddy block memory subsystem's notification handler for MEMORY resource instances.
- * Registered with the core during startup.
- * Called by the core for each memory bank described in the active architecture's config.h file.
- * Requests memory region ownership and calls backend.
- * @param resource The resource to handle (type MEMORY)
- * @return 0 if the memory was claimed and accepted, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_resource_memory(_mali_osk_resource_t * resource);
-
-/**
- * Buddy block memory subsystem's notification handler for MMU resource instances.
- * Registered with the core during startup.
- * Called by the core for each mmu described in the active architecture's config.h file.
- * @param resource The resource to handle (type MMU)
- * @return 0 if the MMU was found and initialized, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource);
-
-/**
- * Buddy block memory subsystem's notification handler for FPGA_FRAMEWORK resource instances.
- * Registered with the core during startup.
- * Called by the core for each fpga framework described in the active architecture's config.h file.
- * @param resource The resource to handle (type FPGA_FRAMEWORK)
- * @return 0 if the FPGA framework was found and initialized, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource);
-
-/* ioctl command implementations */
-/**
- * Buddy block memory subsystem's handler for MALI_IOC_MEM_GET_BIG_BLOCK ioctl
- * Called by the generic ioctl handler when the MALI_IOC_MEM_GET_BIG_BLOCK command is received.
- * Finds an available memory block and maps into the current process' address space.
- * @param ukk_private private word for use by the User/Kernel interface
- * @param session_data Pointer to the per-session object which will track the memory usage
- * @param argument The argument from the user. A pointer to an struct mali_dd_get_big_block in user space
- * @return Zero if successful, a standard Linux error value value on error (a negative value)
- */
-_mali_osk_errcode_t _mali_ukk_get_big_block( _mali_uk_get_big_block_s *args );
-
-/**
- * Buddy block memory subsystem's handler for MALI_IOC_MEM_FREE_BIG_BLOCK ioctl
- * Called by the generic ioctl handler when the MALI_IOC_MEM_FREE_BIG_BLOCK command is received.
- * Unmaps the memory from the process' address space and marks the block as free.
- * @param session_data Pointer to the per-session object which tracks the memory usage
- * @param argument The argument from the user. A pointer to an struct mali_dd_get_big_block in user space
- * @return Zero if successful, a standard Linux error value value on error (a negative value)
- */
-
-/* this static version allows us to make use of it while holding the memory_session lock.
- * This is required for the session_end code */
-static _mali_osk_errcode_t _mali_ukk_free_big_block_internal( struct mali_session_data * mali_session_data, memory_session * session_data, _mali_uk_free_big_block_s *args);
-
-_mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args );
-
-/**
- * Buddy block memory subsystem's memory bank registration routine
- * Called when a MEMORY resource has been found.
- * The memory region has already been reserved for use by this driver.
- * Create a bank object to represent this region and initialize its slots.
- * @note Can only be called in an module atomic scope, i.e. during module init since no locking is performed
- * @param phys_base Physical base address of this bank
- * @param cpu_usage_adjust Adjustment factor for CPU seen address
- * @param size Size of the bank in bytes
- * @param flags Memory type bits
- * @param alloc_order Order in which the bank will be used for allocations
- * @param name descriptive name of the bank
- * @return Zero on success, negative on error
- */
-static int mali_memory_bank_register(u32 phys_base, u32 cpu_usage_adjust, u32 size, u32 flags, u32 alloc_order, const char *name);
-
-/**
- * Get a block of mali memory of at least the given size and of the given type
- * This is the backend for get_big_block.
- * @param type_id The type id of memory requested.
- * @param minimum_size The size requested
- * @return Pointer to a block on success, NULL on failure
- */
-static mali_memory_block * mali_memory_block_get(u32 type_id, u32 minimum_size);
-
-/**
- * Get the mali seen address of the memory described by the block
- * @param block The memory block to return the address of
- * @return The mali seen address of the memory block
- */
-MALI_STATIC_INLINE u32 block_mali_addr_get(mali_memory_block * block);
-
-/**
- * Get the cpu seen address of the memory described by the block
- * The cpu_usage_adjust will be used to change the mali seen phys address
- * @param block The memory block to return the address of
- * @return The mali seen address of the memory block
- */
-MALI_STATIC_INLINE u32 block_cpu_addr_get(mali_memory_block * block);
-
-/**
- * Get the size of the memory described by the given block
- * @param block The memory block to return the size of
- * @return The size of the memory block described by the object
- */
-MALI_STATIC_INLINE u32 block_size_get(mali_memory_block * block);
-
-/**
- * Get the user space accessible mapping the memory described by the given memory block
- * Returns a pointer in user space to the memory, if one has been created.
- * @param block The memory block to return the mapping of
- * @return User space pointer to cpu accessible memory or NULL if not mapped
- */
-MALI_STATIC_INLINE void __user * block_mapping_get(mali_memory_block * block);
-
-/**
- * Set the user space accessible mapping the memory described by the given memory block.
- * Sets the stored pointer to user space for the memory described by this block.
- * @param block The memory block to set mapping info for
- * @param ptr User space pointer to cpu accessible memory or NULL if not mapped
- */
-MALI_STATIC_INLINE void block_mapping_set(mali_memory_block * block, void __user * ptr);
-
-/**
- * Get the cookie for use with _mali_ukk_mem_munmap().
- * @param block The memory block to get the cookie from
- * @return the cookie. A return of 0 is still a valid cookie.
- */
-MALI_STATIC_INLINE u32 block_mmap_cookie_get(mali_memory_block * block);
-
-/**
- * Set the cookie returned via _mali_ukk_mem_mmap().
- * @param block The memory block to set the cookie for
- * @param cookie the cookie
- */
-MALI_STATIC_INLINE void block_mmap_cookie_set(mali_memory_block * block, u32 cookie);
-
-
-/**
- * Get a memory block's free status
- * @param block The block to get the state of
- */
-MALI_STATIC_INLINE u32 get_block_free(mali_memory_block * block);
-
-/**
- * Set a memory block's free status
- * @param block The block to set the state for
- * @param state The state to set
- */
-MALI_STATIC_INLINE void set_block_free(mali_memory_block * block, int state);
-
-/**
- * Set a memory block's order
- * @param block The block to set the order for
- * @param order The order to set
- */
-MALI_STATIC_INLINE void set_block_order(mali_memory_block * block, u32 order);
-
-/**
- * Get a memory block's order
- * @param block The block to get the order for
- * @return The order this block exists on
- */
-MALI_STATIC_INLINE u32 get_block_order(mali_memory_block * block);
-
-/**
- * Tag a block as being a toplevel block.
- * A toplevel block has no buddy and no parent
- * @param block The block to tag as being toplevel
- */
-MALI_STATIC_INLINE void set_block_toplevel(mali_memory_block * block, u32 level);
-
-/**
- * Check if a block is a toplevel block
- * @param block The block to check
- * @return 1 if toplevel, 0 else
- */
-MALI_STATIC_INLINE u32 get_block_toplevel(mali_memory_block * block);
-
-/**
- * Checks if the given block is a buddy at the given order and that it's free
- * @param block The block to check
- * @param order The order to check against
- * @return 0 if not valid, else 1
- */
-MALI_STATIC_INLINE int block_is_valid_buddy(mali_memory_block * block, int order);
-
-/*
- The buddy system uses the following rules to quickly find a blocks buddy
- and parent (block representing this block at a higher order level):
- - Given a block with index i the blocks buddy is at index i ^ ( 1 << order)
- - Given a block with index i the blocks parent is at i & ~(1 << order)
-*/
-
-/**
- * Get a blocks buddy
- * @param block The block to find the buddy for
- * @param order The order to operate on
- * @return Pointer to the buddy block
- */
-MALI_STATIC_INLINE mali_memory_block * block_get_buddy(mali_memory_block * block, u32 order);
-
-/**
- * Get a blocks parent
- * @param block The block to find the parent for
- * @param order The order to operate on
- * @return Pointer to the parent block
- */
-MALI_STATIC_INLINE mali_memory_block * block_get_parent(mali_memory_block * block, u32 order);
-
-/**
- * Release mali memory
- * Backend for free_big_block.
- * Will release the mali memory described by the given block struct.
- * @param block Memory block to free
- */
-static void block_release(mali_memory_block * block);
-
-/* end interface implementation */
-
-/**
- * List of all the memory banks registerd with the subsystem.
- * Access to this list is NOT synchronized since it's only
- * written to during module init and termination.
- */
-static _MALI_OSK_LIST_HEAD(memory_banks_list);
-
-/*
- The buddy memory system's mali subsystem interface implementation.
- We currently handle module and session life-time management.
-*/
-struct mali_kernel_subsystem mali_subsystem_memory =
-{
- mali_memory_core_initialize, /* startup */
- NULL, /*mali_memory_core_terminate,*/ /* shutdown */
- mali_memory_core_load_complete, /* load_complete */
- mali_memory_core_system_info_fill, /* system_info_fill */
- mali_memory_core_session_begin, /* session_begin */
- mali_memory_core_session_end, /* session_end */
- NULL, /* broadcast_notification */
-#if MALI_STATE_TRACKING
- NULL, /* dump_state */
-#endif
-};
-
-/* Initialized when this subsystem is initialized. This is determined by the
- * position in subsystems[], and so the value used to initialize this is
- * determined at compile time */
-static mali_kernel_subsystem_identifier mali_subsystem_memory_id = -1;
-
-/* called during module init */
-static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id)
-{
- _MALI_OSK_INIT_LIST_HEAD(&memory_banks_list);
-
- mali_subsystem_memory_id = id;
-
- /* register our handlers */
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MEMORY, mali_memory_core_resource_memory));
-
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MMU, mali_memory_core_resource_mmu));
-
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(FPGA_FRAMEWORK, mali_memory_core_resource_fpga));
-
- MALI_SUCCESS;
-}
-
-/* called if/when our module is unloaded */
-static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id)
-{
- mali_memory_bank * bank, *temp;
-
- /* loop over all memory banks to free them */
- /* we use the safe version since we delete the current bank in the body */
- _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
- {
- MALI_DEBUG_CODE(int usage_count = _mali_osk_atomic_read(&bank->num_active_allocations));
- /*
- Report leaked memory
- If this happens we have a bug in our session cleanup code.
- */
- MALI_DEBUG_PRINT_IF(1, 0 != usage_count, ("%d allocation(s) from memory bank at 0x%X still in use\n", usage_count, bank->base_addr));
-
- _mali_osk_atomic_term(&bank->num_active_allocations);
-
- _mali_osk_lock_term(bank->lock);
-
- /* unlink from bank list */
- _mali_osk_list_del(&bank->list);
-
- /* release kernel resources used by the bank */
- _mali_osk_mem_unreqregion(bank->base_addr, bank->real_size);
-
- /* remove all resources used to represent this bank*/
- _mali_osk_free(bank->freelist);
- _mali_osk_free(bank->blocklist);
-
- /* destroy the bank object itself */
- _mali_osk_free(bank);
- }
-
- /* No need to de-initialize mali_subsystem_memory_id - it could only be
- * re-initialized to the same value */
-}
-
-/* load_complete handler */
-static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id)
-{
- mali_memory_bank * bank, *temp;
-
- MALI_DEBUG_PRINT( 1, ("Mali memory allocators will be used in this order of preference (lowest number first) :\n"));
-
- _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
- {
- if ( NULL != bank->name )
- {
- MALI_DEBUG_PRINT( 1, ("\t%d: %s\n", bank->alloc_order, bank->name) );
- }
- else
- {
- MALI_DEBUG_PRINT( 1, ("\t%d: (UNNAMED ALLOCATOR)\n", bank->alloc_order ) );
- }
- }
- MALI_SUCCESS;
-}
-
-MALI_STATIC_INLINE u32 order_needed_for_size(u32 size, struct mali_memory_bank * bank)
-{
- u32 order = 0;
-
- if (0 < size)
- {
- for ( order = sizeof(u32)*8 - 1; ((1UL<<order) & size) == 0; --order)
- /* nothing */;
-
- /* check if size is pow2, if not we need increment order by one */
- if (0 != (size & ((1UL<<order)-1))) ++order;
- }
-
- if ((NULL != bank) && (order < bank->min_order)) order = bank->min_order;
- /* Not capped to max order, that doesn't make sense */
-
- return order;
-}
-
-MALI_STATIC_INLINE u32 maximum_order_which_fits(u32 size)
-{
- u32 order = 0;
- u32 powsize = 1;
- while (powsize < size)
- {
- powsize <<= 1;
- if (powsize > size) break;
- order++;
- }
-
- return order;
-}
-
-/* called for new MEMORY resources */
-static _mali_osk_errcode_t mali_memory_bank_register(u32 phys_base, u32 cpu_usage_adjust, u32 size, u32 flags, u32 alloc_order, const char *name)
-{
- /* no locking performed due to function contract */
- int i;
- u32 left, offset;
- mali_memory_bank * bank;
- mali_memory_bank * bank_enum, *temp;
-
- _mali_osk_errcode_t err;
-
- /* Only a multiple of MIN_BLOCK_SIZE is usable */
- u32 usable_size = size & ~(MIN_BLOCK_SIZE - 1);
-
- /* handle zero sized banks and bank smaller than the fixed block size */
- if (0 == usable_size)
- {
- MALI_PRINT(("Usable size == 0\n"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- /* warn for banks not a muliple of the block size */
- MALI_DEBUG_PRINT_IF(1, usable_size != size, ("Memory bank @ 0x%X not a multiple of minimum block size. %d bytes wasted\n", phys_base, size - usable_size));
-
- /* check against previous registrations */
- MALI_DEBUG_CODE(
- {
- _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
- {
- /* duplicate ? */
- if (bank->base_addr == phys_base)
- {
- MALI_PRINT(("Duplicate registration of a memory bank at 0x%X detected\n", phys_base));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- /* overlapping ? */
- else if (
- ( (phys_base > bank->base_addr) && (phys_base < (bank->base_addr + bank->real_size)) ) ||
- ( (phys_base + size) > bank->base_addr && ((phys_base + size) < (bank->base_addr + bank->real_size)) )
- )
- {
- MALI_PRINT(("Overlapping memory blocks found. Memory at 0x%X overlaps with memory at 0x%X size 0x%X\n", bank->base_addr, phys_base, size));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- }
- }
- );
-
- /* create an object to represent this memory bank */
- MALI_CHECK_NON_NULL(bank = (mali_memory_bank*)_mali_osk_malloc(sizeof(mali_memory_bank)), _MALI_OSK_ERR_NOMEM);
-
- /* init the fields */
- _MALI_OSK_INIT_LIST_HEAD(&bank->list);
- bank->base_addr = phys_base;
- bank->cpu_usage_adjust = cpu_usage_adjust;
- bank->size = usable_size;
- bank->real_size = size;
- bank->alloc_order = alloc_order;
- bank->name = name;
-
- err = _mali_osk_atomic_init(&bank->num_active_allocations, 0);
- if (err != _MALI_OSK_ERR_OK)
- {
- _mali_osk_free(bank);
- MALI_ERROR(err);
- }
-
- bank->used_for_flags = flags;
- bank->min_order = order_needed_for_size(MIN_BLOCK_SIZE, NULL);
- bank->max_order = maximum_order_which_fits(usable_size);
- bank->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0);
- if (NULL == bank->lock)
- {
- _mali_osk_atomic_term(&bank->num_active_allocations);
- _mali_osk_free(bank);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- bank->blocklist = _mali_osk_calloc(1, sizeof(struct mali_memory_block) * (usable_size / MIN_BLOCK_SIZE));
- if (NULL == bank->blocklist)
- {
- _mali_osk_lock_term(bank->lock);
- _mali_osk_atomic_term(&bank->num_active_allocations);
- _mali_osk_free(bank);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- for (i = 0; i < (usable_size / MIN_BLOCK_SIZE); i++)
- {
- bank->blocklist[i].bank = bank;
- }
-
- bank->freelist = _mali_osk_calloc(1, sizeof(_mali_osk_list_t) * (bank->max_order - bank->min_order + 1));
- if (NULL == bank->freelist)
- {
- _mali_osk_lock_term(bank->lock);
- _mali_osk_free(bank->blocklist);
- _mali_osk_atomic_term(&bank->num_active_allocations);
- _mali_osk_free(bank);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- for (i = 0; i < (bank->max_order - bank->min_order + 1); i++) _MALI_OSK_INIT_LIST_HEAD(&bank->freelist[i]);
-
- /* init slot info */
- for (offset = 0, left = usable_size; offset < (usable_size / MIN_BLOCK_SIZE); /* updated inside the body */)
- {
- u32 block_order;
- mali_memory_block * block;
-
- /* the maximum order which fits in the remaining area */
- block_order = maximum_order_which_fits(left);
-
- /* find the block pointer */
- block = &bank->blocklist[offset];
-
- /* tag the block as being toplevel */
- set_block_toplevel(block, block_order);
-
- /* tag it as being free */
- set_block_free(block, 1);
-
- /* set the order */
- set_block_order(block, block_order);
-
- _mali_osk_list_addtail(&block->link, bank->freelist + (block_order - bank->min_order));
-
- left -= (1 << block_order);
- offset += ((1 << block_order) / MIN_BLOCK_SIZE);
- }
-
- /* add bank to list of banks on the system */
- _MALI_OSK_LIST_FOREACHENTRY( bank_enum, temp, &memory_banks_list, mali_memory_bank, list )
- {
- if ( bank_enum->alloc_order >= alloc_order )
- {
- /* Found insertion point - our item must go before this one */
- break;
- }
- }
- _mali_osk_list_addtail(&bank->list, &bank_enum->list);
-
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_memory_mmu_register(u32 type, u32 phys_base)
-{
- /* not supported */
- return _MALI_OSK_ERR_INVALID_FUNC;
-}
-
-void mali_memory_mmu_unregister(u32 phys_base)
-{
- /* not supported */
- return;
-}
-
-static mali_memory_block * mali_memory_block_get(u32 type_id, u32 minimum_size)
-{
- mali_memory_bank * bank;
- mali_memory_block * block = NULL;
- u32 requested_order, current_order;
-
- /* input validation */
- if (0 == minimum_size)
- {
- /* bad size */
- MALI_DEBUG_PRINT(2, ("Zero size block requested by mali_memory_block_get\n"));
- return NULL;
- }
-
- bank = (mali_memory_bank*)type_id;
-
- requested_order = order_needed_for_size(minimum_size, bank);
-
- MALI_DEBUG_PRINT(4, ("For size %d we need order %d (%d)\n", minimum_size, requested_order, 1 << requested_order));
-
- _mali_osk_lock_wait(bank->lock, _MALI_OSK_LOCKMODE_RW);
- /* ! critical section begin */
-
- MALI_DEBUG_PRINT(7, ("Bank 0x%x locked\n", bank));
-
- for (current_order = requested_order; current_order <= bank->max_order; ++current_order)
- {
- _mali_osk_list_t * list = bank->freelist + (current_order - bank->min_order);
- MALI_DEBUG_PRINT(7, ("Checking freelist 0x%x for order %d\n", list, current_order));
- if (0 != _mali_osk_list_empty(list)) continue; /* empty list */
-
- MALI_DEBUG_PRINT(7, ("Found an entry on the freelist for order %d\n", current_order));
-
-
- block = _MALI_OSK_LIST_ENTRY(list->next, mali_memory_block, link);
- _mali_osk_list_delinit(&block->link);
-
- while (current_order > requested_order)
- {
- mali_memory_block * buddy_block;
- MALI_DEBUG_PRINT(7, ("Splitting block 0x%x\n", block));
- current_order--;
- list--;
- buddy_block = block_get_buddy(block, current_order - bank->min_order);
- set_block_order(buddy_block, current_order);
- set_block_free(buddy_block, 1);
- _mali_osk_list_add(&buddy_block->link, list);
- }
-
- set_block_order(block, current_order);
- set_block_free(block, 0);
-
- /* update usage count */
- _mali_osk_atomic_inc(&bank->num_active_allocations);
-
- break;
- }
-
- /* ! critical section end */
- _mali_osk_lock_signal(bank->lock, _MALI_OSK_LOCKMODE_RW);
-
- MALI_DEBUG_PRINT(7, ("Lock released for bank 0x%x\n", bank));
-
- MALI_DEBUG_PRINT_IF(7, NULL != block, ("Block 0x%x allocated\n", block));
-
- return block;
-}
-
-
-static void block_release(mali_memory_block * block)
-{
- mali_memory_bank * bank;
- u32 current_order;
-
- if (NULL == block) return;
-
- bank = block->bank;
-
- /* we're manipulating the free list, so we need to lock it */
- _mali_osk_lock_wait(bank->lock, _MALI_OSK_LOCKMODE_RW);
- /* ! critical section begin */
-
- set_block_free(block, 1);
- current_order = get_block_order(block);
-
- while (current_order <= bank->max_order)
- {
- mali_memory_block * buddy_block;
- buddy_block = block_get_buddy(block, current_order - bank->min_order);
- if (!block_is_valid_buddy(buddy_block, current_order)) break;
- _mali_osk_list_delinit(&buddy_block->link); /* remove from free list */
- /* clear tracked data in both blocks */
- set_block_order(block, 0);
- set_block_free(block, 0);
- set_block_order(buddy_block, 0);
- set_block_free(buddy_block, 0);
- /* make the parent control the new state */
- block = block_get_parent(block, current_order - bank->min_order);
- set_block_order(block, current_order + 1); /* merged has a higher order */
- set_block_free(block, 1); /* mark it as free */
- current_order++;
- if (get_block_toplevel(block) == current_order) break; /* stop the merge if we've arrived at a toplevel block */
- }
-
- _mali_osk_list_add(&block->link, &bank->freelist[current_order - bank->min_order]);
-
- /* update bank usage statistics */
- _mali_osk_atomic_dec(&block->bank->num_active_allocations);
-
- /* !critical section end */
- _mali_osk_lock_signal(bank->lock, _MALI_OSK_LOCKMODE_RW);
-
- return;
-}
-
-MALI_STATIC_INLINE u32 block_get_offset(mali_memory_block * block)
-{
- return block - block->bank->blocklist;
-}
-
-MALI_STATIC_INLINE u32 block_mali_addr_get(mali_memory_block * block)
-{
- if (NULL != block) return block->bank->base_addr + MIN_BLOCK_SIZE * block_get_offset(block);
- else return 0;
-}
-
-MALI_STATIC_INLINE u32 block_cpu_addr_get(mali_memory_block * block)
-{
- if (NULL != block) return (block->bank->base_addr + MIN_BLOCK_SIZE * block_get_offset(block)) + block->bank->cpu_usage_adjust;
- else return 0;
-}
-
-MALI_STATIC_INLINE u32 block_size_get(mali_memory_block * block)
-{
- if (NULL != block) return 1 << get_block_order(block);
- else return 0;
-}
-
-MALI_STATIC_INLINE void __user * block_mapping_get(mali_memory_block * block)
-{
- if (NULL != block) return block->mapping;
- else return NULL;
-}
-
-MALI_STATIC_INLINE void block_mapping_set(mali_memory_block * block, void __user * ptr)
-{
- if (NULL != block) block->mapping = ptr;
-}
-
-MALI_STATIC_INLINE u32 block_mmap_cookie_get(mali_memory_block * block)
-{
- if (NULL != block) return block->mmap_cookie;
- else return 0;
-}
-
-/**
- * Set the cookie returned via _mali_ukk_mem_mmap().
- * @param block The memory block to set the cookie for
- * @param cookie the cookie
- */
-MALI_STATIC_INLINE void block_mmap_cookie_set(mali_memory_block * block, u32 cookie)
-{
- if (NULL != block) block->mmap_cookie = cookie;
-}
-
-
-static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
-{
- memory_session * session_data;
-
- /* validate input */
- if (NULL == slot)
- {
- MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- if (NULL != *slot)
- {
- MALI_DEBUG_PRINT(1, ("The slot given to memory session begin already contains data"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- /* create the session data object */
- MALI_CHECK_NON_NULL(session_data = _mali_osk_malloc(sizeof(memory_session)), _MALI_OSK_ERR_NOMEM);
-
- /* create descriptor mapping table */
- session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX);
-
- if (NULL == session_data->descriptor_mapping)
- {
- _mali_osk_free(session_data);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- _MALI_OSK_INIT_LIST_HEAD(&session_data->memory_head); /* no memory in use */
- session_data->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0);
- if (NULL == session_data->lock)
- {
- _mali_osk_free(session_data);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- *slot = session_data; /* slot will point to our data object */
-
- MALI_SUCCESS;
-}
-
-static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
-{
- memory_session * session_data;
-
- /* validate input */
- if (NULL == slot)
- {
- MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
- return;
- }
-
- if (NULL == *slot)
- {
- MALI_DEBUG_PRINT(1, ("NULL memory_session found in current session object"));
- return;
- }
-
- _mali_osk_lock_wait(((memory_session*)*slot)->lock, _MALI_OSK_LOCKMODE_RW);
- session_data = (memory_session *)*slot;
- /* clear our slot */
- *slot = NULL;
-
- /*
- First free all memory still being used.
- This can happen if the caller has leaked memory or
- the application has crashed forcing an auto-session end.
- */
- if (0 == _mali_osk_list_empty(&session_data->memory_head))
- {
- mali_memory_block * block, * temp;
- MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n"));
-
- /* use the _safe version since fre_big_block removes the active block from the list we're iterating */
- _MALI_OSK_LIST_FOREACHENTRY(block, temp, &session_data->memory_head, mali_memory_block, link)
- {
- _mali_osk_errcode_t err;
- _mali_uk_free_big_block_s uk_args;
-
- MALI_DEBUG_PRINT(4, ("Freeing block 0x%x with mali address 0x%x size %d mapped in user space at 0x%x\n",
- block,
- (void*)block_mali_addr_get(block),
- block_size_get(block),
- block_mapping_get(block))
- );
-
- /* free the block */
- /** @note manual type safety check-point */
- uk_args.ctx = mali_session_data;
- uk_args.cookie = (u32)block->descriptor;
- err = _mali_ukk_free_big_block_internal( mali_session_data, session_data, &uk_args );
-
- if ( _MALI_OSK_ERR_OK != err )
- {
- MALI_DEBUG_PRINT_ERROR(("_mali_ukk_free_big_block_internal() failed during session termination on block with cookie==0x%X\n",
- uk_args.cookie)
- );
- }
- }
- }
-
- if (NULL != session_data->descriptor_mapping)
- {
- mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
- session_data->descriptor_mapping = NULL;
- }
-
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- _mali_osk_lock_term(session_data->lock);
-
- /* free the session data object */
- _mali_osk_free(session_data);
-
- return;
-}
-
-static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info)
-{
- mali_memory_bank * bank, *temp;
- _mali_mem_info **mem_info_tail;
-
- /* check input */
- MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS);
-
- /* make sure we won't leak any memory. It could also be that it's an uninitialized variable, but that would be a bug in the caller */
- MALI_DEBUG_ASSERT(NULL == info->mem_info);
-
- mem_info_tail = &info->mem_info;
-
- _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
- {
- _mali_mem_info * mem_info;
-
- mem_info = (_mali_mem_info *)_mali_osk_calloc(1, sizeof(_mali_mem_info));
- if (NULL == mem_info) return _MALI_OSK_ERR_NOMEM; /* memory already allocated will be freed by the caller */
-
- /* set info */
- mem_info->size = bank->size;
- mem_info->flags = (_mali_bus_usage)bank->used_for_flags;
- mem_info->maximum_order_supported = bank->max_order;
- mem_info->identifier = (u32)bank;
-
- /* add to system info linked list */
- (*mem_info_tail) = mem_info;
- mem_info_tail = &mem_info->next;
- }
-
- /* all OK */
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_memory(_mali_osk_resource_t * resource)
-{
- _mali_osk_errcode_t err;
-
- /* Request ownership of the memory */
- if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description))
- {
- 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_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- /* call backend */
- err = mali_memory_bank_register(resource->base, resource->cpu_usage_adjust, resource->size, resource->flags, resource->alloc_order, resource->description);
- if (_MALI_OSK_ERR_OK != err)
- {
- /* if backend refused the memory we have to release the region again */
- MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
- _mali_osk_mem_unreqregion(resource->base, resource->size);
- MALI_ERROR(err);
- }
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource)
-{
- /* Not supported by the fixed block memory system */
- MALI_DEBUG_PRINT(1, ("MMU resource not supported by non-MMU driver!\n"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_FUNC);
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource)
-{
- mali_io_address mapping;
-
- MALI_DEBUG_PRINT(5, ("FPGA framework '%s' @ (0x%08X - 0x%08X)\n",
- resource->description, resource->base, resource->base + sizeof(u32) * 2 - 1
- ));
-
- mapping = _mali_osk_mem_mapioregion(resource->base + 0x1000, sizeof(u32) * 2, "fpga framework");
- if (mapping)
- {
- u32 data;
- data = _mali_osk_mem_ioread32(mapping, 0);
- MALI_DEBUG_PRINT(2, ("FPGA framwork '%s' @ 0x%08X:\n", resource->description, resource->base));
- MALI_DEBUG_PRINT(2, ("\tBitfile date: %d%02d%02d_%02d%02d\n",
- (data >> 20),
- (data >> 16) & 0xF,
- (data >> 11) & 0x1F,
- (data >> 6) & 0x1F,
- (data >> 0) & 0x3F));
- data = _mali_osk_mem_ioread32(mapping, sizeof(u32));
- MALI_DEBUG_PRINT(2, ("\tBitfile SCCS rev: %d\n", data));
-
- _mali_osk_mem_unmapioregion(resource->base + 0x1000, sizeof(u32) *2, mapping);
- }
- else MALI_DEBUG_PRINT(1, ("Failed to access FPGA framwork '%s' @ 0x%08X\n", resource->description, resource->base));
-
- MALI_SUCCESS;
-}
-
-/* static _mali_osk_errcode_t get_big_block(void * ukk_private, struct mali_session_data * mali_session_data, void __user * argument) */
-_mali_osk_errcode_t _mali_ukk_get_big_block( _mali_uk_get_big_block_s *args )
-{
- _mali_uk_mem_mmap_s args_mmap = {0, };
- int md;
- mali_memory_block * block;
- _mali_osk_errcode_t err;
- memory_session * session_data;
-
- MALI_DEBUG_ASSERT_POINTER( args );
-
- MALI_DEBUG_ASSERT_POINTER( args->ctx );
-
- /** @note manual type safety check-point */
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
-
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- if (!args->type_id)
- {
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* at least min block size */
- if (MIN_BLOCK_SIZE > args->minimum_size_requested) args->minimum_size_requested = MIN_BLOCK_SIZE;
-
- /* perform the actual allocation */
- block = mali_memory_block_get(args->type_id, args->minimum_size_requested);
- if ( NULL == block )
- {
- /* no memory available with requested type_id */
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, block, &md))
- {
- block_release(block);
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
- block->descriptor = md;
-
-
- /* fill in response */
- args->mali_address = block_mali_addr_get(block);
- args->block_size = block_size_get(block);
- args->cookie = (u32)md;
- args->flags = block->bank->used_for_flags;
-
- /* map the block into the process' address space */
-
- /** @note manual type safety check-point */
- args_mmap.ukk_private = (void *)args->ukk_private;
- args_mmap.ctx = args->ctx;
- args_mmap.size = args->block_size;
- args_mmap.phys_addr = block_cpu_addr_get(block);
-
-#ifndef _MALI_OSK_SPECIFIC_INDIRECT_MMAP
- err = _mali_ukk_mem_mmap( &args_mmap );
-#else
- err = _mali_osk_specific_indirect_mmap( &args_mmap );
-#endif
-
- /* check if the mapping failed */
- if ( _MALI_OSK_ERR_OK != err )
- {
- MALI_DEBUG_PRINT(1, ("Memory mapping failed 0x%x\n", args->cpuptr));
- /* mapping failed */
-
- /* remove descriptor entry */
- mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
-
- /* free the mali memory */
- block_release(block);
-
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- return err;
- }
-
- args->cpuptr = args_mmap.mapping;
- block_mmap_cookie_set(block, args_mmap.cookie);
- block_mapping_set(block, args->cpuptr);
-
- MALI_DEBUG_PRINT(2, ("Mali memory 0x%x (size %d) mapped in process memory space at 0x%x\n", (void*)args->mali_address, args->block_size, args->cpuptr));
-
- /* track memory in use for the session */
- _mali_osk_list_addtail(&block->link, &session_data->memory_head);
-
- /* memory assigned to the session, memory mapped into the process' view */
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- MALI_SUCCESS;
-}
-
-/* Internal code that assumes the memory session lock is held */
-static _mali_osk_errcode_t _mali_ukk_free_big_block_internal( struct mali_session_data * mali_session_data, memory_session * session_data, _mali_uk_free_big_block_s *args)
-{
- mali_memory_block * block = NULL;
- _mali_osk_errcode_t err;
- _mali_uk_mem_munmap_s args_munmap = {0,};
-
- MALI_DEBUG_ASSERT_POINTER( mali_session_data );
- MALI_DEBUG_ASSERT_POINTER( session_data );
- MALI_DEBUG_ASSERT_POINTER( args );
-
- err = mali_descriptor_mapping_get(session_data->descriptor_mapping, (int)args->cookie, (void**)&block);
- if (_MALI_OSK_ERR_OK != err)
- {
- MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release memory pages\n", (int)args->cookie));
- MALI_ERROR(err);
- }
-
- MALI_DEBUG_ASSERT_POINTER(block);
-
- MALI_DEBUG_PRINT(4, ("Asked to free block 0x%x with mali address 0x%x size %d mapped in user space at 0x%x\n",
- block,
- (void*)block_mali_addr_get(block),
- block_size_get(block),
- block_mapping_get(block))
- );
-
- /** @note manual type safety check-point */
- args_munmap.ctx = (void*)mali_session_data;
- args_munmap.mapping = block_mapping_get( block );
- args_munmap.size = block_size_get( block );
- args_munmap.cookie = block_mmap_cookie_get( block );
-
-#ifndef _MALI_OSK_SPECIFIC_INDIRECT_MMAP
- _mali_ukk_mem_munmap( &args_munmap );
-#else
- _mali_osk_specific_indirect_munmap( &args_munmap );
-#endif
-
- MALI_DEBUG_PRINT(6, ("Session data 0x%x, lock 0x%x\n", session_data, &session_data->lock));
-
- /* unlink from session usage list */
- MALI_DEBUG_PRINT(5, ("unlink from session usage list\n"));
- _mali_osk_list_delinit(&block->link);
-
- /* remove descriptor entry */
- mali_descriptor_mapping_free(session_data->descriptor_mapping, (int)args->cookie);
-
- /* free the mali memory */
- block_release(block);
- MALI_DEBUG_PRINT(5, ("Block freed\n"));
-
- MALI_SUCCESS;
-}
-
-/* static _mali_osk_errcode_t free_big_block( struct mali_session_data * mali_session_data, void __user * argument) */
-_mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args )
-{
- _mali_osk_errcode_t err;
- struct mali_session_data * mali_session_data;
- memory_session * session_data;
-
- MALI_DEBUG_ASSERT_POINTER( args );
-
- MALI_DEBUG_ASSERT_POINTER( args->ctx );
-
- /** @note manual type safety check-point */
- mali_session_data = (struct mali_session_data *)args->ctx;
-
- /* Must always verify this, since these are provided by the user */
- MALI_CHECK_NON_NULL(mali_session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
-
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- /** @note this has been separated out so that the session_end handler can call this while it has the memory_session lock held */
- err = _mali_ukk_free_big_block_internal( mali_session_data, session_data, args );
-
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- return err;
-}
-
-MALI_STATIC_INLINE u32 get_block_free(mali_memory_block * block)
-{
- return (block->misc >> MISC_SHIFT_FREE) & MISC_MASK_FREE;
-}
-
-MALI_STATIC_INLINE void set_block_free(mali_memory_block * block, int state)
-{
- if (state) block->misc |= (MISC_MASK_FREE << MISC_SHIFT_FREE);
- else block->misc &= ~(MISC_MASK_FREE << MISC_SHIFT_FREE);
-}
-
-MALI_STATIC_INLINE void set_block_order(mali_memory_block * block, u32 order)
-{
- block->misc &= ~(MISC_MASK_ORDER << MISC_SHIFT_ORDER);
- block->misc |= ((order & MISC_MASK_ORDER) << MISC_SHIFT_ORDER);
-}
-
-MALI_STATIC_INLINE u32 get_block_order(mali_memory_block * block)
-{
- return (block->misc >> MISC_SHIFT_ORDER) & MISC_MASK_ORDER;
-}
-
-MALI_STATIC_INLINE void set_block_toplevel(mali_memory_block * block, u32 level)
-{
- block->misc |= ((level & MISC_MASK_TOPLEVEL) << MISC_SHIFT_TOPLEVEL);
-}
-
-MALI_STATIC_INLINE u32 get_block_toplevel(mali_memory_block * block)
-{
- return (block->misc >> MISC_SHIFT_TOPLEVEL) & MISC_MASK_TOPLEVEL;
-}
-
-MALI_STATIC_INLINE int block_is_valid_buddy(mali_memory_block * block, int order)
-{
- if (get_block_free(block) && (get_block_order(block) == order)) return 1;
- else return 0;
-}
-
-MALI_STATIC_INLINE mali_memory_block * block_get_buddy(mali_memory_block * block, u32 order)
-{
- return block + ( (block_get_offset(block) ^ (1 << order)) - block_get_offset(block));
-}
-
-MALI_STATIC_INLINE mali_memory_block * block_get_parent(mali_memory_block * block, u32 order)
-{
- return block + ((block_get_offset(block) & ~(1 << order)) - block_get_offset(block));
-}
-
-/* This handler registered to mali_mmap for non-MMU builds */
-_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args )
-{
- _mali_osk_errcode_t ret;
- struct mali_session_data * mali_session_data;
- mali_memory_allocation * descriptor;
- memory_session * session_data;
-
- /* validate input */
- if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
-
- /* Unpack arguments */
- mali_session_data = (struct mali_session_data *)args->ctx;
-
- if (NULL == mali_session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: mali_session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
-
- MALI_DEBUG_ASSERT( mali_subsystem_memory_id >= 0 );
-
- session_data = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
- /* validate input */
- if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); }
-
- descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) );
- if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); }
-
- descriptor->size = args->size;
- descriptor->mali_address = args->phys_addr;
- descriptor->mali_addr_mapping_info = (void*)session_data;
- descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */
- descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE;
-
- ret = _mali_osk_mem_mapregion_init( descriptor );
- if ( _MALI_OSK_ERR_OK != ret )
- {
- MALI_DEBUG_PRINT(3, ("_mali_osk_mem_mapregion_init() failed\n"));
- _mali_osk_free(descriptor);
- MALI_ERROR(ret);
- }
-
- ret = _mali_osk_mem_mapregion_map( descriptor, 0, &descriptor->mali_address, descriptor->size );
- if ( _MALI_OSK_ERR_OK != ret )
- {
- MALI_DEBUG_PRINT(3, ("_mali_osk_mem_mapregion_map() failed\n"));
- _mali_osk_mem_mapregion_term( descriptor );
- _mali_osk_free(descriptor);
- MALI_ERROR(ret);
- }
-
- args->mapping = descriptor->mapping;
-
- /**
- * @note we do not require use of mali_descriptor_mapping here:
- * the cookie gets stored in the mali_memory_block struct, which itself is
- * protected by mali_descriptor_mapping, and so this cookie never leaves
- * kernel space (on any OS).
- *
- * In the MMU case, we must use a mali_descriptor_mapping, since on _some_
- * OSs, the cookie leaves kernel space.
- */
- args->cookie = (u32)descriptor;
- MALI_SUCCESS;
-}
-
-/* This handler registered to mali_munmap for non-MMU builds */
-_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args )
-{
- mali_memory_allocation * descriptor;
-
- /** see note in _mali_ukk_mem_mmap() - no need to use descriptor mapping */
- descriptor = (mali_memory_allocation *)args->cookie;
- MALI_DEBUG_ASSERT_POINTER(descriptor);
-
- /* args->mapping and args->size are also discarded. They are only necessary for certain do_munmap implementations. However, they could be used to check the descriptor at this point. */
- _mali_osk_mem_mapregion_unmap( descriptor, 0, descriptor->size, (_mali_osk_mem_mapregion_flags_t)0 );
-
- _mali_osk_mem_mapregion_term( descriptor );
-
- _mali_osk_free(descriptor);
-
- return _MALI_OSK_ERR_OK;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c
deleted file mode 100644
index c993ad5..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c
+++ /dev/null
@@ -1,3157 +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.
- */
-
-#include "mali_kernel_subsystem.h"
-#include "mali_kernel_mem.h"
-#include "mali_kernel_ioctl.h"
-#include "mali_kernel_descriptor_mapping.h"
-#include "mali_kernel_mem_mmu.h"
-#include "mali_kernel_memory_engine.h"
-#include "mali_block_allocator.h"
-#include "mali_kernel_mem_os.h"
-#include "mali_kernel_session_manager.h"
-#include "mali_kernel_core.h"
-#include "mali_kernel_rendercore.h"
-
-#if defined USING_MALI400_L2_CACHE
-#include "mali_kernel_l2_cache.h"
-#endif
-
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
-#include "ump_kernel_interface.h"
-#endif
-
-/* kernel side OS functions and user-kernel interface */
-#include "mali_osk.h"
-#include "mali_osk_mali.h"
-#include "mali_ukk.h"
-#include "mali_osk_bitops.h"
-#include "mali_osk_list.h"
-
-/**
- * Size of the MMU registers in bytes
- */
-#define MALI_MMU_REGISTERS_SIZE 0x24
-
-/**
- * Size of an MMU page in bytes
- */
-#define MALI_MMU_PAGE_SIZE 0x1000
-
-/**
- * Page directory index from address
- * Calculates the page directory index from the given address
- */
-#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF)
-
-/**
- * Page table index from address
- * Calculates the page table index from the given address
- */
-#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF)
-
-/**
- * Extract the memory address from an PDE/PTE entry
- */
-#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00)
-
-/**
- * Calculate memory address from PDE and PTE
- */
-#define MALI_MMU_ADDRESS(pde, pte) (((pde)<<22) | ((pte)<<12))
-
-/**
- * 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 */
-
-/**
- * Per-session memory descriptor mapping table sizes
- */
-#define MALI_MEM_DESCRIPTORS_INIT 64
-#define MALI_MEM_DESCRIPTORS_MAX 65536
-
-/**
- * Used to disallow more than one core to run a MMU at the same time
- *
- * @note This value is hardwired into some systems' configuration files,
- * which \em might not be a header file (e.g. some external data configuration
- * file). Therefore, if this value is modified, its occurance must be
- * \b manually checked for in the entire driver source tree.
- */
-#define MALI_MMU_DISALLOW_PARALLELL_WORK_OF_MALI_CORES 1
-
-#define MALI_INVALID_PAGE ((u32)(~0))
-
-/**
- *
- */
-typedef enum mali_mmu_entry_flags
-{
- MALI_MMU_FLAGS_PRESENT = 0x01,
- MALI_MMU_FLAGS_READ_PERMISSION = 0x02,
- MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04,
- MALI_MMU_FLAGS_MASK = 0x07
-} mali_mmu_entry_flags;
-
-/**
- * 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 = 0x0001, /**< Status of the MMU */
- MALI_MMU_REGISTER_COMMAND = 0x0002, /**< Command register, used to control the MMU */
- MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x0003, /**< Logical address of the last page fault */
- MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x004, /**< Used to invalidate the mapping of a single page from the MMU */
- MALI_MMU_REGISTER_INT_RAWSTAT = 0x0005, /**< Raw interrupt status, all interrupts visible */
- MALI_MMU_REGISTER_INT_CLEAR = 0x0006, /**< Indicate to the MMU that the interrupt has been received */
- MALI_MMU_REGISTER_INT_MASK = 0x0007, /**< Enable/disable types of interrupts */
- MALI_MMU_REGISTER_INT_STATUS = 0x0008 /**< 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.
- */
-typedef enum mali_mmu_command
-{
- MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
- MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
- MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */
- MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
- MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
- MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
- MALI_MMU_COMMAND_SOFT_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;
-
-/**
- * Defintion of the type used to represent memory used by a session.
- * Containts the pointer to the huge user space virtual memory area
- * used to access the Mali memory.
- */
-typedef struct memory_session
-{
- _mali_osk_lock_t *lock; /**< Lock protecting the vm manipulation */
-
- u32 mali_base_address; /**< Mali virtual memory area used by this session */
- mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
-
- u32 page_directory; /**< Physical address of the memory session's page directory */
-
- mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */
- mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */
- u32 page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */
-
- _mali_osk_list_t active_mmus; /**< The MMUs in this session, in increasing order of ID (so we can lock them in the correct order when necessary) */
- _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */
-} memory_session;
-
-typedef struct mali_kernel_memory_mmu_idle_callback
-{
- _mali_osk_list_t link;
- void (*callback)(void*);
- void * callback_argument;
-} mali_kernel_memory_mmu_idle_callback;
-
-/**
- * Definition of the MMU struct
- * Used to track a MMU unit in the system.
- * Contains information about the mapping of the registers
- */
-typedef struct mali_kernel_memory_mmu
-{
- int id; /**< ID of the MMU, no duplicate IDs may exist on the system */
- const char * description; /**< Description text received from the resource manager to help identify the resource for people */
- int irq_nr; /**< IRQ number */
- u32 base; /**< Physical address of the registers */
- mali_io_address mapped_registers; /**< Virtual mapping of the registers */
- u32 mapping_size; /**< Size of registers in bytes */
- _mali_osk_list_t list; /**< Used to link multiple MMU's into a list */
- _mali_osk_irq_t *irq;
- u32 flags; /**< Used to store if there is something special with this mmu. */
-
- _mali_osk_lock_t *lock; /**< Lock protecting access to the usage fields */
- /* usage fields */
- memory_session * active_session; /**< Active session, NULL if no session is active */
- u32 usage_count; /**< Number of nested activations of the active session */
- _mali_osk_list_t callbacks; /**< Callback registered for MMU idle notification */
- void *core;
-
- int in_page_fault_handler;
-
- _mali_osk_list_t session_link;
-} mali_kernel_memory_mmu;
-
-typedef struct dedicated_memory_info
-{
- u32 base;
- u32 size;
- struct dedicated_memory_info * next;
-} 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
-typedef struct ump_mem_allocation
-{
- mali_allocation_engine * engine;
- mali_memory_allocation * descriptor;
- u32 initial_offset;
- u32 size_allocated;
- ump_dd_handle ump_mem;
-} ump_mem_allocation ;
-#endif
-
-typedef struct external_mem_allocation
-{
- mali_allocation_engine * engine;
- mali_memory_allocation * descriptor;
- u32 initial_offset;
- u32 size;
-} external_mem_allocation;
-
-/*
- Subsystem interface implementation
-*/
-/**
- * Fixed block memory subsystem startup function.
- * Called by the driver core when the driver is loaded.
- * Registers the memory systems ioctl handler, resource handlers and memory map function with the core.
- *
- * @param id Identifier assigned by the core to the memory subsystem
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id);
-
-/**
- * Fixed block memory subsystem shutdown function.
- * Called by the driver core when the driver is unloaded.
- * Cleans up
- * @param id Identifier assigned by the core to the memory subsystem
- */
-static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id);
-
-/**
- * MMU Memory load complete notification function.
- * Called by the driver core when all drivers have loaded and all resources has been registered
- * Builds the memory overall memory list
- * @param id Identifier assigned by the core to the memory subsystem
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id);
-
-/**
- * Fixed block memory subsystem session begin notification
- * Called by the core when a new session to the driver is started.
- * Creates a memory session object and sets it as the subsystem slot data for this session
- * @param slot Pointer to the slot to use for storing per-session data
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
-
-/**
- * Fixed block memory subsystem session end notification
- * Called by the core when a session to the driver has ended.
- * Cleans up per session data, which includes checking and fixing memory leaks
- *
- * @param slot Pointer to the slot to use for storing per-session data
- */
-static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
-
-/**
- * Fixed block memory subsystem system info filler
- * Called by the core when a system info update is needed
- * We fill in info about all the memory types we have
- * @param info Pointer to system info struct to update
- * @return 0 on success, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info);
-
-/* our registered resource handlers */
-
-/**
- * Fixed block memory subsystem's notification handler for MMU resource instances.
- * Registered with the core during startup.
- * Called by the core for each mmu described in the active architecture's config.h file.
- * @param resource The resource to handle (type MMU)
- * @return 0 if the MMU was found and initialized, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource);
-
-/**
- * Fixed block memory subsystem's notification handler for FPGA_FRAMEWORK resource instances.
- * Registered with the core during startup.
- * Called by the core for each fpga framework described in the active architecture's config.h file.
- * @param resource The resource to handle (type FPGA_FRAMEWORK)
- * @return 0 if the FPGA framework was found and initialized, negative on error
- */
-static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource);
-
-
-static _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource);
-static _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource);
-
-/**
- * @brief Internal function for unmapping memory
- *
- * Worker function for unmapping memory from a user-process. We assume that the
- * session/descriptor's lock was obtained before entry. For example, the
- * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this
- * function to do the actual unmapping. mali_memory_core_session_end() could
- * also call this directly (depending on compilation options), having locked
- * the descriptor.
- *
- * This function will fail if it is unable to put the MMU in stall mode (which
- * might be the case if a page fault is also being processed).
- *
- * @param args see _mali_uk_mem_munmap_s in "mali_uk_types.h"
- * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
- */
-static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args );
-
-/**
- * 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_kernel_memory_mmu_interrupt_handler_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_kernel_memory_mmu_interrupt_handler_bottom_half ( void *data );
-
-/**
- * Read MMU register value
- * Reads the contents of the specified register.
- * @param unit The MMU to read from
- * @param reg The register to read
- * @return The contents of the register
- */
-static u32 mali_mmu_register_read(mali_kernel_memory_mmu * unit, mali_mmu_register reg);
-
-/**
- * Write to a MMU register
- * Writes the given value to the specified register
- * @param unit The MMU to write to
- * @param reg The register to write to
- * @param val The value to write to the register
- */
-static void mali_mmu_register_write(mali_kernel_memory_mmu * unit, mali_mmu_register reg, u32 val);
-
-/**
- * Issues the reset command to the MMU and waits for HW to be ready again
- * @param mmu The MMU to reset
- */
-static void mali_mmu_raw_reset(mali_kernel_memory_mmu * mmu);
-
-/**
- * Issues the enable paging command to the MMU and waits for HW to complete the request
- * @param mmu The MMU to enable paging for
- */
-static void mali_mmu_enable_paging(mali_kernel_memory_mmu * 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)
- */
-static mali_bool mali_mmu_enable_stall(mali_kernel_memory_mmu * 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
- */
-static void mali_mmu_disable_stall(mali_kernel_memory_mmu * mmu);
-
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
-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*/
-
-
-static void external_memory_release(void * ctx, void * handle);
-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);
-
-
-
-
-/* nop functions */
-
-/* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */
-static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */
-static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size);
-static void mali_address_manager_release(mali_memory_allocation * descriptor);
-
-static void mali_mmu_activate_address_space(mali_kernel_memory_mmu * mmu, u32 page_directory);
-
-_mali_osk_errcode_t mali_mmu_page_table_cache_create(void);
-void mali_mmu_page_table_cache_destroy(void);
-
-_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping);
-void mali_mmu_release_table_page(u32 pa);
-
-static _mali_osk_errcode_t mali_allocate_empty_page_directory(void);
-
-static void mali_free_empty_page_directory(void);
-
-static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data);
-
-static _mali_osk_errcode_t mali_allocate_fault_flush_pages(void);
-
-static void mali_free_fault_flush_pages(void);
-
-static void mali_mmu_probe_irq_trigger(mali_kernel_memory_mmu * mmu);
-static _mali_osk_errcode_t mali_mmu_probe_irq_acknowledge(mali_kernel_memory_mmu * mmu);
-
-/* MMU variables */
-
-typedef struct mali_mmu_page_table_allocation
-{
- _mali_osk_list_t list;
- u32 * usage_map;
- u32 usage_count;
- u32 num_pages;
- mali_page_table_block pages;
-} mali_mmu_page_table_allocation;
-
-typedef struct mali_mmu_page_table_allocations
-{
- _mali_osk_lock_t *lock;
- _mali_osk_list_t partial;
- _mali_osk_list_t full;
- /* we never hold on to a empty allocation */
-} mali_mmu_page_table_allocations;
-
-/* Head of the list of MMUs */
-static _MALI_OSK_LIST_HEAD(mmu_head);
-
-/* the mmu page table cache */
-static struct mali_mmu_page_table_allocations page_table_cache;
-
-/* page fault queue flush helper pages
- * note that the mapping pointers are currently unused outside of the initialization functions */
-static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
-static mali_io_address mali_page_fault_flush_page_directory_mapping = NULL;
-static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
-static mali_io_address mali_page_fault_flush_page_table_mapping = NULL;
-static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
-static mali_io_address mali_page_fault_flush_data_page_mapping = NULL;
-
-/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */
-static u32 mali_empty_page_directory = MALI_INVALID_PAGE;
-
-/*
- The fixed memory system's mali subsystem interface implementation.
- We currently handle module and session life-time management.
-*/
-struct mali_kernel_subsystem mali_subsystem_memory =
-{
- mali_memory_core_initialize, /* startup */
- NULL, /*mali_memory_core_terminate,*/ /* shutdown */
- mali_memory_core_load_complete, /* load_complete */
- mali_memory_core_system_info_fill, /* system_info_fill */
- mali_memory_core_session_begin, /* session_begin */
- mali_memory_core_session_end, /* session_end */
- NULL, /* broadcast_notification */
-#if MALI_STATE_TRACKING
- NULL, /* dump_state */
-#endif
-};
-
-static mali_kernel_mem_address_manager mali_address_manager =
-{
- mali_address_manager_allocate, /* allocate */
- mali_address_manager_release, /* release */
- mali_address_manager_map, /* map_physical */
- NULL /* unmap_physical not present*/
-};
-
-static mali_kernel_mem_address_manager process_address_manager =
-{
- _mali_osk_mem_mapregion_init, /* allocate */
- _mali_osk_mem_mapregion_term, /* release */
- _mali_osk_mem_mapregion_map, /* map_physical */
- _mali_osk_mem_mapregion_unmap /* unmap_physical */
-};
-
-static mali_allocation_engine memory_engine = NULL;
-static mali_physical_memory_allocator * physical_memory_allocators = NULL;
-
-static dedicated_memory_info * mem_region_registrations = NULL;
-
-/* Initialized when this subsystem is initialized. This is determined by the
- * position in subsystems[], and so the value used to initialize this is
- * determined at compile time */
-static mali_kernel_subsystem_identifier mali_subsystem_memory_id = (mali_kernel_subsystem_identifier)-1;
-
-/* called during module init */
-static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id)
-{
- MALI_DEBUG_PRINT(2, ("MMU memory system initializing\n"));
-
- /* save our subsystem id for later for use in slot lookup during session activation */
- mali_subsystem_memory_id = id;
-
- _MALI_OSK_INIT_LIST_HEAD(&mmu_head);
-
- MALI_CHECK_NO_ERROR( mali_mmu_page_table_cache_create() );
-
- /* register our handlers */
- MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(MMU, mali_memory_core_resource_mmu) );
-
- MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(FPGA_FRAMEWORK, mali_memory_core_resource_fpga) );
-
- MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(MEMORY, mali_memory_core_resource_dedicated_memory) );
-
- MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(OS_MEMORY, mali_memory_core_resource_os_memory) );
-
- memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager);
- MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT);
-
- MALI_SUCCESS;
-}
-
-/* called if/when our module is unloaded */
-static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id)
-{
- mali_kernel_memory_mmu * mmu, *temp_mmu;
-
- MALI_DEBUG_PRINT(2, ("MMU memory system terminating\n"));
-
- /* loop over all MMU units and shut them down */
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list)
- {
- /* reset to defaults */
- mali_mmu_raw_reset(mmu);
-
- /* unregister the irq */
- _mali_osk_irq_term(mmu->irq);
-
- /* remove from the list of MMU's on the system */
- _mali_osk_list_del(&mmu->list);
-
- /* release resources */
- _mali_osk_mem_unmapioregion(mmu->base, mmu->mapping_size, mmu->mapped_registers);
- _mali_osk_mem_unreqregion(mmu->base, mmu->mapping_size);
- _mali_osk_lock_term(mmu->lock);
- _mali_osk_free(mmu);
- }
-
- /* free global helper pages */
- mali_free_empty_page_directory();
- mali_free_fault_flush_pages();
-
- /* destroy the page table cache before shutting down backends in case we have a page table leak to report */
- mali_mmu_page_table_cache_destroy();
-
- while ( NULL != mem_region_registrations)
- {
- dedicated_memory_info * m;
- m = mem_region_registrations;
- mem_region_registrations = m->next;
- _mali_osk_mem_unreqregion(m->base, m->size);
- _mali_osk_free(m);
- }
-
- while ( NULL != physical_memory_allocators)
- {
- mali_physical_memory_allocator * m;
- m = physical_memory_allocators;
- physical_memory_allocators = m->next;
- m->destroy(m);
- }
-
- if (NULL != memory_engine)
- {
- mali_allocation_engine_destroy(memory_engine);
- memory_engine = NULL;
- }
-
-}
-
-static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
-{
- memory_session * session_data;
- _mali_osk_errcode_t err;
- int i;
- mali_io_address pd_mapped;
-
- /* validate input */
- if (NULL == slot)
- {
- MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- if (NULL != *slot)
- {
- MALI_DEBUG_PRINT(1, ("The slot given to memory session begin already contains data"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- MALI_DEBUG_PRINT(2, ("MMU session begin\n"));
-
- /* create the session data object */
- session_data = _mali_osk_calloc(1, sizeof(memory_session));
- MALI_CHECK_NON_NULL( session_data, _MALI_OSK_ERR_NOMEM );
-
- /* create descriptor mapping table */
- session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX);
-
- if (NULL == session_data->descriptor_mapping)
- {
- _mali_osk_free(session_data);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- err = mali_mmu_get_table_page(&session_data->page_directory, &pd_mapped);
-
- session_data->page_directory_mapped = pd_mapped;
- if (_MALI_OSK_ERR_OK != err)
- {
- mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
- _mali_osk_free(session_data);
- MALI_ERROR(err);
- }
- MALI_DEBUG_ASSERT_POINTER( session_data->page_directory_mapped );
-
- MALI_DEBUG_PRINT(2, ("Page directory for session 0x%x placed at physical address 0x%08X\n", mali_session_data, session_data->page_directory));
-
- for (i = 0; i < MALI_MMU_PAGE_SIZE/4; i++)
- {
- /* mark each page table as not present */
- _mali_osk_mem_iowrite32_relaxed(session_data->page_directory_mapped, sizeof(u32) * i, 0);
- }
- _mali_osk_write_mem_barrier();
-
- /* page_table_mapped[] is already set to NULL by _mali_osk_calloc call */
-
- _MALI_OSK_INIT_LIST_HEAD(&session_data->active_mmus);
- session_data->lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 128);
- if (NULL == session_data->lock)
- {
- mali_mmu_release_table_page(session_data->page_directory);
- mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
- _mali_osk_free(session_data);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* Init the session's memory allocation list */
- _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head );
-
- *slot = session_data; /* slot will point to our data object */
- MALI_DEBUG_PRINT(2, ("MMU session begin: success\n"));
- MALI_SUCCESS;
-}
-
-static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target)
-{
- mali_memory_allocation * descriptor;
-
- descriptor = (mali_memory_allocation*)map_target;
-
- MALI_DEBUG_PRINT(1, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target));
- MALI_DEBUG_ASSERT(descriptor);
-
- mali_allocation_engine_release_memory(memory_engine, descriptor);
- _mali_osk_free(descriptor);
-}
-
-static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
-{
- memory_session * session_data;
- int i;
- const int num_page_table_entries = sizeof(session_data->page_entries_mapped) / sizeof(session_data->page_entries_mapped[0]);
-
- MALI_DEBUG_PRINT(2, ("MMU session end\n"));
-
- /* validate input */
- if (NULL == slot)
- {
- MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
- return;
- }
-
- session_data = (memory_session *)*slot;
-
- if (NULL == session_data)
- {
- MALI_DEBUG_PRINT(1, ("No session data found during session end\n"));
- return;
- }
- /* Lock the session so we can modify the memory list */
- _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW );
- /* Noninterruptable spinlock type, so must always have locked. Checking should've been done in OSK function. */
-
-#ifndef MALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP
-#if _MALI_OSK_SPECIFIC_INDIRECT_MMAP
-#error Indirect MMAP specified, but UKK does not have implicit MMAP cleanup. Current implementation does not handle this.
-#else
-
- /* Free all memory engine allocations */
- if (0 == _mali_osk_list_empty(&session_data->memory_head))
- {
- mali_memory_allocation *descriptor;
- mali_memory_allocation *temp;
- _mali_uk_mem_munmap_s unmap_args;
-
- MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n"));
-
- unmap_args.ctx = mali_session_data;
-
- /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
- _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->memory_head, mali_memory_allocation, list)
- {
- MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n",
- descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping)
- );
- /* ASSERT that the descriptor's lock references the correct thing */
- MALI_DEBUG_ASSERT( descriptor->lock == session_data->lock );
- /* Therefore, we have already locked the descriptor */
-
- unmap_args.size = descriptor->size;
- unmap_args.mapping = descriptor->mapping;
- unmap_args.cookie = (u32)descriptor;
-
- /*
- * This removes the descriptor from the list, and frees the descriptor
- *
- * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since
- * the only OS we are aware of that requires indirect MMAP also has
- * implicit mmap cleanup.
- */
- _mali_ukk_mem_munmap_internal( &unmap_args );
- }
- }
-
- /* Assert that we really did free everything */
- MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) );
-#endif /* _MALI_OSK_SPECIFIC_INDIRECT_MMAP */
-#endif /* MALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP */
-
- if (NULL != session_data->descriptor_mapping)
- {
- mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback);
- mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
- session_data->descriptor_mapping = NULL;
- }
-
- for (i = 0; i < num_page_table_entries; i++)
- {
- /* free PTE memory */
- if (session_data->page_directory_mapped && (_mali_osk_mem_ioread32(session_data->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT))
- {
- mali_mmu_release_table_page( _mali_osk_mem_ioread32(session_data->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
- _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), 0);
- }
- }
-
- if (MALI_INVALID_PAGE != session_data->page_directory)
- {
- mali_mmu_release_table_page(session_data->page_directory);
- session_data->page_directory = MALI_INVALID_PAGE;
- }
-
- _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW );
-
- /**
- * @note Could the VMA close handler mean that we use the session data after it was freed?
- * In which case, would need to refcount the session data, and free on VMA close
- */
-
- /* Free the lock */
- _mali_osk_lock_term( session_data->lock );
- /* free the session data object */
- _mali_osk_free(session_data);
-
- /* clear our slot */
- *slot = NULL;
-
- return;
-}
-
-static _mali_osk_errcode_t mali_allocate_empty_page_directory(void)
-{
- _mali_osk_errcode_t err;
- mali_io_address mapping;
-
- MALI_CHECK_NO_ERROR(mali_mmu_get_table_page(&mali_empty_page_directory, &mapping));
-
- MALI_DEBUG_ASSERT_POINTER( mapping );
-
- err = fill_page(mapping, 0);
- if (_MALI_OSK_ERR_OK != err)
- {
- mali_mmu_release_table_page(mali_empty_page_directory);
- mali_empty_page_directory = MALI_INVALID_PAGE;
- }
- return err;
-}
-
-static void mali_free_empty_page_directory(void)
-{
- if (MALI_INVALID_PAGE != mali_empty_page_directory)
- {
- mali_mmu_release_table_page(mali_empty_page_directory);
- mali_empty_page_directory = MALI_INVALID_PAGE;
- }
-}
-
-static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data)
-{
- int i;
- MALI_DEBUG_ASSERT_POINTER( mapping );
-
- for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++)
- {
- _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data);
- }
- _mali_osk_mem_barrier();
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_allocate_fault_flush_pages(void)
-{
- _mali_osk_errcode_t err;
-
- err = mali_mmu_get_table_page(&mali_page_fault_flush_data_page, &mali_page_fault_flush_data_page_mapping);
- if (_MALI_OSK_ERR_OK == err)
- {
- err = mali_mmu_get_table_page(&mali_page_fault_flush_page_table, &mali_page_fault_flush_page_table_mapping);
- if (_MALI_OSK_ERR_OK == err)
- {
- err = mali_mmu_get_table_page(&mali_page_fault_flush_page_directory, &mali_page_fault_flush_page_directory_mapping);
- if (_MALI_OSK_ERR_OK == err)
- {
- fill_page(mali_page_fault_flush_data_page_mapping, 0);
- fill_page(mali_page_fault_flush_page_table_mapping, mali_page_fault_flush_data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
- fill_page(mali_page_fault_flush_page_directory_mapping, mali_page_fault_flush_page_table | MALI_MMU_FLAGS_PRESENT);
- MALI_SUCCESS;
- }
- mali_mmu_release_table_page(mali_page_fault_flush_page_table);
- mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
- mali_page_fault_flush_page_table_mapping = NULL;
- }
- mali_mmu_release_table_page(mali_page_fault_flush_data_page);
- mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
- mali_page_fault_flush_data_page_mapping = NULL;
- }
- MALI_ERROR(err);
-}
-
-static void mali_free_fault_flush_pages(void)
-{
- if (MALI_INVALID_PAGE != mali_page_fault_flush_page_directory)
- {
- mali_mmu_release_table_page(mali_page_fault_flush_page_directory);
- mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
- }
-
- if (MALI_INVALID_PAGE != mali_page_fault_flush_page_table)
- {
- mali_mmu_release_table_page(mali_page_fault_flush_page_table);
- mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
- }
-
- if (MALI_INVALID_PAGE != mali_page_fault_flush_data_page)
- {
- mali_mmu_release_table_page(mali_page_fault_flush_data_page);
- mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
- }
-}
-
-static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id)
-{
- mali_kernel_memory_mmu * mmu, * temp_mmu;
-
- /* Report the allocators */
- mali_allocation_engine_report_allocators( physical_memory_allocators );
-
- /* allocate the helper pages */
- MALI_CHECK_NO_ERROR( mali_allocate_empty_page_directory() );
- if (_MALI_OSK_ERR_OK != mali_allocate_fault_flush_pages())
- {
- mali_free_empty_page_directory();
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* activate the empty page directory on all MMU's */
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list)
- {
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
- mali_mmu_enable_paging(mmu);
- }
-
- MALI_DEBUG_PRINT(4, ("MMUs activated\n"));
- /* the MMU system is now active */
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info)
-{
- _mali_mem_info * mem_info;
-
- /* Make sure we won't leak any memory. It could also be that it's an
- * uninitialized variable, but the caller should have zeroed the
- * variable. */
- MALI_DEBUG_ASSERT(NULL == info->mem_info);
-
- info->has_mmu = 1;
-
- mem_info = _mali_osk_calloc(1,sizeof(_mali_mem_info));
- MALI_CHECK_NON_NULL( mem_info, _MALI_OSK_ERR_NOMEM );
-
- mem_info->size = 2048UL * 1024UL * 1024UL;
- mem_info->maximum_order_supported = 30;
- mem_info->flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE;
- mem_info->identifier = 0;
-
- info->mem_info = mem_info;
-
- /* all OK */
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource)
-{
- mali_kernel_memory_mmu * mmu;
-
- MALI_DEBUG_PRINT(4, ("MMU '%s' @ (0x%08X - 0x%08X)\n",
- resource->description, resource->base, resource->base + MALI_MMU_REGISTERS_SIZE - 1
- ));
-
- if (NULL != mali_memory_core_mmu_lookup(resource->mmu_id))
- {
- MALI_DEBUG_PRINT(1, ("Duplicate MMU ids found. The id %d is already in use\n", resource->mmu_id));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, MALI_MMU_REGISTERS_SIZE, resource->description))
- {
- /* specified addresses are already in used by another driver / the kernel */
- MALI_DEBUG_PRINT(
- 1, ("Failed to request MMU '%s' register address space at (0x%08X - 0x%08X)\n",
- resource->description, resource->base, resource->base + MALI_MMU_REGISTERS_SIZE - 1
- ));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- mmu = _mali_osk_calloc(1, sizeof(mali_kernel_memory_mmu));
-
- if (NULL == mmu)
- {
- MALI_DEBUG_PRINT(1, ("Failed to allocate memory for handling a MMU unit"));
- _mali_osk_mem_unreqregion(resource->base, MALI_MMU_REGISTERS_SIZE);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- /* basic setup */
- _MALI_OSK_INIT_LIST_HEAD(&mmu->list);
-
- mmu->id = resource->mmu_id;
- mmu->irq_nr = resource->irq;
- mmu->flags = resource->flags;
- mmu->base = resource->base;
- mmu->mapping_size = MALI_MMU_REGISTERS_SIZE;
- mmu->description = resource->description; /* no need to copy */
- _MALI_OSK_INIT_LIST_HEAD(&mmu->callbacks);
- _MALI_OSK_INIT_LIST_HEAD(&mmu->session_link);
- mmu->in_page_fault_handler = 0;
-
- mmu->lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 127-mmu->id);
- if (NULL == mmu->lock)
- {
- MALI_DEBUG_PRINT(1, ("Failed to create mmu lock\n"));
- _mali_osk_mem_unreqregion(mmu->base, mmu->mapping_size);
- _mali_osk_free(mmu);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* map the registers */
- mmu->mapped_registers = _mali_osk_mem_mapioregion( mmu->base, mmu->mapping_size, mmu->description );
- if (NULL == mmu->mapped_registers)
- {
- /* failed to map the registers */
- MALI_DEBUG_PRINT(1, ("Failed to map MMU registers at 0x%08X\n", mmu->base));
- _mali_osk_lock_term(mmu->lock);
- _mali_osk_mem_unreqregion(mmu->base, MALI_MMU_REGISTERS_SIZE);
- _mali_osk_free(mmu);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- MALI_DEBUG_PRINT(4, ("MMU '%s' @ (0x%08X - 0x%08X) mapped to 0x%08X\n",
- resource->description, resource->base, resource->base + MALI_MMU_REGISTERS_SIZE - 1, mmu->mapped_registers
- ));
-
- /* setup MMU interrupt mask */
- /* set all values to known defaults */
- mali_mmu_raw_reset(mmu);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
- /* setup MMU page directory pointer */
- /* The mali_page_directory pointer is guaranteed to be 4kb aligned because we've used get_zeroed_page to accquire it */
- /* convert the kernel virtual address into a physical address and set */
-
- /* add to our list of MMU's */
- _mali_osk_list_addtail(&mmu->list, &mmu_head);
-
- mmu->irq = _mali_osk_irq_init(
- mmu->irq_nr,
- mali_kernel_memory_mmu_interrupt_handler_upper_half,
- mali_kernel_memory_mmu_interrupt_handler_bottom_half,
- (_mali_osk_irq_trigger_t)mali_mmu_probe_irq_trigger,
- (_mali_osk_irq_ack_t)mali_mmu_probe_irq_acknowledge,
- mmu,
- "mali_mmu_irq_handlers"
- );
- if (NULL == mmu->irq)
- {
- _mali_osk_list_del(&mmu->list);
- _mali_osk_lock_term(mmu->lock);
- _mali_osk_mem_unmapioregion( mmu->base, mmu->mapping_size, mmu->mapped_registers );
- _mali_osk_mem_unreqregion(resource->base, MALI_MMU_REGISTERS_SIZE);
- _mali_osk_free(mmu);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* set to a known state */
- mali_mmu_raw_reset(mmu);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
-
- MALI_DEBUG_PRINT(2, ("MMU registered\n"));
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource)
-{
- mali_io_address mapping;
-
- MALI_DEBUG_PRINT(5, ("FPGA framework '%s' @ (0x%08X - 0x%08X)\n",
- resource->description, resource->base, resource->base + sizeof(u32) * 2 - 1
- ));
-
- mapping = _mali_osk_mem_mapioregion(resource->base + 0x1000, sizeof(u32) * 2, "fpga framework");
- if (mapping)
- {
- MALI_DEBUG_CODE(u32 data = )
- _mali_osk_mem_ioread32(mapping, 0);
- MALI_DEBUG_PRINT(2, ("FPGA framwork '%s' @ 0x%08X:\n", resource->description, resource->base));
- MALI_DEBUG_PRINT(2, ("\tBitfile date: %d%02d%02d_%02d%02d\n",
- (data >> 20),
- (data >> 16) & 0xF,
- (data >> 11) & 0x1F,
- (data >> 6) & 0x1F,
- (data >> 0) & 0x3F));
- MALI_DEBUG_CODE(data = )
- _mali_osk_mem_ioread32(mapping, sizeof(u32));
- MALI_DEBUG_PRINT(2, ("\tBitfile SCCS rev: %d\n", data));
-
- _mali_osk_mem_unmapioregion(resource->base + 0x1000, sizeof(u32) *2, mapping);
- }
- else MALI_DEBUG_PRINT(1, ("Failed to access FPGA framwork '%s' @ 0x%08X\n", resource->description, resource->base));
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource)
-{
- mali_physical_memory_allocator * allocator;
- mali_physical_memory_allocator ** next_allocator_list;
-
- u32 alloc_order = resource->alloc_order;
-
- allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description);
- if (NULL == allocator)
- {
- MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n"));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- allocator->alloc_order = alloc_order;
-
- /* link in the allocator: insertion into ordered list
- * resources of the same alloc_order will be Last-in-first */
- next_allocator_list = &physical_memory_allocators;
-
- while ( NULL != *next_allocator_list &&
- (*next_allocator_list)->alloc_order < alloc_order )
- {
- next_allocator_list = &((*next_allocator_list)->next);
- }
-
- allocator->next = (*next_allocator_list);
- (*next_allocator_list) = allocator;
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource)
-{
- mali_physical_memory_allocator * allocator;
- mali_physical_memory_allocator ** next_allocator_list;
- dedicated_memory_info * cleanup_data;
-
- u32 alloc_order = resource->alloc_order;
-
- /* do the lowlevel linux operation first */
-
- /* Request ownership of the memory */
- if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description))
- {
- 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_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 );
-
- if (NULL == allocator)
- {
- MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
- _mali_osk_mem_unreqregion(resource->base, resource->size);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* save lowlevel cleanup info */
- allocator->alloc_order = alloc_order;
-
- cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info));
-
- if (NULL == cleanup_data)
- {
- _mali_osk_mem_unreqregion(resource->base, resource->size);
- allocator->destroy(allocator);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- cleanup_data->base = resource->base;
- cleanup_data->size = resource->size;
-
- cleanup_data->next = mem_region_registrations;
- mem_region_registrations = cleanup_data;
-
- /* link in the allocator: insertion into ordered list
- * resources of the same alloc_order will be Last-in-first */
- next_allocator_list = &physical_memory_allocators;
-
- while ( NULL != *next_allocator_list &&
- (*next_allocator_list)->alloc_order < alloc_order )
- {
- next_allocator_list = &((*next_allocator_list)->next);
- }
-
- allocator->next = (*next_allocator_list);
- (*next_allocator_list) = allocator;
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t mali_kernel_memory_mmu_interrupt_handler_upper_half(void * data)
-{
- mali_kernel_memory_mmu * mmu;
- u32 int_stat;
- mali_core_renderunit *core;
-
- if (mali_benchmark) MALI_SUCCESS;
-
- mmu = (mali_kernel_memory_mmu *)data;
-
- MALI_DEBUG_ASSERT_POINTER(mmu);
-
- /* Pointer to core holding this MMU */
- core = (mali_core_renderunit *)mmu->core;
- if(core && (CORE_OFF == core->state))
- {
- MALI_SUCCESS;
- }
-
-
- /* check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
- int_stat = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_STATUS);
- if (0 == int_stat)
- {
- MALI_ERROR(_MALI_OSK_ERR_FAULT); /* no bits set, we are sharing the IRQ line and someone else caused the interrupt */
- }
-
-
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, 0);
-
- mali_mmu_register_read(mmu, 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_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
- /* reenable it */
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
- }
-
- MALI_SUCCESS;
-}
-
-
-static void mali_kernel_mmu_bus_reset(mali_kernel_memory_mmu * mmu)
-{
-
-#if defined(USING_MALI200)
- int i;
- const int replay_buffer_check_interval = 10; /* must be below 1000 */
- const int replay_buffer_max_number_of_checks = 100;
-#endif
-
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- /* add an extra reference while handling the page fault */
- mmu->usage_count++;
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- MALI_DEBUG_PRINT(4, ("Sending stop bus request to cores\n"));
- /* request to stop the bus, but don't wait for it to actually stop */
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES, (u32)mmu);
-
-#if defined(USING_MALI200)
- /* no new request will come from any of the connected cores from now
- * we must now flush the playback buffer for any requests queued already
- */
-
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- MALI_DEBUG_PRINT(4, ("Switching to the special page fault flush page directory\n"));
- /* don't use the mali_mmu_activate_address_space function here as we can't stall the MMU */
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_page_fault_flush_page_directory);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
- /* resume the MMU */
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
- /* the MMU will now play back all the requests, all going to our special page fault flush data page */
-
- /* just to be safe, check that the playback buffer is empty before continuing */
- if (!mali_benchmark) {
- for (i = 0; i < replay_buffer_max_number_of_checks; i++)
- {
- if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY) break;
- _mali_osk_time_ubusydelay(replay_buffer_check_interval);
- }
-
- MALI_DEBUG_PRINT_IF(1, i == replay_buffer_max_number_of_checks, ("MMU: %s: Failed to flush replay buffer on page fault\n", mmu->description));
- MALI_DEBUG_PRINT(1, ("Replay playback took %ld usec\n", i * replay_buffer_check_interval));
- }
-
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
-#endif
- /* notify all subsystems that the core should be reset once the bus is actually stopped */
- MALI_DEBUG_PRINT(4,("Sending job abort command to subsystems\n"));
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS, (u32)mmu);
-
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- /* reprogram the MMU */
- mali_mmu_raw_reset(mmu);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); /* no session is active, so just activate the empty page directory */
- mali_mmu_enable_paging(mmu);
-
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- /* release the extra address space reference, will schedule */
- mali_memory_core_mmu_release_address_space_reference(mmu);
-
- /* resume normal operation */
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP3_CONTINUE_JOB_HANDLING, (u32)mmu);
- MALI_DEBUG_PRINT(4, ("Page fault handling complete\n"));
-}
-
-static void mali_mmu_raw_reset(mali_kernel_memory_mmu * mmu)
-{
- const int max_loop_count = 100;
- const int delay_in_usecs = 1;
-
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET);
-
- if (!mali_benchmark)
- {
- int i;
- for (i = 0; i < max_loop_count; ++i)
- {
- if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_DTE_ADDR) == 0)
- {
- break;
- }
- _mali_osk_time_ubusydelay(delay_in_usecs);
- }
- MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Reset request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
- }
-}
-
-static void mali_mmu_enable_paging(mali_kernel_memory_mmu * mmu)
-{
- const int max_loop_count = 100;
- const int delay_in_usecs = 1;
-
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
-
- if (!mali_benchmark)
- {
- int i;
- for (i = 0; i < max_loop_count; ++i)
- {
- if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED)
- {
- break;
- }
- _mali_osk_time_ubusydelay(delay_in_usecs);
- }
- MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Enable paging request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
- }
-}
-
-static mali_bool mali_mmu_enable_stall(mali_kernel_memory_mmu * mmu)
-{
- const int max_loop_count = 100;
- const int delay_in_usecs = 999;
- int i;
-
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
-
- if (!mali_benchmark)
- {
- for (i = 0; i < max_loop_count; ++i)
- {
- if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE)
- {
- break;
- }
- _mali_osk_time_ubusydelay(delay_in_usecs);
- }
- MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Enable stall request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
- if (max_loop_count == i)
- {
- return MALI_FALSE;
- }
- }
-
- return MALI_TRUE;
-}
-
-static void mali_mmu_disable_stall(mali_kernel_memory_mmu * mmu)
-{
- const int max_loop_count = 100;
- const int delay_in_usecs = 1;
- int i;
-
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
-
- if (!mali_benchmark)
- {
- for (i = 0; i < max_loop_count; ++i)
- {
- if ((mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) == 0)
- {
- break;
- }
- _mali_osk_time_ubusydelay(delay_in_usecs);
- }
- MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Disable stall request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
- }
-}
-
-void mali_kernel_mmu_reset(void * input_mmu)
-{
- mali_kernel_memory_mmu * mmu;
- MALI_DEBUG_ASSERT_POINTER(input_mmu);
- mmu = (mali_kernel_memory_mmu *)input_mmu;
-
- MALI_DEBUG_PRINT(4, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->description));
-
- if ( 0 != mmu->in_page_fault_handler)
- {
- /* This is possible if the bus can never be stopped for some reason */
- MALI_PRINT_ERROR(("Stopping the Memory bus not possible. Mali reset could not be performed."));
- return;
- }
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- mali_mmu_raw_reset(mmu);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); /* no session is active, so just activate the empty page directory */
- mali_mmu_enable_paging(mmu);
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
-}
-
-void mali_kernel_mmu_force_bus_reset(void * input_mmu)
-{
- mali_kernel_memory_mmu * mmu;
- MALI_DEBUG_ASSERT_POINTER(input_mmu);
- mmu = (mali_kernel_memory_mmu *)input_mmu;
- if ( 0 != mmu->in_page_fault_handler)
- {
- /* This is possible if the bus can never be stopped for some reason */
- MALI_PRINT_ERROR(("Stopping the Memory bus not possible. Mali reset could not be performed."));
- return;
- }
- MALI_DEBUG_PRINT(1, ("Mali MMU: Force_bus_reset.\n"));
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, 0);
- mali_kernel_mmu_bus_reset(mmu);
-}
-
-
-static void mali_kernel_memory_mmu_interrupt_handler_bottom_half(void * data)
-{
- mali_kernel_memory_mmu * mmu;
- u32 raw, fault_address, status;
- mali_core_renderunit *core;
-
- MALI_DEBUG_PRINT(1, ("mali_kernel_memory_mmu_interrupt_handler_bottom_half\n"));
- if (NULL == data)
- {
- MALI_PRINT_ERROR(("MMU IRQ work queue: NULL argument"));
- return; /* Error */
- }
- mmu = (mali_kernel_memory_mmu*)data;
-
- MALI_DEBUG_PRINT(4, ("Locking subsystems\n"));
- /* lock all subsystems */
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP0_LOCK_SUBSYSTEM, (u32)mmu);
-
- /* Pointer to core holding this MMU */
- core = (mali_core_renderunit *)mmu->core;
-
- if(CORE_OFF == core->state)
- {
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu);
- return;
- }
-
- raw = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_RAWSTAT);
- status = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS);
-
- if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) && (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) )
- {
- MALI_DEBUG_PRINT(1, ("MMU: Page fault bottom half: No Irq found.\n"));
- MALI_DEBUG_PRINT(4, ("Unlocking subsystems"));
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu);
- return;
- }
-
- mmu->in_page_fault_handler = 1;
-
- fault_address = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
- MALI_PRINT(("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->description)
- );
-
- if (NULL == mmu->active_session)
- {
- MALI_PRINT(("Spurious memory access detected from MMU %s\n", mmu->description));
- }
- else
- {
- MALI_PRINT(("Active page directory at 0x%08X\n", mmu->active_session->page_directory));
- MALI_PRINT(("Info from page table for VA 0x%x:\n", (void*)fault_address));
- MALI_PRINT(("DTE entry: PTE at 0x%x marked as %s\n",
- (void*)(_mali_osk_mem_ioread32(mmu->active_session->page_directory_mapped,
- MALI_MMU_PDE_ENTRY(fault_address) * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK),
- _mali_osk_mem_ioread32(mmu->active_session->page_directory_mapped,
- MALI_MMU_PDE_ENTRY(fault_address) * sizeof(u32)) & MALI_MMU_FLAGS_PRESENT ? "present" : "not present"
- ));
-
- if (_mali_osk_mem_ioread32(mmu->active_session->page_directory_mapped, MALI_MMU_PDE_ENTRY(fault_address) * sizeof(u32)) & MALI_MMU_FLAGS_PRESENT)
- {
- mali_io_address pte;
- u32 data;
- pte = mmu->active_session->page_entries_mapped[MALI_MMU_PDE_ENTRY(fault_address)];
- data = _mali_osk_mem_ioread32(pte, MALI_MMU_PTE_ENTRY(fault_address) * sizeof(u32));
- MALI_PRINT(("PTE entry: Page at 0x%x, %s %s %s\n",
- (void*)(data & ~MALI_MMU_FLAGS_MASK),
- data & MALI_MMU_FLAGS_PRESENT ? "present" : "not present",
- data & MALI_MMU_FLAGS_READ_PERMISSION ? "readable" : "",
- data & MALI_MMU_FLAGS_WRITE_PERMISSION ? "writable" : ""
- ));
- }
- else
- {
- MALI_PRINT(("PTE entry: Not present\n"));
- }
- }
-
-
- mali_kernel_mmu_bus_reset(mmu);
-
- mmu->in_page_fault_handler = 0;
-
- /* unlock all subsystems */
- MALI_DEBUG_PRINT(4, ("Unlocking subsystems"));
- _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu);
-
-}
-
-
-static u32 mali_mmu_register_read(mali_kernel_memory_mmu * unit, mali_mmu_register reg)
-{
- u32 val;
-
- if (mali_benchmark) return 0;
-
- val = _mali_osk_mem_ioread32(unit->mapped_registers, (u32)reg * sizeof(u32));
-
- MALI_DEBUG_PRINT(6, ("mali_mmu_register_read addr:0x%04X val:0x%08x\n", (u32)reg * sizeof(u32),val));
-
- return val;
-}
-
-static void mali_mmu_register_write(mali_kernel_memory_mmu * unit, mali_mmu_register reg, u32 val)
-{
- if (mali_benchmark) return;
-
- MALI_DEBUG_PRINT(6, ("mali_mmu_register_write addr:0x%04X val:0x%08x\n", (u32)reg * sizeof(u32), val));
-
- _mali_osk_mem_iowrite32(unit->mapped_registers, (u32)reg * sizeof(u32), val);
-}
-
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
-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;
- u32 nr_blocks;
- u32 i;
- ump_dd_physical_block * ump_blocks;
- ump_mem_allocation *ret_allocation;
-
- MALI_DEBUG_ASSERT_POINTER(ctx);
- MALI_DEBUG_ASSERT_POINTER(engine);
- MALI_DEBUG_ASSERT_POINTER(descriptor);
- MALI_DEBUG_ASSERT_POINTER(alloc_info);
-
- ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) );
- if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
-
- ump_mem = (ump_dd_handle)ctx;
-
- MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n"));
-
- nr_blocks = ump_dd_phys_block_count_get(ump_mem);
-
- MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks));
-
- if (nr_blocks == 0)
- {
- MALI_DEBUG_PRINT(1, ("No block count\n"));
- _mali_osk_free( ret_allocation );
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
-
- ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks );
- if ( NULL==ump_blocks )
- {
- _mali_osk_free( ret_allocation );
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
-
- if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks))
- {
- _mali_osk_free(ump_blocks);
- _mali_osk_free( ret_allocation );
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
-
- /* Store away the initial offset for unmapping purposes */
- ret_allocation->initial_offset = *offset;
-
- for(i=0; i<nr_blocks; ++i)
- {
- MALI_DEBUG_PRINT(4, ("Mapping in 0x%08x size %d\n", ump_blocks[i].addr , ump_blocks[i].size));
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[i].addr , 0, ump_blocks[i].size ))
- {
- u32 size_allocated = *offset - ret_allocation->initial_offset;
- MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
-
- /* unmap all previous blocks (if any) */
- mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
-
- _mali_osk_free(ump_blocks);
- _mali_osk_free(ret_allocation);
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
- *offset += ump_blocks[i].size;
- }
-
- if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
- {
- /* Map in an extra virtual guard page at the end of the VMA */
- MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE ))
- {
- u32 size_allocated = *offset - ret_allocation->initial_offset;
- MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
-
- /* unmap all previous blocks (if any) */
- mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
-
- _mali_osk_free(ump_blocks);
- _mali_osk_free(ret_allocation);
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
- *offset += _MALI_OSK_MALI_PAGE_SIZE;
- }
-
- _mali_osk_free( ump_blocks );
-
- ret_allocation->engine = engine;
- ret_allocation->descriptor = descriptor;
- ret_allocation->ump_mem = ump_mem;
- ret_allocation->size_allocated = *offset - ret_allocation->initial_offset;
-
- alloc_info->ctx = NULL;
- alloc_info->handle = ret_allocation;
- alloc_info->next = NULL;
- alloc_info->release = ump_memory_release;
-
- return MALI_MEM_ALLOC_FINISHED;
-}
-
-static void ump_memory_release(void * ctx, void * handle)
-{
- ump_dd_handle ump_mem;
- ump_mem_allocation *allocation;
-
- allocation = (ump_mem_allocation *)handle;
-
- MALI_DEBUG_ASSERT_POINTER( allocation );
-
- ump_mem = allocation->ump_mem;
-
- MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem);
-
- /* At present, this is a no-op. But, it allows the mali_address_manager to
- * do unmapping of a subrange in future. */
- mali_allocation_engine_unmap_physical( allocation->engine,
- allocation->descriptor,
- allocation->initial_offset,
- allocation->size_allocated,
- (_mali_osk_mem_mapregion_flags_t)0
- );
- _mali_osk_free( allocation );
-
-
- ump_dd_reference_release(ump_mem) ;
- return;
-}
-
-_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args )
-{
- ump_dd_handle ump_mem;
- mali_physical_memory_allocator external_memory_allocator;
- memory_session * session_data;
- mali_memory_allocation * descriptor;
- int md;
-
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- /* check arguments */
- /* NULL might be a valid Mali address */
- if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
-
- /* size must be a multiple of the system page size */
- if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
-
- MALI_DEBUG_PRINT(3,
- ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n",
- args->secure_id, args->mali_address, args->size));
-
- ump_mem = ump_dd_handle_create_from_secure_id( (int)args->secure_id ) ;
-
- if ( UMP_DD_HANDLE_INVALID==ump_mem ) MALI_ERROR(_MALI_OSK_ERR_FAULT);
-
- descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
- if (NULL == descriptor)
- {
- ump_dd_reference_release(ump_mem);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- descriptor->size = args->size;
- descriptor->mapping = NULL;
- descriptor->mali_address = args->mali_address;
- descriptor->mali_addr_mapping_info = (void*)session_data;
- descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
- descriptor->lock = session_data->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 );
-
- if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
- {
- ump_dd_reference_release(ump_mem);
- _mali_osk_free(descriptor);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- external_memory_allocator.allocate = ump_memory_commit;
- external_memory_allocator.allocate_page_table_block = NULL;
- external_memory_allocator.ctx = ump_mem;
- external_memory_allocator.name = "UMP Memory";
- external_memory_allocator.next = NULL;
-
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
- {
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
- ump_dd_reference_release(ump_mem);
- _mali_osk_free(descriptor);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- args->cookie = md;
-
- MALI_DEBUG_PRINT(5,("Returning from UMP attach\n"));
-
- /* All OK */
- MALI_SUCCESS;
-}
-
-
-_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args )
-{
- mali_memory_allocation * descriptor;
- memory_session * session_data;
-
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor))
- {
- MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
-
- _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW );
-
- mali_allocation_engine_release_memory(memory_engine, descriptor);
-
- _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW );
-
- _mali_osk_free(descriptor);
-
- MALI_SUCCESS;
-
-}
-#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */
-
-
-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)
-{
- u32 * data;
- external_mem_allocation * ret_allocation;
-
- MALI_DEBUG_ASSERT_POINTER(ctx);
- MALI_DEBUG_ASSERT_POINTER(engine);
- MALI_DEBUG_ASSERT_POINTER(descriptor);
- MALI_DEBUG_ASSERT_POINTER(alloc_info);
-
- ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) );
-
- if ( NULL == ret_allocation )
- {
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
-
- data = (u32*)ctx;
-
- ret_allocation->engine = engine;
- ret_allocation->descriptor = descriptor;
- ret_allocation->initial_offset = *offset;
-
- alloc_info->ctx = NULL;
- alloc_info->handle = ret_allocation;
- alloc_info->next = NULL;
- alloc_info->release = external_memory_release;
-
- MALI_DEBUG_PRINT(3, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1]));
-
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1]))
- {
- MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
- _mali_osk_free(ret_allocation);
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
- *offset += data[1];
-
- if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
- {
- /* Map in an extra virtual guard page at the end of the VMA */
- MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE))
- {
- u32 size_allocated = *offset - ret_allocation->initial_offset;
- MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
-
- /* unmap what we previously mapped */
- mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
- _mali_osk_free(ret_allocation);
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
- *offset += _MALI_OSK_MALI_PAGE_SIZE;
- }
-
- ret_allocation->size = *offset - ret_allocation->initial_offset;
-
- return MALI_MEM_ALLOC_FINISHED;
-}
-
-static void external_memory_release(void * ctx, void * handle)
-{
- external_mem_allocation * allocation;
-
- allocation = (external_mem_allocation *) handle;
- MALI_DEBUG_ASSERT_POINTER( allocation );
-
- /* At present, this is a no-op. But, it allows the mali_address_manager to
- * do unmapping of a subrange in future. */
-
- mali_allocation_engine_unmap_physical( allocation->engine,
- allocation->descriptor,
- allocation->initial_offset,
- allocation->size,
- (_mali_osk_mem_mapregion_flags_t)0
- );
-
- _mali_osk_free( allocation );
-
- return;
-}
-
-_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
-{
- mali_physical_memory_allocator external_memory_allocator;
- memory_session * session_data;
- u32 info[2];
- mali_memory_allocation * descriptor;
- int md;
-
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- external_memory_allocator.allocate = external_memory_commit;
- external_memory_allocator.allocate_page_table_block = NULL;
- external_memory_allocator.ctx = &info[0];
- external_memory_allocator.name = "External Memory";
- external_memory_allocator.next = NULL;
-
- /* check arguments */
- /* NULL might be a valid Mali address */
- if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
-
- /* size must be a multiple of the system page size */
- if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
-
- MALI_DEBUG_PRINT(3,
- ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n",
- (void*)args->phys_addr,
- (void*)(args->phys_addr + args->size -1),
- (void*)args->mali_address)
- );
-
- /* Validate the mali physical range */
- MALI_CHECK_NO_ERROR( mali_kernel_core_validate_mali_phys_range( args->phys_addr, args->size ) );
-
- info[0] = args->phys_addr;
- info[1] = args->size;
-
- descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
- if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
-
- descriptor->size = args->size;
- descriptor->mapping = NULL;
- descriptor->mali_address = args->mali_address;
- descriptor->mali_addr_mapping_info = (void*)session_data;
- descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
- descriptor->lock = session_data->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 );
-
- if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
- {
- _mali_osk_free(descriptor);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
- {
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
- _mali_osk_free(descriptor);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- args->cookie = md;
-
- MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n"));
-
- /* All OK */
- MALI_SUCCESS;
-}
-
-
-_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
-{
- mali_memory_allocation * descriptor;
- memory_session * session_data;
-
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
- MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
-
- if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor))
- {
- MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
-
- _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW );
-
- mali_allocation_engine_release_memory(memory_engine, descriptor);
-
- _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW );
-
- _mali_osk_free(descriptor);
-
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args )
-{
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
-
- args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */
- args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args )
-{
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_mmu_page_table_cache_create(void)
-{
- page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 110);
- MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT );
- _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial);
- _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full);
- MALI_SUCCESS;
-}
-
-void mali_mmu_page_table_cache_destroy(void)
-{
- mali_mmu_page_table_allocation * alloc, *temp;
-
- _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
- {
- MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count));
- _mali_osk_list_del(&alloc->list);
- alloc->pages.release(&alloc->pages);
- _mali_osk_free(alloc->usage_map);
- _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_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list)
- {
- MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count));
- _mali_osk_list_del(&alloc->list);
- alloc->pages.release(&alloc->pages);
- _mali_osk_free(alloc->usage_map);
- _mali_osk_free(alloc);
- }
-
- _mali_osk_lock_term(page_table_cache.lock);
-}
-
-_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping)
-{
- _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
-
- if (0 == _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);
- MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number));
- _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map);
- alloc->usage_count++;
- if (alloc->num_pages == alloc->usage_count)
- {
- /* full, move alloc to full list*/
- _mali_osk_list_move(&alloc->list, &page_table_cache.full);
- }
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
-
- *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base;
- *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping);
- MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
- MALI_SUCCESS;
- }
- else
- {
- mali_mmu_page_table_allocation * alloc;
- /* no free pages, allocate a new one */
-
- alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation));
- if (NULL == alloc)
- {
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
- *table_page = MALI_INVALID_PAGE;
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- _MALI_OSK_INIT_LIST_HEAD(&alloc->list);
-
- if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators))
- {
- MALI_DEBUG_PRINT(1, ("No more memory for page tables\n"));
- _mali_osk_free(alloc);
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
- *table_page = MALI_INVALID_PAGE;
- *mapping = NULL;
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- /* create the usage map */
- alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE;
- alloc->usage_count = 1;
- MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages));
- alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long));
- if (NULL == alloc->usage_map)
- {
- MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n"));
- alloc->pages.release(&alloc->pages);
- _mali_osk_free(alloc);
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
- *table_page = MALI_INVALID_PAGE;
- *mapping = NULL;
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
- /* clear memory allocation */
- fill_page(alloc->pages.mapping, 0);
-
- _mali_osk_set_nonatomic_bit(0, alloc->usage_map);
-
- if (alloc->num_pages > 1)
- {
- _mali_osk_list_add(&alloc->list, &page_table_cache.partial);
- }
- else
- {
- _mali_osk_list_add(&alloc->list, &page_table_cache.full);
- }
-
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
- *table_page = alloc->pages.phys_base; /* return the first page */
- *mapping = alloc->pages.mapping; /* Mapping for first page */
- MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
- MALI_SUCCESS;
- }
-}
-
-void mali_mmu_release_table_page(u32 pa)
-{
- mali_mmu_page_table_allocation * alloc, * temp_alloc;
-
- MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa));
-
- MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa));
-
- _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
-
- /* find the entry this address belongs to */
- /* first check the partial list */
- _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
- {
- u32 start = alloc->pages.phys_base;
- u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
- if (pa >= start && pa <= last)
- {
- MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map));
- _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
- alloc->usage_count--;
-
- _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
-
- if (0 == alloc->usage_count)
- {
- /* empty, release whole page alloc */
- _mali_osk_list_del(&alloc->list);
- alloc->pages.release(&alloc->pages);
- _mali_osk_free(alloc->usage_map);
- _mali_osk_free(alloc);
- }
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
- MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa));
- return;
- }
- }
-
- /* the check the full list */
- _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list)
- {
- u32 start = alloc->pages.phys_base;
- u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
- if (pa >= start && pa <= last)
- {
- _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
- alloc->usage_count--;
-
- _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
-
-
- if (0 == alloc->usage_count)
- {
- /* empty, release whole page alloc */
- _mali_osk_list_del(&alloc->list);
- alloc->pages.release(&alloc->pages);
- _mali_osk_free(alloc->usage_map);
- _mali_osk_free(alloc);
- }
- else
- {
- /* transfer to partial list */
- _mali_osk_list_move(&alloc->list, &page_table_cache.partial);
- }
-
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
- MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa));
- return;
- }
- }
-
- MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa));
-
- _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
-}
-
-void* mali_memory_core_mmu_lookup(u32 id)
-{
- mali_kernel_memory_mmu * mmu, * temp_mmu;
-
- /* find an MMU with a matching id */
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list)
- {
- if (id == mmu->id) return mmu;
- }
-
- /* not found */
- return NULL;
-}
-
-void mali_memory_core_mmu_owner(void *core, void *mmu_ptr)
-{
- mali_kernel_memory_mmu *mmu;
-
- MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
- MALI_DEBUG_ASSERT_POINTER(core);
-
- mmu = (mali_kernel_memory_mmu *)mmu_ptr;
- mmu->core = core;
-}
-
-void mali_mmu_activate_address_space(mali_kernel_memory_mmu * mmu, u32 page_directory)
-{
- mali_mmu_enable_stall(mmu); /* this might fail, but changing the DTE address and ZAP should work anyway... */
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
- mali_mmu_disable_stall(mmu);
-}
-
-_mali_osk_errcode_t mali_memory_core_mmu_activate_page_table(void* mmu_ptr, struct mali_session_data * mali_session_data, void(*callback)(void*), void * callback_argument)
-{
- memory_session * requested_memory_session;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
- mali_kernel_memory_mmu * mmu;
-
- MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
- MALI_DEBUG_ASSERT_POINTER(mali_session_data);
-
- mmu = (mali_kernel_memory_mmu *)mmu_ptr;
-
- MALI_DEBUG_PRINT(4, ("Asked to activate page table for session 0x%x on MMU %s\n", mali_session_data, mmu->description));
- requested_memory_session = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
- MALI_DEBUG_PRINT(5, ("Session 0x%x looked up as using memory session 0x%x\n", mali_session_data, requested_memory_session));
-
- MALI_DEBUG_ASSERT_POINTER(requested_memory_session);
-
- MALI_DEBUG_PRINT(7, ("Taking locks\n"));
-
- _mali_osk_lock_wait(requested_memory_session->lock, _MALI_OSK_LOCKMODE_RW);
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- if (0 == mmu->usage_count)
- {
- /* no session currently active, activate the requested session */
- MALI_DEBUG_ASSERT(NULL == mmu->active_session);
- mmu->active_session = requested_memory_session;
- mmu->usage_count = 1;
- MALI_DEBUG_PRINT(4, ("MMU idle, activating page directory 0x%08X on MMU %s\n", requested_memory_session->page_directory, mmu->description));
- mali_mmu_activate_address_space(mmu, requested_memory_session->page_directory);
- {
- /* Insert mmu into the right place in the active_mmus list so that
- * it is still sorted. The list must be sorted by ID so we can get
- * the mutexes in the right order in
- * _mali_ukk_mem_munmap_internal().
- */
- _mali_osk_list_t *entry;
- for (entry = requested_memory_session->active_mmus.next;
- entry != &requested_memory_session->active_mmus;
- entry = entry->next)
- {
- mali_kernel_memory_mmu *temp = _MALI_OSK_LIST_ENTRY(entry, mali_kernel_memory_mmu, session_link);
- if (mmu->id < temp->id)
- break;
- }
- /* If we broke out, then 'entry' points to the list node of the
- * first mmu with a greater ID; otherwise, it points to
- * active_mmus. We want to add *before* this node.
- */
- _mali_osk_list_addtail(&mmu->session_link, entry);
- }
- err = _MALI_OSK_ERR_OK;
- }
-
- /* Allow two cores to run in parallel if they come from the same session */
- else if (
- (mmu->in_page_fault_handler == 0) &&
- (requested_memory_session == mmu->active_session ) &&
- (0==(MALI_MMU_DISALLOW_PARALLELL_WORK_OF_MALI_CORES & mmu->flags))
- )
- {
- /* nested activation detected, just update the reference count */
- MALI_DEBUG_PRINT(4, ("Nested activation detected, %d previous activations found\n", mmu->usage_count));
- mmu->usage_count++;
- err = _MALI_OSK_ERR_OK;
- }
-
- else if (NULL != callback)
- {
- /* can't activate right now, notify caller on idle via callback */
- mali_kernel_memory_mmu_idle_callback * callback_object, * temp_callback_object;
- int found = 0;
-
- MALI_DEBUG_PRINT(3, ("The MMU is busy and is using a different address space, callback given\n"));
- /* check for existing registration */
- _MALI_OSK_LIST_FOREACHENTRY(callback_object, temp_callback_object, &mmu->callbacks, mali_kernel_memory_mmu_idle_callback, link)
- {
- if (callback_object->callback == callback)
- {
- found = 1;
- break;
- }
- }
-
- if (found)
- {
- MALI_DEBUG_PRINT(5, ("Duplicate callback registration found, ignoring\n"));
- /* callback already registered */
- err = _MALI_OSK_ERR_BUSY;
- }
- else
- {
- MALI_DEBUG_PRINT(5,("New callback, registering\n"));
- /* register the new callback */
- callback_object = _mali_osk_malloc(sizeof(mali_kernel_memory_mmu_idle_callback));
- if (NULL != callback_object)
- {
- MALI_DEBUG_PRINT(7,("Callback struct setup\n"));
- callback_object->callback = callback;
- callback_object->callback_argument = callback_argument;
- _mali_osk_list_addtail(&callback_object->link, &mmu->callbacks);
- err = _MALI_OSK_ERR_BUSY;
- }
- }
- }
-
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- _mali_osk_lock_signal(requested_memory_session->lock, _MALI_OSK_LOCKMODE_RW);
-
- MALI_ERROR(err);
-}
-
-void mali_memory_core_mmu_release_address_space_reference(void* mmu_ptr)
-{
- mali_kernel_memory_mmu_idle_callback * callback_object, * temp;
- mali_kernel_memory_mmu * mmu;
- memory_session * session;
-
- _MALI_OSK_LIST_HEAD(callbacks);
-
- MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
- mmu = (mali_kernel_memory_mmu *)mmu_ptr;
-
- session = mmu->active_session;
-
- /* support that we handle spurious page faults */
- if (NULL != session)
- {
- _mali_osk_lock_wait(session->lock, _MALI_OSK_LOCKMODE_RW);
- }
-
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- MALI_DEBUG_PRINT(4, ("Deactivation of address space on MMU %s, %d references exists\n", mmu->description, mmu->usage_count));
- MALI_DEBUG_ASSERT(0 != mmu->usage_count);
- mmu->usage_count--;
- if (0 != mmu->usage_count)
- {
- MALI_DEBUG_PRINT(4, ("MMU still in use by this address space, %d references still exists\n", mmu->usage_count));
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- /* support that we handle spurious page faults */
- if (NULL != session)
- {
- _mali_osk_lock_signal(session->lock, _MALI_OSK_LOCKMODE_RW);
- }
- return;
- }
-
- MALI_DEBUG_PRINT(4, ("Activating the empty page directory on %s\n", mmu->description));
-
- /* last reference gone, deactivate current address space */
- mali_mmu_activate_address_space(mmu, mali_empty_page_directory);
-
- /* unlink from session */
- _mali_osk_list_delinit(&mmu->session_link);
- /* remove the active session pointer */
- mmu->active_session = NULL;
-
- /* Notify all registered callbacks.
- * We have to be clever here:
- * We must call the callbacks with the spinlock unlocked and
- * the callback list emptied to allow them to re-register.
- * So we make a copy of the list, clears the list and then later call the callbacks on the local copy
- */
- /* copy list */
- _MALI_OSK_INIT_LIST_HEAD(&callbacks);
- _mali_osk_list_splice(&mmu->callbacks, &callbacks);
- /* clear the original, allowing new registrations during the callback */
- _MALI_OSK_INIT_LIST_HEAD(&mmu->callbacks);
-
- /* end of mmu manipulation, so safe to unlock */
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- /* then finally remove the (possible) session lock, supporting that no session was active (spurious page fault handling) */
- if (NULL != session)
- {
- _mali_osk_lock_signal(session->lock, _MALI_OSK_LOCKMODE_RW);
- }
-
- _MALI_OSK_LIST_FOREACHENTRY(callback_object, temp, &callbacks, mali_kernel_memory_mmu_idle_callback, link)
- {
- MALI_DEBUG_ASSERT_POINTER(callback_object->callback);
- (callback_object->callback)(callback_object->callback_argument);
- _mali_osk_list_del(&callback_object->link);
- _mali_osk_free(callback_object);
- }
-}
-
-void mali_memory_core_mmu_unregister_callback(void* mmu_ptr, void(*callback)(void*))
-{
- mali_kernel_memory_mmu_idle_callback * callback_object, * temp_callback_object;
- mali_kernel_memory_mmu * mmu;
- MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
-
- MALI_DEBUG_ASSERT_POINTER(callback);
- MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
-
- mmu = (mali_kernel_memory_mmu *)mmu_ptr;
-
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- _MALI_OSK_LIST_FOREACHENTRY(callback_object, temp_callback_object, &mmu->callbacks, mali_kernel_memory_mmu_idle_callback, link)
- {
- MALI_DEBUG_ASSERT_POINTER(callback_object->callback);
- if (callback_object->callback == callback)
- {
- _mali_osk_list_del(&callback_object->link);
- _mali_osk_free(callback_object);
- break;
- }
- }
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-}
-
-static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor)
-{
- /* allocate page tables, if needed */
- int i;
- const int first_pde_idx = MALI_MMU_PDE_ENTRY(descriptor->mali_address);
- int last_pde_idx;
- memory_session * session_data;
-#if defined USING_MALI400_L2_CACHE
- int has_active_mmus = 0;
- int page_dir_updated = 0;
-#endif
-
-
- if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
- {
- last_pde_idx = MALI_MMU_PDE_ENTRY(descriptor->mali_address + _MALI_OSK_MALI_PAGE_SIZE + descriptor->size - 1);
- }
- else
- {
- last_pde_idx = MALI_MMU_PDE_ENTRY(descriptor->mali_address + descriptor->size - 1);
- }
-
- session_data = (memory_session*)descriptor->mali_addr_mapping_info;
- MALI_DEBUG_ASSERT_POINTER(session_data);
-
- MALI_DEBUG_PRINT(4, ("allocating page tables for Mali virtual address space 0x%08X to 0x%08X\n", descriptor->mali_address, descriptor->mali_address + descriptor->size - 1));
-
-#if defined USING_MALI400_L2_CACHE
- if (0 == _mali_osk_list_empty(&session_data->active_mmus))
- {
- /*
- * We have active MMUs, so we are probably in the process of alocating more memory for a suspended GP job (PLBU heap)
- * From Mali-400 MP r1p0, MMU page directory/tables are also cached by the Mali L2 cache, thus we need to invalidate the page directory
- * from the L2 cache if we add new page directory entries (PDEs) to the page directory.
- * We only need to do this when we have an active MMU, because we otherwise invalidate the entire Mali L2 cache before at job start
- */
- has_active_mmus = 1;
- }
-#endif
-
- for (i = first_pde_idx; i <= last_pde_idx; i++)
- {
- if ( 0 == (_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32)) & MALI_MMU_FLAGS_PRESENT) )
- {
- u32 pte_phys;
- mali_io_address pte_mapped;
- _mali_osk_errcode_t err;
-
- /* allocate a new page table */
- MALI_DEBUG_ASSERT(0 == session_data->page_entries_usage_count[i]);
- MALI_DEBUG_ASSERT(NULL == session_data->page_entries_mapped[i]);
-
- err = mali_mmu_get_table_page(&pte_phys, &pte_mapped);
- if (_MALI_OSK_ERR_OK == err)
- {
- session_data->page_entries_mapped[i] = pte_mapped;
- MALI_DEBUG_ASSERT_POINTER( session_data->page_entries_mapped[i] );
-
- _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), pte_phys | MALI_MMU_FLAGS_PRESENT); /* mark page table as present */
-
- /* update usage count */
- session_data->page_entries_usage_count[i]++;
-#if defined USING_MALI400_L2_CACHE
- page_dir_updated = 1;
-#endif
- continue; /* continue loop */
- }
-
- MALI_DEBUG_PRINT(1, ("Page table alloc failed\n"));
- break; /* abort loop, failed to allocate one or more page tables */
- }
- else
- {
- session_data->page_entries_usage_count[i]++;
- }
- }
-
- if (i <= last_pde_idx)
- {
- /* one or more pages could not be allocated, release reference count for the ones we added one for */
- /* adjust for the one which caused the for loop to be aborted */
- i--;
-
- while (i >= first_pde_idx)
- {
- MALI_DEBUG_ASSERT(0 != session_data->page_entries_usage_count[i]);
- session_data->page_entries_usage_count[i]--;
- if (0 == session_data->page_entries_usage_count[i])
- {
- /* last reference removed */
- mali_mmu_release_table_page(MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32))));
- session_data->page_entries_mapped[i] = NULL;
- _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), 0); /* mark as not present in the page directory */
- }
- i--;
- }
-
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
-
-#if defined USING_MALI400_L2_CACHE
- if (1 == has_active_mmus && 1 == page_dir_updated)
- {
- /*
- * We have updated the page directory and have an active MMU using it, so invalidate it in the Mali L2 cache.
- */
- mali_kernel_l2_cache_invalidate_page(session_data->page_directory);
- }
-#endif
-
- /* all OK */
- MALI_SUCCESS;
-}
-
-static void mali_address_manager_release(mali_memory_allocation * descriptor)
-{
- int first_pde_idx;
- int last_pde_idx;
- memory_session * session_data;
- u32 mali_address;
- u32 mali_address_end;
- u32 left;
- int i;
-#if defined USING_MALI400_L2_CACHE
- int has_active_mmus = 0;
- int page_dir_updated = 0;
-#endif
-
- MALI_DEBUG_ASSERT_POINTER(descriptor);
- session_data = (memory_session*)descriptor->mali_addr_mapping_info;
- MALI_DEBUG_ASSERT_POINTER(session_data);
- MALI_DEBUG_ASSERT_POINTER(session_data->page_directory_mapped);
-
- mali_address = descriptor->mali_address;
- mali_address_end = descriptor->mali_address + descriptor->size;
- left = descriptor->size;
-
- first_pde_idx = MALI_MMU_PDE_ENTRY(mali_address);
- last_pde_idx = MALI_MMU_PDE_ENTRY(mali_address_end - 1);
-
- MALI_DEBUG_PRINT(3, ("Zapping Mali MMU table for address 0x%08X size 0x%08X\n", mali_address, left));
- MALI_DEBUG_PRINT(4, ("Zapping PDE %d through %d\n", first_pde_idx, last_pde_idx));
-
-#if defined USING_MALI400_L2_CACHE
- if (0 == _mali_osk_list_empty(&session_data->active_mmus))
- {
- /*
- * From Mali-400 MP r1p0, MMU page directory/tables are also cached by the Mali L2 cache, thus we need to invalidate the page tables
- * from the L2 cache to ensure that the memory is unmapped.
- * We only need to do this when we have an active MMU, because we otherwise invalidate the entire Mali L2 cache before at job start
- */
- has_active_mmus = 1;
- }
-#endif
-
-
- for (i = first_pde_idx; i <= last_pde_idx; i++)
- {
- int size_inside_pte = left < 0x400000 ? left : 0x400000;
- const int first_pte_idx = MALI_MMU_PTE_ENTRY(mali_address);
- int last_pte_idx = MALI_MMU_PTE_ENTRY(mali_address + size_inside_pte - 1);
-
- if (last_pte_idx < first_pte_idx)
- {
- /* The last_pte_idx is into the next PTE, crop it to fit into this */
- last_pte_idx = 1023; /* 1024 PTE entries, so 1023 is the last one */
- size_inside_pte = MALI_MMU_ADDRESS(i + 1, 0) - mali_address;
- }
-
- MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped[i]);
- MALI_DEBUG_ASSERT(0 != session_data->page_entries_usage_count[i]);
- MALI_DEBUG_PRINT(4, ("PDE %d: zapping entries %d through %d, address 0x%08X, size 0x%08X, left 0x%08X (page table at 0x%08X)\n",
- i, first_pte_idx, last_pte_idx, mali_address, size_inside_pte, left,
- MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32)))));
-
- session_data->page_entries_usage_count[i]--;
-
- if (0 == session_data->page_entries_usage_count[i])
- {
- MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n"));
- /* last reference removed, no need to zero out each PTE */
- mali_mmu_release_table_page(MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32))));
- session_data->page_entries_mapped[i] = NULL;
- _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), 0); /* mark as not present in the page directory */
-#if defined USING_MALI400_L2_CACHE
- page_dir_updated = 1;
-#endif
- }
- else
- {
- int j;
-
- for (j = first_pte_idx; j <= last_pte_idx; j++)
- {
- _mali_osk_mem_iowrite32(session_data->page_entries_mapped[i], j * sizeof(u32), 0);
- }
-
-#if defined USING_MALI400_L2_CACHE
- if (1 == has_active_mmus)
- {
- /* Invalidate the page we've just modified */
- mali_kernel_l2_cache_invalidate_page( _mali_osk_mem_ioread32(session_data->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
- }
-#endif
- }
- left -= size_inside_pte;
- mali_address += size_inside_pte;
- }
-
-#if defined USING_MALI400_L2_CACHE
- if ((1 == page_dir_updated) && (1== has_active_mmus))
- {
- /* The page directory was also updated */
- mali_kernel_l2_cache_invalidate_page(session_data->page_directory);
- }
-#endif
-}
-
-static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size)
-{
- memory_session * session_data;
- u32 mali_address;
- u32 mali_address_end;
- u32 current_phys_addr;
-#if defined USING_MALI400_L2_CACHE
- int has_active_mmus = 0;
-#endif
-
- MALI_DEBUG_ASSERT_POINTER(descriptor);
-
- MALI_DEBUG_ASSERT_POINTER( phys_addr );
-
- current_phys_addr = *phys_addr;
-
- session_data = (memory_session*)descriptor->mali_addr_mapping_info;
- MALI_DEBUG_ASSERT_POINTER(session_data);
-
- mali_address = descriptor->mali_address + offset;
- mali_address_end = descriptor->mali_address + offset + size;
-
-#if defined USING_MALI400_L2_CACHE
- if (0 == _mali_osk_list_empty(&session_data->active_mmus))
- {
- /*
- * We have active MMUs, so we are probably in the process of alocating more memory for a suspended GP job (PLBU heap)
- * From Mali-400 MP r1p0, MMU page directory/tables are also cached by the Mali L2 cache, thus we need to invalidate the page tables
- * from the L2 cache when we have allocated more heap memory.
- * We only need to do this when we have an active MMU, because we otherwise invalidate the entire Mali L2 cache before at job start
- */
- has_active_mmus = 1;
- }
-#endif
-
- MALI_DEBUG_PRINT(6, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", current_phys_addr, mali_address, size));
-
- MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped);
-
- for ( ; mali_address < mali_address_end; mali_address += MALI_MMU_PAGE_SIZE, current_phys_addr += MALI_MMU_PAGE_SIZE)
- {
- MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]);
- _mali_osk_mem_iowrite32_relaxed(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), current_phys_addr | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
- }
- _mali_osk_write_mem_barrier();
-
-#if defined USING_MALI400_L2_CACHE
- if (1 == has_active_mmus)
- {
- int i;
- const int first_pde_idx = MALI_MMU_PDE_ENTRY(mali_address);
- const int last_pde_idx = MALI_MMU_PDE_ENTRY(mali_address_end - 1);
-
- /*
- * Invalidate the updated page table(s), incase they have been used for something
- * else since last job start (invalidation of entire Mali L2 cache)
- */
- for (i = first_pde_idx; i <= last_pde_idx; i++)
- {
- mali_kernel_l2_cache_invalidate_page( _mali_osk_mem_ioread32(session_data->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
- }
- }
-#endif
-
- MALI_SUCCESS;
-}
-
-/* This handler registered to mali_mmap for MMU builds */
-_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args )
-{
- struct mali_session_data * mali_session_data;
- mali_memory_allocation * descriptor;
- memory_session * session_data;
-
- /* validate input */
- if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
-
- /* Unpack arguments */
- mali_session_data = (struct mali_session_data *)args->ctx;
-
- if (NULL == mali_session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: mali_session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
-
- MALI_DEBUG_ASSERT( mali_subsystem_memory_id >= 0 );
-
- session_data = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
- /* validate input */
- if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); }
-
- descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) );
- if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); }
-
- descriptor->size = args->size;
- descriptor->mali_address = args->phys_addr;
- descriptor->mali_addr_mapping_info = (void*)session_data;
-
- descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */
- descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE;
- descriptor->lock = session_data->lock;
- _mali_osk_list_init( &descriptor->list );
-
- _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head))
- {
- mali_kernel_memory_mmu * mmu, * temp_mmu;
-
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
- {
- /* no need to lock the MMU as we own it already */
- MALI_DEBUG_PRINT(5, ("Zapping the cache of mmu %s as it's using the page table we have updated\n", mmu->description));
-
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- mali_mmu_enable_stall(mmu); /* this might fail, but ZAP should work anyway... */
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
- mali_mmu_disable_stall(mmu);
-
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- }
-
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
-
- /* All ok, write out any information generated from this call */
- args->mapping = descriptor->mapping;
- args->cookie = (u32)descriptor;
-
- MALI_DEBUG_PRINT(7, ("MMAP OK\n"));
- /* All done */
- MALI_SUCCESS;
- }
- else
- {
- _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
- /* OOM, but not a fatal error */
- MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n"));
- _mali_osk_free(descriptor);
- /* Linux will free the CPU address allocation, userspace client the Mali address allocation */
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-}
-
-static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args )
-{
- memory_session * session_data;
- mali_kernel_memory_mmu * mmu, * temp_mmu;
- mali_memory_allocation * descriptor;
-
- descriptor = (mali_memory_allocation *)args->cookie;
- MALI_DEBUG_ASSERT_POINTER(descriptor);
-
- /** @note args->context unused; we use the memory_session from the cookie */
- /* args->mapping and args->size are also discarded. They are only necessary
- for certain do_munmap implementations. However, they could be used to check the
- descriptor at this point. */
-
- session_data = (memory_session*)descriptor->mali_addr_mapping_info;
- MALI_DEBUG_ASSERT_POINTER(session_data);
-
- /* Stall the MMU(s) which is using the address space we're operating on.
- * Note that active_mmus must be sorted in order of ID to avoid a mutex
- * ordering violation.
- */
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
- {
- u32 status;
- status = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS);
- if ( MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE == (status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) {
- MALI_DEBUG_PRINT(2, ("Stopped stall attempt for mmu with id %d since it is in page fault mode.\n", mmu->id));
- continue;
- }
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
-
- /*
- * If we're unable to stall, then make sure we tell our caller that,
- * the caller should then release the session lock for a while,
- * then this function again.
- * This function will fail if we're in page fault mode, and to get
- * out of page fault mode, the page fault handler must be able to
- * take the session lock.
- */
- if (!mali_mmu_enable_stall(mmu))
- {
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- return _MALI_OSK_ERR_BUSY;
- }
-
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- }
-
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
- {
- _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- }
-
- /* This function also removes the memory from the session's memory list */
- mali_allocation_engine_release_memory(memory_engine, descriptor);
- _mali_osk_free(descriptor);
-
- /* any L2 maintenance was done during mali_allocation_engine_release_memory */
- /* the session is locked, so the active mmu list should be the same */
- /* zap the TLB and resume operation */
- _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
- {
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
- mali_mmu_disable_stall(mmu);
-
- _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
- }
-
- return _MALI_OSK_ERR_OK;
-}
-
-/* Handler for unmapping memory for MMU builds */
-_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args )
-{
- mali_memory_allocation * descriptor;
- _mali_osk_lock_t *descriptor_lock;
- _mali_osk_errcode_t err;
-
- descriptor = (mali_memory_allocation *)args->cookie;
- MALI_DEBUG_ASSERT_POINTER(descriptor);
-
- /** @note args->context unused; we use the memory_session from the cookie */
- /* args->mapping and args->size are also discarded. They are only necessary
- for certain do_munmap implementations. However, they could be used to check the
- descriptor at this point. */
-
- MALI_DEBUG_ASSERT_POINTER((memory_session*)descriptor->mali_addr_mapping_info);
-
- descriptor_lock = descriptor->lock; /* should point to the session data lock... */
-
- err = _MALI_OSK_ERR_BUSY;
- while (err == _MALI_OSK_ERR_BUSY)
- {
- if (descriptor_lock)
- {
- _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
- }
-
- err = _mali_ukk_mem_munmap_internal( args );
-
- if (descriptor_lock)
- {
- _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
- }
-
- if (err == _MALI_OSK_ERR_BUSY)
- {
- /*
- * Reason for this;
- * We where unable to stall the MMU, probably because we are in page fault handling.
- * Sleep for a while with the session lock released, then try again.
- * Abnormal termination of programs with running Mali jobs is a normal reason for this.
- */
- _mali_osk_time_ubusydelay(10);
- }
- }
-
- return err;
-}
-
-/* Is called when the rendercore wants the mmu to give an interrupt */
-static void mali_mmu_probe_irq_trigger(mali_kernel_memory_mmu * mmu)
-{
- MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_trigger\n"));
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
-}
-
-/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
-static _mali_osk_errcode_t mali_mmu_probe_irq_acknowledge(mali_kernel_memory_mmu * mmu)
-{
- u32 int_stat;
-
- int_stat = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_STATUS);
-
- MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
- if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
- {
- MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
- }
- else MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
-
- if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
- {
- MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
- mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
- }
- else MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
-
- if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
- (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR))
- {
- MALI_SUCCESS;
- }
-
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
-}
-
-struct dump_info
-{
- u32 buffer_left;
- u32 register_writes_size;
- u32 page_table_dump_size;
- u32 *buffer;
-};
-
-static _mali_osk_errcode_t writereg(u32 where, u32 what, const char * comment, struct dump_info * info, int dump_to_serial)
-{
- if (dump_to_serial) MALI_DEBUG_PRINT(1, ("writereg %08X %08X # %s\n", where, what, comment));
-
- if (NULL != info)
- {
- info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */
-
- if (NULL != info->buffer)
- {
- /* check that we have enough space */
- if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
-
- *info->buffer = where;
- info->buffer++;
-
- *info->buffer = what;
- info->buffer++;
-
- info->buffer_left -= sizeof(u32)*2;
- }
- }
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info, int dump_to_serial)
-{
- if (dump_to_serial)
- {
- int i;
- for (i = 0; i < 256; i++)
- {
- MALI_DEBUG_PRINT(1, ("%08X: %08X %08X %08X %08X\n", phys_addr + 16*i, _mali_osk_mem_ioread32(page, (i*4 + 0) * sizeof(u32)),
- _mali_osk_mem_ioread32(page, (i*4 + 1) * sizeof(u32)),
- _mali_osk_mem_ioread32(page, (i*4 + 2) * sizeof(u32)),
- _mali_osk_mem_ioread32(page, (i*4 + 3) * sizeof(u32))));
-
- }
- }
-
- if (NULL != info)
- {
- /* 4096 for the page and 4 bytes for the address */
- const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4;
- const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE;
- const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4;
-
- info->page_table_dump_size += dump_size_in_bytes;
-
- if (NULL != info->buffer)
- {
- if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
-
- *info->buffer = phys_addr;
- info->buffer++;
-
- _mali_osk_memcpy(info->buffer, page, page_size_in_bytes);
- info->buffer += page_size_in_elements;
-
- info->buffer_left -= dump_size_in_bytes;
- }
- }
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t dump_mmu_page_table(memory_session * session_data, struct dump_info * info)
-{
- MALI_DEBUG_ASSERT_POINTER(session_data);
- MALI_DEBUG_ASSERT_POINTER(info);
-
- if (NULL != session_data->page_directory_mapped)
- {
- int i;
-
- MALI_CHECK_NO_ERROR(
- dump_page(session_data->page_directory_mapped, session_data->page_directory, info, 0)
- );
-
- for (i = 0; i < 1024; i++)
- {
- if (NULL != session_data->page_entries_mapped[i])
- {
- MALI_CHECK_NO_ERROR(
- dump_page(session_data->page_entries_mapped[i], _mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info, 0)
- );
- }
- }
- }
-
- MALI_SUCCESS;
-}
-
-static _mali_osk_errcode_t dump_mmu_registers(memory_session * session_data, struct dump_info * info)
-{
- MALI_CHECK_NO_ERROR(writereg(0x00000000, session_data->page_directory, "set the page directory address", info, 0));
- MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info, 0));
- MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info, 0));
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args )
-{
- struct dump_info info = { 0, 0, 0, NULL };
- memory_session * session_data;
-
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
-
- MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data, &info));
- MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data, &info));
- args->size = info.register_writes_size + info.page_table_dump_size;
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args )
-{
- struct dump_info info = { 0, 0, 0, NULL };
- memory_session * session_data;
-
- MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS);
-
- session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
-
- info.buffer_left = args->size;
- info.buffer = args->buffer;
-
- args->register_writes = info.buffer;
- MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data, &info));
-
- args->page_table_dump = info.buffer;
- MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data, &info));
-
- args->register_writes_size = info.register_writes_size;
- args->page_table_dump_size = info.page_table_dump_size;
-
- MALI_SUCCESS;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_get_big_block( _mali_uk_get_big_block_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-/**
- * Stub function to satisfy UDD interface exclusion requirement.
- * This is because the Base code compiles in \b both MMU and non-MMU calls,
- * so both sets must be declared (but the 'unused' set may be stub)
- */
-_mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args )
-{
- MALI_IGNORE( args );
- return _MALI_OSK_ERR_FAULT;
-}
-
-u32 _mali_ukk_report_memory_usage(void)
-{
- return mali_allocation_engine_memory_usage(physical_memory_allocators);
-}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h b/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h
deleted file mode 100644
index 6a110d0..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h
+++ /dev/null
@@ -1,75 +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 __MALI_KERNEL_MEM_MMU_H__
-#define __MALI_KERNEL_MEM_MMU_H__
-
-#include "mali_kernel_session_manager.h"
-
-/**
- * Lookup a MMU core by ID.
- * @param id ID of the MMU to find
- * @return NULL if ID not found or valid, non-NULL if a core was found.
- */
-void* mali_memory_core_mmu_lookup(u32 id);
-
-/**
- * Set the core pointer of MMU to core owner of MMU
- *
- * @param core Core holding this MMU
- * @param mmu_ptr The MMU whose core pointer needs set to core holding the MMU
- *
- */
-void mali_memory_core_mmu_owner(void *core, void *mmu_ptr);
-
-/**
- * Activate a user session with its address space on the given MMU.
- * If the session can't be activated due to that the MMU is busy and
- * a callback pointer is given, the callback will be called once the MMU becomes idle.
- * If the same callback pointer is registered multiple time it will only be called once.
- * Nested activations are supported.
- * Each call must be matched by a call to @see mali_memory_core_mmu_release_address_space_reference
- *
- * @param mmu The MMU to activate the address space on
- * @param mali_session_data The user session object which address space to activate
- * @param callback Pointer to the function to call when the MMU becomes idle
- * @param callback_arg Argument given to the callback
- * @return 0 if the address space was activated, -EBUSY if the MMU was busy, -EFAULT in all other cases.
- */
-int mali_memory_core_mmu_activate_page_table(void* mmu_ptr, struct mali_session_data * mali_session_data, void(*callback)(void*), void * callback_argument);
-
-/**
- * Release a reference to the current active address space.
- * Once the last reference is released any callback(s) registered will be called before the function returns
- *
- * @note Caution must be shown calling this function with locks held due to that callback can be called
- * @param mmu The mmu to release a reference to the active address space of
- */
-void mali_memory_core_mmu_release_address_space_reference(void* mmu);
-
-/**
- * Soft reset of MMU - needed after power up
- *
- * @param mmu_ptr The MMU pointer registered with the relevant core
- */
-void mali_kernel_mmu_reset(void * mmu_ptr);
-
-void mali_kernel_mmu_force_bus_reset(void * mmu_ptr);
-
-/**
- * Unregister a previously registered callback.
- * @param mmu The MMU to unregister the callback on
- * @param callback The function to unregister
- */
-void mali_memory_core_mmu_unregister_callback(void* mmu, void(*callback)(void*));
-
-
-
-#endif /* __MALI_KERNEL_MEM_MMU_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c
index 324fcab..7462a6d 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -65,19 +65,19 @@ mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u3
info->num_pages_allocated = 0;
info->cpu_usage_adjust = cpu_usage_adjust;
- info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, 106);
- if (NULL != info->mutex)
- {
- allocator->allocate = os_allocator_allocate;
- allocator->allocate_page_table_block = os_allocator_allocate_page_table_block;
- allocator->destroy = os_allocator_destroy;
+ info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO);
+ if (NULL != info->mutex)
+ {
+ allocator->allocate = os_allocator_allocate;
+ allocator->allocate_page_table_block = os_allocator_allocate_page_table_block;
+ allocator->destroy = os_allocator_destroy;
allocator->stat = os_allocator_stat;
- allocator->ctx = info;
+ allocator->ctx = info;
allocator->name = name;
- return allocator;
- }
- _mali_osk_free(info);
+ return allocator;
+ }
+ _mali_osk_free(info);
}
_mali_osk_free(allocator);
}
@@ -132,7 +132,7 @@ static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, m
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*)));
- while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max) && _mali_osk_mem_check_allocated(os_mem_max_usage))
+ 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);
if ( _MALI_OSK_ERR_OK != err)
@@ -243,7 +243,7 @@ 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)
{
- int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */
+ int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 11 */
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_memory_engine.c b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c
index ff105a4..1377560 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -161,13 +161,28 @@ _mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engin
void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor)
{
+ mali_allocation_engine_release_pt1_mali_pagetables_unmap(mem_engine, descriptor);
+ mali_allocation_engine_release_pt2_physical_memory_free(mem_engine, descriptor);
+}
+
+void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor)
+{
memory_engine * engine = (memory_engine*)mem_engine;
- mali_physical_memory_allocation * active_allocation_tracker;
MALI_DEBUG_ASSERT_POINTER(engine);
MALI_DEBUG_ASSERT_POINTER(descriptor);
- /* Determine whether we need to remove this from a tracking list */
+ /* Calling: mali_address_manager_release() */
+ /* This function is allowed to be called several times, and it only does the release on the first call. */
+ engine->mali_address->release(descriptor);
+}
+
+void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor)
+{
+ memory_engine * engine = (memory_engine*)mem_engine;
+ mali_physical_memory_allocation * active_allocation_tracker;
+
+ /* Remove this from a tracking list in session_data->memory_head */
if ( ! _mali_osk_list_empty( &descriptor->list ) )
{
_mali_osk_list_del( &descriptor->list );
@@ -175,8 +190,6 @@ void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, ma
MALI_DEBUG_CODE( descriptor->list.next = descriptor->list.prev = NULL; )
}
- engine->mali_address->release(descriptor);
-
active_allocation_tracker = &descriptor->physical_allocation;
while (NULL != active_allocation_tracker)
{
@@ -199,7 +212,6 @@ void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, ma
}
}
-
_mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size)
{
_mali_osk_errcode_t err;
@@ -244,7 +256,7 @@ _mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine m
}
}
- MALI_DEBUG_PRINT(4, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X to CPUVA 0x%08X\n", phys, size, offset, (u32)(descriptor->mapping) + offset));
+ MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X to CPUVA 0x%08X\n", phys, size, offset, (u32)(descriptor->mapping) + offset));
/* Mali address manager must use the physical address - no point in asking
* it to allocate another one for us */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h
index 0173c78..cda74c3 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -136,6 +136,9 @@ void mali_allocation_engine_destroy(mali_allocation_engine engine);
int mali_allocation_engine_allocate_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_provider, _mali_osk_list_t *tracking_list );
void mali_allocation_engine_release_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor);
+void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine engine, mali_memory_allocation * descriptor);
+void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine engine, mali_memory_allocation * descriptor);
+
int mali_allocation_engine_map_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size);
void mali_allocation_engine_unmap_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags);
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_pp.h b/drivers/media/video/samsung/mali/common/mali_kernel_pp.h
deleted file mode 100644
index 8cf7bf7..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_pp.h
+++ /dev/null
@@ -1,21 +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 __MALI_KERNEL_PP_H__
-#define __MALI_KERNEL_PP_H__
-
-extern struct mali_kernel_subsystem mali_subsystem_mali200;
-
-#if USING_MALI_PMM
-_mali_osk_errcode_t malipp_signal_power_up( u32 core_num, mali_bool queue_only );
-_mali_osk_errcode_t malipp_signal_power_down( u32 core_num, mali_bool immediate_only );
-#endif
-
-#endif /* __MALI_KERNEL_PP_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.c b/drivers/media/video/samsung/mali/common/mali_kernel_profiling.c
deleted file mode 100644
index ca04b5f..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.c
+++ /dev/null
@@ -1,364 +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.
- */
-
-#include "mali_kernel_common.h"
-#include "mali_osk.h"
-#include "mali_osk_mali.h"
-#include "mali_ukk.h"
-#include "mali_timestamp.h"
-#include "mali_kernel_profiling.h"
-#include "mali_linux_trace.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;
-static mali_bool mali_profiling_default_enable = MALI_FALSE;
-
-_mali_osk_errcode_t _mali_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_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0 );
- 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_profiling_default_enable = MALI_TRUE; /* save this so user space can query this on their startup */
- if (_MALI_OSK_ERR_OK != _mali_profiling_start(&limit))
- {
- return _MALI_OSK_ERR_FAULT;
- }
- }
-
- return _MALI_OSK_ERR_OK;
-}
-
-void _mali_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_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_profiling_add_counter(u32 event_id, u32 data0)
-{
-#if MALI_TRACEPOINTS_ENABLED
- _mali_osk_profiling_add_counter(event_id, data0);
-#endif
-}
-
-inline _mali_osk_errcode_t _mali_profiling_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;
-
-#if MALI_TRACEPOINTS_ENABLED
- _mali_osk_profiling_add_event(event_id, data0);
-#endif
-
- if (prof_state != MALI_PROFILING_STATE_RUNNING || cur_index >= profile_entry_count)
- {
- /*
- * Not in recording mode, or buffer is full
- * Decrement index again, and early out
- */
- _mali_osk_atomic_dec(&profile_insert_index);
- return _MALI_OSK_ERR_FAULT;
- }
-
- 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;
-
- _mali_osk_atomic_inc(&profile_entries_written);
-
- return _MALI_OSK_ERR_OK;
-}
-
-#if MALI_TRACEPOINTS_ENABLED
-/*
- * The following code uses a bunch of magic numbers taken from the userspace
- * side of the DDK; they are re-used here verbatim. They are taken from the
- * file mali_instrumented_counter_types.h.
- */
-#define MALI_GLES_COUNTER_OFFSET 1000
-#define MALI_VG_COUNTER_OFFSET 2000
-#define MALI_EGL_COUNTER_OFFSET 3000
-#define MALI_SHARED_COUNTER_OFFSET 4000
-
-/* These offsets are derived from the gator driver; see gator_events_mali.c. */
-#define GATOR_EGL_COUNTER_OFFSET 17
-#define GATOR_GLES_COUNTER_OFFSET 18
-
-_mali_osk_errcode_t _mali_ukk_transfer_sw_counters(_mali_uk_sw_counters_s *args)
-{
- /* Convert the DDK counter ID to what gator expects */
- unsigned int gator_counter_value = 0;
-
- _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
-
- if (args->id >= MALI_EGL_COUNTER_OFFSET && args->id <= MALI_SHARED_COUNTER_OFFSET)
- {
- gator_counter_value = (args->id - MALI_EGL_COUNTER_OFFSET) + GATOR_EGL_COUNTER_OFFSET;
- }
- else if (args->id >= MALI_GLES_COUNTER_OFFSET && args->id <= MALI_VG_COUNTER_OFFSET)
- {
- gator_counter_value = (args->id - MALI_GLES_COUNTER_OFFSET) + GATOR_GLES_COUNTER_OFFSET;
- }
- else
- {
- /* Pass it straight through; gator will ignore it anyway. */
- gator_counter_value = args->id;
- }
-
- trace_mali_sw_counter(gator_counter_value, args->value);
-
- _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
-
- return _MALI_OSK_ERR_OK;
-}
-#endif
-
-inline _mali_osk_errcode_t _mali_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);
-
- return _MALI_OSK_ERR_OK;
-}
-
-inline u32 _mali_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);
- }
- _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
-
- return retval;
-}
-
-inline _mali_osk_errcode_t _mali_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
-{
- _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 */
- }
-
- if (index >= _mali_osk_atomic_read(&profile_entries_written))
- {
- _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];
-
- _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
- return _MALI_OSK_ERR_OK;
-}
-
-inline _mali_osk_errcode_t _mali_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_profiling_is_recording(void)
-{
- return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE;
-}
-
-mali_bool _mali_profiling_have_recording(void)
-{
- return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE;
-}
-
-void _mali_profiling_set_default_enable_state(mali_bool enable)
-{
- mali_profiling_default_enable = enable;
-}
-
-mali_bool _mali_profiling_get_default_enable_state(void)
-{
- return mali_profiling_default_enable;
-}
-
-_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args)
-{
- return _mali_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 */
- return _mali_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]);
-}
-
-_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args)
-{
- return _mali_profiling_stop(&args->count);
-}
-
-_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args)
-{
- return _mali_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_profiling_clear();
-}
-
-_mali_osk_errcode_t _mali_ukk_profiling_get_config(_mali_uk_profiling_get_config_s *args)
-{
- args->enable_events = mali_profiling_default_enable;
- return _MALI_OSK_ERR_OK;
-}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c b/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c
deleted file mode 100644
index cfc5ec1..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c
+++ /dev/null
@@ -1,2031 +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.
- */
-
-#include "mali_kernel_common.h"
-#include "mali_kernel_core.h"
-#include "mali_osk.h"
-#include "mali_kernel_subsystem.h"
-#include "mali_kernel_rendercore.h"
-#include "mali_osk_list.h"
-#if MALI_GPU_UTILIZATION
-#include "mali_kernel_utilization.h"
-#endif
-#if MALI_TIMELINE_PROFILING_ENABLED
-#include "mali_kernel_profiling.h"
-#endif
-#if USING_MMU
-#include "mali_kernel_mem_mmu.h"
-#endif /* USING_MMU */
-#if defined USING_MALI400_L2_CACHE
-#include "mali_kernel_l2_cache.h"
-#endif /* USING_MALI400_L2_CACHE */
-
-#define HANG_CHECK_MSECS_MIN 100
-#define HANG_CHECK_MSECS_MAX 2000 /* 2 secs */
-#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */
-
-#define WATCHDOG_MSECS_MIN (10*HANG_CHECK_MSECS_MIN)
-#define WATCHDOG_MSECS_MAX 3600000 /* 1 hour */
-#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 secs */
-
-/* max value that will be converted from jiffies to micro seconds and written to job->render_time_usecs */
-#define JOB_MAX_JIFFIES 100000
-
-int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT;
-int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
-
-#if MALI_TIMELINE_PROFILING_ENABLED
-int mali_boot_profiling = 0;
-#endif
-
-#ifdef MALI_REBOOTNOTIFIER
-extern _mali_osk_atomic_t mali_shutdown_state;
-#endif
-
-/* Subsystem entrypoints: */
-static _mali_osk_errcode_t rendercore_subsystem_startup(mali_kernel_subsystem_identifier id);
-static void rendercore_subsystem_terminate(mali_kernel_subsystem_identifier id);
-#if USING_MMU
-static void rendercore_subsystem_broadcast_notification(mali_core_notification_message message, u32 data);
-#endif
-
-
-static void mali_core_subsystem_cleanup_all_renderunits(struct mali_core_subsystem* subsys);
-static void mali_core_subsystem_move_core_set_idle(struct mali_core_renderunit *core);
-
-static mali_core_session * mali_core_subsystem_get_waiting_session(mali_core_subsystem *subsystem);
-static mali_core_job * mali_core_subsystem_release_session_get_job(mali_core_subsystem *subsystem, mali_core_session * session);
-
-static void find_and_abort(mali_core_session* session, u32 abort_id);
-
-static void mali_core_job_start_on_core(mali_core_job *job, mali_core_renderunit *core);
-#if USING_MMU
-static void mali_core_subsystem_callback_schedule_wrapper(void* sub);
-#endif
-static void mali_core_subsystem_schedule(mali_core_subsystem*subsystem);
-static void mali_core_renderunit_detach_job_from_core(mali_core_renderunit* core, mali_subsystem_reschedule_option reschedule, mali_subsystem_job_end_code end_status);
-
-static void mali_core_renderunit_irq_handler_remove(struct mali_core_renderunit *core);
-
-static _mali_osk_errcode_t mali_core_irq_handler_upper_half (void * data);
-static void mali_core_irq_handler_bottom_half ( void *data );
-
-#if USING_MMU
-static void lock_subsystem(struct mali_core_subsystem * subsys);
-static void unlock_subsystem(struct mali_core_subsystem * subsys);
-#endif
-
-
-/**
- * This will be one of the subsystems in the array of subsystems:
- * static struct mali_kernel_subsystem * subsystems[];
- * found in file: mali_kernel_core.c
- *
- * This subsystem is necessary for operations common to all rendercore
- * subsystems. For example, mali_subsystem_mali200 and mali_subsystem_gp2 may
- * share a mutex when RENDERCORES_USE_GLOBAL_MUTEX is non-zero.
- */
-struct mali_kernel_subsystem mali_subsystem_rendercore=
-{
- rendercore_subsystem_startup, /* startup */
- NULL, /*rendercore_subsystem_terminate,*/ /* shutdown */
- NULL, /* load_complete */
- NULL, /* system_info_fill */
- NULL, /* session_begin */
- NULL, /* session_end */
-#if USING_MMU
- rendercore_subsystem_broadcast_notification, /* broadcast_notification */
-#else
- NULL,
-#endif
-#if MALI_STATE_TRACKING
- NULL, /* dump_state */
-#endif
-} ;
-
-static _mali_osk_lock_t *rendercores_global_mutex = NULL;
-static u32 rendercores_global_mutex_is_held = 0;
-static u32 rendercores_global_mutex_owner = 0;
-
-/** The 'dummy' rendercore subsystem to allow global subsystem mutex to be
- * locked for all subsystems that extend the ''rendercore'' */
-static mali_core_subsystem rendercore_dummy_subsystem = {0,};
-
-/*
- * Rendercore Subsystem functions.
- *
- * These are exposed by mali_subsystem_rendercore
- */
-
-/**
- * @brief Initialize the Rendercore subsystem.
- *
- * This must be called before any other subsystem that extends the
- * ''rendercore'' may be initialized. For example, this must be called before
- * the following functions:
- * - mali200_subsystem_startup(), from mali_subsystem_mali200
- * - maligp_subsystem_startup(), from mali_subsystem_gp2
- *
- * @note This function is separate from mali_core_subsystem_init(). They
- * are related, in that mali_core_subsystem_init() may use the structures
- * initialized by rendercore_subsystem_startup()
- */
-static _mali_osk_errcode_t rendercore_subsystem_startup(mali_kernel_subsystem_identifier id)
-{
- rendercores_global_mutex_is_held = 0;
- rendercores_global_mutex = _mali_osk_lock_init(
- (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED),
- 0, 129);
-
- if (NULL == rendercores_global_mutex)
- {
- MALI_PRINT_ERROR(("Failed: _mali_osk_lock_init\n")) ;
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- rendercore_dummy_subsystem.name = "Rendercore Global Subsystem"; /* On the constant pool, do not free */
- rendercore_dummy_subsystem.magic_nr = SUBSYSTEM_MAGIC_NR; /* To please the Subsystem Mutex code */
-
-#if MALI_GPU_UTILIZATION
- if (mali_utilization_init() != _MALI_OSK_ERR_OK)
- {
- _mali_osk_lock_term(rendercores_global_mutex);
- rendercores_global_mutex = NULL;
- MALI_PRINT_ERROR(("Failed: mali_utilization_init\n")) ;
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#endif
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- if (_mali_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE) != _MALI_OSK_ERR_OK)
- {
- /* No biggie if we wheren't able to initialize the profiling */
- MALI_PRINT_ERROR(("Rendercore: Failed to initialize profiling, feature will be unavailable\n")) ;
- }
-#endif
-
- MALI_DEBUG_PRINT(2, ("Rendercore: subsystem global mutex initialized\n")) ;
- MALI_SUCCESS;
-}
-
-/**
- * @brief Terminate the Rendercore subsystem.
- *
- * This must only be called \b after any other subsystem that extends the
- * ''rendercore'' has been terminated. For example, this must be called \b after
- * the following functions:
- * - mali200_subsystem_terminate(), from mali_subsystem_mali200
- * - maligp_subsystem_terminate(), from mali_subsystem_gp2
- *
- * @note This function is separate from mali_core_subsystem_cleanup(), though,
- * the subsystems that extend ''rendercore'' must still call
- * mali_core_subsystem_cleanup() when they terminate.
- */
-static void rendercore_subsystem_terminate(mali_kernel_subsystem_identifier id)
-{
- /* Catch double-terminate */
- MALI_DEBUG_ASSERT_POINTER( rendercores_global_mutex );
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_term();
-#endif
-
-#if MALI_GPU_UTILIZATION
- mali_utilization_term();
-#endif
-
- rendercore_dummy_subsystem.name = NULL; /* The original string was on the constant pool, do not free */
- rendercore_dummy_subsystem.magic_nr = 0;
-
- /* ASSERT that no-one's holding this */
- MALI_DEBUG_PRINT_ASSERT( 0 == rendercores_global_mutex_is_held,
- ("Rendercores' Global Mutex was held at termination time. Have the subsystems that extend ''rendercore'' been terminated?\n") );
-
- _mali_osk_lock_term( rendercores_global_mutex );
- rendercores_global_mutex = NULL;
-
- MALI_DEBUG_PRINT(2, ("Rendercore: subsystem global mutex terminated\n")) ;
-}
-
-
-#if USING_MMU
-/**
- * @brief Handle certain Rendercore subsystem broadcast notifications
- *
- * When RENDERCORES_USE_GLOBAL_MUTEX is non-zero, this handles the following messages:
- * - MMU_KILL_STEP0_LOCK_SUBSYSTEM
- * - MMU_KILL_STEP4_UNLOCK_SUBSYSTEM
- *
- * The purpose is to manage the Rendercode Global Mutex, which cannot be
- * managed by any system that extends the ''rendercore''.
- *
- * All other messages must be handled by mali_core_subsystem_broadcast_notification()
- *
- *
- * When RENDERCORES_USE_GLOBAL_MUTEX is 0, this function does nothing.
- * Instead, the subsystem that extends the ''rendercore' \b must handle its
- * own mutexes - refer to mali_core_subsystem_broadcast_notification().
- *
- * Used currently only for signalling when MMU has a pagefault
- */
-static void rendercore_subsystem_broadcast_notification(mali_core_notification_message message, u32 data)
-{
- switch(message)
- {
- case MMU_KILL_STEP0_LOCK_SUBSYSTEM:
- lock_subsystem( &rendercore_dummy_subsystem );
- break;
- case MMU_KILL_STEP4_UNLOCK_SUBSYSTEM:
- unlock_subsystem( &rendercore_dummy_subsystem );
- break;
-
- case MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES:
- /** FALLTHROUGH */
- case MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS:
- /** FALLTHROUGH */
- case MMU_KILL_STEP3_CONTINUE_JOB_HANDLING:
- break;
-
- default:
- MALI_PRINT_ERROR(("Illegal message: 0x%x, data: 0x%x\n", (u32)message, data));
- break;
- }
-
-}
-#endif
-
-/*
- * Functions inherited by the subsystems that extend the ''rendercore''.
- */
-
-void mali_core_renderunit_timeout_function_hang_detection(void *arg)
-{
- mali_bool action = MALI_FALSE;
- mali_core_renderunit * core;
-
- core = (mali_core_renderunit *) arg;
- if( !core ) return;
-
- /* if NOT idle OR NOT powered off OR has TIMED_OUT */
- if ( !((CORE_WATCHDOG_TIMEOUT == core->state ) || (CORE_IDLE== core->state) || (CORE_OFF == core->state)) )
- {
- core->state = CORE_HANG_CHECK_TIMEOUT;
- action = MALI_TRUE;
- }
-
- if(action) _mali_osk_irq_schedulework(core->irq);
-}
-
-
-void mali_core_renderunit_timeout_function(void *arg)
-{
- mali_core_renderunit * core;
- mali_bool is_watchdog;
-
- core = (mali_core_renderunit *)arg;
- if( !core ) return;
-
- is_watchdog = MALI_TRUE;
- if (mali_benchmark)
- {
- /* poll based core */
- mali_core_job *job;
- job = core->current_job;
- if ( (NULL != job) &&
- (0 != _mali_osk_time_after(job->watchdog_jiffies,_mali_osk_time_tickcount()))
- )
- {
- core->state = CORE_POLL;
- is_watchdog = MALI_FALSE;
- }
- }
-
- if (is_watchdog)
- {
- MALI_DEBUG_PRINT(3, ("SW-Watchdog timeout: Core:%s\n", core->description));
- core->state = CORE_WATCHDOG_TIMEOUT;
- }
-
- _mali_osk_irq_schedulework(core->irq);
-}
-
-/* Used by external renderunit_create<> function */
-_mali_osk_errcode_t mali_core_renderunit_init(mali_core_renderunit * core)
-{
- MALI_DEBUG_PRINT(5, ("Core: renderunit_init: Core:%s\n", core->description));
-
- _MALI_OSK_INIT_LIST_HEAD(&core->list) ;
- core->timer = _mali_osk_timer_init();
- if (NULL == core->timer)
- {
- MALI_PRINT_ERROR(("Core: renderunit_init: Core:%s -- cannot init timer\n", core->description));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- _mali_osk_timer_setcallback(core->timer, mali_core_renderunit_timeout_function, (void *)core);
-
- core->timer_hang_detection = _mali_osk_timer_init();
- if (NULL == core->timer_hang_detection)
- {
- _mali_osk_timer_term(core->timer);
- MALI_PRINT_ERROR(("Core: renderunit_init: Core:%s -- cannot init hang detection timer\n", core->description));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- _mali_osk_timer_setcallback(core->timer_hang_detection, mali_core_renderunit_timeout_function_hang_detection, (void *)core);
-
-#if USING_MALI_PMM
- /* Init no pending power downs */
- core->pend_power_down = MALI_FALSE;
-
- /* Register the core with the PMM - which powers it up */
- if (_MALI_OSK_ERR_OK != malipmm_core_register( core->pmm_id ))
- {
- _mali_osk_timer_term(core->timer);
- _mali_osk_timer_term(core->timer_hang_detection);
- MALI_PRINT_ERROR(("Core: renderunit_init: Core:%s -- cannot register with PMM\n", core->description));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#endif /* USING_MALI_PMM */
-
- core->error_recovery = MALI_FALSE;
- core->in_detach_function = MALI_FALSE;
- core->state = CORE_IDLE;
- core->current_job = NULL;
- core->magic_nr = CORE_MAGIC_NR;
-#if USING_MMU
- core->mmu = NULL;
-#endif /* USING_MMU */
-
- MALI_SUCCESS;
-}
-
-void mali_core_renderunit_term(mali_core_renderunit * core)
-{
- MALI_DEBUG_PRINT(5, ("Core: renderunit_term: Core:%s\n", core->description));
-
- if (NULL != core->timer)
- {
- _mali_osk_timer_term(core->timer);
- core->timer = NULL;
- }
- if (NULL != core->timer_hang_detection)
- {
- _mali_osk_timer_term(core->timer_hang_detection);
- core->timer_hang_detection = NULL;
- }
-
-#if USING_MALI_PMM
- /* Unregister the core with the PMM */
- malipmm_core_unregister( core->pmm_id );
-#endif
-}
-
-/* Used by external renderunit_create<> function */
-_mali_osk_errcode_t mali_core_renderunit_map_registers(mali_core_renderunit *core)
-{
- MALI_DEBUG_PRINT(3, ("Core: renderunit_map_registers: Core:%s\n", core->description)) ;
- if( (0 == core->registers_base_addr) ||
- (0 == core->size) ||
- (NULL == core->description)
- )
- {
- MALI_PRINT_ERROR(("Missing fields in the core structure %u %u 0x%x;\n", core->registers_base_addr, core->size, core->description));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(core->registers_base_addr, core->size, core->description))
- {
- MALI_PRINT_ERROR(("Could not request register region (0x%08X - 0x%08X) to core: %s\n",
- core->registers_base_addr, core->registers_base_addr + core->size - 1, core->description));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
- else
- {
- MALI_DEBUG_PRINT(6, ("Success: request_mem_region: (0x%08X - 0x%08X) Core:%s\n",
- core->registers_base_addr, core->registers_base_addr + core->size - 1, core->description));
- }
-
- core->registers_mapped = _mali_osk_mem_mapioregion( core->registers_base_addr, core->size, core->description );
-
- if ( 0 == core->registers_mapped )
- {
- MALI_PRINT_ERROR(("Could not ioremap registers for %s .\n", core->description));
- _mali_osk_mem_unreqregion(core->registers_base_addr, core->size);
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
- }
- else
- {
- MALI_DEBUG_PRINT(6, ("Success: ioremap_nocache: Internal ptr: (0x%08X - 0x%08X) Core:%s\n",
- (u32) core->registers_mapped,
- ((u32)core->registers_mapped)+ core->size - 1,
- core->description));
- }
-
- MALI_DEBUG_PRINT(4, ("Success: Mapping registers to core: %s\n",core->description));
-
- MALI_SUCCESS;
-}
-
-/* Used by external renderunit_create<> function + other places */
-void mali_core_renderunit_unmap_registers(mali_core_renderunit *core)
-{
- MALI_DEBUG_PRINT(3, ("Core: renderunit_unmap_registers: Core:%s\n", core->description));
- if (0 == core->registers_mapped)
- {
- MALI_PRINT_ERROR(("Trying to unmap register-mapping with NULL from core: %s\n", core->description));
- return;
- }
- _mali_osk_mem_unmapioregion(core->registers_base_addr, core->size, core->registers_mapped);
- core->registers_mapped = 0;
- _mali_osk_mem_unreqregion(core->registers_base_addr, core->size);
-}
-
-static void mali_core_renderunit_irq_handler_remove(mali_core_renderunit *core)
-{
- MALI_DEBUG_PRINT(3, ("Core: renderunit_irq_handler_remove: Core:%s\n", core->description));
- _mali_osk_irq_term(core->irq);
-}
-
-mali_core_renderunit * mali_core_renderunit_get_mali_core_nr(mali_core_subsystem *subsys, u32 mali_core_nr)
-{
- mali_core_renderunit * core;
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
- if (subsys->number_of_cores <= mali_core_nr)
- {
- MALI_PRINT_ERROR(("Trying to get illegal mali_core_nr: 0x%x for %s", mali_core_nr, subsys->name));
- return NULL;
- }
- core = (subsys->mali_core_array)[mali_core_nr];
- MALI_DEBUG_PRINT(6, ("Core: renderunit_get_mali_core_nr: Core:%s\n", core->description));
- MALI_CHECK_CORE(core);
- return core;
-}
-
-/* Is used by external function:
- subsystem_startup<> */
-_mali_osk_errcode_t mali_core_subsystem_init(mali_core_subsystem* new_subsys)
-{
- int i;
-
- /* These function pointers must have been set on before calling this function */
- if (
- ( NULL == new_subsys->name ) ||
- ( NULL == new_subsys->start_job ) ||
- ( NULL == new_subsys->irq_handler_upper_half ) ||
- ( NULL == new_subsys->irq_handler_bottom_half ) ||
- ( NULL == new_subsys->get_new_job_from_user ) ||
- ( NULL == new_subsys->return_job_to_user )
- )
- {
- MALI_PRINT_ERROR(("Missing functions in subsystem."));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- MALI_DEBUG_PRINT(2, ("Core: subsystem_init: %s\n", new_subsys->name)) ;
-
- /* Catch use-before-initialize/use-after-terminate */
- MALI_DEBUG_ASSERT_POINTER( rendercores_global_mutex );
-
- new_subsys->magic_nr = SUBSYSTEM_MAGIC_NR;
-
- _MALI_OSK_INIT_LIST_HEAD(&new_subsys->renderunit_idle_head); /* Idle cores of this type */
- _MALI_OSK_INIT_LIST_HEAD(&new_subsys->renderunit_off_head); /* Powered off cores of this type */
-
- /* Linked list for each priority of sessions with a job ready for scheduleing */
- for(i=0; i<PRIORITY_LEVELS; ++i)
- {
- _MALI_OSK_INIT_LIST_HEAD(&new_subsys->awaiting_sessions_head[i]);
- }
-
- /* Linked list of all sessions connected to this coretype */
- _MALI_OSK_INIT_LIST_HEAD(&new_subsys->all_sessions_head);
-
- MALI_SUCCESS;
-}
-
-#if USING_MMU
-void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys)
-{
- u32 i;
- mali_core_renderunit * core;
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
-
- for(i=0 ; i < subsys->number_of_cores ; ++i)
- {
- core = mali_core_renderunit_get_mali_core_nr(subsys,i);
- if ( NULL==core ) break;
- core->mmu = mali_memory_core_mmu_lookup(core->mmu_id);
- mali_memory_core_mmu_owner(core,core->mmu);
- MALI_DEBUG_PRINT(2, ("Attach mmu: 0x%x to core: %s in subsystem: %s\n", core->mmu, core->description, subsys->name));
- }
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
-}
-#endif
-
-/* This will register an IRQ handler, and add the core to the list of available cores for this subsystem. */
-_mali_osk_errcode_t mali_core_subsystem_register_renderunit(mali_core_subsystem* subsys, mali_core_renderunit * core)
-{
- mali_core_renderunit ** mali_core_array;
- u32 previous_nr;
- u32 previous_size;
- u32 new_nr;
- u32 new_size;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
-
- /* If any of these are 0 there is an error */
- if(0 == core->subsystem ||
- 0 == core->registers_base_addr ||
- 0 == core->size ||
- 0 == core->description)
- {
- MALI_PRINT_ERROR(("Missing fields in the core structure 0x%x 0x%x 0x%x;\n",
- core->registers_base_addr, core->size, core->description));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- MALI_DEBUG_PRINT(3, ("Core: subsystem_register_renderunit: %s\n", core->description));
-
- MALI_CHECK_NON_NULL(
- core->irq = _mali_osk_irq_init(
- core->irq_nr,
- mali_core_irq_handler_upper_half,
- mali_core_irq_handler_bottom_half,
- (_mali_osk_irq_trigger_t)subsys->probe_core_irq_trigger,
- (_mali_osk_irq_ack_t)subsys->probe_core_irq_acknowledge,
- core,
- "mali_core_irq_handlers"
- ),
- _MALI_OSK_ERR_FAULT
- );
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
-
- /* Update which core number this is */
- core->core_number = subsys->number_of_cores;
-
- /* Update the array of cores in the subsystem. */
- previous_nr = subsys->number_of_cores;
- previous_size = sizeof(mali_core_renderunit*)*previous_nr;
- new_nr = previous_nr + 1;
- new_size = sizeof(mali_core_renderunit*)*new_nr;
-
- if (0 != previous_nr)
- {
- if (NULL == subsys->mali_core_array)
- {
- MALI_PRINT_ERROR(("Internal error"));
- goto exit_function;
- }
-
- mali_core_array = (mali_core_renderunit **) _mali_osk_malloc( new_size );
- if (NULL == mali_core_array )
- {
- MALI_PRINT_ERROR(("Out of mem"));
- err = _MALI_OSK_ERR_NOMEM;
- goto exit_function;
- }
- _mali_osk_memcpy(mali_core_array, subsys->mali_core_array, previous_size);
- _mali_osk_free( subsys->mali_core_array);
- MALI_DEBUG_PRINT(5, ("Success: adding a new core to subsystem array %s\n", core->description) ) ;
- }
- else
- {
- mali_core_array = (mali_core_renderunit **) _mali_osk_malloc( new_size );
- if (NULL == mali_core_array )
- {
- MALI_PRINT_ERROR(("Out of mem"));
- err = _MALI_OSK_ERR_NOMEM;
- goto exit_function;
- }
- MALI_DEBUG_PRINT(6, ("Success: adding first core to subsystem array %s\n", core->description) ) ;
- }
- subsys->mali_core_array = mali_core_array;
- mali_core_array[previous_nr] = core;
-
- /* Add the core to the list of available cores on the system */
- _mali_osk_list_add(&(core->list), &(subsys->renderunit_idle_head));
-
- /* Update total number of cores */
- subsys->number_of_cores = new_nr;
- MALI_DEBUG_PRINT(6, ("Success: mali_core_subsystem_register_renderunit %s\n", core->description));
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_SUCCESS;
-
-exit_function:
- mali_core_renderunit_irq_handler_remove(core);
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_ERROR(err);
-}
-
-
-/**
- * Called by the core when a system info update is needed
- * We fill in info about all the core types available
- * @param subsys Pointer to the core's @a mali_core_subsystem data structure
- * @param info Pointer to system info struct to update
- * @return _MALI_OSK_ERR_OK on success, or another _mali_osk_errcode_t error code on failure
- */
-_mali_osk_errcode_t mali_core_subsystem_system_info_fill(mali_core_subsystem* subsys, _mali_system_info* info)
-{
- u32 i;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; /* OK if no cores to update info for */
- mali_core_renderunit * core;
- _mali_core_info **core_info_nextp;
- _mali_core_info * cinfo;
-
- MALI_DEBUG_PRINT(4, ("mali_core_subsystem_system_info_fill: %s\n", subsys->name) ) ;
-
- /* check input */
- MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS);
-
- core_info_nextp = &(info->core_info);
- cinfo = info->core_info;
-
- while(NULL!=cinfo)
- {
- core_info_nextp = &(cinfo->next);
- cinfo = cinfo->next;
- }
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
- for(i=0 ; i < subsys->number_of_cores ; ++i)
- {
- core = mali_core_renderunit_get_mali_core_nr(subsys,i);
- if ( NULL==core )
- {
- err = _MALI_OSK_ERR_FAULT;
- goto early_exit;
- }
- cinfo = (_mali_core_info *)_mali_osk_calloc(1, sizeof(_mali_core_info));
- if ( NULL==cinfo )
- {
- err = _MALI_OSK_ERR_NOMEM;
- goto early_exit;
- }
- cinfo->version = core->core_version;
- cinfo->type =subsys->core_type;
- cinfo->reg_address = core->registers_base_addr;
- cinfo->core_nr = i;
- cinfo->next = NULL;
- /* Writing this address to the previous' *(&next) ptr */
- *core_info_nextp = cinfo;
- /* Setting the next_ptr to point to &this->next_ptr */
- core_info_nextp = &(cinfo->next);
- }
-early_exit:
- if ( _MALI_OSK_ERR_OK != err) MALI_PRINT_ERROR(("Error: In mali_core_subsystem_system_info_fill %d\n", err));
- MALI_DEBUG_CODE(
- cinfo = info->core_info;
-
- MALI_DEBUG_PRINT(3, ("Current list of cores\n"));
- while( NULL != cinfo )
- {
- MALI_DEBUG_PRINT(3, ("Type: 0x%x\n", cinfo->type));
- MALI_DEBUG_PRINT(3, ("Version: 0x%x\n", cinfo->version));
- MALI_DEBUG_PRINT(3, ("Reg_addr: 0x%x\n", cinfo->reg_address));
- MALI_DEBUG_PRINT(3, ("Core_nr: 0x%x\n", cinfo->core_nr));
- MALI_DEBUG_PRINT(3, ("Flags: 0x%x\n", cinfo->flags));
- MALI_DEBUG_PRINT(3, ("*****\n"));
- cinfo = cinfo->next;
- }
- );
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_ERROR(err);
-}
-
-
-/* Is used by external function:
- subsystem_terminate<> */
-void mali_core_subsystem_cleanup(mali_core_subsystem* subsys)
-{
- u32 i;
- mali_core_renderunit * core;
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
- MALI_DEBUG_PRINT(2, ("Core: subsystem_cleanup: %s\n", subsys->name )) ;
-
- for(i=0 ; i < subsys->number_of_cores ; ++i)
- {
- core = mali_core_renderunit_get_mali_core_nr(subsys,i);
-
-#if USING_MMU
- if (NULL != core->mmu)
- {
- /* the MMU is attached in the load_complete callback, which will never be called if the module fails to load, handle that case */
- mali_memory_core_mmu_unregister_callback(core->mmu, mali_core_subsystem_callback_schedule_wrapper);
- }
-#endif
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
-
- mali_core_renderunit_irq_handler_remove(core);
-
- /* When a process terminates, all cores running jobs from that process is reset and put to idle.
- That means that when the module is unloading (this code) we are guaranteed that all cores are idle.
- However: if something (we can't think of) is really wrong, a core may give an interrupt during this
- unloading, and we may now in the code have a bottom-half-processing pending from the interrupts
- we deregistered above. To be sure that the bottom halves do not access the structures after they
- are deallocated we flush the bottom-halves processing here, before the deallocation. */
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
-
-#if USING_MALI_PMM
- /* Only reset when we are using PMM and the core is not off */
-#if MALI_PMM_NO_PMU
- /* We need to reset when there is no PMU - but this will
- * cause the register read/write functions to report an
- * error (hence the if to check for CORE_OFF below) we
- * change state to allow the reset to happen.
- */
- core->state = CORE_IDLE;
-#endif
- if( core->state != CORE_OFF )
- {
- subsys->reset_core( core, MALI_CORE_RESET_STYLE_DISABLE );
- }
-#else
- /* Always reset the core */
- subsys->reset_core( core, MALI_CORE_RESET_STYLE_DISABLE );
-#endif
-
- mali_core_renderunit_unmap_registers(core);
-
- _mali_osk_list_delinit(&core->list);
-
- mali_core_renderunit_term(core);
-
- subsys->renderunit_delete(core);
- }
-
- mali_core_subsystem_cleanup_all_renderunits(subsys);
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_DEBUG_PRINT(6, ("SUCCESS: mali_core_subsystem_cleanup: %s\n", subsys->name )) ;
-}
-
-_mali_osk_errcode_t mali_core_subsystem_ioctl_number_of_cores_get(mali_core_session * session, u32 *number_of_cores)
-{
- mali_core_subsystem * subsystem;
-
- subsystem = session->subsystem;
- if ( NULL != number_of_cores )
- {
- *number_of_cores = subsystem->number_of_cores;
-
- MALI_DEBUG_PRINT(4, ("Core: ioctl_number_of_cores_get: %s: %u\n", subsystem->name, *number_of_cores) ) ;
- }
-
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_core_subsystem_ioctl_start_job(mali_core_session * session, void *job_data)
-{
- mali_core_subsystem * subsystem;
- _mali_osk_errcode_t err;
-
- /* need the subsystem to run callback function */
- subsystem = session->subsystem;
- MALI_CHECK_NON_NULL(subsystem, _MALI_OSK_ERR_FAULT);
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
- err = subsystem->get_new_job_from_user(session, job_data);
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
-
- MALI_ERROR(err);
-}
-
-
-/* We return the version number to the first core in this subsystem */
-_mali_osk_errcode_t mali_core_subsystem_ioctl_core_version_get(mali_core_session * session, _mali_core_version *version)
-{
- mali_core_subsystem * subsystem;
- mali_core_renderunit * core0;
- u32 nr_return;
-
- subsystem = session->subsystem;
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
-
- core0 = mali_core_renderunit_get_mali_core_nr(subsystem, 0);
-
- if( NULL == core0 )
- {
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- nr_return = core0->core_version;
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
-
- MALI_DEBUG_PRINT(4, ("Core: ioctl_core_version_get: %s: %u\n", subsystem->name, nr_return )) ;
-
- *version = nr_return;
-
- MALI_SUCCESS;
-}
-
-void mali_core_subsystem_ioctl_abort_job(mali_core_session * session, u32 id)
-{
- find_and_abort(session, id);
-}
-
-static mali_bool job_should_be_aborted(mali_core_job *job, u32 abort_id)
-{
- if ( job->abort_id == abort_id ) return MALI_TRUE;
- else return MALI_FALSE;
-}
-
-static void find_and_abort(mali_core_session* session, u32 abort_id)
-{
- mali_core_subsystem * subsystem;
- mali_core_renderunit *core;
- mali_core_renderunit *tmp;
- mali_core_job *job;
-
- subsystem = session->subsystem;
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
-
- job = mali_job_queue_abort_job(session, abort_id);
- if (NULL != job)
- {
- MALI_DEBUG_PRINT(3, ("Core: Aborting %s job, with id nr: %u, from the waiting_to_run slot.\n", subsystem->name, abort_id ));
- if (mali_job_queue_empty(session))
- {
- _mali_osk_list_delinit(&(session->awaiting_sessions_list));
- }
- subsystem->awaiting_sessions_sum_all_priorities--;
- subsystem->return_job_to_user(job , JOB_STATUS_END_ABORT);
- }
-
- _MALI_OSK_LIST_FOREACHENTRY( core, tmp, &session->renderunits_working_head, mali_core_renderunit, list )
- {
- job = core->current_job;
- if ( (job!=NULL) && (job_should_be_aborted (job, abort_id) ) )
- {
- MALI_DEBUG_PRINT(3, ("Core: Aborting %s job, with id nr: %u, which is currently running on mali.\n", subsystem->name, abort_id ));
- if ( core->state==CORE_IDLE )
- {
- MALI_PRINT_ERROR(("Aborting core with running job which is idle. Must be something very wrong."));
- goto end_bug;
- }
- mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_ABORT);
- }
- }
-end_bug:
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem );
-}
-
-
-_mali_osk_errcode_t mali_core_subsystem_ioctl_suspend_response(mali_core_session * session, void *argument)
-{
- mali_core_subsystem * subsystem;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
-
- /* need the subsystem to run callback function */
- subsystem = session->subsystem;
- MALI_CHECK_NON_NULL(subsystem, _MALI_OSK_ERR_FAULT);
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
- if ( NULL != subsystem->suspend_response)
- {
- MALI_DEBUG_PRINT(4, ("MALI_IOC_CORE_CMD_SUSPEND_RESPONSE start\n"));
- err = subsystem->suspend_response(session, argument);
- MALI_DEBUG_PRINT(4, ("MALI_IOC_CORE_CMD_SUSPEND_RESPONSE end\n"));
- }
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
-
- return err;
-}
-
-
-/* Is used by internal function:
- mali_core_subsystem_cleanup<>s */
-/* All cores should be removed before calling this function
-Must hold subsystem_mutex before entering this function */
-static void mali_core_subsystem_cleanup_all_renderunits(mali_core_subsystem* subsys)
-{
- int i;
- _mali_osk_free(subsys->mali_core_array);
- subsys->number_of_cores = 0;
-
- MALI_DEBUG_PRINT(5, ("Core: subsystem_cleanup_all_renderunits: %s\n", subsys->name) ) ;
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
-
- if ( ! _mali_osk_list_empty(&(subsys->renderunit_idle_head)))
- {
- MALI_PRINT_ERROR(("List renderunit_list_idle should be empty."));
- _MALI_OSK_INIT_LIST_HEAD(&(subsys->renderunit_idle_head)) ;
- }
-
- if ( ! _mali_osk_list_empty(&(subsys->renderunit_off_head)))
- {
- MALI_PRINT_ERROR(("List renderunit_list_off should be empty."));
- _MALI_OSK_INIT_LIST_HEAD(&(subsys->renderunit_off_head)) ;
- }
-
- for(i=0; i<PRIORITY_LEVELS; ++i)
- {
- if ( ! _mali_osk_list_empty(&(subsys->awaiting_sessions_head[i])))
- {
- MALI_PRINT_ERROR(("List awaiting_sessions_linkedlist should be empty."));
- _MALI_OSK_INIT_LIST_HEAD(&(subsys->awaiting_sessions_head[i])) ;
- subsys->awaiting_sessions_sum_all_priorities = 0;
- }
- }
-
- if ( ! _mali_osk_list_empty(&(subsys->all_sessions_head)))
- {
- MALI_PRINT_ERROR(("List all_sessions_linkedlist should be empty."));
- _MALI_OSK_INIT_LIST_HEAD(&(subsys->all_sessions_head)) ;
- }
-}
-
-/* Is used by internal functions:
- mali_core_irq_handler_bottom_half<>;
- mali_core_subsystem_schedule<>; */
-/* Will release the core.*/
-/* Must hold subsystem_mutex before entering this function */
-static void mali_core_subsystem_move_core_set_idle(mali_core_renderunit *core)
-{
- mali_core_subsystem *subsystem;
-#if USING_MALI_PMM
- mali_core_status oldstatus;
-#endif
- subsystem = core->subsystem;
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
- MALI_CHECK_CORE(core);
- MALI_CHECK_SUBSYSTEM(subsystem);
-
- _mali_osk_timer_del(core->timer);
- _mali_osk_timer_del(core->timer_hang_detection);
-
- MALI_DEBUG_PRINT(5, ("Core: subsystem_move_core_set_idle: %s\n", core->description) ) ;
-
- core->current_job = NULL ;
-
-#if USING_MALI_PMM
-
- oldstatus = core->state;
-
- if ( !core->pend_power_down )
- {
- core->state = CORE_IDLE ;
- _mali_osk_list_move( &core->list, &subsystem->renderunit_idle_head );
- }
-
- if( CORE_OFF != oldstatus )
- {
- /* Message that this core is now idle or in fact off */
- _mali_uk_pmm_message_s event = {
- NULL,
- MALI_PMM_EVENT_JOB_FINISHED,
- 0 };
- event.data = core->pmm_id;
- _mali_ukk_pmm_event_message( &event );
-#if USING_MMU
- /* Only free the reference when entering idle state from
- * anything other than power off
- */
- mali_memory_core_mmu_release_address_space_reference(core->mmu);
-#endif /* USING_MMU */
- }
-
- if( core->pend_power_down )
- {
- core->state = CORE_OFF ;
- _mali_osk_list_move( &core->list, &subsystem->renderunit_off_head );
-
- /* Done the move from the active queues, so the pending power down can be done */
- core->pend_power_down = MALI_FALSE;
- malipmm_core_power_down_okay( core->pmm_id );
- }
-
-#else /* !USING_MALI_PMM */
-
- core->state = CORE_IDLE ;
- _mali_osk_list_move( &core->list, &subsystem->renderunit_idle_head );
-
-#if USING_MMU
- mali_memory_core_mmu_release_address_space_reference(core->mmu);
-#endif
-
-#endif /* USING_MALI_PMM */
-}
-
-/* Must hold subsystem_mutex before entering this function */
-static void mali_core_subsystem_move_set_working(mali_core_renderunit *core, mali_core_job *job)
-{
- mali_core_subsystem *subsystem;
- mali_core_session *session;
- u64 time_now;
-
- session = job->session;
- subsystem = core->subsystem;
-
- MALI_CHECK_CORE(core);
- MALI_CHECK_JOB(job);
- MALI_CHECK_SUBSYSTEM(subsystem);
-
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
-
- MALI_DEBUG_PRINT(5, ("Core: subsystem_move_set_working: %s\n", core->description) ) ;
-
- time_now = _mali_osk_time_get_ns();
- job->start_time = time_now;
-#if MALI_GPU_UTILIZATION
- mali_utilization_core_start(time_now);
-#endif
-
- core->current_job = job ;
- core->state = CORE_WORKING ;
- _mali_osk_list_move( &core->list, &session->renderunits_working_head );
-
-}
-
-#if USING_MALI_PMM
-
-/* Must hold subsystem_mutex before entering this function */
-static void mali_core_subsystem_move_core_set_off(mali_core_renderunit *core)
-{
- mali_core_subsystem *subsystem;
- subsystem = core->subsystem;
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
- MALI_CHECK_CORE(core);
- MALI_CHECK_SUBSYSTEM(subsystem);
-
- /* Cores must be idle before powering off */
- MALI_DEBUG_ASSERT(core->state == CORE_IDLE);
-
- MALI_DEBUG_PRINT(5, ("Core: subsystem_move_core_set_off: %s\n", core->description) ) ;
-
- core->current_job = NULL ;
- core->state = CORE_OFF ;
- _mali_osk_list_move( &core->list, &subsystem->renderunit_off_head );
-}
-
-#endif /* USING_MALI_PMM */
-
-/* Is used by internal function:
- mali_core_subsystem_schedule<>; */
-/* Returns the job with the highest priority for the subsystem. NULL if none*/
-/* Must hold subsystem_mutex before entering this function */
-static mali_core_session * mali_core_subsystem_get_waiting_session(mali_core_subsystem *subsystem)
-{
- int i;
-
- MALI_CHECK_SUBSYSTEM(subsystem);
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
-
- if ( 0 == subsystem->awaiting_sessions_sum_all_priorities )
- {
- MALI_DEBUG_PRINT(5, ("Core: subsystem_get_waiting_job: No awaiting session found\n"));
- return NULL;
- }
-
- for( i=0; i<PRIORITY_LEVELS ; ++i)
- {
- if (!_mali_osk_list_empty(&subsystem->awaiting_sessions_head[i]))
- {
- return _MALI_OSK_LIST_ENTRY(subsystem->awaiting_sessions_head[i].next, mali_core_session, awaiting_sessions_list);
- }
- }
-
- return NULL;
-}
-
-static mali_core_job * mali_core_subsystem_release_session_get_job(mali_core_subsystem *subsystem, mali_core_session * session)
-{
- mali_core_job *job;
- MALI_CHECK_SUBSYSTEM(subsystem);
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
-
- job = mali_job_queue_get_job(session);
- subsystem->awaiting_sessions_sum_all_priorities--;
-
- if(mali_job_queue_empty(session))
- {
- /* This is the last job, so remove it from the list */
- _mali_osk_list_delinit(&session->awaiting_sessions_list);
- }
- else
- {
- if (0 == (job->flags & MALI_UK_START_JOB_FLAG_MORE_JOBS_FOLLOW))
- {
- /* There are more jobs, but the follow flag is not set, so let other sessions run their jobs first */
- _mali_osk_list_del(&(session->awaiting_sessions_list));
- _mali_osk_list_addtail(&(session->awaiting_sessions_list), &(subsystem->awaiting_sessions_head[
- session->queue[session->queue_head]->priority]));
- }
- /* else; keep on list, follow flag is set and there are more jobs in queue for this session */
- }
-
- MALI_CHECK_JOB(job);
- return job;
-}
-
-/* Is used by internal functions:
- mali_core_subsystem_schedule<> */
-/* This will start the job on the core. It will also release the core if it did not start.*/
-/* Must hold subsystem_mutex before entering this function */
-static void mali_core_job_start_on_core(mali_core_job *job, mali_core_renderunit *core)
-{
- mali_core_session *session;
- mali_core_subsystem *subsystem;
- _mali_osk_errcode_t err;
- session = job->session;
- subsystem = core->subsystem;
-
- MALI_CHECK_CORE(core);
- MALI_CHECK_JOB(job);
- MALI_CHECK_SUBSYSTEM(subsystem);
- MALI_CHECK_SESSION(session);
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
-
- MALI_DEBUG_PRINT(4, ("Core: job_start_on_core: job=0x%x, session=0x%x, core=%s\n", job, session, core->description));
-
- MALI_DEBUG_ASSERT(NULL == core->current_job) ;
- MALI_DEBUG_ASSERT(CORE_IDLE == core->state );
-
- mali_core_subsystem_move_set_working(core, job);
-
-#if defined USING_MALI400_L2_CACHE
- if (0 == (job->flags & MALI_UK_START_JOB_FLAG_NO_FLUSH))
- {
- /* Invalidate the L2 cache */
- if (_MALI_OSK_ERR_OK != mali_kernel_l2_cache_invalidate_all() )
- {
- MALI_DEBUG_PRINT(4, ("Core: Clear of L2 failed, return job. System may not be usable for some reason.\n"));
- mali_core_subsystem_move_core_set_idle(core);
- subsystem->return_job_to_user(job,JOB_STATUS_END_SYSTEM_UNUSABLE );
- return;
- }
- }
-#endif
-
- /* Tries to start job on the core. Returns MALI_FALSE if the job could not be started */
- err = subsystem->start_job(job, core);
-
- if ( _MALI_OSK_ERR_OK != err )
- {
- /* This will happen only if there is something in the job object
- which make it inpossible to start. Like if it require illegal memory.*/
- MALI_DEBUG_PRINT(4, ("Core: start_job failed, return job and putting core back into idle list\n"));
- mali_core_subsystem_move_core_set_idle(core);
- subsystem->return_job_to_user(job,JOB_STATUS_END_ILLEGAL_JOB );
- }
- else
- {
- u32 delay = _mali_osk_time_mstoticks(job->watchdog_msecs)+1;
- job->watchdog_jiffies = _mali_osk_time_tickcount() + delay;
- if (mali_benchmark)
- {
- _mali_osk_timer_add(core->timer, 1);
- }
- else
- {
- _mali_osk_timer_add(core->timer, delay);
- }
- }
-}
-
-#if USING_MMU
-static void mali_core_subsystem_callback_schedule_wrapper(void* sub)
-{
- mali_core_subsystem * subsystem;
- subsystem = (mali_core_subsystem *)sub;
- MALI_DEBUG_PRINT(3, ("MMU: Is schedulling subsystem: %s\n", subsystem->name));
- mali_core_subsystem_schedule(subsystem);
-}
-#endif
-
-/* Is used by internal function:
- mali_core_irq_handler_bottom_half
- mali_core_session_add_job
-*/
-/* Must hold subsystem_mutex before entering this function */
-static void mali_core_subsystem_schedule(mali_core_subsystem * subsystem)
-{
- mali_core_renderunit *core, *tmp;
- mali_core_session *session;
- mali_core_job *job;
-#ifdef MALI_REBOOTNOTIFIER
- if (_mali_osk_atomic_read(&mali_shutdown_state) > 0) {
- MALI_DEBUG_PRINT(3, ("Core: mali already under shutdown process!!")) ;
- return;
- }
-#endif
-
- MALI_DEBUG_PRINT(5, ("Core: subsystem_schedule: %s\n", subsystem->name )) ;
-
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
-
- /* First check that there are sessions with jobs waiting to run */
- if ( 0 == subsystem->awaiting_sessions_sum_all_priorities)
- {
- MALI_DEBUG_PRINT(6, ("Core: No jobs available for %s\n", subsystem->name) ) ;
- return;
- }
-
- /* Returns the session with the highest priority job for the subsystem. NULL if none*/
- session = mali_core_subsystem_get_waiting_session(subsystem);
-
- if (NULL == session)
- {
- MALI_DEBUG_PRINT(6, ("Core: Schedule: No runnable job found\n"));
- return;
- }
-
- _MALI_OSK_LIST_FOREACHENTRY(core, tmp, &subsystem->renderunit_idle_head, mali_core_renderunit, list)
- {
-#if USING_MMU
- int err = mali_memory_core_mmu_activate_page_table(core->mmu, session->mmu_session, mali_core_subsystem_callback_schedule_wrapper, subsystem);
- if (0 == err)
- {
- /* core points to a core where the MMU page table activation succeeded */
-#endif
- /* This will remove the job from queue system */
- job = mali_core_subsystem_release_session_get_job(subsystem, session);
- MALI_DEBUG_ASSERT_POINTER(job);
-
- MALI_DEBUG_PRINT(6, ("Core: Schedule: Got a job 0x%x\n", job));
-
-#if USING_MALI_PMM
- {
- /* Message that there is a job scheduled to run
- * NOTE: mali_core_job_start_on_core() can fail to start
- * the job for several reasons, but it will move the core
- * back to idle which will create the FINISHED message
- * so we can still say that the job is SCHEDULED
- */
- _mali_uk_pmm_message_s event = {
- NULL,
- MALI_PMM_EVENT_JOB_SCHEDULED,
- 0 };
- event.data = core->pmm_id;
- _mali_ukk_pmm_event_message( &event );
- }
-#endif
- /* This will {remove core from freelist AND start the job on the core}*/
- mali_core_job_start_on_core(job, core);
-
- MALI_DEBUG_PRINT(6, ("Core: Schedule: Job started, done\n"));
- return;
-#if USING_MMU
- }
-#endif
- }
- MALI_DEBUG_PRINT(6, ("Core: Schedule: Could not activate MMU. Scheduelling postponed to MMU, checking next.\n"));
-
-#if USING_MALI_PMM
- {
- /* Message that there are jobs to run */
- _mali_uk_pmm_message_s event = {
- NULL,
- MALI_PMM_EVENT_JOB_QUEUED,
- 0 };
- if( subsystem->core_type == _MALI_GP2 || subsystem->core_type == _MALI_400_GP )
- {
- event.data = MALI_PMM_CORE_GP;
- }
- else
- {
- /* Check the PP is supported by the PMM */
- MALI_DEBUG_ASSERT( subsystem->core_type == _MALI_200 || subsystem->core_type == _MALI_400_PP );
- /* We state that all PP cores are scheduled to inform the PMM
- * that it may need to power something up!
- */
- event.data = MALI_PMM_CORE_PP_ALL;
- }
- _mali_ukk_pmm_event_message( &event );
- }
-#endif /* USING_MALI_PMM */
-
-}
-
-/* Is used by external function:
- session_begin<> */
-void mali_core_session_begin(mali_core_session * session)
-{
- mali_core_subsystem * subsystem;
- int i;
-
- subsystem = session->subsystem;
- if ( NULL == subsystem )
- {
- MALI_PRINT_ERROR(("Missing data in struct\n"));
- return;
- }
- MALI_DEBUG_PRINT(2, ("Core: session_begin: for %s\n", session->subsystem->name )) ;
-
- session->magic_nr = SESSION_MAGIC_NR;
-
- _MALI_OSK_INIT_LIST_HEAD(&session->renderunits_working_head);
-
- for (i = 0; i < MALI_JOB_QUEUE_SIZE; i++)
- {
- session->queue[i] = NULL;
- }
- session->queue_head = 0;
- session->queue_tail = 0;
- _MALI_OSK_INIT_LIST_HEAD(&session->awaiting_sessions_list);
- _MALI_OSK_INIT_LIST_HEAD(&session->all_sessions_list);
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
- _mali_osk_list_add(&session->all_sessions_list, &session->subsystem->all_sessions_head);
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_init(&session->jobs_received, 0);
- _mali_osk_atomic_init(&session->jobs_returned, 0);
- session->pid = _mali_osk_get_pid();
-#endif
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
-
- MALI_DEBUG_PRINT(5, ("Core: session_begin: for %s DONE\n", session->subsystem->name) ) ;
-}
-
-#if USING_MMU
-static void mali_core_renderunit_stop_bus(mali_core_renderunit* core)
-{
- core->subsystem->stop_bus(core);
-}
-#endif
-
-void mali_core_session_close(mali_core_session * session)
-{
- mali_core_subsystem * subsystem;
- mali_core_renderunit *core;
-
- subsystem = session->subsystem;
- MALI_DEBUG_ASSERT_POINTER(subsystem);
-
- MALI_DEBUG_PRINT(2, ("Core: session_close: for %s\n", session->subsystem->name) ) ;
-
- /* We must grab subsystem mutex since the list this session belongs to
- is owned by the subsystem */
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
-
- /* Remove this session from the global sessionlist */
- _mali_osk_list_delinit(&session->all_sessions_list);
-
- _mali_osk_list_delinit(&(session->awaiting_sessions_list));
-
- /* Return the potensial waiting job to user */
- while ( !mali_job_queue_empty(session) )
- {
- /* Queue not empty */
- mali_core_job *job = mali_job_queue_get_job(session);
- subsystem->return_job_to_user( job, JOB_STATUS_END_SHUTDOWN );
- subsystem->awaiting_sessions_sum_all_priorities--;
- }
-
- /* Kill active cores working for this session - freeing their jobs
- Since the handling of one core also could stop jobs from another core, there is a while loop */
- while ( ! _mali_osk_list_empty(&session->renderunits_working_head) )
- {
- core = _MALI_OSK_LIST_ENTRY(session->renderunits_working_head.next, mali_core_renderunit, list);
- MALI_DEBUG_PRINT(3, ("Core: session_close: Core was working: %s\n", core->description )) ;
- mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_SHUTDOWN );
- }
- _MALI_OSK_INIT_LIST_HEAD(&session->renderunits_working_head); /* Not necessary - we will _mali_osk_free session*/
-
- MALI_DEBUG_PRINT(5, ("Core: session_close: for %s FINISHED\n", session->subsystem->name )) ;
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem );
-}
-
-/* Must hold subsystem_mutex before entering this function */
-_mali_osk_errcode_t mali_core_session_add_job(mali_core_session * session, mali_core_job *job, mali_core_job **job_return)
-{
- mali_core_subsystem * subsystem;
-
- job->magic_nr = JOB_MAGIC_NR;
- MALI_CHECK_SESSION(session);
-
- subsystem = session->subsystem;
- MALI_CHECK_SUBSYSTEM(subsystem);
- MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
-
- MALI_DEBUG_PRINT(5, ("Core: session_add_job: for %s\n", subsystem->name )) ;
-
- /* Setting the default value; No job to return */
- MALI_DEBUG_ASSERT_POINTER(job_return);
- *job_return = NULL;
-
- if (mali_job_queue_empty(session))
- {
- /* Add session to the wait list only if it didn't already have a job waiting. */
- _mali_osk_list_addtail( &(session->awaiting_sessions_list), &(subsystem->awaiting_sessions_head[job->priority]));
- }
-
-
- if (_MALI_OSK_ERR_OK != mali_job_queue_add_job(session, job))
- {
- if (mali_job_queue_empty(session))
- {
- _mali_osk_list_delinit(&(session->awaiting_sessions_list));
- }
- MALI_DEBUG_PRINT(4, ("Core: session_add_job: %s queue is full\n", subsystem->name));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* Continue to add the new job as the next job from this session */
- MALI_DEBUG_PRINT(6, ("Core: session_add_job job=0x%x\n", job));
-
- subsystem->awaiting_sessions_sum_all_priorities++;
-
- mali_core_subsystem_schedule(subsystem);
-
- MALI_DEBUG_PRINT(6, ("Core: session_add_job: for %s FINISHED\n", session->subsystem->name )) ;
-
- MALI_SUCCESS;
-}
-
-static void mali_core_job_set_run_time(mali_core_job * job, u64 end_time)
-{
- u32 time_used_nano_seconds;
-
- time_used_nano_seconds = end_time - job->start_time;
- job->render_time_usecs = time_used_nano_seconds / 1000;
-}
-
-static void mali_core_renderunit_detach_job_from_core(mali_core_renderunit* core, mali_subsystem_reschedule_option reschedule, mali_subsystem_job_end_code end_status)
-{
- mali_core_job * job;
- mali_core_subsystem * subsystem;
- mali_bool already_in_detach_function;
- u64 time_now;
-
- MALI_DEBUG_ASSERT(CORE_IDLE != core->state);
- time_now = _mali_osk_time_get_ns();
- job = core->current_job;
- subsystem = core->subsystem;
-
- /* The reset_core() called some lines below might call this detach
- * funtion again. To protect the core object from being modified by
- * recursive calls, the in_detach_function would track if it is an recursive call
- */
- already_in_detach_function = core->in_detach_function;
-
-
- if ( MALI_FALSE == already_in_detach_function )
- {
- core->in_detach_function = MALI_TRUE;
- if ( NULL != job )
- {
- mali_core_job_set_run_time(job, time_now);
- core->current_job = NULL;
- }
- }
-
- if (JOB_STATUS_END_SEG_FAULT == end_status)
- {
- subsystem->reset_core( core, MALI_CORE_RESET_STYLE_HARD );
- }
- else
- {
- subsystem->reset_core( core, MALI_CORE_RESET_STYLE_RUNABLE );
- }
-
- if ( MALI_FALSE == already_in_detach_function )
- {
- if ( CORE_IDLE != core->state )
- {
- #if MALI_GPU_UTILIZATION
- mali_utilization_core_end(time_now);
- #endif
- mali_core_subsystem_move_core_set_idle(core);
- }
-
- core->in_detach_function = MALI_FALSE;
-
- if ( SUBSYSTEM_RESCHEDULE == reschedule )
- {
- mali_core_subsystem_schedule(subsystem);
- }
- if ( NULL != job )
- {
- core->subsystem->return_job_to_user(job, end_status);
- }
- }
-}
-
-#if USING_MMU
-/* This function intentionally does not release the semaphore. You must run
- stop_bus_for_all_cores(), reset_all_cores_on_mmu() and continue_job_handling()
- after calling this function, and then call unlock_subsystem() to release the
- semaphore. */
-
-static void lock_subsystem(struct mali_core_subsystem * subsys)
-{
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
-}
-
-/* You must run lock_subsystem() before entering this function, to ensure that
- the subsystem mutex is held.
- Later, unlock_subsystem() can be called to release the mutex.
-
- This function only stops cores behind the given MMU, unless "mmu" is NULL, in
- which case all cores are stopped.
-*/
-static void stop_bus_for_all_cores_on_mmu(struct mali_core_subsystem * subsys, void* mmu)
-{
- u32 i;
-
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
- MALI_DEBUG_PRINT(2,("Handling: bus stop %s\n", subsys->name ));
- for(i=0 ; i < subsys->number_of_cores ; ++i)
- {
- mali_core_renderunit * core;
- core = mali_core_renderunit_get_mali_core_nr(subsys,i);
-
- /* We stop only cores behind the given MMU, unless MMU is NULL */
- if ( (NULL!=mmu) && (core->mmu != mmu) ) continue;
-
- if ( CORE_IDLE != core->state )
- {
- MALI_DEBUG_PRINT(4, ("Stopping bus on core %s\n", core->description));
- mali_core_renderunit_stop_bus(core);
- core->error_recovery = MALI_TRUE;
- }
- else
- {
- MALI_DEBUG_PRINT(4,("Core: not active %s\n", core->description ));
- }
- }
- /* Mutex is still being held, to prevent things to happen while we do cleanup */
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
-}
-
-/* You must run lock_subsystem() before entering this function, to ensure that
- the subsystem mutex is held.
- Later, unlock_subsystem() can be called to release the mutex.
-
- This function only resets cores behind the given MMU, unless "mmu" is NULL, in
- which case all cores are reset.
-*/
-static void reset_all_cores_on_mmu(struct mali_core_subsystem * subsys, void* mmu)
-{
- u32 i;
-
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
- MALI_DEBUG_PRINT(3, ("Handling: reset cores from mmu: 0x%x on %s\n", mmu, subsys->name ));
- for(i=0 ; i < subsys->number_of_cores ; ++i)
- {
- mali_core_renderunit * core;
- core = mali_core_renderunit_get_mali_core_nr(subsys,i);
-
- /* We reset only cores behind the given MMU, unless MMU is NULL */
- if ( (NULL!=mmu) && (core->mmu != mmu) ) continue;
-
- if ( CORE_IDLE != core->state )
- {
- MALI_DEBUG_PRINT(4, ("Abort and reset core: %s\n", core->description ));
- mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_WAIT, JOB_STATUS_END_SEG_FAULT);
- }
- else
- {
- MALI_DEBUG_PRINT(4, ("Core: not active %s\n", core->description ));
- }
- }
- MALI_DEBUG_PRINT(4, ("Handling: done %s\n", subsys->name ));
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
-}
-
-/* You must run lock_subsystem() before entering this function, to ensure that
- the subsystem mutex is held.
- Later, unlock_subsystem() can be called to release the mutex. */
-static void continue_job_handling(struct mali_core_subsystem * subsys)
-{
- u32 i, j;
-
- MALI_DEBUG_PRINT(3, ("Handling: Continue: %s\n", subsys->name ));
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
-
-
- for(i=0 ; i < subsys->number_of_cores ; ++i)
- {
- mali_core_renderunit * core;
- core = mali_core_renderunit_get_mali_core_nr(subsys,i);
- core->error_recovery = MALI_FALSE;
- }
-
- i = subsys->number_of_cores;
- j = subsys->awaiting_sessions_sum_all_priorities;
-
- /* Schedule MIN(nr_waiting_jobs , number of cores) times */
- while( i-- && j--)
- {
- mali_core_subsystem_schedule(subsys);
- }
- MALI_DEBUG_PRINT(4, ("Handling: done %s\n", subsys->name ));
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
-}
-
-/* Unlock the subsystem. */
-static void unlock_subsystem(struct mali_core_subsystem * subsys)
-{
- MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
-}
-
-void mali_core_subsystem_broadcast_notification(struct mali_core_subsystem * subsys, mali_core_notification_message message, u32 data)
-{
- void * mmu;
- mmu = (void*) data;
-
- switch(message)
- {
- case MMU_KILL_STEP0_LOCK_SUBSYSTEM:
- break;
- case MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES:
- stop_bus_for_all_cores_on_mmu(subsys, mmu);
- break;
- case MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS:
- reset_all_cores_on_mmu(subsys, mmu );
- break;
- case MMU_KILL_STEP3_CONTINUE_JOB_HANDLING:
- continue_job_handling(subsys);
- break;
- case MMU_KILL_STEP4_UNLOCK_SUBSYSTEM:
- break;
-
- default:
- MALI_PRINT_ERROR(("Illegal message: 0x%x, data: 0x%x\n", (u32)message, data));
- break;
- }
-}
-#endif /* USING_MMU */
-
-void job_watchdog_set(mali_core_job * job, u32 watchdog_msecs)
-{
- if (watchdog_msecs == 0) job->watchdog_msecs = mali_max_job_runtime; /* use the default */
- else if (watchdog_msecs > WATCHDOG_MSECS_MAX) job->watchdog_msecs = WATCHDOG_MSECS_MAX; /* no larger than max */
- else if (watchdog_msecs < WATCHDOG_MSECS_MIN) job->watchdog_msecs = WATCHDOG_MSECS_MIN; /* not below min */
- else job->watchdog_msecs = watchdog_msecs;
-}
-
-u32 mali_core_hang_check_timeout_get(void)
-{
- /* check the value. The user might have set the value outside the allowed range */
- if (mali_hang_check_interval > HANG_CHECK_MSECS_MAX) mali_hang_check_interval = HANG_CHECK_MSECS_MAX; /* cap to max */
- else if (mali_hang_check_interval < HANG_CHECK_MSECS_MIN) mali_hang_check_interval = HANG_CHECK_MSECS_MIN; /* cap to min */
-
- /* return the active value */
- return mali_hang_check_interval;
-}
-
-static _mali_osk_errcode_t mali_core_irq_handler_upper_half (void * data)
-{
- mali_core_renderunit *core;
- u32 has_pending_irq;
-
- core = (mali_core_renderunit * )data;
-
- if(core && (CORE_OFF == core->state))
- {
- MALI_SUCCESS;
- }
-
- if ( (NULL == core) ||
- (NULL == core->subsystem) ||
- (NULL == core->subsystem->irq_handler_upper_half) )
- {
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
- MALI_CHECK_CORE(core);
- MALI_CHECK_SUBSYSTEM(core->subsystem);
-
- has_pending_irq = core->subsystem->irq_handler_upper_half(core);
-
- if ( has_pending_irq )
- {
- _mali_osk_irq_schedulework( core->irq ) ;
- MALI_SUCCESS;
- }
-
- if (mali_benchmark) MALI_SUCCESS;
-
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
-}
-
-static void mali_core_irq_handler_bottom_half ( void *data )
-{
- mali_core_renderunit *core;
- mali_core_subsystem* subsystem;
-
- mali_subsystem_job_end_code job_status;
-
- core = (mali_core_renderunit * )data;
-
- MALI_CHECK_CORE(core);
- subsystem = core->subsystem;
- MALI_CHECK_SUBSYSTEM(subsystem);
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
- if ( CORE_IDLE == core->state || CORE_OFF == core->state ) goto end_function;
-
- MALI_DEBUG_PRINT(5, ("IRQ: handling irq from core %s\n", core->description )) ;
-
- _mali_osk_cache_flushall();
-
- /* This function must also update the job status flag */
- job_status = subsystem->irq_handler_bottom_half( core );
-
- /* Retval is nonzero if the job is finished. */
- if ( JOB_STATUS_CONTINUE_RUN != job_status )
- {
- mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, job_status);
- }
- else
- {
- switch ( core->state )
- {
- case CORE_WATCHDOG_TIMEOUT:
- MALI_DEBUG_PRINT(2, ("Watchdog SW Timeout of job from core: %s\n", core->description ));
- mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_TIMEOUT_SW );
- break;
-
- case CORE_POLL:
- MALI_DEBUG_PRINT(5, ("Poll core: %s\n", core->description )) ;
- core->state = CORE_WORKING;
- _mali_osk_timer_add( core->timer, 1);
- break;
-
- default:
- MALI_DEBUG_PRINT(4, ("IRQ: The job on the core continue to run: %s\n", core->description )) ;
- break;
- }
- }
-end_function:
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
-}
-
-void subsystem_flush_mapped_mem_cache(void)
-{
- _mali_osk_cache_flushall();
- _mali_osk_mem_barrier();
-}
-
-#if USING_MALI_PMM
-
-_mali_osk_errcode_t mali_core_subsystem_signal_power_down(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool immediate_only)
-{
- mali_core_renderunit * core = NULL;
-
- MALI_CHECK_SUBSYSTEM(subsys);
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
-
- /* It is possible that this signal funciton can be called during a driver exit,
- * and so the requested core may now be destroyed. (This is due to us not having
- * the subsys lock before signalling power down).
- * mali_core_renderunit_get_mali_core_nr() will report a Mali ERR because
- * the core number is out of range (which is a valid error in other cases).
- * So instead we check here (now that we have the subsys lock) and let the
- * caller cope with the core get failure and check that the core has
- * been unregistered in the PMM as part of its destruction.
- */
- if ( subsys->number_of_cores > mali_core_nr )
- {
- core = mali_core_renderunit_get_mali_core_nr(subsys, mali_core_nr);
- }
-
- if ( NULL == core )
- {
- /* Couldn't find the core */
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_DEBUG_PRINT( 1, ("Core: Failed to find core to power down\n") );
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- else if ( core->state != CORE_IDLE )
- {
- /* When powering down we either set a pending power down flag here so we
- * can power down cleanly after the job completes or we don't set the
- * flag if we have been asked to only do a power down right now
- * In either case, return that the core is busy
- */
- if ( !immediate_only ) core->pend_power_down = MALI_TRUE;
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_DEBUG_PRINT( 5, ("Core: No idle core to power down\n") );
- MALI_ERROR(_MALI_OSK_ERR_BUSY);
- }
-
- /* Shouldn't have a pending power down flag set */
- MALI_DEBUG_ASSERT( !core->pend_power_down );
-
- /* Move core to off queue */
- mali_core_subsystem_move_core_set_off(core);
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
-
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool queue_only)
-{
- mali_core_renderunit * core;
-
- MALI_CHECK_SUBSYSTEM(subsys);
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
-
- core = mali_core_renderunit_get_mali_core_nr(subsys, mali_core_nr);
-
- if( core == NULL )
- {
- /* Couldn't find the core */
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_DEBUG_PRINT( 1, ("Core: Failed to find core to power up\n") );
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
- else if( core->state != CORE_OFF )
- {
- /* This will usually happen because we are trying to cancel a pending power down */
- core->pend_power_down = MALI_FALSE;
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
- MALI_DEBUG_PRINT( 1, ("Core: No powered off core to power up (cancelled power down?)\n") );
- MALI_ERROR(_MALI_OSK_ERR_BUSY);
- }
-
- /* Shouldn't have a pending power down set */
- MALI_DEBUG_ASSERT( !core->pend_power_down );
-
- /* Move core to idle queue */
- mali_core_subsystem_move_core_set_idle(core);
-
- if( !queue_only )
- {
- /* Reset MMU & core - core must be idle to allow this */
-#if USING_MMU
- if ( NULL!=core->mmu )
- {
-#if defined(USING_MALI200)
- if (core->pmm_id != MALI_PMM_CORE_PP0)
- {
-#endif
- mali_kernel_mmu_reset(core->mmu);
-#if defined(USING_MALI200)
- }
-#endif
-
- }
-#endif /* USING_MMU */
- subsys->reset_core( core, MALI_CORE_RESET_STYLE_RUNABLE );
- }
-
- /* Need to schedule work to start on this core */
- mali_core_subsystem_schedule(subsys);
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
-
- MALI_SUCCESS;
-}
-
-#endif /* USING_MALI_PMM */
-
-#if MALI_STATE_TRACKING
-u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size)
-{
- u32 i, len = 0;
- mali_core_renderunit *core;
- mali_core_renderunit *tmp_core;
-
- mali_core_session* session;
- mali_core_session* tmp_session;
-
- if (0 >= size)
- {
- return 0;
- }
-
- MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
-
- len += _mali_osk_snprintf(buf + len, size - len, "Subsystem:\n");
- len += _mali_osk_snprintf(buf + len, size - len, " Name: %s\n", subsystem->name);
-
- for (i = 0; i < subsystem->number_of_cores; i++)
- {
- len += _mali_osk_snprintf(buf + len, size - len, " Core: #%u\n",
- subsystem->mali_core_array[i]->core_number);
- len += _mali_osk_snprintf(buf + len, size - len, " Description: %s\n",
- subsystem->mali_core_array[i]->description);
- switch(subsystem->mali_core_array[i]->state)
- {
- case CORE_IDLE:
- len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_IDLE\n");
- break;
- case CORE_WORKING:
- len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WORKING\n");
- break;
- case CORE_WATCHDOG_TIMEOUT:
- len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WATCHDOG_TIMEOUT\n");
- break;
- case CORE_POLL:
- len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_POLL\n");
- break;
- case CORE_HANG_CHECK_TIMEOUT:
- len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_HANG_CHECK_TIMEOUT\n");
- break;
- case CORE_OFF:
- len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_OFF\n");
- break;
- default:
- len += _mali_osk_snprintf(buf + len, size - len, " State: Unknown (0x%X)\n",
- subsystem->mali_core_array[i]->state);
- break;
- }
- len += _mali_osk_snprintf(buf + len, size - len, " Current job: 0x%X\n",
- (u32)(subsystem->mali_core_array[i]->current_job));
- if (subsystem->mali_core_array[i]->current_job)
- {
- u64 time_used_nano_seconds;
- u32 time_used_micro_seconds;
- u64 time_now = _mali_osk_time_get_ns();
-
- time_used_nano_seconds = time_now - subsystem->mali_core_array[i]->current_job->start_time;
- time_used_micro_seconds = ((u32)(time_used_nano_seconds)) / 1000;
-
- len += _mali_osk_snprintf(buf + len, size - len, " Current job session: 0x%X\n",
- subsystem->mali_core_array[i]->current_job->session);
- len += _mali_osk_snprintf(buf + len, size - len, " Current job number: %d\n",
- subsystem->mali_core_array[i]->current_job->job_nr);
- len += _mali_osk_snprintf(buf + len, size - len, " Current job render_time micro seconds: %d\n",
- time_used_micro_seconds );
- len += _mali_osk_snprintf(buf + len, size - len, " Current job start time micro seconds: %d\n",
- (u32) (subsystem->mali_core_array[i]->current_job->start_time >>10) );
- }
- len += _mali_osk_snprintf(buf + len, size - len, " Core version: 0x%X\n",
- subsystem->mali_core_array[i]->core_version);
-#if USING_MALI_PMM
- len += _mali_osk_snprintf(buf + len, size - len, " PMM id: 0x%X\n",
- subsystem->mali_core_array[i]->pmm_id);
- len += _mali_osk_snprintf(buf + len, size - len, " Power down requested: %s\n",
- subsystem->mali_core_array[i]->pend_power_down ? "TRUE" : "FALSE");
-#endif
- }
-
- len += _mali_osk_snprintf(buf + len, size - len, " Cores on idle list:\n");
- _MALI_OSK_LIST_FOREACHENTRY(core, tmp_core, &subsystem->renderunit_idle_head, mali_core_renderunit, list)
- {
- len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number);
- }
-
- len += _mali_osk_snprintf(buf + len, size - len, " Cores on off list:\n");
- _MALI_OSK_LIST_FOREACHENTRY(core, tmp_core, &subsystem->renderunit_off_head, mali_core_renderunit, list)
- {
- len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number);
- }
-
- len += _mali_osk_snprintf(buf + len, size - len, " Connected sessions:\n");
- _MALI_OSK_LIST_FOREACHENTRY(session, tmp_session, &subsystem->all_sessions_head, mali_core_session, all_sessions_list)
- {
- len += _mali_osk_snprintf(buf + len, size - len,
- " Session 0x%X:\n", (u32)session);
- len += _mali_osk_snprintf(buf + len, size - len,
- " Queue depth: %u\n", mali_job_queue_size(session));
- len += _mali_osk_snprintf(buf + len, size - len,
- " First waiting job: 0x%p\n", session->queue[session->queue_head]);
- len += _mali_osk_snprintf(buf + len, size - len, " Notification queue: %s\n",
- _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY");
- len += _mali_osk_snprintf(buf + len, size - len,
- " Jobs received:%4d\n", _mali_osk_atomic_read(&session->jobs_received));
- len += _mali_osk_snprintf(buf + len, size - len,
- " Jobs started :%4d\n", _mali_osk_atomic_read(&session->jobs_started));
- len += _mali_osk_snprintf(buf + len, size - len,
- " Jobs ended :%4d\n", _mali_osk_atomic_read(&session->jobs_ended));
- len += _mali_osk_snprintf(buf + len, size - len,
- " Jobs returned:%4d\n", _mali_osk_atomic_read(&session->jobs_returned));
- len += _mali_osk_snprintf(buf + len, size - len, " PID: %d\n", session->pid);
- }
-
- len += _mali_osk_snprintf(buf + len, size - len, " Waiting sessions sum all priorities: %u\n",
- subsystem->awaiting_sessions_sum_all_priorities);
- for (i = 0; i < PRIORITY_LEVELS; i++)
- {
- len += _mali_osk_snprintf(buf + len, size - len, " Waiting sessions with priority %u:\n", i);
- _MALI_OSK_LIST_FOREACHENTRY(session, tmp_session, &subsystem->awaiting_sessions_head[i],
- mali_core_session, awaiting_sessions_list)
- {
- len += _mali_osk_snprintf(buf + len, size - len, " Session 0x%X:\n", (u32)session);
- len += _mali_osk_snprintf(buf + len, size - len, " Waiting job: 0x%X\n",
- (u32)session->queue[session->queue_head]);
- len += _mali_osk_snprintf(buf + len, size - len, " Notification queue: %s\n",
- _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY");
- }
- }
-
- MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem );
- return len;
-}
-#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h b/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h
deleted file mode 100644
index 5fbe686..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h
+++ /dev/null
@@ -1,565 +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 __MALI_RENDERCORE_H__
-#define __MALI_RENDERCORE_H__
-
-#include "mali_osk.h"
-#include "mali_kernel_common.h"
-#include "mali_kernel_subsystem.h"
-
-#define PRIORITY_LEVELS 3
-#define PRIORITY_MAX 0
-#define PRIORITY_MIN (PRIORITY_MAX+PRIORITY_LEVELS-1)
-
-/* This file contains what we need in kernel for all core types. */
-
-typedef enum
-{
- CORE_IDLE, /**< Core is ready for a new job */
- CORE_WORKING, /**< Core is working on a job */
- CORE_WATCHDOG_TIMEOUT, /**< Core is working but it has timed out */
- CORE_POLL, /**< Poll timer triggered, pending handling */
- CORE_HANG_CHECK_TIMEOUT,/**< Timeout for hang detection */
- CORE_OFF /**< Core is powered off */
-} mali_core_status;
-
-typedef enum
-{
- SUBSYSTEM_RESCHEDULE,
- SUBSYSTEM_WAIT
-} mali_subsystem_reschedule_option;
-
-typedef enum
-{
- MALI_CORE_RESET_STYLE_RUNABLE,
- MALI_CORE_RESET_STYLE_DISABLE,
- MALI_CORE_RESET_STYLE_HARD
-} mali_core_reset_style;
-
-typedef enum
-{
- JOB_STATUS_CONTINUE_RUN = 0x01,
- JOB_STATUS_END_SUCCESS = 1<<(16+0),
- JOB_STATUS_END_OOM = 1<<(16+1),
- JOB_STATUS_END_ABORT = 1<<(16+2),
- JOB_STATUS_END_TIMEOUT_SW = 1<<(16+3),
- JOB_STATUS_END_HANG = 1<<(16+4),
- JOB_STATUS_END_SEG_FAULT = 1<<(16+5),
- JOB_STATUS_END_ILLEGAL_JOB = 1<<(16+6),
- JOB_STATUS_END_UNKNOWN_ERR = 1<<(16+7),
- JOB_STATUS_END_SHUTDOWN = 1<<(16+8),
- JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9)
-} mali_subsystem_job_end_code;
-
-
-struct mali_core_job;
-struct mali_core_subsystem;
-struct mali_core_renderunit;
-struct mali_core_session;
-
-/* We have one of these subsystems for each core type */
-typedef struct mali_core_subsystem
-{
- struct mali_core_renderunit ** mali_core_array; /* An array of all cores of this type */
- u32 number_of_cores; /* Number of cores in this list */
-
- _mali_core_type core_type;
-
- u32 magic_nr;
-
- _mali_osk_list_t renderunit_idle_head; /* Idle cores of this type */
- _mali_osk_list_t renderunit_off_head; /* Powered off cores of this type */
-
- /* Linked list for each priority of sessions with a job ready for scheduelling */
- _mali_osk_list_t awaiting_sessions_head[PRIORITY_LEVELS];
- u32 awaiting_sessions_sum_all_priorities;
-
- /* Linked list of all sessions connected to this coretype */
- _mali_osk_list_t all_sessions_head;
-
- /* Linked list of all sessions connected to this coretype */
- struct _mali_osk_notification_queue_t * notification_queue;
-
- const char * name;
- mali_kernel_subsystem_identifier id;
-
- /**** Functions registered for this core type. Set during mali_core_init ******/
- /* Start this job on this core. Return MALI_TRUE if the job was started. */
- _mali_osk_errcode_t (*start_job)(struct mali_core_job * job, struct mali_core_renderunit * core);
-
- /* Check if given core has an interrupt pending. Return MALI_TRUE and set mask to 0 if pending */
- u32 (*irq_handler_upper_half)(struct mali_core_renderunit * core);
-
- /* This function should check if the interrupt indicates that job was finished.
- If so it should update the job-struct, reset the core registers, and return MALI_TRUE, .
- If the job is still working after this function it should return MALI_FALSE.
- The function must also enable the bits in the interrupt mask for the core.
- Called by the bottom half interrupt function. */
- int (*irq_handler_bottom_half)(struct mali_core_renderunit* core);
-
- /* This function is called from the ioctl function and should return a mali_core_job pointer
- to a created mali_core_job object with the data given from userspace */
- _mali_osk_errcode_t (*get_new_job_from_user)(struct mali_core_session * session, void * argument);
-
- _mali_osk_errcode_t (*suspend_response)(struct mali_core_session * session, void * argument);
-
- /* This function is called from the ioctl function and should write the necessary data
- to userspace telling which job was finished and the status and debuginfo for this job.
- The function must also free and cleanup the input job object. */
- void (*return_job_to_user)(struct mali_core_job * job, mali_subsystem_job_end_code end_status);
-
- /* Is called when a subsystem shuts down. This function needs to
- release internal pointers in the core struct, and free the
- core struct before returning.
- It is not allowed to write to any registers, since this
- unmapping is already done. */
- void (*renderunit_delete)(struct mali_core_renderunit * core);
-
- /* Is called when we want to abort a job that is running on the core.
- This is done if program exits while core is running */
- void (*reset_core)(struct mali_core_renderunit * core, mali_core_reset_style style);
-
- /* Is called when the rendercore wants the core to give an interrupt */
- void (*probe_core_irq_trigger)(struct mali_core_renderunit* core);
-
- /* Is called when the irq probe wants the core to acknowledge an interrupt from the hw */
- _mali_osk_errcode_t (*probe_core_irq_acknowledge)(struct mali_core_renderunit* core);
-
- /* Called when the rendercore want to issue a bus stop request to a core */
- void (*stop_bus)(struct mali_core_renderunit* core);
-} mali_core_subsystem;
-
-
-/* Per core data. This must be embedded into each core type internal core info. */
-typedef struct mali_core_renderunit
-{
- struct mali_core_subsystem * subsystem; /* The core belongs to this subsystem */
- _mali_osk_list_t list; /* Is always in subsystem->idle_list OR session->renderunits_working */
- mali_core_status state;
- mali_bool error_recovery; /* Indicates if the core is waiting for external help to recover (typically the MMU) */
- mali_bool in_detach_function;
- struct mali_core_job * current_job; /* Current job being processed on this core ||NULL */
- u32 magic_nr;
- _mali_osk_timer_t * timer;
- _mali_osk_timer_t * timer_hang_detection;
-
- mali_io_address registers_mapped; /* IO-mapped pointer to registers */
- u32 registers_base_addr; /* Base addres of the registers */
- u32 size; /* The size of registers_mapped */
- const char * description; /* Description of this core. */
- u32 irq_nr; /* The IRQ nr for this core */
- u32 core_version;
-#if USING_MMU
- u32 mmu_id;
- void * mmu; /* The MMU this rendercore is behind.*/
-#endif
-#if USING_MALI_PMM
- mali_pmm_core_id pmm_id; /* The PMM core id */
- mali_bool pend_power_down; /* Power down is requested */
-#endif
-
- u32 core_number; /* 0 for first detected core of this type, 1 for second and so on */
-
- _mali_osk_irq_t *irq;
-} mali_core_renderunit;
-
-
-#define MALI_JOB_QUEUE_SIZE 8
-/* Per open FILE data. */
-/* You must held subsystem->mutex before any transactions to this datatype. */
-typedef struct mali_core_session
-{
- struct mali_core_subsystem * subsystem; /* The session belongs to this subsystem */
- _mali_osk_list_t renderunits_working_head; /* List of renderunits working for this session */
- struct mali_core_job *queue[MALI_JOB_QUEUE_SIZE]; /* The next job from this session to run */
- int queue_head;
- int queue_tail;
- int queue_size;
-
- _mali_osk_list_t awaiting_sessions_list; /* Linked list of sessions with jobs, for each priority */
- _mali_osk_list_t all_sessions_list; /* Linked list of all sessions on the system. */
-
- _mali_osk_notification_queue_t * notification_queue; /* Messages back to Base in userspace*/
-#if USING_MMU
- struct mali_session_data * mmu_session; /* The session associated with the MMU page tables for this core */
-#endif
- u32 magic_nr;
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_t jobs_received;
- _mali_osk_atomic_t jobs_started;
- _mali_osk_atomic_t jobs_ended;
- _mali_osk_atomic_t jobs_returned;
- u32 pid;
-#endif
-} mali_core_session;
-
-/* This must be embedded into a specific mali_core_job struct */
-/* use this macro to get spesific mali_core_job: container_of(ptr, type, member)*/
-typedef struct mali_core_job
-{
- _mali_osk_list_t list; /* Linked list of jobs. Used by struct mali_core_session */
- struct mali_core_session *session;
- u32 magic_nr;
- u32 priority;
- u32 watchdog_msecs;
- u32 render_time_usecs ;
- u64 start_time;
- unsigned long watchdog_jiffies;
- u32 abort_id;
- u32 job_nr;
- _mali_uk_start_job_flags flags;
-} mali_core_job;
-
-MALI_STATIC_INLINE mali_bool mali_job_queue_empty(mali_core_session *session)
-{
- if (0 == session->queue_size)
- {
- return MALI_TRUE;
- }
- return MALI_FALSE;
-}
-
-MALI_STATIC_INLINE mali_bool mali_job_queue_full(mali_core_session *session)
-{
- if (MALI_JOB_QUEUE_SIZE == session->queue_size)
- {
- return MALI_TRUE;
- }
- return MALI_FALSE;
-}
-
-
-MALI_STATIC_INLINE _mali_osk_errcode_t mali_job_queue_add_job(mali_core_session *session, struct mali_core_job *job)
-{
- if (mali_job_queue_full(session))
- {
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- session->queue[session->queue_tail] = job;
- session->queue_tail = (session->queue_tail + 1) % MALI_JOB_QUEUE_SIZE;
- session->queue_size++;
-
- MALI_SUCCESS;
-}
-
-MALI_STATIC_INLINE struct mali_core_job *mali_job_queue_get_job(mali_core_session *session)
-{
- struct mali_core_job *job;
- MALI_DEBUG_ASSERT(!mali_job_queue_empty(session));
-
- job = session->queue[session->queue_head];
-
- MALI_DEBUG_ASSERT_POINTER(job);
-
- session->queue[session->queue_head] = NULL;
- session->queue_head = (session->queue_head + 1) % MALI_JOB_QUEUE_SIZE;
- session->queue_size--;
-
- return job;
-}
-
-MALI_STATIC_INLINE u32 mali_job_queue_size(mali_core_session *session)
-{
- return (u32)(session->queue_size);
-}
-
-MALI_STATIC_INLINE struct mali_core_job *mali_job_queue_abort_job(mali_core_session *session, u32 abort_id)
-{
- int i;
- int n;
- struct mali_core_job *job = NULL;
-
- for (i = session->queue_head, n = session->queue_size; n > 0; n--, i = (i+1)%MALI_JOB_QUEUE_SIZE)
- {
- if (session->queue[i]->abort_id == abort_id)
- {
- /* Remove job from queue */
- job = session->queue[i];
- session->queue[i] = NULL;
-
- session->queue_size -= 1;
- n--;
- break;
- }
- }
- if (NULL == job)
- {
- return NULL;
- }
-
- /* Rearrange queue */
- while (n > 0)
- {
- int next = (i + 1) % MALI_JOB_QUEUE_SIZE;
- session->queue[i] = session->queue[next];
- i = next;
- n--;
- }
- session->queue_tail = i;
-
- return job;
-}
-
-
-/*
- * The rendercode subsystem is included in the subsystems[] array.
- */
-extern struct mali_kernel_subsystem mali_subsystem_rendercore;
-
-void subsystem_flush_mapped_mem_cache(void);
-
-
-#define SUBSYSTEM_MAGIC_NR 0xdeadbeef
-#define CORE_MAGIC_NR 0xcafebabe
-#define SESSION_MAGIC_NR 0xbabe1234
-#define JOB_MAGIC_NR 0x0123abcd
-
-
-#define MALI_CHECK_SUBSYSTEM(subsystem)\
- do { \
- if ( SUBSYSTEM_MAGIC_NR != subsystem->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
- } while (0)
-
-#define MALI_CHECK_CORE(CORE)\
- do { \
- if ( CORE_MAGIC_NR != CORE->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
-} while (0)
-
-#define MALI_CHECK_SESSION(SESSION)\
- do { \
- if ( SESSION_MAGIC_NR != SESSION->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
-} while (0)
-
-#define MALI_CHECK_JOB(JOB)\
- do { \
- if ( JOB_MAGIC_NR != JOB->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
-} while (0)
-
-
-/* Check if job_a has higher priority than job_b */
-MALI_STATIC_INLINE int job_has_higher_priority(mali_core_job * job_a, mali_core_job * job_b)
-{
- /* The lowest number has the highest priority */
- return (int) (job_a->priority < job_b->priority);
-}
-
-MALI_STATIC_INLINE void job_priority_set(mali_core_job * job, u32 priority)
-{
- if (priority > PRIORITY_MIN) job->priority = PRIORITY_MIN;
- else job->priority = priority;
-}
-
-void job_watchdog_set(mali_core_job * job, u32 watchdog_msecs);
-
-/* For use by const default register settings (e.g. set these after reset) */
-typedef struct register_address_and_value
-{
- u32 address;
- u32 value;
-} register_address_and_value ;
-
-
-/* For use by dynamic default register settings (e.g. set these after reset) */
-typedef struct register_address_and_value_list
-{
- _mali_osk_list_t list;
- register_address_and_value item;
-} register_address_and_value_list ;
-
-/* Used if the user wants to set a continious block of registers */
-typedef struct register_array_user
-{
- u32 entries_in_array;
- u32 start_address;
- void __user * reg_array;
-}register_array_user;
-
-
-#define MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys) \
- do { \
- MALI_DEBUG_PRINT(5, ("MUTEX: GRAB %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
- _mali_osk_lock_wait( rendercores_global_mutex, _MALI_OSK_LOCKMODE_RW); \
- MALI_DEBUG_PRINT(5, ("MUTEX: GRABBED %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
- if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
- rendercores_global_mutex_is_held = 1; \
- rendercores_global_mutex_owner = _mali_osk_get_tid(); \
- } while (0) ;
-
-#define MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys) \
- do { \
- MALI_DEBUG_PRINT(5, ("MUTEX: RELEASE %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
- rendercores_global_mutex_is_held = 0; \
- rendercores_global_mutex_owner = 0; \
- if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
- _mali_osk_lock_signal( rendercores_global_mutex, _MALI_OSK_LOCKMODE_RW); \
- MALI_DEBUG_PRINT(5, ("MUTEX: RELEASED %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
- if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
- } while (0) ;
-
-
-#define MALI_ASSERT_MUTEX_IS_GRABBED(input_pointer)\
- do { \
- if ( 0 == rendercores_global_mutex_is_held ) MALI_PRINT_ERROR(("ASSERT MUTEX SHOULD BE GRABBED"));\
- if ( SUBSYSTEM_MAGIC_NR != input_pointer->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
- if ( rendercores_global_mutex_owner != _mali_osk_get_tid() ) MALI_PRINT_ERROR(("Owner mismatch"));\
- } while (0)
-
-MALI_STATIC_INLINE _mali_osk_errcode_t mali_core_renderunit_register_rw_check(mali_core_renderunit *core,
- u32 relative_address)
-{
-#if USING_MALI_PMM
- if( core->state == CORE_OFF )
- {
- MALI_PRINT_ERROR(("Core is OFF during access: Core: %s Addr: 0x%04X\n",
- core->description,relative_address));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-#endif
-
- MALI_DEBUG_ASSERT((relative_address & 0x03) == 0);
-
- if (mali_benchmark) MALI_ERROR(_MALI_OSK_ERR_FAULT);
-
- MALI_DEBUG_CODE(if (relative_address >= core->size)
- {
- MALI_PRINT_ERROR(("Trying to access illegal register: 0x%04x in core: %s",
- relative_address, core->description));
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- })
-
- MALI_SUCCESS;
-}
-
-
-MALI_STATIC_INLINE u32 mali_core_renderunit_register_read(struct mali_core_renderunit *core, u32 relative_address)
-{
- u32 read_val;
-
- if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address))
- return 0xDEADBEEF;
-
- read_val = _mali_osk_mem_ioread32(core->registers_mapped, relative_address);
-
- MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read: Core:%s Addr:0x%04X Val:0x%08x\n",
- core->description,relative_address, read_val));
-
- return read_val;
-}
-
-MALI_STATIC_INLINE void mali_core_renderunit_register_read_array(struct mali_core_renderunit *core,
- u32 relative_address,
- u32 * result_array,
- u32 nr_of_regs)
-{
- /* NOTE Do not use burst reads against the registers */
- u32 i;
-
- MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read_array: Core:%s Addr:0x%04X Nr_regs: %u\n",
- core->description,relative_address, nr_of_regs));
-
- for(i=0; i<nr_of_regs; ++i)
- {
- result_array[i] = mali_core_renderunit_register_read(core, relative_address + i*4);
- }
-}
-
-/*
- * Write to a core register, and bypass implied memory barriers.
- *
- * On some systems, _mali_osk_mem_iowrite32() implies a memory barrier. This
- * can be a performance problem when doing many writes in sequence.
- *
- * When using this function, ensure proper barriers are put in palce. Most
- * likely a _mali_osk_mem_barrier() is needed after all related writes are
- * completed.
- *
- */
-MALI_STATIC_INLINE void mali_core_renderunit_register_write_relaxed(mali_core_renderunit *core,
- u32 relative_address,
- u32 new_val)
-{
- if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address))
- return;
-
- MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write_relaxed: Core:%s Addr:0x%04X Val:0x%08x\n",
- core->description,relative_address, new_val));
-
- _mali_osk_mem_iowrite32_relaxed(core->registers_mapped, relative_address, new_val);
-}
-
-MALI_STATIC_INLINE void mali_core_renderunit_register_write(struct mali_core_renderunit *core,
- u32 relative_address,
- u32 new_val)
-{
- MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write: Core:%s Addr:0x%04X Val:0x%08x\n",
- core->description,relative_address, new_val));
-
- if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address))
- return;
-
- _mali_osk_mem_iowrite32(core->registers_mapped, relative_address, new_val);
-}
-
-MALI_STATIC_INLINE void mali_core_renderunit_register_write_array(struct mali_core_renderunit *core,
- u32 relative_address,
- u32 * write_array,
- u32 nr_of_regs)
-{
- u32 i;
- MALI_DEBUG_PRINT(6, ("Core: renderunit_register_write_array: Core:%s Addr:0x%04X Nr_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++)
- {
- mali_core_renderunit_register_write_relaxed(core, relative_address + i*4, write_array[i]);
- }
-}
-
-_mali_osk_errcode_t mali_core_renderunit_init(struct mali_core_renderunit * core);
-void mali_core_renderunit_term(struct mali_core_renderunit * core);
-int mali_core_renderunit_map_registers(struct mali_core_renderunit *core);
-void mali_core_renderunit_unmap_registers(struct mali_core_renderunit *core);
-int mali_core_renderunit_irq_handler_add(struct mali_core_renderunit *core);
-mali_core_renderunit * mali_core_renderunit_get_mali_core_nr(mali_core_subsystem *subsys, u32 mali_core_nr);
-
-int mali_core_subsystem_init(struct mali_core_subsystem * new_subsys);
-#if USING_MMU
-void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys);
-#endif
-int mali_core_subsystem_register_renderunit(struct mali_core_subsystem * subsys, struct mali_core_renderunit * core);
-int mali_core_subsystem_system_info_fill(mali_core_subsystem* subsys, _mali_system_info* info);
-void mali_core_subsystem_cleanup(struct mali_core_subsystem * subsys);
-#if USING_MMU
-void mali_core_subsystem_broadcast_notification(struct mali_core_subsystem * subsys, mali_core_notification_message message, u32 data);
-#endif
-void mali_core_session_begin(mali_core_session *session);
-void mali_core_session_close(mali_core_session * session);
-int mali_core_session_add_job(mali_core_session * session, mali_core_job *job, mali_core_job **job_return);
-u32 mali_core_hang_check_timeout_get(void);
-
-_mali_osk_errcode_t mali_core_subsystem_ioctl_start_job(mali_core_session * session, void *job_data);
-_mali_osk_errcode_t mali_core_subsystem_ioctl_number_of_cores_get(mali_core_session * session, u32 *number_of_cores);
-_mali_osk_errcode_t mali_core_subsystem_ioctl_core_version_get(mali_core_session * session, _mali_core_version *version);
-_mali_osk_errcode_t mali_core_subsystem_ioctl_suspend_response(mali_core_session * session, void* argument);
-void mali_core_subsystem_ioctl_abort_job(mali_core_session * session, u32 id);
-
-#if USING_MALI_PMM
-_mali_osk_errcode_t mali_core_subsystem_signal_power_down(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool immediate_only);
-_mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool queue_only);
-#endif
-
-#if MALI_STATE_TRACKING
-u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size);
-#endif
-
-#endif /* __MALI_RENDERCORE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h b/drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h
deleted file mode 100644
index 8f05216..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h
+++ /dev/null
@@ -1,107 +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.
- */
-
-/**
- * @file mali_kernel_subsystem.h
- */
-
-#ifndef __MALI_KERNEL_SUBSYSTEM_H__
-#define __MALI_KERNEL_SUBSYSTEM_H__
-
-#include "mali_osk.h"
-#include "mali_uk_types.h"
-#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
-
-/* typedefs of the datatypes used in the hook functions */
-typedef void * mali_kernel_subsystem_session_slot;
-typedef int mali_kernel_subsystem_identifier;
-typedef _mali_osk_errcode_t (*mali_kernel_resource_registrator)(_mali_osk_resource_t *);
-
-/**
- * Broadcast notification messages
- */
-typedef enum mali_core_notification_message
-{
- MMU_KILL_STEP0_LOCK_SUBSYSTEM, /**< Request to lock subsystem */
- MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES, /**< Request to stop all buses */
- MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS, /**< Request kill all jobs, and not start more jobs */
- MMU_KILL_STEP3_CONTINUE_JOB_HANDLING, /**< Request to continue with new jobs on all cores */
- MMU_KILL_STEP4_UNLOCK_SUBSYSTEM /**< Request to unlock subsystem */
-} mali_core_notification_message;
-
-/**
- * A function pointer can be NULL if the subsystem isn't interested in the event.
- */
-typedef struct mali_kernel_subsystem
-{
- /* subsystem control */
- _mali_osk_errcode_t (*startup)(mali_kernel_subsystem_identifier id); /**< Called during module load or system startup*/
- void (*shutdown)(mali_kernel_subsystem_identifier id); /**< Called during module unload or system shutdown */
-
- /**
- * Called during module load or system startup.
- * Called when all subsystems have reported startup OK and all resources where successfully initialized
- */
- _mali_osk_errcode_t (*load_complete)(mali_kernel_subsystem_identifier id);
-
- /* per subsystem handlers */
- _mali_osk_errcode_t (*system_info_fill)(_mali_system_info* info); /**< Fill info into info struct. MUST allocate memory with kmalloc, since it's kfree'd */
-
- /* per session handlers */
- /**
- * Informs about a new session.
- * slot can be used to track per-session per-subsystem data.
- * queue can be used to send events to user space.
- * _mali_osk_errcode_t error return value.
- */
- _mali_osk_errcode_t (*session_begin)(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
- /**
- * Informs that a session is ending
- * slot was the same as given during session_begin
- */
- void (*session_end)(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
-
- /* Used by subsystems to send messages to each other. This is the receiving end */
- void (*broadcast_notification)(mali_core_notification_message message, u32 data);
-
-#if MALI_STATE_TRACKING
- /** Dump the current state of the subsystem */
- u32 (*dump_state)(char *buf, u32 size);
-#endif
-} mali_kernel_subsystem;
-
-/* functions used by the subsystems to interact with the core */
-/**
- * Register a resouce handler
- * @param type The resoruce type to register a handler for
- * @param handler Pointer to the function handling this resource
- * @return _MALI_OSK_ERR_OK on success. Otherwise, a suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t _mali_kernel_core_register_resource_handler(_mali_osk_resource_type_t type, mali_kernel_resource_registrator handler);
-
-/* function used to interact with other subsystems */
-/**
- * Broadcast a message
- * Sends a message to all subsystems which have registered a broadcast notification handler
- * @param message The message to send
- * @param data Message specific extra data
- */
-void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data);
-
-#if MALI_STATE_TRACKING
-/**
- * Tell all subsystems to dump their current state
- */
-u32 _mali_kernel_core_dump_state(char *buf, u32 size);
-#endif
-
-
-#endif /* __MALI_KERNEL_SUBSYSTEM_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c
index b43b872..a374dbf 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -27,7 +27,7 @@ static _mali_osk_timer_t *utilization_timer = NULL;
static mali_bool timer_running = MALI_FALSE;
-static void calculate_gpu_utilization(void *arg)
+static void calculate_gpu_utilization(void* arg)
{
u64 time_now;
u64 time_period;
@@ -39,7 +39,8 @@ static void calculate_gpu_utilization(void *arg)
_mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW);
- if (accumulated_work_time == 0 && work_start_time == 0) {
+ 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;
@@ -55,7 +56,8 @@ static void calculate_gpu_utilization(void *arg)
time_period = time_now - period_start_time;
/* If we are currently busy, update working period up to now */
- if (work_start_time != 0) {
+ if (work_start_time != 0)
+ {
accumulated_work_time += (time_now - work_start_time);
work_start_time = time_now;
}
@@ -79,10 +81,13 @@ static void calculate_gpu_utilization(void *arg)
* (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) {
+ if (period_normalized > 0x00FFFFFF)
+ {
/* The divisor is so big that it is safe to shift it down */
period_normalized >>= 8;
- } else {
+ }
+ else
+ {
/*
* The divisor is so small that we can shift up the dividend, without loosing any data.
* (dividend is always smaller than the divisor)
@@ -99,22 +104,25 @@ static void calculate_gpu_utilization(void *arg)
_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_SPINLOCK_IRQ|_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0 );
+ 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) {
+ if (NULL == utilization_timer)
+ {
_mali_osk_lock_term(time_data_lock);
return _MALI_OSK_ERR_FAULT;
}
@@ -125,7 +133,8 @@ _mali_osk_errcode_t mali_utilization_init(void)
void mali_utilization_suspend(void)
{
- if (NULL != utilization_timer) {
+ if (NULL != utilization_timer)
+ {
_mali_osk_timer_del(utilization_timer);
timer_running = MALI_FALSE;
}
@@ -133,7 +142,8 @@ void mali_utilization_suspend(void)
void mali_utilization_term(void)
{
- if (NULL != utilization_timer) {
+ if (NULL != utilization_timer)
+ {
_mali_osk_timer_del(utilization_timer);
timer_running = MALI_FALSE;
_mali_osk_timer_term(utilization_timer);
@@ -145,11 +155,10 @@ void mali_utilization_term(void)
_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) {
+ 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
@@ -167,27 +176,26 @@ void mali_utilization_core_start(u64 time_now)
}
work_start_time = time_now;
-
- if (timer_running != MALI_TRUE) {
+ 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_del(utilization_timer);
-
_mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT));
- } else {
+ }
+ 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) {
+ if (_mali_osk_atomic_dec_return(&num_running_cores) == 0)
+ {
/*
* No more cores are working, so accumulate the time we was busy.
*/
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h
index c779978..1f60517 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c
index dc39e01..63c9f5b 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 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.
@@ -10,39 +10,41 @@
#include "mali_kernel_common.h"
#include "mali_osk.h"
-#include "mali_osk_mali.h"
#include "mali_ukk.h"
-/*#include "mali_timestamp.h"*/
#if MALI_TIMELINE_PROFILING_ENABLED
-#include "mali_kernel_profiling.h"
+#include "mali_osk_profiling.h"
#endif
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args)
{
_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 */
-/* u64 ts = _mali_timestamp_get();
- */
#if MALI_TIMELINE_PROFILING_ENABLED
+ /*
+ * Manually generate user space events in kernel space.
+ * This saves user space from calling kernel space twice in this case.
+ * We just need to remember to add pid and tid manually.
+ */
if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT)
{
- _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SUSPEND |
- MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
- MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
- 0, 0, 0, 0, 0);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+ _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
}
- if ( event==_MALI_UK_VSYNC_EVENT_END_WAIT)
+ if (event==_MALI_UK_VSYNC_EVENT_END_WAIT)
{
- _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_RESUME |
- MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
- MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
- 0, 0, 0, 0, 0);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+ _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
}
#endif
+
MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));
MALI_SUCCESS;
}
diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.c b/drivers/media/video/samsung/mali/common/mali_l2_cache.c
new file mode 100644
index 0000000..aa5cc54
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_l2_cache.c
@@ -0,0 +1,398 @@
+/*
+ * 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_l2_cache.h"
+#include "mali_hw_core.h"
+#include "mali_pm.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.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_l2_cache_register {
+ MALI400_L2_CACHE_REGISTER_STATUS = 0x0008,
+ /*unused = 0x000C */
+ MALI400_L2_CACHE_REGISTER_COMMAND = 0x0010, /**< Misc cache commands, e.g. clear */
+ MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0014,
+ MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0018, /**< Limit of outstanding read requests */
+ MALI400_L2_CACHE_REGISTER_ENABLE = 0x001C, /**< Enable misc cache features */
+ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C,
+} mali_l2_cache_register;
+
+/**
+ * Mali L2 cache commands
+ * These are the commands that can be sent to the Mali L2 cache unit
+ */
+typedef enum mali_l2_cache_command
+{
+ MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */
+ /* Read HW TRM carefully before adding/using other commands than the clear above */
+} mali_l2_cache_command;
+
+/**
+ * Mali L2 cache commands
+ * These are the commands that can be sent to the Mali L2 cache unit
+ */
+typedef enum mali_l2_cache_enable
+{
+ MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */
+ MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */
+ MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */
+} mali_l2_cache_enable;
+
+/**
+ * Mali L2 cache status bits
+ */
+typedef enum mali_l2_cache_status
+{
+ MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */
+ 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 u32 mali_global_num_l2_cache_cores = 0;
+
+int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT;
+
+/* Local helper functions */
+static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val);
+
+
+struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource)
+{
+ struct mali_l2_cache_core *cache = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description));
+
+ if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES)
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n"));
+ return NULL;
+ }
+
+ cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core));
+ if (NULL != cache)
+ {
+ 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;
+ 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);
+ 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);
+ 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);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description));
+ }
+
+ _mali_osk_lock_term(cache->command_lock);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description));
+ }
+
+ mali_hw_core_delete(&cache->hw_core);
+ }
+
+ _mali_osk_free(cache);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n"));
+ }
+
+ return NULL;
+}
+
+void mali_l2_cache_delete(struct mali_l2_cache_core *cache)
+{
+ u32 i;
+
+ /* reset to defaults */
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT);
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT);
+
+ _mali_osk_lock_term(cache->counter_lock);
+ _mali_osk_lock_term(cache->command_lock);
+ mali_hw_core_delete(&cache->hw_core);
+
+ for (i = 0; i < mali_global_num_l2_cache_cores; i++)
+ {
+ if (mali_global_l2_cache_cores[i] == cache)
+ {
+ mali_global_l2_cache_cores[i] = NULL;
+ mali_global_num_l2_cache_cores--;
+ }
+ }
+
+ _mali_osk_free(cache);
+}
+
+u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache)
+{
+ return cache->core_id;
+}
+
+mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter)
+{
+ u32 value = 0; /* disabled src */
+
+ MALI_DEBUG_ASSERT_POINTER(cache);
+ MALI_DEBUG_ASSERT(counter < (1 << 7)); /* the possible values are 0-127 */
+
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ cache->counter_src0 = counter;
+
+ if (counter != MALI_HW_CORE_NO_COUNTER)
+ {
+ value = counter;
+ }
+
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value);
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+ return MALI_TRUE;
+}
+
+mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter)
+{
+ u32 value = 0; /* disabled src */
+
+ MALI_DEBUG_ASSERT_POINTER(cache);
+ MALI_DEBUG_ASSERT(counter < (1 << 7)); /* the possible values are 0-127 */
+
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ cache->counter_src1 = counter;
+
+ if (counter != MALI_HW_CORE_NO_COUNTER)
+ {
+ value = counter;
+ }
+
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value);
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+ return MALI_TRUE;
+}
+
+u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache)
+{
+ return cache->counter_src0;
+}
+
+u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache)
+{
+ return cache->counter_src1;
+}
+
+void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1)
+{
+ MALI_DEBUG_ASSERT(NULL != src0);
+ MALI_DEBUG_ASSERT(NULL != value0);
+ MALI_DEBUG_ASSERT(NULL != src1);
+ MALI_DEBUG_ASSERT(NULL != value1);
+
+ /* Caller must hold the PM lock and know that we are powered on */
+
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ *src0 = cache->counter_src0;
+ *src1 = cache->counter_src1;
+
+ if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
+ {
+ *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0);
+ }
+
+ if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
+ {
+ *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1);
+ }
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index)
+{
+ if (MALI_MAX_NUMBER_OF_L2_CACHE_CORES > index)
+ {
+ return mali_global_l2_cache_cores[index];
+ }
+
+ return NULL;
+}
+
+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)
+{
+ /* Invalidate cache (just to keep it in a known state at startup) */
+ mali_l2_cache_invalidate_all(cache);
+
+ /* 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);
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads);
+
+ /* Restart any performance counters (if enabled) */
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
+ {
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0);
+ }
+
+ if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER)
+ {
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1);
+ }
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_l2_cache_invalidate_all(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_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages)
+{
+ u32 i;
+ _mali_osk_errcode_t ret1, ret = _MALI_OSK_ERR_OK;
+
+ for (i = 0; i < num_pages; i++)
+ {
+ ret1 = mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[i]);
+ if (_MALI_OSK_ERR_OK != ret1)
+ {
+ ret = ret1;
+ }
+ }
+
+ return ret;
+}
+
+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();
+}
+
+void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache)
+{
+ /* Release PM lock */
+ mali_pm_unlock();
+}
+
+/* -------- local helper functions below -------- */
+
+
+static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val)
+{
+ int i = 0;
+ const int loop_count = 100000;
+
+ /*
+ * Grab lock in order to send commands to the L2 cache in a serialized fashion.
+ * The L2 cache will ignore commands if it is busy.
+ */
+ _mali_osk_lock_wait(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* First, wait for L2 cache command handler to go idle */
+
+ for (i = 0; i < loop_count; i++)
+ {
+ if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY))
+ {
+ break;
+ }
+ }
+
+ if (i == loop_count)
+ {
+ _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n"));
+ MALI_ERROR( _MALI_OSK_ERR_FAULT );
+ }
+
+ /* then issue the command */
+ mali_hw_core_register_write(&cache->hw_core, reg, val);
+
+ _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_SUCCESS;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.h b/drivers/media/video/samsung/mali/common/mali_l2_cache.h
new file mode 100644
index 0000000..5a8e4da
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_l2_cache.h
@@ -0,0 +1,43 @@
+/*
+ * 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_L2_CACHE_H__
+#define __MALI_KERNEL_L2_CACHE_H__
+
+#include "mali_osk.h"
+
+struct mali_l2_cache_core;
+
+_mali_osk_errcode_t mali_l2_cache_initialize(void);
+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);
+
+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);
+mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter);
+u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache);
+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);
+
+_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);
+
+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);
+
+#endif /* __MALI_KERNEL_L2_CACHE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.c b/drivers/media/video/samsung/mali/common/mali_mem_validation.c
new file mode 100644
index 0000000..ea9c428
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mem_validation.c
@@ -0,0 +1,71 @@
+/*
+ * 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_mem_validation.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+#define MALI_INVALID_MEM_ADDR 0xFFFFFFFF
+
+typedef struct
+{
+ u32 phys_base; /**< Mali physical base of the memory, page aligned */
+ u32 size; /**< size in bytes of the memory, multiple of page size */
+} _mali_mem_validation_t;
+
+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)
+{
+ /* 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));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* Check restrictions on page alignment */
+ if ((0 != (resource->base & (~_MALI_OSK_CPU_PAGE_MASK))) ||
+ (0 != (resource->size & (~_MALI_OSK_CPU_PAGE_MASK))))
+ {
+ MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; incorrect alignment\n", resource->description));
+ 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));
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size)
+{
+ if (phys_addr < (phys_addr + size)) /* Don't allow overflow (or zero size) */
+ {
+ if ((0 == ( phys_addr & (~_MALI_OSK_CPU_PAGE_MASK))) &&
+ (0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK))))
+ {
+ if ((phys_addr >= mali_mem_validator.phys_base) &&
+ ((phys_addr + (size - 1)) >= mali_mem_validator.phys_base) &&
+ (phys_addr <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) &&
+ ((phys_addr + (size - 1)) <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) )
+ {
+ MALI_DEBUG_PRINT(3, ("Accepted range 0x%08X + size 0x%08X (= 0x%08X)\n", phys_addr, size, (phys_addr + size - 1)));
+ return _MALI_OSK_ERR_OK;
+ }
+ }
+ }
+
+ MALI_PRINT_ERROR(("MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_addr, size));
+
+ return _MALI_OSK_ERR_FAULT;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_session_manager.h b/drivers/media/video/samsung/mali/common/mali_mem_validation.h
index 8cc41d7..2043b44 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_session_manager.h
+++ b/drivers/media/video/samsung/mali/common/mali_mem_validation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 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.
@@ -8,12 +8,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_SESSION_MANAGER_H__
-#define __MALI_KERNEL_SESSION_MANAGER_H__
+#ifndef __MALI_MEM_VALIDATION_H__
+#define __MALI_MEM_VALIDATION_H__
-/* Incomplete struct to pass around pointers to it */
-struct mali_session_data;
+#include "mali_osk.h"
-void * mali_kernel_session_manager_slot_get(struct mali_session_data * session, int id);
+_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t * resource);
+_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size);
-#endif /* __MALI_KERNEL_SESSION_MANAGER_H__ */
+#endif /* __MALI_MEM_VALIDATION_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_memory.c b/drivers/media/video/samsung/mali/common/mali_memory.c
new file mode 100644
index 0000000..7a11d1a
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_memory.c
@@ -0,0 +1,1321 @@
+/*
+ * 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_kernel_descriptor_mapping.h"
+#include "mali_mem_validation.h"
+#include "mali_memory.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_kernel_memory_engine.h"
+#include "mali_block_allocator.h"
+#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 "ump_kernel_interface.h"
+#endif
+
+/* kernel side OS functions and user-kernel interface */
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_ukk.h"
+#include "mali_osk_list.h"
+#include "mali_osk_bitops.h"
+
+/**
+ * Per-session memory descriptor mapping table sizes
+ */
+#define MALI_MEM_DESCRIPTORS_INIT 64
+#define MALI_MEM_DESCRIPTORS_MAX 65536
+
+typedef struct dedicated_memory_info
+{
+ u32 base;
+ u32 size;
+ struct dedicated_memory_info * next;
+} 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
+typedef struct ump_mem_allocation
+{
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+ u32 initial_offset;
+ u32 size_allocated;
+ ump_dd_handle ump_mem;
+} ump_mem_allocation ;
+#endif
+
+typedef struct external_mem_allocation
+{
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+ u32 initial_offset;
+ u32 size;
+} external_mem_allocation;
+
+/**
+ * @brief Internal function for unmapping memory
+ *
+ * Worker function for unmapping memory from a user-process. We assume that the
+ * session/descriptor's lock was obtained before entry. For example, the
+ * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this
+ * function to do the actual unmapping. mali_memory_core_session_end() could
+ * also call this directly (depending on compilation options), having locked
+ * the descriptor.
+ *
+ * This function will fail if it is unable to put the MMU in stall mode (which
+ * might be the case if a page fault is also being processed).
+ *
+ * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args );
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+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*/
+
+
+static void external_memory_release(void * ctx, void * handle);
+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);
+
+
+/* nop functions */
+
+/* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */
+static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */
+static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size);
+static void mali_address_manager_release(mali_memory_allocation * descriptor);
+
+/* MMU variables */
+
+typedef struct mali_mmu_page_table_allocation
+{
+ _mali_osk_list_t list;
+ u32 * usage_map;
+ u32 usage_count;
+ u32 num_pages;
+ mali_page_table_block pages;
+} mali_mmu_page_table_allocation;
+
+typedef struct mali_mmu_page_table_allocations
+{
+ _mali_osk_lock_t *lock;
+ _mali_osk_list_t partial;
+ _mali_osk_list_t full;
+ /* we never hold on to a empty allocation */
+} mali_mmu_page_table_allocations;
+
+static mali_kernel_mem_address_manager mali_address_manager =
+{
+ mali_address_manager_allocate, /* allocate */
+ mali_address_manager_release, /* release */
+ mali_address_manager_map, /* map_physical */
+ NULL /* unmap_physical not present*/
+};
+
+/* the mmu page table cache */
+static struct mali_mmu_page_table_allocations page_table_cache;
+
+
+static mali_kernel_mem_address_manager process_address_manager =
+{
+ _mali_osk_mem_mapregion_init, /* allocate */
+ _mali_osk_mem_mapregion_term, /* release */
+ _mali_osk_mem_mapregion_map, /* map_physical */
+ _mali_osk_mem_mapregion_unmap /* unmap_physical */
+};
+
+static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void);
+static void mali_mmu_page_table_cache_destroy(void);
+
+static mali_allocation_engine memory_engine = NULL;
+static mali_physical_memory_allocator * physical_memory_allocators = NULL;
+
+static dedicated_memory_info * mem_region_registrations = NULL;
+
+/* called during module init */
+_mali_osk_errcode_t mali_memory_initialize(void)
+{
+ _mali_osk_errcode_t err;
+
+ MALI_DEBUG_PRINT(2, ("Memory system initializing\n"));
+
+ err = mali_mmu_page_table_cache_create();
+ if(_MALI_OSK_ERR_OK != err)
+ {
+ MALI_ERROR(err);
+ }
+
+ memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager);
+ MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT);
+
+ MALI_SUCCESS;
+}
+
+/* called if/when our module is unloaded */
+void mali_memory_terminate(void)
+{
+ MALI_DEBUG_PRINT(2, ("Memory system terminating\n"));
+
+ mali_mmu_page_table_cache_destroy();
+
+ while ( NULL != mem_region_registrations)
+ {
+ dedicated_memory_info * m;
+ m = mem_region_registrations;
+ mem_region_registrations = m->next;
+ _mali_osk_mem_unreqregion(m->base, m->size);
+ _mali_osk_free(m);
+ }
+
+ while ( NULL != physical_memory_allocators)
+ {
+ mali_physical_memory_allocator * m;
+ m = physical_memory_allocators;
+ physical_memory_allocators = m->next;
+ m->destroy(m);
+ }
+
+ if (NULL != memory_engine)
+ {
+ mali_allocation_engine_destroy(memory_engine);
+ memory_engine = NULL;
+ }
+}
+
+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data)
+{
+ MALI_DEBUG_PRINT(5, ("Memory session begin\n"));
+
+ /* create descriptor mapping table */
+ session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX);
+
+ if (NULL == session_data->descriptor_mapping)
+ {
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ session_data->memory_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK
+ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_SESSION);
+ if (NULL == session_data->memory_lock)
+ {
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Init the session's memory allocation list */
+ _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head );
+
+ MALI_DEBUG_PRINT(5, ("MMU session begin: success\n"));
+ MALI_SUCCESS;
+}
+
+static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target)
+{
+ mali_memory_allocation * descriptor;
+
+ descriptor = (mali_memory_allocation*)map_target;
+
+ MALI_DEBUG_PRINT(3, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target));
+ MALI_DEBUG_ASSERT(descriptor);
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+ _mali_osk_free(descriptor);
+}
+
+void mali_memory_session_end(struct mali_session_data *session_data)
+{
+ MALI_DEBUG_PRINT(3, ("MMU session end\n"));
+
+ if (NULL == session_data)
+ {
+ MALI_DEBUG_PRINT(1, ("No session data found during session end\n"));
+ return;
+ }
+
+#ifndef MALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP
+#if _MALI_OSK_SPECIFIC_INDIRECT_MMAP
+#error Indirect MMAP specified, but UKK does not have implicit MMAP cleanup. Current implementation does not handle this.
+#else
+ {
+ _mali_osk_errcode_t err;
+ err = _MALI_OSK_ERR_BUSY;
+ while (err == _MALI_OSK_ERR_BUSY)
+ {
+ /* Lock the session so we can modify the memory list */
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+ err = _MALI_OSK_ERR_OK;
+
+ /* Free all memory engine allocations */
+ if (0 == _mali_osk_list_empty(&session_data->memory_head))
+ {
+ mali_memory_allocation *descriptor;
+ mali_memory_allocation *temp;
+ _mali_uk_mem_munmap_s unmap_args;
+
+ MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n"));
+
+ unmap_args.ctx = session_data;
+
+ /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
+ _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->memory_head, mali_memory_allocation, list)
+ {
+ MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n",
+ descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping)
+ );
+ /* ASSERT that the descriptor's lock references the correct thing */
+ MALI_DEBUG_ASSERT( descriptor->lock == session_data->memory_lock );
+ /* Therefore, we have already locked the descriptor */
+
+ unmap_args.size = descriptor->size;
+ unmap_args.mapping = descriptor->mapping;
+ unmap_args.cookie = (u32)descriptor;
+
+ /*
+ * This removes the descriptor from the list, and frees the descriptor
+ *
+ * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since
+ * the only OS we are aware of that requires indirect MMAP also has
+ * implicit mmap cleanup.
+ */
+ err = _mali_ukk_mem_munmap_internal( &unmap_args );
+
+ if (err == _MALI_OSK_ERR_BUSY)
+ {
+ _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+ /*
+ * Reason for this;
+ * We where unable to stall the MMU, probably because we are in page fault handling.
+ * Sleep for a while with the session lock released, then try again.
+ * Abnormal termination of programs with running Mali jobs is a normal reason for this.
+ */
+ _mali_osk_time_ubusydelay(10);
+ break; /* Will jump back into: "while (err == _MALI_OSK_ERR_BUSY)" */
+ }
+ }
+ }
+ }
+ /* Assert that we really did free everything */
+ MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) );
+ }
+#endif /* _MALI_OSK_SPECIFIC_INDIRECT_MMAP */
+#else
+ /* Lock the session so we can modify the memory list */
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+#endif /* MALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP */
+
+ if (NULL != session_data->descriptor_mapping)
+ {
+ mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback);
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ session_data->descriptor_mapping = NULL;
+ }
+
+ _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ /**
+ * @note Could the VMA close handler mean that we use the session data after it was freed?
+ * In which case, would need to refcount the session data, and free on VMA close
+ */
+
+ /* Free the lock */
+ _mali_osk_lock_term( session_data->memory_lock );
+
+ return;
+}
+
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource)
+{
+ mali_physical_memory_allocator * allocator;
+ mali_physical_memory_allocator ** next_allocator_list;
+
+ u32 alloc_order = resource->alloc_order;
+
+ allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description);
+ if (NULL == allocator)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n"));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ allocator->alloc_order = alloc_order;
+
+ /* link in the allocator: insertion into ordered list
+ * resources of the same alloc_order will be Last-in-first */
+ next_allocator_list = &physical_memory_allocators;
+
+ while (NULL != *next_allocator_list &&
+ (*next_allocator_list)->alloc_order < alloc_order )
+ {
+ next_allocator_list = &((*next_allocator_list)->next);
+ }
+
+ allocator->next = (*next_allocator_list);
+ (*next_allocator_list) = allocator;
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource)
+{
+ mali_physical_memory_allocator * allocator;
+ mali_physical_memory_allocator ** next_allocator_list;
+ dedicated_memory_info * cleanup_data;
+
+ u32 alloc_order = resource->alloc_order;
+
+ /* 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))
+ {
+ 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_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 );
+
+ if (NULL == allocator)
+ {
+ MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
+ _mali_osk_mem_unreqregion(resource->base, resource->size);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* save low level cleanup info */
+ allocator->alloc_order = alloc_order;
+
+ cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info));
+
+ if (NULL == cleanup_data)
+ {
+ _mali_osk_mem_unreqregion(resource->base, resource->size);
+ allocator->destroy(allocator);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ cleanup_data->base = resource->base;
+ cleanup_data->size = resource->size;
+
+ cleanup_data->next = mem_region_registrations;
+ mem_region_registrations = cleanup_data;
+
+ /* link in the allocator: insertion into ordered list
+ * resources of the same alloc_order will be Last-in-first */
+ next_allocator_list = &physical_memory_allocators;
+
+ while ( NULL != *next_allocator_list &&
+ (*next_allocator_list)->alloc_order < alloc_order )
+ {
+ next_allocator_list = &((*next_allocator_list)->next);
+ }
+
+ allocator->next = (*next_allocator_list);
+ (*next_allocator_list) = allocator;
+
+ MALI_SUCCESS;
+}
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+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;
+ u32 nr_blocks;
+ u32 i;
+ ump_dd_physical_block * ump_blocks;
+ ump_mem_allocation *ret_allocation;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(alloc_info);
+
+ ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) );
+ if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ ump_mem = (ump_dd_handle)ctx;
+
+ MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n"));
+
+ nr_blocks = ump_dd_phys_block_count_get(ump_mem);
+
+ MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks));
+
+ if (nr_blocks == 0)
+ {
+ MALI_DEBUG_PRINT(1, ("No block count\n"));
+ _mali_osk_free( ret_allocation );
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks );
+ if ( NULL==ump_blocks )
+ {
+ _mali_osk_free( ret_allocation );
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks))
+ {
+ _mali_osk_free(ump_blocks);
+ _mali_osk_free( ret_allocation );
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ /* Store away the initial offset for unmapping purposes */
+ ret_allocation->initial_offset = *offset;
+
+ for(i=0; i<nr_blocks; ++i)
+ {
+ MALI_DEBUG_PRINT(4, ("Mapping in 0x%08x size %d\n", ump_blocks[i].addr , ump_blocks[i].size));
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[i].addr , 0, ump_blocks[i].size ))
+ {
+ u32 size_allocated = *offset - ret_allocation->initial_offset;
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
+
+ /* unmap all previous blocks (if any) */
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
+
+ _mali_osk_free(ump_blocks);
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += ump_blocks[i].size;
+ }
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ /* Map in an extra virtual guard page at the end of the VMA */
+ MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE ))
+ {
+ u32 size_allocated = *offset - ret_allocation->initial_offset;
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
+
+ /* unmap all previous blocks (if any) */
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
+
+ _mali_osk_free(ump_blocks);
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += _MALI_OSK_MALI_PAGE_SIZE;
+ }
+
+ _mali_osk_free( ump_blocks );
+
+ ret_allocation->engine = engine;
+ ret_allocation->descriptor = descriptor;
+ ret_allocation->ump_mem = ump_mem;
+ ret_allocation->size_allocated = *offset - ret_allocation->initial_offset;
+
+ alloc_info->ctx = NULL;
+ alloc_info->handle = ret_allocation;
+ alloc_info->next = NULL;
+ alloc_info->release = ump_memory_release;
+
+ return MALI_MEM_ALLOC_FINISHED;
+}
+
+static void ump_memory_release(void * ctx, void * handle)
+{
+ ump_dd_handle ump_mem;
+ ump_mem_allocation *allocation;
+
+ allocation = (ump_mem_allocation *)handle;
+
+ MALI_DEBUG_ASSERT_POINTER( allocation );
+
+ ump_mem = allocation->ump_mem;
+
+ MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem);
+
+ /* At present, this is a no-op. But, it allows the mali_address_manager to
+ * do unmapping of a subrange in future. */
+ mali_allocation_engine_unmap_physical( allocation->engine,
+ allocation->descriptor,
+ allocation->initial_offset,
+ allocation->size_allocated,
+ (_mali_osk_mem_mapregion_flags_t)0
+ );
+ _mali_osk_free( allocation );
+
+
+ ump_dd_reference_release(ump_mem) ;
+ return;
+}
+
+_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args )
+{
+ ump_dd_handle ump_mem;
+ mali_physical_memory_allocator external_memory_allocator;
+ struct mali_session_data *session_data;
+ mali_memory_allocation * descriptor;
+ int md;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)args->ctx;
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ /* check arguments */
+ /* NULL might be a valid Mali address */
+ if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+ /* size must be a multiple of the system page size */
+ if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+ MALI_DEBUG_PRINT(3,
+ ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n",
+ args->secure_id, args->mali_address, args->size));
+
+ ump_mem = ump_dd_handle_create_from_secure_id( (int)args->secure_id ) ;
+
+ if ( UMP_DD_HANDLE_INVALID==ump_mem ) MALI_ERROR(_MALI_OSK_ERR_FAULT);
+
+ descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
+ if (NULL == descriptor)
+ {
+ ump_dd_reference_release(ump_mem);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ descriptor->size = args->size;
+ descriptor->mapping = NULL;
+ descriptor->mali_address = args->mali_address;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+ descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
+ descriptor->lock = session_data->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 );
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
+ {
+ ump_dd_reference_release(ump_mem);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ external_memory_allocator.allocate = ump_memory_commit;
+ external_memory_allocator.allocate_page_table_block = NULL;
+ external_memory_allocator.ctx = ump_mem;
+ external_memory_allocator.name = "UMP Memory";
+ external_memory_allocator.next = NULL;
+
+ _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
+ {
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
+ ump_dd_reference_release(ump_mem);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ args->cookie = md;
+
+ MALI_DEBUG_PRINT(5,("Returning from UMP attach\n"));
+
+ /* All OK */
+ MALI_SUCCESS;
+}
+
+
+_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args )
+{
+ mali_memory_allocation * descriptor;
+ struct mali_session_data *session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)args->ctx;
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor))
+ {
+ MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ descriptor = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
+
+ if (NULL != descriptor)
+ {
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+
+ _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ _mali_osk_free(descriptor);
+ }
+
+ MALI_SUCCESS;
+
+}
+#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */
+
+
+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)
+{
+ u32 * data;
+ external_mem_allocation * ret_allocation;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(alloc_info);
+
+ ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) );
+
+ if ( NULL == ret_allocation )
+ {
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ data = (u32*)ctx;
+
+ ret_allocation->engine = engine;
+ ret_allocation->descriptor = descriptor;
+ ret_allocation->initial_offset = *offset;
+
+ alloc_info->ctx = NULL;
+ alloc_info->handle = ret_allocation;
+ alloc_info->next = NULL;
+ alloc_info->release = external_memory_release;
+
+ MALI_DEBUG_PRINT(5, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1]));
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1]))
+ {
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += data[1];
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ /* Map in an extra virtual guard page at the end of the VMA */
+ MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE))
+ {
+ u32 size_allocated = *offset - ret_allocation->initial_offset;
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
+
+ /* unmap what we previously mapped */
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += _MALI_OSK_MALI_PAGE_SIZE;
+ }
+
+ ret_allocation->size = *offset - ret_allocation->initial_offset;
+
+ return MALI_MEM_ALLOC_FINISHED;
+}
+
+static void external_memory_release(void * ctx, void * handle)
+{
+ external_mem_allocation * allocation;
+
+ allocation = (external_mem_allocation *) handle;
+ MALI_DEBUG_ASSERT_POINTER( allocation );
+
+ /* At present, this is a no-op. But, it allows the mali_address_manager to
+ * do unmapping of a subrange in future. */
+
+ mali_allocation_engine_unmap_physical( allocation->engine,
+ allocation->descriptor,
+ allocation->initial_offset,
+ allocation->size,
+ (_mali_osk_mem_mapregion_flags_t)0
+ );
+
+ _mali_osk_free( allocation );
+
+ return;
+}
+
+_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
+{
+ mali_physical_memory_allocator external_memory_allocator;
+ struct mali_session_data *session_data;
+ u32 info[2];
+ mali_memory_allocation * descriptor;
+ int md;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)args->ctx;
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ external_memory_allocator.allocate = external_memory_commit;
+ external_memory_allocator.allocate_page_table_block = NULL;
+ external_memory_allocator.ctx = &info[0];
+ external_memory_allocator.name = "External Memory";
+ external_memory_allocator.next = NULL;
+
+ /* check arguments */
+ /* NULL might be a valid Mali address */
+ if ( ! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+ /* size must be a multiple of the system page size */
+ if ( args->size % _MALI_OSK_MALI_PAGE_SIZE ) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+ MALI_DEBUG_PRINT(3,
+ ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n",
+ (void*)args->phys_addr,
+ (void*)(args->phys_addr + args->size -1),
+ (void*)args->mali_address)
+ );
+
+ /* Validate the mali physical range */
+ if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size))
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ info[0] = args->phys_addr;
+ info[1] = args->size;
+
+ descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
+ if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+ descriptor->size = args->size;
+ descriptor->mapping = NULL;
+ descriptor->mali_address = args->mali_address;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+ descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
+ descriptor->lock = session_data->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 );
+
+ _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
+ {
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
+ {
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ args->cookie = md;
+
+ MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n"));
+
+ /* All OK */
+ MALI_SUCCESS;
+}
+
+
+_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
+{
+ mali_memory_allocation * descriptor;
+ void* old_value;
+ struct mali_session_data *session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)args->ctx;
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->descriptor_mapping, args->cookie, (void**)&descriptor))
+ {
+ MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ old_value = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
+
+ if (NULL != old_value)
+ {
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+
+ _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ _mali_osk_free(descriptor);
+ }
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args )
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */
+ args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args )
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor)
+{
+ struct mali_session_data *session_data;
+ u32 actual_size;
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+
+ actual_size = descriptor->size;
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ actual_size += _MALI_OSK_MALI_PAGE_SIZE;
+ }
+
+ return mali_mmu_pagedir_map(session_data->page_directory, descriptor->mali_address, actual_size);
+}
+
+static void mali_address_manager_release(mali_memory_allocation * descriptor)
+{
+ const u32 illegal_mali_address = 0xffffffff;
+ struct mali_session_data *session_data;
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /* It is allowed to call this function several times on the same descriptor.
+ When memory is released we set the illegal_mali_address so we can early out here. */
+ if ( illegal_mali_address == descriptor->mali_address) return;
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+ mali_mmu_pagedir_unmap(session_data->page_directory, descriptor->mali_address, descriptor->size);
+
+ descriptor->mali_address = illegal_mali_address ;
+}
+
+static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size)
+{
+ struct mali_session_data *session_data;
+ u32 mali_address;
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(phys_addr);
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ mali_address = descriptor->mali_address + offset;
+
+ MALI_DEBUG_PRINT(7, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", *phys_addr, mali_address, size));
+
+ mali_mmu_pagedir_update(session_data->page_directory, mali_address, *phys_addr, size);
+
+ MALI_SUCCESS;
+}
+
+/* This handler registered to mali_mmap for MMU builds */
+_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args )
+{
+ struct mali_session_data *session_data;
+ mali_memory_allocation * descriptor;
+
+ /* validate input */
+ if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
+
+ /* Unpack arguments */
+ session_data = (struct mali_session_data *)args->ctx;
+
+ /* validate input */
+ if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); }
+
+ descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) );
+ if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); }
+
+ descriptor->size = args->size;
+ descriptor->mali_address = args->phys_addr;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+
+ descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */
+ descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE;
+ descriptor->lock = session_data->memory_lock;
+ _mali_osk_list_init( &descriptor->list );
+
+ _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head))
+ {
+ /* We do not FLUSH nor TLB_ZAP on MMAP, since we do both of those on job start*/
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ args->mapping = descriptor->mapping;
+ args->cookie = (u32)descriptor;
+
+ MALI_DEBUG_PRINT(7, ("MMAP OK\n"));
+ MALI_SUCCESS;
+ }
+ else
+ {
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+ /* OOM, but not a fatal error */
+ MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n"));
+ _mali_osk_free(descriptor);
+ /* Linux will free the CPU address allocation, userspace client the Mali address allocation */
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+}
+
+static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args )
+{
+ 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);
+
+ /** @note args->context unused; we use the memory_session from the cookie */
+ /* args->mapping and args->size are also discarded. They are only necessary
+ for certain do_munmap implementations. However, they could be used to check the
+ descriptor at this point. */
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ /* Unmapping the memory from the mali virtual address space.
+ 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);
+ }
+
+ /* 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);
+
+ _mali_osk_free(descriptor);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+/* Handler for unmapping memory for MMU builds */
+_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args )
+{
+ mali_memory_allocation * descriptor;
+ _mali_osk_lock_t *descriptor_lock;
+ _mali_osk_errcode_t err;
+
+ descriptor = (mali_memory_allocation *)args->cookie;
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /** @note args->context unused; we use the memory_session from the cookie */
+ /* args->mapping and args->size are also discarded. They are only necessary
+ for certain do_munmap implementations. However, they could be used to check the
+ descriptor at this point. */
+
+ MALI_DEBUG_ASSERT_POINTER((struct mali_session_data *)descriptor->mali_addr_mapping_info);
+
+ descriptor_lock = descriptor->lock; /* should point to the session data lock... */
+
+ err = _MALI_OSK_ERR_BUSY;
+ while (err == _MALI_OSK_ERR_BUSY)
+ {
+ if (descriptor_lock)
+ {
+ _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
+ }
+
+ err = _mali_ukk_mem_munmap_internal( args );
+
+ if (descriptor_lock)
+ {
+ _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
+ }
+
+ if (err == _MALI_OSK_ERR_BUSY)
+ {
+ /*
+ * Reason for this;
+ * We where unable to stall the MMU, probably because we are in page fault handling.
+ * Sleep for a while with the session lock released, then try again.
+ * Abnormal termination of programs with running Mali jobs is a normal reason for this.
+ */
+ _mali_osk_time_ubusydelay(10);
+ }
+ }
+
+ return err;
+}
+
+u32 _mali_ukk_report_memory_usage(void)
+{
+ return mali_allocation_engine_memory_usage(physical_memory_allocators);
+}
+
+_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping)
+{
+ _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (0 == _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);
+ MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number));
+ _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map);
+ alloc->usage_count++;
+ if (alloc->num_pages == alloc->usage_count)
+ {
+ /* full, move alloc to full list*/
+ _mali_osk_list_move(&alloc->list, &page_table_cache.full);
+ }
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+
+ *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base;
+ *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping);
+ MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
+ MALI_SUCCESS;
+ }
+ else
+ {
+ mali_mmu_page_table_allocation * alloc;
+ /* no free pages, allocate a new one */
+
+ alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation));
+ if (NULL == alloc)
+ {
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = MALI_INVALID_PAGE;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _MALI_OSK_INIT_LIST_HEAD(&alloc->list);
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators))
+ {
+ MALI_DEBUG_PRINT(1, ("No more memory for page tables\n"));
+ _mali_osk_free(alloc);
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = MALI_INVALID_PAGE;
+ *mapping = NULL;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ /* create the usage map */
+ alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE;
+ alloc->usage_count = 1;
+ MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages));
+ alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long));
+ if (NULL == alloc->usage_map)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n"));
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc);
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = MALI_INVALID_PAGE;
+ *mapping = NULL;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _mali_osk_set_nonatomic_bit(0, alloc->usage_map);
+
+ if (alloc->num_pages > 1)
+ {
+ _mali_osk_list_add(&alloc->list, &page_table_cache.partial);
+ }
+ else
+ {
+ _mali_osk_list_add(&alloc->list, &page_table_cache.full);
+ }
+
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = alloc->pages.phys_base; /* return the first page */
+ *mapping = alloc->pages.mapping; /* Mapping for first page */
+ MALI_DEBUG_PRINT(4, ("Page table allocated: VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
+ MALI_SUCCESS;
+ }
+}
+
+void mali_mmu_release_table_page(u32 pa)
+{
+ mali_mmu_page_table_allocation * alloc, * temp_alloc;
+
+ MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa));
+
+ MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa));
+
+ _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* find the entry this address belongs to */
+ /* first check the partial list */
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
+ {
+ u32 start = alloc->pages.phys_base;
+ u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
+ if (pa >= start && pa <= last)
+ {
+ MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map));
+ _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
+ alloc->usage_count--;
+
+ _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
+
+ if (0 == alloc->usage_count)
+ {
+ /* empty, release whole page alloc */
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa));
+ return;
+ }
+ }
+
+ /* the check the full list */
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list)
+ {
+ u32 start = alloc->pages.phys_base;
+ u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
+ if (pa >= start && pa <= last)
+ {
+ _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
+ alloc->usage_count--;
+
+ _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
+
+
+ if (0 == alloc->usage_count)
+ {
+ /* empty, release whole page alloc */
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+ else
+ {
+ /* transfer to partial list */
+ _mali_osk_list_move(&alloc->list, &page_table_cache.partial);
+ }
+
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa));
+ return;
+ }
+ }
+
+ MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa));
+
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+static _mali_osk_errcode_t mali_mmu_page_table_cache_create(void)
+{
+ page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK
+ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE);
+ MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT );
+ _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial);
+ _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full);
+ MALI_SUCCESS;
+}
+
+static void mali_mmu_page_table_cache_destroy(void)
+{
+ mali_mmu_page_table_allocation * alloc, *temp;
+
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
+ {
+ MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count));
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _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_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list)
+ {
+ MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count));
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+
+ _mali_osk_lock_term(page_table_cache.lock);
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_memory.h b/drivers/media/video/samsung/mali/common/mali_memory.h
new file mode 100644
index 0000000..53a994c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_memory.h
@@ -0,0 +1,80 @@
+/*
+ * 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_MEMORY_H__
+#define __MALI_MEMORY_H__
+
+#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
+ * allocating Mali memory.
+ *
+ * @return On success _MALI_OSK_ERR_OK, othervise some error code describing the error.
+ */
+_mali_osk_errcode_t mali_memory_initialize(void);
+
+/** @brief Terminate Mali memory system
+ *
+ * Clean up and release internal data structures.
+ */
+void mali_memory_terminate(void);
+
+/** @brief Start new Mali memory session
+ *
+ * Allocate and prepare session specific memory allocation data data. The
+ * session page directory, lock, and descriptor map is set up.
+ *
+ * @param mali_session_data pointer to the session data structure
+ */
+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *mali_session_data);
+
+/** @brief Close a Mali memory session
+ *
+ * Release session specific memory allocation related data.
+ *
+ * @param mali_session_data pointer to the session data structure
+ */
+void mali_memory_session_end(struct mali_session_data *mali_session_data);
+
+/** @brief Allocate a page table page
+ *
+ * Allocate a page for use as a page directory or page table. The page is
+ * mapped into kernel space.
+ *
+ * @return _MALI_OSK_ERR_OK on success, othervise an error code
+ * @param table_page GPU pointer to the allocated page
+ * @param mapping CPU pointer to the mapping of the allocated page
+ */
+_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping);
+
+/** @brief Release a page table page
+ *
+ * Release a page table page allocated through \a mali_mmu_get_table_page
+ *
+ * @param pa the GPU address of the page to release
+ */
+void mali_mmu_release_table_page(u32 pa);
+
+
+/** @brief Parse resource and prepare the OS memory allocator
+ */
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource);
+
+/** @brief Parse resource and prepare the dedicated memory allocator
+ */
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource);
+
+#endif /* __MALI_MEMORY_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.c b/drivers/media/video/samsung/mali/common/mali_mmu.c
new file mode 100644
index 0000000..2f2fa4d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu.c
@@ -0,0 +1,619 @@
+/*
+ * 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_bitops.h"
+#include "mali_osk_list.h"
+#include "mali_ukk.h"
+
+#include "mali_mmu.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "mali_mmu_page_directory.h"
+
+/**
+ * Size of the MMU registers in bytes
+ */
+#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.
+ */
+typedef enum mali_mmu_command
+{
+ MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
+ MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
+ MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */
+ MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
+ MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
+ MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
+ 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);
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu);
+
+/* page fault queue flush helper pages
+ * note that the mapping pointers are currently unused outside of the initialization functions */
+static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
+static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
+static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
+
+/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */
+static u32 mali_empty_page_directory = MALI_INVALID_PAGE;
+
+_mali_osk_errcode_t mali_mmu_initialize(void)
+{
+ /* allocate the helper pages */
+ mali_empty_page_directory = mali_allocate_empty_page();
+ if(0 == mali_empty_page_directory)
+ {
+ mali_empty_page_directory = MALI_INVALID_PAGE;
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory,
+ &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page))
+ {
+ mali_free_empty_page(mali_empty_page_directory);
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_mmu_terminate(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n"));
+
+ /* Free global helper pages */
+ mali_free_empty_page(mali_empty_page_directory);
+
+ /* Free the page fault flush pages */
+ mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory,
+ &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* mmu = NULL;
+
+ MALI_DEBUG_ASSERT_POINTER(resource);
+
+ MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description));
+
+ mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
+ if (NULL != mmu)
+ {
+ 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))
+ {
+ /* 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)
+ {
+ return mmu;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
+ }
+ }
+ mali_hw_core_delete(&mmu->hw_core);
+ }
+
+ _mali_osk_free(mmu);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n"));
+ }
+
+ return NULL;
+}
+
+void mali_mmu_delete(struct mali_mmu_core *mmu)
+{
+ _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)
+ {
+ 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)
+ {
+ 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)));
+ }
+}
+
+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);
+
+ if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) )
+ {
+ MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n"));
+ return MALI_TRUE;
+ }
+
+ if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
+ {
+ MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n"));
+ return MALI_FALSE;
+ }
+
+ 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)
+ {
+ 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))
+ {
+ break;
+ }
+ if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED )))
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ if (max_loop_count == 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)));
+ 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"));
+ return MALI_FALSE;
+ }
+
+ return MALI_TRUE;
+}
+
+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);
+
+ if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
+ {
+ MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n"));
+ return;
+ }
+ if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)
+ {
+ MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n"));
+ return;
+ }
+
+ 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)
+ {
+ u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+ if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) )
+ {
+ break;
+ }
+ if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_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) 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_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET);
+
+ for (i = 0; i < max_loop_count; ++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)
+ {
+ 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;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_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);
+
+ MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
+
+ if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu))
+ {
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ /* no session is active, so just activate the empty page directory */
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
+ mali_mmu_enable_paging(mmu);
+ err = _MALI_OSK_ERR_OK;
+ }
+ mali_mmu_disable_stall(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_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+
+ if (MALI_FALSE == stall_success)
+ {
+ /* False means that it is in Pagefault state. Not possible to disable_stall then */
+ return MALI_FALSE;
+ }
+
+ mali_mmu_disable_stall(mmu);
+ return MALI_TRUE;
+}
+
+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_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);
+
+}
+
+mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
+{
+ 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);
+
+ if ( MALI_FALSE==stall_success ) return MALI_FALSE;
+ mali_mmu_activate_address_space(mmu, pagedir->page_directory);
+ mali_mmu_disable_stall(mmu);
+ return MALI_TRUE;
+}
+
+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_mmu_activate_address_space(mmu, mali_empty_page_directory);
+ mali_mmu_disable_stall(mmu);
+}
+
+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);
+ /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */
+ mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory);
+ if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu);
+}
+
+/* Is called when we want the mmu to give an interrupt */
+static void mali_mmu_probe_trigger(void *data)
+{
+ struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+}
+
+/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
+static _mali_osk_errcode_t mali_mmu_probe_ack(void *data)
+{
+ struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+ u32 int_stat;
+
+ int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
+
+ MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
+ if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
+ {
+ MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
+ }
+
+ if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
+ {
+ MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
+ }
+
+ if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
+ (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR))
+ {
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+#if 0
+void mali_mmu_print_state(struct mali_mmu_core *mmu)
+{
+ MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.h b/drivers/media/video/samsung/mali/common/mali_mmu.h
new file mode 100644
index 0000000..c7274b8
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu.h
@@ -0,0 +1,55 @@
+/*
+ * 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_mmu_page_directory.c b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c
new file mode 100644
index 0000000..43a4cf4
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c
@@ -0,0 +1,459 @@
+/*
+ * 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_kernel_core.h"
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_memory.h"
+
+#include "mali_cluster.h"
+#include "mali_group.h"
+
+static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data);
+
+u32 mali_allocate_empty_page(void)
+{
+ _mali_osk_errcode_t err;
+ mali_io_address mapping;
+ u32 address;
+
+ if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&address, &mapping))
+ {
+ /* Allocation failed */
+ return 0;
+ }
+
+ MALI_DEBUG_ASSERT_POINTER( mapping );
+
+ err = fill_page(mapping, 0);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ mali_mmu_release_table_page(address);
+ }
+ return address;
+}
+
+void mali_free_empty_page(u32 address)
+{
+ if (MALI_INVALID_PAGE != address)
+ {
+ mali_mmu_release_table_page(address);
+ }
+}
+
+_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page)
+{
+ _mali_osk_errcode_t err;
+ mali_io_address page_directory_mapping;
+ mali_io_address page_table_mapping;
+ mali_io_address data_page_mapping;
+
+ err = mali_mmu_get_table_page(data_page, &data_page_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ err = mali_mmu_get_table_page(page_table, &page_table_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ err = mali_mmu_get_table_page(page_directory, &page_directory_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ fill_page(data_page_mapping, 0);
+ fill_page(page_table_mapping, *data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
+ fill_page(page_directory_mapping, *page_table | MALI_MMU_FLAGS_PRESENT);
+ MALI_SUCCESS;
+ }
+ mali_mmu_release_table_page(*page_table);
+ *page_table = MALI_INVALID_PAGE;
+ }
+ mali_mmu_release_table_page(*data_page);
+ *data_page = MALI_INVALID_PAGE;
+ }
+ return err;
+}
+
+void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page)
+{
+ if (MALI_INVALID_PAGE != *page_directory)
+ {
+ mali_mmu_release_table_page(*page_directory);
+ *page_directory = MALI_INVALID_PAGE;
+ }
+
+ if (MALI_INVALID_PAGE != *page_table)
+ {
+ mali_mmu_release_table_page(*page_table);
+ *page_table = MALI_INVALID_PAGE;
+ }
+
+ if (MALI_INVALID_PAGE != *data_page)
+ {
+ mali_mmu_release_table_page(*data_page);
+ *data_page = MALI_INVALID_PAGE;
+ }
+}
+
+static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data)
+{
+ int i;
+ MALI_DEBUG_ASSERT_POINTER( mapping );
+
+ for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++)
+ {
+ _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data);
+ }
+ _mali_osk_mem_barrier();
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size)
+{
+ const int first_pde = MALI_MMU_PDE_ENTRY(mali_address);
+ const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1);
+ _mali_osk_errcode_t err;
+ mali_io_address pde_mapping;
+ u32 pde_phys;
+ int i;
+
+ for(i = first_pde; i <= last_pde; i++)
+ {
+ if(0 == (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & MALI_MMU_FLAGS_PRESENT))
+ {
+ /* Page table not present */
+ MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]);
+ MALI_DEBUG_ASSERT(NULL == pagedir->page_entries_mapped[i]);
+
+ err = mali_mmu_get_table_page(&pde_phys, &pde_mapping);
+ if(_MALI_OSK_ERR_OK != err)
+ {
+ MALI_PRINT_ERROR(("Failed to allocate page table page.\n"));
+ return err;
+ }
+ pagedir->page_entries_mapped[i] = pde_mapping;
+
+ /* Update PDE, mark as present */
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32),
+ pde_phys | MALI_MMU_FLAGS_PRESENT);
+
+ MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]);
+ pagedir->page_entries_usage_count[i] = 1;
+ }
+ else
+ {
+ pagedir->page_entries_usage_count[i]++;
+ }
+ }
+ _mali_osk_write_mem_barrier();
+
+ MALI_SUCCESS;
+}
+
+MALI_STATIC_INLINE void mali_mmu_zero_pte(mali_io_address page_table, u32 mali_address, u32 size)
+{
+ int i;
+ const int first_pte = MALI_MMU_PTE_ENTRY(mali_address);
+ const int last_pte = MALI_MMU_PTE_ENTRY(mali_address + size - 1);
+
+ for (i = first_pte; i <= last_pte; i++)
+ {
+ _mali_osk_mem_iowrite32_relaxed(page_table, i * sizeof(u32), 0);
+ }
+}
+
+_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size)
+{
+ const int first_pde = MALI_MMU_PDE_ENTRY(mali_address);
+ 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
+
+ /* For all page directory entries in range. */
+ for (i = first_pde; i <= last_pde; i++)
+ {
+ u32 size_in_pde, offset;
+
+ MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]);
+ MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]);
+
+ /* Offset into page table, 0 if mali_address is 4MiB aligned */
+ offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1));
+ if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset)
+ {
+ size_in_pde = left;
+ }
+ else
+ {
+ size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset;
+ }
+
+ pagedir->page_entries_usage_count[i]--;
+
+ /* If entire page table is unused, free it */
+ if (0 == pagedir->page_entries_usage_count[i])
+ {
+ u32 page_address;
+ MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n"));
+ /* last reference removed, no need to zero out each PTE */
+
+ page_address = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)));
+ pagedir->page_entries_mapped[i] = NULL;
+ _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
+
+ /* 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);
+ }
+
+ left -= size_in_pde;
+ mali_address += size_in_pde;
+ }
+ _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);
+ }
+
+ if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id())
+ {
+ mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv);
+ }
+#endif
+
+ MALI_SUCCESS;
+}
+
+struct mali_page_directory *mali_mmu_pagedir_alloc(void)
+{
+ struct mali_page_directory *pagedir;
+
+ pagedir = _mali_osk_calloc(1, sizeof(struct mali_page_directory));
+ if(NULL == pagedir)
+ {
+ return NULL;
+ }
+
+ if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&pagedir->page_directory, &pagedir->page_directory_mapped))
+ {
+ _mali_osk_free(pagedir);
+ return NULL;
+ }
+
+ /* Zero page directory */
+ fill_page(pagedir->page_directory_mapped, 0);
+
+ return pagedir;
+}
+
+void mali_mmu_pagedir_free(struct mali_page_directory *pagedir)
+{
+ const int num_page_table_entries = sizeof(pagedir->page_entries_mapped) / sizeof(pagedir->page_entries_mapped[0]);
+ int i;
+
+ /* Free referenced page tables and zero PDEs. */
+ for (i = 0; i < num_page_table_entries; i++)
+ {
+ if (pagedir->page_directory_mapped && (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT))
+ {
+ mali_mmu_release_table_page( _mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i * sizeof(u32), 0);
+ }
+ }
+ _mali_osk_write_mem_barrier();
+
+ /* Free the page directory page. */
+ mali_mmu_release_table_page(pagedir->page_directory);
+
+ _mali_osk_free(pagedir);
+}
+
+
+void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size)
+{
+ u32 end_address = mali_address + size;
+
+ /* Map physical pages into MMU page tables */
+ for ( ; mali_address < end_address; mali_address += MALI_MMU_PAGE_SIZE, phys_address += MALI_MMU_PAGE_SIZE)
+ {
+ MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]);
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)],
+ MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32),
+ phys_address | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
+ }
+ _mali_osk_write_mem_barrier();
+}
+
+u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index)
+{
+ return (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, index*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+}
+
+/* For instrumented */
+struct dump_info
+{
+ u32 buffer_left;
+ u32 register_writes_size;
+ u32 page_table_dump_size;
+ u32 *buffer;
+};
+
+static _mali_osk_errcode_t writereg(u32 where, u32 what, const char *comment, struct dump_info *info)
+{
+ if (NULL != info)
+ {
+ info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */
+
+ if (NULL != info->buffer)
+ {
+ /* check that we have enough space */
+ if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+ *info->buffer = where;
+ info->buffer++;
+
+ *info->buffer = what;
+ info->buffer++;
+
+ info->buffer_left -= sizeof(u32)*2;
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info)
+{
+ if (NULL != info)
+ {
+ /* 4096 for the page and 4 bytes for the address */
+ const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4;
+ const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE;
+ const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4;
+
+ info->page_table_dump_size += dump_size_in_bytes;
+
+ if (NULL != info->buffer)
+ {
+ if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+ *info->buffer = phys_addr;
+ info->buffer++;
+
+ _mali_osk_memcpy(info->buffer, page, page_size_in_bytes);
+ info->buffer += page_size_in_elements;
+
+ info->buffer_left -= dump_size_in_bytes;
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_page_table(struct mali_page_directory *pagedir, struct dump_info * info)
+{
+ MALI_DEBUG_ASSERT_POINTER(pagedir);
+ MALI_DEBUG_ASSERT_POINTER(info);
+
+ if (NULL != pagedir->page_directory_mapped)
+ {
+ int i;
+
+ MALI_CHECK_NO_ERROR(
+ dump_page(pagedir->page_directory_mapped, pagedir->page_directory, info)
+ );
+
+ for (i = 0; i < 1024; i++)
+ {
+ if (NULL != pagedir->page_entries_mapped[i])
+ {
+ MALI_CHECK_NO_ERROR(
+ dump_page(pagedir->page_entries_mapped[i],
+ _mali_osk_mem_ioread32(pagedir->page_directory_mapped,
+ i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info)
+ );
+ }
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_registers(struct mali_page_directory *pagedir, struct dump_info * info)
+{
+ MALI_CHECK_NO_ERROR(writereg(0x00000000, pagedir->page_directory,
+ "set the page directory address", info));
+ MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info));
+ MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info));
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args )
+{
+ struct dump_info info = { 0, 0, 0, NULL };
+ struct mali_session_data * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)(args->ctx);
+
+ MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info));
+ MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info));
+ args->size = info.register_writes_size + info.page_table_dump_size;
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args )
+{
+ struct dump_info info = { 0, 0, 0, NULL };
+ struct mali_session_data * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)(args->ctx);
+
+ info.buffer_left = args->size;
+ info.buffer = args->buffer;
+
+ args->register_writes = info.buffer;
+ MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info));
+
+ args->page_table_dump = info.buffer;
+ MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info));
+
+ args->register_writes_size = info.register_writes_size;
+ args->page_table_dump_size = info.page_table_dump_size;
+
+ MALI_SUCCESS;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h
new file mode 100644
index 0000000..8aababe
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h
@@ -0,0 +1,83 @@
+/*
+ * 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_MMU_PAGE_DIRECTORY_H__
+#define __MALI_MMU_PAGE_DIRECTORY_H__
+
+#include "mali_osk.h"
+
+/**
+ * Size of an MMU page in bytes
+ */
+#define MALI_MMU_PAGE_SIZE 0x1000
+
+/*
+ * Size of the address space referenced by a page table page
+ */
+#define MALI_MMU_VIRTUAL_PAGE_SIZE 0x400000 /* 4 MiB */
+
+/**
+ * Page directory index from address
+ * Calculates the page directory index from the given address
+ */
+#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF)
+
+/**
+ * Page table index from address
+ * Calculates the page table index from the given address
+ */
+#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF)
+
+/**
+ * Extract the memory address from an PDE/PTE entry
+ */
+#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00)
+
+#define MALI_INVALID_PAGE ((u32)(~0))
+
+/**
+ *
+ */
+typedef enum mali_mmu_entry_flags
+{
+ MALI_MMU_FLAGS_PRESENT = 0x01,
+ MALI_MMU_FLAGS_READ_PERMISSION = 0x02,
+ MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04,
+ MALI_MMU_FLAGS_MASK = 0x07
+} mali_mmu_entry_flags;
+
+
+struct mali_page_directory
+{
+ u32 page_directory; /**< Physical address of the memory session's page directory */
+ mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */
+
+ mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */
+ u32 page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */
+};
+
+/* Map Mali virtual address space (i.e. ensure page tables exist for the virtual range) */
+_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size);
+_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size);
+
+/* Back virtual address space with actual pages. Assumes input is contiguous and 4k aligned. */
+void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size);
+
+u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index);
+
+u32 mali_allocate_empty_page(void);
+void mali_free_empty_page(u32 address);
+_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page);
+void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page);
+
+struct mali_page_directory *mali_mmu_pagedir_alloc(void);
+void mali_mmu_pagedir_free(struct mali_page_directory *pagedir);
+
+#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_osk.h b/drivers/media/video/samsung/mali/common/mali_osk.h
index 72d851d..e32d15d 100644
--- a/drivers/media/video/samsung/mali/common/mali_osk.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -165,9 +165,6 @@ typedef void (*_mali_osk_irq_bhandler_t)( void * arg );
* This is public for allocation on stack. On systems that support it, this is just a single 32-bit value.
* On others, it could be encapsulating an object stored elsewhere.
*
- * Even though the structure has space for a u32, the counters will only
- * represent signed 24-bit integers.
- *
* Regardless of implementation, the \ref _mali_osk_atomic functions \b must be used
* for all accesses to the variable's value, even if atomicity is not required.
* Do not access u.val or u.obj directly.
@@ -186,6 +183,40 @@ typedef struct
/** @defgroup _mali_osk_lock OSK Mutual Exclusion Locks
* @{ */
+
+/** @brief OSK Mutual Exclusion Lock ordered list
+ *
+ * This lists the various types of locks in the system and is used to check
+ * that locks are taken in the correct order.
+ *
+ * Holding more than one lock of the same order at the same time is not
+ * allowed.
+ *
+ */
+typedef enum
+{
+ _MALI_OSK_LOCK_ORDER_LAST = 0,
+
+ _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,
+
+ _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_FIRST
+} _mali_osk_lock_order_t;
+
+
/** @brief OSK Mutual Exclusion Lock flags type
*
* Flags are supplied at the point where the Lock is initialized. Each flag can
@@ -271,6 +302,17 @@ typedef enum
/** @brief Private type for Mutual Exclusion lock objects */
typedef struct _mali_osk_lock_t_struct _mali_osk_lock_t;
+
+#ifdef DEBUG
+/** @brief Macro for asserting that the current thread holds a given lock
+ */
+#define MALI_DEBUG_ASSERT_LOCK_HELD(l) MALI_DEBUG_ASSERT(_mali_osk_lock_get_owner(l) == _mali_osk_get_tid());
+
+/** @brief returns a lock's owner (thread id) if debugging is enabled
+ */
+u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock );
+#endif
+
/** @} */ /* end group _mali_osk_lock */
/** @defgroup _mali_osk_low_level_memory OSK Low-level Memory Operations
@@ -368,7 +410,6 @@ typedef struct _mali_osk_notification_queue_t_struct _mali_osk_notification_queu
/** @brief Public notification data object type */
typedef struct _mali_osk_notification_t_struct
{
- u32 magic_code;
u32 notification_type; /**< The notification type */
u32 result_buffer_size; /**< Size of the result buffer to copy to user space */
void * result_buffer; /**< Buffer containing any type specific data */
@@ -527,20 +568,35 @@ typedef struct _mali_osk_list_s
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 */
- MALI200 =3, /**< Mali200 Programmable Fragment Shader */
- MALIGP2 =4, /**< MaliGP2 Programmable Vertex Shader */
- MMU =5, /**< Mali MMU (Memory Management Unit) */
- FPGA_FRAMEWORK =6, /**< Mali registers specific to FPGA implementations */
- MALI400L2 =7, /**< Mali400 L2 Cache */
- MALI300L2 =7, /**< Mali300 L2 Cache */
- MALI400GP =8, /**< Mali400 Programmable Vertex Shader Core */
- MALI300GP =8, /**< Mali300 Programmable Vertex Shader Core */
- MALI400PP =9, /**< Mali400 Programmable Fragment Shader Core */
- MALI300PP =9, /**< Mali300 Programmable Fragment Shader Core */
- MEM_VALIDATION =10, /**< External Memory Validator */
- PMU =11, /**< Power Manangement Unit */
+
+ 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;
@@ -726,11 +782,6 @@ void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom );
/** @brief Decrement an atomic counter, return new value
*
- * Although the value returned is a u32, only numbers with signed 24-bit
- * precision (sign extended to u32) are returned.
- *
- * @note It is an error to decrement the counter beyond -(1<<23)
- *
* @param atom pointer to an atomic counter
* @return The new value, after decrement */
u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom );
@@ -744,19 +795,11 @@ void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom );
/** @brief Increment an atomic counter, return new value
*
- * Although the value returned is a u32, only numbers with signed 24-bit
- * precision (sign extended to u32) are returned.
- *
- * @note It is an error to increment the counter beyond (1<<23)-1
- *
* @param atom pointer to an atomic counter */
u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom );
/** @brief Initialize an atomic counter
*
- * The counters have storage for signed 24-bit integers. Initializing to signed
- * values requiring more than 24-bits storage will fail.
- *
* @note the parameter required is a u32, and so signed integers should be
* cast to u32.
*
@@ -769,9 +812,6 @@ _mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val );
/** @brief Read a value from an atomic counter
*
- * Although the value returned is a u32, only numbers with signed 24-bit
- * precision (sign extended to u32) are returned.
- *
* This can only be safely used to determine the value of the counter when it
* is guaranteed that other threads will not be modifying the counter. This
* makes its usefulness limited.
@@ -1624,6 +1664,41 @@ u64 _mali_osk_time_get_ns( void );
u32 _mali_osk_clz( u32 val );
/** @} */ /* end group _mali_osk_math */
+/** @defgroup _mali_osk_wait_queue OSK Wait Queue functionality
+ * @{ */
+/** @brief Private type for wait queue objects */
+typedef struct _mali_osk_wait_queue_t_struct _mali_osk_wait_queue_t;
+
+/** @brief Initialize an empty Wait Queue */
+_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void );
+
+/** @brief Sleep if condition is false
+ *
+ * @param queue the queue to use
+ * @param condition function pointer to a boolean function
+ *
+ * Put thread to sleep if the given \a codition function returns false. When
+ * being asked to wake up again, the condition will be re-checked and the
+ * thread only woken up if the condition is now true.
+ */
+void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) );
+
+/** @brief Wake up all threads in wait queue if their respective conditions are
+ * true
+ *
+ * @param queue the queue whose threads should be woken up
+ *
+ * Wake up all threads in wait queue \a queue whose condition is now true.
+ */
+void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue );
+
+/** @brief terminate a wait queue
+ *
+ * @param queue the queue to terminate.
+ */
+void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue );
+/** @} */ /* end group _mali_osk_wait_queue */
+
/** @addtogroup _mali_osk_miscellaneous
* @{ */
@@ -1647,6 +1722,7 @@ void _mali_osk_dbgmsg( const char *fmt, ... );
* @param size the total number of bytes allowed to write to \a buf
* @param fmt a _mali_osu_vsnprintf() style format string
* @param ... a variable-number of parameters suitable for \a fmt
+ * @return The number of bytes written to \a buf
*/
u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... );
@@ -1685,13 +1761,19 @@ u32 _mali_osk_get_pid(void);
*/
u32 _mali_osk_get_tid(void);
-void _mali_osk_profiling_add_event(u32 event_id, u32 data0);
-void _mali_osk_profiling_add_counter(u32 event_id, u32 data0);
-int _mali_osk_counter_event(u32 counter, u32 event);
-extern u32 counter_table[];
+/** @brief Enable OS controlled runtime power management
+ */
+void _mali_osk_pm_dev_enable(void);
-/** @} */ /* end group _mali_osk_miscellaneous */
+/** @brief Tells the OS that device is now idle
+ */
+_mali_osk_errcode_t _mali_osk_pm_dev_idle(void);
+/** @brief Tells the OS that the device is about to become active
+ */
+_mali_osk_errcode_t _mali_osk_pm_dev_activate(void);
+
+/** @} */ /* end group _mali_osk_miscellaneous */
/** @} */ /* end group osuapi */
diff --git a/drivers/media/video/samsung/mali/common/mali_osk_list.h b/drivers/media/video/samsung/mali/common/mali_osk_list.h
index 3a562bb..a8d15f2 100644
--- a/drivers/media/video/samsung/mali/common/mali_osk_list.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk_list.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 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/common/mali_osk_mali.h b/drivers/media/video/samsung/mali/common/mali_osk_mali.h
index 0b1d13a..427fcc8 100644
--- a/drivers/media/video/samsung/mali/common/mali_osk_mali.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk_mali.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -26,36 +26,6 @@ extern "C"
/** @addtogroup _mali_osk_miscellaneous
* @{ */
-/** @brief Initialize the OSK layer
- *
- * This function is used to setup any initialization of OSK functionality, if
- * required.
- *
- * This must be the first function called from the common code, specifically,
- * from the common code entry-point, mali_kernel_constructor.
- *
- * The OS-integration into the OS's kernel must handle calling of
- * mali_kernel_constructor when the device driver is loaded.
- *
- * @return _MALI_OSK_ERR_OK on success, or a suitable _mali_osk_errcode_t on
- * failure.
- */
-_mali_osk_errcode_t _mali_osk_init( void );
-
-/** @brief Terminate the OSK layer
- *
- * This function is used to terminate any resources initialized by
- * _mali_osk_init.
- *
- * This must be the last function called from the common code, specifically,
- * from the common code closedown function, mali_kernel_destructor, and the
- * error path in mali_kernel_constructor.
- *
- * The OS-integration into the OS's kernel must handle calling of
- * mali_kernel_destructor when the device driver is terminated.
- */
-void _mali_osk_term( void );
-
/** @brief Read the Mali Resource configuration
*
* Populates a _mali_arch_resource_t array from configuration settings, which
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.h b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h
index eb1e6c2..fd9a8fb 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,31 +8,34 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_PROFILING_H__
-#define __MALI_KERNEL_PROFILING_H__
+#ifndef __MALI_OSK_PROFILING_H__
+#define __MALI_OSK_PROFILING_H__
#if MALI_TIMELINE_PROFILING_ENABLED
-#include "cinstr/mali_cinstr_profiling_events_m200.h"
+#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"
#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576
+#define MALI_PROFILING_NO_HW_COUNTER = ((u32)-1)
+
+/** @defgroup _mali_osk_profiling External profiling connectivity
+ * @{ */
+
/**
* Initialize the profiling module.
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_init(mali_bool auto_start);
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start);
/*
* Terminate the profiling module.
*/
-void _mali_profiling_term(void);
-
-/** Add a counter event
- * @param event_id - Magic counter id
- * @param data0 - Value of counter
- */
-void _mali_profiling_add_counter(u32 event_id, u32 data0);
+void _mali_osk_profiling_term(void);
/**
* Start recording profiling data
@@ -43,7 +46,7 @@ void _mali_profiling_add_counter(u32 event_id, u32 data0);
* @param limit The desired maximum number of events to record on input, the actual maximum on output.
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_start(u32 * limit);
+_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit);
/**
* Add an profiling event
@@ -56,7 +59,35 @@ _mali_osk_errcode_t _mali_profiling_start(u32 * limit);
* @param data4 Fifth data parameter, depending on event_id specified.
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4);
+#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.
+ *
+ * @param counter_id The ID of the counter.
+ * @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
+ *
+ * @param counters array of counter values
+ */
+void _mali_osk_profiling_report_sw_counters(u32 *counters);
/**
* Stop recording profiling data
@@ -64,14 +95,14 @@ _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1
* @param count Returns the number of recorded events.
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_stop(u32 * count);
+_mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count);
/**
* Retrieves the number of events that can be retrieved
*
* @return The number of recorded events that can be retrieved.
*/
-u32 _mali_profiling_get_count(void);
+u32 _mali_osk_profiling_get_count(void);
/**
* Retrieve an event
@@ -81,7 +112,8 @@ u32 _mali_profiling_get_count(void);
* @param event_id The event ID for the retrieved event will be stored here.
* @param data The 5 data values for the retrieved event will be stored here.
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
- */_mali_osk_errcode_t _mali_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]);
+ */
+_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]);
/**
* Clear the recorded buffer.
@@ -90,38 +122,26 @@ u32 _mali_profiling_get_count(void);
*
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_clear(void);
+_mali_osk_errcode_t _mali_osk_profiling_clear(void);
/**
* Checks if a recording of profiling data is in progress
*
* @return MALI_TRUE if recording of profiling data is in progress, MALI_FALSE if not
*/
-mali_bool _mali_profiling_is_recording(void);
+mali_bool _mali_osk_profiling_is_recording(void);
/**
* Checks if profiling data is available for retrival
*
* @return MALI_TRUE if profiling data is avaiable, MALI_FALSE if not
*/
-mali_bool _mali_profiling_have_recording(void);
+mali_bool _mali_osk_profiling_have_recording(void);
-/**
- * Enable or disable profiling events as default for new sessions (applications)
- *
- * @param enable MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE
- */
-void _mali_profiling_set_default_enable_state(mali_bool enable);
-
-/**
- * Get current default enable state for new sessions (applications)
- *
- * @return MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE
- */
-mali_bool _mali_profiling_get_default_enable_state(void);
+/** @} */ /* end group _mali_osk_profiling */
#endif /* MALI_TIMELINE_PROFILING_ENABLED */
-#endif /* __MALI_KERNEL_PROFILING_H__ */
+#endif /* __MALI_OSK_PROFILING_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pm.c b/drivers/media/video/samsung/mali/common/mali_pm.c
new file mode 100644
index 0000000..1ef3807
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pm.c
@@ -0,0 +1,547 @@
+/*
+ * 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)
+{
+ 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);
+
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+
+ /* Aquire our reference */
+ MALI_DEBUG_PRINT(4, ("Mali PM: Getting device PM reference (=> requesting MALI_POWER_MODE_ON)\n"));
+ _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();
+ }
+ mali_platform_power_mode_change(power_mode);
+
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ _mali_osk_pm_dev_idle();
+#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"));
+}
+
+void mali_pm_runtime_resume(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali PM: OS runtime resumed\n"));
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_pm.h b/drivers/media/video/samsung/mali/common/mali_pm.h
new file mode 100644
index 0000000..d4ccfde
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pm.h
@@ -0,0 +1,56 @@
+/*
+ * 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_PM_H__
+#define __MALI_PM_H__
+
+#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);
+
+void mali_pm_os_suspend(void);
+void mali_pm_os_resume(void);
+void mali_pm_runtime_suspend(void);
+void mali_pm_runtime_resume(void);
+
+
+#endif /* __MALI_PM_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.c b/drivers/media/video/samsung/mali/common/mali_pmu.c
new file mode 100644
index 0000000..348b5dc
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pmu.c
@@ -0,0 +1,199 @@
+/*
+ * 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_pmu.h b/drivers/media/video/samsung/mali/common/mali_pmu.h
new file mode 100644
index 0000000..fd10c08
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pmu.h
@@ -0,0 +1,70 @@
+/*
+ * 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
+ */
+
+#include "mali_osk.h"
+
+struct mali_pmu_core;
+
+/** @brief Initialisation of MALI PMU
+ *
+ * This is called from entry point of the driver in order to create and intialize the PMU resource
+ *
+ * @param resource it will be a pointer to a PMU resource
+ * @param number_of_pp_cores Number of found PP resources in configuration
+ * @param number_of_l2_caches Number of found L2 cache resources in configuration
+ * @return The created PMU object, or NULL in case of failure.
+ */
+struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches);
+
+/** @brief It deallocates the PMU resource
+ *
+ * This is called on the exit of the driver to terminate the PMU resource
+ *
+ * @param pmu Pointer to PMU core object to delete
+ */
+void mali_pmu_delete(struct mali_pmu_core *pmu);
+
+/** @brief Reset PMU core
+ *
+ * @param pmu Pointer to PMU core object to reset
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_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
+ *
+ * @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_powerdown_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);
+
+
+/** @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);
diff --git a/drivers/media/video/samsung/mali/common/mali_pp.c b/drivers/media/video/samsung/mali/common/mali_pp.c
new file mode 100644
index 0000000..5549f82
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp.c
@@ -0,0 +1,710 @@
+/*
+ * 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
new file mode 100644
index 0000000..9b425a0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp.h
@@ -0,0 +1,47 @@
+/*
+ * 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
new file mode 100644
index 0000000..1efcfda
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_job.c
@@ -0,0 +1,92 @@
+/*
+ * 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;
+ _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_job.h b/drivers/media/video/samsung/mali/common/mali_pp_job.h
new file mode 100644
index 0000000..7fe87f8
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_job.h
@@ -0,0 +1,255 @@
+/*
+ * 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_JOB_H__
+#define __MALI_PP_JOB_H__
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+#include "mali_session.h"
+#include "mali_kernel_common.h"
+#include "regs/mali_200_regs.h"
+
+/**
+ * The structure represends a PP job, including all sub-jobs
+ * (This struct unfortunatly 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) */
+ 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 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 */
+};
+
+struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, 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:
+ *****************************************************/
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job)
+{
+ return (NULL == job) ? 0 : job->id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job)
+{
+ return job->user_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job)
+{
+ return job->frame_builder_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job)
+{
+ return job->flush_id;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job)
+{
+ return job->frame_registers;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job)
+{
+ if (sub_job == 0)
+ {
+ return job->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 0;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job)
+{
+ if (sub_job == 0)
+ {
+ return job->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 0;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job)
+{
+ return job->wb0_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job)
+{
+ return job->wb1_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job)
+{
+ return job->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;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job)
+{
+ job->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;
+}
+
+MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job)
+{
+ return job->session;
+}
+
+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;
+}
+
+/* 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)
+{
+ /* 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;
+}
+
+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;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job)
+{
+ return job->sub_jobs_started;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job)
+{
+ return job->sub_job_count;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job)
+{
+ /* Assert that we are marking the "first unstarted sub job" as started */
+ MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job);
+ job->sub_jobs_started++;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success)
+{
+ job->sub_jobs_completed++;
+ if ( MALI_FALSE == success )
+ {
+ job->sub_job_errors++;
+ }
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job)
+{
+ if ( 0 == job->sub_job_errors )
+ {
+ return MALI_TRUE;
+ }
+ return MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job)
+{
+ return job->perf_counter_flag;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job)
+{
+ return job->perf_counter_src0;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job)
+{
+ return job->perf_counter_src1;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job)
+{
+ return job->perf_counter_value0[sub_job];
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job)
+{
+ return job->perf_counter_value1[sub_job];
+}
+
+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;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value)
+{
+ job->perf_counter_value1[sub_job] = value;
+}
+
+#endif /* __MALI_PP_JOB_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c
new file mode 100644
index 0000000..ce07a76
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c
@@ -0,0 +1,542 @@
+/*
+ * 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;
+};
+
+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;
+ 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 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_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;
+ 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)
+{
+ _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;
+ 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 */
+ }
+
+ 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
new file mode 100644
index 0000000..48eb3bd
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h
@@ -0,0 +1,38 @@
+/*
+ * 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/common/mali_scheduler.c b/drivers/media/video/samsung/mali/common/mali_scheduler.c
new file mode 100644
index 0000000..52159a0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_scheduler.c
@@ -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.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+static _mali_osk_atomic_t mali_job_autonumber;
+
+_mali_osk_errcode_t mali_scheduler_initialize(void)
+{
+ if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_autonumber, 0))
+ {
+ MALI_DEBUG_PRINT(1, ("Initialization of atomic job id counter failed.\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_scheduler_terminate(void)
+{
+ _mali_osk_atomic_term(&mali_job_autonumber);
+}
+
+u32 mali_scheduler_get_new_id(void)
+{
+ u32 job_id = _mali_osk_atomic_inc_return(&mali_job_autonumber);
+ return job_id;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem.h b/drivers/media/video/samsung/mali/common/mali_scheduler.h
index 8caafe3..74f0947 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem.h
+++ b/drivers/media/video/samsung/mali/common/mali_scheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,10 +8,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_MEM_H__
-#define __MALI_KERNEL_MEM_H__
+#ifndef __MALI_SCHEDULER_H__
+#define __MALI_SCHEDULER_H__
-#include "mali_kernel_subsystem.h"
-extern struct mali_kernel_subsystem mali_subsystem_memory;
+#include "mali_osk.h"
-#endif /* __MALI_KERNEL_MEM_H__ */
+_mali_osk_errcode_t mali_scheduler_initialize(void);
+void mali_scheduler_terminate(void);
+
+u32 mali_scheduler_get_new_id(void);
+
+#endif /* __MALI_SCHEDULER_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_session.c b/drivers/media/video/samsung/mali/common/mali_session.c
new file mode 100644
index 0000000..2394bb9
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_session.c
@@ -0,0 +1,47 @@
+/*
+ * 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_osk.h"
+#include "mali_osk_list.h"
+#include "mali_session.h"
+
+_MALI_OSK_LIST_HEAD(mali_sessions);
+
+_mali_osk_lock_t *mali_sessions_lock;
+
+_mali_osk_errcode_t mali_session_initialize(void)
+{
+ _MALI_OSK_INIT_LIST_HEAD(&mali_sessions);
+
+ mali_sessions_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_SESSIONS);
+
+ if (NULL == mali_sessions_lock) return _MALI_OSK_ERR_NOMEM;
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_session_terminate(void)
+{
+ _mali_osk_lock_term(mali_sessions_lock);
+}
+
+void mali_session_add(struct mali_session_data *session)
+{
+ mali_session_lock();
+ _mali_osk_list_add(&session->link, &mali_sessions);
+ mali_session_unlock();
+}
+
+void mali_session_remove(struct mali_session_data *session)
+{
+ mali_session_lock();
+ _mali_osk_list_delinit(&session->link);
+ mali_session_unlock();
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_session.h b/drivers/media/video/samsung/mali/common/mali_session.h
new file mode 100644
index 0000000..b47c340
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_session.h
@@ -0,0 +1,65 @@
+/*
+ * 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_SESSION_H__
+#define __MALI_SESSION_H__
+
+#include "mali_mmu_page_directory.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+
+struct mali_session_data
+{
+ _mali_osk_notification_queue_t * ioctl_queue;
+
+ _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 */
+
+ 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_errcode_t mali_session_initialize(void);
+void mali_session_terminate(void);
+
+/* List of all sessions. Actual list head in mali_kernel_core.c */
+extern _mali_osk_list_t mali_sessions;
+/* Lock to protect modification and access to the mali_sessions list */
+extern _mali_osk_lock_t *mali_sessions_lock;
+
+MALI_STATIC_INLINE void mali_session_lock(void)
+{
+ _mali_osk_lock_wait(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+MALI_STATIC_INLINE void mali_session_unlock(void)
+{
+ _mali_osk_lock_signal(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+void mali_session_add(struct mali_session_data *session);
+void mali_session_remove(struct mali_session_data *session);
+#define MALI_SESSION_FOREACH(session, tmp, link) \
+ _MALI_OSK_LIST_FOREACHENTRY(session, tmp, &mali_sessions, struct mali_session_data, link)
+
+MALI_STATIC_INLINE struct mali_page_directory *mali_session_get_page_directory(struct mali_session_data *session)
+{
+ return session->page_directory;
+}
+
+MALI_STATIC_INLINE void mali_session_send_notification(struct mali_session_data *session, _mali_osk_notification_t *object)
+{
+ _mali_osk_notification_queue_send(session->ioctl_queue, object);
+}
+
+#endif /* __MALI_SESSION_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_uk_types.h b/drivers/media/video/samsung/mali/common/mali_uk_types.h
deleted file mode 100644
index e114fa8..0000000
--- a/drivers/media/video/samsung/mali/common/mali_uk_types.h
+++ /dev/null
@@ -1,1176 +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.
- */
-
-/**
- * @file mali_uk_types.h
- * Defines the types and constants used in the user-kernel interface
- */
-
-#ifndef __MALI_UK_TYPES_H__
-#define __MALI_UK_TYPES_H__
-
-/*
- * NOTE: Because this file can be included from user-side and kernel-side,
- * it is up to the includee to ensure certain typedefs (e.g. u32) are already
- * defined when #including this.
- */
-#include "regs/mali_200_regs.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @addtogroup uddapi Unified Device Driver (UDD) APIs
- *
- * @{
- */
-
-/**
- * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs
- *
- * @{
- */
-
-/** @defgroup _mali_uk_core U/K Core
- * @{ */
-
-/** Definition of subsystem numbers, to assist in creating a unique identifier
- * for each U/K call.
- *
- * @see _mali_uk_functions */
-typedef enum
-{
- _MALI_UK_CORE_SUBSYSTEM, /**< Core Group of U/K calls */
- _MALI_UK_MEMORY_SUBSYSTEM, /**< Memory Group of U/K calls */
- _MALI_UK_PP_SUBSYSTEM, /**< Fragment Processor Group of U/K calls */
- _MALI_UK_GP_SUBSYSTEM, /**< Vertex Processor Group of U/K calls */
- _MALI_UK_PROFILING_SUBSYSTEM, /**< Profiling Group of U/K calls */
- _MALI_UK_PMM_SUBSYSTEM, /**< Power Management Module Group of U/K calls */
- _MALI_UK_VSYNC_SUBSYSTEM, /**< VSYNC Group of U/K calls */
-} _mali_uk_subsystem_t;
-
-/** Within a function group each function has its unique sequence number
- * to assist in creating a unique identifier for each U/K call.
- *
- * An ordered pair of numbers selected from
- * ( \ref _mali_uk_subsystem_t,\ref _mali_uk_functions) will uniquely identify the
- * U/K call across all groups of functions, and all functions. */
-typedef enum
-{
- /** Core functions */
-
- _MALI_UK_OPEN = 0, /**< _mali_ukk_open() */
- _MALI_UK_CLOSE, /**< _mali_ukk_close() */
- _MALI_UK_GET_SYSTEM_INFO_SIZE, /**< _mali_ukk_get_system_info_size() */
- _MALI_UK_GET_SYSTEM_INFO, /**< _mali_ukk_get_system_info() */
- _MALI_UK_WAIT_FOR_NOTIFICATION, /**< _mali_ukk_wait_for_notification() */
- _MALI_UK_GET_API_VERSION, /**< _mali_ukk_get_api_version() */
- _MALI_UK_POST_NOTIFICATION, /**< _mali_ukk_post_notification() */
-
- /** Memory functions */
-
- _MALI_UK_INIT_MEM = 0, /**< _mali_ukk_init_mem() */
- _MALI_UK_TERM_MEM, /**< _mali_ukk_term_mem() */
- _MALI_UK_GET_BIG_BLOCK, /**< _mali_ukk_get_big_block() */
- _MALI_UK_FREE_BIG_BLOCK, /**< _mali_ukk_free_big_block() */
- _MALI_UK_MAP_MEM, /**< _mali_ukk_mem_mmap() */
- _MALI_UK_UNMAP_MEM, /**< _mali_ukk_mem_munmap() */
- _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, /**< _mali_ukk_mem_get_mmu_page_table_dump_size() */
- _MALI_UK_DUMP_MMU_PAGE_TABLE, /**< _mali_ukk_mem_dump_mmu_page_table() */
- _MALI_UK_ATTACH_UMP_MEM, /**< _mali_ukk_attach_ump_mem() */
- _MALI_UK_RELEASE_UMP_MEM, /**< _mali_ukk_release_ump_mem() */
- _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() */
-
- /** Common functions for each core */
-
- _MALI_UK_START_JOB = 0, /**< Start a Fragment/Vertex Processor Job on a core */
- _MALI_UK_ABORT_JOB, /**< Abort a job */
- _MALI_UK_GET_NUMBER_OF_CORES, /**< Get the number of Fragment/Vertex Processor cores */
- _MALI_UK_GET_CORE_VERSION, /**< Get the Fragment/Vertex Processor version compatible with all cores */
-
- /** Fragment Processor Functions */
-
- _MALI_UK_PP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_pp_start_job() */
- _MALI_UK_PP_ABORT_JOB = _MALI_UK_ABORT_JOB, /**< _mali_ukk_pp_abort_job() */
- _MALI_UK_GET_PP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_pp_number_of_cores() */
- _MALI_UK_GET_PP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_pp_core_version() */
-
- /** Vertex Processor Functions */
-
- _MALI_UK_GP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_gp_start_job() */
- _MALI_UK_GP_ABORT_JOB = _MALI_UK_ABORT_JOB, /**< _mali_ukk_gp_abort_job() */
- _MALI_UK_GET_GP_NUMBER_OF_CORES = _MALI_UK_GET_NUMBER_OF_CORES, /**< _mali_ukk_get_gp_number_of_cores() */
- _MALI_UK_GET_GP_CORE_VERSION = _MALI_UK_GET_CORE_VERSION, /**< _mali_ukk_get_gp_core_version() */
- _MALI_UK_GP_SUSPEND_RESPONSE, /**< _mali_ukk_gp_suspend_response() */
-
- /** Profiling functions */
-
- _MALI_UK_PROFILING_START = 0, /**< __mali_uku_profiling_start() */
- _MALI_UK_PROFILING_ADD_EVENT, /**< __mali_uku_profiling_add_event() */
- _MALI_UK_PROFILING_STOP, /**< __mali_uku_profiling_stop() */
- _MALI_UK_PROFILING_GET_EVENT, /**< __mali_uku_profiling_get_event() */
- _MALI_UK_PROFILING_CLEAR, /**< __mali_uku_profiling_clear() */
- _MALI_UK_PROFILING_GET_CONFIG, /**< __mali_uku_profiling_get_config() */
- _MALI_UK_TRANSFER_SW_COUNTERS,
-
-#if USING_MALI_PMM
- /** Power Management Module Functions */
- _MALI_UK_PMM_EVENT_MESSAGE = 0, /**< Raise an event message */
-#endif
-
- /** VSYNC reporting fuctions */
- _MALI_UK_VSYNC_EVENT_REPORT = 0, /**< _mali_ukk_vsync_event_report() */
-
-} _mali_uk_functions;
-
-/** @brief Get the size necessary for system info
- *
- * @see _mali_ukk_get_system_info_size()
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 size; /**< [out] size of buffer necessary to hold system information data, in bytes */
-} _mali_uk_get_system_info_size_s;
-
-
-/** @defgroup _mali_uk_getsysteminfo U/K Get System Info
- * @{ */
-
-/**
- * Type definition for the core version number.
- * Used when returning the version number read from a core
- *
- * Its format is that of the 32-bit Version register for a particular core.
- * Refer to the "Mali200 and MaliGP2 3D Graphics Processor Technical Reference
- * Manual", ARM DDI 0415C, for more information.
- */
-typedef u32 _mali_core_version;
-
-/**
- * Enum values for the different modes the driver can be put in.
- * Normal is the default mode. The driver then uses a job queue and takes job objects from the clients.
- * Job completion is reported using the _mali_ukk_wait_for_notification call.
- * The driver blocks this io command until a job has completed or failed or a timeout occurs.
- *
- * The 'raw' mode is reserved for future expansion.
- */
-typedef enum _mali_driver_mode
-{
- _MALI_DRIVER_MODE_RAW = 1, /**< Reserved for future expansion */
- _MALI_DRIVER_MODE_NORMAL = 2 /**< Normal mode of operation */
-} _mali_driver_mode;
-
-/** @brief List of possible cores
- *
- * add new entries to the end of this enum */
-typedef enum _mali_core_type
-{
- _MALI_GP2 = 2, /**< MaliGP2 Programmable Vertex Processor */
- _MALI_200 = 5, /**< Mali200 Programmable Fragment Processor */
- _MALI_400_GP = 6, /**< Mali400 Programmable Vertex Processor */
- _MALI_400_PP = 7, /**< Mali400 Programmable Fragment Processor */
- /* insert new core here, do NOT alter the existing values */
-} _mali_core_type;
-
-/** @brief Information about each Mali Core
- *
- * Information is stored in a linked list, which is stored entirely in the
- * buffer pointed to by the system_info member of the
- * _mali_uk_get_system_info_s arguments provided to _mali_ukk_get_system_info()
- *
- * Both Fragment Processor (PP) and Vertex Processor (GP) cores are represented
- * by this struct.
- *
- * The type is reported by the type field, _mali_core_info::_mali_core_type.
- *
- * Each core is given a unique Sequence number identifying it, the core_nr
- * member.
- *
- * Flags are taken directly from the resource's flags, and are currently unused.
- *
- * Multiple mali_core_info structs are linked in a single linked list using the next field
- */
-typedef struct _mali_core_info
-{
- _mali_core_type type; /**< Type of core */
- _mali_core_version version; /**< Core Version, as reported by the Core's Version Register */
- u32 reg_address; /**< Address of Registers */
- u32 core_nr; /**< Sequence number */
- u32 flags; /**< Flags. Currently Unused. */
- struct _mali_core_info * next; /**< Next core in Linked List */
-} _mali_core_info;
-
-/** @brief Capabilities of Memory Banks
- *
- * These may be used to restrict memory banks for certain uses. They may be
- * used when access is not possible (e.g. Bus does not support access to it)
- * or when access is possible but not desired (e.g. Access is slow).
- *
- * In the case of 'possible but not desired', there is no way of specifying
- * the flags as an optimization hint, so that the memory could be used as a
- * last resort.
- *
- * @see _mali_mem_info
- */
-typedef enum _mali_bus_usage
-{
-
- _MALI_PP_READABLE = (1<<0), /** Readable by the Fragment Processor */
- _MALI_PP_WRITEABLE = (1<<1), /** Writeable by the Fragment Processor */
- _MALI_GP_READABLE = (1<<2), /** Readable by the Vertex Processor */
- _MALI_GP_WRITEABLE = (1<<3), /** Writeable by the Vertex Processor */
- _MALI_CPU_READABLE = (1<<4), /** Readable by the CPU */
- _MALI_CPU_WRITEABLE = (1<<5), /** Writeable by the CPU */
- _MALI_MMU_READABLE = _MALI_PP_READABLE | _MALI_GP_READABLE, /** Readable by the MMU (including all cores behind it) */
- _MALI_MMU_WRITEABLE = _MALI_PP_WRITEABLE | _MALI_GP_WRITEABLE, /** Writeable by the MMU (including all cores behind it) */
-} _mali_bus_usage;
-
-/** @brief Information about the Mali Memory system
- *
- * Information is stored in a linked list, which is stored entirely in the
- * buffer pointed to by the system_info member of the
- * _mali_uk_get_system_info_s arguments provided to _mali_ukk_get_system_info()
- *
- * Each element of the linked list describes a single Mali Memory bank.
- * Each allocation can only come from one bank, and will not cross multiple
- * banks.
- *
- * Each bank is uniquely identified by its identifier member. On Mali-nonMMU
- * systems, to allocate from this bank, the value of identifier must be passed
- * as the type_id member of the _mali_uk_get_big_block_s arguments to
- * _mali_ukk_get_big_block.
- *
- * On Mali-MMU systems, there is only one bank, which describes the maximum
- * possible address range that could be allocated (which may be much less than
- * the available physical memory)
- *
- * The flags member describes the capabilities of the memory. It is an error
- * to attempt to build a job for a particular core (PP or GP) when the memory
- * regions used do not have the capabilities for supporting that core. This
- * would result in a job abort from the Device Driver.
- *
- * For example, it is correct to build a PP job where read-only data structures
- * are taken from a memory with _MALI_PP_READABLE set and
- * _MALI_PP_WRITEABLE clear, and a framebuffer with _MALI_PP_WRITEABLE set and
- * _MALI_PP_READABLE clear. However, it would be incorrect to use a framebuffer
- * where _MALI_PP_WRITEABLE is clear.
- */
-typedef struct _mali_mem_info
-{
- u32 size; /**< Size of the memory bank in bytes */
- _mali_bus_usage flags; /**< Capabilitiy flags of the memory */
- u32 maximum_order_supported; /**< log2 supported size */
- u32 identifier; /**< Unique identifier, to be used in allocate calls */
- struct _mali_mem_info * next; /**< Next List Link */
-} _mali_mem_info;
-
-/** @brief Info about the whole Mali system.
- *
- * This Contains a linked list of the cores and memory banks available. Each
- * list pointer will remain inside the system_info buffer supplied in the
- * _mali_uk_get_system_info_s arguments to a _mali_ukk_get_system_info call.
- *
- * The has_mmu member must be inspected to ensure the correct group of
- * Memory function calls is obtained - that is, those for either Mali-MMU
- * or Mali-nonMMU. @see _mali_uk_memory
- */
-typedef struct _mali_system_info
-{
- _mali_core_info * core_info; /**< List of _mali_core_info structures */
- _mali_mem_info * mem_info; /**< List of _mali_mem_info structures */
- u32 has_mmu; /**< Non-zero if Mali-MMU present. Zero otherwise. */
- _mali_driver_mode drivermode; /**< Reserved. Must always be _MALI_DRIVER_MODE_NORMAL */
-} _mali_system_info;
-
-/** @brief Arguments to _mali_ukk_get_system_info()
- *
- * A buffer of the size returned by _mali_ukk_get_system_info_size() must be
- * allocated, and the pointer to this buffer must be written into the
- * system_info member. The buffer must be suitably aligned for storage of
- * the _mali_system_info structure - for example, one returned by
- * _mali_osk_malloc(), which will be suitably aligned for any structure.
- *
- * The ukk_private member must be set to zero by the user-side. Under an OS
- * implementation, the U/K interface must write in the user-side base address
- * into the ukk_private member, so that the common code in
- * _mali_ukk_get_system_info() can determine how to adjust the pointers such
- * that they are sensible from user space. Leaving ukk_private as NULL implies
- * that no pointer adjustment is necessary - which will be the case on a
- * bare-metal/RTOS system.
- *
- * @see _mali_system_info
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 size; /**< [in] size of buffer provided to store system information data */
- _mali_system_info * system_info; /**< [in,out] pointer to buffer to store system information data. No initialisation of buffer required on input. */
- u32 ukk_private; /**< [in] Kernel-side private word inserted by certain U/K interface implementations. Caller must set to Zero. */
-} _mali_uk_get_system_info_s;
-/** @} */ /* end group _mali_uk_getsysteminfo */
-
-/** @} */ /* end group _mali_uk_core */
-
-
-/** @defgroup _mali_uk_gp U/K Vertex Processor
- * @{ */
-
-/** @defgroup _mali_uk_gp_suspend_response_s Vertex Processor Suspend Response
- * @{ */
-
-/** @brief Arguments for _mali_ukk_gp_suspend_response()
- *
- * When _mali_wait_for_notification() receives notification that a
- * Vertex Processor job was suspended, you need to send a response to indicate
- * what needs to happen with this job. You can either abort or resume the job.
- *
- * - set @c code to indicate response code. This is either @c _MALIGP_JOB_ABORT or
- * @c _MALIGP_JOB_RESUME_WITH_NEW_HEAP to indicate you will provide a new heap
- * for the job that will resolve the out of memory condition for the job.
- * - copy the @c cookie value from the @c _mali_uk_gp_job_suspended_s notification;
- * this is an identifier for the suspended job
- * - set @c arguments[0] and @c arguments[1] to zero if you abort the job. If
- * you resume it, @c argument[0] should specify the Mali start address for the new
- * heap and @c argument[1] the Mali end address of the heap.
- * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
- *
- */
-typedef enum _maligp_job_suspended_response_code
-{
- _MALIGP_JOB_ABORT, /**< Abort the Vertex Processor job */
- _MALIGP_JOB_RESUME_WITH_NEW_HEAP /**< Resume the Vertex Processor job with a new heap */
-} _maligp_job_suspended_response_code;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 cookie; /**< [in] cookie from the _mali_uk_gp_job_suspended_s notification */
- _maligp_job_suspended_response_code code; /**< [in] abort or resume response code, see \ref _maligp_job_suspended_response_code */
- u32 arguments[2]; /**< [in] 0 when aborting a job. When resuming a job, the Mali start and end address for a new heap to resume the job with */
-} _mali_uk_gp_suspend_response_s;
-
-/** @} */ /* end group _mali_uk_gp_suspend_response_s */
-
-/** @defgroup _mali_uk_gpstartjob_s Vertex Processor Start Job
- * @{ */
-
-/** @brief Status indicating the result of starting a Vertex or Fragment processor job */
-typedef enum
-{
- _MALI_UK_START_JOB_STARTED, /**< Job started */
- _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED, /**< Job started and bumped a lower priority job that was pending execution */
- _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE /**< Job could not be started at this time. Try starting the job again */
-} _mali_uk_start_job_status;
-
-/** @brief Status indicating the result of starting a Vertex or Fragment processor job */
-typedef enum
-{
- MALI_UK_START_JOB_FLAG_DEFAULT = 0, /**< Default behaviour; Flush L2 caches before start, no following jobs */
- MALI_UK_START_JOB_FLAG_NO_FLUSH = 1, /**< No need to flush L2 caches before start */
- MALI_UK_START_JOB_FLAG_MORE_JOBS_FOLLOW = 2, /**< More related jobs follows, try to schedule them as soon as possible after this job */
-} _mali_uk_start_job_flags;
-
-/** @brief Status indicating the result of the execution of a Vertex or Fragment processor job */
-
-typedef enum
-{
- _MALI_UK_JOB_STATUS_END_SUCCESS = 1<<(16+0),
- _MALI_UK_JOB_STATUS_END_OOM = 1<<(16+1),
- _MALI_UK_JOB_STATUS_END_ABORT = 1<<(16+2),
- _MALI_UK_JOB_STATUS_END_TIMEOUT_SW = 1<<(16+3),
- _MALI_UK_JOB_STATUS_END_HANG = 1<<(16+4),
- _MALI_UK_JOB_STATUS_END_SEG_FAULT = 1<<(16+5),
- _MALI_UK_JOB_STATUS_END_ILLEGAL_JOB = 1<<(16+6),
- _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR = 1<<(16+7),
- _MALI_UK_JOB_STATUS_END_SHUTDOWN = 1<<(16+8),
- _MALI_UK_JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9)
-} _mali_uk_job_status;
-
-#define MALIGP2_NUM_REGS_FRAME (6)
-
-/** @brief Arguments for _mali_ukk_gp_start_job()
- *
- * To start a Vertex Processor job
- * - associate the request with a reference to a @c mali_gp_job_info by setting
- * user_job_ptr to the address of the @c mali_gp_job_info of the job.
- * - set @c priority to the priority of the @c mali_gp_job_info
- * - specify a timeout for the job by setting @c watchdog_msecs to the number of
- * milliseconds the job is allowed to run. Specifying a value of 0 selects the
- * default timeout in use by the device driver.
- * - copy the frame registers from the @c mali_gp_job_info into @c frame_registers.
- * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero
- * for a non-instrumented build. For an instrumented build you can use up
- * to two performance counters. Set the corresponding bit in @c perf_counter_flag
- * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify
- * the source of what needs to get counted (e.g. number of vertex loader
- * cache hits). For source id values, see ARM DDI0415A, Table 3-60.
- * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
- *
- * When @c _mali_ukk_gp_start_job() returns @c _MALI_OSK_ERR_OK, status contains the
- * result of the request (see \ref _mali_uk_start_job_status). If the job could
- * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be
- * tried again. If the job had a higher priority than the one currently pending
- * execution (@c _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED), it will bump
- * the lower priority job and returns the address of the @c mali_gp_job_info
- * for that job in @c returned_user_job_ptr. That job should get requeued.
- *
- * After the job has started, @c _mali_wait_for_notification() will be notified
- * that the job finished or got suspended. It may get suspended due to
- * resource shortage. If it finished (see _mali_ukk_wait_for_notification())
- * the notification will contain a @c _mali_uk_gp_job_finished_s result. If
- * it got suspended the notification will contain a @c _mali_uk_gp_job_suspended_s
- * result.
- *
- * The @c _mali_uk_gp_job_finished_s contains the job status (see \ref _mali_uk_job_status),
- * the number of milliseconds the job took to render, and values of core registers
- * when the job finished (irq status, performance counters, renderer list
- * address). A job has finished succesfully when its status is
- * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering
- * the job, or software detected the job is taking more than watchdog_msecs to
- * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG.
- * If the hardware detected a bus error while accessing memory associated with the
- * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT.
- * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to
- * stop the job but the job didn't start on the hardware yet, e.g. when the
- * driver shutdown.
- *
- * In case the job got suspended, @c _mali_uk_gp_job_suspended_s contains
- * the @c user_job_ptr identifier used to start the job with, the @c reason
- * why the job stalled (see \ref _maligp_job_suspended_reason) and a @c cookie
- * to identify the core on which the job stalled. This @c cookie will be needed
- * when responding to this nofication by means of _mali_ukk_gp_suspend_response().
- * (see _mali_ukk_gp_suspend_response()). The response is either to abort or
- * resume the job. If the job got suspended due to an out of memory condition
- * you may be able to resolve this by providing more memory and resuming the job.
- *
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 user_job_ptr; /**< [in] identifier for the job in user space, a @c mali_gp_job_info* */
- u32 priority; /**< [in] job priority. A lower number means higher priority */
- u32 watchdog_msecs; /**< [in] maximum allowed runtime in milliseconds. The job gets killed if it runs longer than this. A value of 0 selects the default used by the device driver. */
- u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job */
- 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) */
- u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
- u32 returned_user_job_ptr; /**< [out] identifier for the returned job in user space, a @c mali_gp_job_info* */
- _mali_uk_start_job_status status; /**< [out] indicates job start status (success, previous job returned, requeue) */
- u32 abort_id; /**< [in] abort id of this job, used to identify this job for later abort requests */
- u32 perf_counter_l2_src0; /**< [in] soruce id for Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_src1; /**< [in] source id for Mali-400 MP L2 cache performance counter 1 */
- u32 frame_builder_id; /**< [in] id of the originating frame builder */
- u32 flush_id; /**< [in] flush id within the originating frame builder */
-} _mali_uk_gp_start_job_s;
-
-#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE (1<<0) /**< Enable performance counter SRC0 for a job */
-#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE (1<<1) /**< Enable performance counter SRC1 for a job */
-#define _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE (1<<2) /**< Enable performance counter L2_SRC0 for a job */
-#define _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE (1<<3) /**< Enable performance counter L2_SRC1 for a job */
-#define _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET (1<<4) /**< Enable performance counter L2_RESET for a job */
-
-/** @} */ /* end group _mali_uk_gpstartjob_s */
-
-typedef struct
-{
- u32 user_job_ptr; /**< [out] identifier for the job in user space */
- _mali_uk_job_status status; /**< [out] status of finished job */
- u32 irq_status; /**< [out] value of the GP interrupt rawstat register (see ARM DDI0415A) */
- u32 status_reg_on_stop; /**< [out] value of the GP control register */
- u32 vscl_stop_addr; /**< [out] value of the GP VLSCL start register */
- u32 plbcl_stop_addr; /**< [out] value of the GP PLBCL start register */
- u32 heap_current_addr; /**< [out] value of the GP PLB PL heap start address register */
- u32 perf_counter_src0; /**< [out] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
- u32 perf_counter_src1; /**< [out] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
- u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */
- u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */
- u32 render_time; /**< [out] number of microseconds it took for the job to render */
- u32 perf_counter_l2_src0; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_src1; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 1 */
- u32 perf_counter_l2_val0; /**< [out] Value of the Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_val1; /**< [out] Value of the Mali-400 MP L2 cache performance counter 1 */
-} _mali_uk_gp_job_finished_s;
-
-typedef enum _maligp_job_suspended_reason
-{
- _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY /**< Polygon list builder unit (PLBU) has run out of memory */
-} _maligp_job_suspended_reason;
-
-typedef struct
-{
- u32 user_job_ptr; /**< [out] identifier for the job in user space */
- _maligp_job_suspended_reason reason; /**< [out] reason why the job stalled */
- u32 cookie; /**< [out] identifier for the core in kernel space on which the job stalled */
-} _mali_uk_gp_job_suspended_s;
-
-/** @} */ /* end group _mali_uk_gp */
-
-
-/** @defgroup _mali_uk_pp U/K Fragment Processor
- * @{ */
-
-/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job
- * @{ */
-
-/** @brief Arguments for _mali_ukk_pp_start_job()
- *
- * To start a Fragment Processor job
- * - associate the request with a reference to a mali_pp_job by setting
- * @c user_job_ptr to the address of the @c mali_pp_job of the job.
- * - set @c priority to the priority of the mali_pp_job
- * - specify a timeout for the job by setting @c watchdog_msecs to the number of
- * milliseconds the job is allowed to run. Specifying a value of 0 selects the
- * default timeout in use by the device driver.
- * - copy the frame registers from the @c mali_pp_job into @c frame_registers.
- * For MALI200 you also need to copy the write back 0,1 and 2 registers.
- * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero
- * for a non-instrumented build. For an instrumented build you can use up
- * to two performance counters. Set the corresponding bit in @c perf_counter_flag
- * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify
- * the source of what needs to get counted (e.g. number of vertex loader
- * cache hits). For source id values, see ARM DDI0415A, Table 3-60.
- * - pass in the user-kernel context in @c ctx that was returned from _mali_ukk_open()
- *
- * When _mali_ukk_pp_start_job() returns @c _MALI_OSK_ERR_OK, @c status contains the
- * result of the request (see \ref _mali_uk_start_job_status). If the job could
- * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be
- * tried again. If the job had a higher priority than the one currently pending
- * execution (@c _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED), it will bump
- * the lower priority job and returns the address of the @c mali_pp_job
- * for that job in @c returned_user_job_ptr. That job should get requeued.
- *
- * After the job has started, _mali_wait_for_notification() will be notified
- * when the job finished. The notification will contain a
- * @c _mali_uk_pp_job_finished_s result. It contains the @c user_job_ptr
- * identifier used to start the job with, the job @c status (see \ref _mali_uk_job_status),
- * the number of milliseconds the job took to render, and values of core registers
- * when the job finished (irq status, performance counters, renderer list
- * address). A job has finished succesfully when its status is
- * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering
- * the job, or software detected the job is taking more than @c watchdog_msecs to
- * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG.
- * If the hardware detected a bus error while accessing memory associated with the
- * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT.
- * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to
- * stop the job but the job didn't start on the hardware yet, e.g. when the
- * driver shutdown.
- *
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 user_job_ptr; /**< [in] identifier for the job in user space */
- u32 priority; /**< [in] job priority. A lower number means higher priority */
- u32 watchdog_msecs; /**< [in] maximum allowed runtime in milliseconds. The job gets killed if it runs longer than this. A value of 0 selects the default used by the device driver. */
- u32 frame_registers[MALI200_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job, see ARM DDI0415A */
- u32 wb0_registers[MALI200_NUM_REGS_WBx];
- u32 wb1_registers[MALI200_NUM_REGS_WBx];
- u32 wb2_registers[MALI200_NUM_REGS_WBx];
- 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) */
- u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
- u32 returned_user_job_ptr; /**< [out] identifier for the returned job in user space */
- _mali_uk_start_job_status status; /**< [out] indicates job start status (success, previous job returned, requeue) */
- u32 abort_id; /**< [in] abort id of this job, used to identify this job for later abort requests */
- u32 perf_counter_l2_src0; /**< [in] soruce id for Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_src1; /**< [in] source id for Mali-400 MP L2 cache performance counter 1 */
- u32 frame_builder_id; /**< [in] id of the originating frame builder */
- u32 flush_id; /**< [in] flush id within the originating frame builder */
- _mali_uk_start_job_flags flags; /**< [in] Flags for job, see _mali_uk_start_job_flags for more information */
-} _mali_uk_pp_start_job_s;
-/** @} */ /* end group _mali_uk_ppstartjob_s */
-
-typedef struct
-{
- u32 user_job_ptr; /**< [out] identifier for the job in user space */
- _mali_uk_job_status status; /**< [out] status of finished job */
- u32 irq_status; /**< [out] value of interrupt rawstat register (see ARM DDI0415A) */
- u32 last_tile_list_addr; /**< [out] value of renderer list register (see ARM DDI0415A); necessary to restart a stopped job */
- u32 perf_counter_src0; /**< [out] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
- u32 perf_counter_src1; /**< [out] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
- u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */
- u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */
- u32 render_time; /**< [out] number of microseconds it took for the job to render */
- u32 perf_counter_l2_src0; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_src1; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 1 */
- u32 perf_counter_l2_val0; /**< [out] Value of the Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_val1; /**< [out] Value of the Mali-400 MP L2 cache performance counter 1 */
- u32 perf_counter_l2_val0_raw; /**< [out] Raw value of the Mali-400 MP L2 cache performance counter 0 */
- u32 perf_counter_l2_val1_raw; /**< [out] Raw value of the Mali-400 MP L2 cache performance counter 1 */
-} _mali_uk_pp_job_finished_s;
-/** @} */ /* end group _mali_uk_pp */
-
-
-/** @addtogroup _mali_uk_core U/K Core
- * @{ */
-
-/** @defgroup _mali_uk_waitfornotification_s Wait For Notification
- * @{ */
-
-/** @brief Notification type encodings
- *
- * Each Notification type is an ordered pair of (subsystem,id), and is unique.
- *
- * The encoding of subsystem,id into a 32-bit word is:
- * encoding = (( subsystem << _MALI_NOTIFICATION_SUBSYSTEM_SHIFT ) & _MALI_NOTIFICATION_SUBSYSTEM_MASK)
- * | (( id << _MALI_NOTIFICATION_ID_SHIFT ) & _MALI_NOTIFICATION_ID_MASK)
- *
- * @see _mali_uk_wait_for_notification_s
- */
-typedef enum
-{
- /** core notifications */
-
- _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20,
- _MALI_NOTIFICATION_APPLICATION_QUIT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40,
-
- /** Fragment Processor notifications */
-
- _MALI_NOTIFICATION_PP_FINISHED = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10,
-
- /** Vertex Processor notifications */
-
- _MALI_NOTIFICATION_GP_FINISHED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x10,
- _MALI_NOTIFICATION_GP_STALLED = (_MALI_UK_GP_SUBSYSTEM << 16) | 0x20,
-} _mali_uk_notification_type;
-
-/** to assist in splitting up 32-bit notification value in subsystem and id value */
-#define _MALI_NOTIFICATION_SUBSYSTEM_MASK 0xFFFF0000
-#define _MALI_NOTIFICATION_SUBSYSTEM_SHIFT 16
-#define _MALI_NOTIFICATION_ID_MASK 0x0000FFFF
-#define _MALI_NOTIFICATION_ID_SHIFT 0
-
-
-/** @brief Arguments for _mali_ukk_wait_for_notification()
- *
- * On successful return from _mali_ukk_wait_for_notification(), the members of
- * this structure will indicate the reason for notification.
- *
- * Specifically, the source of the notification can be identified by the
- * subsystem and id fields of the mali_uk_notification_type in the code.type
- * member. The type member is encoded in a way to divide up the types into a
- * subsystem field, and a per-subsystem ID field. See
- * _mali_uk_notification_type for more information.
- *
- * Interpreting the data union member depends on the notification type:
- *
- * - type == _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS
- * - The kernel side is shutting down. No further
- * _mali_uk_wait_for_notification() calls should be made.
- * - In this case, the value of the data union member is undefined.
- * - This is used to indicate to the user space client that it should close
- * the connection to the Mali Device Driver.
- * - type == _MALI_NOTIFICATION_PP_FINISHED
- * - The notification data is of type _mali_uk_pp_job_finished_s. It contains the user_job_ptr
- * identifier used to start the job with, the job status, the number of milliseconds the job took to render,
- * and values of core registers when the job finished (irq status, performance counters, renderer list
- * address).
- * - A job has finished succesfully when its status member is _MALI_UK_JOB_STATUS_FINISHED.
- * - If the hardware detected a timeout while rendering the job, or software detected the job is
- * taking more than watchdog_msecs (see _mali_ukk_pp_start_job()) to complete, the status member will
- * indicate _MALI_UK_JOB_STATUS_HANG.
- * - If the hardware detected a bus error while accessing memory associated with the job, status will
- * indicate _MALI_UK_JOB_STATUS_SEG_FAULT.
- * - Status will indicate MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to stop the job but the job
- * didn't start the hardware yet, e.g. when the driver closes.
- * - type == _MALI_NOTIFICATION_GP_FINISHED
- * - The notification data is of type _mali_uk_gp_job_finished_s. The notification is similar to that of
- * type == _MALI_NOTIFICATION_PP_FINISHED, except that several other GP core register values are returned.
- * The status values have the same meaning for type == _MALI_NOTIFICATION_PP_FINISHED.
- * - type == _MALI_NOTIFICATION_GP_STALLED
- * - The nofication data is of type _mali_uk_gp_job_suspended_s. It contains the user_job_ptr
- * identifier used to start the job with, the reason why the job stalled and a cookie to identify the core on
- * which the job stalled.
- * - The reason member of gp_job_suspended is set to _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY
- * when the polygon list builder unit has run out of memory.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- _mali_uk_notification_type type; /**< [out] Type of notification available */
- union
- {
- _mali_uk_gp_job_suspended_s gp_job_suspended;/**< [out] Notification data for _MALI_NOTIFICATION_GP_STALLED notification type */
- _mali_uk_gp_job_finished_s gp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_GP_FINISHED notification type */
- _mali_uk_pp_job_finished_s pp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_PP_FINISHED notification type */
- } data;
-} _mali_uk_wait_for_notification_s;
-
-/** @brief Arguments for _mali_ukk_post_notification()
- *
- * Posts the specified notification to the notification queue for this application.
- * This is used to send a quit message to the callback thread.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- _mali_uk_notification_type type; /**< [in] Type of notification to post */
-} _mali_uk_post_notification_s;
-/** @} */ /* end group _mali_uk_waitfornotification_s */
-
-/** @defgroup _mali_uk_getapiversion_s Get API Version
- * @{ */
-
-/** helpers for Device Driver API version handling */
-
-/** @brief Encode a version ID from a 16-bit input
- *
- * @note the input is assumed to be 16 bits. It must not exceed 16 bits. */
-#define _MAKE_VERSION_ID(x) (((x) << 16UL) | (x))
-
-/** @brief Check whether a 32-bit value is likely to be Device Driver API
- * version ID. */
-#define _IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF))
-
-/** @brief Decode a 16-bit version number from a 32-bit Device Driver API version
- * ID */
-#define _GET_VERSION(x) (((x) >> 16UL) & 0xFFFF)
-
-/** @brief Determine whether two 32-bit encoded version IDs match */
-#define _IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y))))
-
-/**
- * API version define.
- * Indicates the version of the kernel API
- * The version is a 16bit integer incremented on each API change.
- * The 16bit integer is stored twice in a 32bit integer
- * For example, for version 1 the value would be 0x00010001
- */
-#define _MALI_API_VERSION 10
-#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION)
-
-/**
- * The API version is a 16-bit integer stored in both the lower and upper 16-bits
- * of a 32-bit value. The 16-bit API version value is incremented on each API
- * change. Version 1 would be 0x00010001. Used in _mali_uk_get_api_version_s.
- */
-typedef u32 _mali_uk_api_version;
-
-/** @brief Arguments for _mali_uk_get_api_version()
- *
- * The user-side interface version must be written into the version member,
- * encoded using _MAKE_VERSION_ID(). It will be compared to the API version of
- * the kernel-side interface.
- *
- * On successful return, the version member will be the API version of the
- * kernel-side interface. _MALI_UK_API_VERSION macro defines the current version
- * of the API.
- *
- * The compatible member must be checked to see if the version of the user-side
- * interface is compatible with the kernel-side interface, since future versions
- * of the interface may be backwards compatible.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- _mali_uk_api_version version; /**< [in,out] API version of user-side interface. */
- int compatible; /**< [out] @c 1 when @version is compatible, @c 0 otherwise */
-} _mali_uk_get_api_version_s;
-/** @} */ /* end group _mali_uk_getapiversion_s */
-
-/** @} */ /* end group _mali_uk_core */
-
-
-/** @defgroup _mali_uk_memory U/K Memory
- * @{ */
-
-/** @brief Arguments for _mali_ukk_init_mem(). */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 mali_address_base; /**< [out] start of MALI address space */
- u32 memory_size; /**< [out] total MALI address space available */
-} _mali_uk_init_mem_s;
-
-/** @brief Arguments for _mali_ukk_term_mem(). */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
-} _mali_uk_term_mem_s;
-
-/** @brief Arguments for _mali_ukk_get_big_block()
- *
- * - type_id should be set to the value of the identifier member of one of the
- * _mali_mem_info structures returned through _mali_ukk_get_system_info()
- * - ukk_private must be zero when calling from user-side. On Kernel-side, the
- * OS implementation of the U/K interface can use it to communicate data to the
- * OS implementation of the OSK layer. Specifically, ukk_private will be placed
- * into the ukk_private member of the _mali_uk_mem_mmap_s structure. See
- * _mali_ukk_mem_mmap() for more details.
- * - minimum_size_requested will be updated if it is too small
- * - block_size will always be >= minimum_size_requested, because the underlying
- * allocation mechanism may only be able to divide up memory regions in certain
- * ways. To avoid wasting memory, block_size should always be taken into account
- * rather than assuming minimum_size_requested was really allocated.
- * - to free the memory, the returned cookie member must be stored, and used to
- * refer to it.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 type_id; /**< [in] the type id of the memory bank to allocate memory from */
- u32 minimum_size_requested; /**< [in,out] minimum size of the allocation */
- u32 ukk_private; /**< [in] Kernel-side private word inserted by certain U/K interface implementations. Caller must set to Zero. */
- u32 mali_address; /**< [out] address of the allocation in mali address space */
- void *cpuptr; /**< [out] address of the allocation in the current process address space */
- u32 block_size; /**< [out] size of the block that got allocated */
- u32 flags; /**< [out] flags associated with the allocated block, of type _mali_bus_usage */
- u32 cookie; /**< [out] identifier for the allocated block in kernel space */
-} _mali_uk_get_big_block_s;
-
-/** @brief Arguments for _mali_ukk_free_big_block()
- *
- * All that is required is that the cookie member must be set to the value of
- * the cookie member returned through _mali_ukk_get_big_block()
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 cookie; /**< [in] identifier for mapped memory object in kernel space */
-} _mali_uk_free_big_block_s;
-
-/** @note Mali-MMU only */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 phys_addr; /**< [in] physical address */
- u32 size; /**< [in] size */
- u32 mali_address; /**< [in] mali address to map the physical memory to */
- u32 rights; /**< [in] rights necessary for accessing memory */
- u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */
- u32 cookie; /**< [out] identifier for mapped memory object in kernel space */
-} _mali_uk_map_external_mem_s;
-
-/** Flag for _mali_uk_map_external_mem_s and _mali_uk_attach_ump_mem_s */
-#define _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE (1<<0)
-
-/** @note Mali-MMU only */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 cookie; /**< [out] identifier for mapped memory object in kernel space */
-} _mali_uk_unmap_external_mem_s;
-
-/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by secure_id */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 secure_id; /**< [in] secure id */
- u32 size; /**< [in] size */
- u32 mali_address; /**< [in] mali address to map the physical memory to */
- u32 rights; /**< [in] rights necessary for accessing memory */
- u32 flags; /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */
- u32 cookie; /**< [out] identifier for mapped memory object in kernel space */
-} _mali_uk_attach_ump_mem_s;
-
-/** @note Mali-MMU only; will be supported in future version */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 cookie; /**< [in] identifier for mapped memory object in kernel space */
-} _mali_uk_release_ump_mem_s;
-
-/** @brief Arguments for _mali_ukk_va_to_mali_pa()
- *
- * if size is zero or not a multiple of the system's page size, it will be
- * rounded up to the next multiple of the page size. This will occur before
- * any other use of the size parameter.
- *
- * if va is not PAGE_SIZE aligned, it will be rounded down to the next page
- * boundary.
- *
- * The range (va) to ((u32)va)+(size-1) inclusive will be checked for physical
- * contiguity.
- *
- * The implementor will check that the entire physical range is allowed to be mapped
- * into user-space.
- *
- * Failure will occur if either of the above are not satisfied.
- *
- * Otherwise, the physical base address of the range is returned through pa,
- * va is updated to be page aligned, and size is updated to be a non-zero
- * multiple of the system's pagesize.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- void *va; /**< [in,out] Virtual address of the start of the range */
- u32 pa; /**< [out] Physical base address of the range */
- u32 size; /**< [in,out] Size of the range, in bytes. */
-} _mali_uk_va_to_mali_pa_s;
-
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 size; /**< [out] size of MMU page table information (registers + page tables) */
-} _mali_uk_query_mmu_page_table_dump_size_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 size; /**< [in] size of buffer to receive mmu page table information */
- void *buffer; /**< [in,out] buffer to receive mmu page table information */
- u32 register_writes_size; /**< [out] size of MMU register dump */
- u32 *register_writes; /**< [out] pointer within buffer where MMU register dump is stored */
- u32 page_table_dump_size; /**< [out] size of MMU page table dump */
- u32 *page_table_dump; /**< [out] pointer within buffer where MMU page table dump is stored */
-} _mali_uk_dump_mmu_page_table_s;
-
-/** @} */ /* end group _mali_uk_memory */
-
-
-/** @addtogroup _mali_uk_pp U/K Fragment Processor
- * @{ */
-
-/** @brief Arguments for _mali_ukk_get_pp_number_of_cores()
- *
- * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
- * - Upon successful return from _mali_ukk_get_pp_number_of_cores(), @c number_of_cores
- * will contain the number of Fragment Processor cores in the system.
- */
-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 */
-} _mali_uk_get_pp_number_of_cores_s;
-
-/** @brief Arguments for _mali_ukk_get_pp_core_version()
- *
- * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
- * - Upon successful return from _mali_ukk_get_pp_core_version(), @c version contains
- * the version that all Fragment Processor cores are compatible with.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */
-} _mali_uk_get_pp_core_version_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 abort_id; /**< [in] ID of job(s) to abort */
-} _mali_uk_pp_abort_job_s;
-
-/** @} */ /* end group _mali_uk_pp */
-
-
-/** @addtogroup _mali_uk_gp U/K Vertex Processor
- * @{ */
-
-/** @brief Arguments for _mali_ukk_get_gp_number_of_cores()
- *
- * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
- * - Upon successful return from _mali_ukk_get_gp_number_of_cores(), @c number_of_cores
- * will contain the number of Vertex Processor cores in the system.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 number_of_cores; /**< [out] number of Vertex Processor cores in the system */
-} _mali_uk_get_gp_number_of_cores_s;
-
-/** @brief Arguments for _mali_ukk_get_gp_core_version()
- *
- * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
- * - Upon successful return from _mali_ukk_get_gp_core_version(), @c version contains
- * the version that all Vertex Processor cores are compatible with.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- _mali_core_version version; /**< [out] version returned from core, see \ref _mali_core_version */
-} _mali_uk_get_gp_core_version_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 abort_id; /**< [in] ID of job(s) to abort */
-} _mali_uk_gp_abort_job_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 limit; /**< [in,out] The desired limit for number of events to record on input, actual limit on output */
-} _mali_uk_profiling_start_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 event_id; /**< [in] event id to register (see enum mali_profiling_events for values) */
- u32 data[5]; /**< [in] event specific data */
-} _mali_uk_profiling_add_event_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 count; /**< [out] The number of events sampled */
-} _mali_uk_profiling_stop_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 index; /**< [in] which index to get (starting at zero) */
- u64 timestamp; /**< [out] timestamp of event */
- u32 event_id; /**< [out] event id of event (see enum mali_profiling_events for values) */
- u32 data[5]; /**< [out] event specific data */
-} _mali_uk_profiling_get_event_s;
-
-typedef struct
-{
- void *ctx;
-
- u32 id;
- s64 value;
-} _mali_uk_sw_counters_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
-} _mali_uk_profiling_clear_s;
-
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 enable_events; /**< [out] 1 if user space process should generate events, 0 if not */
-} _mali_uk_profiling_get_config_s;
-
-
-/** @} */ /* end group _mali_uk_gp */
-
-
-/** @addtogroup _mali_uk_memory U/K Memory
- * @{ */
-
-/** @brief Arguments to _mali_ukk_mem_mmap()
- *
- * Use of the phys_addr member depends on whether the driver is compiled for
- * Mali-MMU or nonMMU:
- * - in the nonMMU case, this is the physical address of the memory as seen by
- * the CPU (which may be a constant offset from that used by Mali)
- * - in the MMU case, this is the Mali Virtual base address of the memory to
- * allocate, and the particular physical pages used to back the memory are
- * entirely determined by _mali_ukk_mem_mmap(). The details of the physical pages
- * are not reported to user-space for security reasons.
- *
- * The cookie member must be stored for use later when freeing the memory by
- * calling _mali_ukk_mem_munmap(). In the Mali-MMU case, the cookie is secure.
- *
- * The ukk_private word must be set to zero when calling from user-space. On
- * Kernel-side, the OS implementation of the U/K interface can use it to
- * communicate data to the OS implementation of the OSK layer. In particular,
- * _mali_ukk_get_big_block() directly calls _mali_ukk_mem_mmap directly, and
- * will communicate its own ukk_private word through the ukk_private member
- * here. The common code itself will not inspect or modify the ukk_private
- * word, and so it may be safely used for whatever purposes necessary to
- * integrate Mali Memory handling into the OS.
- *
- * The uku_private member is currently reserved for use by the user-side
- * implementation of the U/K interface. Its value must be zero.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- void *mapping; /**< [out] Returns user-space virtual address for the mapping */
- u32 size; /**< [in] Size of the requested mapping */
- u32 phys_addr; /**< [in] Physical address - could be offset, depending on caller+callee convention */
- u32 cookie; /**< [out] Returns a cookie for use in munmap calls */
- void *uku_private; /**< [in] User-side Private word used by U/K interface */
- void *ukk_private; /**< [in] Kernel-side Private word used by U/K interface */
-} _mali_uk_mem_mmap_s;
-
-/** @brief Arguments to _mali_ukk_mem_munmap()
- *
- * The cookie and mapping members must be that returned from the same previous
- * call to _mali_ukk_mem_mmap(). The size member must correspond to cookie
- * and mapping - that is, it must be the value originally supplied to a call to
- * _mali_ukk_mem_mmap that returned the values of mapping and cookie.
- *
- * An error will be returned if an attempt is made to unmap only part of the
- * originally obtained range, or to unmap more than was originally obtained.
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- void *mapping; /**< [in] The mapping returned from mmap call */
- u32 size; /**< [in] The size passed to mmap call */
- u32 cookie; /**< [in] Cookie from mmap call */
-} _mali_uk_mem_munmap_s;
-/** @} */ /* end group _mali_uk_memory */
-
-#if USING_MALI_PMM
-
-/** @defgroup _mali_uk_pmm U/K Power Management Module
- * @{ */
-
-/** @brief Power management event message identifiers.
- *
- * U/K events start after id 200, and can range up to 999
- * Adding new events will require updates to the PMM mali_pmm_event_id type
- */
-#define _MALI_PMM_EVENT_UK_EXAMPLE 201
-
-/** @brief Generic PMM message data type, that will be dependent on the event msg
- */
-typedef u32 mali_pmm_message_data;
-
-
-/** @brief Arguments to _mali_ukk_pmm_event_message()
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- u32 id; /**< [in] event id */
- mali_pmm_message_data data; /**< [in] specific data associated with the event */
-} _mali_uk_pmm_message_s;
-
-/** @} */ /* end group _mali_uk_pmm */
-#endif /* USING_MALI_PMM */
-
-/** @defgroup _mali_uk_vsync U/K VSYNC Wait Reporting Module
- * @{ */
-
-/** @brief VSYNC events
- *
- * These events are reported when DDK starts to wait for vsync and when the
- * vsync has occured and the DDK can continue on the next frame.
- */
-typedef enum _mali_uk_vsync_event
-{
- _MALI_UK_VSYNC_EVENT_BEGIN_WAIT = 0,
- _MALI_UK_VSYNC_EVENT_END_WAIT
-} _mali_uk_vsync_event;
-
-/** @brief Arguments to _mali_ukk_vsync_event()
- *
- */
-typedef struct
-{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- _mali_uk_vsync_event event; /**< [in] VSYNCH event type */
-} _mali_uk_vsync_event_report_s;
-
-/** @} */ /* end group _mali_uk_vsync */
-
-/** @} */ /* end group u_k_api */
-
-/** @} */ /* end group uddapi */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_UK_TYPES_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_ukk.h b/drivers/media/video/samsung/mali/common/mali_ukk.h
index 94efdf5..8ff2002 100644
--- a/drivers/media/video/samsung/mali/common/mali_ukk.h
+++ b/drivers/media/video/samsung/mali/common/mali_ukk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -17,7 +17,7 @@
#define __MALI_UKK_H__
#include "mali_osk.h"
-#include "mali_uk_types.h"
+#include "../linux/mali_uk_types.h"
#ifdef __cplusplus
extern "C"
@@ -139,14 +139,6 @@ extern "C"
* (_mali_osk_mem_mapregion_init()) functions will collaborate on the
* meaning of ukk_private member. On other OSs, it may be unused by both
* U/K and OSK layers
- * - On OS systems (not including direct function call U/K interface
- * implementations), _mali_ukk_get_big_block() may succeed, but the subsequent
- * copying to user space may fail.
- * - A problem scenario exists: some memory has been reserved by
- * _mali_ukk_get_big_block(), but the user-mode will be unaware of it (it will
- * never receive any information about this memory). In this case, the U/K
- * implementation must do everything necessary to 'rollback' the \em atomic
- * _mali_ukk_get_big_block() transaction.
* - Therefore, on error inside the U/K interface implementation itself,
* it will be as though the _mali_ukk function itself had failed, and cleaned
* up after itself.
@@ -233,7 +225,7 @@ _mali_osk_errcode_t _mali_ukk_close( void **context );
* allocated, and a pointer to this memory written into the system_info member
* of _mali_uk_get_system_info_s.
*
- * @param args see _mali_uk_get_system_info_size_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_system_info_size_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_get_system_info_size( _mali_uk_get_system_info_size_s *args );
@@ -270,7 +262,7 @@ _mali_osk_errcode_t _mali_ukk_get_system_info_size( _mali_uk_get_system_info_siz
* destination address for pointer-patching to occur. When NULL, it is unused, an no pointer-patching occurs in the
* common code.
*
- * @param args see _mali_uk_get_system_info_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_system_info_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_get_system_info( _mali_uk_get_system_info_s *args );
@@ -279,24 +271,37 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
*
* Sleeps until notified or a timeout occurs. Returns information about the notification.
*
- * @param args see _mali_uk_wait_for_notification_s in "mali_uk_types.h"
+ * @param args see _mali_uk_wait_for_notification_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_wait_for_notification( _mali_uk_wait_for_notification_s *args );
/** @brief Post a notification to the notification queue of this application.
*
- * @param args see _mali_uk_post_notification_s in "mali_uk_types.h"
+ * @param args see _mali_uk_post_notification_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_post_notification( _mali_uk_post_notification_s *args );
/** @brief Verifies if the user and kernel side of this API are compatible.
*
- * @param args see _mali_uk_get_api_version_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_api_version_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_get_api_version( _mali_uk_get_api_version_s *args );
+
+/** @brief Get the user space settings applicable for calling process.
+ *
+ * @param args see _mali_uk_get_user_settings_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args);
+
+/** @brief Get a user space setting applicable for calling process.
+ *
+ * @param args see _mali_uk_get_user_setting_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args);
+
/** @} */ /* end group _mali_uk_core */
@@ -324,7 +329,7 @@ _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args
* @note This function is for Mali-MMU builds \b only. It should not be called
* when the drivers are built without Mali-MMU support.
*
- * @param args see \ref _mali_uk_init_mem_s in mali_uk_types.h
+ * @param args see \ref _mali_uk_init_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable
* _mali_osk_errcode_t on failure.
*/
@@ -340,43 +345,18 @@ _mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args );
* @note This function is for Mali-MMU builds \b only. It should not be called
* when the drivers are built without Mali-MMU support.
*
- * @param args see \ref _mali_uk_term_mem_s in mali_uk_types.h
+ * @param args see \ref _mali_uk_term_mem_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_term_mem( _mali_uk_term_mem_s *args );
-/** @brief Map a block of memory into the current user process
- *
- * Allocates a minimum of minimum_size_requested bytes of MALI memory and maps it into the current
- * process space. The number of bytes allocated is returned in args->block_size.
- *
- * This is only used for Mali-nonMMU mode.
- *
- * @param args see _mali_uk_get_big_block_s in "mali_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_get_big_block( _mali_uk_get_big_block_s *args );
-
-/** @brief Unmap a block of memory from the current user process
- *
- * Frees allocated MALI memory and unmaps it from the current process space. The previously allocated memory
- * is indicated by the cookie as returned by _mali_ukk_get_big_block().
- *
- * This is only used for Mali-nonMMU mode.
- *
- * @param args see _mali_uk_free_big_block_s in "mali_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_free_big_block( _mali_uk_free_big_block_s *args );
-
/** @brief Map Mali Memory into the current user process
*
* Maps Mali memory into the current user process in a generic way.
*
* This function is to be used for Mali-MMU mode. The function is available in both Mali-MMU and Mali-nonMMU modes,
- * but should not be called by a user process in Mali-nonMMU mode. In Mali-nonMMU mode, the function is callable
- * from the kernel side, and is used to implement _mali_ukk_get_big_block() in this case.
+ * but should not be called by a user process in Mali-nonMMU mode.
*
* The implementation and operation of _mali_ukk_mem_mmap() is dependant on whether the driver is built for Mali-MMU
* or Mali-nonMMU:
@@ -392,9 +372,6 @@ _mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args );
* they are unnecsessary; the \em Mali-virtual address range must be used for
* programming Mali structures.
*
- * This means that in the first (nonMMU) case, the caller must manage the physical address allocations. The caller
- * in this case is _mali_ukk_get_big_block(), which does indeed manage the Mali physical address ranges.
- *
* In the second (MMU) case, _mali_ukk_mem_mmap() handles management of
* CPU-virtual and CPU-physical ranges, but the \em caller must manage the
* \em Mali-virtual address range from the user-side.
@@ -403,7 +380,7 @@ _mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args );
* It is not possible for a process to accidentally corrupt another process'
* \em Mali-virtual address space.
*
- * @param args see _mali_uk_mem_mmap_s in "mali_uk_types.h"
+ * @param args see _mali_uk_mem_mmap_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_mmap( _mali_uk_mem_mmap_s *args );
@@ -413,42 +390,42 @@ _mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args );
* Unmaps Mali memory from the current user process in a generic way. This only operates on Mali memory supplied
* from _mali_ukk_mem_mmap().
*
- * @param args see _mali_uk_mem_munmap_s in "mali_uk_types.h"
+ * @param args see _mali_uk_mem_munmap_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_munmap( _mali_uk_mem_munmap_s *args );
/** @brief Determine the buffer size necessary for an MMU page table dump.
- * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_uk_types.h
+ * @param args see _mali_uk_query_mmu_page_table_dump_size_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_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args );
/** @brief Dump MMU Page tables.
- * @param args see _mali_uk_dump_mmu_page_table_s in mali_uk_types.h
+ * @param args see _mali_uk_dump_mmu_page_table_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_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args );
/** @brief Map a physically contiguous range of memory into Mali
- * @param args see _mali_uk_map_external_mem_s in mali_uk_types.h
+ * @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.
*/
_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args );
/** @brief Unmap a physically contiguous range of memory from Mali
- * @param args see _mali_uk_unmap_external_mem_s in mali_uk_types.h
+ * @param args see _mali_uk_unmap_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.
*/
_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args );
#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
/** @brief Map UMP memory into Mali
- * @param args see _mali_uk_attach_ump_mem_s in mali_uk_types.h
+ * @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.
*/
_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args );
/** @brief Unmap UMP memory from Mali
- * @param args see _mali_uk_release_ump_mem_s in mali_uk_types.h
+ * @param args see _mali_uk_release_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.
*/
_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args );
@@ -492,7 +469,7 @@ _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args
* @note if implemented, this function is entirely platform-dependant, and does
* not exist in common code.
*
- * @param args see _mali_uk_va_to_mali_pa_s in "mali_uk_types.h"
+ * @param args see _mali_uk_va_to_mali_pa_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_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args );
@@ -519,20 +496,16 @@ _mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args );
* existing one returned, otherwise the new job is started and the status field args->status is set to
* _MALI_UK_START_JOB_STARTED.
*
- * If an existing lower priority job is returned, args->returned_user_job_ptr contains a
- * pointer to the returned job and the status field args->status is set to
- * _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED.
- *
* Job completion can be awaited with _mali_ukk_wait_for_notification().
*
- * @param args see _mali_uk_pp_start_job_s in "mali_uk_types.h"
+ * @param args see _mali_uk_pp_start_job_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_pp_start_job( _mali_uk_pp_start_job_s *args );
/** @brief Returns the number of Fragment Processors in the system
*
- * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_pp_number_of_cores_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_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args );
@@ -542,22 +515,18 @@ _mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_
* This function may only be called when _mali_ukk_get_pp_number_of_cores() indicated at least one Fragment
* Processor core is available.
*
- * @param args see _mali_uk_get_pp_core_version_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_pp_core_version_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_get_pp_core_version( _mali_uk_get_pp_core_version_s *args );
-/** @brief Abort any PP jobs with the given ID.
+/** @brief Disable Write-back unit(s) on specified job
*
- * Jobs internally queued or currently running on the hardware is to be stopped/aborted.
- * Jobs aborted are reported via the normal job completion system.
- * Any jobs, running or internally queued should be aborted imediately.
- * Normal notifiction procedures to report on the status of these jobs.
- *
- *
- * @param args see _malu_uk_pp_abort_job_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h"
*/
-void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_s *args );
+void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args);
+
+
/** @} */ /* end group _mali_uk_pp */
@@ -580,20 +549,16 @@ void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_s *args );
* existing one returned, otherwise the new job is started and the status field args->status is set to
* _MALI_UK_START_JOB_STARTED.
*
- * If an existing lower priority job is returned, args->returned_user_job_ptr contains a pointer to
- * the returned job and the status field args->status is set to
- * _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED.
- *
* Job completion can be awaited with _mali_ukk_wait_for_notification().
*
- * @param args see _mali_uk_gp_start_job_s in "mali_uk_types.h"
+ * @param args see _mali_uk_gp_start_job_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_gp_start_job( _mali_uk_gp_start_job_s *args );
/** @brief Returns the number of Vertex Processors in the system.
*
- * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_gp_number_of_cores_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_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args );
@@ -603,7 +568,7 @@ _mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_
* This function may only be called when _mali_uk_get_gp_number_of_cores() indicated at least one Vertex
* Processor core is available.
*
- * @param args see _mali_uk_get_gp_core_version_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_gp_core_version_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_get_gp_core_version( _mali_uk_get_gp_core_version_s *args );
@@ -613,85 +578,47 @@ _mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_
* After receiving notification that a Vertex Processor job was suspended from
* _mali_ukk_wait_for_notification() you can use this function to resume or abort the job.
*
- * @param args see _mali_uk_gp_suspend_response_s in "mali_uk_types.h"
+ * @param args see _mali_uk_gp_suspend_response_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_gp_suspend_response( _mali_uk_gp_suspend_response_s *args );
-/** @brief Abort any GP jobs with the given ID.
- *
- * Jobs internally queued or currently running on the hardware is to be stopped/aborted.
- * Jobs aborted are reported via the normal job completion system.
- *
- * Any jobs, running or internally queued should be aborted imediately.
- * Normal notifiction procedures to report on the status of these jobs.
- *
- * @param args see _mali_uk_gp_abort_job_s in "mali_uk_types.h"
- */
-void _mali_ukk_gp_abort_job( _mali_uk_gp_abort_job_s *args );
/** @} */ /* end group _mali_uk_gp */
-#if USING_MALI_PMM
-/** @addtogroup _mali_uk_pmm U/K Power Management Module
- * @{ */
-
-/* @brief Power Management Module event message
- *
- * @note The event message can fail to be sent due to OOM but this is
- * stored in the PMM state machine to be handled later
- *
- * @param args see _mali_uk_pmm_event_message_s in "mali_uk_types.h"
- */
-void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args );
-/** @} */ /* end group _mali_uk_pmm */
-#endif /* USING_MALI_PMM */
-
#if MALI_TIMELINE_PROFILING_ENABLED
/** @addtogroup _mali_uk_profiling U/K Timeline profiling module
* @{ */
/** @brief Start recording profiling events.
*
- * @param args see _mali_uk_profiling_start_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_start_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args);
/** @brief Add event to profiling buffer.
*
- * @param args see _mali_uk_profiling_add_event_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_add_event_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args);
/** @brief Stop recording profiling events.
*
- * @param args see _mali_uk_profiling_stop_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_stop_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args);
/** @brief Retrieve a recorded profiling event.
*
- * @param args see _mali_uk_profiling_get_event_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_get_event_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args);
/** @brief Clear recorded profiling events.
*
- * @param args see _mali_uk_profiling_clear_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_clear_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args);
-/** @brief Get the profiling config applicable for calling process.
- *
- * @param args see _mali_uk_profiling_get_config_s in "mali_uk_types.h"
- */
-_mali_osk_errcode_t _mali_ukk_profiling_get_config(_mali_uk_profiling_get_config_s *args);
-
-/** @brief Transfer software counters from user to kernel space
- *
- * @param args see _mali_uk_transfer_sw_counters_s in "mali_uk_types.h"
- */
-_mali_osk_errcode_t _mali_ukk_transfer_sw_counters(_mali_uk_sw_counters_s *args);
-
/** @} */ /* end group _mali_uk_profiling */
#endif
@@ -704,12 +631,23 @@ _mali_osk_errcode_t _mali_ukk_transfer_sw_counters(_mali_uk_sw_counters_s *args)
* waiting is finished. This information can then be used in kernel space to
* complement the GPU utilization metric.
*
- * @param args see _mali_uk_vsync_event_report_s in "mali_uk_types.h"
+ * @param args see _mali_uk_vsync_event_report_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args);
/** @} */ /* end group _mali_uk_vsync */
+/** @addtogroup _mali_sw_counters_report U/K Software counter reporting
+ * @{ */
+
+/** @brief Report software counters.
+ *
+ * @param args see _mali_uk_sw_counters_report_s in "mali_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args);
+
+/** @} */ /* end group _mali_sw_counters_report */
+
/** @} */ /* end group u_k_api */
/** @} */ /* end group uddapi */
diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c
new file mode 100644
index 0000000..681c2b0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c
@@ -0,0 +1,88 @@
+/**
+ * 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_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_uk_types.h"
+#include "mali_user_settings_db.h"
+#include "mali_session.h"
+
+static u32 mali_user_settings[_MALI_UK_USER_SETTING_MAX];
+const char *_mali_uk_user_setting_descriptions[] = _MALI_UK_USER_SETTING_DESCRIPTIONS;
+
+static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value)
+{
+ 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_SETTINGS_CHANGED, sizeof(_mali_uk_settings_changed_s));
+ _mali_uk_settings_changed_s *data = notobj->result_buffer;
+ data->setting = setting;
+ data->value = value;
+
+ mali_session_send_notification(session, notobj);
+ }
+ mali_session_unlock();
+}
+
+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 (mali_user_settings[setting] != value)
+ {
+ notify = MALI_TRUE;
+ }
+
+ mali_user_settings[setting] = value;
+
+ if (notify)
+ {
+ mali_user_settings_notify(setting, value);
+ }
+}
+
+u32 mali_get_user_setting(_mali_uk_user_setting_t setting)
+{
+ MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0);
+
+ return mali_user_settings[setting];
+}
+
+_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args)
+{
+ _mali_uk_user_setting_t setting;
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ setting = args->setting;
+
+ if (0 <= setting && _MALI_UK_USER_SETTING_MAX > setting)
+ {
+ args->value = mali_user_settings[setting];
+ return _MALI_OSK_ERR_OK;
+ }
+ else
+ {
+ return _MALI_OSK_ERR_INVALID_ARGS;
+ }
+}
+
+_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ _mali_osk_memcpy(args->settings, mali_user_settings, (sizeof(u32) * _MALI_UK_USER_SETTING_MAX));
+
+ return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h
new file mode 100644
index 0000000..fbb9415
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h
@@ -0,0 +1,40 @@
+/**
+ * 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_USER_SETTINGS_DB_H__
+#define __MALI_USER_SETTINGS_DB_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "mali_uk_types.h"
+
+/** @brief Set Mali user setting in DB
+ *
+ * Update the DB with a new value for \a setting. If the value is different from theprevious set value running sessions will be notified of the change.
+ *
+ * @param setting the setting to be changed
+ * @param value the new value to set
+ */
+void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value);
+
+/** @brief Get current Mali user setting value from DB
+ *
+ * @param setting the setting to extract
+ * @return the value of the selected setting
+ */
+u32 mali_get_user_setting(_mali_uk_user_setting_t setting);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MALI_KERNEL_USER_SETTING__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c
deleted file mode 100644
index 7041391..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c
+++ /dev/null
@@ -1,1024 +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.
- */
-
-/**
- * @file mali_pmm.c
- * Implementation of the power management module for the kernel device driver
- */
-
-#if USING_MALI_PMM
-
-#include "mali_ukk.h"
-#include "mali_kernel_common.h"
-#include "mali_kernel_subsystem.h"
-
-#include "mali_pmm.h"
-#include "mali_pmm_system.h"
-#include "mali_pmm_state.h"
-#include "mali_pmm_policy.h"
-#include "mali_pmm_pmu.h"
-#include "mali_platform.h"
-#include "mali_kernel_pm.h"
-
-/* Internal PMM subsystem state */
-static _mali_pmm_internal_state_t *pmm_state = NULL;
-/* Mali kernel subsystem id */
-static mali_kernel_subsystem_identifier mali_subsystem_pmm_id = -1;
-
-#define GET_PMM_STATE_PTR (pmm_state)
-
-/* Internal functions */
-static _mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource);
-static void pmm_event_process( void );
-_mali_osk_errcode_t malipmm_irq_uhandler(void *data);
-void malipmm_irq_bhandler(void *data);
-
-/** @brief Start the PMM subsystem
- *
- * @param id Subsystem id to uniquely identify this subsystem
- * @return _MALI_OSK_ERR_OK if the system started successfully, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t malipmm_kernel_subsystem_start( mali_kernel_subsystem_identifier id );
-
-/** @brief Perform post start up of the PMM subsystem
- *
- * Post start up includes initializing the current policy, now that the system is
- * completely started - to stop policies turning off hardware during the start up
- *
- * @param id the unique subsystem id
- * @return _MALI_OSK_ERR_OK if the post startup was successful, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifier id );
-
-/** @brief Terminate the PMM subsystem
- *
- * @param id the unique subsystem id
- */
-void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id );
-
-#if MALI_STATE_TRACKING
-u32 malipmm_subsystem_dump_state( char *buf, u32 size );
-#endif
-
-
-/* This will be one of the subsystems in the array of subsystems:
- static struct mali_kernel_subsystem * subsystems[];
- found in file: mali_kernel_core.c
-*/
-struct mali_kernel_subsystem mali_subsystem_pmm=
-{
- malipmm_kernel_subsystem_start, /* startup */
- NULL, /*malipmm_kernel_subsystem_terminate,*/ /* shutdown */
- malipmm_kernel_load_complete, /* loaded all subsystems */
- NULL,
- NULL,
- NULL,
- NULL,
-#if MALI_STATE_TRACKING
- malipmm_subsystem_dump_state, /* dump_state */
-#endif
-};
-
-#if PMM_OS_TEST
-
-u32 power_test_event = 0;
-mali_bool power_test_flag = MALI_FALSE;
-_mali_osk_timer_t *power_test_timer = NULL;
-
-void _mali_osk_pmm_power_up_done(mali_pmm_message_data data)
-{
- MALI_PRINT(("POWER TEST OS UP DONE\n"));
-}
-
-void _mali_osk_pmm_power_down_done(mali_pmm_message_data data)
-{
- MALI_PRINT(("POWER TEST OS DOWN DONE\n"));
-}
-
-/**
- * Symbian OS Power Up call to the driver
- */
-void power_test_callback( void *arg )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- power_test_flag = MALI_TRUE;
- _mali_osk_irq_schedulework( pmm->irq );
-}
-
-void power_test_start()
-{
- power_test_timer = _mali_osk_timer_init();
- _mali_osk_timer_setcallback( power_test_timer, power_test_callback, NULL );
-
- /* First event is power down */
- power_test_event = MALI_PMM_EVENT_OS_POWER_DOWN;
- _mali_osk_timer_add( power_test_timer, 10000 );
-}
-
-mali_bool power_test_check()
-{
- if( power_test_flag )
- {
- _mali_uk_pmm_message_s event = {
- NULL,
- 0,
- 1 };
- event.id = power_test_event;
-
- power_test_flag = MALI_FALSE;
-
- /* Send event */
- _mali_ukk_pmm_event_message( &event );
-
- /* Switch to next event to test */
- if( power_test_event == MALI_PMM_EVENT_OS_POWER_DOWN )
- {
- power_test_event = MALI_PMM_EVENT_OS_POWER_UP;
- }
- else
- {
- power_test_event = MALI_PMM_EVENT_OS_POWER_DOWN;
- }
- _mali_osk_timer_add( power_test_timer, 5000 );
-
- return MALI_TRUE;
- }
-
- return MALI_FALSE;
-}
-
-void power_test_end()
-{
- _mali_osk_timer_del( power_test_timer );
- _mali_osk_timer_term( power_test_timer );
- power_test_timer = NULL;
-}
-
-#endif
-
-void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- _mali_osk_notification_t *msg;
- mali_pmm_message_t *event;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(args);
-
- MALIPMM_DEBUG_PRINT( ("PMM: sending message\n") );
-
-#if MALI_PMM_TRACE && MALI_PMM_TRACE_SENT_EVENTS
- _mali_pmm_trace_event_message( args, MALI_FALSE );
-#endif
-
- msg = _mali_osk_notification_create( MALI_PMM_NOTIFICATION_TYPE, sizeof( mali_pmm_message_t ) );
-
- if( msg )
- {
- event = (mali_pmm_message_t *)msg->result_buffer;
- event->id = args->id;
- event->ts = _mali_osk_time_tickcount();
- event->data = args->data;
-
- _mali_osk_atomic_inc( &(pmm->messages_queued) );
-
- if( args->id > MALI_PMM_EVENT_INTERNALS )
- {
- /* Internal PMM message */
- _mali_osk_notification_queue_send( pmm->iqueue, msg );
- #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
- pmm->imessages_sent++;
- #endif
- }
- else
- {
- /* Real event */
- _mali_osk_notification_queue_send( pmm->queue, msg );
- #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
- pmm->messages_sent++;
- #endif
- }
- }
- else
- {
- MALI_PRINT_ERROR( ("PMM: Could not send message %d", args->id) );
- /* Make note of this OOM - which has caused a missed event */
- pmm->missed++;
- }
-
- /* Schedule time to look at the event or the fact we couldn't create an event */
- _mali_osk_irq_schedulework( pmm->irq );
-}
-
-mali_pmm_state _mali_pmm_state( void )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- if( pmm && (mali_subsystem_pmm_id != -1) )
- {
- return pmm->state;
- }
-
- /* No working subsystem yet */
- return MALI_PMM_STATE_UNAVAILABLE;
-}
-
-
-mali_pmm_core_mask _mali_pmm_cores_list( void )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- return pmm->cores_registered;
-}
-
-mali_pmm_core_mask _mali_pmm_cores_powered( void )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- return pmm->cores_powered;
-}
-
-
-_mali_osk_errcode_t _mali_pmm_list_policies(
- u32 policy_list_size,
- mali_pmm_policy *policy_list,
- u32 *policies_available )
-{
- /* TBD - This is currently a stub function for basic power management */
-
- MALI_ERROR( _MALI_OSK_ERR_UNSUPPORTED );
-}
-
-_mali_osk_errcode_t _mali_pmm_set_policy( mali_pmm_policy policy )
-{
- /* TBD - This is currently a stub function for basic power management */
-
-/* TBD - When this is not a stub... include tracing...
-#if MALI_PMM_TRACE
- _mali_pmm_trace_policy_change( old, newpolicy );
-#endif
-*/
- MALI_ERROR( _MALI_OSK_ERR_UNSUPPORTED );
-}
-
-_mali_osk_errcode_t _mali_pmm_get_policy( mali_pmm_policy *policy )
-{
- if( policy )
- {
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- if( pmm )
- {
- *policy = pmm->policy;
- MALI_SUCCESS;
- }
- else
- {
- *policy = MALI_PMM_POLICY_NONE;
- MALI_ERROR( _MALI_OSK_ERR_FAULT );
- }
- }
-
- /* No return argument */
- MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS );
-}
-
-#if ( MALI_PMM_TRACE || MALI_STATE_TRACKING )
-
-/* Event names - order must match mali_pmm_event_id enum */
-static char *pmm_trace_events[] = {
- "OS_POWER_UP",
- "OS_POWER_DOWN",
- "JOB_SCHEDULED",
- "JOB_QUEUED",
- "JOB_FINISHED",
- "TIMEOUT",
-};
-
-/* State names - order must match mali_pmm_state enum */
-static char *pmm_trace_state[] = {
- "UNAVAILABLE",
- "SYSTEM ON",
- "SYSTEM OFF",
- "SYSTEM TRANSITION",
-};
-
-/* Policy names - order must match mali_pmm_policy enum */
-static char *pmm_trace_policy[] = {
- "NONE",
- "ALWAYS ON",
- "JOB CONTROL",
-};
-
-/* Status names - order must match mali_pmm_status enum */
-static char *pmm_trace_status[] = {
- "MALI_PMM_STATUS_IDLE", /**< PMM is waiting next event */
- "MALI_PMM_STATUS_POLICY_POWER_DOWN", /**< Policy initiated power down */
- "MALI_PMM_STATUS_POLICY_POWER_UP", /**< Policy initiated power down */
- "MALI_PMM_STATUS_OS_WAITING", /**< PMM is waiting for OS power up */
- "MALI_PMM_STATUS_OS_POWER_DOWN", /**< OS initiated power down */
- "MALI_PMM_STATUS_RUNTIME_IDLE_IN_PROGRESS",
- "MALI_PMM_STATUS_DVFS_PAUSE", /**< PMM DVFS Status Pause */
- "MALI_PMM_STATUS_OS_POWER_UP", /**< OS initiated power up */
- "MALI_PMM_STATUS_OFF", /**< PMM is not active */
-};
-
-#endif /* MALI_PMM_TRACE || MALI_STATE_TRACKING */
-#if MALI_PMM_TRACE
-
-/* UK event names - order must match mali_pmm_event_id enum */
-static char *pmm_trace_events_uk[] = {
- "UKS",
- "UK_EXAMPLE",
-};
-
-/* Internal event names - order must match mali_pmm_event_id enum */
-static char *pmm_trace_events_internal[] = {
- "INTERNALS",
- "INTERNAL_POWER_UP_ACK",
- "INTERNAL_POWER_DOWN_ACK",
-};
-
-void _mali_pmm_trace_hardware_change( mali_pmm_core_mask old, mali_pmm_core_mask newstate )
-{
- const char *dname;
- const char *cname;
- const char *ename;
-
- if( old != newstate )
- {
- if( newstate == 0 )
- {
- dname = "NO cores";
- }
- else
- {
- dname = pmm_trace_get_core_name( newstate );
- }
-
- /* These state checks only work if the assumption that only cores can be
- * turned on or turned off in seperate actions is true. If core power states can
- * be toggled (some one, some off) at the same time, this check does not work
- */
- if( old > newstate )
- {
- /* Cores have turned off */
- cname = pmm_trace_get_core_name( old - newstate );
- ename = "OFF";
- }
- else
- {
- /* Cores have turned on */
- cname = pmm_trace_get_core_name( newstate - old );
- ename = "ON";
- }
- MALI_PRINT( ("PMM Trace: Hardware %s ON, %s just turned %s. { 0x%08x -> 0x%08x }", dname, cname, ename, old, newstate) );
- }
-}
-
-void _mali_pmm_trace_state_change( mali_pmm_state old, mali_pmm_state newstate )
-{
- if( old != newstate )
- {
- MALI_PRINT( ("PMM Trace: State changed from %s to %s", pmm_trace_state[old], pmm_trace_state[newstate]) );
- }
-}
-
-void _mali_pmm_trace_policy_change( mali_pmm_policy old, mali_pmm_policy newpolicy )
-{
- if( old != newpolicy )
- {
- MALI_PRINT( ("PMM Trace: Policy changed from %s to %s", pmm_trace_policy[old], pmm_trace_policy[newpolicy]) );
- }
-}
-
-void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool received )
-{
- const char *ename;
- const char *dname;
- const char *tname;
- const char *format = "PMM Trace: Event %s { (%d) %s, %d ticks, (0x%x) %s }";
-
- MALI_DEBUG_ASSERT_POINTER(event);
-
- tname = (received) ? "received" : "sent";
-
- if( event->id >= MALI_PMM_EVENT_INTERNALS )
- {
- ename = pmm_trace_events_internal[((int)event->id) - MALI_PMM_EVENT_INTERNALS];
- }
- else if( event->id >= MALI_PMM_EVENT_UKS )
- {
- ename = pmm_trace_events_uk[((int)event->id) - MALI_PMM_EVENT_UKS];
- }
- else
- {
- ename = pmm_trace_events[event->id];
- }
-
- switch( event->id )
- {
- case MALI_PMM_EVENT_OS_POWER_UP:
- case MALI_PMM_EVENT_OS_POWER_DOWN:
- dname = "os event";
- break;
-
- case MALI_PMM_EVENT_JOB_SCHEDULED:
- case MALI_PMM_EVENT_JOB_QUEUED:
- case MALI_PMM_EVENT_JOB_FINISHED:
- case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
- case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
- dname = pmm_trace_get_core_name( (mali_pmm_core_mask)event->data );
- break;
-
- case MALI_PMM_EVENT_TIMEOUT:
- dname = "timeout start";
- /* Print data with a different format */
- format = "PMM Trace: Event %s { (%d) %s, %d ticks, %d ticks %s }";
- break;
- default:
- dname = "unknown data";
- }
-
- MALI_PRINT( (format, tname, (u32)event->id, ename, event->ts, (u32)event->data, dname) );
-}
-
-#endif /* MALI_PMM_TRACE */
-
-
-/****************** Mali Kernel API *****************/
-
-_mali_osk_errcode_t malipmm_kernel_subsystem_start( mali_kernel_subsystem_identifier id )
-{
- mali_subsystem_pmm_id = id;
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(PMU, malipmm_create));
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource)
-{
- /* Create PMM state memory */
- MALI_DEBUG_ASSERT( pmm_state == NULL );
- pmm_state = (_mali_pmm_internal_state_t *) _mali_osk_malloc(sizeof(*pmm_state));
- MALI_CHECK_NON_NULL( pmm_state, _MALI_OSK_ERR_NOMEM );
-
- /* All values get 0 as default */
- _mali_osk_memset(pmm_state, 0, sizeof(*pmm_state));
-
- /* Set up the initial PMM state */
- pmm_state->waiting = 0;
- pmm_state->status = MALI_PMM_STATUS_IDLE;
- pmm_state->state = MALI_PMM_STATE_UNAVAILABLE; /* Until a core registers */
-
- /* Set up policy via compile time option for the moment */
-#if MALI_PMM_ALWAYS_ON
- pmm_state->policy = MALI_PMM_POLICY_ALWAYS_ON;
-#else
- pmm_state->policy = MALI_PMM_POLICY_JOB_CONTROL;
-#endif
-
-#if MALI_PMM_TRACE
- _mali_pmm_trace_policy_change( MALI_PMM_POLICY_NONE, pmm_state->policy );
-#endif
-
- /* Set up assumes all values are initialized to NULL or MALI_FALSE, so
- * we can exit halfway through set up and perform clean up
- */
-
-#if USING_MALI_PMU
- if( mali_pmm_pmu_init(resource) != _MALI_OSK_ERR_OK ) goto pmm_fail_cleanup;
- pmm_state->pmu_initialized = MALI_TRUE;
-#endif
- pmm_state->queue = _mali_osk_notification_queue_init();
- if( !pmm_state->queue ) goto pmm_fail_cleanup;
-
- pmm_state->iqueue = _mali_osk_notification_queue_init();
- if( !pmm_state->iqueue ) goto pmm_fail_cleanup;
-
- /* We are creating an IRQ handler just for the worker thread it gives us */
- pmm_state->irq = _mali_osk_irq_init( _MALI_OSK_IRQ_NUMBER_PMM,
- malipmm_irq_uhandler,
- malipmm_irq_bhandler,
- NULL,
- NULL,
- (void *)pmm_state, /* PMM state is passed to IRQ */
- "PMM handler" );
-
- if( !pmm_state->irq ) goto pmm_fail_cleanup;
-
- pmm_state->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 75);
- if( !pmm_state->lock ) goto pmm_fail_cleanup;
-
- if( _mali_osk_atomic_init( &(pmm_state->messages_queued), 0 ) != _MALI_OSK_ERR_OK )
- {
- goto pmm_fail_cleanup;
- }
-
- MALIPMM_DEBUG_PRINT( ("PMM: subsystem created, policy=%d\n", pmm_state->policy) );
-
- MALI_SUCCESS;
-
-pmm_fail_cleanup:
- MALI_PRINT_ERROR( ("PMM: subsystem failed to be created\n") );
- if( pmm_state )
- {
- if( pmm_state->lock ) _mali_osk_lock_term( pmm_state->lock );
- if( pmm_state->irq ) _mali_osk_irq_term( pmm_state->irq );
- if( pmm_state->queue ) _mali_osk_notification_queue_term( pmm_state->queue );
- if( pmm_state->iqueue ) _mali_osk_notification_queue_term( pmm_state->iqueue );
-#if USING_MALI_PMU
- if( pmm_state->pmu_initialized )
- {
- _mali_osk_resource_type_t t = PMU;
- mali_pmm_pmu_deinit(&t);
- }
-#endif /* USING_MALI_PMU */
-
- _mali_osk_free(pmm_state);
- pmm_state = NULL;
- }
- MALI_ERROR( _MALI_OSK_ERR_FAULT );
-}
-
-_mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifier id )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- MALIPMM_DEBUG_PRINT( ("PMM: subsystem loaded, policy initializing\n") );
-
-#if PMM_OS_TEST
- power_test_start();
-#endif
-
- /* Initialize the profile now the system has loaded - so that cores are
- * not turned off during start up
- */
- return pmm_policy_init( pmm );
-}
-
-void malipmm_force_powerup( void )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_LOCK(pmm);
- pmm->status = MALI_PMM_STATUS_OFF;
- MALI_PMM_UNLOCK(pmm);
-
- /* flush PMM workqueue */
- _mali_osk_flush_workqueue( pmm->irq );
-
- if (pmm->cores_powered == 0)
- {
- malipmm_powerup(pmm->cores_registered);
- }
-}
-
-void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id )
-{
- /* Check this is the right system */
- MALI_DEBUG_ASSERT( id == mali_subsystem_pmm_id );
- MALI_DEBUG_ASSERT_POINTER(pmm_state);
-
- if( pmm_state )
- {
-#if PMM_OS_TEST
- power_test_end();
-#endif
- /* Get the lock so we can shutdown */
- MALI_PMM_LOCK(pmm_state);
-#if MALI_STATE_TRACKING
- pmm_state->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
- pmm_state->status = MALI_PMM_STATUS_OFF;
-#if MALI_STATE_TRACKING
- pmm_state->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
- MALI_PMM_UNLOCK(pmm_state);
- _mali_osk_pmm_ospmm_cleanup();
- pmm_policy_term(pmm_state);
- _mali_osk_irq_term( pmm_state->irq );
- _mali_osk_notification_queue_term( pmm_state->queue );
- _mali_osk_notification_queue_term( pmm_state->iqueue );
- if (pmm_state->cores_registered) malipmm_powerdown(pmm_state->cores_registered,MALI_POWER_MODE_LIGHT_SLEEP);
-#if USING_MALI_PMU
- if( pmm_state->pmu_initialized )
- {
- _mali_osk_resource_type_t t = PMU;
- mali_pmm_pmu_deinit(&t);
- }
-#endif /* USING_MALI_PMU */
-
- _mali_osk_atomic_term( &(pmm_state->messages_queued) );
- MALI_PMM_LOCK_TERM(pmm_state);
- _mali_osk_free(pmm_state);
- pmm_state = NULL;
- }
-
- MALIPMM_DEBUG_PRINT( ("PMM: subsystem terminated\n") );
-}
-
-_mali_osk_errcode_t malipmm_powerup( u32 cores )
-{
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
-
- /* If all the cores are powered down, power up the MALI */
- if (pmm->cores_powered == 0) {
- mali_platform_power_mode_change(MALI_POWER_MODE_ON);
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
- /* Initiate the power up */
- if (_mali_osk_pmm_dev_activate() < 0) {
- MALI_PRINT(("PMM: Try again PD_G3D enable\n"));
- if (mali_pd_enable() < 0) {
- MALI_PRINT(("PMM: Mali PMM device activate failed\n"));
- err = _MALI_OSK_ERR_FAULT;
- return err;
- }
- }
-#endif
- }
-
-#if USING_MALI_PMU
- err = mali_pmm_pmu_powerup( cores );
-#endif
-
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
- mali_platform_powerup(cores);
-#endif
-
- return err;
-}
-
-_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode )
-{
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
-
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
- mali_platform_powerdown(cores);
-#endif
-
-#if USING_MALI_PMU
- err = mali_pmm_pmu_powerdown( cores );
-#endif
-
- /* If all cores are powered down, power off the MALI */
- if (pmm->cores_powered == 0)
- {
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
- /* Initiate the power down */
- _mali_osk_pmm_dev_idle();
-#endif
- mali_platform_power_mode_change(power_mode);
- }
- return err;
-}
-
-_mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core )
-{
- _mali_osk_errcode_t err;
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
-
- if( pmm == NULL )
- {
- /* PMM state has not been created, this is because the PMU resource has not been
- * created yet.
- * This probably means that the PMU resource has not been specfied as the first
- * resource in the config file
- */
- MALI_PRINT_ERROR( ("PMM: Cannot register core %s because the PMU resource has not been\n initialized. Please make sure the PMU resource is the first resource in the\n resource configuration.\n",
- pmm_trace_get_core_name(core)) );
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- MALI_PMM_LOCK(pmm);
-
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
-
- /* Check if the core is registered more than once in PMM */
- MALI_DEBUG_ASSERT( (pmm->cores_registered & core) == 0 );
-
- MALIPMM_DEBUG_PRINT( ("PMM: core registered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) );
-
-#if !MALI_PMM_NO_PMU
- /* Make sure the core is powered up */
- err = malipmm_powerup( core );
-#else
- err = _MALI_OSK_ERR_OK;
-#endif
- if( _MALI_OSK_ERR_OK == err )
- {
-#if MALI_PMM_TRACE
- mali_pmm_core_mask old_power = pmm->cores_powered;
-#endif
- /* Assume a registered core is now powered up and idle */
- pmm->cores_registered |= core;
- pmm->cores_idle |= core;
- pmm->cores_powered |= core;
- pmm_update_system_state( pmm );
-
-#if MALI_PMM_TRACE
- _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
-#endif
- }
- else
- {
- MALI_PRINT_ERROR( ("PMM: Error(%d) powering up registered core: (0x%x) %s\n",
- err, core, pmm_trace_get_core_name(core)) );
- }
-
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
-
- return err;
-}
-
-void malipmm_core_unregister( mali_pmm_core_id core )
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- MALI_PMM_LOCK(pmm);
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
-
- /* Check if the core is registered in PMM */
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, core );
-
- MALIPMM_DEBUG_PRINT( ("PMM: core unregistered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) );
-
- {
-#if MALI_PMM_TRACE
- mali_pmm_core_mask old_power = pmm->cores_powered;
-#endif
-
- /* Remove the core from the system */
- pmm->cores_idle &= (~core);
- pmm->cores_powered &= (~core);
- pmm->cores_pend_down &= (~core);
- pmm->cores_pend_up &= (~core);
- pmm->cores_ack_down &= (~core);
- pmm->cores_ack_up &= (~core);
-
- pmm_update_system_state( pmm );
-
-#if MALI_PMM_TRACE
- _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
-#endif
- }
-
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
-}
-void malipmm_core_power_down_okay( mali_pmm_core_id core )
-{
- _mali_uk_pmm_message_s event = {
- NULL,
- MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK,
- 0 };
-
- event.data = core;
-
- _mali_ukk_pmm_event_message( &event );
-}
-
-void malipmm_set_policy_check()
-{
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- pmm->check_policy = MALI_TRUE;
-
- /* To check the policy we need to schedule some work */
- _mali_osk_irq_schedulework( pmm->irq );
-}
-
-_mali_osk_errcode_t malipmm_irq_uhandler(void *data)
-{
- MALIPMM_DEBUG_PRINT( ("PMM: uhandler - not expected to be used\n") );
-
- MALI_SUCCESS;
-}
-
-void malipmm_irq_bhandler(void *data)
-{
- _mali_pmm_internal_state_t *pmm;
- pmm = (_mali_pmm_internal_state_t *)data;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
-#if PMM_OS_TEST
- if( power_test_check() ) return;
-#endif
-
- MALI_PMM_LOCK(pmm);
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
- /* Quick out when we are shutting down */
- if( pmm->status == MALI_PMM_STATUS_OFF )
- {
-
- #if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
- #endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
- return;
- }
-
- MALIPMM_DEBUG_PRINT( ("PMM: bhandler - Processing event\n") );
-
- if( pmm->missed > 0 )
- {
- MALI_PRINT_ERROR( ("PMM: Failed to send %d events", pmm->missed) );
- pmm_fatal_reset( pmm );
- }
-
- if( pmm->check_policy )
- {
- pmm->check_policy = MALI_FALSE;
- pmm_policy_check_policy(pmm);
- }
- else
- {
- /* Perform event processing */
- pmm_event_process();
- if( pmm->fatal_power_err )
- {
- /* Try a reset */
- pmm_fatal_reset( pmm );
- }
- }
-
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
-}
-
-static void pmm_event_process( void )
-{
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
- _mali_osk_notification_t *msg = NULL;
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
- mali_pmm_message_t *event;
- u32 process_messages;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
-
- /* Max number of messages to process before exiting - as we shouldn't stay
- * processing the messages for a long time
- */
- process_messages = _mali_osk_atomic_read( &(pmm->messages_queued) );
-
- while( process_messages > 0 )
- {
- /* Check internal message queue first */
- err = _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg );
-
- if( err != _MALI_OSK_ERR_OK )
- {
- if( pmm->status == MALI_PMM_STATUS_IDLE || pmm->status == MALI_PMM_STATUS_OS_WAITING || pmm->status == MALI_PMM_STATUS_DVFS_PAUSE)
- {
- if( pmm->waiting > 0 ) pmm->waiting--;
-
- /* We aren't busy changing state, so look at real events */
- err = _mali_osk_notification_queue_dequeue( pmm->queue, &msg );
-
- if( err != _MALI_OSK_ERR_OK )
- {
- pmm->no_events++;
- MALIPMM_DEBUG_PRINT( ("PMM: event_process - No message to process\n") );
- /* Nothing to do - so return */
- return;
- }
- else
- {
- #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
- pmm->messages_received++;
- #endif
- }
- }
- else
- {
- /* Waiting for an internal message */
- pmm->waiting++;
- MALIPMM_DEBUG_PRINT( ("PMM: event_process - Waiting for internal message, messages queued=%d\n", pmm->waiting) );
- return;
- }
- }
- else
- {
- #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
- pmm->imessages_received++;
- #endif
- }
-
- MALI_DEBUG_ASSERT_POINTER( msg );
- /* Check the message type matches */
- MALI_DEBUG_ASSERT( msg->notification_type == MALI_PMM_NOTIFICATION_TYPE );
-
- event = msg->result_buffer;
-
- _mali_osk_atomic_dec( &(pmm->messages_queued) );
- process_messages--;
-
- #if MALI_PMM_TRACE
- /* Trace before we process the event in case we have an error */
- _mali_pmm_trace_event_message( event, MALI_TRUE );
- #endif
- err = pmm_policy_process( pmm, event );
-
-
- if( err != _MALI_OSK_ERR_OK )
- {
- MALI_PRINT_ERROR( ("PMM: Error(%d) in policy %d when processing event message with id: %d",
- err, pmm->policy, event->id) );
- }
-
- /* Delete notification */
- _mali_osk_notification_delete ( msg );
-
- if( pmm->fatal_power_err )
- {
- /* Nothing good has happened - exit */
- return;
- }
-
-
- #if MALI_PMM_TRACE
- MALI_PRINT( ("PMM Trace: Event processed, msgs (sent/read) = %d/%d, int msgs (sent/read) = %d/%d, no events = %d, waiting = %d\n",
- pmm->messages_sent, pmm->messages_received, pmm->imessages_sent, pmm->imessages_received, pmm->no_events, pmm->waiting) );
- #endif
- }
-
- if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->waiting > 0 )
- {
- /* For events we ignored whilst we were busy, add a new
- * scheduled time to look at them */
- _mali_osk_irq_schedulework( pmm->irq );
- }
-}
-
-#if MALI_STATE_TRACKING
-u32 malipmm_subsystem_dump_state(char *buf, u32 size)
-{
- int len = 0;
- _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
-
- if( !pmm )
- {
- len += _mali_osk_snprintf(buf + len, size + len, "PMM: Null state\n");
- }
- else
- {
- len += _mali_osk_snprintf(buf+len, size+len, "Locks:\n PMM lock acquired: %s\n",
- pmm->mali_pmm_lock_acquired ? "true" : "false");
- len += _mali_osk_snprintf(buf+len, size+len,
- "PMM state:\n Previous status: %s\n Status: %s\n Current event: %s\n Policy: %s\n Check policy: %s\n State: %s\n",
- pmm_trace_status[pmm->mali_last_pmm_status], pmm_trace_status[pmm->status],
- pmm_trace_events[pmm->mali_new_event_status], pmm_trace_policy[pmm->policy],
- pmm->check_policy ? "true" : "false", pmm_trace_state[pmm->state]);
- len += _mali_osk_snprintf(buf+len, size+len,
- "PMM cores:\n Cores registered: %d\n Cores powered: %d\n Cores idle: %d\n"
- " Cores pending down: %d\n Cores pending up: %d\n Cores ack down: %d\n Cores ack up: %d\n",
- pmm->cores_registered, pmm->cores_powered, pmm->cores_idle, pmm->cores_pend_down,
- pmm->cores_pend_up, pmm->cores_ack_down, pmm->cores_ack_up);
- len += _mali_osk_snprintf(buf+len, size+len, "PMM misc:\n PMU init: %s\n Messages queued: %d\n"
- " Waiting: %d\n No events: %d\n Missed events: %d\n Fatal power error: %s\n",
- pmm->pmu_initialized ? "true" : "false", _mali_osk_atomic_read(&(pmm->messages_queued)),
- pmm->waiting, pmm->no_events, pmm->missed, pmm->fatal_power_err ? "true" : "false");
- }
- return len;
-}
-#endif /* MALI_STATE_TRACKING */
-
-#endif /* USING_MALI_PMM */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm.h
deleted file mode 100644
index 5170650..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.h
+++ /dev/null
@@ -1,348 +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.
- */
-
-/**
- * @file mali_pmm.h
- * Defines the power management module for the kernel device driver
- */
-
-#ifndef __MALI_PMM_H__
-#define __MALI_PMM_H__
-
-/* For mali_pmm_message_data and MALI_PMM_EVENT_UK_* defines */
-#include "mali_uk_types.h"
-#include "mali_platform.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @defgroup pmmapi Power Management Module APIs
- *
- * @{
- */
-
-/** OS event tester */
-#define PMM_OS_TEST 0
-
-/** @brief Compile option to turn on/off tracing */
-#define MALI_PMM_TRACE 0
-#define MALI_PMM_TRACE_SENT_EVENTS 0
-
-/** @brief Compile option to switch between always on or job control PMM policy */
-#define MALI_PMM_ALWAYS_ON 0
-
-/** @brief Overrides hardware PMU and uses software simulation instead
- * @note This even stops intialization of PMU and cores being powered on at start up
- */
-#define MALI_PMM_NO_PMU 0
-
-/** @brief PMM debug print to control debug message level */
-#define MALIPMM_DEBUG_PRINT(args) \
- MALI_DEBUG_PRINT(3, args)
-
-
-/** @brief power management event message identifiers.
- */
-/* These must match up with the pmm_trace_events & pmm_trace_events_internal
- * arrays
- */
-typedef enum mali_pmm_event_id
-{
- MALI_PMM_EVENT_OS_POWER_UP = 0, /**< OS power up event */
- MALI_PMM_EVENT_OS_POWER_DOWN = 1, /**< OS power down event */
- MALI_PMM_EVENT_JOB_SCHEDULED = 2, /**< Job scheduled to run event */
- MALI_PMM_EVENT_JOB_QUEUED = 3, /**< Job queued (but not run) event */
- MALI_PMM_EVENT_JOB_FINISHED = 4, /**< Job finished event */
- MALI_PMM_EVENT_TIMEOUT = 5, /**< Time out timer has expired */
- MALI_PMM_EVENT_DVFS_PAUSE = 6, /**< Mali device pause event */
- MALI_PMM_EVENT_DVFS_RESUME = 7, /**< Mali device resume event */
-
- MALI_PMM_EVENT_UKS = 200, /**< Events from the user-side start here */
- MALI_PMM_EVENT_UK_EXAMPLE = _MALI_PMM_EVENT_UK_EXAMPLE,
-
- MALI_PMM_EVENT_INTERNALS = 1000,
- MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK = 1001, /**< Internal power up acknowledgement */
- MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK = 1002, /**< Internal power down acknowledgment */
-} mali_pmm_event_id;
-
-
-/** @brief Use this when the power up/down callbacks do not need any OS data. */
-#define MALI_PMM_NO_OS_DATA 1
-
-
-/* @brief Geometry and pixel processor identifiers for the PMM
- *
- * @note these match the ARM Mali 400 PMU hardware definitions, apart from the "SYSTEM"
- */
-typedef enum mali_pmm_core_id_tag
-{
- MALI_PMM_CORE_SYSTEM = 0x00000000, /**< All of the Mali hardware */
- MALI_PMM_CORE_GP = 0x00000001, /**< Mali GP2 */
- MALI_PMM_CORE_L2 = 0x00000002, /**< Level 2 cache */
- MALI_PMM_CORE_PP0 = 0x00000004, /**< Mali 200 pixel processor 0 */
- MALI_PMM_CORE_PP1 = 0x00000008, /**< Mali 200 pixel processor 1 */
- MALI_PMM_CORE_PP2 = 0x00000010, /**< Mali 200 pixel processor 2 */
- MALI_PMM_CORE_PP3 = 0x00000020, /**< Mali 200 pixel processor 3 */
- MALI_PMM_CORE_PP_ALL = 0x0000003C /**< Mali 200 pixel processors 0-3 */
-} mali_pmm_core_id;
-
-
-/* @brief PMM bitmask of mali_pmm_core_ids
- */
-typedef u32 mali_pmm_core_mask;
-
-/* @brief PMM event timestamp type
- */
-typedef u32 mali_pmm_timestamp;
-
-/** @brief power management event message struct
- */
-typedef struct _mali_pmm_message
-{
- mali_pmm_event_id id; /**< event id */
- mali_pmm_message_data data; /**< specific data associated with the event */
- mali_pmm_timestamp ts; /**< timestamp the event was placed in the event queue */
-} mali_pmm_message_t;
-
-
-
-/** @brief the state of the power management module.
- */
-/* These must match up with the pmm_trace_state array */
-typedef enum mali_pmm_state_tag
-{
- MALI_PMM_STATE_UNAVAILABLE = 0, /**< PMM is not available */
- MALI_PMM_STATE_SYSTEM_ON = 1, /**< All of the Mali hardware is on */
- MALI_PMM_STATE_SYSTEM_OFF = 2, /**< All of the Mali hardware is off */
- MALI_PMM_STATE_SYSTEM_TRANSITION = 3 /**< System is changing state */
-} mali_pmm_state;
-
-
-/** @brief a power management policy.
- */
-/* These must match up with the pmm_trace_policy array */
-typedef enum mali_pmm_policy_tag
-{
- MALI_PMM_POLICY_NONE = 0, /**< No policy */
- MALI_PMM_POLICY_ALWAYS_ON = 1, /**< Always on policy */
- MALI_PMM_POLICY_JOB_CONTROL = 2, /**< Job control policy */
- MALI_PMM_POLICY_RUNTIME_JOB_CONTROL = 3 /**< Run time power management control policy */
-} mali_pmm_policy;
-
-/** @brief Function to power up MALI
- *
- * @param cores core mask to power up the cores
- *
- * @return error code if MALI fails to power up
- */
-_mali_osk_errcode_t malipmm_powerup( u32 cores );
-
-/** @brief Function to power down MALI
- *
- * @param cores core mask to power down the cores
- * @param The power mode to which MALI transitions
- *
- * @return error code if MALI fails to power down
- */
-_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode );
-
-/** @brief Function to report to the OS when the power down has finished
- *
- * @param data The event message data that initiated the power down
- */
-void _mali_osk_pmm_power_down_done(mali_pmm_message_data data);
-
-/** @brief Function to report to the OS when the power up has finished
- *
- * @param data The event message data that initiated the power up
- */
-void _mali_osk_pmm_power_up_done(mali_pmm_message_data data);
-
-/** @brief Function to report that DVFS operation done
- *
- * @param data The event message data
- */
-void _mali_osk_pmm_dvfs_operation_done(mali_pmm_message_data data);
-
-#if MALI_POWER_MGMT_TEST_SUITE
-/** @brief Function to notify power management events
- *
- * @param data The event message data
- */
-void _mali_osk_pmm_policy_events_notifications(mali_pmm_event_id event_id);
-
-#endif
-
-/** @brief Function to power up MALI
- *
- * @note powers up the MALI during MALI device driver is unloaded
- */
-void malipmm_force_powerup( void );
-
-/** @brief Function to report the OS that device is idle
- *
- * @note inform the OS that device is idle
- */
-_mali_osk_errcode_t _mali_osk_pmm_dev_idle( void );
-
-/** @brief Function to report the OS to activate device
- *
- * @note inform the os that device needs to be activated
- */
-int _mali_osk_pmm_dev_activate( void );
-
-/** @brief Function to report OS PMM for cleanup
- *
- * @note Function to report OS PMM for cleanup
- */
-void _mali_osk_pmm_ospmm_cleanup( void );
-
-/** @brief Queries the current state of the PMM software
- *
- * @note the state of the PMM can change after this call has returned
- *
- * @return the current PMM state value
- */
-mali_pmm_state _mali_pmm_state( void );
-
-/** @brief List of cores that are registered with the PMM
- *
- * This will return the cores that have been currently registered with the PMM,
- * which is a bitwise OR of the mali_pmm_core_id_tags. A value of 0x0 means that
- * there are no cores registered.
- *
- * @note the list of cores can change after this call has returned
- *
- * @return a bit mask representing all the cores that have been registered with the PMM
- */
-mali_pmm_core_mask _mali_pmm_cores_list( void );
-
-/** @brief List of cores that are powered up in the PMM
- *
- * This will return the subset of the cores that can be listed using mali_pmm_cores_
- * list, that have power. It is a bitwise OR of the mali_pmm_core_id_tags. A value of
- * 0x0 means that none of the cores registered are powered.
- *
- * @note the list of cores can change after this call has returned
- *
- * @return a bit mask representing all the cores that are powered up
- */
-mali_pmm_core_mask _mali_pmm_cores_powered( void );
-
-
-/** @brief List of power management policies that are supported by the PMM
- *
- * Given an empty array of policies - policy_list - which contains the number
- * of entries as specified by - policy_list_size, this function will populate
- * the list with the available policies. If the policy_list is too small for
- * all the policies then only policy_list_size entries will be returned. If the
- * policy_list is bigger than the number of available policies then, the extra
- * entries will be set to MALI_PMM_POLICY_NONE.
- * The function will also update available_policies with the number of policies
- * that are available, even if it exceeds the policy_list_size.
- * The function will succeed if all policies could be returned, else it will
- * fail if none or only a subset of policies could be returned.
- * The function will also fail if no policy_list is supplied, though
- * available_policies is optional.
- *
- * @note this is a STUB function and is not yet implemented
- *
- * @param policy_list_size is the number of policies that can be returned in
- * the policy_list argument
- * @param policy_list is an array of policies that should be populated with
- * the list of policies that are supported by the PMM
- * @param policies_available optional argument, if non-NULL will be set to the
- * number of policies available
- * @return _MALI_OSK_ERR_OK if the policies could be listed, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t _mali_pmm_list_policies(
- u32 policy_list_size,
- mali_pmm_policy *policy_list,
- u32 *policies_available );
-
-/** @brief Set the power management policy in the PMM
- *
- * Given a valid supported policy, this function will change the PMM to use
- * this new policy
- * The function will fail if the policy given is invalid or unsupported.
- *
- * @note this is a STUB function and is not yet implemented
- *
- * @param policy the new policy to be set
- * @return _MALI_OSK_ERR_OK if the policy could be set, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t _mali_pmm_set_policy( mali_pmm_policy policy );
-
-/** @brief Get the current power management policy in the PMM
- *
- * Given a pointer to a policy data type, this function will return the current
- * policy that is in effect for the PMM. This maybe out of date if there is a
- * pending set policy call that has not been serviced.
- * The function will fail if the policy given is NULL.
- *
- * @note the policy of the PMM can change after this call has returned
- *
- * @param policy a pointer to a policy that can be updated to the current
- * policy
- * @return _MALI_OSK_ERR_OK if the policy could be returned, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t _mali_pmm_get_policy( mali_pmm_policy *policy );
-
-#if MALI_PMM_TRACE
-
-/** @brief Indicates when a hardware state change occurs in the PMM
- *
- * @param old a mask of the cores indicating the previous state of the cores
- * @param newstate a mask of the cores indicating the new current state of the cores
- */
-void _mali_pmm_trace_hardware_change( mali_pmm_core_mask old, mali_pmm_core_mask newstate );
-
-/** @brief Indicates when a state change occurs in the PMM
- *
- * @param old the previous state for the PMM
- * @param newstate the new current state of the PMM
- */
-void _mali_pmm_trace_state_change( mali_pmm_state old, mali_pmm_state newstate );
-
-/** @brief Indicates when a policy change occurs in the PMM
- *
- * @param old the previous policy for the PMM
- * @param newpolicy the new current policy of the PMM
- */
-void _mali_pmm_trace_policy_change( mali_pmm_policy old, mali_pmm_policy newpolicy );
-
-/** @brief Records when an event message is read by the event system
- *
- * @param event the message details
- * @param received MALI_TRUE when the message is received by the PMM, else it is being sent
- */
-void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool received );
-
-#endif /* MALI_PMM_TRACE */
-
-/** @brief Dumps the current state of OS PMM thread
- */
-#if MALI_STATE_TRACKING
-u32 mali_pmm_dump_os_thread_state( char *buf, u32 size );
-#endif /* MALI_STATE_TRACKING */
-
-/** @} */ /* end group pmmapi */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_PMM_H__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c
deleted file mode 100644
index a8160ac..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c
+++ /dev/null
@@ -1,350 +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.
- */
-
-/**
- * @file mali_pmm_pmu.c
- * Mali driver functions for Mali 400 PMU hardware
- */
-#include "mali_kernel_common.h"
-#include "mali_osk.h"
-#include "mali_platform.h"
-
-#if USING_MALI_PMU
-#if USING_MALI_PMM
-
-#include "mali_pmm.h"
-
-/* Internal test on/off */
-#define PMU_TEST 0
-
-#if MALI_POWER_MGMT_TEST_SUITE
-#include "mali_platform_pmu_internal_testing.h"
-#endif /* MALI_POWER_MGMT_TEST_SUITE */
-
-/** @brief PMU hardware info
- */
-typedef struct platform_pmu
-{
- u32 reg_base_addr; /**< PMU registers base address */
- u32 reg_size; /**< PMU registers size */
- const char *name; /**< PMU name */
- u32 irq_num; /**< PMU irq number */
-
- mali_io_address reg_mapped; /**< IO-mapped pointer to registers */
-} platform_pmu_t;
-
-static platform_pmu_t *pmu_info = 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_STAT = 0x14, /*< Interrupt status register */
- PMU_REG_ADDR_MGMT_INT_CLEAR = 0x18, /*< Interrupt clear register */
- PMU_REG_ADDR_MGMT_SW_DELAY = 0x1C, /*< Software delay register */
- PMU_REG_ADDR_MGMT_MASTER_PWR_UP = 0x24, /*< Master power up register */
- PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x28, /*< Size of register space */
-} pmu_reg_addr_mgmt_addr;
-
-/* Internal functions */
-static u32 pmu_reg_read(platform_pmu_t *pmu, u32 relative_address);
-static void pmu_reg_write(platform_pmu_t *pmu, u32 relative_address, u32 new_val);
-static mali_pmm_core_mask pmu_translate_cores_to_pmu(mali_pmm_core_mask cores);
-#if PMU_TEST
-static void pmm_pmu_dump_regs( platform_pmu_t *pmu );
-static pmm_pmu_test( platform_pmu_t *pmu, u32 cores );
-#endif
-
-_mali_osk_errcode_t mali_pmm_pmu_init(_mali_osk_resource_t *resource)
-{
-
- if( resource->type == PMU )
- {
- if( (resource->base == 0) ||
- (resource->description == NULL) )
- {
- /* NOTE: We currently don't care about any other resource settings */
- MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Missing PMU set up information\n"));
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
- pmu_info = (platform_pmu_t *)_mali_osk_malloc(sizeof(*pmu_info));
- MALI_CHECK_NON_NULL( pmu_info, _MALI_OSK_ERR_NOMEM );
-
- /* All values get 0 as default */
- _mali_osk_memset(pmu_info, 0, sizeof(*pmu_info));
-
- pmu_info->reg_base_addr = resource->base;
- pmu_info->reg_size = (u32)PMU_REGISTER_ADDRESS_SPACE_SIZE;
- pmu_info->name = resource->description;
- pmu_info->irq_num = resource->irq;
-
- if( _MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name) )
- {
- MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not request register region (0x%08X - 0x%08X) for %s\n",
- pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name));
- goto cleanup;
- }
- else
- {
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: request_mem_region: (0x%08X - 0x%08X) for %s\n",
- pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name));
- }
-
- pmu_info->reg_mapped = _mali_osk_mem_mapioregion( pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name );
-
- if( 0 == pmu_info->reg_mapped )
- {
- MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not ioremap registers for %s .\n", pmu_info->name));
- _mali_osk_mem_unreqregion( pmu_info->reg_base_addr, pmu_info->reg_size );
- goto cleanup;
- }
- else
- {
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: ioremap_nocache: Internal ptr: (0x%08X - 0x%08X) for %s\n",
- (u32) pmu_info->reg_mapped,
- ((u32)pmu_info->reg_mapped)+ pmu_info->reg_size - 1,
- pmu_info->name));
- }
-
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: Mapping registers to %s\n", pmu_info->name));
-
-#if PMU_TEST
- pmu_test(pmu_info, (MALI_PMM_CORE_GP));
- pmu_test(pmu_info, (MALI_PMM_CORE_GP|MALI_PMM_CORE_L2|MALI_PMM_CORE_PP0));
-#endif
-
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Initialized - %s\n", pmu_info->name) );
- }
- else
- {
- /* Didn't expect a different resource */
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- MALI_SUCCESS;
-
-cleanup:
- _mali_osk_free(pmu_info);
- pmu_info = NULL;
- MALI_ERROR(_MALI_OSK_ERR_NOMEM);
-}
-
-_mali_osk_errcode_t mali_pmm_pmu_deinit(_mali_osk_resource_type_t *type)
-{
- if (*type == PMU)
- {
- if( pmu_info )
- {
- _mali_osk_mem_unmapioregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->reg_mapped);
- _mali_osk_mem_unreqregion(pmu_info->reg_base_addr, pmu_info->reg_size);
- _mali_osk_free(pmu_info);
- pmu_info = NULL;
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Terminated PMU\n") );
- }
- }
- else
- {
- /* Didn't expect a different resource */
- MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
- }
-
- MALI_SUCCESS;
-
-}
-
-_mali_osk_errcode_t mali_pmm_pmu_powerdown(u32 cores)
-{
- u32 stat;
- u32 timeout;
- u32 cores_pmu;
-
- MALI_DEBUG_ASSERT_POINTER(pmu_info);
- MALI_DEBUG_ASSERT( cores != 0 ); /* Shouldn't receive zero from PMM */
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: power down (0x%x)\n", cores) );
-
- cores_pmu = pmu_translate_cores_to_pmu(cores);
- pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_POWER_DOWN, cores_pmu );
-
- /* Wait for cores to be powered down */
- timeout = 10; /* 10ms */
- do
- {
- /* Get status of sleeping cores */
- stat = pmu_reg_read( pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS );
- stat &= cores_pmu;
- if( stat == cores_pmu ) break; /* All cores we wanted are now asleep */
- _mali_osk_time_ubusydelay(1000); /* 1ms */
- timeout--;
- } while( timeout > 0 );
-
- if( timeout == 0 ) MALI_ERROR(_MALI_OSK_ERR_TIMEOUT);
-
- MALI_SUCCESS;
-}
-
-_mali_osk_errcode_t mali_pmm_pmu_powerup(u32 cores)
-{
- u32 cores_pmu;
- u32 stat;
- u32 timeout;
-
- MALI_DEBUG_ASSERT_POINTER(pmu_info);
- MALI_DEBUG_ASSERT( cores != 0 ); /* Shouldn't receive zero from PMM */
- MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: power up (0x%x)\n", cores) );
-
- /* Don't use interrupts - just poll status */
- pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_INT_MASK, 0 );
- cores_pmu = pmu_translate_cores_to_pmu(cores);
- pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_POWER_UP, cores_pmu );
-
- timeout = 10; /* 10ms */
- do
- {
- /* Get status of sleeping cores */
- stat = pmu_reg_read( pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS );
- stat &= cores_pmu;
- if( stat == 0 ) break; /* All cores we wanted are now awake */
- _mali_osk_time_ubusydelay(1000); /* 1ms */
- timeout--;
- } while( timeout > 0 );
-
- if( timeout == 0 ) MALI_ERROR(_MALI_OSK_ERR_TIMEOUT);
-
- MALI_SUCCESS;
-}
-
-
-/***** INTERNAL *****/
-
-/** @brief Internal PMU function to translate the cores bit mask
- * into something the hardware PMU understands
- *
- * @param cores PMM cores bitmask
- * @return PMU hardware cores bitmask
- */
-static u32 pmu_translate_cores_to_pmu(mali_pmm_core_mask cores)
-{
- /* For Mali 400 PMU the cores mask is already the same as what
- * the hardware PMU expects.
- * For other hardware, some translation can be done here, by
- * translating the MALI_PMM_CORE_* bits into specific hardware
- * bits
- */
- return cores;
-}
-
-/** @brief Internal PMU function to read a PMU register
- *
- * @param pmu handle that identifies the PMU hardware
- * @param relative_address relative PMU hardware address to read from
- * @return 32-bit value that was read from the address
- */
-static u32 pmu_reg_read(platform_pmu_t *pmu, u32 relative_address)
-{
- u32 read_val;
-
- MALI_DEBUG_ASSERT_POINTER(pmu);
- MALI_DEBUG_ASSERT((relative_address & 0x03) == 0);
- MALI_DEBUG_ASSERT(relative_address < pmu->reg_size);
-
- read_val = _mali_osk_mem_ioread32(pmu->reg_mapped, relative_address);
-
- MALI_DEBUG_PRINT( 5, ("PMU: reg_read: %s Addr:0x%04X Val:0x%08x\n",
- pmu->name, relative_address, read_val));
-
- return read_val;
-}
-
-/** @brief Internal PMU function to write to a PMU register
- *
- * @param pmu handle that identifies the PMU hardware
- * @param relative_address relative PMU hardware address to write to
- * @param new_val new 32-bit value to write into the address
- */
-static void pmu_reg_write(platform_pmu_t *pmu, u32 relative_address, u32 new_val)
-{
- MALI_DEBUG_ASSERT_POINTER(pmu);
- MALI_DEBUG_ASSERT((relative_address & 0x03) == 0);
- MALI_DEBUG_ASSERT(relative_address < pmu->reg_size);
-
- MALI_DEBUG_PRINT( 5, ("PMU: reg_write: %s Addr:0x%04X Val:0x%08x\n",
- pmu->name, relative_address, new_val));
-
- _mali_osk_mem_iowrite32(pmu->reg_mapped, relative_address, new_val);
-}
-
-#if PMU_TEST
-
-/***** TEST *****/
-
-static void pmu_dump_regs( platform_pmu_t *pmu )
-{
- u32 addr;
- for( addr = 0x0; addr < PMU_REGISTER_ADDRESS_SPACE_SIZE; addr += 0x4 )
- {
- MALI_PRINT( ("PMU_REG: 0x%08x: 0x%04x\n", (addr + pmu->reg_base_addr), pmu_reg_read( pmu, addr ) ) );
- }
-}
-
-/* This function is an internal test for the PMU without any Mali h/w interaction */
-static void pmu_test( platform_pmu_t *pmu, u32 cores )
-{
- u32 stat;
- u32 timeout;
-
- MALI_PRINT( ("PMU_TEST: Start\n") );
-
- pmu_dump_regs( pmu );
-
- MALI_PRINT( ("PMU_TEST: Power down cores: 0x%x\n", cores) );
- _mali_pmm_pmu_power_down( pmu, cores, MALI_TRUE );
-
- stat = pmu_reg_read( pmu, (u32)PMU_REG_ADDR_MGMT_STATUS );
- MALI_PRINT( ("PMU_TEST: %s\n", (stat & cores) == cores ? "SUCCESS" : "FAIL" ) );
-
- pmu_dump_regs( pmu );
-
- MALI_PRINT( ("PMU_TEST: Power up cores: 0x%x\n", cores) );
- _mali_pmm_pmu_power_up( pmu, cores, MALI_FALSE );
-
- MALI_PRINT( ("PMU_TEST: Waiting for power up...\n") );
- timeout = 1000; /* 1 sec */
- while( !_mali_pmm_pmu_irq_power_up(pmu) && timeout > 0 )
- {
- _mali_osk_time_ubusydelay(1000); /* 1ms */
- timeout--;
- }
-
- MALI_PRINT( ("PMU_TEST: Waited %dms for interrupt\n", (1000-timeout)) );
- stat = pmu_reg_read( pmu, (u32)PMU_REG_ADDR_MGMT_STATUS );
- MALI_PRINT( ("PMU_TEST: %s\n", (stat & cores) == 0 ? "SUCCESS" : "FAIL" ) );
-
- _mali_pmm_pmu_irq_power_up_clear(pmu);
-
- pmu_dump_regs( pmu );
-
- MALI_PRINT( ("PMU_TEST: Finish\n") );
-}
-#endif /* PMU_TEST */
-
-#if MALI_POWER_MGMT_TEST_SUITE
-
-u32 pmu_get_power_up_down_info(void)
-{
- return pmu_reg_read(pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS);
-}
-
-#endif /* MALI_POWER_MGMT_TEST_SUITE */
-#endif /* USING_MALI_PMM */
-#endif /* USING_MALI_PMU */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h
deleted file mode 100644
index 7525cac..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h
+++ /dev/null
@@ -1,86 +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.
- */
-/**
- * @file mali_platform.h
- * Platform specific Mali driver functions
- */
-
-#include "mali_osk.h"
-
-#if !USING_MALI_PMM
-/* @brief System power up/down cores that can be passed into mali_platform_powerdown/up() */
-#define MALI_PLATFORM_SYSTEM 0
-#endif
-
-#if USING_MALI_PMM
-#if USING_MALI_PMU
-#include "mali_pmm.h"
-
-/** @brief Platform specific setup and initialisation of MALI
- *
- * This is called from the entrypoint of the driver to initialize the platform
- * When using PMM, it is also called from the PMM start up to initialise the
- * system PMU
- *
- * @param resource This is NULL when called on first driver start up, else it will
- * be a pointer to a PMU resource
- * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t mali_pmm_pmu_init(_mali_osk_resource_t *resource);
-
-/** @brief Platform specific deinitialisation of MALI
- *
- * This is called on the exit of the driver to terminate the platform
- * When using PMM, it is also called from the PMM termination code to clean up the
- * system PMU
- *
- * @param type This is NULL when called on driver exit, else it will
- * be a pointer to a PMU resource type (not the full resource)
- * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t mali_pmm_pmu_deinit(_mali_osk_resource_type_t *type);
-
-/** @brief Platform specific powerdown sequence of MALI
- *
- * Called as part of platform init if there is no PMM support, else the
- * PMM will call it.
- *
- * @param cores This is MALI_PLATFORM_SYSTEM when called without PMM, else it will
- * be a mask of cores to power down based on the mali_pmm_core_id enum
- * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t mali_pmm_pmu_powerdown(u32 cores);
-
-/** @brief Platform specific powerup sequence of MALI
- *
- * Called as part of platform deinit if there is no PMM support, else the
- * PMM will call it.
- *
- * @param cores This is MALI_PLATFORM_SYSTEM when called without PMM, else it will
- * be a mask of cores to power down based on the mali_pmm_core_id enum
- * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
- */
-_mali_osk_errcode_t mali_pmm_pmu_powerup(u32 cores);
-
-#if MALI_POWER_MGMT_TEST_SUITE
-#if USING_MALI_PMM
-#if USING_MALI_PMU
-/** @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
-#endif
-#endif
-#endif
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c
deleted file mode 100644
index 87b6ec2..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c
+++ /dev/null
@@ -1,243 +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.
- */
-
-/**
- * @file mali_pmm_policy.c
- * Implementation of the common routines for power management module
- * policies
- */
-
-#if USING_MALI_PMM
-
-#include "mali_ukk.h"
-#include "mali_kernel_common.h"
-
-#include "mali_pmm.h"
-#include "mali_pmm_system.h"
-#include "mali_pmm_state.h"
-#include "mali_pmm_policy.h"
-
-#include "mali_pmm_policy_alwayson.h"
-#include "mali_pmm_policy_jobcontrol.h"
-
-/* Call back function for timer expiration */
-static void pmm_policy_timer_callback( void *arg );
-
-_mali_osk_errcode_t pmm_policy_timer_init( _pmm_policy_timer_t *pptimer, u32 timeout, mali_pmm_event_id id )
-{
- MALI_DEBUG_ASSERT_POINTER(pptimer);
-
- /* All values get 0 as default */
- _mali_osk_memset(pptimer, 0, sizeof(*pptimer));
-
- pptimer->timer = _mali_osk_timer_init();
- if( pptimer->timer )
- {
- _mali_osk_timer_setcallback( pptimer->timer, pmm_policy_timer_callback, (void *)pptimer );
- pptimer->timeout = timeout;
- pptimer->event_id = id;
- MALI_SUCCESS;
- }
-
- return _MALI_OSK_ERR_FAULT;
-}
-
-static void pmm_policy_timer_callback( void *arg )
-{
- _pmm_policy_timer_t *pptimer = (_pmm_policy_timer_t *)arg;
-
- MALI_DEBUG_ASSERT_POINTER(pptimer);
- MALI_DEBUG_ASSERT( pptimer->set );
-
- /* Set timer expired and flag there is a policy to check */
- pptimer->expired = MALI_TRUE;
- malipmm_set_policy_check();
-}
-
-
-void pmm_policy_timer_term( _pmm_policy_timer_t *pptimer )
-{
- MALI_DEBUG_ASSERT_POINTER(pptimer);
-
- _mali_osk_timer_del( pptimer->timer );
- _mali_osk_timer_term( pptimer->timer );
- pptimer->timer = NULL;
-}
-
-mali_bool pmm_policy_timer_start( _pmm_policy_timer_t *pptimer )
-{
- MALI_DEBUG_ASSERT_POINTER(pptimer);
- MALI_DEBUG_ASSERT_POINTER(pptimer->timer);
-
- if( !(pptimer->set) )
- {
- pptimer->set = MALI_TRUE;
- pptimer->expired = MALI_FALSE;
- pptimer->start = _mali_osk_time_tickcount();
- _mali_osk_timer_add( pptimer->timer, pptimer->timeout );
- return MALI_TRUE;
- }
-
- return MALI_FALSE;
-}
-
-mali_bool pmm_policy_timer_stop( _pmm_policy_timer_t *pptimer )
-{
- MALI_DEBUG_ASSERT_POINTER(pptimer);
- MALI_DEBUG_ASSERT_POINTER(pptimer->timer);
-
- if( pptimer->set )
- {
- _mali_osk_timer_del( pptimer->timer );
- pptimer->set = MALI_FALSE;
- pptimer->expired = MALI_FALSE;
- return MALI_TRUE;
- }
-
- return MALI_FALSE;
-}
-
-mali_bool pmm_policy_timer_raise_event( _pmm_policy_timer_t *pptimer )
-{
- MALI_DEBUG_ASSERT_POINTER(pptimer);
-
- if( pptimer->expired )
- {
- _mali_uk_pmm_message_s event = {
- NULL,
- MALI_PMM_EVENT_TIMEOUT, /* Assume timeout id, but set it below */
- 0 };
-
- event.id = pptimer->event_id;
- event.data = (mali_pmm_message_data)pptimer->start;
-
- /* Don't need to do any other notification with this timer */
- pptimer->expired = MALI_FALSE;
- /* Unset timer so it is free to be set again */
- pptimer->set = MALI_FALSE;
-
- _mali_ukk_pmm_event_message( &event );
-
- return MALI_TRUE;
- }
-
- return MALI_FALSE;
-}
-
-mali_bool pmm_policy_timer_valid( u32 timer_start, u32 other_start )
-{
- return (_mali_osk_time_after( other_start, timer_start ) == 0);
-}
-
-
-_mali_osk_errcode_t pmm_policy_init(_mali_pmm_internal_state_t *pmm)
-{
- _mali_osk_errcode_t err;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- switch( pmm->policy )
- {
- case MALI_PMM_POLICY_ALWAYS_ON:
- {
- err = pmm_policy_init_always_on();
- }
- break;
-
- case MALI_PMM_POLICY_JOB_CONTROL:
- {
- err = pmm_policy_init_job_control(pmm);
- }
- break;
-
- case MALI_PMM_POLICY_NONE:
- default:
- err = _MALI_OSK_ERR_FAULT;
- }
-
- return err;
-}
-
-void pmm_policy_term(_mali_pmm_internal_state_t *pmm)
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- switch( pmm->policy )
- {
- case MALI_PMM_POLICY_ALWAYS_ON:
- {
- pmm_policy_term_always_on();
- }
- break;
-
- case MALI_PMM_POLICY_JOB_CONTROL:
- {
- pmm_policy_term_job_control();
- }
- break;
-
- case MALI_PMM_POLICY_NONE:
- default:
- MALI_PRINT_ERROR( ("PMM: Invalid policy terminated %d\n", pmm->policy) );
- }
-}
-
-
-_mali_osk_errcode_t pmm_policy_process(_mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event)
-{
- _mali_osk_errcode_t err;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(event);
-
- switch( pmm->policy )
- {
- case MALI_PMM_POLICY_ALWAYS_ON:
- {
- err = pmm_policy_process_always_on( pmm, event );
- }
- break;
-
- case MALI_PMM_POLICY_JOB_CONTROL:
- {
- err = pmm_policy_process_job_control( pmm, event );
- }
- break;
-
- case MALI_PMM_POLICY_NONE:
- default:
- err = _MALI_OSK_ERR_FAULT;
- }
-
- return err;
-}
-
-
-void pmm_policy_check_policy( _mali_pmm_internal_state_t *pmm )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- switch( pmm->policy )
- {
- case MALI_PMM_POLICY_JOB_CONTROL:
- {
- pmm_policy_check_job_control();
- }
- break;
-
- default:
- /* Nothing needs to be done */
- break;
- }
-}
-
-
-#endif /* USING_MALI_PMM */
-
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h
deleted file mode 100644
index 75ac8c8..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h
+++ /dev/null
@@ -1,155 +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.
- */
-
-/**
- * @file mali_pmm_policy.h
- * Defines the power management module policies
- */
-
-#ifndef __MALI_PMM_POLICY_H__
-#define __MALI_PMM_POLICY_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @addtogroup pmmapi Power Management Module APIs
- *
- * @{
- *
- * @defgroup pmmapi_policy Power Management Module Policies
- *
- * @{
- */
-
-/** @brief Generic timer for use with policies
- */
-typedef struct _pmm_policy_timer
-{
- u32 timeout; /**< Timeout for this timer in ticks */
- mali_pmm_event_id event_id; /**< Event id that will be raised when timer expires */
- _mali_osk_timer_t *timer; /**< Timer */
- mali_bool set; /**< Timer set */
- mali_bool expired; /**< Timer expired - event needs to be raised */
- u32 start; /**< Timer start ticks */
-} _pmm_policy_timer_t;
-
-/** @brief Policy timer initialization
- *
- * This will create a timer for use in policies, but won't start it
- *
- * @param pptimer An empty timer structure to be initialized
- * @param timeout Timeout in ticks for the timer
- * @param id Event id that will be raised on timeout
- * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_timer_init( _pmm_policy_timer_t *pptimer, u32 timeout, mali_pmm_event_id id );
-
-/** @brief Policy timer termination
- *
- * This will clean up a timer that was previously used in policies, it
- * will also stop it if started
- *
- * @param pptimer An initialized timer structure to be terminated
- */
-void pmm_policy_timer_term( _pmm_policy_timer_t *pptimer );
-
-/** @brief Policy timer start
- *
- * This will start a previously created timer for use in policies
- * When the timer expires after the initialized timeout it will raise
- * a PMM event of the event id given on initialization
- * As data for the event it will pass the start time of the timer
- *
- * @param pptimer A previously initialized policy timer
- * @return MALI_TRUE if the timer was started, MALI_FALSE if it is already started
- */
-mali_bool pmm_policy_timer_start( _pmm_policy_timer_t *pptimer );
-
-/** @brief Policy timer stop
- *
- * This will stop a previously created timer for use in policies
- *
- * @param pptimer A previously started policy timer
- * @return MALI_TRUE if the timer was stopped, MALI_FALSE if it is already stopped
- */
-mali_bool pmm_policy_timer_stop( _pmm_policy_timer_t *pptimer );
-
-/** @brief Policy timer stop
- *
- * This raise an event for an expired timer
- *
- * @param pptimer An expired policy timer
- * @return MALI_TRUE if an event was raised, else MALI_FALSE
- */
-mali_bool pmm_policy_timer_raise_event( _pmm_policy_timer_t *pptimer );
-
-/** @brief Policy timer valid checker
- *
- * This will check that a timer was started after a given time
- *
- * @param timer_start Time the timer was started
- * @param other_start Time when another event or action occurred
- * @return MALI_TRUE if the timer was started after the other time, else MALI_FALSE
- */
-mali_bool pmm_policy_timer_valid( u32 timer_start, u32 other_start );
-
-
-/** @brief Common policy initialization
- *
- * This will initialize the current policy
- *
- * @note Any previously initialized policy should be terminated first
- *
- * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_init( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Common policy termination
- *
- * This will terminate the current policy.
- * @note This can be called when a policy has not been initialized
- */
-void pmm_policy_term( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Common policy state changer
- *
- * Given the next available event message, this routine passes it to
- * the current policy for processing
- *
- * @param pmm internal PMM state
- * @param event PMM event to process
- * @return _MALI_OSK_ERR_OK if the policy state completed okay, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_process( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
-
-
-/** @brief Common policy checker
- *
- * If a policy timer fires then this function will be called to
- * allow the policy to take the correct action
- *
- * @param pmm internal PMM state
- */
-void pmm_policy_check_policy( _mali_pmm_internal_state_t *pmm );
-
-/** @} */ /* End group pmmapi_policy */
-/** @} */ /* End group pmmapi */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_PMM_POLICY_H__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c
deleted file mode 100644
index 0a6b471..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c
+++ /dev/null
@@ -1,80 +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.
- */
-
-/**
- * @file mali_pmm_policy_alwayson.c
- * Implementation of the power management module policy - always on
- */
-
-#if USING_MALI_PMM
-
-#include "mali_ukk.h"
-#include "mali_kernel_common.h"
-
-#include "mali_pmm.h"
-#include "mali_pmm_system.h"
-#include "mali_pmm_state.h"
-#include "mali_pmm_policy_alwayson.h"
-
-_mali_osk_errcode_t pmm_policy_init_always_on(void)
-{
- /* Nothing to set up */
- MALI_SUCCESS;
-}
-
-void pmm_policy_term_always_on(void)
-{
- /* Nothing to tear down */
-}
-
-_mali_osk_errcode_t pmm_policy_process_always_on( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(event);
-
- switch( event->id )
- {
- case MALI_PMM_EVENT_OS_POWER_DOWN:
- /* We aren't going to do anything, but signal so we don't block the OS
- * NOTE: This may adversely affect any jobs Mali is currently running
- */
- _mali_osk_pmm_power_down_done( event->data );
- break;
-
- case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
- case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
- /* Not expected in this policy */
- MALI_DEBUG_ASSERT( MALI_FALSE );
- break;
-
- case MALI_PMM_EVENT_OS_POWER_UP:
- /* Nothing to do */
- _mali_osk_pmm_power_up_done( event->data );
- break;
-
- case MALI_PMM_EVENT_JOB_SCHEDULED:
- case MALI_PMM_EVENT_JOB_QUEUED:
- case MALI_PMM_EVENT_JOB_FINISHED:
- /* Nothing to do - we are always on */
- break;
-
- case MALI_PMM_EVENT_TIMEOUT:
- /* Not expected in this policy */
- MALI_DEBUG_ASSERT( MALI_FALSE );
- break;
-
- default:
- MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
- }
-
- MALI_SUCCESS;
-}
-
-#endif
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h
deleted file mode 100644
index da13224..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h
+++ /dev/null
@@ -1,62 +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.
- */
-
-/**
- * @file mali_pmm_policy_alwayson.h
- * Defines the power management module policy for always on
- */
-
-#ifndef __MALI_PMM_POLICY_ALWAYSON_H__
-#define __MALI_PMM_POLICY_ALWAYSON_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @addtogroup pmmapi_policy Power Management Module Policies
- *
- * @{
- */
-
-/** @brief Always on policy initialization
- *
- * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_init_always_on(void);
-
-/** @brief Always on policy termination
- */
-void pmm_policy_term_always_on(void);
-
-/** @brief Always on policy state changer
- *
- * Given the next available event message, this routine processes it
- * for the policy and changes state as needed.
- *
- * Always on policy will ignore all events and keep the Mali cores on
- * all the time
- *
- * @param pmm internal PMM state
- * @param event PMM event to process
- * @return _MALI_OSK_ERR_OK if the policy state completed okay, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_process_always_on( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
-
-/** @} */ /* End group pmmapi_policies */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_PMM_POLICY_ALWAYSON_H__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c
deleted file mode 100644
index 237d702..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c
+++ /dev/null
@@ -1,470 +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.
- */
-
-/**
- * @file mali_pmm_policy_jobcontrol.c
- * Implementation of the power management module policy - job control
- */
-
-#if USING_MALI_PMM
-
-#include "mali_ukk.h"
-#include "mali_kernel_common.h"
-#include "mali_platform.h"
-
-#include "mali_pmm.h"
-#include "mali_pmm_system.h"
-#include "mali_pmm_state.h"
-#include "mali_pmm_policy.h"
-#include "mali_pmm_policy_jobcontrol.h"
-
-typedef struct _pmm_policy_data_job_control
-{
- _pmm_policy_timer_t latency; /**< Latency timeout timer for all cores */
- u32 core_active_start; /**< Last time a core was set to active */
- u32 timeout; /**< Timeout in ticks for latency timer */
-} _pmm_policy_data_job_control_t;
-
-
-/* @ brief Local data for this policy
- */
-static _pmm_policy_data_job_control_t *data_job_control = NULL;
-
-/* @brief Set up the timeout if it hasn't already been set and if there are active cores */
-static void job_control_timeout_setup( _mali_pmm_internal_state_t *pmm, _pmm_policy_timer_t *pptimer )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(pptimer);
-
- /* Do we have an inactivity time out and some powered cores? */
- if( pptimer->timeout > 0 && pmm->cores_powered != 0 )
- {
- /* Is the system idle and all the powered cores are idle? */
- if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->cores_idle == pmm->cores_powered )
- {
- if( pmm_policy_timer_start(pptimer) )
- {
- MALIPMM_DEBUG_PRINT( ("PMM policy - Job control: Setting in-activity latency timer\n") );
- }
- }
- else
- {
- /* We are not idle so there is no need for an inactivity timer
- */
- if( pmm_policy_timer_stop(pptimer) )
- {
- MALIPMM_DEBUG_PRINT( ("PMM policy - Job control: Removing in-activity latency timer\n") );
- }
- }
- }
-}
-
-/* @brief Check the validity of the timeout - and if there is one set */
-static mali_bool job_control_timeout_valid( _mali_pmm_internal_state_t *pmm, _pmm_policy_timer_t *pptimer, u32 timer_start )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(pptimer);
-
- /* Not a valid timer! */
- if( pptimer->timeout == 0 ) return MALI_FALSE;
-
- /* Are some cores powered and are they all idle? */
- if( (pmm->cores_powered != 0) && (pmm->cores_idle == pmm->cores_powered) )
- {
- /* Has latency timeout started after the last core was active? */
- if( pmm_policy_timer_valid( timer_start, data_job_control->core_active_start ) )
- {
- return MALI_TRUE;
- }
- else
- {
- MALIPMM_DEBUG_PRINT( ("PMM: In-activity latency time out ignored - out of date\n") );
- }
- }
- else
- {
- if( pmm->cores_powered == 0 )
- {
- MALIPMM_DEBUG_PRINT( ("PMM: In-activity latency time out ignored - cores already off\n") );
- }
- else
- {
- MALIPMM_DEBUG_PRINT( ("PMM: In-activity latency time out ignored - cores active\n") );
- }
- }
-
- return MALI_FALSE;
-}
-
-_mali_osk_errcode_t pmm_policy_init_job_control( _mali_pmm_internal_state_t *pmm )
-{
- _mali_osk_errcode_t err;
- MALI_DEBUG_ASSERT_POINTER( pmm );
- MALI_DEBUG_ASSERT( data_job_control == NULL );
-
- data_job_control = (_pmm_policy_data_job_control_t *) _mali_osk_malloc(sizeof(*data_job_control));
- MALI_CHECK_NON_NULL( data_job_control, _MALI_OSK_ERR_NOMEM );
-
- data_job_control->core_active_start = _mali_osk_time_tickcount();
- data_job_control->timeout = MALI_PMM_POLICY_JOBCONTROL_INACTIVITY_TIMEOUT;
-
- err = pmm_policy_timer_init( &data_job_control->latency, data_job_control->timeout, MALI_PMM_EVENT_TIMEOUT );
- if( err != _MALI_OSK_ERR_OK )
- {
- _mali_osk_free( data_job_control );
- data_job_control = NULL;
- return err;
- }
-
- /* Start the latency timeout */
- job_control_timeout_setup( pmm, &data_job_control->latency );
-
- MALI_SUCCESS;
-}
-
-void pmm_policy_term_job_control(void)
-{
- if( data_job_control != NULL )
- {
- pmm_policy_timer_term( &data_job_control->latency );
- _mali_osk_free( data_job_control );
- data_job_control = NULL;
- }
-}
-
-static void pmm_policy_job_control_job_queued( _mali_pmm_internal_state_t *pmm )
-{
- mali_pmm_core_mask cores;
- mali_pmm_core_mask cores_subset;
-
- /* Make sure that all cores are powered in this
- * simple policy
- */
- cores = pmm->cores_registered;
- cores_subset = pmm_cores_to_power_up( pmm, cores );
- if( cores_subset != 0 )
- {
- /* There are some cores that need powering up */
- if( !pmm_invoke_power_up( pmm ) )
- {
- /* Need to wait until finished */
- pmm->status = MALI_PMM_STATUS_POLICY_POWER_UP;
- }
- }
-}
-
-_mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
-{
- mali_pmm_core_mask cores;
- mali_pmm_core_mask cores_subset;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(event);
- MALI_DEBUG_ASSERT_POINTER(data_job_control);
-
- MALIPMM_DEBUG_PRINT( ("PMM: Job control policy process start - status=%d\n", pmm->status) );
-
- /* Mainly the data is the cores */
- cores = pmm_cores_from_event_data( pmm, event );
-
-#if MALI_STATE_TRACKING
- pmm->mali_last_pmm_status = pmm->status;
-#endif /* MALI_STATE_TRACKING */
-
- switch( pmm->status )
- {
- /**************** IDLE ****************/
- case MALI_PMM_STATUS_IDLE:
- switch( event->id )
- {
- case MALI_PMM_EVENT_OS_POWER_UP:
- /* Not expected in this state */
- break;
-
- case MALI_PMM_EVENT_JOB_SCHEDULED:
-
- /* Update idle cores to indicate active - remove these! */
- pmm_cores_set_active( pmm, cores );
- /* Remember when this happened */
- data_job_control->core_active_start = event->ts;
-#if MALI_POWER_MGMT_TEST_SUITE
- _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_JOB_SCHEDULED);
-#endif
-
- /*** FALL THROUGH to QUEUED to check POWER UP ***/
-
- case MALI_PMM_EVENT_JOB_QUEUED:
-
- pmm_policy_job_control_job_queued( pmm );
-#if MALI_POWER_MGMT_TEST_SUITE
- _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_JOB_QUEUED);
-#endif
- break;
-
- case MALI_PMM_EVENT_DVFS_PAUSE:
-
- cores_subset = pmm_cores_to_power_down( pmm, cores, MALI_FALSE );
- if ( cores_subset != 0 )
- {
- if ( !pmm_power_down_okay( pmm ) )
- {
- pmm->is_dvfs_active = 1;
- pmm->status = MALI_PMM_STATUS_OS_POWER_DOWN;
- pmm_save_os_event_data( pmm, event->data );
- break;
- }
- }
- pmm->status = MALI_PMM_STATUS_DVFS_PAUSE;
- _mali_osk_pmm_dvfs_operation_done(0);
- break;
-
- case MALI_PMM_EVENT_OS_POWER_DOWN:
-
- /* Need to power down all cores even if we need to wait for them */
- cores_subset = pmm_cores_to_power_down( pmm, cores, MALI_FALSE );
- if( cores_subset != 0 )
- {
- /* There are some cores that need powering down */
- if( !pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) )
- {
- /* We need to wait until they are idle */
-
- pmm->status = MALI_PMM_STATUS_OS_POWER_DOWN;
- /* Save the OS data to respond later */
- pmm_save_os_event_data( pmm, event->data );
- /* Exit this case - as we have to wait */
- break;
- }
- }
- else
- {
- mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
-
- }
- /* Set waiting status */
- pmm->status = MALI_PMM_STATUS_OS_WAITING;
- /* All cores now down - respond to OS power event */
- _mali_osk_pmm_power_down_done( event->data );
- break;
-
- case MALI_PMM_EVENT_JOB_FINISHED:
-
- /* Update idle cores - add these! */
- pmm_cores_set_idle( pmm, cores );
-#if MALI_POWER_MGMT_TEST_SUITE
- _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_JOB_FINISHED);
-#endif
- if( data_job_control->timeout > 0 )
- {
- /* Wait for time out to fire */
- break;
- }
- /* For job control policy - turn off all cores */
- cores = pmm->cores_powered;
-
- /*** FALL THROUGH to TIMEOUT TEST as NO TIMEOUT ***/
-
- case MALI_PMM_EVENT_TIMEOUT:
-
- /* Main job control policy - turn off cores after inactivity */
- if( job_control_timeout_valid( pmm, &data_job_control->latency, (u32)event->data ) )
- {
- /* Valid timeout of inactivity - so find out if we can power down
- * immedately - if we can't then this means the cores are still in fact
- * active
- */
- cores_subset = pmm_cores_to_power_down( pmm, cores, MALI_TRUE );
- if( cores_subset != 0 )
- {
- /* Check if we can really power down, if not then we are not
- * really in-active
- */
- if( !pmm_invoke_power_down( pmm, MALI_POWER_MODE_LIGHT_SLEEP ) )
- {
- pmm_power_down_cancel( pmm );
- }
- }
- /* else there are no cores powered up! */
- }
-#if MALI_POWER_MGMT_TEST_SUITE
- _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_TIMEOUT);
-#endif
- break;
-
- default:
- /* Unexpected event */
- MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
- }
- break;
-
- /******************DVFS PAUSE**************/
- case MALI_PMM_STATUS_DVFS_PAUSE:
- switch ( event->id )
- {
- case MALI_PMM_EVENT_DVFS_RESUME:
-
- if ( pmm->cores_powered != 0 )
- {
- pmm->cores_ack_down =0;
- pmm_power_down_cancel( pmm );
- pmm->status = MALI_PMM_STATUS_IDLE;
- }
- else
- {
- pmm_policy_job_control_job_queued( pmm );
- }
- _mali_osk_pmm_dvfs_operation_done( 0 );
- break;
-
- case MALI_PMM_EVENT_OS_POWER_DOWN:
- /* Set waiting status */
- pmm->status = MALI_PMM_STATUS_OS_WAITING;
- if ( pmm->cores_powered != 0 )
- {
- if ( pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) )
- {
- _mali_osk_pmm_power_down_done( 0 );
- break;
- }
- }
- else
- {
- mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
- }
- _mali_osk_pmm_power_down_done( 0 );
- break;
- default:
- break;
- }
- break;
-
- /**************** POWER UP ****************/
- case MALI_PMM_STATUS_OS_POWER_UP:
- case MALI_PMM_STATUS_POLICY_POWER_UP:
- switch( event->id )
- {
- case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
- /* Make sure cores powered off equal what we expect */
- MALI_DEBUG_ASSERT( cores == pmm->cores_pend_up );
- pmm_cores_set_up_ack( pmm, cores );
-
- if( pmm_invoke_power_up( pmm ) )
- {
- if( pmm->status == MALI_PMM_STATUS_OS_POWER_UP )
- {
- /* Get the OS data and respond to the power up */
- _mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) );
- }
- pmm->status = MALI_PMM_STATUS_IDLE;
- }
- break;
-
- default:
- /* Unexpected event */
- MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
- }
- break;
-
- /**************** POWER DOWN ****************/
- case MALI_PMM_STATUS_OS_POWER_DOWN:
- case MALI_PMM_STATUS_POLICY_POWER_DOWN:
- switch( event->id )
- {
-
- case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
-
- pmm_cores_set_down_ack( pmm, cores );
-
- if ( pmm->is_dvfs_active == 1 )
- {
- if( pmm_power_down_okay( pmm ) )
- {
- pmm->is_dvfs_active = 0;
- pmm->status = MALI_PMM_STATUS_DVFS_PAUSE;
- _mali_osk_pmm_dvfs_operation_done( pmm_retrieve_os_event_data( pmm ) );
- }
- break;
- }
-
- /* Now check if we can power down */
- if( pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) )
- {
- if( pmm->status == MALI_PMM_STATUS_OS_POWER_DOWN )
- {
- /* Get the OS data and respond to the power down */
- _mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) );
- }
- pmm->status = MALI_PMM_STATUS_OS_WAITING;
- }
- break;
-
- default:
- /* Unexpected event */
- MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
- }
- break;
-
- case MALI_PMM_STATUS_OS_WAITING:
- switch( event->id )
- {
- case MALI_PMM_EVENT_OS_POWER_UP:
- cores_subset = pmm_cores_to_power_up( pmm, cores );
- if( cores_subset != 0 )
- {
- /* There are some cores that need powering up */
- if( !pmm_invoke_power_up( pmm ) )
- {
- /* Need to wait until power up complete */
- pmm->status = MALI_PMM_STATUS_OS_POWER_UP;
- /* Save the OS data to respond later */
- pmm_save_os_event_data( pmm, event->data );
- /* Exit this case - as we have to wait */
- break;
- }
- }
- pmm->status = MALI_PMM_STATUS_IDLE;
- /* All cores now up - respond to OS power up event */
- _mali_osk_pmm_power_up_done( event->data );
- break;
-
- default:
- /* All other messages are ignored in this state */
- break;
- }
- break;
-
- default:
- /* Unexpected state */
- MALI_ERROR(_MALI_OSK_ERR_FAULT);
- }
-
- /* Set in-activity latency timer - if required */
- job_control_timeout_setup( pmm, &data_job_control->latency );
-
- /* Update the PMM state */
- pmm_update_system_state( pmm );
-#if MALI_STATE_TRACKING
- pmm->mali_new_event_status = event->id;
-#endif /* MALI_STATE_TRACKING */
-
- MALIPMM_DEBUG_PRINT( ("PMM: Job control policy process end - status=%d and event=%d\n", pmm->status,event->id) );
-
- MALI_SUCCESS;
-}
-
-void pmm_policy_check_job_control()
-{
- MALI_DEBUG_ASSERT_POINTER(data_job_control);
-
- /* Latency timer must have expired raise the event */
- pmm_policy_timer_raise_event(&data_job_control->latency);
-}
-
-
-#endif /* USING_MALI_PMM */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h
deleted file mode 100644
index dcfa438..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h
+++ /dev/null
@@ -1,80 +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.
- */
-
-/**
- * @file mali_pmm_policy.h
- * Defines the power management module policies
- */
-
-#ifndef __MALI_PMM_POLICY_JOBCONTROL_H__
-#define __MALI_PMM_POLICY_JOBCONTROL_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @addtogroup pmmapi_policy Power Management Module Policies
- *
- * @{
- */
-
-/** @brief The jobcontrol policy inactivity latency timeout (in ticks)
- * before the hardware is switched off
- *
- * @note Setting this low whilst tracing or producing debug output can
- * cause alot of timeouts to fire which can affect the PMM behaviour
- */
-#define MALI_PMM_POLICY_JOBCONTROL_INACTIVITY_TIMEOUT 50
-
-/** @brief Job control policy initialization
- *
- * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_init_job_control(_mali_pmm_internal_state_t *pmm);
-
-/** @brief Job control policy termination
- */
-void pmm_policy_term_job_control(void);
-
-/** @brief Job control policy state changer
- *
- * Given the next available event message, this routine processes it
- * for the policy and changes state as needed.
- *
- * Job control policy depends on events from the Mali cores, and will
- * power down all cores after an inactivity latency timeout. It will
- * power the cores back on again when a job is scheduled to run.
- *
- * @param pmm internal PMM state
- * @param event PMM event to process
- * @return _MALI_OSK_ERR_OK if the policy state completed okay, or a suitable
- * _mali_osk_errcode_t otherwise.
- */
-_mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
-
-/** @brief Job control policy checker
- *
- * The latency timer has fired and we need to raise the correct event to
- * handle it
- *
- * @param pmm internal PMM state
- */
-void pmm_policy_check_job_control(void);
-
-/** @} */ /* End group pmmapi_policy */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_PMM_POLICY_JOBCONTROL_H__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c
deleted file mode 100644
index d529b9a..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c
+++ /dev/null
@@ -1,716 +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.
- */
-
-#if USING_MALI_PMM
-
-#include "mali_ukk.h"
-#include "mali_kernel_common.h"
-#include "mali_kernel_subsystem.h"
-
-#include "mali_pmm.h"
-#include "mali_pmm_state.h"
-#include "mali_pmm_system.h"
-
-#include "mali_kernel_core.h"
-#include "mali_platform.h"
-
-#define SIZEOF_CORES_LIST 6
-
-/* NOTE: L2 *MUST* be first on the list so that it
- * is correctly powered on first and powered off last
- */
-static mali_pmm_core_id cores_list[] = { MALI_PMM_CORE_L2,
- MALI_PMM_CORE_GP,
- MALI_PMM_CORE_PP0,
- MALI_PMM_CORE_PP1,
- MALI_PMM_CORE_PP2,
- MALI_PMM_CORE_PP3 };
-
-
-
-void pmm_update_system_state( _mali_pmm_internal_state_t *pmm )
-{
- mali_pmm_state state;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- if( pmm->cores_registered == 0 )
- {
- state = MALI_PMM_STATE_UNAVAILABLE;
- }
- else if( pmm->cores_powered == 0 )
- {
- state = MALI_PMM_STATE_SYSTEM_OFF;
- }
- else if( pmm->cores_powered == pmm->cores_registered )
- {
- state = MALI_PMM_STATE_SYSTEM_ON;
- }
- else
- {
- /* Some other state where not everything is on or off */
- state = MALI_PMM_STATE_SYSTEM_TRANSITION;
- }
-
-#if MALI_PMM_TRACE
- _mali_pmm_trace_state_change( pmm->state, state );
-#endif
- pmm->state = state;
-}
-
-mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
-{
- mali_pmm_core_mask cores;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_DEBUG_ASSERT_POINTER(event);
-
- switch( event->id )
- {
- case MALI_PMM_EVENT_OS_POWER_UP:
- case MALI_PMM_EVENT_OS_POWER_DOWN:
- /* All cores - the system */
- cores = pmm->cores_registered;
- break;
-
- case MALI_PMM_EVENT_JOB_SCHEDULED:
- case MALI_PMM_EVENT_JOB_QUEUED:
- case MALI_PMM_EVENT_JOB_FINISHED:
- case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
- case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
- /* Currently the main event data is only the cores
- * for these messages
- */
- cores = (mali_pmm_core_mask)event->data;
- if( cores == MALI_PMM_CORE_SYSTEM )
- {
- cores = pmm->cores_registered;
- }
- else if( cores == MALI_PMM_CORE_PP_ALL )
- {
- /* Get the subset of registered PP cores */
- cores = (pmm->cores_registered & MALI_PMM_CORE_PP_ALL);
- }
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
- break;
-
- default:
- /* Assume timeout messages - report cores still powered */
- cores = pmm->cores_powered;
- break;
- }
-
- return cores;
-}
-
-mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
-{
- mali_pmm_core_mask cores_subset;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
-
- /* Check that cores aren't pending power down when asked for power up */
- MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );
-
- cores_subset = (~(pmm->cores_powered) & cores);
- if( cores_subset != 0 )
- {
- /* There are some cores that need powering up */
- pmm->cores_pend_up = cores_subset;
- }
-
- return cores_subset;
-}
-
-mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only )
-{
- mali_pmm_core_mask cores_subset;
- _mali_osk_errcode_t err;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
-
- /* Check that cores aren't pending power up when asked for power down */
- MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );
-
- cores_subset = (pmm->cores_powered & cores);
- if( cores_subset != 0 )
- {
- int n;
- volatile mali_pmm_core_mask *ppowered = &(pmm->cores_powered);
-
- /* There are some cores that need powering up, but we may
- * need to wait until they are idle
- */
- for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
- {
- if( (cores_list[n] & cores_subset) != 0 )
- {
- /* Core is to be powered down */
- pmm->cores_pend_down |= cores_list[n];
-
- /* Can't hold the power lock, when acessing subsystem mutex via
- * the core power call.
- * Due to terminatation of driver requiring a subsystem mutex
- * and then power lock held to unregister a core.
- * This does mean that the following function could fail
- * as the core is unregistered before we tell it to power
- * down, but it does not matter as we are terminating
- */
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
- /* Signal the core to power down
- * If it is busy (not idle) it will set a pending power down flag
- * (as long as we don't want to only immediately power down).
- * If it isn't busy it will move out of the idle queue right
- * away
- */
- err = mali_core_signal_power_down( cores_list[n], immediate_only );
- MALI_PMM_LOCK(pmm);
-
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
-
- /* Re-read cores_subset in case it has changed */
- cores_subset = (*ppowered & cores);
-
- if( err == _MALI_OSK_ERR_OK )
- {
- /* We moved an idle core to the power down queue
- * which means it is now acknowledged (if it is still
- * registered)
- */
- pmm->cores_ack_down |= (cores_list[n] & cores_subset);
- }
- else
- {
- MALI_DEBUG_PRINT(1,("PMM: In pmm_cores_to_power_down, the error and cores powered are..%x....%x",err,*ppowered));
- MALI_DEBUG_ASSERT( err == _MALI_OSK_ERR_BUSY ||
- (err == _MALI_OSK_ERR_FAULT &&
- (*ppowered & cores_list[n]) == 0) );
- /* If we didn't move a core - it must be active, so
- * leave it pending, so we get an acknowledgement (when
- * not in immediate only mode)
- * Alternatively we are shutting down and the core has
- * been unregistered
- */
- }
- }
- }
- }
-
- return cores_subset;
-}
-
-void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm )
-{
- int n;
- mali_pmm_core_mask pd, ad;
- _mali_osk_errcode_t err;
- volatile mali_pmm_core_mask *pregistered;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- MALIPMM_DEBUG_PRINT( ("PMM: Cancelling power down\n") );
-
- pd = pmm->cores_pend_down;
- ad = pmm->cores_ack_down;
- /* Clear the pending cores so that they don't move to the off
- * queue if they haven't already
- */
- pmm->cores_pend_down = 0;
- pmm->cores_ack_down = 0;
- pregistered = &(pmm->cores_registered);
-
- /* Power up all the pending power down cores - just so
- * we make sure the system is in a known state, as a
- * pending core might have sent an acknowledged message
- * which hasn't been read yet.
- */
- for( n = 0; n < SIZEOF_CORES_LIST; n++ )
- {
- if( (cores_list[n] & pd) != 0 )
- {
- /* Can't hold the power lock, when acessing subsystem mutex via
- * the core power call.
- * Due to terminatation of driver requiring a subsystem mutex
- * and then power lock held to unregister a core.
- * This does mean that the following power up function could fail
- * as the core is unregistered before we tell it to power
- * up, but it does not matter as we are terminating
- */
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
- /* As we are cancelling - only move the cores back to the queue -
- * no reset needed
- */
- err = mali_core_signal_power_up( cores_list[n], MALI_TRUE );
- MALI_PMM_LOCK(pmm);
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
- /* Update pending list with the current registered cores */
- pd &= (*pregistered);
-
- if( err != _MALI_OSK_ERR_OK )
- {
- MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_BUSY &&
- ((cores_list[n] & ad) == 0)) ||
- (err == _MALI_OSK_ERR_FAULT &&
- (*pregistered & cores_list[n]) == 0) );
- /* If we didn't power up a core - it must be active and
- * hasn't actually tried to power down - this is expected
- * for cores that haven't acknowledged
- * Alternatively we are shutting down and the core has
- * been unregistered
- */
- }
- }
- }
- /* Only used in debug builds */
- MALI_IGNORE(ad);
-}
-
-
-mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- return ( pmm->cores_pend_down == pmm->cores_ack_down ? MALI_TRUE : MALI_FALSE );
-}
-
-mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode )
-{
- _mali_osk_errcode_t err;
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- /* Check that cores are pending power down during power down invoke */
- MALI_DEBUG_ASSERT( pmm->cores_pend_down != 0 );
- /* Check that cores are not pending power up during power down invoke */
- MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );
-
- if( !pmm_power_down_okay( pmm ) )
- {
- MALIPMM_DEBUG_PRINT( ("PMM: Waiting for cores to go idle for power off - 0x%08x / 0x%08x\n",
- pmm->cores_pend_down, pmm->cores_ack_down) );
- return MALI_FALSE;
- }
- else
- {
- pmm->cores_powered &= ~(pmm->cores_pend_down);
-#if !MALI_PMM_NO_PMU
- err = malipmm_powerdown( pmm->cores_pend_down, power_mode);
-#else
- err = _MALI_OSK_ERR_OK;
-#endif
-
- if( err == _MALI_OSK_ERR_OK )
- {
-#if MALI_PMM_TRACE
- mali_pmm_core_mask old_power = pmm->cores_powered;
-#endif
- /* Remove powered down cores from idle and powered list */
- pmm->cores_idle &= ~(pmm->cores_pend_down);
- /* Reset pending/acknowledged status */
- pmm->cores_pend_down = 0;
- pmm->cores_ack_down = 0;
-#if MALI_PMM_TRACE
- _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
-#endif
- }
- else
- {
- pmm->cores_powered |= pmm->cores_pend_down;
- MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power down cores - (0x%x) %s",
- pmm->cores_pend_down, pmm_trace_get_core_name(pmm->cores_pend_down)) );
- pmm->fatal_power_err = MALI_TRUE;
- }
- }
-
- return MALI_TRUE;
-}
-
-
-mali_bool pmm_power_up_okay( _mali_pmm_internal_state_t *pmm )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- return ( pmm->cores_pend_up == pmm->cores_ack_up ? MALI_TRUE : MALI_FALSE );
-}
-
-
-mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm )
-{
- _mali_osk_errcode_t err;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
-
- /* Check that cores are pending power up during power up invoke */
- MALI_DEBUG_ASSERT( pmm->cores_pend_up != 0 );
- /* Check that cores are not pending power down during power up invoke */
- MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );
-
- if( pmm_power_up_okay( pmm ) )
- {
- /* Power up has completed - sort out subsystem core status */
-
- int n;
- /* Use volatile to access, so that it is updated if any cores are unregistered */
- volatile mali_pmm_core_mask *ppendup = &(pmm->cores_pend_up);
-#if MALI_PMM_TRACE
- mali_pmm_core_mask old_power = pmm->cores_powered;
-#endif
- /* Move cores into idle queues */
- for( n = 0; n < SIZEOF_CORES_LIST; n++ )
- {
- if( (cores_list[n] & (*ppendup)) != 0 )
- {
- /* Can't hold the power lock, when acessing subsystem mutex via
- * the core power call.
- * Due to terminatation of driver requiring a subsystem mutex
- * and then power lock held to unregister a core.
- * This does mean that the following function could fail
- * as the core is unregistered before we tell it to power
- * up, but it does not matter as we are terminating
- */
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
- err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
- MALI_PMM_LOCK(pmm);
-
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
-
- if( err != _MALI_OSK_ERR_OK )
- {
- MALI_DEBUG_PRINT(1,("In pmm_invoke_power_up:: The error and pending cores to be powered up are...%x...%x",err,*ppendup));
- MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_FAULT &&
- (*ppendup & cores_list[n]) == 0) );
- /* We only expect this to fail when we are shutting down
- * and the core has been unregistered
- */
- }
- }
- }
- /* Finished power up - add cores to idle and powered list */
- pmm->cores_powered |= (*ppendup);
- pmm->cores_idle |= (*ppendup);
- /* Reset pending/acknowledge status */
- pmm->cores_pend_up = 0;
- pmm->cores_ack_up = 0;
-
-#if MALI_PMM_TRACE
- _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
-#endif
- return MALI_TRUE;
- }
- else
- {
-#if !MALI_PMM_NO_PMU
- /* Power up must now be done */
- err = malipmm_powerup( pmm->cores_pend_up );
-#else
- err = _MALI_OSK_ERR_OK;
-#endif
- if( err != _MALI_OSK_ERR_OK )
- {
- MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power up cores - (0x%x) %s",
- pmm->cores_pend_up, pmm_trace_get_core_name(pmm->cores_pend_up)) );
- pmm->fatal_power_err = MALI_TRUE;
- }
- else
- {
- /* TBD - Update core status immediately rather than use event message */
- _mali_uk_pmm_message_s event = {
- NULL,
- MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK,
- 0 };
- /* All the cores that were pending power up, have now completed power up */
- event.data = pmm->cores_pend_up;
- _mali_ukk_pmm_event_message( &event );
- MALIPMM_DEBUG_PRINT( ("PMM: Sending ACK to power up") );
- }
- }
-
- /* Always return false, as we need an interrupt to acknowledge
- * when power up is complete
- */
- return MALI_FALSE;
-}
-
-mali_pmm_core_mask pmm_cores_set_active( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
-
- pmm->cores_idle &= (~cores);
- return pmm->cores_idle;
-}
-
-mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
-
- pmm->cores_idle |= (cores);
- return pmm->cores_idle;
-}
-
-mali_pmm_core_mask pmm_cores_set_down_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
-
- /* Check core is not pending a power down */
- MALI_DEBUG_ASSERT( (pmm->cores_pend_down & cores) != 0 );
- /* Check core has not acknowledged power down more than once */
- MALI_DEBUG_ASSERT( (pmm->cores_ack_down & cores) == 0 );
-
- pmm->cores_ack_down |= (cores);
-
- return pmm->cores_ack_down;
-}
-
-void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm )
-{
- _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
- _mali_osk_notification_t *msg = NULL;
- mali_pmm_status status;
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALIPMM_DEBUG_PRINT( ("PMM: Fatal Reset called") );
-
- MALI_DEBUG_ASSERT( pmm->status != MALI_PMM_STATUS_OFF );
-
- /* Reset the common status */
- pmm->waiting = 0;
- pmm->missed = 0;
- pmm->fatal_power_err = MALI_FALSE;
- pmm->no_events = 0;
- pmm->check_policy = MALI_FALSE;
- pmm->cores_pend_down = 0;
- pmm->cores_pend_up = 0;
- pmm->cores_ack_down = 0;
- pmm->cores_ack_up = 0;
- pmm->is_dvfs_active = 0;
-#if MALI_PMM_TRACE
- pmm->messages_sent = 0;
- pmm->messages_received = 0;
- pmm->imessages_sent = 0;
- pmm->imessages_received = 0;
- MALI_PRINT( ("PMM Trace: *** Fatal reset occurred ***") );
-#endif
-
- /* Set that we are unavailable whilst resetting */
- pmm->state = MALI_PMM_STATE_UNAVAILABLE;
- status = pmm->status;
- pmm->status = MALI_PMM_STATUS_OFF;
-
- /* We want all cores powered */
- pmm->cores_powered = pmm->cores_registered;
- /* The cores may not be idle, but this state will be rectified later */
- pmm->cores_idle = pmm->cores_registered;
-
- /* So power on any cores that are registered */
- if( pmm->cores_registered != 0 )
- {
- int n;
- volatile mali_pmm_core_mask *pregistered = &(pmm->cores_registered);
-#if !MALI_PMM_NO_PMU
- err = malipmm_powerup( pmm->cores_registered );
-#endif
- if( err != _MALI_OSK_ERR_OK )
- {
- /* This is very bad as we can't even be certain the cores are now
- * powered up
- */
- MALI_PRINT_ERROR( ("PMM: Failed to perform PMM reset!\n") );
- /* TBD driver exit? */
- }
-
- for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
- {
- if( (cores_list[n] & (*pregistered)) != 0 )
- {
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 0;
-#endif /* MALI_STATE_TRACKING */
-
- MALI_PMM_UNLOCK(pmm);
- /* Core is now active - so try putting it in the idle queue */
- err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
- MALI_PMM_LOCK(pmm);
-#if MALI_STATE_TRACKING
- pmm->mali_pmm_lock_acquired = 1;
-#endif /* MALI_STATE_TRACKING */
-
- /* We either succeeded, or we were not off anyway, or we have
- * just be deregistered
- */
- MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_OK) ||
- (err == _MALI_OSK_ERR_BUSY) ||
- (err == _MALI_OSK_ERR_FAULT &&
- (*pregistered & cores_list[n]) == 0) );
- }
- }
- }
-
- /* Unblock any pending OS event */
- if( status == MALI_PMM_STATUS_OS_POWER_UP )
- {
- /* Get the OS data and respond to the power up */
- _mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) );
- }
- if( status == MALI_PMM_STATUS_OS_POWER_DOWN )
- {
- /* Get the OS data and respond to the power down
- * NOTE: We are not powered down at this point due to power problems,
- * so we are lying to the system, but something bad has already
- * happened and we are trying unstick things
- * TBD - Add busy loop to power down cores?
- */
- _mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) );
- }
-
- /* Purge the event queues */
- do
- {
- if( _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ) == _MALI_OSK_ERR_OK )
- {
- _mali_osk_notification_delete ( msg );
- break;
- }
- } while (MALI_TRUE);
-
- do
- {
- if( _mali_osk_notification_queue_dequeue( pmm->queue, &msg ) == _MALI_OSK_ERR_OK )
- {
- _mali_osk_notification_delete ( msg );
- break;
- }
- } while (MALI_TRUE);
-
- /* Return status/state to normal */
- pmm->status = MALI_PMM_STATUS_IDLE;
- pmm_update_system_state(pmm);
-}
-
-mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
-
- /* Check core is not pending a power up */
- MALI_DEBUG_ASSERT( (pmm->cores_pend_up & cores) != 0 );
- /* Check core has not acknowledged power up more than once */
- MALI_DEBUG_ASSERT( (pmm->cores_ack_up & cores) == 0 );
-
- pmm->cores_ack_up |= (cores);
-
- return pmm->cores_ack_up;
-}
-
-void pmm_save_os_event_data(_mali_pmm_internal_state_t *pmm, mali_pmm_message_data data)
-{
- MALI_DEBUG_ASSERT_POINTER(pmm);
- /* Check that there is no saved data */
- MALI_DEBUG_ASSERT( pmm->os_data == 0 );
- /* Can't store zero data - as retrieve check will fail */
- MALI_DEBUG_ASSERT( data != 0 );
-
- pmm->os_data = data;
-}
-
-mali_pmm_message_data pmm_retrieve_os_event_data(_mali_pmm_internal_state_t *pmm)
-{
- mali_pmm_message_data data;
-
- MALI_DEBUG_ASSERT_POINTER(pmm);
- /* Check that there is saved data */
- MALI_DEBUG_ASSERT( pmm->os_data != 0 );
-
- /* Get data, and clear the saved version */
- data = pmm->os_data;
- pmm->os_data = 0;
-
- return data;
-}
-
-/* Create list of core names to look up
- * We are doing it this way to overcome the need for
- * either string allocation, or stack space, so we
- * use constant strings instead
- */
-typedef struct pmm_trace_corelist
-{
- mali_pmm_core_mask id;
- const char *name;
-} pmm_trace_corelist_t;
-
-static pmm_trace_corelist_t pmm_trace_cores[] = {
- { MALI_PMM_CORE_SYSTEM, "SYSTEM" },
- { MALI_PMM_CORE_GP, "GP" },
- { MALI_PMM_CORE_L2, "L2" },
- { MALI_PMM_CORE_PP0, "PP0" },
- { MALI_PMM_CORE_PP1, "PP1" },
- { MALI_PMM_CORE_PP2, "PP2" },
- { MALI_PMM_CORE_PP3, "PP3" },
- { MALI_PMM_CORE_PP_ALL, "PP (all)" },
- { (MALI_PMM_CORE_GP | MALI_PMM_CORE_L2 | MALI_PMM_CORE_PP0),
- "GP+L2+PP0" },
- { (MALI_PMM_CORE_GP | MALI_PMM_CORE_PP0),
- "GP+PP0" },
- { (MALI_PMM_CORE_GP | MALI_PMM_CORE_L2 | MALI_PMM_CORE_PP0 | MALI_PMM_CORE_PP1),
- "GP+L2+PP0+PP1" },
- { (MALI_PMM_CORE_GP | MALI_PMM_CORE_PP0 | MALI_PMM_CORE_PP1),
- "GP+PP0+PP1" },
- { 0, NULL } /* Terminator of list */
-};
-
-const char *pmm_trace_get_core_name( mali_pmm_core_mask cores )
-{
- const char *dname = NULL;
- int cl;
-
- /* Look up name in corelist */
- cl = 0;
- while( pmm_trace_cores[cl].name != NULL )
- {
- if( pmm_trace_cores[cl].id == cores )
- {
- dname = pmm_trace_cores[cl].name;
- break;
- }
- cl++;
- }
-
- if( dname == NULL )
- {
- /* We don't know a good short-hand for the configuration */
- dname = "[multi-core]";
- }
-
- return dname;
-}
-
-#endif /* USING_MALI_PMM */
-
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h
deleted file mode 100644
index 4768344..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h
+++ /dev/null
@@ -1,290 +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 __MALI_PMM_STATE_H__
-#define __MALI_PMM_STATE_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @addtogroup pmmapi Power Management Module APIs
- *
- * @{
- *
- * @defgroup pmmapi_state Power Management Module State
- *
- * @{
- */
-
-/* Check that the subset is really a subset of cores */
-#define MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( cores, subset ) \
- MALI_DEBUG_ASSERT( ((~(cores)) & (subset)) == 0 )
-
-
-/* Locking macros */
-#define MALI_PMM_LOCK(pmm) \
- _mali_osk_lock_wait( pmm->lock, _MALI_OSK_LOCKMODE_RW )
-#define MALI_PMM_UNLOCK(pmm) \
- _mali_osk_lock_signal( pmm->lock, _MALI_OSK_LOCKMODE_RW )
-#define MALI_PMM_LOCK_TERM(pmm) \
- _mali_osk_lock_term( pmm->lock )
-
-/* Notification type for messages */
-#define MALI_PMM_NOTIFICATION_TYPE 0
-
-/** @brief Status of the PMM state machine
- */
-typedef enum mali_pmm_status_tag
-{
- MALI_PMM_STATUS_IDLE, /**< PMM is waiting next event */
- MALI_PMM_STATUS_POLICY_POWER_DOWN, /**< Policy initiated power down */
- MALI_PMM_STATUS_POLICY_POWER_UP, /**< Policy initiated power down */
- MALI_PMM_STATUS_OS_WAITING, /**< PMM is waiting for OS power up */
- MALI_PMM_STATUS_OS_POWER_DOWN, /**< OS initiated power down */
- MALI_PMM_STATUS_DVFS_PAUSE, /**< PMM DVFS Status Pause */
- MALI_PMM_STATUS_OS_POWER_UP, /**< OS initiated power up */
- MALI_PMM_STATUS_OFF, /**< PMM is not active */
-} mali_pmm_status;
-
-
-/** @brief Internal state of the PMM
- */
-typedef struct _mali_pmm_internal_state
-{
- mali_pmm_status status; /**< PMM state machine */
- mali_pmm_policy policy; /**< PMM policy */
- mali_bool check_policy; /**< PMM policy needs checking */
- mali_pmm_state state; /**< PMM state */
- mali_pmm_core_mask cores_registered; /**< Bitmask of cores registered */
- mali_pmm_core_mask cores_powered; /**< Bitmask of cores powered up */
- mali_pmm_core_mask cores_idle; /**< Bitmask of cores idle */
- mali_pmm_core_mask cores_pend_down; /**< Bitmask of cores pending power down */
- mali_pmm_core_mask cores_pend_up; /**< Bitmask of cores pending power up */
- mali_pmm_core_mask cores_ack_down; /**< Bitmask of cores acknowledged power down */
- mali_pmm_core_mask cores_ack_up; /**< Bitmask of cores acknowledged power up */
-
- _mali_osk_notification_queue_t *queue; /**< PMM event queue */
- _mali_osk_notification_queue_t *iqueue; /**< PMM internal event queue */
- _mali_osk_irq_t *irq; /**< PMM irq handler */
- _mali_osk_lock_t *lock; /**< PMM lock */
-
- mali_pmm_message_data os_data; /**< OS data sent via the OS events */
-
- mali_bool pmu_initialized; /**< PMU initialized */
-
- _mali_osk_atomic_t messages_queued; /**< PMM event messages queued */
- u32 waiting; /**< PMM waiting events - due to busy */
- u32 no_events; /**< PMM called to process when no events */
-
- u32 missed; /**< PMM missed events due to OOM */
- mali_bool fatal_power_err; /**< PMM has had a fatal power error? */
- u32 is_dvfs_active; /**< PMM DVFS activity */
-
-#if MALI_STATE_TRACKING
- mali_pmm_status mali_last_pmm_status; /**< The previous PMM status */
- mali_pmm_event_id mali_new_event_status;/**< The type of the last PMM event */
- mali_bool mali_pmm_lock_acquired; /**< Is the PMM lock held somewhere or not */
-#endif
-
-#if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
- u32 messages_sent; /**< Total event messages sent */
- u32 messages_received; /**< Total event messages received */
- u32 imessages_sent; /**< Total event internal messages sent */
- u32 imessages_received; /**< Total event internal messages received */
-#endif
-} _mali_pmm_internal_state_t;
-
-/** @brief Sets that a policy needs a check before processing events
- *
- * A timer or something has expired that needs dealing with
- */
-void malipmm_set_policy_check(void);
-
-/** @brief Update the PMM externally viewable state depending on the current PMM internal state
- *
- * @param pmm internal PMM state
- * @return MALI_TRUE if the timeout is valid, else MALI_FALSE
- */
-void pmm_update_system_state( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Returns the core mask from the event data - if applicable
- *
- * @param pmm internal PMM state
- * @param event event message to get the core mask from
- * @return mask of cores that is relevant to this event message
- */
-mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
-
-/** @brief Sort out which cores need to be powered up from the given core mask
- *
- * All cores that can be powered up will be put into a pending state
- *
- * @param pmm internal PMM state
- * @param cores mask of cores to check if they need to be powered up
- * @return mask of cores that need to be powered up, this can be 0 if all cores
- * are powered up already
- */
-mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
-
-/** @brief Sort out which cores need to be powered down from the given core mask
- *
- * All cores that can be powered down will be put into a pending state. If they
- * can be powered down immediately they will also be acknowledged that they can be
- * powered down. If the immediate_only flag is set, then only those cores that
- * can be acknowledged for power down will be put into a pending state.
- *
- * @param pmm internal PMM state
- * @param cores mask of cores to check if they need to be powered down
- * @param immediate_only MALI_TRUE means that only cores that can power down now will
- * be put into a pending state
- * @return mask of cores that need to be powered down, this can be 0 if all cores
- * are powered down already
- */
-mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only );
-
-/** @brief Cancel an invokation to power down (pmm_invoke_power_down)
- *
- * @param pmm internal PMM state
- */
-void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Check if a call to invoke power down should succeed, or fail
- *
- * This will report MALI_FALSE if some of the cores are still active and need
- * to acknowledge that they are ready to power down
- *
- * @param pmm internal PMM state
- * @return MALI_TRUE if the pending cores to power down have acknowledged they
- * can power down, else MALI_FALSE
- */
-mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Try to make all the pending cores power down
- *
- * If all the pending cores have acknowledged they can power down, this will call the
- * PMU power down function to turn them off
- *
- * @param pmm internal PMM state
- * @return MALI_TRUE if the pending cores have been powered down, else MALI_FALSE
- */
-mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode );
-
-/** @brief Check if all the pending cores to power up have done so
- *
- * This will report MALI_FALSE if some of the cores are still powered off
- * and have not acknowledged that they have powered up
- *
- * @param pmm internal PMM state
- * @return MALI_TRUE if the pending cores to power up have acknowledged they
- * are now powered up, else MALI_FALSE
- */
-mali_bool pmm_power_up_okay( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Try to make all the pending cores power up
- *
- * If all the pending cores have acknowledged they have powered up, this will
- * make the cores start processing jobs again, else this will call the PMU
- * power up function to turn them on, and the PMM is then expected to wait for an
- * interrupt to acknowledge the power up
- *
- * @param pmm internal PMM state
- * @return MALI_TRUE if the pending cores have been powered up, else MALI_FALSE
- */
-mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Set the cores that are now active in the system
- *
- * Updates which cores are active and returns which cores are still idle
- *
- * @param pmm internal PMM state
- * @param cores mask of cores to set to active
- * @return mask of all the cores that are idle
- */
-mali_pmm_core_mask pmm_cores_set_active( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
-
-/** @brief Set the cores that are now idle in the system
- *
- * Updates which cores are idle and returns which cores are still idle
- *
- * @param pmm internal PMM state
- * @param cores mask of cores to set to idle
- * @return mask of all the cores that are idle
- */
-mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
-
-/** @brief Set the cores that have acknowledged a pending power down
- *
- * Updates which cores have acknowledged the pending power down and are now ready
- * to be turned off
- *
- * @param pmm internal PMM state
- * @param cores mask of cores that have acknowledged the pending power down
- * @return mask of all the cores that have acknowledged the power down
- */
-mali_pmm_core_mask pmm_cores_set_down_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
-
-/** @brief Set the cores that have acknowledged a pending power up
- *
- * Updates which cores have acknowledged the pending power up and are now
- * fully powered and ready to run jobs
- *
- * @param pmm internal PMM state
- * @param cores mask of cores that have acknowledged the pending power up
- * @return mask of all the cores that have acknowledged the power up
- */
-mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
-
-
-/** @brief Tries to reset the PMM and PMU hardware to a known state after any fatal issues
- *
- * This will try and make all the cores powered up and reset the PMM state
- * to its initial state after core registration - all cores powered but not
- * pending or active.
- * All events in the event queues will be thrown away.
- *
- * @note: Any pending power down will be cancelled including the OS calling for power down
- */
-void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm );
-
-/** @brief Save the OS specific data for an OS power up/down event
- *
- * @param pmm internal PMM state
- * @param data OS specific event data
- */
-void pmm_save_os_event_data(_mali_pmm_internal_state_t *pmm, mali_pmm_message_data data);
-
-/** @brief Retrieve the OS specific data for an OS power up/down event
- *
- * This will clear the stored OS data, as well as return it.
- *
- * @param pmm internal PMM state
- * @return OS specific event data that was saved previously
- */
-mali_pmm_message_data pmm_retrieve_os_event_data(_mali_pmm_internal_state_t *pmm);
-
-
-/** @brief Get a human readable name for the cores in a core mask
- *
- * @param core the core mask
- * @return string containing a name relating to the given core mask
- */
-const char *pmm_trace_get_core_name( mali_pmm_core_mask core );
-
-/** @} */ /* End group pmmapi_state */
-/** @} */ /* End group pmmapi */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_PMM_STATE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h
deleted file mode 100644
index eccd35b..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h
+++ /dev/null
@@ -1,61 +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 __MALI_PMM_SYSTEM_H__
-#define __MALI_PMM_SYSTEM_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @addtogroup pmmapi Power Management Module APIs
- *
- * @{
- *
- * @defgroup pmmapi_system Power Management Module System Functions
- *
- * @{
- */
-
-extern struct mali_kernel_subsystem mali_subsystem_pmm;
-
-/** @brief Register a core with the PMM, which will power up
- * the core
- *
- * @param core the core to register with the PMM
- * @return error if the core cannot be powered up
- */
-_mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core );
-
-/** @brief Unregister a core with the PMM
- *
- * @param core the core to unregister with the PMM
- */
-void malipmm_core_unregister( mali_pmm_core_id core );
-
-/** @brief Acknowledge that a power down is okay to happen
- *
- * A core should not be running a job, or be in the idle queue when this
- * is called.
- *
- * @param core the core that can now be powered down
- */
-void malipmm_core_power_down_okay( mali_pmm_core_id core );
-
-/** @} */ /* End group pmmapi_system */
-/** @} */ /* End group pmmapi */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MALI_PMM_H__ */