import r3p2-00dev0 from amlogic-3.0-staging
authorLawrence Mok <lawrence.mok@amlogic.com>
Fri, 30 Nov 2012 02:19:45 +0000 (18:19 -0800)
committerLawrence Mok <lawrence.mok@amlogic.com>
Fri, 30 Nov 2012 02:23:52 +0000 (18:23 -0800)
ump/mali directories up to these commits:
3bdfcff configure two pp core for m6tv
87a2535 update mali to r3p2: add missing files
fc2ddc9 remove useless files
c7fdeb1 update mali driver to r3p2

123 files changed:
mali/Kbuild
mali/Kconfig
mali/Makefile
mali/common/mali_block_allocator.c
mali/common/mali_block_allocator.h
mali/common/mali_broadcast.c [new file with mode: 0644]
mali/common/mali_broadcast.h [new file with mode: 0644]
mali/common/mali_device_pause_resume.c
mali/common/mali_device_pause_resume.h
mali/common/mali_dlbu.c
mali/common/mali_dlbu.h
mali/common/mali_gp.c
mali/common/mali_gp.h
mali/common/mali_gp_job.c
mali/common/mali_gp_job.h
mali/common/mali_gp_scheduler.c
mali/common/mali_gp_scheduler.h
mali/common/mali_group.c
mali/common/mali_group.h
mali/common/mali_hw_core.c
mali/common/mali_hw_core.h
mali/common/mali_kernel_common.h
mali/common/mali_kernel_core.c
mali/common/mali_kernel_core.h
mali/common/mali_kernel_descriptor_mapping.c
mali/common/mali_kernel_descriptor_mapping.h
mali/common/mali_kernel_mem_os.c
mali/common/mali_kernel_mem_os.h
mali/common/mali_kernel_memory_engine.c
mali/common/mali_kernel_memory_engine.h
mali/common/mali_kernel_utilization.c
mali/common/mali_kernel_utilization.h
mali/common/mali_kernel_vsync.c
mali/common/mali_l2_cache.c
mali/common/mali_l2_cache.h
mali/common/mali_mem_validation.c
mali/common/mali_mem_validation.h
mali/common/mali_memory.c
mali/common/mali_memory.h
mali/common/mali_mmu.c
mali/common/mali_mmu.h
mali/common/mali_mmu_page_directory.c
mali/common/mali_mmu_page_directory.h
mali/common/mali_osk.h
mali/common/mali_osk_bitops.h
mali/common/mali_osk_list.h
mali/common/mali_osk_mali.h
mali/common/mali_osk_profiling.h
mali/common/mali_pm.c
mali/common/mali_pm.h
mali/common/mali_pmu.c
mali/common/mali_pmu.h
mali/common/mali_pp.c
mali/common/mali_pp.h
mali/common/mali_pp_job.c
mali/common/mali_pp_job.h
mali/common/mali_pp_scheduler.c
mali/common/mali_pp_scheduler.h
mali/common/mali_scheduler.c
mali/common/mali_scheduler.h
mali/common/mali_session.c
mali/common/mali_session.h
mali/common/mali_ukk.h
mali/common/mali_user_settings_db.c
mali/common/mali_user_settings_db.h
mali/include/linux/mali/mali_utgard.h
mali/include/linux/mali/mali_utgard_counters.h
mali/include/linux/mali/mali_utgard_ioctl.h
mali/include/linux/mali/mali_utgard_profiling_events.h
mali/include/linux/mali/mali_utgard_uk_types.h
mali/linux/mali_dma_buf.c
mali/linux/mali_dma_buf.h
mali/linux/mali_kernel_linux.c
mali/linux/mali_kernel_linux.h
mali/linux/mali_kernel_sysfs.c
mali/linux/mali_kernel_sysfs.h
mali/linux/mali_linux_pm_testsuite.h
mali/linux/mali_linux_trace.h
mali/linux/mali_osk_atomics.c
mali/linux/mali_osk_irq.c
mali/linux/mali_osk_locks.c
mali/linux/mali_osk_low_level_mem.c
mali/linux/mali_osk_mali.c
mali/linux/mali_osk_math.c
mali/linux/mali_osk_memory.c
mali/linux/mali_osk_misc.c
mali/linux/mali_osk_notification.c
mali/linux/mali_osk_pm.c
mali/linux/mali_osk_profiling.c
mali/linux/mali_osk_specific.h
mali/linux/mali_osk_time.c
mali/linux/mali_osk_timers.c
mali/linux/mali_osk_wait_queue.c
mali/linux/mali_osk_wq.c [new file with mode: 0644]
mali/linux/mali_pmu_power_up_down.c
mali/linux/mali_profiling_events.h
mali/linux/mali_profiling_internal.c
mali/linux/mali_profiling_internal.h
mali/linux/mali_sync.c [new file with mode: 0644]
mali/linux/mali_sync.h [new file with mode: 0644]
mali/linux/mali_sync_user.c [new file with mode: 0644]
mali/linux/mali_uk_types.h
mali/linux/mali_ukk_core.c
mali/linux/mali_ukk_gp.c
mali/linux/mali_ukk_mem.c
mali/linux/mali_ukk_pp.c
mali/linux/mali_ukk_profiling.c
mali/linux/mali_ukk_vsync.c
mali/linux/mali_ukk_wrappers.h
mali/platform/meson_platform/mali_fix.c
mali/platform/meson_platform/mali_platform.c
mali/platform/meson_platform/mali_platform.h [new file with mode: 0644]
mali/platform/meson_platform/meson_main.c [new file with mode: 0644]
mali/regs/mali_200_regs.h
mali/regs/mali_gp_regs.h
mali/timestamp-arm11-cc/mali_timestamp.c
mali/timestamp-arm11-cc/mali_timestamp.h
mali/timestamp-default/mali_timestamp.c
mali/timestamp-default/mali_timestamp.h
ump/Kbuild
ump/Kconfig
ump/Makefile
ump/arch-aml-meson-m400-1/config.h

index 27f5a8b1528d39ff414275c682c4859deabf473d..20c876f835fc7f4090f903c2e7e362cdc4b614ff 100644 (file)
@@ -1,18 +1,20 @@
 #
-# Copyright (C) 2010-2011 ARM Limited. All rights reserved.
-# 
-# This program is free software and is provided to you under the terms of the GNU General Public License version 2
-# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
-# 
-# A copy of the licence is included with the program, and can also be obtained from Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2007-2011 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
 #
 
 # This file is called by the Linux build system.
 
 OSKOS=linux
+TARGET_PLATFORM=meson_platform
 
 # set up defaults if not defined by the user
+TIMESTAMP ?= default
 ifeq ($(CONFIG_UMP), m)
   USING_UMP ?= 1
 else
@@ -20,63 +22,32 @@ else
 endif
 
 ifneq ($(KBUILD_SRC),)
-       ifneq ($(wildcard $(KBUILD_SRC)/$(src)),)
-               TOP_KBUILD_SRC := $(KBUILD_SRC)/
-       endif
+TOP_KBUILD_SRC := $(KBUILD_SRC)/
 endif
-
-USING_OS_MEMORY ?= 1
-USING_MALI_PMM_TESTSUITE ?= 0
 OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16
 
 ifeq ($(CONFIG_MALI400_PROFILING),y)
-       USING_PROFILING ?= 1
-       USING_INTERNAL_PROFILING ?= 1
+       USING_GPU_UTILIZATION ?= 1
 else
-       USING_PROFILING ?= 0
-       USING_INTERNAL_PROFILING ?= 0
+       USING_GPU_UTILIZATION ?= 0
 endif
-
-DISABLE_PP0 ?= 0
-DISABLE_PP1 ?= 0
-DISABLE_PP2 ?= 0
-DISABLE_PP3 ?= 0
 PROFILING_SKIP_PP_JOBS ?= 0
 PROFILING_SKIP_PP_AND_GP_JOBS ?= 0
-PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0
-TIMESTAMP ?= default
-
 ifeq ($(CONFIG_MALI400_DEBUG),y)
        BUILD ?= debug
 else
        BUILD ?= release
 endif
 
-TARGET_PLATFORM ?= meson_platform
-
-ifeq ($(CONFIG_ARCH_MESON6TV),y)
-       CONFIG ?= aml-meson-m400-4-nobr
-else
-       ifeq ($(CONFIG_ARCH_MESON6),y)
-       CONFIG ?= aml-meson-m400-2
-       else
-       CONFIG ?= aml-meson-m400-1
-       endif
-endif
-
 ifeq ($(USING_UMP),1)
        UMP_SYMVERS_FILE = ../ump/Module.symvers
        KBUILD_EXTRA_SYMBOLS = $(srctree)/$(src)/$(UMP_SYMVERS_FILE)
 endif
 
-KERNEL_RUNTIME_PM_ENABLED ?= 0
-CONFIG ?= pb-virtex5-m200
 MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0
 MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0
 MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0
 
-DEFINES := $(EXTRA_DEFINES)
-
 # Get path to driver source from Linux build system
 DRIVER_DIR=$(src)
 
@@ -84,240 +55,144 @@ DRIVER_DIR=$(src)
 # The ARM proprietary product will only include the license/proprietary directory
 # The GPL product will only include the license/gpl directory
 
-ifeq ($(wildcard $(TOP_KBUILD_SRC)$(DRIVER_DIR)/linux/license/gpl/*),)
-ccflags-y += -I$(TOP_KBUILD_SRC)$(DRIVER_DIR)/linux/license/gpl
-# Disable profiling for proprietary
-override USING_PROFILING := 0
-$(warning "USING_PROFILING not supported, disabling.$(TOP_KBUILD_SRC)    ")
-else
+
 ccflags-y += -I$(TOP_KBUILD_SRC)$(DRIVER_DIR)/linux/license/gpl
-endif
 
+mali-y += \
+       $(OSKOS)/mali_osk_atomics.o \
+       $(OSKOS)/mali_osk_irq.o \
+       $(OSKOS)/mali_osk_wq.o \
+       $(OSKOS)/mali_osk_locks.o \
+       $(OSKOS)/mali_osk_wait_queue.o \
+       $(OSKOS)/mali_osk_low_level_mem.o \
+       $(OSKOS)/mali_osk_math.o \
+       $(OSKOS)/mali_osk_memory.o \
+       $(OSKOS)/mali_osk_misc.o \
+       $(OSKOS)/mali_osk_mali.o \
+       $(OSKOS)/mali_osk_notification.o \
+       $(OSKOS)/mali_osk_time.o \
+       $(OSKOS)/mali_osk_timers.o
+
+mali-y += \
+       $(OSKOS)/mali_ukk_mem.o \
+       $(OSKOS)/mali_ukk_gp.o \
+       $(OSKOS)/mali_ukk_pp.o \
+       $(OSKOS)/mali_ukk_core.o
+       
+# Source files which always are included in a build
+mali-y += \
+       common/mali_kernel_core.o \
+       linux/mali_kernel_linux.o \
+       common/mali_kernel_descriptor_mapping.o \
+       common/mali_session.o \
+       common/mali_device_pause_resume.o \
+       common/mali_kernel_vsync.o \
+       linux/mali_ukk_vsync.o \
+       linux/mali_kernel_sysfs.o \
+       common/mali_mmu.o \
+       common/mali_mmu_page_directory.o \
+       common/mali_memory.o \
+       common/mali_kernel_memory_engine.o \
+       common/mali_block_allocator.o \
+       common/mali_kernel_mem_os.o \
+       common/mali_mem_validation.o \
+       common/mali_hw_core.o \
+       common/mali_gp.o \
+       common/mali_pp.o \
+       common/mali_pp_job.o \
+       common/mali_gp_job.o \
+       common/mali_scheduler.o \
+       common/mali_gp_scheduler.o \
+       common/mali_pp_scheduler.o \
+       common/mali_group.o \
+       common/mali_dlbu.o \
+       common/mali_broadcast.o \
+       common/mali_pm.o \
+       common/mali_pmu.o \
+       common/mali_user_settings_db.o \
+       common/mali_kernel_utilization.o \
+       common/mali_l2_cache.o \
+       linux/mali_osk_pm.o \
+       linux/mali_pmu_power_up_down.o \
+       __malidrv_build_info.o
+
+MALI_PLATFORM_FILES = platform/meson_platform/mali_fix.c \
+                       platform/meson_platform/mali_platform.c \
+                       platform/meson_platform/meson_main.c
+
+ifneq ($(MALI_PLATFORM_FILES),)
+       mali-y += $(MALI_PLATFORM_FILES:.c=.o)
+endif
+
+mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o
+mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o
+
+mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o
+ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP)
 
-ifeq ($(USING_PROFILING),1)
-ifndef CONFIG_TRACEPOINTS
-# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling
-override USING_PROFILING = 0
-$(warning "CONFIG_TRACEPOINTS required for USING_PROFILING")
-endif
-endif
+mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o
+mali-$(CONFIG_SYNC) += linux/mali_sync.o linux/mali_sync_user.o
 
-MALI_RELEASE_NAME=$(shell cat $(TOP_KBUILD_SRC)$(DRIVER_DIR)/.version 2> /dev/null)
+# Tell the Linux build system from which .o file to create the kernel module
+obj-$(CONFIG_MALI400) := mali.o
 
-# Check if a Mali Core sub module should be enabled, true or false returned
-submodule_enabled = $(shell gcc $(DEFINES) -E $1/arch/config.h | grep type | grep -c $(2))
+ccflags-y += $(EXTRA_DEFINES)
 
-OSKFILES = \
-       $(OSKOS)/mali_osk_atomics.c \
-       $(OSKOS)/mali_osk_irq.c \
-       $(OSKOS)/mali_osk_locks.c \
-       $(OSKOS)/mali_osk_wait_queue.c \
-       $(OSKOS)/mali_osk_low_level_mem.c \
-       $(OSKOS)/mali_osk_math.c \
-       $(OSKOS)/mali_osk_memory.c \
-       $(OSKOS)/mali_osk_misc.c \
-       $(OSKOS)/mali_osk_mali.c \
-       $(OSKOS)/mali_osk_notification.c \
-       $(OSKOS)/mali_osk_time.c \
-       $(OSKOS)/mali_osk_timers.c
+# Set up our defines, which will be passed to gcc
+ccflags-y += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS)
+ccflags-y += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS)
 
-UKKFILES = \
-       $(OSKOS)/mali_ukk_mem.c \
-       $(OSKOS)/mali_ukk_gp.c \
-       $(OSKOS)/mali_ukk_pp.c \
-       $(OSKOS)/mali_ukk_core.c
+ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP)
+ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED)
+ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS)
+ccflags-y += -DMALI_STATE_TRACKING=1
+ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
+ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION)
+ccflags-y += -DMALI_FAKE_PLATFORM_DEVICE
 
-ifeq ($(USING_PROFILING),1)
-UKKFILES += \
-       $(OSKOS)/mali_ukk_profiling.c
-endif
+ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../ump/include/ump
+ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG
 
-ifeq ($(MALI_PLATFORM_FILE),)
-MALI_PLATFORM_FILE = platform/default/mali_platform.c
-endif
+# Use our defines when compiling
+ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform
 
 # Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available
-SVN_REV := $(shell (cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); (svnversion | grep -qv exported && svnversion) || git svn info | grep '^Revision: '| sed -e 's/^Revision: //' ) 2>/dev/null )
+MALI_RELEASE_NAME=$(shell cat $(TOP_KBUILD_SRC)$(DRIVER_DIR)/.version 2> /dev/null)
+
+SVN_INFO = (cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); (svn info || git svn info || \
+       echo -e "\nURL: $(MALI_RELEASE_NAME)\n" \
+       "Last Changed Rev: $(MALI_RELEASE_NAME)\n" \
+       "Last Changed Date: $(MALI_RELEASE_NAME)") 2>/dev/null)
+
+SVN_REV := $(shell (cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); echo "$(SVN_INFO)" | grep '^Revision: '| sed -e 's/^Revision: //' ) 2>/dev/null )
 ifeq ($(SVN_REV),)
 SVN_REV := $(MALI_RELEASE_NAME)
 else
 SVN_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV)
 endif
 
-# Validate selected config
-ifneq ($(shell [ -d $(TOP_KBUILD_SRC)$(DRIVER_DIR)/arch-$(CONFIG) ] && [ -f $(TOP_KBUILD_SRC)$(DRIVER_DIR)/arch-$(CONFIG)/config.h ] && echo "OK"), OK)
-$(warning Current directory is $(shell pwd))
-$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists)
-else
-# Link arch to the selected arch-config directory
-$(shell [ -L $(TOP_KBUILD_SRC)$(DRIVER_DIR)/arch ] && rm $(TOP_KBUILD_SRC)$(DRIVER_DIR)/arch)
-$(shell ln -sf arch-$(CONFIG) $(TOP_KBUILD_SRC)$(DRIVER_DIR)/arch)
-$(shell touch $(TOP_KBUILD_SRC)$(DRIVER_DIR)/arch/config.h)
-endif
-
-# Set up our defines, which will be passed to gcc
-DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY)
-DEFINES += -DUSING_MMU=1
-DEFINES += -DUSING_UMP=$(USING_UMP)
-DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP
-DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING)
-DEFINES += -DDISABLE_PP0=$(DISABLE_PP0)
-DEFINES += -DDISABLE_PP1=$(DISABLE_PP1)
-DEFINES += -DDISABLE_PP2=$(DISABLE_PP2)
-DEFINES += -DDISABLE_PP3=$(DISABLE_PP3)
-DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS)
-DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS)
-DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH)
-
-DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP)
-DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED)
-DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS)
-DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING)
-DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE)
-ifeq ($(shell test $(SUBLEVEL) -gt 32 -a $(PATCHLEVEL) = 6 -a $(VERSION) = 2 -o $(VERSION) -gt 2 && echo "OK"),OK)
-# MALI_STATE_TRACKING is only supported on Linux kernels from version 2.6.32.
-DEFINES += -DMALI_STATE_TRACKING=1
-else
-DEFINES += -DMALI_STATE_TRACKING=0
-endif
-DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
-
-MALI_PLATFORM_FILE = platform/$(TARGET_PLATFORM)/mali_platform.c platform/$(TARGET_PLATFORM)/mali_fix.c
-
-
-ifdef CONFIG_PM
-ifdef CONFIG_PM_RUNTIME
-       KERNEL_RUNTIME_PM_ENABLED = 1
-endif
-endif
-
-DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(KERNEL_RUNTIME_PM_ENABLED)
-
-ifeq ($(BUILD), debug)
-DEFINES += -DDEBUG
-endif
-DEFINES += -DSVN_REV=$(SVN_REV)
-DEFINES += -DSVN_REV_STRING=\"$(SVN_REV)\"
-
-# Linux has its own mmap cleanup handlers (see mali_kernel_memory.c)
-DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP
-
-ifeq ($(USING_UMP),1)
-       DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1
-       ccflags-y += -I$(TOP_KBUILD_SRC)$(DRIVER_DIR)/../ump/include/ump
-else
-       DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0
-endif
-
-# Use our defines when compiling
-ccflags-y += $(DEFINES) -I$(TOP_KBUILD_SRC)$(DRIVER_DIR) -I$(DRIVER_DIR)/include -I$(DRIVER_DIR)/common -I$(DRIVER_DIR)/linux -I$(DRIVER_DIR)/platform
-
-# Source files which always are included in a build
-SRC = \
-       common/mali_kernel_core.c \
-       linux/mali_kernel_linux.c \
-       common/mali_kernel_descriptor_mapping.c \
-       common/mali_session.c \
-       common/mali_device_pause_resume.c \
-       common/mali_kernel_vsync.c \
-       linux/mali_ukk_vsync.c \
-       linux/mali_kernel_sysfs.c \
-       common/mali_mmu.c \
-       common/mali_mmu_page_directory.c \
-       common/mali_memory.c \
-       common/mali_kernel_memory_engine.c \
-       common/mali_block_allocator.c \
-       common/mali_kernel_mem_os.c \
-       common/mali_mem_validation.c \
-       common/mali_hw_core.c \
-       common/mali_gp.c \
-       common/mali_pp.c \
-       common/mali_pp_job.c \
-       common/mali_gp_job.c \
-       common/mali_scheduler.c \
-       common/mali_gp_scheduler.c \
-       common/mali_pp_scheduler.c \
-       common/mali_cluster.c \
-       common/mali_group.c \
-       common/mali_dlbu.c \
-       common/mali_pm.c \
-       common/mali_pmu.c \
-       common/mali_user_settings_db.c \
-       $(OSKOS)/mali_osk_pm.c \
-       linux/mali_kernel_pm.c \
-       linux/mali_pmu_power_up_down.c \
-       $(MALI_PLATFORM_FILE) \
-       $(OSKFILES) \
-       $(UKKFILES) \
-       __malidrv_build_info.c
-
-# Selecting files to compile by parsing the config file
-ifeq ($(USING_PROFILING),1)
-SRC += \
-    linux/mali_osk_profiling.c
-
-ifeq ($(USING_INTERNAL_PROFILING),1)
-SRC += \
-    linux/mali_profiling_internal.c \
-    timestamp-$(TIMESTAMP)/mali_timestamp.c
-ccflags-y += -I$(TOP_KBUILD_SRC)$(DRIVER_DIR)/timestamp-$(TIMESTAMP)
-endif
-endif
-
-ifeq ($(USING_MALI_PMM_TESTSUITE),1)
-ccflags-y += -I$(TOP_KBUILD_SRC)$(DRIVER_DIR)/platform/mali_pmu_testing
-endif
-
-mali-$(CONFIG_MALI400_GPU_UTILIZATION) += common/mali_kernel_utilization.o
-mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_dma_buf.o
-
-ifneq ($(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALI400PP),0)
-       # Mali-400 PP in use
-       ccflags-y += -DUSING_MALI400
-endif
-
-ifneq ($(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALI300PP),0)
-       # Mali-400 PP in use
-       ccflags-y += -DUSING_MALI400
-endif
-
-ifneq ($(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALI200),0)
-       # Mali200 in use
-       ccflags-y += -DUSING_MALI200
-endif
-
-# Always build in support for Mali L2 cache
-SRC += common/mali_l2_cache.c
-
-# Tell the Linux build system to enable building of our .c files
-mali-y += $(SRC:.c=.o)
-# Tell the Linux build system from which .o file to create the kernel module
-obj-$(CONFIG_MALI400) := mali.o
-
+ccflags-y += -DSVN_REV_STRING=\"$(SVN_REV)\"
 
 VERSION_STRINGS :=
-VERSION_STRINGS += CONFIG=$(CONFIG)
-VERSION_STRINGS += USING_OS_MEMORY=$(USING_OS_MEMORY)
-VERSION_STRINGS += API_VERSION=$(shell cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 )
-VERSION_STRINGS += REPO_URL=$(shell cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); (svn info || git svn info || echo 'URL: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^URL: ' | cut -d: -f2- | cut -b2-)
+VERSION_STRINGS += API_VERSION=$(shell cd $(TOP_KBUILD_SRC)$(DRIVER_DIR);  grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 )
+VERSION_STRINGS += REPO_URL=$(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-)
 VERSION_STRINGS += REVISION=$(SVN_REV)
-VERSION_STRINGS += CHANGED_REVISION=$(shell cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Rev: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-)
-VERSION_STRINGS += CHANGE_DATE=$(shell cd $(TOP_KBUILD_SRC)$(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Date: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-)
+VERSION_STRINGS += CHANGED_REVISION=$(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-)
+VERSION_STRINGS += CHANGE_DATE=$(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-)
 VERSION_STRINGS += BUILD_DATE=$(shell date)
-
-VERSION_STRINGS += BUILD=$(shell echo $(BUILD) | tr a-z A-Z)
-VERSION_STRINGS += CPU=$(CPU)
-VERSION_STRINGS += USING_UMP=$(USING_UMP)
-VERSION_STRINGS += USING_MALI200=$(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALI200)
-VERSION_STRINGS += USING_MALI400=$(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALI400)
-VERSION_STRINGS += USING_MALI400_L2_CACHE=$(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALI400L2)
-VERSION_STRINGS += USING_GP2=$(call submodule_enabled, $(TOP_KBUILD_SRC)$(DRIVER_DIR), MALIGP2)
+ifdef CONFIG_MALI400_DEBUG
+VERSION_STRINGS += BUILD=debug
+else
+VERSION_STRINGS += BUILD=release
+endif
+VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM)
+VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM)
 VERSION_STRINGS += KDIR=$(KDIR)
-VERSION_STRINGS += MALI_PLATFORM_FILE=$(MALI_PLATFORM_FILE)
 VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
-VERSION_STRINGS += USING_PROFILING=$(USING_PROFILING)
-VERSION_STRINGS += USING_INTERNAL_PROFILING=$(USING_INTERNAL_PROFILING)
-VERSION_STRINGS += USING_GPU_UTILIZATION=$(CONFIG_MALI400_GPU_UTILIZATION)
+VERSION_STRINGS += USING_UMP=$(CONFIG_MALI400_UMP)
+VERSION_STRINGS += USING_PROFILING=$(CONFIG_MALI400_PROFILING)
+VERSION_STRINGS += USING_INTERNAL_PROFILING=$(CONFIG_MALI400_INTERNAL_PROFILING)
+VERSION_STRINGS += USING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION)
 
 # Create file with Mali driver configuration
 $(TOP_KBUILD_SRC)$(DRIVER_DIR)/__malidrv_build_info.c:
index 810746ae9fe29b3f40b5d962fe9fc47fea926561..747fe3742ed5d64db66ab55fda4a64f593f4d8a1 100644 (file)
@@ -1,22 +1,22 @@
 menu "Mali GPU OpenGL device driver"
 config MALI400
-       tristate "Mali support"
+       tristate "Mali-300/400/450 support"
+       depends on ARM
        depends on m
        default m
-       select FB
+       select DMA_SHARED_BUFFER
        ---help---
-         This enables support for the Mali-300, Mali-400, and Mali-450 GPUs.
+         This enables support for the ARM Mali-300, Mali-400, and Mali-450
+         GPUs.
 
          To compile this driver as a module, choose M here: the module will be
          called mali.
 
-
 config MALI400_DEBUG
        bool "Enable debug in Mali driver"
        depends on MALI400
        ---help---
-         This enabled extra debug checks and messages in the Mali-300/400/450
-         driver.
+         This enabled extra debug checks and messages in the Mali driver.
 
 if !PROFILING || !FTRACE
 comment "ARM mali streamline with gator is depends on CONFIG_FTRACE and PROFILING."
@@ -38,12 +38,17 @@ config MALI400_PROFILING
        ---help---
          This enables gator profiling of Mali GPU events.
 
-config MALI400_GPU_UTILIZATION
-       bool "Enable Mali GPU utilization tracking"
+config MALI400_INTERNAL_PROFILING
+       bool "Enable internal Mali profiling API"
+       depends on MALI400_PROFILING
+       default n
+       ---help---
+         This enables the internal legacy Mali profiling API.
+
+config MALI400_UMP
+       bool "Enable UMP support"
        depends on MALI400
        ---help---
-         This enables gathering and processing of the utilization of Mali GPU.
-         This data can be used as a basis to change GPU operating frequency.
-         
+         This enables support for the UMP memory sharing API in the Mali driver.         
 endmenu
 
index 506af783c2204b1386580360e0de7fe334c03ddc..8deb4efd0f1f2347196085b46fb2673386303c46 100644 (file)
@@ -1,21 +1,16 @@
 #
-# 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.
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2007-2012 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
 #
 
-# KDIR not set when included by modpost
-ifneq ($(KBUILD_EXTMOD),)
-       ifeq ($(KDIR),)
-               KDIR := $(KBUILD_SRC)
-       endif
-endif
-
 USE_UMPV2=0
+USING_PROFILING ?= 1
+USING_INTERNAL_PROFILING ?= 0
 
 # The Makefile sets up "arch" based on the CONFIG, creates the version info
 # string and the __malidrv_build_info.c file, and then call the Linux build
@@ -28,18 +23,46 @@ ARCH ?= arm
 OSKOS=linux
 FILES_PREFIX=
 
+check_cc2 = \
+       $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \
+       then \
+               echo "$(2)"; \
+       else \
+               echo "$(3)"; \
+       fi ;)
+
 # This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak
 -include ../../../arm_internal.mak
 
-# Check that required parameters are supplied.
-ifeq ($(CONFIG),)
-$(error "CONFIG must be specified.")
+# Give warning of old config parameters are used
+ifneq ($(CONFIG),)
+$(warning "You have specified the CONFIG variable which is no longer in used. Use TARGET_PLATFORM instead.")
+endif
+
+ifneq ($(CPU),)
+$(warning "You have specified the CPU variable which is no longer in used. Use TARGET_PLATFORM instead.")
+endif
+
+# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM
+-include MALI_CONFIGURATION
+export KDIR ?= $(KDIR-$(TARGET_PLATFORM))
+export MALI_PLATFORM ?= $(MALI_PLATFORM-$(TARGET_PLATFORM))
+
+ifneq ($(TARGET_PLATFORM),)
+ifeq ($(MALI_PLATFORM),)
+$(error "Invalid TARGET_PLATFORM: $(TARGET_PLATFORM)")
 endif
-ifeq ($(CPU)$(KDIR),)
-$(error "KDIR or CPU must be specified.")
 endif
 
+# validate lookup result
+ifeq ($(KDIR),)
+$(error No KDIR found for platform $(TARGET_PLATFORM))
+endif
+
+
 ifeq ($(USING_UMP),1)
+export CONFIG_MALI400_UMP=y
+export EXTRA_DEFINES += -DCONFIG_MALI400_UMP=1
 ifeq ($(USE_UMPV2),1)
 UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers
 else
@@ -49,38 +72,46 @@ KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE))
 $(warning $(KBUILD_EXTRA_SYMBOLS))
 endif
 
-# Get any user defined KDIR-<names> or maybe even a hardcoded KDIR
--include KDIR_CONFIGURATION
-
 # Define host system directory
 KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build
 
-ifeq ($(ARCH), arm)
-       # when compiling for ARM we're cross compiling
-       export CROSS_COMPILE ?= arm-none-eabi-
-endif
+include $(KDIR)/.config
 
-# look up KDIR based om CPU selection
-KDIR ?= $(KDIR-$(CPU))
-
-# validate lookup result
-ifeq ($(KDIR),)
-$(error No KDIR found for platform $(CPU))
+ifeq ($(ARCH), arm)
+# when compiling for ARM we're cross compiling
+export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-)
 endif
 
 # report detected/selected settings
 ifdef ARM_INTERNAL_BUILD
-$(warning Config $(CONFIG))
-$(warning Host CPU $(CPU))
-$(warning OS_MEMORY $(USING_OS_MEMORY))
+$(warning TARGET_PLATFORM $(TARGET_PLATFORM))
+$(warning KDIR $(KDIR))
+$(warning MALI_PLATFORM $(MALI_PLATFORM))
 endif
 
 # Set up build config
 export CONFIG_MALI400=m
 
-ifeq ($(USING_GPU_UTILIZATION),1)
-export EXTRA_DEFINES += -DCONFIG_MALI400_GPU_UTILIZATION=1
-export CONFIG_MALI400_GPU_UTILIZATION := y
+ifneq ($(MALI_PLATFORM),)
+export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1
+export MALI_PLATFORM_FILES = $(wildcard platform/$(MALI_PLATFORM)/*.c)
+endif
+
+ifeq ($(USING_PROFILING),1)
+ifeq ($(CONFIG_TRACEPOINTS),)
+$(warning CONFIG_TRACEPOINTS reqired for profiling)
+else
+export CONFIG_MALI400_PROFILING=y
+export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1
+ifeq ($(USING_INTERNAL_PROFILING),1)
+export CONFIG_MALI400_INTERNAL_PROFILING=y
+export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1
+endif
+endif
+endif
+
+ifneq ($(BUILD),release)
+export CONFIG_MALI400_DEBUG=y
 endif
 
 all: $(UMP_SYMVERS_FILE)
index 269e662d818a4ae1fad918dddfe1b8491df3f868..0a467c0cb7519619365388eee988ee9ef003aeef 100644 (file)
@@ -1,14 +1,13 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include "mali_kernel_common.h"
-#include "mali_kernel_core.h"
 #include "mali_kernel_memory_engine.h"
 #include "mali_block_allocator.h"
 #include "mali_osk.h"
index 6c6f13eec34aa2e7d4b8f0c6e25c8e60e825ce64..141719b420f369b9b18cf0625a42ce28d8d7d83f 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_BLOCK_ALLOCATOR_H__
diff --git a/mali/common/mali_broadcast.c b/mali/common/mali_broadcast.c
new file mode 100644 (file)
index 0000000..e9338ee
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/*
+ *  Interface for the broadcast unit on Mali-450
+ *
+ * - Represents up to 8 Ã— (MMU + PP) pairs
+ * - Supports dynamically changing which (MMU + PP) pairs that it broadcasts to
+ *   by setting a mask.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_broadcast.h"
+
+struct mali_bcast_unit
+{
+       struct mali_hw_core hw_core;
+       u32 current_mask;
+};
+
+struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t * resource)
+{
+       struct mali_bcast_unit* bcast_unit = NULL;
+
+       MALI_DEBUG_PRINT(2, ("Mali Broadcast unit: Creating Mali Broadcast unit: %s\n", resource->description));
+
+       bcast_unit = _mali_osk_malloc(sizeof(struct mali_bcast_unit));
+       if (_MALI_OSK_ERR_OK == mali_hw_core_create(&bcast_unit->hw_core, resource, 0x1000))
+       {
+               bcast_unit->current_mask = 0;
+               mali_bcast_reset(bcast_unit);
+
+               return bcast_unit;
+       }
+       else
+       {
+               MALI_PRINT_ERROR(("Mali Broadcast unit: Failed to allocate memory for Broadcast unit\n"));
+       }
+
+       return NULL;
+}
+
+void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit)
+{
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+
+       mali_hw_core_delete(&bcast_unit->hw_core);
+       _mali_osk_free(bcast_unit);
+}
+
+/* Add a group to the list of (PP + MMU) pairs broadcasts go out to */
+void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group)
+{
+       u32 core_id;
+       u32 broadcast_mask;
+
+       MALI_DEBUG_ASSERT_POINTER( bcast_unit );
+       MALI_DEBUG_ASSERT_POINTER( group );
+
+       core_id = mali_pp_core_get_id(mali_group_get_pp_core(group));
+       broadcast_mask = bcast_unit->current_mask;
+
+       /* Set the bit corresponding to the group's core's id to 1 */
+       core_id = 1 << core_id;
+       broadcast_mask |= (core_id); /* Add PP core to broadcast */
+       broadcast_mask |= (core_id << 16); /* Add MMU to broadcast */
+
+       /* store mask so we can restore on reset */
+       bcast_unit->current_mask = broadcast_mask;
+
+       mali_bcast_reset(bcast_unit);
+}
+
+/* Remove a group to the list of (PP + MMU) pairs broadcasts go out to */
+void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group)
+{
+       u32 core_id;
+       u32 broadcast_mask;
+
+       MALI_DEBUG_ASSERT_POINTER( bcast_unit );
+       MALI_DEBUG_ASSERT_POINTER( group );
+
+       core_id = mali_pp_core_get_id(mali_group_get_pp_core(group));
+       broadcast_mask = bcast_unit->current_mask;
+
+       /* set the bit corresponding to the group's core's id to 0 */
+       core_id = 1 << core_id;
+       broadcast_mask &= ~((core_id << 16) | core_id);
+
+       /* store mask so we can restore on reset */
+       bcast_unit->current_mask = broadcast_mask;
+
+       mali_bcast_reset(bcast_unit);
+}
+
+/* Re-set cached mask. This needs to be called after having been suspended */
+void mali_bcast_reset(struct mali_bcast_unit *bcast_unit)
+{
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+
+       mali_hw_core_register_write(&bcast_unit->hw_core, 0, bcast_unit->current_mask); /* Set broadcast mask */
+       mali_hw_core_register_write(&bcast_unit->hw_core, 0x4, bcast_unit->current_mask & 0xFF); /* Set IRQ override mask */
+}
+
+void mali_bcast_print(struct mali_bcast_unit *bcast_unit)
+{
+       MALI_DEBUG_PRINT(2,("Broadcast mask 0x%02x\n", bcast_unit->current_mask & 0xFF));
+}
diff --git a/mali/common/mali_broadcast.h b/mali/common/mali_broadcast.h
new file mode 100644 (file)
index 0000000..0ac3544
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_hw_core.h"
+#include "mali_group.h"
+
+struct mali_bcast_unit;
+
+struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t * resource);
+void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit);
+
+void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group);
+void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group);
+
+void mali_bcast_reset(struct mali_bcast_unit *bcast_unit);
+
+void mali_bcast_print(struct mali_bcast_unit *bcast_unit);
index 6af12790d6c1b7f7ec38103ed12d971314a1e098..f8368ebefd592ff460be78e8f4ad76cf6d3df340 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
 
 #include "mali_gp_scheduler.h"
 #include "mali_pp_scheduler.h"
-#include "mali_pm.h"
+#include "mali_group.h"
 
 void mali_dev_pause(mali_bool *power_is_on)
 {
-       mali_gp_scheduler_suspend();
-       mali_pp_scheduler_suspend();
+       mali_bool power_is_on_tmp;
 
-       /*
-        * 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();    
+       /* Locking the current power state - so it will not switch from being ON to OFF, but it might remain OFF */
+       power_is_on_tmp = _mali_osk_pm_dev_ref_add_no_power_on();
        if (NULL != power_is_on)
        {
-               *power_is_on = mali_pm_is_powered_on();
+               *power_is_on = power_is_on_tmp;
        }
+
+       mali_gp_scheduler_suspend();
+       mali_pp_scheduler_suspend();
 }
 
 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);
-*/
+       /* Release our PM reference, as it is now safe to turn of the GPU again */
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+}
index 6be75b0510f3424f375167ae69378c709e3a5bd9..a5df14b30a1fefa4a62ecc11fbe8e4a2f484f0e1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_DEVICE_PAUSE_RESUME_H__
index fcc51fac694a45faa5b3d753d9e4383da548708b..7dfb5652c6a9336baeb2efc835feb014ec9e61d0 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_dlbu.h"
@@ -23,8 +23,6 @@
 u32 mali_dlbu_phys_addr = 0;
 static mali_io_address mali_dlbu_cpu_addr = 0;
 
-static u32 mali_dlbu_tile_position;
-
 /**
  * DLBU register numbers
  * Used in the register read/write routines.
@@ -86,7 +84,7 @@ struct mali_dlbu_core
 _mali_osk_errcode_t mali_dlbu_initialize(void)
 {
 
-       MALI_DEBUG_PRINT(2, ("Dynamic Load Balancing Unit initializing\n"));
+       MALI_DEBUG_PRINT(2, ("Mali DLBU: Initializing\n"));
 
        if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr))
        {
@@ -114,10 +112,9 @@ struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
        {
                if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE))
                {
+                       core->pp_cores_mask = 0;
                        if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core))
                        {
-                               mali_hw_core_register_write(&core->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR, MALI_DLB_VIRT_ADDR);
-
                                return core;
                        }
                        MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description));
@@ -136,150 +133,81 @@ struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
 
 void mali_dlbu_delete(struct mali_dlbu_core *dlbu)
 {
+       MALI_DEBUG_ASSERT_POINTER(dlbu);
+
        mali_dlbu_reset(dlbu);
        mali_hw_core_delete(&dlbu->hw_core);
        _mali_osk_free(dlbu);
 }
 
-void mali_dlbu_enable(struct mali_dlbu_core *dlbu)
-{
-       u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR);
-
-       wval |= 0x1;
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval);
-}
-
-void mali_dlbu_disable(struct mali_dlbu_core *dlbu)
-{
-       u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR);
-
-       wval |= (wval & 0xFFFFFFFE);
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval);
-}
-
-_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val)
-{
-       u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK);
-
-       if((pp_core_enable < mali_pp_get_glob_num_pp_cores()) && ((0 == val) || (1 == val))) /* check for valid input parameters */
-       {
-               if (val == 1)
-               {
-                       val = (wval | (pp_core_enable <<= 0x1));
-               }
-               if (val == 0)
-               {
-                       val = (wval & ~(pp_core_enable << 0x1));
-               }
-               wval |= val;
-               mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, wval);
-               dlbu->pp_cores_mask = wval;
-
-               return _MALI_OSK_ERR_OK;
-       }
-
-       return _MALI_OSK_ERR_FAULT;
-}
-
-void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu)
-{
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
-}
-
-void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu)
-{
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, 0x0);
-}
-
-void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1)
-{
-       u32 wval = 0x0;
-
-       /* write the framebuffer dimensions */
-       wval = (16 << (u32)fb_ydim) | (u32)fb_xdim;
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, wval);
-
-       /* write the tile list configuration */
-       wval = 0x0;
-       wval = (28 << (u32)blocksize) | (16 << (u32)ytilesize) | ((u32)xtilesize);
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, wval);
-
-       /* write the start tile position */
-       wval = 0x0;
-       wval = (24 << (u32)ygr1 | (16 << (u32)xgr1) | 8 << (u32)ygr0) | (u32)xgr0;
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, wval);
-}
-
 _mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu)
 {
+       u32 dlbu_registers[7];
        _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
        MALI_DEBUG_ASSERT_POINTER(dlbu);
 
        MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description));
 
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, mali_dlbu_phys_addr);
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, 0x00);
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, 0x00);
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, 0x00);
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, 0x00);
+       dlbu_registers[0] = mali_dlbu_phys_addr | 1; /* bit 0 enables the whole core */
+       dlbu_registers[1] = MALI_DLBU_VIRT_ADDR;
+       dlbu_registers[2] = 0;
+       dlbu_registers[3] = 0;
+       dlbu_registers[4] = 0;
+       dlbu_registers[5] = 0;
+       dlbu_registers[6] = dlbu->pp_cores_mask;
 
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
+       /* write reset values to core registers */
+       mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, dlbu_registers, 7);
 
        err = _MALI_OSK_ERR_OK;
 
        return err;
 }
 
-_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
+void mali_dlbu_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);
+       struct mali_pp_core *pp_core;
+       u32 core_id;
 
-       /* find the core id and set the mask */
+       MALI_DEBUG_ASSERT_POINTER( dlbu );
+       MALI_DEBUG_ASSERT_POINTER( group );
 
-       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;
-       }
+       pp_core = mali_group_get_pp_core(group);
+       core_id = mali_pp_core_get_id(pp_core);
 
-       return err;
-}
+       dlbu->pp_cores_mask |= (0x1 << core_id);
+       MALI_DEBUG_PRINT(3, ("Mali DLB: Adding core[%d] New mask= 0x%02x\n",core_id , dlbu->pp_cores_mask));
 
-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);
+       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
 }
 
-void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu)
+/* Remove a group to the list of (PP + MMU) pairs dlb go out to */
+void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
 {
-       /* this function to implement (see documentation):
-        * 1) clear all bits in the enable register
-        * 2) wait until all PPs have finished - mali_pp_scheduler.c code - this done in interrupts call?
-        * 3) read the current tile position registers to get current tile positions -
-        * note that current tile position register is the same as start tile position - perhaps the name should be changed!!! */
+       struct mali_pp_core *pp_core;
+       u32 core_id;
+
+       MALI_DEBUG_ASSERT_POINTER( dlbu );
+       MALI_DEBUG_ASSERT_POINTER( group );
 
-       /* 1) */
-       mali_dlbu_disable_all_pp_cores(dlbu);
+       pp_core = mali_group_get_pp_core(group);
+       core_id = mali_pp_core_get_id(pp_core);
 
-       /* 3) */
-       mali_dlbu_tile_position = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS);
+       dlbu->pp_cores_mask &= ~(0x1 << core_id);
+               MALI_DEBUG_PRINT(3, ("Mali DLB: Removing core[%d] New mask= 0x%02x\n", core_id, dlbu->pp_cores_mask));
+
+       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
 }
 
-void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu)
+void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job)
 {
-       /* this function to implement (see the document):
-        * 1) configure the dynamic load balancing unit as normal
-        * 2) set the current tile position registers as read when stopping the job
-        * 3) configure the PPs to start the job as normal - done by another part of the system - scheduler */
+       u32 *registers;
+       MALI_DEBUG_ASSERT(job);
+       registers = mali_pp_job_get_dlbu_registers(job);
+       MALI_DEBUG_PRINT(4, ("Mali DLBU: Starting job\n"));
 
-       /* 1) */
-       mali_dlbu_reset(dlbu);
-       /* ++ setup the needed values - see this */
+       /* Writing 4 registers:
+        * DLBU registers except the first two (written once at DLBU initialisation / reset) and the PP_ENABLE_MASK register */
+       mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4);
 
-       /* 2)  */
-       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, mali_dlbu_tile_position);
 }
index e3c3b9db9775899d7818fcf88f72219d1f952281..111b15642e527fc51860fa6ebf1917d6f3a07d79 100644 (file)
@@ -1,20 +1,22 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_DLBU_H__
 #define __MALI_DLBU_H__
 
+#define MALI_DLBU_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */
+
 #include "mali_osk.h"
-#include "mali_group.h"
 
-#define MALI_DLB_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */
+struct mali_pp_job;
+struct mali_group;
 
 extern u32 mali_dlbu_phys_addr;
 
@@ -26,20 +28,11 @@ void mali_dlbu_terminate(void);
 struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource);
 void mali_dlbu_delete(struct mali_dlbu_core *dlbu);
 
-void mali_dlbu_enable(struct mali_dlbu_core *dlbu);
-void mali_dlbu_disable(struct mali_dlbu_core *dlbu);
-
-_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val);
-void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu);
-void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu);
-
 _mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu);
-void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1);
 
-_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group);
-void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val);
+void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group);
+void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group);
 
-void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu);
-void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu);
+void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job);
 
 #endif /* __MALI_DLBU_H__ */
index 2110471c1a4345f5174551d60b4848a201420dbd..4ef4e62956a884acdea5e05565efca0754d2c58b 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_gp.h"
 #include "regs/mali_gp_regs.h"
 #include "mali_kernel_common.h"
 #include "mali_kernel_core.h"
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
 #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)
 {
@@ -58,37 +35,29 @@ struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struc
        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)
+                               ret = mali_group_add_gp_core(group, core);
+                               if (_MALI_OSK_ERR_OK == ret)
                                {
-                                       /* Initialise the timeout timer */
-                                       core->timeout_timer = _mali_osk_timer_init();
-                                       if(NULL != core->timeout_timer)
+                                       /* Setup IRQ handlers (which will do IRQ probing if needed) */
+                                       core->irq = _mali_osk_irq_init(resource->irq,
+                                                                      mali_group_upper_half_gp,
+                                                                      group,
+                                                                      mali_gp_irq_probe_trigger,
+                                                                      mali_gp_irq_probe_ack,
+                                                                      core,
+                                                                      "mali_gp_irq_handlers");
+                                       if (NULL != core->irq)
                                        {
-                                               _mali_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;
 
@@ -96,14 +65,13 @@ struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struc
                                        }
                                        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);
+                                               MALI_PRINT_ERROR(("Mali GP: Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
                                        }
+                                       mali_group_remove_gp_core(group);
                                }
                                else
                                {
-                                       MALI_PRINT_ERROR(("Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
+                                       MALI_PRINT_ERROR(("Mali GP: Failed to add core %s to group\n", core->hw_core.description));
                                }
                        }
                        mali_hw_core_delete(&core->hw_core);
@@ -123,7 +91,6 @@ 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;
@@ -140,7 +107,6 @@ void mali_gp_stop_bus(struct mali_gp_core *core)
 _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);
 
@@ -148,16 +114,15 @@ _mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core)
        mali_gp_stop_bus(core);
 
        /* Wait for bus to be stopped */
-       for (i = 0; i < request_loop_count; i++)
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
        {
                if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED)
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(10);
        }
 
-       if (request_loop_count == i)
+       if (MALI_REG_POLL_COUNT_FAST == i)
        {
                MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description));
                return _MALI_OSK_ERR_FAULT;
@@ -167,7 +132,6 @@ _mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core)
 
 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;
@@ -176,15 +140,12 @@ void mali_gp_hard_reset(struct mali_gp_core *core)
 
        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++)
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
        {
                mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value);
                if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register))
@@ -193,7 +154,7 @@ void mali_gp_hard_reset(struct mali_gp_core *core)
                }
        }
 
-       if (i == reset_finished_loop_count)
+       if (MALI_REG_POLL_COUNT_FAST == i)
        {
                MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n"));
        }
@@ -205,67 +166,40 @@ 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_reset_async(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_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description));
 
        mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
 
-#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_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core)
+{
+       int i;
+       u32 rawstat = 0;
 
-       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
-       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
+       MALI_DEBUG_ASSERT_POINTER(core);
 
-       for (i = 0; i < request_loop_count; i++)
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
        {
-               if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED)
+               rawstat = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT);
+               if (rawstat & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED)
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(10);
        }
 
-       if (request_loop_count == i)
+       if (i == MALI_REG_POLL_COUNT_FAST)
        {
-               MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, unable to recover\n", core->hw_core.description));
+               MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, rawstat: 0x%08x\n",
+                                core->hw_core.description, rawstat));
                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);
@@ -274,15 +208,21 @@ _mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core)
        return _MALI_OSK_ERR_OK;
 }
 
+_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core)
+{
+       mali_gp_reset_async(core);
+       return mali_gp_reset_wait(core);
+}
+
 void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job)
 {
        u32 startcmd = 0;
        u32 *frame_registers = mali_gp_job_get_frame_registers(job);
-       core->counter_src0_used = core->counter_src0;
-       core->counter_src1_used = core->counter_src1;
+
+       core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job);
+       core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job);
 
        MALI_DEBUG_ASSERT_POINTER(core);
-       MALI_ASSERT_GROUP_LOCKED(core->group);
 
        if (mali_gp_job_has_vs_job(job))
        {
@@ -298,49 +238,15 @@ void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job)
 
        mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME);
 
-#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH
-       {
-               /* Read hits and Read misses*/
-               mali_l2_cache_core_set_counter_src0(mali_l2_cache_core_get_glob_l2_core(0), 20);
-               mali_l2_cache_core_set_counter_src1(mali_l2_cache_core_get_glob_l2_core(0), 21);
-       }
-#endif
-
-       /* This selects which performance counters we are reading */
-       if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+       if (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);
-               }
+               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);
        }
-       else
+       if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
        {
-               /* 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_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));
@@ -353,19 +259,6 @@ void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job)
 
        /* 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,
-                                     mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0);
-       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0);
-#endif
-
-       core->running_job = job;
 }
 
 void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr)
@@ -373,7 +266,6 @@ void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32
        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);
 
@@ -388,10 +280,6 @@ void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32
 
                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.
@@ -399,195 +287,23 @@ void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32
         */
 }
 
-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
-       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0);
-#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);
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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 */
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-                       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 */
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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;
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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 */
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               return;
-       }
-       else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG)
-       {
-               /* we mask hang interrupts, so this should never happen... */
-               MALI_DEBUG_ASSERT( 0 );
-       }
-
-       /* The only way to get here is if we only got one of two needed END_CMD_LST
-        * interrupts. Disable the interrupt that has been received and continue to
-        * run. */
-       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK,
-                       MALIGP2_REG_VAL_IRQ_MASK_USED &
-                       ((irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)
-                       ? ~MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST
-                       : ~MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST
-                       ));
-       mali_group_unlock(core->group);
-
-#if MALI_TIMELINE_PROFILING_ENABLED
-       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#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_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
        mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG);
        _mali_osk_mem_barrier();
 }
@@ -609,153 +325,40 @@ static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data)
 }
 
 /* ------ local helper functions below --------- */
-
-static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend)
+#if MALI_STATE_TRACKING
+u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size)
 {
-       MALI_ASSERT_GROUP_LOCKED(core->group);
-
-       if (NULL != core->running_job)
-       {
-               u32 val0 = 0;
-               u32 val1 = 0;
-#if MALI_TIMELINE_PROFILING_ENABLED
-               u32 event_id;
-#endif
-
-#if PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH
-       {
-               u32 src0, value0, src1, value1, sum, per_thousand, per_thousand_now, diff0, diff1;
-               static u32 print_nr=0;
-               static u32 prev0=0;
-               static u32 prev1=0;
-               if ( !(++print_nr&511) )
-               {
-                       mali_l2_cache_core_get_counter_values(mali_l2_cache_core_get_glob_l2_core(0), &src0, &value0, &src1, &value1);
-                       MALI_DEBUG_ASSERT( src0==20 ); /* Read hits */
-                       MALI_DEBUG_ASSERT( src1==21 ); /* Read misses */
-
-                       sum = value0+value1;
-                       if ( sum > 1000000 )
-                       {
-                               per_thousand = value0 / (sum/1000);
-                       }
-                       else
-                       {
-                               per_thousand = (value0*1000) / (sum);
-                       }
-                       diff0 = value0-prev0;
-                       diff1 = value1-prev1;
-
-                       sum = diff0 + diff1 ;
-                       if ( sum > 1000000 )
-                       {
-                               per_thousand_now = diff0 / (sum/1000);
-                       }
-                       else
-                       {
-                               per_thousand_now = (diff0*1000) / (sum);
-                       }
-
-                       prev0=value0;
-                       prev1=value1;
-                       if (per_thousand_now<=1000)
-                       {
-                               MALI_DEBUG_PRINT(2, ("Mali L2: Read hits/misses:  %d/%d  =  %d thousand_parts total, since previous: %d\n", value0, value1, per_thousand, per_thousand_now));
-                       }
-
-               }
-       }
-#endif
+       int n = 0;
 
-               if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
-               {
-                       val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
-                       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);
-                       }
+       n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description);
 
-#if MALI_TIMELINE_PROFILING_ENABLED
-                       _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0);
+       return n;
+}
 #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);
-                       }
+void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend)
+{
+       u32 val0 = 0;
+       u32 val1 = 0;
 
-#if MALI_TIMELINE_PROFILING_ENABLED
-                       _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1);
-#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);
+               mali_gp_job_set_perf_counter_value0(job, val0);
 
-#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);
+#if defined(CONFIG_MALI400_PROFILING)
+               _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0);
 #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 (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+       {
+               val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+               mali_gp_job_set_perf_counter_value1(job, val1);
 
-#if 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) ));
-}
+#if defined(CONFIG_MALI400_PROFILING)
+               _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1);
 #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
index 3175b7548acb724699cf089e637bdde455aadb15..f3f6e3d3ceb3cbe2ec9d1d533f8ebff931d6a5ef 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_GP_H__
 
 #include "mali_osk.h"
 #include "mali_gp_job.h"
+#include "mali_hw_core.h"
+#include "regs/mali_gp_regs.h"
 
-struct mali_gp_core;
 struct mali_group;
 
+/**
+ * Definition of the GP core struct
+ * Used to track a GP core in the system.
+ */
+struct mali_gp_core
+{
+       struct mali_hw_core  hw_core;           /**< Common for all HW cores */
+       _mali_osk_irq_t     *irq;               /**< IRQ handler */
+       u32                  counter_src0_used; /**< The selected performance counter 0 when a job is running */
+       u32                  counter_src1_used; /**< The selected performance counter 1 when a job is running */
+};
+
 _mali_osk_errcode_t mali_gp_initialize(void);
 void mali_gp_terminate(void);
 
@@ -25,22 +38,59 @@ void mali_gp_delete(struct mali_gp_core *core);
 
 void mali_gp_stop_bus(struct mali_gp_core *core);
 _mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core);
+void mali_gp_reset_async(struct mali_gp_core *core);
+_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core);
 void mali_gp_hard_reset(struct mali_gp_core *core);
 _mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core);
 
 void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job);
 void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr);
 
-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);
 
+void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend);
+
+/*** Accessor functions ***/
+MALI_STATIC_INLINE const char *mali_gp_get_hw_core_desc(struct mali_gp_core *core)
+{
+       return core->hw_core.description;
+}
+
+/*** Register reading/writing functions ***/
+MALI_STATIC_INLINE u32 mali_gp_get_int_stat(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+}
+
+MALI_STATIC_INLINE void mali_gp_mask_all_interrupts(struct mali_gp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE);
+}
+
+MALI_STATIC_INLINE u32 mali_gp_read_rawstat(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_read_core_status(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS);
+}
+
+MALI_STATIC_INLINE void mali_gp_enable_interrupts(struct mali_gp_core *core, u32 irq_exceptions)
+{
+       /* Enable all interrupts, except those specified in irq_exceptions */
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK,
+                                   MALIGP2_REG_VAL_IRQ_MASK_USED & ~irq_exceptions);
+}
+
+MALI_STATIC_INLINE u32 mali_gp_read_plbu_alloc_start_addr(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR);
+}
+
 #endif /* __MALI_GP_H__ */
index 2e445d6e0512cb6858c923100cd98f8d069323ce..54b0a06681905700e68af35922aaba61ff245f05 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_gp_job.h"
 #include "mali_osk_list.h"
 #include "mali_uk_types.h"
 
+static u32 gp_counter_src0 = MALI_HW_CORE_NO_COUNTER;      /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+static u32 gp_counter_src1 = MALI_HW_CORE_NO_COUNTER;          /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+
 struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id)
 {
        struct mali_gp_job *job;
+       u32 perf_counter_flag;
 
        job = _mali_osk_malloc(sizeof(struct mali_gp_job));
        if (NULL != job)
        {
+               job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s));
+               if (NULL == job->finished_notification)
+               {
+                       _mali_osk_free(job);
+                       return NULL;
+               }
+
+               job->oom_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s));
+               if (NULL == job->oom_notification)
+               {
+                       _mali_osk_notification_delete(job->finished_notification);
+                       _mali_osk_free(job);
+                       return NULL;
+               }
+
                if (0 != copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s)))
                {
+                       _mali_osk_notification_delete(job->finished_notification);
+                       _mali_osk_notification_delete(job->oom_notification);
                        _mali_osk_free(job);
                        return NULL;
                }
 
+               perf_counter_flag = mali_gp_job_get_perf_counter_flag(job);
+               /* set counters got from user space only if no counters were set through debugfs / DS-5 */
+               if (MALI_HW_CORE_NO_COUNTER == mali_gp_job_get_gp_counter_src0())
+               {
+                       if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
+                       {
+                               mali_gp_job_set_gp_counter_src0(job->uargs.perf_counter_src0);
+                               mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0());
+                       }
+               }
+               else
+               {
+                       mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0());
+               }
+               if (MALI_HW_CORE_NO_COUNTER == mali_gp_job_get_gp_counter_src1())
+               {
+                       if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
+                       {
+                                       mali_gp_job_set_gp_counter_src1(job->uargs.perf_counter_src1);
+                                       mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1());
+                       }
+               }
+               else
+               {
+                       mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1());
+               }
+
                _mali_osk_list_init(&job->list);
                job->session = session;
                job->id = id;
@@ -43,5 +91,42 @@ struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_
 
 void mali_gp_job_delete(struct mali_gp_job *job)
 {
+
+       /* de-allocate the pre-allocated oom notifications */
+       if (NULL != job->oom_notification)
+       {
+               _mali_osk_notification_delete(job->oom_notification);
+               job->oom_notification = NULL;
+       }
+       if (NULL != job->finished_notification)
+       {
+               _mali_osk_notification_delete(job->finished_notification);
+               job->finished_notification = NULL;
+       }
+
        _mali_osk_free(job);
 }
+
+u32 mali_gp_job_get_gp_counter_src0(void)
+{
+       return gp_counter_src0;
+}
+
+mali_bool mali_gp_job_set_gp_counter_src0(u32 counter)
+{
+       gp_counter_src0 = counter;
+
+       return MALI_TRUE;
+}
+
+u32 mali_gp_job_get_gp_counter_src1(void)
+{
+       return gp_counter_src1;
+}
+
+mali_bool mali_gp_job_set_gp_counter_src1(u32 counter)
+{
+       gp_counter_src1 = counter;
+
+       return MALI_TRUE;
+}
index 7b45552a931ee0c85574d07aacba67d846db08a1..cf74e79abab4d2e8b47ad47f9ca52992109d7b06 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_GP_JOB_H__
@@ -17,8 +17,8 @@
 #include "mali_session.h"
 
 /**
- * The structure represends a GP job, including all sub-jobs
- * (This struct unfortunatly needs to be public because of how the _mali_osk_list_*
+ * The structure represents a GP job, including all sub-jobs
+ * (This struct unfortunately needs to be public because of how the _mali_osk_list_*
  * mechanism works)
  */
 struct mali_gp_job
@@ -32,11 +32,18 @@ struct mali_gp_job
        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 */
+       _mali_osk_notification_t *finished_notification;   /**< Notification sent back to userspace on job complete */
+       _mali_osk_notification_t *oom_notification;        /**< Notification sent back to userspace on OOM */
 };
 
 struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id);
 void mali_gp_job_delete(struct mali_gp_job *job);
 
+u32 mali_gp_job_get_gp_counter_src0(void);
+mali_bool mali_gp_job_set_gp_counter_src0(u32 counter);
+u32 mali_gp_job_get_gp_counter_src1(void);
+mali_bool mali_gp_job_set_gp_counter_src1(u32 counter);
+
 MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job)
 {
        return (NULL == job) ? 0 : job->id;
@@ -122,6 +129,16 @@ MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *j
        return job->perf_counter_value1;
 }
 
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src0(struct mali_gp_job *job, u32 src)
+{
+       job->uargs.perf_counter_src0 = src;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src1(struct mali_gp_job *job, u32 src)
+{
+       job->uargs.perf_counter_src1 = src;
+}
+
 MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value)
 {
        job->perf_counter_value0 = value;
index 52fa15b2f7fe2a8b6fcc3ed10257ae4ce78dd423..c159fafb5ee8a0f6f90dad8926ee08f231753687 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_gp_scheduler.h"
@@ -16,7 +16,7 @@
 #include "mali_gp.h"
 #include "mali_gp_job.h"
 #include "mali_group.h"
-#include "mali_cluster.h"
+#include "mali_pm.h"
 
 enum mali_gp_slot_state
 {
@@ -51,11 +51,12 @@ static _mali_osk_lock_t *gp_scheduler_lock = NULL;
 
 _mali_osk_errcode_t mali_gp_scheduler_initialize(void)
 {
+       u32 num_groups;
        u32 i;
 
        _MALI_OSK_INIT_LIST_HEAD(&job_queue);
 
-       gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+       gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER);
        if (NULL == gp_scheduler_lock)
        {
                return _MALI_OSK_ERR_NOMEM;
@@ -69,27 +70,22 @@ _mali_osk_errcode_t mali_gp_scheduler_initialize(void)
        }
 
        /* Find all the available GP cores */
-       for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++)
+       num_groups = mali_group_get_glob_num_groups();
+       for (i = 0; i < num_groups; 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_group *group = mali_group_get_glob_group(i);
+
+               struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+               if (NULL != gp_core)
                {
-                       struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
-                       if (NULL != gp_core)
+                       if (0 == gp_version)
                        {
-                               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 */
+                               /* Retrieve GP version */
+                               gp_version = mali_gp_core_get_version(gp_core);
                        }
-                       group_id++;
-                       group = mali_cluster_get_group(curr_cluster, group_id);
+                       slot.group = group;
+                       slot.state = MALI_GP_SLOT_STATE_IDLE;
+                       break; /* There is only one GP, no point in looking for more */
                }
        }
 
@@ -98,6 +94,10 @@ _mali_osk_errcode_t mali_gp_scheduler_initialize(void)
 
 void mali_gp_scheduler_terminate(void)
 {
+       MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_IDLE == slot.state);
+       MALI_DEBUG_ASSERT_POINTER(slot.group);
+       mali_group_delete(slot.group);
+
        _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue);
        _mali_osk_lock_term(gp_scheduler_lock);
 }
@@ -132,38 +132,77 @@ static void mali_gp_scheduler_schedule(void)
 {
        struct mali_gp_job *job;
 
-       MALI_ASSERT_GP_SCHEDULER_LOCKED();
+       mali_gp_scheduler_lock();
 
        if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue))
        {
+               mali_gp_scheduler_unlock();
                MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
                                     pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0));
                return; /* Nothing to do, so early out */
        }
 
+       /* Get (and remove) next job in queue */
        job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list);
+       _mali_osk_list_del(&job->list);
+
+       /* Mark slot as busy */
+       slot.state = MALI_GP_SLOT_STATE_WORKING;
+
+       mali_gp_scheduler_unlock();
 
        MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job));
-       if (_MALI_OSK_ERR_OK == mali_group_start_gp_job(slot.group, job))
+
+       mali_group_lock(slot.group);
+
+       if (_MALI_OSK_ERR_OK != mali_group_start_gp_job(slot.group, job))
        {
-               /* Mark slot as busy */
-               slot.state = MALI_GP_SLOT_STATE_WORKING;
+               MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n"));
+               MALI_DEBUG_ASSERT(0); /* @@@@ todo: this cant fail on Mali-300+, no need to implement put back of job */
+       }
 
-               /* Remove from queue of unscheduled jobs */
-               _mali_osk_list_del(&job->list);
+       mali_group_unlock(slot.group);
+}
+
+/* @@@@ todo: pass the job in as a param to this function, so that we don't have to take the scheduler lock again */
+static void mali_gp_scheduler_schedule_on_group(struct mali_group *group)
+{
+       struct mali_gp_job *job;
+
+       mali_gp_scheduler_lock();
+
+       if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue))
+       {
+               mali_gp_scheduler_unlock();
+               MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
+                                    pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0));
+               return; /* Nothing to do, so early out */
        }
-       else
+
+       /* Get (and remove) next job in queue */
+       job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list);
+       _mali_osk_list_del(&job->list);
+
+       /* Mark slot as busy */
+       slot.state = MALI_GP_SLOT_STATE_WORKING;
+
+       mali_gp_scheduler_unlock();
+
+       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job));
+
+       if (_MALI_OSK_ERR_OK != mali_group_start_gp_job(slot.group, job))
        {
                MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n"));
+               MALI_DEBUG_ASSERT(0); /* @@@@ todo: this cant fail on Mali-300+, no need to implement put back of job */
        }
 }
 
 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_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_uk_gp_job_finished_s *jobres = job->finished_notification->result_buffer;
                _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */
                jobres->user_job_ptr = mali_gp_job_get_user_id(job);
                if (MALI_TRUE == success)
@@ -179,26 +218,13 @@ static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_b
                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_session_send_notification(mali_gp_job_get_session(job), job->finished_notification);
+               job->finished_notification = NULL;
        }
 
        mali_gp_job_delete(job);
 }
 
-
-void mali_gp_scheduler_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"));
@@ -213,39 +239,37 @@ void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *jo
        {
                _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);
+
+       mali_gp_scheduler_schedule_on_group(group);
+
+       /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
+       mali_pm_core_event(MALI_CORE_EVENT_GP_STOP);
 }
 
 void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job)
 {
-       _mali_osk_notification_t *notobj;
+       _mali_uk_gp_job_suspended_s * jobres;
+       _mali_osk_notification_t * notification;
 
-       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();
 
-               mali_gp_scheduler_lock();
+       notification = job->oom_notification;
+       job->oom_notification = NULL;
+       slot.returned_cookie = mali_gp_job_get_id(job);
 
-               jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer;
+       jobres = (_mali_uk_gp_job_suspended_s *)notification->result_buffer;
+       jobres->user_job_ptr = mali_gp_job_get_user_id(job);
+       jobres->cookie = mali_gp_job_get_id(job);
 
-               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_gp_scheduler_unlock();
 
-               mali_session_send_notification(mali_gp_job_get_session(job), notobj);
+       jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY;
 
-               mali_gp_scheduler_unlock();
-       }
+       mali_session_send_notification(mali_gp_job_get_session(job), notification);
 
        /*
        * If this function failed, then we could return the job to user space right away,
@@ -267,11 +291,11 @@ void mali_gp_scheduler_resume(void)
 {
        mali_gp_scheduler_lock();
        pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
+       mali_gp_scheduler_unlock();
        if (0 == pause_count)
        {
                mali_gp_scheduler_schedule();
        }
-       mali_gp_scheduler_unlock();
 }
 
 _mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *uargs)
@@ -296,16 +320,16 @@ _mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *u
        return _MALI_OSK_ERR_OK;
 #endif
 
-       mali_gp_scheduler_lock();
+       mali_pm_core_event(MALI_CORE_EVENT_GP_START);
 
+       mali_gp_scheduler_lock();
        _mali_osk_list_addtail(&job->list, &job_queue);
+       mali_gp_scheduler_unlock();
 
        MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job));
 
        mali_gp_scheduler_schedule();
 
-       mali_gp_scheduler_unlock();
-
        return _MALI_OSK_ERR_OK;
 }
 
@@ -328,7 +352,8 @@ _mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s
 _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;
+       struct mali_gp_job *resumed_job;
+       _mali_osk_notification_t *new_notification = 0;
 
        MALI_DEBUG_ASSERT_POINTER(args);
 
@@ -343,6 +368,20 @@ _mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s
                return _MALI_OSK_ERR_FAULT;
        }
 
+       if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code)
+       {
+               new_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s));
+
+               if (NULL == new_notification)
+               {
+                       MALI_PRINT_ERROR(("Mali GP scheduler: Failed to allocate notification object. Will abort GP job.\n"));
+                       mali_group_lock(slot.group);
+                       mali_group_abort_gp_job(slot.group, args->cookie);
+                       mali_group_unlock(slot.group);
+                       return _MALI_OSK_ERR_FAULT;
+               }
+       }
+
        mali_gp_scheduler_lock();
 
        /* Make sure that the cookie returned by user space is the same as we provided in the first place */
@@ -355,28 +394,32 @@ _mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s
 
        mali_gp_scheduler_unlock();
 
-       switch (args->code)
+       mali_group_lock(slot.group);
+
+       if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == 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;
+               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]));
 
-               default:
-                       MALI_PRINT_ERROR(("Mali GP scheduler: Wrong suspend response from user space\n"));
-                       ret = _MALI_OSK_ERR_FAULT;
-                       break;
+               resumed_job = mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]);
+               if (NULL != resumed_job)
+               {
+                       /* @@@@ todo: move this and other notification handling into the job object itself */
+                       resumed_job->oom_notification = new_notification;
+                       mali_group_unlock(slot.group);
+                       return _MALI_OSK_ERR_OK;
+               }
+               else
+               {
+                       mali_group_unlock(slot.group);
+                       _mali_osk_notification_delete(new_notification);
+                       return _MALI_OSK_ERR_FAULT;
+               }
        }
 
-    return ret;
-
+       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie));
+       mali_group_abort_gp_job(slot.group, args->cookie);
+       mali_group_unlock(slot.group);
+       return _MALI_OSK_ERR_OK;
 }
 
 void mali_gp_scheduler_abort_session(struct mali_session_data *session)
@@ -394,15 +437,13 @@ void mali_gp_scheduler_abort_session(struct mali_session_data *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_pm_core_event(MALI_CORE_EVENT_GP_STOP);
                }
        }
 
        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);
 }
 
@@ -427,9 +468,24 @@ u32 mali_gp_scheduler_dump_state(char *buf, u32 size)
        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
+
+void mali_gp_scheduler_reset_all_groups(void)
+{
+       if (NULL != slot.group)
+       {
+               mali_group_reset(slot.group);
+       }
+}
+
+void mali_gp_scheduler_zap_all_active(struct mali_session_data *session)
+{
+       if (NULL != slot.group)
+       {
+               mali_group_zap_session(slot.group, session);
+       }
+}
index ef5850944589d68df79ef929406123dcd967f928..e32ad1f18173ddaa120dc7732ca77c0b8804f3cf 100644 (file)
@@ -1,24 +1,23 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_GP_SCHEDULER_H__
 #define __MALI_GP_SCHEDULER_H__
 
 #include "mali_osk.h"
-#include "mali_cluster.h"
 #include "mali_gp_job.h"
+#include "mali_group.h"
 
 _mali_osk_errcode_t mali_gp_scheduler_initialize(void);
 void mali_gp_scheduler_terminate(void);
 
-void mali_gp_scheduler_do_schedule(void);
 void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success);
 void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job);
 void mali_gp_scheduler_abort_session(struct mali_session_data *session);
@@ -27,4 +26,19 @@ u32 mali_gp_scheduler_dump_state(char *buf, u32 size);
 void mali_gp_scheduler_suspend(void);
 void mali_gp_scheduler_resume(void);
 
+/**
+ * @brief Reset all groups
+ *
+ * This function resets all groups known by the GP scheuduler. This must be
+ * called after the Mali HW has been powered on in order to reset the HW.
+ */
+void mali_gp_scheduler_reset_all_groups(void);
+
+/**
+ * @brief Zap TLB on all groups with \a session active
+ *
+ * The scheculer will zap the session on all groups it owns.
+ */
+void mali_gp_scheduler_zap_all_active(struct mali_session_data *session);
+
 #endif /* __MALI_GP_SCHEDULER_H__ */
index f57a147952d49bc1a80414be5f9ac5d5011ab5c4..ae6e8f3e4e4a4e6ab441b012ce36bc6f42dc1170 100644 (file)
@@ -1,23 +1,42 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
+ //#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <mach/am_regs.h>
+#include <linux/module.h>
+//#endif
 
 #include "mali_kernel_common.h"
 #include "mali_group.h"
 #include "mali_osk.h"
-#include "mali_cluster.h"
+#include "mali_l2_cache.h"
 #include "mali_gp.h"
 #include "mali_pp.h"
 #include "mali_mmu.h"
+#include "mali_dlbu.h"
+#include "mali_broadcast.h"
 #include "mali_gp_scheduler.h"
 #include "mali_pp_scheduler.h"
-#include "mali_pm.h"
+#include "mali_kernel_core.h"
+#include "mali_osk_profiling.h"
+
+#define CONFIG_MALI400_UPPER_HALF_SCHEDULING
+
+static void mali_group_bottom_half_mmu(void *data);
+static void mali_group_bottom_half_gp(void *data);
+static void mali_group_bottom_half_pp(void *data);
+
+static void mali_group_timeout(void *data);
+static void mali_group_reset_pp(struct mali_group *group);
 
 /*
  * The group object is the most important object in the device driver,
  * 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;
 
@@ -73,8 +63,12 @@ enum mali_group_activate_pd_status
 /* local helper functions */
 static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session);
 static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session);
+static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session);
 static void mali_group_recovery_reset(struct mali_group *group);
-static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success);
+static void mali_group_mmu_page_fault(struct mali_group *group);
+
+void mali_group_post_process_job_pp(struct mali_group *group);
+void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend);
 
 void mali_group_lock(struct mali_group *group)
 {
@@ -100,7 +94,7 @@ void mali_group_assert_locked(struct mali_group *group)
 #endif
 
 
-struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu)
+struct mali_group *mali_group_create(struct mali_l2_cache_core *core, struct mali_dlbu_core *dlbu, struct mali_bcast_unit *bcast)
 {
        struct mali_group *group = NULL;
 
@@ -110,28 +104,49 @@ struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_m
                return NULL;
        }
 
-       group = _mali_osk_malloc(sizeof(struct mali_group));
+       group = _mali_osk_calloc(1, 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->timeout_timer = _mali_osk_timer_init();
+
+               if (NULL != group->timeout_timer)
                {
-                       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;
+                       _mali_osk_lock_order_t order;
+                       _mali_osk_timer_setcallback(group->timeout_timer, mali_group_timeout, (void *)group);
 
-                       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++;
+                       if (mali_group_is_virtual(group))
+                       {
+                               order = _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL;
+                       }
+                       else
+                       {
+                               order = _MALI_OSK_LOCK_ORDER_GROUP;
+                       }
 
-                       return group;
+                       group->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |
+                                                         _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |
+                                                         _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE,
+                                                         0, order);
+                       if (NULL != group->lock)
+                       {
+                               group->l2_cache_core[0] = core;
+                               group->session = NULL;
+                               group->page_dir_ref_count = 0;
+                               group->power_is_on = MALI_TRUE;
+                               group->state = MALI_GROUP_STATE_IDLE;
+                               _mali_osk_list_init(&group->group_list);
+                               _mali_osk_list_init(&group->pp_scheduler_list);
+                               group->parent_group = NULL;
+                               group->l2_cache_core_ref_count[0] = 0;
+                               group->l2_cache_core_ref_count[1] = 0;
+                               group->bcast_core = bcast;
+                               group->dlbu_core = dlbu;
+
+                               mali_global_groups[mali_global_num_groups] = group;
+                               mali_global_num_groups++;
+
+                               return group;
+                       }
                }
                _mali_osk_free(group);
        }
@@ -139,22 +154,80 @@ struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_m
        return NULL;
 }
 
-void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core)
+_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core)
+{
+       /* This group object now owns the MMU core object */
+       group->mmu= mmu_core;
+       group->bottom_half_work_mmu = _mali_osk_wq_create_work(mali_group_bottom_half_mmu, group);
+       if (NULL == group->bottom_half_work_mmu)
+       {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_group_remove_mmu_core(struct mali_group *group)
+{
+       /* This group object no longer owns the MMU core object */
+       group->mmu = NULL;
+       if (NULL != group->bottom_half_work_mmu)
+       {
+               _mali_osk_wq_delete_work(group->bottom_half_work_mmu);
+       }
+}
+
+_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core)
 {
        /* This group object now owns the GP core object */
        group->gp_core = gp_core;
+       group->bottom_half_work_gp = _mali_osk_wq_create_work(mali_group_bottom_half_gp, group);
+       if (NULL == group->bottom_half_work_gp)
+       {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_group_remove_gp_core(struct mali_group *group)
+{
+       /* This group object no longer owns the GP core object */
+       group->gp_core = NULL;
+       if (NULL != group->bottom_half_work_gp)
+       {
+               _mali_osk_wq_delete_work(group->bottom_half_work_gp);
+       }
 }
 
-void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core)
+_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core)
 {
        /* This group object now owns the PP core object */
        group->pp_core = pp_core;
+       group->bottom_half_work_pp = _mali_osk_wq_create_work(mali_group_bottom_half_pp, group);
+       if (NULL == group->bottom_half_work_pp)
+       {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_group_remove_pp_core(struct mali_group *group)
+{
+       /* This group object no longer owns the PP core object */
+       group->pp_core = NULL;
+       if (NULL != group->bottom_half_work_pp)
+       {
+               _mali_osk_wq_delete_work(group->bottom_half_work_pp);
+       }
 }
 
 void mali_group_delete(struct mali_group *group)
 {
        u32 i;
 
+       MALI_DEBUG_PRINT(4, ("Deleting group %p\n", group));
+
+       MALI_DEBUG_ASSERT(NULL == group->parent_group);
+
        /* Delete the resources that this group owns */
        if (NULL != group->gp_core)
        {
@@ -171,24 +244,274 @@ void mali_group_delete(struct mali_group *group)
                mali_mmu_delete(group->mmu);
        }
 
-       for (i = 0; i < mali_global_num_groups; i++)
+       if (mali_group_is_virtual(group))
+       {
+               /* Remove all groups from virtual group */
+               struct mali_group *child;
+               struct mali_group *temp;
+
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+               {
+                       child->parent_group = NULL;
+                       mali_group_delete(child);
+               }
+       }
+
+       if (NULL != group->dlbu_core)
+       {
+               mali_dlbu_delete(group->dlbu_core);
+       }
+
+       if (NULL != group->bcast_core)
+       {
+               mali_bcast_unit_delete(group->bcast_core);
+       }
+
+       for (i = 0; i < MALI_MAX_NUMBER_OF_GROUPS; i++)
        {
                if (mali_global_groups[i] == group)
                {
                        mali_global_groups[i] = NULL;
                        mali_global_num_groups--;
+
+                       if (i != mali_global_num_groups)
+                       {
+                               /* We removed a group from the middle of the array -- move the last
+                                * group to the current position to close the gap */
+                               mali_global_groups[i] = mali_global_groups[mali_global_num_groups];
+                               mali_global_groups[mali_global_num_groups] = NULL;
+                       }
+
                        break;
                }
        }
 
+       if (NULL != group->timeout_timer)
+       {
+               _mali_osk_timer_del(group->timeout_timer);
+               _mali_osk_timer_term(group->timeout_timer);
+       }
+
+       if (NULL != group->bottom_half_work_mmu)
+       {
+               _mali_osk_wq_delete_work(group->bottom_half_work_mmu);
+       }
+
+       if (NULL != group->bottom_half_work_gp)
+       {
+               _mali_osk_wq_delete_work(group->bottom_half_work_gp);
+       }
+
+       if (NULL != group->bottom_half_work_pp)
+       {
+               _mali_osk_wq_delete_work(group->bottom_half_work_pp);
+       }
+
        _mali_osk_lock_term(group->lock);
 
        _mali_osk_free(group);
 }
 
-/* Called from mali_cluster_reset() when the system is re-turned on */
+MALI_DEBUG_CODE(static void mali_group_print_virtual(struct mali_group *vgroup)
+{
+       u32 i;
+       struct mali_group *group;
+       struct mali_group *temp;
+
+       MALI_DEBUG_PRINT(4, ("Virtual group %p\n", vgroup));
+       MALI_DEBUG_PRINT(4, ("l2_cache_core[0] = %p, ref = %d\n", vgroup->l2_cache_core[0], vgroup->l2_cache_core_ref_count[0]));
+       MALI_DEBUG_PRINT(4, ("l2_cache_core[1] = %p, ref = %d\n", vgroup->l2_cache_core[1], vgroup->l2_cache_core_ref_count[1]));
+
+       i = 0;
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &vgroup->group_list, struct mali_group, group_list)
+       {
+               MALI_DEBUG_PRINT(4, ("[%d] %p, l2_cache_core[0] = %p\n", i, group, group->l2_cache_core[0]));
+               i++;
+       }
+})
+
+/**
+ * @brief Add child group to virtual group parent
+ *
+ * Before calling this function, child must have it's state set to JOINING_VIRTUAL
+ * to ensure it's not touched during the transition period. When this function returns,
+ * child's state will be IN_VIRTUAL.
+ */
+void mali_group_add_group(struct mali_group *parent, struct mali_group *child)
+{
+       mali_bool found;
+       u32 i;
+
+       MALI_DEBUG_PRINT(3, ("Adding group %p to virtual group %p\n", child, parent));
+
+       MALI_ASSERT_GROUP_LOCKED(parent);
+
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
+       MALI_DEBUG_ASSERT(!mali_group_is_virtual(child));
+       MALI_DEBUG_ASSERT(NULL == child->parent_group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_JOINING_VIRTUAL == child->state);
+
+       _mali_osk_list_addtail(&child->group_list, &parent->group_list);
+
+       child->state = MALI_GROUP_STATE_IN_VIRTUAL;
+       child->parent_group = parent;
+
+       MALI_DEBUG_ASSERT_POINTER(child->l2_cache_core[0]);
+
+       MALI_DEBUG_PRINT(4, ("parent->l2_cache_core: [0] = %p, [1] = %p\n", parent->l2_cache_core[0], parent->l2_cache_core[1]));
+       MALI_DEBUG_PRINT(4, ("child->l2_cache_core: [0] = %p, [1] = %p\n", child->l2_cache_core[0], child->l2_cache_core[1]));
+
+       /* Keep track of the L2 cache cores of child groups */
+       found = MALI_FALSE;
+       for (i = 0; i < 2; i++)
+       {
+               if (parent->l2_cache_core[i] == child->l2_cache_core[0])
+               {
+                       MALI_DEBUG_ASSERT(parent->l2_cache_core_ref_count[i] > 0);
+                       parent->l2_cache_core_ref_count[i]++;
+                       found = MALI_TRUE;
+               }
+       }
+
+       if (!found)
+       {
+               /* First time we see this L2 cache, add it to our list */
+               i = (NULL == parent->l2_cache_core[0]) ? 0 : 1;
+
+               MALI_DEBUG_PRINT(4, ("First time we see l2_cache %p. Adding to [%d] = %p\n", child->l2_cache_core[0], i, parent->l2_cache_core[i]));
+
+               MALI_DEBUG_ASSERT(NULL == parent->l2_cache_core[i]);
+
+               parent->l2_cache_core[i] = child->l2_cache_core[0];
+               parent->l2_cache_core_ref_count[i]++;
+       }
+
+       /* Update Broadcast Unit and DLBU */
+       mali_bcast_add_group(parent->bcast_core, child);
+       mali_dlbu_add_group(parent->dlbu_core, child);
+
+       /* Update MMU */
+       MALI_DEBUG_ASSERT(0 == child->page_dir_ref_count);
+       if (parent->session == child->session)
+       {
+               mali_mmu_zap_tlb(child->mmu);
+       }
+       else
+       {
+               child->session = NULL;
+
+               if (NULL == parent->session)
+               {
+                       mali_mmu_activate_empty_page_directory(child->mmu);
+               }
+               else
+               {
+
+                       mali_bool activate_success = mali_mmu_activate_page_directory(child->mmu,
+                               mali_session_get_page_directory(parent->session));
+                       MALI_DEBUG_ASSERT(activate_success);
+               }
+       }
+       child->session = NULL;
+
+       /* Start job on child when parent is active */
+       if (NULL != parent->pp_running_job)
+       {
+               struct mali_pp_job *job = parent->pp_running_job;
+               MALI_DEBUG_PRINT(3, ("Group %x joining running job %d on virtual group %x\n",
+                                    child, mali_pp_job_get_id(job), parent));
+               MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING == parent->state);
+               mali_pp_job_start(child->pp_core, job, mali_pp_core_get_id(child->pp_core), MALI_TRUE);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
+                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                             MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                             mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
+                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
+                                             mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
+       }
+
+       MALI_DEBUG_CODE(mali_group_print_virtual(parent);)
+}
+
+/**
+ * @brief Remove child group from virtual group parent
+ *
+ * After the child is removed, it's state will be LEAVING_VIRTUAL and must be set
+ * to IDLE before it can be used.
+ */
+void mali_group_remove_group(struct mali_group *parent, struct mali_group *child)
+{
+       u32 i;
+
+       MALI_ASSERT_GROUP_LOCKED(parent);
+
+       MALI_DEBUG_PRINT(3, ("Removing group %p from virtual group %p\n", child, parent));
+
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
+       MALI_DEBUG_ASSERT(!mali_group_is_virtual(child));
+       MALI_DEBUG_ASSERT(parent == child->parent_group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IN_VIRTUAL == child->state);
+       /* Removing groups while running is not yet supported. */
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == parent->state);
+
+       mali_group_lock(child);
+
+       /* Update Broadcast Unit and DLBU */
+       mali_bcast_remove_group(parent->bcast_core, child);
+       mali_dlbu_remove_group(parent->dlbu_core, child);
+
+       _mali_osk_list_delinit(&child->group_list);
+
+       child->session = parent->session;
+       child->parent_group = NULL;
+       child->state = MALI_GROUP_STATE_LEAVING_VIRTUAL;
+
+       /* Keep track of the L2 cache cores of child groups */
+       i = (child->l2_cache_core[0] == parent->l2_cache_core[0]) ? 0 : 1;
+
+       MALI_DEBUG_ASSERT(child->l2_cache_core[0] == parent->l2_cache_core[i]);
+
+       parent->l2_cache_core_ref_count[i]--;
+
+       if (parent->l2_cache_core_ref_count[i] == 0)
+       {
+               parent->l2_cache_core[i] = NULL;
+       }
+
+       MALI_DEBUG_CODE(mali_group_print_virtual(parent));
+
+       mali_group_unlock(child);
+}
+
+struct mali_group *mali_group_acquire_group(struct mali_group *parent)
+{
+       struct mali_group *child;
+
+       MALI_ASSERT_GROUP_LOCKED(parent);
+
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
+       MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&parent->group_list));
+
+       child = _MALI_OSK_LIST_ENTRY(parent->group_list.prev, struct mali_group, group_list);
+
+       mali_group_remove_group(parent, child);
+
+       return child;
+}
+
 void mali_group_reset(struct mali_group *group)
 {
+       /*
+        * This function should not be used to abort jobs,
+        * currently only called during insmod and PM resume
+        */
+       MALI_DEBUG_ASSERT(NULL == group->gp_running_job);
+       MALI_DEBUG_ASSERT(NULL == group->pp_running_job);
+
        mali_group_lock(group);
 
        group->session = NULL;
@@ -205,7 +528,7 @@ void mali_group_reset(struct mali_group *group)
 
        if (NULL != group->pp_core)
        {
-               mali_pp_reset(group->pp_core);
+               mali_group_reset_pp(group);
        }
 
        mali_group_unlock(group);
@@ -226,15 +549,15 @@ _mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mal
        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);
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
 
        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));
+       if (NULL != group->l2_cache_core[0])
+       {
+               mali_l2_cache_invalidate_all_conditional(group->l2_cache_core[0], mali_gp_job_get_id(job));
+       }
 
        activate_status = mali_group_activate_page_directory(group, session);
        if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
@@ -245,21 +568,20 @@ _mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mal
                        mali_mmu_zap_tlb_without_stall(group->mmu);
                }
                mali_gp_job_start(group->gp_core, job);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                             mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0);
+
                group->gp_running_job = job;
-               group->gp_state = MALI_GROUP_CORE_STATE_WORKING;
+               group->state = MALI_GROUP_STATE_WORKING;
 
-               mali_group_unlock(group);
+               /* Setup the timeout timer value and save the job id for the job running on the gp core */
+               _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
 
                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;
 }
 
@@ -268,15 +590,20 @@ _mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mal
        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);
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
 
        session = mali_pp_job_get_session(job);
 
-       mali_group_lock(group);
+       if (NULL != group->l2_cache_core[0])
+       {
+               mali_l2_cache_invalidate_all_conditional(group->l2_cache_core[0], mali_pp_job_get_id(job));
+       }
 
-       mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job));
+       if (NULL != group->l2_cache_core[1])
+       {
+               mali_l2_cache_invalidate_all_conditional(group->l2_cache_core[1], mali_pp_job_get_id(job));
+       }
 
        activate_status = mali_group_activate_page_directory(group, session);
        if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
@@ -287,184 +614,258 @@ _mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mal
                        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);
+
+               if (mali_group_is_virtual(group))
+               {
+                       struct mali_group *child;
+                       struct mali_group *temp;
+                       u32 core_num = 0;
+
+                       /* Configure DLBU for the job */
+                       mali_dlbu_config_job(group->dlbu_core, job);
+
+                       /* Write stack address for each child group */
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+                       {
+                               mali_pp_write_addr_stack(child->pp_core, job);
+                               core_num++;
+                       }
+               }
+
+               mali_pp_job_start(group->pp_core, job, sub_job, MALI_FALSE);
+
+               /* if the group is virtual, loop through physical groups which belong to this group
+                * and call profiling events for its cores as virtual */
+               if (MALI_TRUE == mali_group_is_virtual(group))
+               {
+                       struct mali_group *child;
+                       struct mali_group *temp;
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+                       {
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
+                                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                                             MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                                             mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
+
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
+                                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
+                                                             mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
+
+                       }
+               }
+               else /* group is physical - call profiling events for physical cores */
+               {
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
+                                                     MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                                     mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
+
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL,
+                                                     mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
+
+               }
                group->pp_running_job = job;
                group->pp_running_sub_job = sub_job;
-               group->pp_state = MALI_GROUP_CORE_STATE_WORKING;
+               group->state = MALI_GROUP_STATE_WORKING;
 
-               mali_group_unlock(group);
+               /* Setup the timeout timer value and save the job id for the job running on the pp core */
+               _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
 
                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)
+struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr)
 {
-       mali_group_lock(group);
+       MALI_ASSERT_GROUP_LOCKED(group);
 
-       if (group->gp_state != MALI_GROUP_CORE_STATE_OOM ||
+       if (group->state != MALI_GROUP_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 */
+               return NULL; /* Illegal request or job has already been aborted */
+       }
+
+       if (NULL != group->l2_cache_core[0])
+       {
+               mali_l2_cache_invalidate_all_force(group->l2_cache_core[0]);
        }
 
-       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);
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0);
+
+       group->state = MALI_GROUP_STATE_WORKING;
+
+       return group->gp_running_job;
 }
 
-void mali_group_abort_gp_job(struct mali_group *group, u32 job_id)
+static void mali_group_reset_pp(struct mali_group *group)
 {
-       mali_group_lock(group);
+       struct mali_group *child;
+       struct mali_group *temp;
 
-       if (group->gp_state == MALI_GROUP_CORE_STATE_IDLE ||
-           mali_gp_job_get_id(group->gp_running_job) != job_id)
+       /* TODO: If we *know* that the group is idle, this could be faster. */
+
+       mali_pp_reset_async(group->pp_core);
+
+       if (!mali_group_is_virtual(group) || group->pp_running_job)
        {
-               mali_group_unlock(group);
-               return; /* No need to cancel or job has already been aborted or completed */
+               /* This is a physical group or an idle virtual group -- simply wait for
+                * the reset to complete. */
+               mali_pp_reset_wait(group->pp_core);
+       }
+       else /* virtual group */
+       {
+               /* Loop through all members of this virtual group and wait until they
+                * are done resetting.
+                */
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+               {
+                       mali_pp_reset_wait(child->pp_core);
+               }
        }
-
-       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)
+static void mali_group_complete_pp(struct mali_group *group, mali_bool success)
 {
-       mali_group_lock(group);
+       struct mali_pp_job *pp_job_to_return;
+       u32 pp_sub_job_to_return;
 
-       if (group->pp_state == MALI_GROUP_CORE_STATE_IDLE ||
-           mali_pp_job_get_id(group->pp_running_job) != job_id)
+       MALI_DEBUG_ASSERT_POINTER(group->pp_core);
+       MALI_DEBUG_ASSERT_POINTER(group->pp_running_job);
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       mali_group_post_process_job_pp(group);
+
+       mali_pp_reset_async(group->pp_core);
+
+       pp_job_to_return = group->pp_running_job;
+       pp_sub_job_to_return = group->pp_running_sub_job;
+       group->state = MALI_GROUP_STATE_IDLE;
+       group->pp_running_job = NULL;
+
+       mali_group_deactivate_page_directory(group, group->session);
+
+       if (_MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core))
        {
-               mali_group_unlock(group);
-               return; /* No need to cancel or job has already been aborted or completed */
+               MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n"));
+               mali_group_recovery_reset(group);
        }
 
-       mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* Will release group lock */
+       mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, success);
 }
 
-void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session)
+static void mali_group_complete_gp(struct mali_group *group, mali_bool success)
 {
-       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;
+       struct mali_gp_job *gp_job_to_return;
 
-       mali_group_lock(group);
+       MALI_DEBUG_ASSERT_POINTER(group->gp_core);
+       MALI_DEBUG_ASSERT_POINTER(group->gp_running_job);
+       MALI_ASSERT_GROUP_LOCKED(group);
 
-       gp_job = group->gp_running_job;
-       pp_job = group->pp_running_job;
+       mali_group_post_process_job_gp(group, MALI_FALSE);
 
-       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));
+       mali_gp_reset_async(group->gp_core);
 
-               gp_job_id = mali_gp_job_get_id(gp_job);
-               abort_gp = MALI_TRUE;
-       }
+       gp_job_to_return = group->gp_running_job;
+       group->state = MALI_GROUP_STATE_IDLE;
+       group->gp_running_job = NULL;
 
-       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_deactivate_page_directory(group, group->session);
 
-       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)
+       if (_MALI_OSK_ERR_OK != mali_gp_reset_wait(group->gp_core))
        {
-               mali_group_abort_pp_job(group, pp_job_id);
+               MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n"));
+               mali_group_recovery_reset(group);
        }
 
-       mali_group_lock(group);
-       mali_group_remove_session_if_unused(group, session);
-       mali_group_unlock(group);
+       mali_gp_scheduler_job_done(group, gp_job_to_return, success);
 }
 
-enum mali_group_core_state mali_group_gp_state(struct mali_group *group)
+void mali_group_abort_gp_job(struct mali_group *group, u32 job_id)
 {
-       return group->gp_state;
-}
+       MALI_ASSERT_GROUP_LOCKED(group);
 
-enum mali_group_core_state mali_group_pp_state(struct mali_group *group)
-{
-       return group->pp_state;
+       if (group->state == MALI_GROUP_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_gp(group, MALI_FALSE);
 }
 
-/* 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)
+static void mali_group_abort_pp_job(struct mali_group *group, u32 job_id)
 {
        MALI_ASSERT_GROUP_LOCKED(group);
 
-       switch (event)
+       if (group->state == MALI_GROUP_STATE_IDLE ||
+           mali_pp_job_get_id(group->pp_running_job) != job_id)
        {
-               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;
+               mali_group_unlock(group);
+               return; /* No need to cancel or job has already been aborted or completed */
        }
-}
 
-struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group)
-{
-       return group->mmu;
+       mali_group_complete_pp(group, MALI_FALSE);
 }
 
-struct mali_session_data *mali_group_get_session(struct mali_group *group)
+void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session)
 {
-       return group->session;
+       struct mali_gp_job *gp_job;
+       struct mali_pp_job *pp_job;
+       u32 gp_job_id = 0;
+       u32 pp_job_id = 0;
+       mali_bool abort_pp = MALI_FALSE;
+       mali_bool abort_gp = MALI_FALSE;
+
+       mali_group_lock(group);
+
+       if (mali_group_is_in_virtual(group))
+       {
+               /* Group is member of a virtual group, don't touch it! */
+               mali_group_unlock(group);
+               return;
+       }
+
+       gp_job = group->gp_running_job;
+       pp_job = group->pp_running_job;
+
+       if (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;
+       }
+
+       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_remove_session_if_unused(group, session);
+
+       mali_group_unlock(group);
 }
 
 struct mali_group *mali_group_get_glob_group(u32 index)
@@ -482,28 +883,6 @@ 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;
@@ -565,14 +944,13 @@ static void mali_group_deactivate_page_directory(struct mali_group *group, struc
        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)
+static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session)
 {
        MALI_ASSERT_GROUP_LOCKED(group);
 
        if (0 == group->page_dir_ref_count)
        {
-               MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
-               MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
+               MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING != group->state);
 
                if (group->session == session)
                {
@@ -591,14 +969,22 @@ void mali_group_power_on(void)
        {
                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);
+               MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
                group->power_is_on = MALI_TRUE;
-               mali_cluster_power_is_enabled_set(group->cluster, MALI_TRUE);
+
+               if (NULL != group->l2_cache_core[0])
+               {
+                       mali_l2_cache_power_is_enabled_set(group->l2_cache_core[0], MALI_TRUE);
+               }
+
+               if (NULL != group->l2_cache_core[1])
+               {
+                       mali_l2_cache_power_is_enabled_set(group->l2_cache_core[1], MALI_TRUE);
+               }
+
                mali_group_unlock(group);
        }
-       MALI_DEBUG_PRINT(3,("group: POWER ON\n"));
+       MALI_DEBUG_PRINT(4,("group: POWER ON\n"));
 }
 
 mali_bool mali_group_power_is_on(struct mali_group *group)
@@ -607,18 +993,6 @@ mali_bool mali_group_power_is_on(struct mali_group *group)
        return group->power_is_on;
 }
 
-inline mali_bool mali_group_power_is_on_2(struct mali_group *group)
-{
-#ifdef DEBUG
-       if(_mali_osk_lock_get_owner(group->lock) == _mali_osk_get_tid())
-               return group->power_is_on;
-       else 
-               return MALI_FALSE;
-#else
-       return group->power_is_on;
-#endif
-}
-
 void mali_group_power_off(void)
 {
        int i;
@@ -628,16 +1002,23 @@ void mali_group_power_off(void)
        {
                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);
+               MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
                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);
+
+               if (NULL != group->l2_cache_core[0])
+               {
+                       mali_l2_cache_power_is_enabled_set(group->l2_cache_core[0], MALI_FALSE);
+               }
+
+               if (NULL != group->l2_cache_core[1])
+               {
+                       mali_l2_cache_power_is_enabled_set(group->l2_cache_core[1], MALI_FALSE);
+               }
+
                mali_group_unlock(group);
        }
-       MALI_DEBUG_PRINT(3,("group: POWER OFF\n"));
+       MALI_DEBUG_PRINT(4,("group: POWER OFF\n"));
 }
 
 
@@ -650,32 +1031,37 @@ static void mali_group_recovery_reset(struct mali_group *group)
        {
                mali_pp_stop_bus(group->pp_core);
        }
-       if (NULL != group->gp_core)
+       else
        {
                mali_gp_stop_bus(group->gp_core);
        }
 
-       /* Flush MMU */
+       /* Flush MMU and clear page fault (if any) */
        mali_mmu_activate_fault_flush_page_directory(group->mmu);
        mali_mmu_page_fault_done(group->mmu);
 
-       /* Wait for cores to stop bus */
+       /* Wait for cores to stop bus, then do a hard reset on them */
        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);
-       }
+               if (mali_group_is_virtual(group))
+               {
+                       struct mali_group *child, *temp;
 
-       /* Reset cores */
-       if (NULL != group->pp_core)
-       {
-               mali_pp_hard_reset(group->pp_core);
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+                       {
+                               mali_pp_stop_bus_wait(child->pp_core);
+                               mali_pp_hard_reset(child->pp_core);
+                       }
+               }
+               else
+               {
+                       mali_pp_stop_bus_wait(group->pp_core);
+                       mali_pp_hard_reset(group->pp_core);
+               }
        }
-       if (NULL != group->gp_core)
+       else
        {
+               mali_gp_stop_bus_wait(group->gp_core);
                mali_gp_hard_reset(group->gp_core);
        }
 
@@ -684,170 +1070,670 @@ static void mali_group_recovery_reset(struct mali_group *group)
        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)
+#if MALI_STATE_TRACKING
+u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size)
 {
-       mali_bool need_group_reset = MALI_FALSE;
-       mali_bool gp_success = success;
-       mali_bool pp_success = success;
+       int n = 0;
 
+       n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group);
+       n += _mali_osk_snprintf(buf + n, size - n, "\tstate: %d\n", group->state);
+       if (group->gp_core)
+       {
+               n += mali_gp_dump_state(group->gp_core, buf + n, size - n);
+               n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job);
+       }
+       if (group->pp_core)
+       {
+               n += mali_pp_dump_state(group->pp_core, buf + n, size - n);
+               n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n",
+                                       group->pp_running_job, group->pp_running_sub_job);
+       }
+
+       return n;
+}
+#endif
+
+static void mali_group_mmu_page_fault(struct mali_group *group)
+{
        MALI_ASSERT_GROUP_LOCKED(group);
 
-       if (complete_gp && !complete_pp)
+       if (NULL != group->pp_core)
        {
-               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;
+               struct mali_pp_job *pp_job_to_return;
+               u32 pp_sub_job_to_return;
 
-                       MALI_DEBUG_ASSERT_POINTER(gp_job_to_return);
+               MALI_DEBUG_ASSERT_POINTER(group->pp_running_job);
 
-                       mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return));
+               mali_group_post_process_job_pp(group);
 
-                       if(mali_group_other_reschedule_needed(group))
-                       {
-                               mali_group_unlock(group);
-                               mali_pp_scheduler_do_schedule();
-                       }
-                       else
-                       {
-                               mali_group_unlock(group);
-                       }
+               pp_job_to_return = group->pp_running_job;
+               pp_sub_job_to_return = group->pp_running_sub_job;
+               group->state = MALI_GROUP_STATE_IDLE;
+               group->pp_running_job = NULL;
 
-                       mali_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 */
+               mali_group_deactivate_page_directory(group, group->session);
 
-                       return;
+               mali_group_recovery_reset(group); /* This will also clear the page fault itself */
+
+               mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, MALI_FALSE);
+       }
+       else
+       {
+               struct mali_gp_job *gp_job_to_return;
+
+               MALI_DEBUG_ASSERT_POINTER(group->gp_running_job);
+
+               mali_group_post_process_job_gp(group, MALI_FALSE);
+
+               gp_job_to_return = group->gp_running_job;
+               group->state = MALI_GROUP_STATE_IDLE;
+               group->gp_running_job = NULL;
+
+               mali_group_deactivate_page_directory(group, group->session);
+
+               mali_group_recovery_reset(group); /* This will also clear the page fault itself */
+
+               mali_gp_scheduler_job_done(group, gp_job_to_return, MALI_FALSE);
+       }
+}
+
+
+inline mali_bool mali_group_power_is_on_2(struct mali_group *group)
+{
+#ifdef DEBUG
+       if(_mali_osk_lock_get_owner(group->lock) == _mali_osk_get_tid())
+               return group->power_is_on;
+       else 
+               return MALI_FALSE;
+#else
+       return group->power_is_on;
+#endif
+}
+
+_mali_osk_errcode_t mali_group_upper_half_mmu(void * data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_mmu_core *mmu = group->mmu;
+       u32 int_stat;
+
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+       if ( MALI_FALSE == mali_group_power_is_on_2(group) )
+       {
+               if (mmu->id == 2)
+                       malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
+               else if (mmu->id == 3)
+                       malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
+               MALI_DEBUG_PRINT(4, ("Mali MMU: invalid interrupt. <<-- \n"));
+               MALI_SUCCESS;
+       }
+#endif
+       
+       /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
+       int_stat = mali_mmu_get_int_status(mmu);
+       if (0 != int_stat)
+       {
+               struct mali_group *parent = group->parent_group;
+
+               /* page fault or bus error, we thread them both in the same way */
+               mali_mmu_mask_all_interrupts(mmu);
+               if (NULL == parent)
+               {
+                       _mali_osk_wq_schedule_work(group->bottom_half_work_mmu);
                }
                else
                {
-                       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 */
+                       _mali_osk_wq_schedule_work(parent->bottom_half_work_mmu);
                }
+               return _MALI_OSK_ERR_OK;
        }
-       if (complete_pp && !complete_gp)
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+static void mali_group_bottom_half_mmu(void * data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_mmu_core *mmu = group->mmu;
+       u32 rawstat;
+       u32 status;
+
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+       mali_group_lock(group);
+
+       /* TODO: Remove some of these asserts? Will we ever end up in
+        * "physical" bottom half for a member of the virtual group? */
+       MALI_DEBUG_ASSERT(NULL == group->parent_group);
+       MALI_DEBUG_ASSERT(!mali_group_is_in_virtual(group));
+
+       if ( MALI_FALSE == mali_group_power_is_on(group) )
        {
-               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_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mmu->hw_core.description));
+               mali_group_unlock(group);
+               return;
+       }
 
-                       MALI_DEBUG_ASSERT_POINTER(pp_job_to_return);
+       rawstat = mali_mmu_get_rawstat(mmu);
+       status = mali_mmu_get_status(mmu);
 
-                       mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return));
+       MALI_DEBUG_PRINT(4, ("Mali MMU: Bottom half, interrupt 0x%08X, status 0x%08X\n", rawstat, status));
 
-                       if(mali_group_other_reschedule_needed(group))
-                       {
-                               mali_group_unlock(group);
-                               mali_gp_scheduler_do_schedule();
-                       }
-                       else
-                       {
-                               mali_group_unlock(group);
-                       }
+       if (rawstat & (MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR))
+       {
+               /* An actual page fault has occurred. */
+               u32 fault_address = mali_mmu_get_page_fault_addr(mmu);
+               MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n",
+                                (void*)fault_address,
+                                (status >> 6) & 0x1F,
+                                (status & 32) ? "write" : "read",
+                                mmu->hw_core.description));
+
+               mali_group_mmu_page_fault(group);
+       }
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+       if (mmu->id == 2)
+               malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
+       else if (mmu->id == 3)
+               malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
+#endif 
+
+       mali_group_unlock(group);
+}
+
+_mali_osk_errcode_t mali_group_upper_half_gp(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_gp_core *core = group->gp_core;
+       u32 irq_readout;
+
+       irq_readout = mali_gp_get_int_stat(core);
+
+       if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout)
+       {
+               /* Mask out all IRQs from this core until IRQ is handled */
+               mali_gp_mask_all_interrupts(core);
 
-                       mali_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 */
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
 
+               /* We do need to handle this in a bottom half */
+               _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
+               return _MALI_OSK_ERR_OK;
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+static void mali_group_bottom_half_gp(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       u32 irq_readout;
+       u32 irq_errors;
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0);
+
+       mali_group_lock(group);
+
+       if ( MALI_FALSE == mali_group_power_is_on(group) )
+       {
+               MALI_PRINT_ERROR(("Mali group: Interrupt bottom half of %s when core is OFF.", mali_gp_get_hw_core_desc(group->gp_core)));
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       irq_readout = mali_gp_read_rawstat(group->gp_core);
+
+       MALI_DEBUG_PRINT(4, ("Mali group: GP bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core)));
+
+       if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST))
+       {
+               u32 core_status = mali_gp_read_core_status(group->gp_core);
+               if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
+               {
+                       MALI_DEBUG_PRINT(4, ("Mali group: GP job completed, calling group handler\n"));
+                       group->core_timed_out = MALI_FALSE;
+                       mali_group_complete_gp(group, MALI_TRUE);
+                       mali_group_unlock(group);
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                                     0, _mali_osk_get_tid(), 0, 0, 0);
                        return;
                }
-               else
+       }
+
+       /*
+        * Now lets look at the possible error cases (IRQ indicating error or timeout)
+        * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error.
+        */
+       irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM);
+       if (0 != irq_errors)
+       {
+               MALI_PRINT_ERROR(("Mali group: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core)));
+               group->core_timed_out = MALI_FALSE;
+               mali_group_complete_gp(group, MALI_FALSE);
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+       else if (group->core_timed_out) /* SW timeout */
+       {
+               group->core_timed_out = MALI_FALSE;
+               if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->gp_running_job)
                {
-                       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 */
+                       MALI_PRINT(("Mali group: Job %d timed out\n", mali_gp_job_get_id(group->gp_running_job)));
+                       mali_group_complete_gp(group, MALI_FALSE); /* Will release group lock */
+                       mali_group_unlock(group);
+                       return;
                }
        }
-       else if (complete_gp && complete_pp)
+       else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
        {
-               need_group_reset = MALI_TRUE;
+               /* GP wants more memory in order to continue. */
+               MALI_DEBUG_PRINT(3, ("Mali group: PLBU needs more heap memory\n"));
+
+               group->state = MALI_GROUP_STATE_OOM;
+               mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */
+               mali_gp_scheduler_oom(group, group->gp_running_job);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
        }
 
-       if (MALI_TRUE == need_group_reset)
+       /*
+        * The only way to get here is if we only got one of two needed END_CMD_LST
+        * interrupts. Enable all but not the complete interrupt that has been
+        * received and continue to run.
+        */
+       mali_gp_enable_interrupts(group->gp_core, irq_readout & (MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST));
+       mali_group_unlock(group);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+}
+
+void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend)
+{
+       if (NULL == group->pp_running_job)
        {
-               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;
+               /* There is no running jobs, stop the timer. */
+               _mali_osk_timer_del_async(group->timeout_timer);
+       }
 
-               MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n"));
+       if (NULL == group->gp_running_job)
+       {
+               /* Nothing to do */
+               return;
+       }
 
-               group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
-               group->gp_running_job = NULL;
-               if (NULL != gp_job_to_return)
+       mali_gp_update_performance_counters(group->gp_core, group->gp_running_job, suspend);
+
+#if defined(CONFIG_MALI400_PROFILING)
+       if (suspend)
+       {
+               /* @@@@ todo: test this case and see if it is still working*/
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
+                                             mali_gp_job_get_perf_counter_value0(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_value1(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8),
+                                             0, 0);
+       }
+       else
+       {
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
+                                             mali_gp_job_get_perf_counter_value0(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_value1(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8),
+                                             0, 0);
+       }
+#endif
+
+       mali_gp_job_set_current_heap_addr(group->gp_running_job,
+                                         mali_gp_read_plbu_alloc_start_addr(group->gp_core));
+}
+
+_mali_osk_errcode_t mali_group_upper_half_pp(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_pp_core *core = group->pp_core;
+       u32 irq_readout;
+
+       /*
+        * For Mali-450 there is one particular case we need to watch out for:
+        *
+        * Criteria 1) this function call can be due to a shared interrupt,
+        * and not necessary because this core signaled an interrupt.
+        * Criteria 2) this core is a part of a virtual group, and thus it should
+        * not do any post processing.
+        * Criteria 3) this core has actually indicated that is has completed by
+        * having set raw_stat/int_stat registers to != 0
+        *
+        * If all this criteria is meet, then we could incorrectly start post
+        * processing on the wrong group object (this should only happen on the
+        * parent group)
+        */
+#if !defined(CONFIG_MALI400_UPPER_HALF_SCHEDULING)
+       if (mali_group_is_in_virtual(group))
+       {
+               /*
+                * This check is done without the group lock held, which could lead to
+                * a potential race. This is however ok, since we will safely re-check
+                * this with the group lock held at a later stage. This is just an
+                * early out which will strongly benefit shared IRQ systems.
+                */
+               return _MALI_OSK_ERR_OK;
+       }
+#endif
+
+       irq_readout = mali_pp_get_int_stat(core);
+       if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout)
+       {
+               /* Mask out all IRQs from this core until IRQ is handled */
+               mali_pp_mask_all_interrupts(core);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               /* Currently no support for this interrupt event for the virtual PP core */
+               if (!mali_group_is_virtual(group))
                {
-                       mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return));
+                       _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
 
-               group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
-               group->pp_running_job = NULL;
-               if (NULL != pp_job_to_return)
+#if defined(CONFIG_MALI400_UPPER_HALF_SCHEDULING)
+               if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
                {
-                       mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return));
-               }
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                     0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
 
-               /* The reset has to be done after mali_group_deactivate_page_directory() */
-               mali_group_recovery_reset(group);
+                       MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler from upper half\n"));
 
-               if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return))
-               {
-                       schedule_other = MALI_TRUE;
+                       mali_group_lock(group);
+
+                       /* Read int stat again */
+                       irq_readout = mali_pp_read_rawstat(core);
+                       if (!(irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME))
+                       {
+                               /* There was nothing to do */
+                               mali_pp_enable_interrupts(core);
+                               mali_group_unlock(group);
+                               return _MALI_OSK_ERR_OK;
+                       }
+
+                       if (mali_group_is_in_virtual(group))
+                       {
+                               /* We're member of a virtual group, so interrupt should be handled by the virtual group */
+                               mali_pp_enable_interrupts(core);
+                               mali_group_unlock(group);
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                             0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+                               return _MALI_OSK_ERR_FAULT;
+                       }
+
+                       mali_group_complete_pp(group, MALI_TRUE);
+                       /* No need to enable interrupts again, since the core will be reset while completing the job */
+
+                       mali_group_unlock(group);
+
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                     0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+
+                       return _MALI_OSK_ERR_OK;
                }
+#endif
+
+               /* We do need to handle this in a bottom half */
+               _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
+               return _MALI_OSK_ERR_OK;
+       }
 
+       return _MALI_OSK_ERR_FAULT;
+}
+
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+int PP0_int_cnt = 0;
+int mali_PP0_int_cnt(void)
+{
+    return PP0_int_cnt;
+}
+EXPORT_SYMBOL(mali_PP0_int_cnt);
+
+int PP1_int_cnt = 0;
+int mali_PP1_int_cnt(void)
+{
+    return PP1_int_cnt;
+}
+EXPORT_SYMBOL(mali_PP1_int_cnt);
+#endif
+
+static void mali_group_bottom_half_pp(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_pp_core *core = group->pp_core;
+       u32 irq_readout;
+       u32 irq_errors;
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
+                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                     0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+
+       mali_group_lock(group);
+
+       if (mali_group_is_in_virtual(group))
+       {
+               /* We're member of a virtual group, so interrupt should be handled by the virtual group */
+               mali_pp_enable_interrupts(core);
                mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
 
-               if (NULL != gp_job_to_return)
+       if ( MALI_FALSE == mali_group_power_is_on(group) )
+       {
+               MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mali_pp_get_hw_core_desc(core)));
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       irq_readout = mali_pp_read_rawstat(group->pp_core);
+
+       MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
+
+       if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
+       {
+               MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n"));
+               group->core_timed_out = MALI_FALSE;
+               mali_group_complete_pp(group, MALI_TRUE);
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+       if (core->core_id == 0)
+               PP0_int_cnt++;
+       else if (core->core_id == 1)
+               PP1_int_cnt++;
+#endif
+
+       /*
+        * Now lets look at the possible error cases (IRQ indicating error or timeout)
+        * END_OF_FRAME and HANG interrupts are not considered error.
+        */
+       irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG);
+       if (0 != irq_errors)
+       {
+               MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n",
+                                 irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
+               group->core_timed_out = MALI_FALSE;
+               mali_group_complete_pp(group, MALI_FALSE);
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+       else if (group->core_timed_out) /* SW timeout */
+       {
+               group->core_timed_out = MALI_FALSE;
+               if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->pp_running_job)
                {
-                       mali_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 */
+                       MALI_PRINT(("Mali PP: Job %d timed out on core %s\n",
+                                   mali_pp_job_get_id(group->pp_running_job), mali_pp_get_hw_core_desc(core)));
+                       mali_group_complete_pp(group, MALI_FALSE);
+                       mali_group_unlock(group);
                }
-               else if (schedule_other)
+               else
                {
-                       mali_pp_scheduler_do_schedule();
+                       mali_group_unlock(group);
                }
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       /*
+        * We should never get here, re-enable interrupts and continue
+        */
+       if (0 == irq_readout)
+       {
+               MALI_DEBUG_PRINT(3, ("Mali group: No interrupt found on core %s\n",
+                                   mali_pp_get_hw_core_desc(group->pp_core)));
+       }
+       else
+       {
+               MALI_PRINT_ERROR(("Mali group: Unhandled PP interrupt 0x%08X on %s\n", irq_readout,
+                                   mali_pp_get_hw_core_desc(group->pp_core)));
+       }
+       mali_pp_enable_interrupts(core);
+       mali_group_unlock(group);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                     0, _mali_osk_get_tid(), 0, 0, 0);
+}
+
+void mali_group_post_process_job_pp(struct mali_group *group)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       if (NULL == group->gp_running_job)
+       {
+               /* There are no running jobs, stop the timer. */
+               _mali_osk_timer_del_async(group->timeout_timer);
+       }
 
-               if (NULL != pp_job_to_return)
+       /*todo add stop SW counters profiling*/
+
+       if (NULL != group->pp_running_job)
+       {
+               if (MALI_TRUE == mali_group_is_virtual(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 */
+                       struct mali_group *child;
+                       struct mali_group *temp;
+
+                       /* update performance counters from each physical pp core within this virtual group */
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+                       {
+                               mali_pp_update_performance_counters(child->pp_core, group->pp_running_job, group->pp_running_sub_job);
+                       }
+
+#if defined(CONFIG_MALI400_PROFILING)
+                       /* send profiling data per physical core */
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
+                       {
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
+                                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
+                                                             mali_pp_job_get_perf_counter_value0(group->pp_running_job, mali_pp_core_get_id(child->pp_core)),
+                                                             mali_pp_job_get_perf_counter_value1(group->pp_running_job, mali_pp_core_get_id(child->pp_core)),
+                                                             mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8),
+                                                             0, 0);
+                       }
+#endif
                }
-               else if (schedule_other)
+               else
                {
-                       mali_gp_scheduler_do_schedule();
+                       /* update performance counters for a physical group's pp core */
+                       mali_pp_update_performance_counters(group->pp_core, group->pp_running_job, group->pp_running_sub_job);
+
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL,
+                                                     mali_pp_job_get_perf_counter_value0(group->pp_running_job, group->pp_running_sub_job),
+                                                     mali_pp_job_get_perf_counter_value1(group->pp_running_job, group->pp_running_sub_job),
+                                                     mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8),
+                                                     0, 0);
                }
-
-               return;
        }
-
-       mali_group_unlock(group);
 }
 
-#if MALI_STATE_TRACKING
-u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size)
+static void mali_group_timeout(void *data)
 {
-       int n = 0;
+       struct mali_group *group = (struct mali_group *)data;
 
-       n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group);
-       if (group->gp_core)
+       group->core_timed_out = MALI_TRUE;
+
+       if (NULL != 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);
+               /* TODO lower debug level */
+               MALI_DEBUG_PRINT(1, ("Mali group: TIMEOUT on %s\n", mali_gp_get_hw_core_desc(group->gp_core)));
+               _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
        }
-       if (group->pp_core)
+       else
        {
-               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);
+               /* TODO lower debug level */
+               MALI_DEBUG_PRINT(1, ("Mali group: TIMEOUT on %s\n", mali_pp_get_hw_core_desc(group->pp_core)));
+               _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
        }
+}
 
-       return n;
+void mali_group_zap_session(struct mali_group* group, struct mali_session_data *session)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       /* Early out - safe even if mutex is not held */
+       if (group->session != session) return;
+
+       mali_group_lock(group);
+
+       mali_group_remove_session_if_unused(group, session);
+
+       if (group->session == session)
+       {
+               /* The Zap also does the stall and disable_stall */
+               mali_bool zap_success = mali_mmu_zap_tlb(group->mmu);
+               if (MALI_TRUE != zap_success)
+               {
+                       MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n"));
+                       mali_group_mmu_page_fault(group);
+               }
+       }
+
+       mali_group_unlock(group);
 }
-#endif
index 1561d6bf8ef7cd46adb2b4fc6e75d429084642a2..130133c3721e4c7342618c29296b63a3edbea16f 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_GROUP_H__
@@ -13,7 +13,7 @@
 
 #include "linux/jiffies.h"
 #include "mali_osk.h"
-#include "mali_cluster.h"
+#include "mali_l2_cache.h"
 #include "mali_mmu.h"
 #include "mali_gp.h"
 #include "mali_pp.h"
 /** @brief A mali group object represents a MMU and a PP and/or a GP core.
  *
  */
-#define MALI_MAX_NUMBER_OF_GROUPS 9
+#define MALI_MAX_NUMBER_OF_GROUPS 10
 
-struct mali_group;
-
-enum mali_group_event_t
+enum mali_group_core_state
 {
-       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 */
+       MALI_GROUP_STATE_IDLE,
+       MALI_GROUP_STATE_WORKING,
+       MALI_GROUP_STATE_OOM,
+       MALI_GROUP_STATE_IN_VIRTUAL,
+       MALI_GROUP_STATE_JOINING_VIRTUAL,
+       MALI_GROUP_STATE_LEAVING_VIRTUAL,
 };
 
-enum mali_group_core_state
+/**
+ * The structure represents a render group
+ * A render group is defined by all the cores that share the same Mali MMU
+ */
+
+struct mali_group
 {
-       MALI_GROUP_CORE_STATE_IDLE,
-       MALI_GROUP_CORE_STATE_WORKING,
-       MALI_GROUP_CORE_STATE_OOM
+       struct mali_mmu_core        *mmu;
+       struct mali_session_data    *session;
+       int                         page_dir_ref_count;
+
+       mali_bool                   power_is_on;
+       enum mali_group_core_state  state; /* @@@@ TODO: include power_is_on in this state? */
+
+       struct mali_gp_core         *gp_core;
+       struct mali_gp_job          *gp_running_job;
+
+       struct mali_pp_core         *pp_core;
+       struct mali_pp_job          *pp_running_job;
+       u32                         pp_running_sub_job;
+
+       struct mali_l2_cache_core   *l2_cache_core[2];
+       u32                         l2_cache_core_ref_count[2];
+
+       struct mali_dlbu_core       *dlbu_core;
+       struct mali_bcast_unit      *bcast_core;
+
+       _mali_osk_lock_t            *lock;
+
+       _mali_osk_list_t            pp_scheduler_list;
+
+       /* List used for virtual groups. For a virtual group, the list represents the
+        * head element. */
+       _mali_osk_list_t            group_list;
+
+       /* Parent virtual group (if any) */
+       struct mali_group           *parent_group;
+
+       _mali_osk_wq_work_t         *bottom_half_work_mmu;
+       _mali_osk_wq_work_t         *bottom_half_work_gp;
+       _mali_osk_wq_work_t         *bottom_half_work_pp;
+
+       _mali_osk_timer_t           *timeout_timer;
+       mali_bool                   core_timed_out;
 };
 
 /** @brief Create a new Mali group object
@@ -53,11 +88,43 @@ enum mali_group_core_state
  * @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);
+struct mali_group *mali_group_create(struct mali_l2_cache_core *core,
+                                     struct mali_dlbu_core *dlbu,
+                                    struct mali_bcast_unit *bcast);
+
+_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core);
+void mali_group_remove_mmu_core(struct mali_group *group);
+
+_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core);
+void mali_group_remove_gp_core(struct mali_group *group);
+
+_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core);
+void mali_group_remove_pp_core(struct mali_group *group);
+
 void mali_group_delete(struct mali_group *group);
 
+/** @brief Virtual groups */
+void mali_group_add_group(struct mali_group *parent, struct mali_group *child);
+void mali_group_remove_group(struct mali_group *parent, struct mali_group *child);
+struct mali_group *mali_group_acquire_group(struct mali_group *parent);
+
+MALI_STATIC_INLINE mali_bool mali_group_is_virtual(struct mali_group *group)
+{
+       return (NULL != group->dlbu_core);
+}
+
+/** @brief Check if a group is considered as part of a virtual group
+ *
+ * @note A group is considered to be "part of" a virtual group also during the transition
+ *       in to / out of the virtual group.
+ */
+MALI_STATIC_INLINE mali_bool mali_group_is_in_virtual(struct mali_group *group)
+{
+       return (MALI_GROUP_STATE_IN_VIRTUAL == group->state ||
+               MALI_GROUP_STATE_JOINING_VIRTUAL == group->state ||
+               MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state);
+}
+
 /** @brief Reset group
  *
  * This function will reset the entire group, including all the cores present in the group.
@@ -66,6 +133,12 @@ void mali_group_delete(struct mali_group *group);
  */
 void mali_group_reset(struct mali_group *group);
 
+/** @brief Zap MMU TLB on all groups
+ *
+ * Zap TLB on group if \a session is active.
+ */
+void mali_group_zap_session(struct mali_group* group, struct mali_session_data *session);
+
 /** @brief Get pointer to GP core object
  */
 struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group);
@@ -102,9 +175,9 @@ _mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mal
  */
 _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
+/** @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);
+struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr);
 /** @brief Abort GP job
  *
  * Used to abort suspended OOM jobs when user space failed to allocte more memory.
@@ -116,24 +189,6 @@ void mali_group_abort_gp_job(struct mali_group *group, u32 job_id);
  */
 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);
@@ -143,4 +198,13 @@ u32 mali_group_get_glob_num_groups(void);
 
 u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size);
 
+/* MMU-related functions */
+_mali_osk_errcode_t mali_group_upper_half_mmu(void * data);
+
+/* GP-related functions */
+_mali_osk_errcode_t mali_group_upper_half_gp(void *data);
+
+/* PP-related functions */
+_mali_osk_errcode_t mali_group_upper_half_pp(void *data);
+
 #endif /* __MALI_GROUP_H__ */
index 0b0862257c958fbec8c37294451cd4d5ed29e291..2c3f05e6305397110c2112213f8228302b161ce9 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_hw_core.h"
@@ -17,6 +17,7 @@ _mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_o
        core->phys_addr = resource->base;
        core->description = resource->description;
        core->size = reg_size;
+
        if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description))
        {
                core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description);
index b62e843a9c83321265a560bb998437ac4171c923..25d049a46e21088d756be8787cf2aaa390e08959 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_HW_CORE_H__
@@ -26,9 +26,13 @@ struct mali_hw_core
        const char* description;          /**< Name of unit (as specified in device configuration) */
 };
 
-#define MALI_HW_CORE_NO_COUNTER     ((u32)-1)
+/*todo moved to mali_osk.h*/
+/*#define MALI_HW_CORE_NO_COUNTER     ((u32)-1)*/
 #define MALI_HW_CORE_INVALID_VALUE  ((u32)-1)
 
+#define MALI_REG_POLL_COUNT_FAST 1000
+#define MALI_REG_POLL_COUNT_SLOW 1000000
+
 _mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size);
 void mali_hw_core_delete(struct mali_hw_core *core);
 
index a33660bf8fd10a0c6aa06c9fe3ae6e1b13938d15..4ad1a530ef7e59cf9e8242c113dce70b466780f1 100644 (file)
@@ -1,16 +1,18 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_COMMON_H__
 #define __MALI_KERNEL_COMMON_H__
 
+#include "mali_osk.h"
+
 /* Make sure debug is defined when it should be */
 #ifndef DEBUG
        #if defined(_DEBUG)
index f31c50537cb40afad871bc4a01d1a9d153f98907..b45126d2774fb2725d620e72728e94a060337a27 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
 #include "mali_mmu.h"
 #include "mali_mmu_page_directory.h"
 #include "mali_dlbu.h"
+#include "mali_broadcast.h"
 #include "mali_gp.h"
 #include "mali_pp.h"
 #include "mali_gp_scheduler.h"
 #include "mali_pp_scheduler.h"
-#include "mali_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
+#if defined(CONFIG_MALI400_PROFILING)
 #include "mali_osk_profiling.h"
 #endif
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
 #include "mali_profiling_internal.h"
 #endif
 
 
-/** Pointer to table of resource definitions available to the Mali driver.
- *  _mali_osk_resources_init() sets up the pointer to this table.
- */
-static _mali_osk_resource_t *arch_configuration = NULL;
+/* Mali GPU memory. Real values come from module parameter or from device specific data */
+int mali_dedicated_mem_start = 0;
+int mali_dedicated_mem_size = 0;
+int mali_shared_mem_size = 0;
+
+/* Frame buffer memory to be accessible by Mali GPU */
+int mali_fb_start = 0;
+int mali_fb_size = 0;
 
 /** Start profiling from module load? */
 int mali_boot_profiling = 0;
 
-/** Number of resources initialized by _mali_osk_resources_init() */
-static u32 num_resources;
-
 static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN;
 static u32 global_gpu_base_address = 0;
 static u32 global_gpu_major_version = 0;
 static u32 global_gpu_minor_version = 0;
 
-static u32 first_pp_offset = 0;
-
 #define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */
 
 /* timer related */
 int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
 
-static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset)
-{
-       int i;
-       u32 addr = global_gpu_base_address + offset;
-
-       for (i = 0; i < num_resources; i++)
-       {
-               if (type == arch_configuration[i].type && arch_configuration[i].base == addr)
-               {
-                       return &(arch_configuration[i]);
-               }
-       }
-
-       return NULL;
-}
-
-static u32 mali_count_resources(_mali_osk_resource_type_t type)
-{
-       int i;
-       u32 retval = 0;
-
-       for (i = 0; i < num_resources; i++)
-       {
-               if (type == arch_configuration[i].type)
-               {
-                       retval++;
-               }
-       }
-
-       return retval;
-}
-
-
-static _mali_osk_errcode_t mali_parse_gpu_base_and_first_pp_offset_address(void)
+static _mali_osk_errcode_t mali_parse_product_info(void)
 {
-       int i;
-       _mali_osk_resource_t *first_gp_resource = NULL;
-       _mali_osk_resource_t *first_pp_resource = NULL;
+       /*
+        * Mali-200 has the PP core first, while Mali-300, Mali-400 and Mali-450 have the GP core first.
+        * Look at the version register for the first PP core in order to determine the GPU HW revision.
+        */
 
-       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]);
-                       }
-               }
-       }
+       u32 first_pp_offset;
+       _mali_osk_resource_t first_pp_resource;
 
-       if (NULL == first_gp_resource || NULL == first_pp_resource)
+       global_gpu_base_address = _mali_osk_resource_base_address();
+       if (0 == global_gpu_base_address)
        {
-               MALI_PRINT_ERROR(("No GP+PP core specified in config file\n"));
-               return _MALI_OSK_ERR_FAULT;
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
        }
 
-       if (first_gp_resource->base < first_pp_resource->base)
+       /* Find out where the first PP core is located */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL))
        {
-               /* GP is first, so we are dealing with Mali-300, Mali-400 or Mali-450 */
-               global_gpu_base_address = first_gp_resource->base;
+               /* Mali-300/400/450 */
                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-200 */
+               first_pp_offset = 0x0000;
        }
-       MALI_SUCCESS;
-}
 
-static _mali_osk_errcode_t mali_parse_product_info(void)
-{
-       _mali_osk_resource_t *first_pp_resource = NULL;
-
-       /* Find the first PP core */
-       first_pp_resource = mali_find_resource(MALI_PP, first_pp_offset);
-       if (NULL != first_pp_resource)
+       /* Find the first PP core resource (again) */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + first_pp_offset, &first_pp_resource))
        {
                /* Create a dummy PP object for this core so that we can read the version register */
-               struct mali_group *group = mali_group_create(NULL, NULL);
+               struct mali_group *group = mali_group_create(NULL, NULL, NULL);
                if (NULL != group)
                {
-                       /*struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group, 0);*/
-                       struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group);
+                       struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE);
                        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;
@@ -183,7 +123,7 @@ static _mali_osk_errcode_t mali_parse_product_info(void)
                                                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));
+                                               MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version));
                                                return _MALI_OSK_ERR_FAULT;
                                }
 
@@ -207,77 +147,107 @@ static _mali_osk_errcode_t mali_parse_product_info(void)
        return _MALI_OSK_ERR_FAULT;
 }
 
-static void mali_delete_clusters(void)
+
+void mali_resource_count(u32 *pp_count, u32 *l2_count)
+{
+       *pp_count = 0;
+       *l2_count = 0;
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL))
+       {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL))
+       {
+               ++(*pp_count);
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL))
+       {
+               ++(*l2_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL))
+       {
+               ++(*l2_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL))
+       {
+               ++(*l2_count);
+       }
+}
+
+static void mali_delete_l2_cache_cores(void)
 {
        u32 i;
-       u32 number_of_clusters = mali_cluster_get_glob_num_clusters();
+       u32 number_of_l2_ccores = mali_l2_cache_core_get_glob_num_l2_cores();
 
-       for (i = 0; i < number_of_clusters; i++)
+       for (i = 0; i < number_of_l2_ccores; i++)
        {
-               mali_cluster_delete(mali_cluster_get_global_cluster(i));
+               mali_l2_cache_delete(mali_l2_cache_core_get_glob_l2_core(i));
        }
 }
 
-static _mali_osk_errcode_t mali_create_cluster(_mali_osk_resource_t *resource)
+static _mali_osk_errcode_t mali_create_l2_cache_core(_mali_osk_resource_t *resource)
 {
        if (NULL != resource)
        {
                struct mali_l2_cache_core *l2_cache;
 
-               if (mali_l2_cache_core_get_glob_num_l2_cores() >= mali_l2_cache_core_get_max_num_l2_cores())
-               {
-                       MALI_PRINT_ERROR(("Found too many L2 cache core objects, max %u is supported\n", mali_l2_cache_core_get_max_num_l2_cores()));
-                       return _MALI_OSK_ERR_FAULT;
-               }
-
-               MALI_DEBUG_PRINT(3, ("Found L2 cache %s, starting new cluster\n", resource->description));
+               MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description));
 
-               /*l2_cache = mali_l2_cache_create(resource, global_num_l2_cache_cores);*/
                l2_cache = mali_l2_cache_create(resource);
                if (NULL == l2_cache)
                {
                        MALI_PRINT_ERROR(("Failed to create L2 cache object\n"));
                        return _MALI_OSK_ERR_FAULT;
                }
-
-               if (NULL == mali_cluster_create(l2_cache))
-               {
-                       MALI_PRINT_ERROR(("Failed to create cluster object\n"));
-                       mali_l2_cache_delete(l2_cache);
-                       return _MALI_OSK_ERR_FAULT;
-               }
-       }
-       else
-       {
-               mali_cluster_create(NULL);
-               if (NULL == mali_cluster_get_global_cluster(0))
-               {
-                       MALI_PRINT_ERROR(("Failed to create cluster object\n"));
-                       return _MALI_OSK_ERR_FAULT;
-               }
        }
+       MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n"));
 
-       MALI_DEBUG_PRINT(3, ("Created cluster object\n"));
        return _MALI_OSK_ERR_OK;
 }
 
-static _mali_osk_errcode_t mali_parse_config_cluster(void)
+static _mali_osk_errcode_t mali_parse_config_l2_cache(void)
 {
        if (_MALI_PRODUCT_ID_MALI200 == global_product_id)
        {
-               /* Create dummy cluster without L2 cache */
-               return mali_create_cluster(NULL);
+               /* Create dummy L2 cache - nothing happens here!!! */
+               return mali_create_l2_cache_core(NULL);
        }
        else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || _MALI_PRODUCT_ID_MALI400 == global_product_id)
        {
-               _mali_osk_resource_t *l2_resource = mali_find_resource(MALI_L2, 0x1000);
-               if (NULL == l2_resource)
+               _mali_osk_resource_t l2_resource;
+               if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_resource))
                {
                        MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n"));
                        return _MALI_OSK_ERR_FAULT;
                }
 
-               return mali_create_cluster(l2_resource);
+               return mali_create_l2_cache_core(&l2_resource);
        }
        else if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
        {
@@ -287,17 +257,16 @@ static _mali_osk_errcode_t mali_parse_config_cluster(void)
                 * 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;
+               _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)
+               if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, &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);
+                       MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n"));
+                       ret = mali_create_l2_cache_core(&l2_gp_resource);
                        if (_MALI_OSK_ERR_OK != ret)
                        {
                                return ret;
@@ -310,12 +279,11 @@ static _mali_osk_errcode_t mali_parse_config_cluster(void)
                }
 
                /* Make cluster for first PP core group */
-               l2_pp_grp0_resource = mali_find_resource(MALI_L2, 0x1000);
-               if (NULL != l2_pp_grp0_resource)
+               if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, &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);
+                       MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n"));
+                       ret = mali_create_l2_cache_core(&l2_pp_grp0_resource);
                        if (_MALI_OSK_ERR_OK != ret)
                        {
                                return ret;
@@ -328,12 +296,11 @@ static _mali_osk_errcode_t mali_parse_config_cluster(void)
                }
 
                /* 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)
+               if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, &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);
+                       MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n"));
+                       ret = mali_create_l2_cache_core(&l2_pp_grp1_resource);
                        if (_MALI_OSK_ERR_OK != ret)
                        {
                                return ret;
@@ -344,71 +311,124 @@ static _mali_osk_errcode_t mali_parse_config_cluster(void)
        return _MALI_OSK_ERR_OK;
 }
 
-static _mali_osk_errcode_t mali_create_group(struct mali_cluster *cluster,
+static _mali_osk_errcode_t mali_create_group(struct mali_l2_cache_core *cache,
                                              _mali_osk_resource_t *resource_mmu,
                                              _mali_osk_resource_t *resource_gp,
                                              _mali_osk_resource_t *resource_pp)
 {
        struct mali_mmu_core *mmu;
        struct mali_group *group;
-       struct mali_pp_core *pp;
 
        MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
 
-       /* Create the MMU object */
-       mmu = mali_mmu_create(resource_mmu);
-       if (NULL == mmu)
-       {
-               MALI_PRINT_ERROR(("Failed to create MMU object\n"));
-               return _MALI_OSK_ERR_FAULT;
-       }
-
        /* Create the group object */
-       group = mali_group_create(cluster, mmu);
+       group = mali_group_create(cache, NULL, NULL);
        if (NULL == group)
        {
                MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description));
-               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);
+       /* Create the MMU object inside group */
+       mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE);
+       if (NULL == mmu)
+       {
+               MALI_PRINT_ERROR(("Failed to create MMU object\n"));
+               mali_group_delete(group);
+               return _MALI_OSK_ERR_FAULT;
+       }
 
        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))
+               struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group);
+               if (NULL == gp_core)
                {
                        /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
                        MALI_PRINT_ERROR(("Failed to create GP object\n"));
+                       mali_group_delete(group);
                        return _MALI_OSK_ERR_FAULT;
                }
-
-               /* Add GP object to this group */
-               MALI_DEBUG_PRINT(3, ("Adding GP %s to group\n", resource_gp->description));
-               mali_group_add_gp_core(group, mali_gp_get_global_gp_core());
        }
 
        if (NULL != resource_pp)
        {
-               /* Create the PP core object inside this group */
-               pp = mali_pp_create(resource_pp, group);
+               struct mali_pp_core *pp_core;
 
-               if (NULL == pp)
+               /* Create the PP core object inside this group */
+               pp_core = mali_pp_create(resource_pp, group, MALI_FALSE);
+               if (NULL == pp_core)
                {
                        /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
                        MALI_PRINT_ERROR(("Failed to create PP object\n"));
+                       mali_group_delete(group);
                        return _MALI_OSK_ERR_FAULT;
                }
+       }
+
+       /* Reset group */
+       mali_group_reset(group);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast,
+                                                    _mali_osk_resource_t *resource_pp_bcast,
+                                                    _mali_osk_resource_t *resource_dlbu,
+                                                    _mali_osk_resource_t *resource_bcast)
+{
+       struct mali_mmu_core *mmu_pp_bcast_core;
+       struct mali_pp_core *pp_bcast_core;
+       struct mali_dlbu_core *dlbu_core;
+       struct mali_bcast_unit *bcast_core;
+       struct mali_group *group;
+
+       MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
+
+       /* Create the DLBU core object */
+       dlbu_core = mali_dlbu_create(resource_dlbu);
+       if (NULL == dlbu_core)
+       {
+               MALI_PRINT_ERROR(("Failed to create DLBU object \n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the Broadcast unit core */
+       bcast_core = mali_bcast_unit_create(resource_bcast);
+       if (NULL == bcast_core)
+       {
+               MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n"));
+               mali_dlbu_delete(dlbu_core);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the group object */
+       group = mali_group_create(NULL, dlbu_core, bcast_core);
+       if (NULL == group)
+       {
+               MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
+               mali_bcast_unit_delete(bcast_core);
+               mali_dlbu_delete(dlbu_core);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the MMU object inside group */
+       mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE);
+       if (NULL == mmu_pp_bcast_core)
+       {
+               MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n"));
+               mali_group_delete(group);
+               return _MALI_OSK_ERR_FAULT;
+       }
 
-               /* 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);
+       /* Create the PP core object inside this group */
+       pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE);
+       if (NULL == pp_bcast_core)
+       {
+               /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
+               MALI_PRINT_ERROR(("Failed to create PP object\n"));
+               mali_group_delete(group);
+               return _MALI_OSK_ERR_FAULT;
        }
 
        return _MALI_OSK_ERR_OK;
@@ -418,24 +438,21 @@ 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_osk_resource_t resource_gp;
+               _mali_osk_resource_t resource_pp;
+               _mali_osk_resource_t resource_mmu;
 
-               resource_gp  = mali_find_resource(MALI_GP, 0x02000);
-               resource_pp  = mali_find_resource(MALI_PP, 0x00000);
-               resource_mmu = mali_find_resource(MMU, 0x03000);
+               MALI_DEBUG_ASSERT(1 == mali_l2_cache_core_get_glob_num_l2_cores());
 
-               if (NULL == resource_mmu || NULL == resource_gp || NULL == resource_pp)
+               if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_gp) ||
+                   _MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_pp) ||
+                   _MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_mmu))
                {
                        /* 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);
+               return mali_create_group(mali_l2_cache_core_get_glob_l2_core(0), &resource_mmu, &resource_gp, &resource_pp);
        }
        else if (_MALI_PRODUCT_ID_MALI300 == global_product_id ||
                 _MALI_PRODUCT_ID_MALI400 == global_product_id ||
@@ -446,56 +463,89 @@ static _mali_osk_errcode_t mali_parse_config_groups(void)
                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();
+
+               _mali_osk_resource_t resource_gp;
+               _mali_osk_resource_t resource_gp_mmu;
+               _mali_osk_resource_t resource_pp[MALI_MAX_NUMBER_OF_PP_CORES];
+               _mali_osk_resource_t resource_pp_mmu[MALI_MAX_NUMBER_OF_PP_CORES];
+               _mali_osk_resource_t resource_pp_mmu_bcast;
+               _mali_osk_resource_t resource_pp_bcast;
+               _mali_osk_resource_t resource_dlbu;
+               _mali_osk_resource_t resource_bcast;
+               _mali_osk_errcode_t resource_gp_found;
+               _mali_osk_errcode_t resource_gp_mmu_found;
+               _mali_osk_errcode_t resource_pp_found[MALI_MAX_NUMBER_OF_PP_CORES];
+               _mali_osk_errcode_t resource_pp_mmu_found[MALI_MAX_NUMBER_OF_PP_CORES];
+               _mali_osk_errcode_t resource_pp_mmu_bcast_found;
+               _mali_osk_errcode_t resource_pp_bcast_found;
+               _mali_osk_errcode_t resource_dlbu_found;
+               _mali_osk_errcode_t resource_bcast_found;
 
                if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
                {
-                       /* Mali-450 has separate L2s for GP, and PP core group(s) */
+                       /* Mali-450 have 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])
+               resource_gp_found = _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_gp);
+               resource_gp_mmu_found = _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_gp_mmu);
+               resource_pp_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x08000, &(resource_pp[0]));
+               resource_pp_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x0A000, &(resource_pp[1]));
+               resource_pp_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x0C000, &(resource_pp[2]));
+               resource_pp_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x0E000, &(resource_pp[3]));
+               resource_pp_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x28000, &(resource_pp[4]));
+               resource_pp_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x2A000, &(resource_pp[5]));
+               resource_pp_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x2C000, &(resource_pp[6]));
+               resource_pp_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x2E000, &(resource_pp[7]));
+               resource_pp_mmu_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x04000, &(resource_pp_mmu[0]));
+               resource_pp_mmu_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x05000, &(resource_pp_mmu[1]));
+               resource_pp_mmu_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x06000, &(resource_pp_mmu[2]));
+               resource_pp_mmu_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x07000, &(resource_pp_mmu[3]));
+               resource_pp_mmu_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x1C000, &(resource_pp_mmu[4]));
+               resource_pp_mmu_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x1D000, &(resource_pp_mmu[5]));
+               resource_pp_mmu_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x1E000, &(resource_pp_mmu[6]));
+               resource_pp_mmu_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x1F000, &(resource_pp_mmu[7]));
+
+
+               if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
+               {
+                       resource_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x13000, &resource_bcast);
+                       resource_dlbu_found = _mali_osk_resource_find(global_gpu_base_address + 0x14000, &resource_dlbu);
+                       resource_pp_mmu_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x15000, &resource_pp_mmu_bcast);
+                       resource_pp_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x16000, &resource_pp_bcast);
+
+                       if (_MALI_OSK_ERR_OK != resource_bcast_found ||
+                           _MALI_OSK_ERR_OK != resource_dlbu_found ||
+                           _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found ||
+                           _MALI_OSK_ERR_OK != resource_pp_bcast_found)
+                       {
+                               /* Missing mandatory core(s) for Mali-450 */
+                               MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n"));
+                               return _MALI_OSK_ERR_FAULT;
+                       }
+               }
+
+               if (_MALI_OSK_ERR_OK != resource_gp_found ||
+                   _MALI_OSK_ERR_OK != resource_gp_mmu_found ||
+                   _MALI_OSK_ERR_OK != resource_pp_found[0] ||
+                   _MALI_OSK_ERR_OK != resource_pp_mmu_found[0])
                {
                        /* Missing mandatory core(s) */
-                       MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU (0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
-                                            resource_gp, resource_gp_mmu, resource_pp[0], resource_pp_mmu[0]));
+                       MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n"));
                        return _MALI_OSK_ERR_FAULT;
                }
 
-               MALI_DEBUG_ASSERT(1 <= mali_cluster_get_glob_num_clusters());
-               err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_gp), resource_gp_mmu, resource_gp, NULL);
+               MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores());
+               err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(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]);
+               MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */
+               err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0]);
                if (err != _MALI_OSK_ERR_OK)
                {
                        return err;
@@ -504,9 +554,9 @@ static _mali_osk_errcode_t mali_parse_config_groups(void)
                /* 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])
+                       if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i])
                        {
-                               err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[i], NULL, resource_pp[i]);
+                               err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i]);
                                if (err != _MALI_OSK_ERR_OK)
                                {
                                        return err;
@@ -515,18 +565,28 @@ static _mali_osk_errcode_t mali_parse_config_groups(void)
                }
 
                /* 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 */
+               for (i = 4; i < MALI_MAX_NUMBER_OF_PP_CORES; i++) /* Second half of the PP cores belong to second core group */
                {
-                       if (NULL != resource_pp[i])
+                       if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[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]);
+                               MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */
+                               err = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i]);
                                if (err != _MALI_OSK_ERR_OK)
                                {
                                        return err;
                                }
                        }
                }
+
+               if(_MALI_PRODUCT_ID_MALI450 == global_product_id)
+               {
+                       err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast);
+                       if (_MALI_OSK_ERR_OK != err)
+                       {
+                               return err;
+                       }
+               }
+
        }
 
        return _MALI_OSK_ERR_OK;
@@ -534,77 +594,125 @@ static _mali_osk_errcode_t mali_parse_config_groups(void)
 
 static _mali_osk_errcode_t mali_parse_config_pmu(void)
 {
-       _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
-       _mali_osk_resource_t *resource_pmu;
-       u32 number_of_pp_cores;
-       u32 number_of_l2_caches;
-
-       resource_pmu = mali_find_resource(PMU, 0x02000);
-       number_of_pp_cores = mali_count_resources(MALI_PP);
-       number_of_l2_caches = mali_count_resources(MALI_L2);
+       _mali_osk_resource_t resource_pmu;
 
-       if (NULL != resource_pmu)
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu))
        {
-               if (NULL == mali_pmu_create(resource_pmu, number_of_pp_cores, number_of_l2_caches))
+               u32 number_of_pp_cores = 0;
+               u32 number_of_l2_caches = 0;
+
+               mali_resource_count(&number_of_pp_cores, &number_of_l2_caches);
+
+               if (NULL == mali_pmu_create(&resource_pmu, number_of_pp_cores, number_of_l2_caches))
                {
-                       err = _MALI_OSK_ERR_FAULT;
+                       return _MALI_OSK_ERR_FAULT;
                }
        }
-       return err;
+
+       /* It's ok if the PMU doesn't exist */
+       return _MALI_OSK_ERR_OK;
 }
 
 static _mali_osk_errcode_t mali_parse_config_memory(void)
 {
-       int i;
        _mali_osk_errcode_t ret;
 
-       for(i = 0; i < num_resources; i++)
+       if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size)
        {
-               switch(arch_configuration[i].type)
+               /* Memory settings are not overridden by module parameters, so use device settings */
+               struct _mali_osk_device_data data = { 0, };
+
+               if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data))
                {
-                       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;
+                       /* Use device specific settings (if defined) */
+                       mali_dedicated_mem_start = data.dedicated_mem_start;
+                       mali_dedicated_mem_size = data.dedicated_mem_size;
+                       mali_shared_mem_size = data.shared_mem_size;
+               }
+
+               if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size)
+               {
+                       /* No GPU memory specified */
+                       return _MALI_OSK_ERR_INVALID_ARGS;
+               }
+
+               MALI_DEBUG_PRINT(2, ("Using device defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
+                                    mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
+       }
+       else
+       {
+               MALI_DEBUG_PRINT(2, ("Using module defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
+                                    mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
+       }
+
+       if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start)
+       {
+               /* Dedicated memory */
+               ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size);
+               if (_MALI_OSK_ERR_OK != ret)
+               {
+                       MALI_PRINT_ERROR(("Failed to register dedicated memory\n"));
+                       mali_memory_terminate();
+                       return ret;
                }
        }
+
+       if (0 < mali_shared_mem_size)
+       {
+               /* Shared OS memory */
+               ret = mali_memory_core_resource_os_memory(mali_shared_mem_size);
+               if (_MALI_OSK_ERR_OK != ret)
+               {
+                       MALI_PRINT_ERROR(("Failed to register shared OS memory\n"));
+                       mali_memory_terminate();
+                       return ret;
+               }
+       }
+
+       if (0 == mali_fb_start && 0 == mali_fb_size)
+       {
+               /* Frame buffer settings are not overridden by module parameters, so use device settings */
+               struct _mali_osk_device_data data = { 0, };
+
+               if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data))
+               {
+                       /* Use device specific settings (if defined) */
+                       mali_fb_start = data.fb_start;
+                       mali_fb_size = data.fb_size;
+               }
+
+               MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n",
+                                    mali_fb_size, mali_fb_start));
+       }
+       else
+       {
+               MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n",
+                                    mali_fb_size, mali_fb_start));
+       }
+
+       if (0 != mali_fb_size)
+       {
+               /* Register frame buffer */
+               ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size);
+               if (_MALI_OSK_ERR_OK != ret)
+               {
+                       MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n"));
+                       mali_memory_terminate();
+                       return ret;
+               }
+       }
+
        return _MALI_OSK_ERR_OK;
 }
 
 _mali_osk_errcode_t mali_initialize_subsystems(void)
 {
        _mali_osk_errcode_t err;
-       mali_bool is_pmu_enabled;
 
        err = mali_session_initialize();
        if (_MALI_OSK_ERR_OK != err) goto session_init_failed;
 
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
        err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
        if (_MALI_OSK_ERR_OK != err)
        {
@@ -613,11 +721,6 @@ _mali_osk_errcode_t mali_initialize_subsystems(void)
        }
 #endif
 
-       /* Get data from config.h */
-       err = _mali_osk_resources_init(&arch_configuration, &num_resources);
-       if (_MALI_OSK_ERR_OK != err) goto osk_resources_init_failed;
-
-       /* Initialize driver subsystems */
        err = mali_memory_initialize();
        if (_MALI_OSK_ERR_OK != err) goto memory_init_failed;
 
@@ -625,22 +728,17 @@ _mali_osk_errcode_t mali_initialize_subsystems(void)
        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);
+       err = _mali_osk_pm_dev_ref_add();
+       if (_MALI_OSK_ERR_OK != err) goto pm_always_on_failed;
 
        /* Detect which Mali GPU we are dealing with */
        err = mali_parse_product_info();
@@ -652,7 +750,6 @@ _mali_osk_errcode_t mali_initialize_subsystems(void)
        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();
@@ -660,7 +757,7 @@ _mali_osk_errcode_t mali_initialize_subsystems(void)
        }
 
        /* Start configuring the actual Mali hardware. */
-       err = mali_parse_config_cluster();
+       err = mali_parse_config_l2_cache();
        if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
        err = mali_parse_config_groups();
        if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
@@ -673,51 +770,50 @@ _mali_osk_errcode_t mali_initialize_subsystems(void)
        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);
+       /* Allowing the system to be turned off */
+       _mali_osk_pm_dev_ref_dec();
+
        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();
-       }
+       mali_delete_l2_cache_cores(); /* Delete L2 cache cores even if config parsing failed. */
 dlbu_init_failed:
-       mali_mmu_terminate();
+       mali_dlbu_terminate();
 mmu_init_failed:
+       mali_mmu_terminate();
        /* Nothing to roll back */
 product_info_parsing_failed:
+       /* Allowing the system to be turned off */
+       _mali_osk_pm_dev_ref_dec();
+pm_always_on_failed:
        mali_pm_terminate();
 pm_init_failed:
-       if (is_pmu_enabled)
        {
-               mali_pmu_delete(mali_pmu_get_global_pmu_core());
+               struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+               if (NULL != pmu)
+               {
+                       mali_pmu_delete(pmu);
+               }
        }
 parse_pmu_config_failed:
-parse_gpu_base_address_failed:
+       /* undoing mali_parse_config_memory() is done by mali_memory_terminate() */
 parse_memory_config_failed:
        mali_memory_terminate();
 memory_init_failed:
-       _mali_osk_resources_term(&arch_configuration, num_resources);
-osk_resources_init_failed:
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
        _mali_osk_profiling_term();
 #endif
        mali_session_terminate();
@@ -727,47 +823,38 @@ session_init_failed:
 
 void mali_terminate_subsystems(void)
 {
-       struct mali_pmu_core *pmu;
+       struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
 
        MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n"));
 
        /* shut down subsystems in reverse order from startup */
 
-       mali_pm_always_on(MALI_TRUE); /* Mali will be powered off once PM subsystem terminates */
+       /* We need the GPU to be powered up for the terminate sequence */
+       _mali_osk_pm_dev_ref_add();
 
-#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. */
-
+       mali_delete_l2_cache_cores();
        if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
        {
                mali_dlbu_terminate();
        }
-
        mali_mmu_terminate();
-
-       pmu = mali_pmu_get_global_pmu_core();
        if (NULL != pmu)
        {
                mali_pmu_delete(pmu);
        }
-
        mali_pm_terminate();
-
        mali_memory_terminate();
-
-       _mali_osk_resources_term(&arch_configuration, num_resources);
-
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
        _mali_osk_profiling_term();
 #endif
 
+       /* Allowing the system to be turned off */
+       _mali_osk_pm_dev_ref_dec();
+
        mali_session_terminate();
 }
 
@@ -776,19 +863,6 @@ _mali_product_id_t mali_kernel_core_get_product_id(void)
        return global_product_id;
 }
 
-void mali_kernel_core_wakeup(void)
-{
-       u32 i;
-       u32 glob_num_clusters = mali_cluster_get_glob_num_clusters();
-       struct mali_cluster *cluster;
-
-       for (i = 0; i < glob_num_clusters; i++)
-       {
-               cluster = mali_cluster_get_global_cluster(i);
-               mali_cluster_reset(cluster);
-       }
-}
-
 _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args )
 {
        MALI_DEBUG_ASSERT_POINTER(args);
@@ -813,7 +887,7 @@ _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args
 _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_t * notification;
        _mali_osk_notification_queue_t *queue;
 
        /* check input */
@@ -866,7 +940,7 @@ _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)
+       if (NULL == notification)
        {
                MALI_PRINT_ERROR( ("Failed to create notification object\n"));
                return _MALI_OSK_ERR_NOMEM;
@@ -879,57 +953,76 @@ _mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *a
 
 _mali_osk_errcode_t _mali_ukk_open(void **context)
 {
-       struct mali_session_data *session_data;
+       struct mali_session_data *session;
 
        /* allocated struct to track this session */
-       session_data = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data));
-       MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM);
+       session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data));
+       MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM);
 
-       MALI_DEBUG_PRINT(2, ("Session starting\n"));
+       MALI_DEBUG_PRINT(3, ("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)
+       session->ioctl_queue = _mali_osk_notification_queue_init();
+       if (NULL == session->ioctl_queue)
        {
-               _mali_osk_free(session_data);
+               _mali_osk_free(session);
                MALI_ERROR(_MALI_OSK_ERR_NOMEM);
        }
 
-       session_data->page_directory = mali_mmu_pagedir_alloc();
-       if (NULL == session_data->page_directory)
+       session->page_directory = mali_mmu_pagedir_alloc();
+       if (NULL == session->page_directory)
        {
-               _mali_osk_notification_queue_term(session_data->ioctl_queue);
-               _mali_osk_free(session_data);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
                MALI_ERROR(_MALI_OSK_ERR_NOMEM);
        }
 
-       if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session_data->page_directory, MALI_DLB_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE))
+       if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE))
        {
                MALI_PRINT_ERROR(("Failed to map DLB page into session\n"));
-               _mali_osk_notification_queue_term(session_data->ioctl_queue);
-               _mali_osk_free(session_data);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
                MALI_ERROR(_MALI_OSK_ERR_NOMEM);
        }
 
        if (0 != mali_dlbu_phys_addr)
        {
-               mali_mmu_pagedir_update(session_data->page_directory, MALI_DLB_VIRT_ADDR, mali_dlbu_phys_addr, _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD);
+               mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr,
+                                       _MALI_OSK_MALI_PAGE_SIZE, MALI_CACHE_STANDARD);
        }
 
-       if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session_data))
+       if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session))
        {
-               mali_mmu_pagedir_free(session_data->page_directory);
-               _mali_osk_notification_queue_term(session_data->ioctl_queue);
-               _mali_osk_free(session_data);
+               mali_mmu_pagedir_free(session->page_directory);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
                MALI_ERROR(_MALI_OSK_ERR_NOMEM);
        }
 
-       *context = (void*)session_data;
+#ifdef CONFIG_SYNC
+       _mali_osk_list_init(&session->pending_jobs);
+       session->pending_jobs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK,
+                                                        0, _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS);
+       if (NULL == session->pending_jobs_lock)
+       {
+               MALI_PRINT_ERROR(("Failed to create pending jobs lock\n"));
+               mali_memory_session_end(session);
+               mali_mmu_pagedir_free(session->page_directory);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+#endif
+
+       *context = (void*)session;
 
        /* Add session to the list of all sessions. */
-       mali_session_add(session_data);
+       mali_session_add(session);
 
-       MALI_DEBUG_PRINT(3, ("Session started\n"));
+       /* Initialize list of jobs on this session */
+       _MALI_OSK_INIT_LIST_HEAD(&session->job_list);
+
+       MALI_DEBUG_PRINT(2, ("Session started\n"));
        MALI_SUCCESS;
 }
 
@@ -944,6 +1037,38 @@ _mali_osk_errcode_t _mali_ukk_close(void **context)
        /* Remove session from list of all sessions. */
        mali_session_remove(session);
 
+       /* Abort pending jobs */
+#ifdef CONFIG_SYNC
+       {
+               _mali_osk_list_t tmp_job_list;
+               struct mali_pp_job *job, *tmp;
+               _MALI_OSK_INIT_LIST_HEAD(&tmp_job_list);
+
+               _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+               /* Abort asynchronous wait on fence. */
+               _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &session->pending_jobs, struct mali_pp_job, list)
+               {
+                       MALI_DEBUG_PRINT(2, ("Sync: Aborting wait for session %x job %x\n", session, job));
+                       if (sync_fence_cancel_async(job->pre_fence, &job->sync_waiter))
+                       {
+                               MALI_DEBUG_PRINT(2, ("Sync: Failed to abort job %x\n", job));
+                       }
+                       _mali_osk_list_add(&job->list, &tmp_job_list);
+               }
+               _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+
+               _mali_osk_wq_flush();
+
+               _mali_osk_lock_term(session->pending_jobs_lock);
+
+               /* Delete jobs */
+               _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &tmp_job_list, struct mali_pp_job, list)
+               {
+                       mali_pp_job_delete(job);
+               }
+       }
+#endif
+
        /* Abort queued and running jobs */
        mali_gp_scheduler_abort_session(session);
        mali_pp_scheduler_abort_session(session);
@@ -952,7 +1077,7 @@ _mali_osk_errcode_t _mali_ukk_close(void **context)
         * 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_wq_flush();
 
        /* Free remaining memory allocated to this session */
        mali_memory_session_end(session);
index 0ac967eabe0b24c40fa625d7d47f9d793ef3ee54..5dec47237f53d3ba5f9e1d5d5545b17f0b17f9f7 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_CORE_H__
@@ -28,8 +28,6 @@ _mali_osk_errcode_t mali_initialize_subsystems(void);
 
 void mali_terminate_subsystems(void);
 
-void mali_kernel_core_wakeup(void);
-
 _mali_product_id_t mali_kernel_core_get_product_id(void);
 
 u32 _mali_kernel_core_dump_state(char* buf, u32 size);
index b9f05ca4965a007645712331633c59dca01975e7..18dd132642a48df61feb33a7c4b3995d2d92a0f6 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
index 82ed94d6ffef2794efa3b071501394141dff1561..7364f262e8a647d45732e18cd687ebfa4f3f8cc1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 167b01fd3e0dbd7d40bc4cf1704c82bc41deae60..0b823f745202551bf99d9f1a5cfd6f1d693dc6cf 100644 (file)
@@ -1,15 +1,14 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
-#include "mali_kernel_core.h"
 #include "mali_kernel_memory_engine.h"
 #include "mali_osk.h"
 
@@ -95,7 +94,7 @@ static u32 os_allocator_stat(mali_physical_memory_allocator * allocator)
 static void os_allocator_destroy(mali_physical_memory_allocator * allocator)
 {
        os_allocator * info;
-       MALI_DEBUG_ASSERT_POINTER(allocator);
+        MALI_DEBUG_ASSERT_POINTER(allocator);
        MALI_DEBUG_ASSERT_POINTER(allocator->ctx);
        info = (os_allocator*)allocator->ctx;
        _mali_osk_lock_term(info->mutex);
index 59e6494c5eb633eb8a5c0dee3c1ab3477e1725c3..41186684c84907482c21915bc61d339d3ff51d03 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_MEM_OS_H__
index d770e3e666afebdb829a366837eb218ab3f95e2a..bc0ab98b16c659e17d60e4251fa8b53ea5442808 100644 (file)
@@ -1,15 +1,14 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
-#include "mali_kernel_core.h"
 #include "mali_kernel_memory_engine.h"
 #include "mali_osk.h"
 #include "mali_osk_list.h"
index 3b41cee4a12d7cfc915cc7a8ac6b1ab43c87e09e..0835c642d17fdaccbe15db42e4c52f629dfbe9e3 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_MEMORY_ENGINE_H__
index a374dbfed7009f38a01a43a13ef4b9c7df547fd8..9ad0b616f71b2e1ca12752263345c1d350c574d3 100644 (file)
@@ -1,20 +1,19 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_utilization.h"
 #include "mali_osk.h"
-#include "mali_platform.h"
+#include "mali_osk_mali.h"
+#include "mali_kernel_common.h"
 
 /* Define how often to calculate and report GPU utilization, in milliseconds */
-#define MALI_GPU_UTILIZATION_TIMEOUT 1000
-
 static _mali_osk_lock_t *time_data_lock;
 
 static _mali_osk_atomic_t num_running_cores;
@@ -26,6 +25,10 @@ static u64 accumulated_work_time = 0;
 static _mali_osk_timer_t *utilization_timer = NULL;
 static mali_bool timer_running = MALI_FALSE;
 
+static u32 last_utilization = 0 ;
+
+static u32 mali_utilization_timeout = 1000;
+void (*mali_utilization_callback)(unsigned int) = NULL;
 
 static void calculate_gpu_utilization(void* arg)
 {
@@ -47,7 +50,10 @@ static void calculate_gpu_utilization(void* arg)
                _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
 
                /* No work done for this period, report zero usage */
-               mali_gpu_utilization_handler(0);
+               if (NULL != mali_utilization_callback)
+               {
+                       mali_utilization_callback(0);
+               }
 
                return;
        }
@@ -97,21 +103,50 @@ static void calculate_gpu_utilization(void* arg)
 
        utilization = work_normalized / period_normalized;
 
+       last_utilization = utilization;
+
        accumulated_work_time = 0;
        period_start_time = time_now; /* starting a new period */
 
        _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
 
-       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT));
-
+       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout));
 
-       mali_gpu_utilization_handler(utilization);
+       if (NULL != mali_utilization_callback)
+       {
+               mali_utilization_callback(utilization);
+       }
 }
 
 _mali_osk_errcode_t mali_utilization_init(void)
 {
+#if USING_GPU_UTILIZATION
+       struct _mali_osk_device_data data;
+       if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data))
+       {
+               /* Use device specific settings (if defined) */
+               if (0 != data.utilization_interval)
+               {
+                       mali_utilization_timeout = data.utilization_interval;
+               }
+               if (NULL != data.utilization_handler)
+               {
+                       mali_utilization_callback = data.utilization_handler;
+               }
+       }
+#endif
+
+       if (NULL != mali_utilization_callback)
+       {
+               MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: Utilization handler installed with interval %u\n", mali_utilization_timeout));
+       }
+       else
+       {
+               MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: No utilization handler installed\n"));
+       }
+
        time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |
-                            _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION);
+                                            _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION);
 
        if (NULL == time_data_lock)
        {
@@ -183,7 +218,7 @@ void mali_utilization_core_start(u64 time_now)
 
                        _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
 
-                       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT));
+                       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout));
                }
                else
                {
@@ -216,3 +251,18 @@ void mali_utilization_core_end(u64 time_now)
                _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
        }
 }
+
+u32 _mali_ukk_utilization_gp_pp(void)
+{
+       return last_utilization;
+}
+
+u32 _mali_ukk_utilization_gp(void)
+{
+       return last_utilization;
+}
+
+u32 _mali_ukk_utilization_pp(void)
+{
+       return last_utilization;
+}
index 1f605179d8fc7d77db58344491463667031f8598..fbf6774a0276b6c4981be10cfba5619c2ae4b823 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_UTILIZATION_H__
@@ -13,6 +13,8 @@
 
 #include "mali_osk.h"
 
+extern void (*mali_utilization_callback)(unsigned int);
+
 /**
  * Initialize/start the Mali GPU utilization metrics reporting.
  *
@@ -25,6 +27,14 @@ _mali_osk_errcode_t mali_utilization_init(void);
  */
 void mali_utilization_term(void);
 
+/**
+ * Check if Mali utilization is enabled
+ */
+MALI_STATIC_INLINE mali_bool mali_utilization_enabled(void)
+{
+       return (NULL != mali_utilization_callback);
+}
+
 /**
  * Should be called when a job is about to execute a job
  */
@@ -40,5 +50,4 @@ void mali_utilization_suspend(void);
  */
 void mali_utilization_core_end(u64 time_now);
 
-
 #endif /* __MALI_KERNEL_UTILIZATION_H__ */
index 63c9f5b71c58937c81bee7f2e3fcf8cd67792ed1..0b9a660106200c6353873f6243a42dec48acf070 100644 (file)
@@ -1,18 +1,18 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
 #include "mali_osk.h"
 #include "mali_ukk.h"
 
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
 #include "mali_osk_profiling.h"
 #endif
 
@@ -21,7 +21,7 @@ _mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *
        _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event;
        MALI_IGNORE(event); /* event is not used for release code, and that is OK */
 
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
        /*
         * Manually generate user space events in kernel space.
         * This saves user space from calling kernel space twice in this case.
index b7267f1d5f47843a95ebe009f9b89b153289ad96..db3db93a803ea56fff549ea3bdf4b43e87c22549 100644 (file)
@@ -1,26 +1,23 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include "mali_kernel_common.h"
 #include "mali_osk.h"
-
 #include "mali_l2_cache.h"
 #include "mali_hw_core.h"
-#include "mali_pm.h"
+#include "mali_scheduler.h"
 
 /**
  * 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.
@@ -82,6 +79,8 @@ struct mali_l2_cache_core
        _mali_osk_lock_t    *counter_lock; /**< Synchronize L2 cache counter access */
        u32                  counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
        u32                  counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+       u32                  last_invalidated_id;
+       mali_bool            power_is_enabled;
 };
 
 #define MALI400_L2_MAX_READS_DEFAULT 0x1C
@@ -115,27 +114,23 @@ struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource)
                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,
+                       cache->command_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _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,
+                               cache->counter_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _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);
+                                       mali_l2_cache_reset(cache);
+
+                                       cache->last_invalidated_id = 0;
+                                       cache->power_is_enabled = MALI_TRUE;
+
+                                       mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache;
+                                       mali_global_num_l2_cache_cores++;
+
+                                       return cache;
                                }
                                else
                                {
@@ -174,7 +169,7 @@ void mali_l2_cache_delete(struct mali_l2_cache_core *cache)
        _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++)
+       for (i = 0; i < MALI_MAX_NUMBER_OF_L2_CACHE_CORES; i++)
        {
                if (mali_global_l2_cache_cores[i] == cache)
                {
@@ -186,6 +181,16 @@ void mali_l2_cache_delete(struct mali_l2_cache_core *cache)
        _mali_osk_free(cache);
 }
 
+void mali_l2_cache_power_is_enabled_set(struct mali_l2_cache_core * core, mali_bool power_is_enabled)
+{
+       core->power_is_enabled = power_is_enabled;
+}
+
+mali_bool mali_l2_cache_power_is_enabled_get(struct mali_l2_cache_core * core)
+{
+       return core->power_is_enabled;
+}
+
 u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache)
 {
        return cache->core_id;
@@ -303,12 +308,7 @@ u32 mali_l2_cache_core_get_glob_num_l2_cores(void)
        return mali_global_num_l2_cache_cores;
 }
 
-u32 mali_l2_cache_core_get_max_num_l2_cores(void)
-{
-       return MALI_MAX_NUMBER_OF_L2_CACHE_CORES;
-}
-
-_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache)
+void mali_l2_cache_reset(struct mali_l2_cache_core *cache)
 {
        /* Invalidate cache (just to keep it in a known state at startup) */
        mali_l2_cache_invalidate_all(cache);
@@ -331,8 +331,17 @@ _mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache)
        }
 
        _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+}
 
-       return _MALI_OSK_ERR_OK;
+void mali_l2_cache_reset_all(void)
+{
+       int i;
+       u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores();
+
+       for (i = 0; i < num_cores; i++)
+       {
+               mali_l2_cache_reset(mali_l2_cache_core_get_glob_l2_core(i));
+       }
 }
 
 _mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache)
@@ -340,6 +349,43 @@ _mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cach
        return mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
 }
 
+mali_bool mali_l2_cache_invalidate_all_conditional(struct mali_l2_cache_core *cache, u32 id)
+{
+       MALI_DEBUG_ASSERT_POINTER(cache);
+
+       if (NULL != cache)
+       {
+               /* If the last cache invalidation was done by a job with a higher id we
+                * don't have to flush. Since user space will store jobs w/ their
+                * corresponding memory in sequence (first job #0, then job #1, ...),
+                * we don't have to flush for job n-1 if job n has already invalidated
+                * the cache since we know for sure that job n-1's memory was already
+                * written when job n was started. */
+               if (((s32)id) <= ((s32)cache->last_invalidated_id))
+               {
+                       return MALI_FALSE;
+               }
+               else
+               {
+                       cache->last_invalidated_id = mali_scheduler_get_new_id();
+               }
+
+               mali_l2_cache_invalidate_all(cache);
+       }
+       return MALI_TRUE;
+}
+
+void mali_l2_cache_invalidate_all_force(struct mali_l2_cache_core *cache)
+{
+       MALI_DEBUG_ASSERT_POINTER(cache);
+
+       if (NULL != cache)
+       {
+               cache->last_invalidated_id = mali_scheduler_get_new_id();
+               mali_l2_cache_invalidate_all(cache);
+       }
+}
+
 _mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages)
 {
        u32 i;
@@ -357,21 +403,30 @@ _mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *ca
        return ret;
 }
 
+void mali_l2_cache_invalidate_pages_conditional(u32 *pages, u32 num_pages)
+{
+       u32 i;
+
+       for (i = 0; i < mali_global_num_l2_cache_cores; i++)
+       {
+               /*additional check*/
+               if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i]))
+               {
+                       mali_l2_cache_invalidate_pages(mali_global_l2_cache_cores[i], pages, num_pages);
+               }
+               mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]);
+               /*check for failed power locking???*/
+       }
+}
+
 mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache)
 {
-       /*
-        * Take PM lock and check power state.
-        * Returns MALI_TRUE if module is powered on.
-        * Power state will not change until mali_l2_cache_unlock_power_state() is called.
-        */
-       mali_pm_lock();
-       return mali_pm_is_powered_on();
+       return _mali_osk_pm_dev_ref_add_no_power_on();
 }
 
 void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache)
 {
-       /* Release PM lock */
-       mali_pm_unlock();
+       _mali_osk_pm_dev_ref_dec_no_power_on();
 }
 
 /* -------- local helper functions below -------- */
index 5a8e4dacd7e9243a20aae9cb45d0c259fc292bf4..a21589a288bf7dce7f791e25b44ef2e17751f771 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_L2_CACHE_H__
 
 #include "mali_osk.h"
 
+#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES  3
+/* Maximum 1 GP and 4 PP for an L2 cache core (Mali-400 Quad-core) */
+#define MALI_MAX_NUMBER_OF_GROUPS_PER_L2_CACHE 5
+
 struct mali_l2_cache_core;
+struct mali_group;
 
 _mali_osk_errcode_t mali_l2_cache_initialize(void);
 void mali_l2_cache_terminate(void);
@@ -21,6 +26,9 @@ 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);
 
+void mali_l2_cache_power_is_enabled_set(struct mali_l2_cache_core *core, mali_bool power_is_enabled);
+mali_bool mali_l2_cache_power_is_enabled_get(struct mali_l2_cache_core * core);
+
 u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache);
 
 mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter);
@@ -30,12 +38,17 @@ u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache);
 void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1);
 struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index);
 u32 mali_l2_cache_core_get_glob_num_l2_cores(void);
-u32 mali_l2_cache_core_get_max_num_l2_cores(void);
 
-_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache);
+void mali_l2_cache_reset(struct mali_l2_cache_core *cache);
+void mali_l2_cache_reset_all(void);
+
+struct mali_group *mali_l2_cache_get_group(struct mali_l2_cache_core *cache, u32 index);
 
 _mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache);
+mali_bool mali_l2_cache_invalidate_all_conditional(struct mali_l2_cache_core *cache, u32 id);
+void mali_l2_cache_invalidate_all_force(struct mali_l2_cache_core *cache);
 _mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages);
+void mali_l2_cache_invalidate_pages_conditional(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);
index ea9c4289a1a15771446333b15bd56aa566983f1a..d5224de6b44a34346ce33ace978126b09e245633 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_mem_validation.h"
@@ -22,27 +22,27 @@ typedef struct
 
 static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR };
 
-_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t *resource)
+_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size)
 {
        /* Check that no other MEM_VALIDATION resources exist */
        if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base)
        {
-               MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; another range is already specified\n", resource->description));
+               MALI_PRINT_ERROR(("Failed to add frame buffer memory; another range is already specified\n"));
                return _MALI_OSK_ERR_FAULT;
        }
 
        /* Check restrictions on page alignment */
-       if ((0 != (resource->base & (~_MALI_OSK_CPU_PAGE_MASK))) ||
-           (0 != (resource->size & (~_MALI_OSK_CPU_PAGE_MASK))))
+       if ((0 != (start & (~_MALI_OSK_CPU_PAGE_MASK))) ||
+           (0 != (size & (~_MALI_OSK_CPU_PAGE_MASK))))
        {
-               MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; incorrect alignment\n", resource->description));
+               MALI_PRINT_ERROR(("Failed to add frame buffer memory; incorrect alignment\n"));
                return _MALI_OSK_ERR_FAULT;
        }
 
-       mali_mem_validator.phys_base = resource->base;
-       mali_mem_validator.size = resource->size;
-       MALI_DEBUG_PRINT(2, ("Memory Validator '%s' installed for Mali physical address base=0x%08X, size=0x%08X\n",
-                        resource->description, mali_mem_validator.phys_base, mali_mem_validator.size));
+       mali_mem_validator.phys_base = start;
+       mali_mem_validator.size = size;
+       MALI_DEBUG_PRINT(2, ("Memory Validator installed for Mali physical address base=0x%08X, size=0x%08X\n",
+                        mali_mem_validator.phys_base, mali_mem_validator.size));
 
        return _MALI_OSK_ERR_OK;
 }
index 2043b44f89c1e469509e314bc6f7b97d394a439b..051a979bf91517f129d14036111d7430a48a4097 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_MEM_VALIDATION_H__
@@ -13,7 +13,7 @@
 
 #include "mali_osk.h"
 
-_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t * resource);
+_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size);
 _mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size);
 
 #endif /* __MALI_MEM_VALIDATION_H__ */
index 75506ed060f9b3bc04ba88a6fecb2318f70b20bf..ee0a7f6299c7507b53e01dd13bf765574929e933 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
@@ -18,9 +18,8 @@
 #include "mali_kernel_mem_os.h"
 #include "mali_session.h"
 #include "mali_l2_cache.h"
-#include "mali_cluster.h"
-#include "mali_group.h"
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#include "mali_scheduler.h"
+#if defined(CONFIG_MALI400_UMP)
 #include "ump_kernel_interface.h"
 #endif
 
@@ -45,7 +44,7 @@ typedef struct dedicated_memory_info
 } dedicated_memory_info;
 
 /* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 typedef struct ump_mem_allocation
 {
        mali_allocation_engine * engine;
@@ -82,10 +81,10 @@ typedef struct external_mem_allocation
  */
 static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args );
 
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 static void ump_memory_release(void * ctx, void * handle);
 static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
-#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0*/
+#endif /* CONFIG_MALI400_UMP */
 
 
 static void external_memory_release(void * ctx, void * handle);
@@ -261,7 +260,7 @@ void mali_memory_session_end(struct mali_session_data *session_data)
                err = _MALI_OSK_ERR_OK;
 
                /* Free all memory engine allocations */
-               if (0 == _mali_osk_list_empty(&session_data->memory_head))
+               if (!_mali_osk_list_empty(&session_data->memory_head))
                {
                        mali_memory_allocation *descriptor;
                        mali_memory_allocation *temp;
@@ -332,14 +331,14 @@ void mali_memory_session_end(struct mali_session_data *session_data)
        return;
 }
 
-_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource)
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size)
 {
        mali_physical_memory_allocator * allocator;
        mali_physical_memory_allocator ** next_allocator_list;
 
-       u32 alloc_order = resource->alloc_order;
+       u32 alloc_order = 1; /* OS memory has second priority */
 
-       allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description);
+       allocator = mali_os_allocator_create(size, 0 /* cpu_usage_adjust */, "Shared Mali GPU memory");
        if (NULL == allocator)
        {
                MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n"));
@@ -364,30 +363,30 @@ _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * r
        MALI_SUCCESS;
 }
 
-_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource)
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size)
 {
        mali_physical_memory_allocator * allocator;
        mali_physical_memory_allocator ** next_allocator_list;
        dedicated_memory_info * cleanup_data;
 
-       u32 alloc_order = resource->alloc_order;
+       u32 alloc_order = 0; /* Dedicated range has first priority */
 
        /* do the low level linux operation first */
 
        /* Request ownership of the memory */
-       if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description))
+       if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory"))
        {
-               MALI_DEBUG_PRINT(1, ("Failed to request memory region %s (0x%08X - 0x%08X)\n", resource->description, resource->base, resource->base + resource->size - 1));
+               MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1));
                MALI_ERROR(_MALI_OSK_ERR_FAULT);
        }
 
        /* create generic block allocator object to handle it */
-       allocator = mali_block_allocator_create(resource->base, resource->cpu_usage_adjust, resource->size, resource->description );
+       allocator = mali_block_allocator_create(start, 0 /* cpu_usage_adjust */, size, "Dedicated Mali GPU memory");
 
        if (NULL == allocator)
        {
                MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
-               _mali_osk_mem_unreqregion(resource->base, resource->size);
+               _mali_osk_mem_unreqregion(start, size);
                MALI_ERROR(_MALI_OSK_ERR_FAULT);
        }
 
@@ -398,13 +397,13 @@ _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resourc
 
        if (NULL == cleanup_data)
        {
-               _mali_osk_mem_unreqregion(resource->base, resource->size);
+               _mali_osk_mem_unreqregion(start, size);
                allocator->destroy(allocator);
                MALI_ERROR(_MALI_OSK_ERR_FAULT);
        }
 
-       cleanup_data->base = resource->base;
-       cleanup_data->size = resource->size;
+       cleanup_data->base = start;
+       cleanup_data->size = size;
 
        cleanup_data->next = mem_region_registrations;
        mem_region_registrations = cleanup_data;
@@ -425,7 +424,7 @@ _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resourc
        MALI_SUCCESS;
 }
 
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
 {
        ump_dd_handle ump_mem;
@@ -672,7 +671,7 @@ _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args
        MALI_SUCCESS;
 
 }
-#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */
+#endif /* CONFIG_MALI400_UMP */
 
 
 static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
@@ -1006,10 +1005,6 @@ static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s
        struct mali_session_data *session_data;
        mali_memory_allocation * descriptor;
 
-       u32 num_groups = mali_group_get_glob_num_groups();
-       struct mali_group *group;
-       u32 i;
-
        descriptor = (mali_memory_allocation *)args->cookie;
        MALI_DEBUG_ASSERT_POINTER(descriptor);
 
@@ -1027,38 +1022,21 @@ static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s
 
 #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++)
+               u32 i;
+               u32 number_of_l2_ccores = mali_l2_cache_core_get_glob_num_l2_cores();
+               for (i = 0; i < number_of_l2_ccores; i++)
                {
-                       struct mali_cluster *cluster;
-                       cluster = mali_cluster_get_global_cluster(i);
-                       if( mali_cluster_power_is_enabled_get(cluster) )
+                       struct mali_l2_cache_core *core;
+                       core = mali_l2_cache_core_get_glob_l2_core(i);
+                       if (mali_l2_cache_power_is_enabled_get(core) )
                        {
-                               mali_cluster_l2_cache_invalidate_all_force(cluster);
+                               mali_l2_cache_invalidate_all_force(core);
                        }
                }
        }
 #endif
 
-       for (i = 0; i < num_groups; i++)
-       {
-               group = mali_group_get_glob_group(i);
-               mali_group_lock(group);
-               mali_group_remove_session_if_unused(group, session_data);
-               if (mali_group_get_session(group) == session_data)
-               {
-                       /* The Zap also does the stall and disable_stall */
-                       mali_bool zap_success = mali_mmu_zap_tlb(mali_group_get_mmu(group));
-                       if (MALI_TRUE != zap_success)
-                       {
-                               MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n"));
-                               mali_group_bottom_half(group, GROUP_EVENT_MMU_PAGE_FAULT);
-                               /* The bottom half will also do the unlock */
-                               continue;
-                       }
-               }
-               mali_group_unlock(group);
-       }
+       mali_scheduler_zap_all_active(session_data);
 
        /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */
        mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor);
@@ -1126,7 +1104,7 @@ _mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *ma
 {
        _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
 
-       if (0 == _mali_osk_list_empty(&page_table_cache.partial))
+       if (!_mali_osk_list_empty(&page_table_cache.partial))
        {
                mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list);
                int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages);
@@ -1304,7 +1282,7 @@ static void mali_mmu_page_table_cache_destroy(void)
                _mali_osk_free(alloc);
        }
 
-       MALI_DEBUG_PRINT_IF(1, 0 == _mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n"));
+       MALI_DEBUG_PRINT_IF(1, !_mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n"));
 
        _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list)
        {
index 78e294595bbbee8ae68152ab9f2183f346cbaecf..d504fcfb8d1ecd6c8afa2dfefaf72fc0a158c3ca 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_MEMORY_H__
@@ -14,9 +14,6 @@
 #include "mali_osk.h"
 #include "mali_session.h"
 
-struct mali_cluster;
-struct mali_group;
-
 /** @brief Initialize Mali memory subsystem
  *
  * Allocate and initialize internal data structures. Must be called before
@@ -70,12 +67,19 @@ void mali_mmu_release_table_page(u32 pa);
 
 
 /** @brief Parse resource and prepare the OS memory allocator
+ *
+ * @param size Maximum size to allocate for Mali GPU.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
  */
-_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource);
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size);
 
 /** @brief Parse resource and prepare the dedicated memory allocator
+ *
+ * @param start Physical start address of dedicated Mali GPU memory.
+ * @param size Size of dedicated Mali GPU memory.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
  */
-_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource);
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size);
 
 mali_allocation_engine mali_mem_get_memory_engine(void);
 
index 168d9e64db61250e2fe92ad57210729dee3670cd..da0ccab1248bd619fb2d54dcf80d2d3b5e0681ad 100644 (file)
@@ -1,21 +1,12 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <mach/am_regs.h>
-#include <linux/module.h>
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-#include "meson_platform/mali_fix.h"
-#endif
-#include "mali_platform.h"
 
 #include "mali_kernel_common.h"
 #include "mali_osk.h"
  */
 #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
@@ -79,53 +40,6 @@ typedef enum mali_mmu_command
        MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */
 } mali_mmu_command;
 
-typedef enum mali_mmu_status_bits
-{
-       MALI_MMU_STATUS_BIT_PAGING_ENABLED      = 1 << 0,
-       MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE   = 1 << 1,
-       MALI_MMU_STATUS_BIT_STALL_ACTIVE        = 1 << 2,
-       MALI_MMU_STATUS_BIT_IDLE                = 1 << 3,
-       MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4,
-       MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5,
-} mali_mmu_status_bits;
-
-/**
- * Definition of the MMU struct
- * Used to track a MMU unit in the system.
- * Contains information about the mapping of the registers
- */
-struct mali_mmu_core
-{
-       struct mali_hw_core hw_core; /**< Common for all HW cores */
-       struct mali_group *group;    /**< Parent core group */
-       _mali_osk_irq_t *irq;        /**< IRQ handler */
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-       u32 id;
-#endif
-};
-
-/**
- * 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);
 
@@ -172,7 +86,7 @@ void mali_mmu_terminate(void)
                                    &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page);
 }
 
-struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource)
+struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual)
 {
        struct mali_mmu_core* mmu = NULL;
 
@@ -184,29 +98,44 @@ struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource)
        if (NULL != mmu)
        {
 #if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-               mmu->id = resource->mmu_id;
-               MALI_DEBUG_PRINT(3, ("Mali MMU: mmu_id: %d\n", resource->mmu_id));
+               extern int static_pp_mmu_cnt;
+               mmu->id = static_pp_mmu_cnt++;
+               //MALI_DEBUG_PRINT(3, ("Mali MMU: mmu_id: %d\n", resource->mmu_id));
 #endif
                if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE))
                {
-                       if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu))
+                       if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu))
                        {
-                               /* Setup IRQ handlers (which will do IRQ probing if needed) */
-                               mmu->irq = _mali_osk_irq_init(resource->irq,
-                                                             mali_mmu_upper_half,
-                                                             mali_mmu_bottom_half,
-                                                             mali_mmu_probe_trigger,
-                                                             mali_mmu_probe_ack,
-                                                             mmu,
-                                                             "mali_mmu_irq_handlers");
-                               if (NULL != mmu->irq)
+                               if (is_virtual)
                                {
+                                       /* Skip reset and IRQ setup for virtual MMU */
                                        return mmu;
                                }
-                               else
+
+                               if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu))
                                {
-                                       MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
+                                       /* Setup IRQ handlers (which will do IRQ probing if needed) */
+                                       mmu->irq = _mali_osk_irq_init(resource->irq,
+                                                                     mali_group_upper_half_mmu,
+                                                                     group,
+                                                                     mali_mmu_probe_trigger,
+                                                                     mali_mmu_probe_ack,
+                                                                     mmu,
+                                                                     "mali_mmu_irq_handlers");
+                                       if (NULL != mmu->irq)
+                                       {
+                                               return mmu;
+                                       }
+                                       else
+                                       {
+                                               MALI_PRINT_ERROR(("Mali MMU: Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
+                                       }
                                }
+                               mali_group_remove_mmu_core(group);
+                       }
+                       else
+                       {
+                               MALI_PRINT_ERROR(("Mali MMU: Failed to add core %s to group\n", mmu->hw_core.description));
                        }
                        mali_hw_core_delete(&mmu->hw_core);
                }
@@ -223,33 +152,29 @@ struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource)
 
 void mali_mmu_delete(struct mali_mmu_core *mmu)
 {
-       _mali_osk_irq_term(mmu->irq);
+       if (NULL != mmu->irq)
+       {
+               _mali_osk_irq_term(mmu->irq);
+       }
+
        mali_hw_core_delete(&mmu->hw_core);
        _mali_osk_free(mmu);
 }
 
-void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group)
-{
-       mmu->group = group;
-}
-
 static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
 {
-       const int max_loop_count = 100;
-       const int delay_in_usecs = 1;
        int i;
 
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
 
-       for (i = 0; i < max_loop_count; ++i)
+       for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
        {
                if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED)
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(delay_in_usecs);
        }
-       if (max_loop_count == i)
+       if (MALI_REG_POLL_COUNT_SLOW == 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)));
        }
@@ -257,15 +182,8 @@ static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
 
 mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
 {
-       const int max_loop_count = 100;
-       const int delay_in_usecs = 999;
        int i;
-       u32 mmu_status;
-
-       /* There are no group when it is called from mali_mmu_create */
-       if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group);
-
-       mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+       u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
 
        if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) )
        {
@@ -281,20 +199,20 @@ mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
 
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
 
-       for (i = 0; i < max_loop_count; ++i)
+       for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
        {
                mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
-               if ( mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE))
+               if (mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) &&
+                   (0 == (mmu_status & MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE)))
                {
                        break;
                }
-               if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED )))
+               if (0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED )))
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(delay_in_usecs);
        }
-       if (max_loop_count == i)
+       if (MALI_REG_POLL_COUNT_SLOW == 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;
@@ -311,14 +229,8 @@ mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
 
 void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
 {
-       const int max_loop_count = 100;
-       const int delay_in_usecs = 1;
        int i;
-       u32 mmu_status;
-       /* There are no group when it is called from mali_mmu_create */
-       if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group);
-
-       mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+       u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
 
        if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
        {
@@ -333,7 +245,7 @@ void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
 
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
 
-       for (i = 0; i < max_loop_count; ++i)
+       for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
        {
                u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
                if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) )
@@ -348,38 +260,31 @@ void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(delay_in_usecs);
        }
-       if (max_loop_count == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+       if (MALI_REG_POLL_COUNT_SLOW == 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)
+       for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
        {
                if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0)
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(delay_in_usecs);
        }
-       if (max_loop_count == i)
+       if (MALI_REG_POLL_COUNT_SLOW == 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;
@@ -393,11 +298,6 @@ _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);
 
@@ -419,137 +319,9 @@ _mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
        return err;
 }
 
-
-extern mali_bool mali_group_power_is_on_2(struct mali_group *group);
-/* ------------- 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) */
-       //MALI_DEBUG_PRINT(5, ("Mali MMU: %d..\n",mmu->id));
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-       if ( MALI_FALSE == mali_group_power_is_on_2(mmu->group) )
-       {
-               if (mmu->id == 2)
-                       malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
-               else if (mmu->id == 3)
-                       malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
-               MALI_DEBUG_PRINT(4, ("Mali MMU: invalid interrupt. <<-- \n"));
-               MALI_SUCCESS;
-       }
-#endif
-
-       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)
-               {
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 
-                       MALI_DEBUG_PRINT(3, ("Mali MMU: core0 page fault reply. <<-- \n"));
-                       if (mmu->id == 2)
-                               malifix_set_mmu_int_process_state(0, MMU_INT_TOP);
-                       else if (mmu->id == 3)
-                               malifix_set_mmu_int_process_state(1, MMU_INT_TOP);
-#endif
-                       _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"));
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-                       if (mmu->id == 2) {
-                               if (malifix_get_mmu_int_process_state(0) == MMU_INT_TOP)
-                                       malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
-                       }
-                       else if (mmu->id == 3) {
-                               if (malifix_get_mmu_int_process_state(1) == MMU_INT_TOP)
-                                       malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
-                       }
-#endif
-               }
-               return _MALI_OSK_ERR_OK;
-       } 
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-       else { 
-
-               if (mmu->id == 2)
-                       malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
-               else if (mmu->id == 3)
-                       malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
-       }
-#endif 
-
-       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"));
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-       if (mmu->id == 2) {
-           malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
-       } else if (mmu->id == 3) {
-           malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
-       }
-#endif
-       mali_group_lock(mmu->group); /* Unlocked in mali_group_bottom_half */
-
-       if ( MALI_FALSE == mali_group_power_is_on(mmu->group) )
-       {
-               MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.",mmu->hw_core.description));
-               mali_group_unlock(mmu->group);
-               return;
-       }
-
-       raw = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT);
-       status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
-
-       if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) &&  (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) )
-       {
-               MALI_DEBUG_PRINT(2, ("Mali MMU: Page fault bottom half: No Irq found.\n"));
-               mali_group_unlock(mmu->group);
-               /* MALI_DEBUG_ASSERT(0); */
-               return;
-       }
-
-       /* An actual page fault has occurred. */
-
-       fault_address = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
-
-       MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n",
-                  (void*)fault_address,
-                  (status >> 6) & 0x1F,
-                  (status & 32) ? "write" : "read",
-                  mmu->hw_core.description));
-
-       mali_group_bottom_half(mmu->group, GROUP_EVENT_MMU_PAGE_FAULT); /* Unlocks the group lock */
-}
-
 mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
 {
-       mali_bool stall_success;
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
-
-       stall_success = mali_mmu_enable_stall(mmu);
+       mali_bool stall_success = mali_mmu_enable_stall(mmu);
 
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
 
@@ -565,23 +337,20 @@ mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
 
 void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu)
 {
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
 }
 
 
 void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address)
 {
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address));
 }
 
 static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory)
 {
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
        /* The MMU must be in stalled or page fault mode, for this writing to work */
        MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)
-                                                         & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
+                         & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
        mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
 
@@ -591,7 +360,6 @@ mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mal
 {
        mali_bool stall_success;
        MALI_DEBUG_ASSERT_POINTER(mmu);
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
 
        MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));
        stall_success = mali_mmu_enable_stall(mmu);
@@ -605,8 +373,8 @@ mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mal
 void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu)
 {
        mali_bool stall_success;
+
        MALI_DEBUG_ASSERT_POINTER(mmu);
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
        MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
 
        stall_success = mali_mmu_enable_stall(mmu);
@@ -620,7 +388,6 @@ void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu)
 {
        mali_bool stall_success;
        MALI_DEBUG_ASSERT_POINTER(mmu);
-       MALI_ASSERT_GROUP_LOCKED(mmu->group);
 
        MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description));
        stall_success = mali_mmu_enable_stall(mmu);
index c7274b8edd3ec588c1e3a8b5674377313f5ed7e0..eb1c49ae4aa76de381ae967280a02d13a2c6c1fa 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_MMU_H__
 
 #include "mali_osk.h"
 #include "mali_mmu_page_directory.h"
+#include "mali_hw_core.h"
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <mach/am_regs.h>
+#include <linux/module.h>
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+#include "mali_platform.h"
+#include "meson_platform/mali_fix.h"
+#endif
+
 
 /* Forward declaration from mali_group.h */
 struct mali_group;
 
-struct mali_mmu_core;
+/**
+ * MMU register numbers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_mmu_register {
+       MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */
+       MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */
+       MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */
+       MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */
+       MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */
+       MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */
+       MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */
+       MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */
+       MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */
+} mali_mmu_register;
+
+/**
+ * MMU interrupt register bits
+ * Each cause of the interrupt is reported
+ * through the (raw) interrupt status registers.
+ * Multiple interrupts can be pending, so multiple bits
+ * can be set at once.
+ */
+typedef enum mali_mmu_interrupt
+{
+       MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */
+       MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */
+} mali_mmu_interrupt;
+
+typedef enum mali_mmu_status_bits
+{
+       MALI_MMU_STATUS_BIT_PAGING_ENABLED      = 1 << 0,
+       MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE   = 1 << 1,
+       MALI_MMU_STATUS_BIT_STALL_ACTIVE        = 1 << 2,
+       MALI_MMU_STATUS_BIT_IDLE                = 1 << 3,
+       MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4,
+       MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5,
+       MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE    = 1 << 31,
+} mali_mmu_status_bits;
+
+/**
+ * Definition of the MMU struct
+ * Used to track a MMU unit in the system.
+ * Contains information about the mapping of the registers
+ */
+struct mali_mmu_core
+{
+       struct mali_hw_core hw_core; /**< Common for all HW cores */
+       _mali_osk_irq_t *irq;        /**< IRQ handler */
+
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+       u32 id;
+#endif
+};
 
 _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);
+struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual);
 void mali_mmu_delete(struct mali_mmu_core *mmu);
 
 _mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu);
@@ -51,5 +115,43 @@ void mali_mmu_disable_stall(struct mali_mmu_core *mmu);
 
 void mali_mmu_page_fault_done(struct mali_mmu_core *mmu);
 
+/*** Register reading/writing functions ***/
+MALI_STATIC_INLINE u32 mali_mmu_get_int_status(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
+}
+
+MALI_STATIC_INLINE u32 mali_mmu_get_rawstat(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT);
+}
+
+MALI_STATIC_INLINE void mali_mmu_mask_all_interrupts(struct mali_mmu_core *mmu)
+{
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0);
+}
+
+MALI_STATIC_INLINE u32 mali_mmu_get_status(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+}
+
+MALI_STATIC_INLINE u32 mali_mmu_get_page_fault_addr(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
+}
+
+/*
+needed?
+MALI_STATIC_INLINE void mali_mmu_unmask_all_interrupts(struct mali_mmu_core *mmu)
+{
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+}
+needed?
+MALI_STATIC_INLINE void mali_mmu_clear_interrupt(struct mali_mmu_core *mmu, u32 interrupt)
+{
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, interrupt);
+}
+*/
 
 #endif /* __MALI_MMU_H__ */
index cc91ae978891b692b212bcf8b3f07a5d2b5fdf2b..36ecde85eaec8e98ff1b5c92c95f47c83753f1f8 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
@@ -14,8 +14,7 @@
 #include "mali_uk_types.h"
 #include "mali_mmu_page_directory.h"
 #include "mali_memory.h"
-
-#include "mali_cluster.h"
+#include "mali_l2_cache.h"
 #include "mali_group.h"
 
 static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data);
@@ -245,7 +244,7 @@ _mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir,
 
        if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id())
        {
-               mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv);
+               mali_l2_cache_invalidate_pages_conditional(pages_to_invalidate, num_pages_inv);
        }
 #endif
 
@@ -305,12 +304,12 @@ void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_addre
        switch ( cache_settings )
        {
                case MALI_CACHE_GP_READ_ALLOCATE:
-               MALI_DEBUG_PRINT(3, ("Map L2 GP_Read_allocate\n"));
+               MALI_DEBUG_PRINT(5, ("Map L2 GP_Read_allocate\n"));
                permission_bits = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE;
                break;
 
                case MALI_CACHE_STANDARD:
-               MALI_DEBUG_PRINT(3, ("Map L2 Standard\n"));
+               MALI_DEBUG_PRINT(5, ("Map L2 Standard\n"));
                /*falltrough */
                default:
                if ( MALI_CACHE_STANDARD != cache_settings) MALI_PRINT_ERROR(("Wrong cache settings\n"));
index 628833a1180a14c6b8ed06c95d156956c0445161..e6ffb26486da7ca36c09b73a23f54abe2b863a2d 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_MMU_PAGE_DIRECTORY_H__
index c478057570d49e8ef28d4f72d2bf2412fec06097..1d984f03660985ce293d405a93e9cdaa0750088a 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -63,6 +63,9 @@ extern "C"
        #define MALI_FALSE ((mali_bool)0)
 #endif
 
+/*todo moved from mali_hw_core.h*/
+#define MALI_HW_CORE_NO_COUNTER     ((u32)-1)
+
 /**
  * @brief OSK Error codes
  *
@@ -92,6 +95,25 @@ typedef enum
 
 /** @} */ /* end group _mali_osk_miscellaneous */
 
+/** @defgroup _mali_osk_wq OSK work queues
+ * @{ */
+
+/** @brief Private type for work objects */
+typedef struct _mali_osk_wq_work_t_struct _mali_osk_wq_work_t;
+
+/** @brief Work queue handler function
+ *
+ * This function type is called when the work is scheduled by the work queue,
+ * e.g. as an IRQ bottom-half handler.
+ *
+ * Refer to \ref _mali_osk_wq_schedule_work() for more information on the
+ * work-queue and work handlers.
+ *
+ * @param arg resource-specific data
+ */
+typedef void (*_mali_osk_wq_work_handler_t)( void * arg );
+
+/* @} */ /* end group _mali_osk_wq */
 
 /** @defgroup _mali_osk_irq OSK IRQ handling
  * @{ */
@@ -127,7 +149,7 @@ typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg );
  *
  * If an IRQ upper-half handler requires more work to be done than can be
  * acheived in an IRQ context, then it may defer the work with
- * _mali_osk_irq_schedulework(). Refer to \ref _mali_osk_irq_schedulework() for
+ * _mali_osk_wq_schedule_work(). Refer to \ref _mali_osk_wq_create_work() for
  * more information.
  *
  * @param arg resource-specific data
@@ -136,24 +158,6 @@ typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg );
  */
 typedef _mali_osk_errcode_t  (*_mali_osk_irq_uhandler_t)( void * arg );
 
-/** @brief IRQ 'bottom-half' handler callback.
- *
- * This function is implemented by the common layer to do the deferred handling
- * of a resource's IRQ. Usually, this work cannot be carried out in IRQ context
- * by the IRQ upper-half handler.
- *
- * The IRQ bottom-half handler maps on to the concept of an IST that may
- * execute some time after the actual IRQ has fired.
- *
- * All OSK-registered IRQ bottom-half handlers will be serialized, across all
- * CPU-cores in the system.
- *
- * Refer to \ref _mali_osk_irq_schedulework() for more information on the
- * IRQ work-queue, and the calling of the IRQ bottom-half handler.
- *
- * @param arg resource-specific data
- */
-typedef void (*_mali_osk_irq_bhandler_t)( void * arg );
 /** @} */ /* end group _mali_osk_irq */
 
 
@@ -197,20 +201,20 @@ typedef enum
 {
        _MALI_OSK_LOCK_ORDER_LAST = 0,
 
+       _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS,
        _MALI_OSK_LOCK_ORDER_PM_EXECUTE,
        _MALI_OSK_LOCK_ORDER_UTILIZATION,
        _MALI_OSK_LOCK_ORDER_L2_COUNTER,
        _MALI_OSK_LOCK_ORDER_PROFILING,
        _MALI_OSK_LOCK_ORDER_L2_COMMAND,
        _MALI_OSK_LOCK_ORDER_PM_CORE_STATE,
-       _MALI_OSK_LOCK_ORDER_GROUP,
        _MALI_OSK_LOCK_ORDER_SCHEDULER,
-
+       _MALI_OSK_LOCK_ORDER_GROUP,
+       _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL,
        _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP,
        _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE,
        _MALI_OSK_LOCK_ORDER_MEM_INFO,
        _MALI_OSK_LOCK_ORDER_MEM_SESSION,
-
        _MALI_OSK_LOCK_ORDER_SESSIONS,
 
        _MALI_OSK_LOCK_ORDER_FIRST
@@ -429,7 +433,7 @@ typedef struct _mali_osk_notification_t_struct
  *
  * If a timer requires more work to be done than can be acheived in an IRQ
  * context, then it may defer the work with a work-queue. For example, it may
- * use \ref _mali_osk_irq_schedulework() to make use of the IRQ bottom-half handler
+ * use \ref _mali_osk_wq_schedule_work() to make use of a bottom-half handler
  * to carry out the remaining work.
  *
  * Stopping the timer with \ref _mali_osk_timer_del() blocks on compeletion of
@@ -473,6 +477,10 @@ typedef struct _mali_osk_list_s
  * @param exp the name of the variable that the list will be defined as. */
 #define _MALI_OSK_LIST_HEAD(exp)      _mali_osk_list_t exp
 
+/** @brief Define a list variable, which is initialized.
+ * @param exp the name of the variable that the list will be defined as. */
+#define _MALI_OSK_LIST_HEAD_STATIC_INIT(exp) _mali_osk_list_t exp = { &exp, &exp }
+
 /** @brief Find the containing structure of another structure
  *
  * This is the reverse of the operation 'offsetof'. This means that the
@@ -557,131 +565,61 @@ typedef struct _mali_osk_list_s
 /** @addtogroup _mali_osk_miscellaneous
  * @{ */
 
-/** @brief The known resource types
- *
- * @note \b IMPORTANT: these must remain fixed, and only be extended. This is
- * because not all systems use a header file for reading in their resources.
- * The resources may instead come from a data file where these resources are
- * 'hard-coded' in, because there's no easy way of transferring the enum values
- * into such data files. E.g. the C-Pre-processor does \em not process enums.
- */
-typedef enum _mali_osk_resource_type
-{
-       RESOURCE_TYPE_FIRST =0,  /**< Duplicate resource marker for the first resource*/
-
-       MEMORY              =0,  /**< Physically contiguous memory block, not managed by the OS */
-       OS_MEMORY           =1,  /**< Memory managed by and shared with the OS */
-
-       MALI_PP             =2,  /**< Mali Pixel Processor core */
-       MALI450PP           =2,  /**< Compatibility option */
-       MALI400PP           =2,  /**< Compatibility option */
-       MALI300PP           =2,  /**< Compatibility option */
-       MALI200             =2,  /**< Compatibility option */
-       
-       MALI_GP             =3,  /**< Mali Geometry Processor core */
-       MALI450GP           =3,  /**< Compatibility option */
-       MALI400GP           =3,  /**< Compatibility option */
-       MALI300GP           =3,  /**< Compatibility option */
-       MALIGP2             =3,  /**< Compatibility option */
-
-       MMU                 =4,  /**< Mali MMU (Memory Management Unit) */
-
-       FPGA_FRAMEWORK      =5,  /**< Mali registers specific to FPGA implementations */
-
-       MALI_L2             =6,  /**< Mali Level 2 cache core */
-       MALI450L2           =6,  /**< Compatibility option */
-       MALI400L2           =6,  /**< Compatibility option */
-       MALI300L2           =6,  /**< Compatibility option */
-
-       MEM_VALIDATION      =7, /**< External Memory Validator */
-
-       PMU                 =8, /**< Power Manangement Unit */
-
-       RESOURCE_TYPE_COUNT      /**< The total number of known resources */
-} _mali_osk_resource_type_t;
-
 /** @brief resource description struct
  *
- * _mali_osk_resources_init() will enumerate objects of this type. Not all
- * members have a valid meaning across all types.
- *
- * The mmu_id is used to group resources to a certain MMU, since there may be
- * more than one MMU in the system, and each resource may be using a different
- * MMU:
- * - For MMU resources, the setting of mmu_id is a uniquely identifying number.
- * - For Other resources, the setting of mmu_id determines which MMU the
- * resource uses.
+ * Platform independent representation of a Mali HW resource
  */
 typedef struct _mali_osk_resource
 {
-       _mali_osk_resource_type_t type; /**< type of the resource */
        const char * description;       /**< short description of the resource */
        u32 base;                       /**< Physical base address of the resource, as seen by Mali resources. */
-       s32 cpu_usage_adjust;           /**< Offset added to the base address of the resource to arrive at the CPU physical address of the resource (if different from the Mali physical address) */
-       u32 size;                       /**< Size in bytes of the resource - either the size of its register range, or the size of the memory block. */
        u32 irq;                        /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */
-       u32 flags;                      /**< Resources-specific flags. */
-       u32 mmu_id;                     /**< Identifier for Mali MMU resources. */
-       u32 alloc_order;                /**< Order in which MEMORY/OS_MEMORY resources are used */
 } _mali_osk_resource_t;
 /** @} */ /* end group _mali_osk_miscellaneous */
 
 
 #include "mali_kernel_memory_engine.h"   /* include for mali_memory_allocation and mali_physical_memory_allocation type */
 
-/** @addtogroup _mali_osk_irq
+/** @addtogroup _mali_osk_wq
  * @{ */
 
-/** @brief Fake IRQ number for testing purposes
+/** @brief Initialize work queues (for deferred work)
+ *
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
  */
-#define _MALI_OSK_IRQ_NUMBER_FAKE ((u32)0xFFFFFFF1)
-
-/** @addtogroup _mali_osk_irq
- * @{ */
+_mali_osk_errcode_t _mali_osk_wq_init(void);
 
-/** @brief PMM Virtual IRQ number
+/** @brief Terminate work queues (for deferred work)
  */
-#define _MALI_OSK_IRQ_NUMBER_PMM ((u32)0xFFFFFFF2)
+void _mali_osk_wq_term(void);
 
-
-/** @brief Initialize IRQ handling for a resource
+/** @brief Create work in the work queue
  *
- * The _mali_osk_irq_t returned must be written into the resource-specific data
- * pointed to by data. This is so that the upper and lower handlers can call
- * _mali_osk_irq_schedulework().
+ * Creates a work object which can be scheduled in the work queue. When
+ * scheduled, \a handler will be called with \a data as the argument.
  *
- * @note The caller must ensure that the resource does not generate an
- * interrupt after _mali_osk_irq_init() finishes, and before the
- * _mali_osk_irq_t is written into the resource-specific data. Otherwise,
- * the upper-half handler will fail to call _mali_osk_irq_schedulework().
+ * Refer to \ref _mali_osk_wq_schedule_work() for details on how work
+ * is scheduled in the queue.
  *
- * @param irqnum The IRQ number that the resource uses, as seen by the CPU.
- * The value -1 has a special meaning which indicates the use of probing, and trigger_func and ack_func must be
- * non-NULL.
- * @param uhandler The upper-half handler, corresponding to a ISR handler for
- * the resource
- * @param bhandler The lower-half handler, corresponding to an IST handler for
- * the resource
- * @param trigger_func Optional: a function to trigger the resource's irq, to
- * probe for the interrupt. Use NULL if irqnum != -1.
- * @param ack_func Optional: a function to acknowledge the resource's irq, to
- * probe for the interrupt. Use NULL if irqnum != -1.
- * @param data resource-specific data, which will be passed to uhandler,
- * bhandler and (if present) trigger_func and ack_funnc
- * @param description textual description of the IRQ resource.
- * @return on success, a pointer to a _mali_osk_irq_t object, which represents
- * the IRQ handling on this resource. NULL on failure.
+ * The returned pointer must be freed with \ref _mali_osk_wq_delete_work()
+ * when no longer needed.
  */
-_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler,    _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description );
+_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data );
 
-/** @brief Cause a queued, deferred call of the IRQ bottom-half.
+/** @brief Delete a work object
  *
- * _mali_osk_irq_schedulework provides a mechanism for enqueuing deferred calls
- * to the IRQ bottom-half handler. The queue is known as the IRQ work-queue.
- * After calling _mali_osk_irq_schedulework(), the IRQ bottom-half handler will
- * be scheduled to run at some point in the future.
+ * This will flush the work queue to ensure that the work handler will not
+ * be called after deletion.
+ */
+void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work );
+
+/** @brief Cause a queued, deferred call of the work handler
  *
- * This is called by the IRQ upper-half to defer further processing of
+ * _mali_osk_wq_schedule_work provides a mechanism for enqueuing deferred calls
+ * to the work handler. After calling \ref _mali_osk_wq_schedule_work(), the
+ * work handler will be scheduled to run at some point in the future.
+ *
+ * Typically this is called by the IRQ upper-half to defer further processing of
  * IRQ-related work to the IRQ bottom-half handler. This is necessary for work
  * that cannot be done in an IRQ context by the IRQ upper-half handler. Timer
  * callbacks also use this mechanism, because they are treated as though they
@@ -694,78 +632,97 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
  * IRQ bottom half to hold the same mutex, with a guarantee that they will not
  * deadlock just by using this mechanism.
  *
- * _mali_osk_irq_schedulework() places deferred call requests on a queue, to
+ * _mali_osk_wq_schedule_work() places deferred call requests on a queue, to
  * allow for more than one thread to make a deferred call. Therfore, if it is
  * called 'K' times, then the IRQ bottom-half will be scheduled 'K' times too.
  * 'K' is a number that is implementation-specific.
  *
- * _mali_osk_irq_schedulework() is guaranteed to not block on:
+ * _mali_osk_wq_schedule_work() is guaranteed to not block on:
  * - enqueuing a deferred call request.
- * - the completion of the IRQ bottom-half handler.
+ * - the completion of the work handler.
  *
- * This is to prevent deadlock. For example, if _mali_osk_irq_schedulework()
+ * This is to prevent deadlock. For example, if _mali_osk_wq_schedule_work()
  * blocked, then it would cause a deadlock when the following two conditions
  * hold:
- * - The IRQ bottom-half callback (of type _mali_osk_irq_bhandler_t) locks
+ * - The work handler callback (of type _mali_osk_wq_work_handler_t) locks
  * a mutex
- * - And, at the same time, the caller of _mali_osk_irq_schedulework() also
+ * - And, at the same time, the caller of _mali_osk_wq_schedule_work() also
  * holds the same mutex
  *
  * @note care must be taken to not overflow the queue that
- * _mali_osk_irq_schedulework() operates on. Code must be structured to
+ * _mali_osk_wq_schedule_work() operates on. Code must be structured to
  * ensure that the number of requests made to the queue is bounded. Otherwise,
- * IRQs will be lost.
+ * work will be lost.
  *
- * The queue that _mali_osk_irq_schedulework implements is a FIFO of N-writer,
- * 1-reader type. The writers are the callers of _mali_osk_irq_schedulework
+ * The queue that _mali_osk_wq_schedule_work implements is a FIFO of N-writer,
+ * 1-reader type. The writers are the callers of _mali_osk_wq_schedule_work
  * (all OSK-registered IRQ upper-half handlers in the system, watchdog timers,
  * callers from a Kernel-process context). The reader is a single thread that
- * handles all OSK-registered IRQs.
- *
- * The consequence of the queue being a 1-reader type is that calling
- * _mali_osk_irq_schedulework() on different _mali_osk_irq_t objects causes
- * their IRQ bottom-halves to be serialized, across all CPU-cores in the
- * system.
+ * handles all OSK-registered work.
  *
- * @param irq a pointer to the _mali_osk_irq_t object corresponding to the
- * resource whose IRQ bottom-half must begin processing.
+ * @param work a pointer to the _mali_osk_wq_work_t object corresponding to the
+ * work to begin processing.
  */
-void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq );
+void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work );
 
-/** @brief Terminate IRQ handling on a resource.
+/** @brief Flush the work queue
  *
- * This will disable the interrupt from the device, and then waits for the
- * IRQ work-queue to finish the work that is currently in the queue. That is,
- * for every deferred call currently in the IRQ work-queue, it waits for each
- * of those to be processed by their respective IRQ bottom-half handler.
+ * This will flush the OSK work queue, ensuring all work in the queue has
+ * completed before returning.
  *
- * This function is used to ensure that the bottom-half handler of the supplied
- * IRQ object will not be running at the completion of this function call.
- * However, the caller must ensure that no other sources could call the
- * _mali_osk_irq_schedulework() on the same IRQ object. For example, the
- * relevant timers must be stopped.
+ * Since this blocks on the completion of work in the work-queue, the
+ * caller of this function \b must \b not hold any mutexes that are taken by
+ * any registered work handler. To do so may cause a deadlock.
  *
- * @note While this function is being called, other OSK-registered IRQs in the
- * system may enqueue work for their respective bottom-half handlers. This
- * function will not wait for those entries in the work-queue to be flushed.
+ */
+void _mali_osk_wq_flush(void);
+
+
+/** @} */ /* end group _mali_osk_wq */
+
+/** @addtogroup _mali_osk_irq
+ * @{ */
+
+/** @brief Initialize IRQ handling for a resource
  *
- * Since this blocks on the completion of work in the IRQ work-queue, the
- * caller of this function \b must \b not hold any mutexes that are taken by
- * any OSK-registered IRQ bottom-half handler. To do so may cause a deadlock.
+ * Registers an interrupt handler \a uhandler for the given IRQ number \a irqnum.
+ * \a data will be passed as argument to the handler when an interrupt occurs.
  *
- * @param irq a pointer to the _mali_osk_irq_t object corresponding to the
- * resource whose IRQ handling is to be terminated.
+ * If \a irqnum is -1, _mali_osk_irq_init will probe for the IRQ number using
+ * the supplied \a trigger_func and \a ack_func. These functions will also
+ * receive \a data as their argument.
+ *
+ * @param irqnum The IRQ number that the resource uses, as seen by the CPU.
+ * The value -1 has a special meaning which indicates the use of probing, and
+ * trigger_func and ack_func must be non-NULL.
+ * @param uhandler The interrupt handler, corresponding to a ISR handler for
+ * the resource
+ * @param int_data resource specific data, which will be passed to uhandler
+ * @param trigger_func Optional: a function to trigger the resource's irq, to
+ * probe for the interrupt. Use NULL if irqnum != -1.
+ * @param ack_func Optional: a function to acknowledge the resource's irq, to
+ * probe for the interrupt. Use NULL if irqnum != -1.
+ * @param probe_data resource-specific data, which will be passed to
+ * (if present) trigger_func and ack_func
+ * @param description textual description of the IRQ resource.
+ * @return on success, a pointer to a _mali_osk_irq_t object, which represents
+ * the IRQ handling on this resource. NULL on failure.
  */
-void _mali_osk_irq_term( _mali_osk_irq_t *irq );
+_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description );
 
-/** @brief flushing workqueue.
+/** @brief Terminate IRQ handling on a resource.
+ *
+ * This will disable the interrupt from the device, and then waits for any
+ * currently executing IRQ handlers to complete.
  *
- * This will flush the workqueue.
+ * @note If work is deferred to an IRQ bottom-half handler through
+ * \ref _mali_osk_wq_schedule_work(), be sure to flush any remaining work
+ * with \ref _mali_osk_wq_flush() or (implicitly) with \ref _mali_osk_wq_delete_work()
  *
  * @param irq a pointer to the _mali_osk_irq_t object corresponding to the
  * resource whose IRQ handling is to be terminated.
  */
-void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq );
+void _mali_osk_irq_term( _mali_osk_irq_t *irq );
 
 /** @} */ /* end group _mali_osk_irq */
 
@@ -1493,23 +1450,22 @@ void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire );
 
 /** @brief Modify a timer
  *
- * Set the absolute time at which a timer will expire, and start it if it is
- * stopped. If \a expiry_tick is in the past (determined by
- * _mali_osk_time_after() ), the timer fires immediately.
+ * Set the relative time at which a timer will expire, and start it if it is
+ * stopped. If \a ticks_to_expire 0 the timer fires immediately.
  *
  * It is an error to modify a timer without setting the callback via
  *  _mali_osk_timer_setcallback().
  *
- * The timer will expire at absolute time \a expiry_tick, at which point, the
- * callback function will be invoked with the callback-specific data, as set
- * by _mali_osk_timer_setcallback().
+ * The timer will expire at \a ticks_to_expire from the time of the call, at
+ * which point, the callback function will be invoked with the
+ * callback-specific data, as set by _mali_osk_timer_setcallback().
  *
  * @param tim the timer to modify, and start if necessary
- * @param expiry_tick the \em absolute time in ticks at which this timer should
- * trigger.
+ * @param ticks_to_expire the \em absolute time in ticks at which this timer
+ * should trigger.
  *
  */
-void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick);
+void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire);
 
 /** @brief Stop a timer, and block on its completion.
  *
@@ -1521,9 +1477,9 @@ void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick);
  * occur.
  *
  * @note While the callback itself is guaranteed to not be running, work
- * enqueued on the IRQ work-queue by the timer (with
- * \ref _mali_osk_irq_schedulework()) may still run. The timer callback and IRQ
- * bottom-half handler must take this into account.
+ * enqueued on the work-queue by the timer (with
+ * \ref _mali_osk_wq_schedule_work()) may still run. The timer callback and
+ * work handler must take this into account.
  *
  * It is legal to stop an already stopped timer.
  *
@@ -1532,6 +1488,26 @@ void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick);
  */
 void _mali_osk_timer_del( _mali_osk_timer_t *tim );
 
+/** @brief Stop a timer.
+ *
+ * Stop the timer. When the function returns, the timer's callback may still be
+ * running on any CPU core.
+ *
+ * It is legal to stop an already stopped timer.
+ *
+ * @param tim the timer to stop.
+ */
+void _mali_osk_timer_del_async( _mali_osk_timer_t *tim );
+
+/** @brief Check if timer is pemding.
+ *
+ * Check if timer is active.
+ *
+ * @param tim the timer to check
+ * @return MALI_TRUE if time is active, MALI_FALSE if it is not active
+ */
+mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim );
+
 /** @brief Set a timer's callback parameters.
  *
  * This must be called at least once before a timer is started/modified.
@@ -1754,13 +1730,47 @@ u32 _mali_osk_get_tid(void);
  */
 void _mali_osk_pm_dev_enable(void);
 
-/** @brief Tells the OS that device is now idle
+/** @brief Disable OS controlled runtime power management
  */
-_mali_osk_errcode_t _mali_osk_pm_dev_idle(void);
+void _mali_osk_pm_dev_disable(void);
+
 
-/** @brief Tells the OS that the device is about to become active
+/** @brief Take a reference to the power manager system for the Mali device.
+ *
+ * When function returns successfully, Mali is ON.
+ *
+ * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference.
  */
-_mali_osk_errcode_t _mali_osk_pm_dev_activate(void);
+_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void);
+
+
+/** @brief Release the reference to the power manger system for the Mali device.
+ *
+ * When reference count reach zero, the cores can be off.
+ *
+ * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add().
+ */
+void _mali_osk_pm_dev_ref_dec(void);
+
+
+/** @brief Take a reference to the power manager system for the Mali device.
+ *
+ * Will leave the cores powered off if they are already powered off.
+ *
+ * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference.
+ *
+ * @return MALI_TRUE if the Mali GPU is powered on, otherwise MALI_FALSE.
+ */
+mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void);
+
+
+/** @brief Releasing the reference to the power manger system for the Mali device.
+ *
+ * When reference count reach zero, the cores can be off.
+ *
+ * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add_no_power_on().
+ */
+void _mali_osk_pm_dev_ref_dec_no_power_on(void);
 
 /** @} */ /* end group  _mali_osk_miscellaneous */
 
@@ -1768,7 +1778,6 @@ _mali_osk_errcode_t _mali_osk_pm_dev_activate(void);
 
 /** @} */ /* end group uddapi */
 
-
 #ifdef __cplusplus
 }
 #endif
index ada1488eef67446ce3c6a93a3caf4c53b3e78003..10484ba05e015ba7f7a3f8d9881dee3cae50126a 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 5987b0a9149edced736c49a2161efe504c90676a..edee5eac4a17739b0726cb9034c7fba31696668e 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -128,7 +128,7 @@ MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list )
  * @param list the list to check.
  * @return non-zero if the list is empty, and zero otherwise.
  */
-MALI_STATIC_INLINE int _mali_osk_list_empty( _mali_osk_list_t *list )
+MALI_STATIC_INLINE mali_bool _mali_osk_list_empty( _mali_osk_list_t *list )
 {
     return list->next == list;
 }
index 427fcc8de335be201d996b354572c06972699f59..1439d18010a6ecec008a8f8a10a3fb393b2f6b95 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -26,33 +26,54 @@ extern "C"
 /** @addtogroup _mali_osk_miscellaneous
  * @{ */
 
-/** @brief Read the Mali Resource configuration
- *
- * Populates a _mali_arch_resource_t array from configuration settings, which
- * are stored in an OS-specific way.
- *
- * For example, these may be compiled in to a static structure, or read from
- * the filesystem at startup.
- *
- * On failure, do not call _mali_osk_resources_term.
+/** @brief Struct with device specific configuration data
+ */
+struct _mali_osk_device_data
+{
+       /* Dedicated GPU memory range (physical). */
+       u32 dedicated_mem_start;
+       u32 dedicated_mem_size;
+
+       /* Shared GPU memory */
+       u32 shared_mem_size;
+
+       /* Frame buffer memory to be accessible by Mali GPU (physical) */
+       u32 fb_start;
+       u32 fb_size;
+
+       /* Report GPU utilization in this interval (specified in ms) */
+       u32 utilization_interval;
+
+       /* Function that will receive periodic GPU utilization numbers */
+       void (*utilization_handler)(unsigned int);
+};
+
+/** @brief Find Mali GPU HW resource
  *
- * @param arch_config a pointer to the store the pointer to the resources
- * @param num_resources the number of resources read
- * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_NOMEM on allocation
- * error. For other failures, a suitable _mali_osk_errcode_t is returned.
+ * @param addr Address of Mali GPU resource to find
+ * @param res Storage for resource information if resource is found.
+ * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if resource is not found
  */
-_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources );
+_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res);
+
 
-/** @brief Free resources allocated by _mali_osk_resources_init.
+/** @brief Find Mali GPU HW base address
  *
- * Frees the _mali_arch_resource_t array allocated by _mali_osk_resources_init
+ * @return 0 if resources are found, otherwise the Mali GPU component with lowest address.
+ */
+u32 _mali_osk_resource_base_address(void);
+
+/** @brief Retrieve the Mali GPU specific data
  *
- * @param arch_config a pointer to the stored the pointer to the resources
- * @param num_resources the number of resources in the array
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
  */
-void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources);
+_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data);
+
 /** @} */ /* end group _mali_osk_miscellaneous */
 
+
+
+
 /** @addtogroup _mali_osk_low_level_memory
  * @{ */
 
index bf1cf8c422b34b5f25b94fd6e08a11830251ac37..200325ecb1e267b3576b461b061f4e34779c1a61 100644 (file)
@@ -1,17 +1,17 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_OSK_PROFILING_H__
 #define __MALI_OSK_PROFILING_H__
 
-#if MALI_TIMELINE_PROFILING_ENABLED && defined (CONFIG_TRACEPOINTS)
+#if defined(CONFIG_MALI400_PROFILING) && defined (CONFIG_TRACEPOINTS)
 
 #include "mali_linux_trace.h"
 #include "mali_profiling_events.h"
@@ -127,12 +127,13 @@ mali_bool _mali_osk_profiling_have_recording(void);
 
 /** @} */ /* end group _mali_osk_profiling */
 
-#else
+#else /* defined(CONFIG_MALI400_PROFILING)  && defined(CONFIG_TRACEPOINTS) */
+
  /* Dummy add_event, for when profiling is disabled. */
 
 #define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4)
 
-#endif /* MALI_TIMELINE_PROFILING_ENABLED  && defined(CONFIG_TRACEPOINTS*/
+#endif /* defined(CONFIG_MALI400_PROFILING)  && defined(CONFIG_TRACEPOINTS) */
 
 #endif /* __MALI_OSK_PROFILING_H__ */
 
index 933e54e36236dad53b83e0fff01f20faa0ad6e16..a6ac3deab799d9d3586c62a04c58d56c37f70077 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_pm.h"
 #include "mali_osk.h"
 #include "mali_gp_scheduler.h"
 #include "mali_pp_scheduler.h"
-#include "mali_platform.h"
+#include "mali_scheduler.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 );
+static mali_bool mali_power_on = MALI_FALSE;
 
 _mali_osk_errcode_t mali_pm_initialize(void)
 {
-       mali_pm_lock_execute_state_change = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_EXECUTE);
-
-       if (NULL != mali_pm_lock_execute_state_change )
-       {
-               mali_pm_lock_set_next_state = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ONELOCK| _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_LAST);
-
-               if (NULL != mali_pm_lock_set_next_state)
-               {
-                       mali_pm_lock_set_core_states = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_CORE_STATE);
-
-                       if (NULL != mali_pm_lock_set_core_states)
-                       {
-                               idle_timer = _mali_osk_timer_init();
-                               if (NULL != idle_timer)
-                               {
-                                       wq_irq = _mali_osk_irq_init(_MALI_OSK_IRQ_NUMBER_PMM,
-                                                                                               mali_pm_upper_half,
-                                                                                               mali_pm_bottom_half,
-                                                                                               NULL,
-                                                                                               NULL,
-                                                                                               (void *)NULL,
-                                                                                               "Mali PM deferred work");
-                                       if (NULL != wq_irq)
-                                       {
-                                               if (_MALI_OSK_ERR_OK == mali_platform_init())
-                                               {
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
-                                                       _mali_osk_pm_dev_enable();
-                                                       mali_pm_powerup();
-#endif
-                                                       return _MALI_OSK_ERR_OK;
-                                               }
-
-                                               _mali_osk_irq_term(wq_irq);
-                                       }
-
-                                       _mali_osk_timer_del(idle_timer);
-                                       _mali_osk_timer_term(idle_timer);
-                               }
-                               _mali_osk_lock_term(mali_pm_lock_set_core_states);
-                       }
-                       _mali_osk_lock_term(mali_pm_lock_set_next_state);
-               }
-               _mali_osk_lock_term(mali_pm_lock_execute_state_change);
-       }
-
-       return _MALI_OSK_ERR_FAULT;
-}
-
-void mali_pm_terminate(void)
-{
-       mali_platform_deinit();
-       _mali_osk_irq_term(wq_irq);
-       _mali_osk_timer_del(idle_timer);
-       _mali_osk_timer_term(idle_timer);
-       _mali_osk_lock_term(mali_pm_lock_execute_state_change);
-       _mali_osk_lock_term(mali_pm_lock_set_next_state);
-       _mali_osk_lock_term(mali_pm_lock_set_core_states);
-}
-
-
-inline void mali_pm_lock(void)
-{
-       _mali_osk_lock_wait(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW);
-}
-
-inline void mali_pm_unlock(void)
-{
-       _mali_osk_lock_signal(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW);
-}
-
-inline void mali_pm_execute_state_change_lock(void)
-{
-       _mali_osk_lock_wait(mali_pm_lock_execute_state_change,_MALI_OSK_LOCKMODE_RW);
-}
-
-inline void mali_pm_execute_state_change_unlock(void)
-{
-       _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
-}
-
-static void mali_pm_powerup(void)
-{
-#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
-       MALI_DEBUG_PRINT(3, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n"));
-       mali_platform_power_mode_change(MALI_POWER_MODE_ON);
-#else
-       /* Aquire our reference */
-       _mali_osk_pm_dev_activate();
-#endif
-       mali_group_power_on();
-}
-
-static void mali_pm_powerdown(mali_power_mode power_mode)
-{
-       if ( (MALI_PM_LEVEL_1_ON == current_level) || (MALI_PM_LEVEL_2_STANDBY == current_level) )
-       {
-               mali_group_power_off();
-       }
-
-#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
-       mali_platform_power_mode_change(power_mode);
-#else
-       _mali_osk_pm_dev_idle();
-
-       if (MALI_POWER_MODE_DEEP_SLEEP == power_mode)
-       {
-               mali_platform_power_mode_change(power_mode);
-       }
-#endif
-}
-
-mali_bool mali_pm_is_powered_on(void)
-{
-       mali_bool is_on = MALI_TRUE;
-
-       if( ! (MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme) )
-       {
-               is_on = MALI_FALSE;
-       }
-       else if ( ! (MALI_PM_LEVEL_1_ON == current_level || MALI_PM_LEVEL_2_STANDBY == current_level))
-       {
-               is_on = MALI_FALSE;
-       }
-       else if ( ! (MALI_PM_LEVEL_1_ON == next_level_dynamic || MALI_PM_LEVEL_2_STANDBY == next_level_dynamic))
-       {
-               is_on = MALI_FALSE;
-       }
-
-       return is_on;
-}
-
-MALI_DEBUG_CODE(
-static const char *state_as_string(enum mali_pm_level level)
-{
-       switch(level)
-       {
-               case MALI_PM_LEVEL_1_ON:
-                       return "MALI_PM_LEVEL_1_ON";
-               case MALI_PM_LEVEL_2_STANDBY:
-                       return "MALI_PM_LEVEL_2_STANDBY";
-               case MALI_PM_LEVEL_3_LIGHT_SLEEP:
-                       return "MALI_PM_LEVEL_3_LIGHT_SLEEP";
-               case MALI_PM_LEVEL_4_DEEP_SLEEP:
-                       return "MALI_PM_LEVEL_4_DEEP_SLEEP";
-               default:
-                       return "UNKNOWN LEVEL";
-       }
-});
-
-/* This could be used from another thread (work queue), if we need that */
-static void mali_pm_process_next(void)
-{
-       enum mali_pm_level pm_level_to_set;
-
-       _mali_osk_lock_wait(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
-
-       pm_level_to_set = current_level;
-
-       if (MALI_PM_SCHEME_DYNAMIC == current_scheme)
-       {
-               pm_level_to_set = next_level_dynamic;
-
-               MALI_DEBUG_PRINT(4, ("Mali PM: Dynamic scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(pm_level_to_set)));
-
-               if (current_level == pm_level_to_set)
-               {
-                       goto end_function; /* early out, no change in power level */
-               }
-
-               /* Start timers according to new state, so we get STANDBY -> LIGHT_SLEEP -> DEEP_SLEEP */
-
-               if (MALI_TRUE == idle_timer_running)
-               {
-                       /* There is an existing timeout, so delete it */
-                       _mali_osk_timer_del(idle_timer);
-                       idle_timer_running = MALI_FALSE;
-               }
-
-               /* Making sure that we turn on through the platform file
-                  Since it was turned OFF directly through the platform file.
-                  This might lead to double turn-on, but the plaform file supports that.*/
-               if ( current_level == MALI_PM_LEVEL_4_DEEP_SLEEP)
-               {
-                       mali_pm_powerup();
-                       mali_kernel_core_wakeup();
-
-               }
-               if (MALI_PM_LEVEL_1_ON == pm_level_to_set)
-               {
-                       if (MALI_PM_LEVEL_2_STANDBY != current_level)
-                       {
-                               /* We only need to do anything if we came from one of the sleeping states */
-                               mali_pm_powerup();
-
-                               /* Wake up Mali cores since we came from a sleep state */
-                               mali_kernel_core_wakeup();
-                       }
-               }
-               else if (MALI_PM_LEVEL_2_STANDBY == pm_level_to_set)
-               {
-                       /* This is just an internal state, so we don't bother to report it to the platform file */
-                       idle_timer_running = MALI_TRUE;
-                       _mali_osk_timer_setcallback(idle_timer, timeout_light_sleep, (void*) mali_pm_event_number_get());
-                       _mali_osk_timer_add(idle_timer, _mali_osk_time_mstoticks(MALI_PM_LIGHT_SLEEP_TIMEOUT));
-               }
-               else if (MALI_PM_LEVEL_3_LIGHT_SLEEP == pm_level_to_set)
-               {
-                       mali_pm_powerdown(MALI_POWER_MODE_LIGHT_SLEEP);
-               }
-               else if (MALI_PM_LEVEL_4_DEEP_SLEEP == pm_level_to_set)
-               {
-                       MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n"));
-                       mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP);
-               }
-       }
-       else if (MALI_PM_SCHEME_OS_SUSPENDED == current_scheme)
-       {
-               MALI_DEBUG_PRINT(4, ("Mali PM: OS scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_4_DEEP_SLEEP)));
-
-               pm_level_to_set = MALI_PM_LEVEL_4_DEEP_SLEEP;
-
-               if (current_level == pm_level_to_set)
-               {
-                       goto end_function; /* early out, no change in power level */
-               }
-
-               /* Cancel any timers */
-               if (MALI_TRUE == idle_timer_running)
-               {
-                       /* There is an existing timeout, so delete it */
-                       _mali_osk_timer_del(idle_timer);
-                       idle_timer_running = MALI_FALSE;
-               }
-
-               MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n"));
-               mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP);
-               next_level_dynamic = current_level;
-       }
-       else if (MALI_PM_SCHEME_ALWAYS_ON == current_scheme)
-       {
-               MALI_DEBUG_PRINT(4, ("Mali PM: Always on scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_1_ON)));
-
-               pm_level_to_set = MALI_PM_LEVEL_1_ON;
-               if (current_level == pm_level_to_set)
-               {
-                       goto end_function; /* early out, no change in power level */
-               }
-
-               MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n"));
-               mali_pm_powerup();
-               if (MALI_PM_LEVEL_2_STANDBY != current_level)
-               {
-                       /* Wake up Mali cores since we came from a sleep state */
-                       mali_kernel_core_wakeup();
-               }
-       }
-       else
-       {
-               MALI_PRINT_ERROR(("MALI PM: Illegal scheme"));
-       }
-
-       current_level = pm_level_to_set;
-
-end_function:
-       _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
-
-}
-
-void mali_pm_always_on(mali_bool enable)
-{
-       if (MALI_TRUE == enable)
-       {
-               /* The event is processed in current thread synchronously */
-               mali_pm_event(MALI_PM_EVENT_SCHEME_ALWAYS_ON, MALI_FALSE, 0 );
-       }
-       else
-       {
-               /* The event is processed in current thread synchronously */
-               mali_pm_event(MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, MALI_FALSE, 0 );
-       }
-}
-
-static _mali_osk_errcode_t mali_pm_upper_half(void *data)
-{
-       /* not used */
+       _mali_osk_pm_dev_enable();
        return _MALI_OSK_ERR_OK;
 }
 
-static void mali_pm_bottom_half(void *data)
+void mali_pm_terminate(void)
 {
-       mali_pm_process_next();
+       _mali_osk_pm_dev_disable();
 }
 
-static u32 mali_pm_event_number_get(void)
+void mali_pm_core_event(enum mali_core_event core_event)
 {
-       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;
-}
+       MALI_DEBUG_ASSERT(MALI_CORE_EVENT_GP_START == core_event ||
+                         MALI_CORE_EVENT_PP_START == core_event ||
+                         MALI_CORE_EVENT_GP_STOP  == core_event ||
+                         MALI_CORE_EVENT_PP_STOP  == core_event);
 
-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 )
+       if (MALI_CORE_EVENT_GP_START == core_event || MALI_CORE_EVENT_PP_START == core_event)
        {
-               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 )
+               _mali_osk_pm_dev_ref_add();
+               if (mali_utilization_enabled())
                {
-                       /* 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;
+                       mali_utilization_core_start(_mali_osk_time_get_ns());
                }
        }
        else
        {
-               /* Delete possible ongoing timers
-               if (  (MALI_PM_LEVEL_2_STANDBY==current_level) || (MALI_PM_LEVEL_3_LIGHT_SLEEP==current_level) )
+               _mali_osk_pm_dev_ref_dec();
+               if (mali_utilization_enabled())
                {
-                       _mali_osk_timer_del(idle_timer);
+                       mali_utilization_core_end(_mali_osk_time_get_ns());
                }
-               */
-       }
-       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)
+/* Reset GPU after power up */
+static void mali_pm_reset_gpu(void)
 {
-       /* 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);
-}
+       /* Reset all L2 caches */
+       mali_l2_cache_reset_all();
 
-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);
+       /* Reset all groups */
+       mali_scheduler_reset_all_groups();
 }
 
 void mali_pm_os_suspend(void)
 {
-       MALI_DEBUG_PRINT(2, ("Mali PM: OS suspending...\n"));
-
+       MALI_DEBUG_PRINT(3, ("Mali PM: OS suspend\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"));
+       mali_group_power_off();
+       mali_power_on = MALI_FALSE;
 }
 
 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_DEBUG_PRINT(3, ("Mali PM: OS resume\n"));
+       if (MALI_TRUE != mali_power_on)
+       {
+               mali_pm_reset_gpu();
+               mali_group_power_on();
+       }
        mali_gp_scheduler_resume();
        mali_pp_scheduler_resume();
-
-       MALI_DEBUG_PRINT(2, ("Mali PM: OS resume completed\n"));
+       mali_power_on = MALI_TRUE;
 }
 
 void mali_pm_runtime_suspend(void)
 {
-       MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime suspended\n"));
-       mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
+       MALI_DEBUG_PRINT(3, ("Mali PM: Runtime suspend\n"));
+       mali_group_power_off();
+       mali_power_on = MALI_FALSE;
 }
 
 void mali_pm_runtime_resume(void)
 {
-       MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime resumed\n"));
-       mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+       MALI_DEBUG_PRINT(3, ("Mali PM: Runtime resume\n"));
+       if (MALI_TRUE != mali_power_on)
+       {
+               mali_pm_reset_gpu();
+               mali_group_power_on();
+       }
+       mali_power_on = MALI_TRUE;
 }
index d4ccfde490bbc5b13b97e6674b23ac4194d82366..70b353397124dfa4de65556013a3c50840db7ea1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_PM_H__
@@ -21,32 +21,12 @@ enum mali_core_event
        MALI_CORE_EVENT_PP_STOP
 };
 
-enum mali_pm_event
-{
-       MALI_PM_EVENT_CORES_WORKING,
-       MALI_PM_EVENT_CORES_IDLE,
-       MALI_PM_EVENT_TIMER_LIGHT_SLEEP,
-       MALI_PM_EVENT_TIMER_DEEP_SLEEP,
-       MALI_PM_EVENT_OS_SUSPEND,
-       MALI_PM_EVENT_OS_RESUME,
-       MALI_PM_EVENT_SCHEME_ALWAYS_ON,
-       MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL,
-};
-
 _mali_osk_errcode_t mali_pm_initialize(void);
 void mali_pm_terminate(void);
-void mali_pm_always_on(mali_bool enable);
-
-void mali_pm_lock(void);
-void mali_pm_unlock(void);
-void mali_pm_execute_state_change_lock(void);
-
-void mali_pm_execute_state_change_unlock(void);
-
-mali_bool mali_pm_is_powered_on(void);
 
 void mali_pm_core_event(enum mali_core_event core_event);
 
+/* Callback functions registered for the runtime PMM system */
 void mali_pm_os_suspend(void);
 void mali_pm_os_resume(void);
 void mali_pm_runtime_suspend(void);
index 348b5dc74dd0a3620d5818cfaf4dc0a60bd1c34b..a06df8f69fed6849679305d528c684f88ad02546 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -94,14 +94,13 @@ _mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu)
        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;
+       timeout = MALI_REG_POLL_COUNT_SLOW ;
        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 );
 
@@ -125,18 +124,17 @@ _mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu)
        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;
+       timeout = MALI_REG_POLL_COUNT_SLOW;
        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);
+               if ( stat == 0 ) break; /* All cores we wanted are now awake */
                timeout--;
-       } while( timeout > 0 );
+       } while ( timeout > 0 );
 
-       if( timeout == 0 )
+       if ( timeout == 0 )
        {
                return _MALI_OSK_ERR_TIMEOUT;
        }
index fd10c080cbdcf8de1b02036f52642be3debbdde1..82b8574e7782da219a4509a6734de5feb4546e7a 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 290cdea2388d7c48b29fc470a2f3ae944e48eb70..78eddd681413aa33554bc8d5e7e4ca3119118298 100644 (file)
@@ -1,71 +1,37 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
-//#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <mach/am_regs.h>
-#include <linux/module.h>
-//#endif
-
+#include "mali_pp_job.h"
 #include "mali_pp.h"
 #include "mali_hw_core.h"
 #include "mali_group.h"
-#include "mali_osk.h"
-#include "mali_pp_scheduler.h"
 #include "regs/mali_200_regs.h"
 #include "mali_kernel_common.h"
 #include "mali_kernel_core.h"
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
 #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 */
-};
+/* Number of frame registers on Mali-200 */
+#define MALI_PP_MALI200_NUM_FRAME_REGISTERS ((0x04C/4)+1)
+/* Number of frame registers on Mali-300 and later */
+#define MALI_PP_MALI400_NUM_FRAME_REGISTERS ((0x058/4)+1)
 
 static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES];
 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 *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual)
 {
        struct mali_pp_core* core = NULL;
 
@@ -81,39 +47,40 @@ struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct
        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 (!is_virtual)
+                       {
+                               ret = mali_pp_reset(core);
+                       }
+                       else
+                       {
+                               ret = _MALI_OSK_ERR_OK;
+                       }
 
                        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)
+                               ret = mali_group_add_pp_core(group, core);
+                               if (_MALI_OSK_ERR_OK == ret)
                                {
-                                       /* Initialise the timeout timer */
-                                       core->timeout_timer = _mali_osk_timer_init();
-                                       if(NULL != core->timeout_timer)
+                                       /* Setup IRQ handlers (which will do IRQ probing if needed) */
+                                       MALI_DEBUG_ASSERT(!is_virtual || -1 != resource->irq);
+
+                                       core->irq = _mali_osk_irq_init(resource->irq,
+                                                                      mali_group_upper_half_pp,
+                                                                      group,
+                                                                      mali_pp_irq_probe_trigger,
+                                                                      mali_pp_irq_probe_ack,
+                                                                      core,
+                                                                      "mali_pp_irq_handlers");
+                                       if (NULL != core->irq)
                                        {
-                                               _mali_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++;
 
@@ -121,14 +88,13 @@ struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct
                                        }
                                        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);
+                                               MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
                                        }
+                                       mali_group_remove_pp_core(group);
                                }
                                else
                                {
-                                       MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
+                                       MALI_PRINT_ERROR(("Mali PP: Failed to add core %s to group\n", core->hw_core.description));
                                }
                        }
                        mali_hw_core_delete(&core->hw_core);
@@ -150,12 +116,11 @@ void mali_pp_delete(struct mali_pp_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);
 
        /* Remove core from global list */
-       for (i = 0; i < mali_global_num_pp_cores; i++)
+       for (i = 0; i < MALI_MAX_NUMBER_OF_PP_CORES; i++)
        {
                if (mali_global_pp_cores[i] == core)
                {
@@ -178,23 +143,20 @@ void mali_pp_stop_bus(struct mali_pp_core *core)
 _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++)
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
        {
                if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED)
                        break;
-               _mali_osk_time_ubusydelay(10);
        }
 
-       if (request_loop_count == i)
+       if (MALI_REG_POLL_COUNT_FAST == i)
        {
                MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
                return _MALI_OSK_ERR_FAULT;
@@ -254,35 +216,31 @@ static const u32 mali_perf_cnt_enable_reset_value = 0;
 _mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core)
 {
        /* Bus must be stopped before calling this function */
-       const 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);
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value);
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
 
        /* Force core to reset */
        mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);
 
        /* Wait for reset to be complete */
-       for (i = 0; i < reset_finished_loop_count; i++)
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
        {
                mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value);
                if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW))
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(10);
        }
 
-       if (i == reset_finished_loop_count)
+       if (MALI_REG_POLL_COUNT_FAST == i)
        {
                MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n"));
        }
@@ -295,67 +253,39 @@ _mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core)
        return _MALI_OSK_ERR_OK;
 }
 
-_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
+void mali_pp_reset_async(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_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description));
 
        mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_MASK_ALL);
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);
+}
 
-#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_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core)
+{
+       int i;
+       u32 rawstat = 0;
 
-       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);
+       /* TODO: For virtual Mali-450 core, check that PP active in STATUS is 0 (this must be initiated from group) */
 
-       for (i = 0; i < request_loop_count; i++)
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
        {
-               if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)
+               rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT);
+               if (rawstat & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)
                {
                        break;
                }
-               _mali_osk_time_ubusydelay(10);
        }
 
-       if (request_loop_count == i)
+       if (i == MALI_REG_POLL_COUNT_FAST)
        {
-               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)));
+               MALI_PRINT_ERROR(("Mali PP: Failed to reset core %s, rawstat: 0x%08x\n",
+                                core->hw_core.description, rawstat));
                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);
@@ -364,96 +294,96 @@ _mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
        return _MALI_OSK_ERR_OK;
 }
 
-void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job)
+_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
+{
+       mali_pp_reset_async(core);
+       return mali_pp_reset_wait(core);
+}
+
+void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual)
 {
+       u32 num_frame_registers;
+       u32 relative_address;
+       u32 start_index;
+       u32 nr_of_regs;
        u32 *frame_registers = mali_pp_job_get_frame_registers(job);
        u32 *wb0_registers = mali_pp_job_get_wb0_registers(job);
        u32 *wb1_registers = mali_pp_job_get_wb1_registers(job);
        u32 *wb2_registers = mali_pp_job_get_wb2_registers(job);
-       core->counter_src0_used = core->counter_src0;
-       core->counter_src1_used = core->counter_src1;
+       core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job);
+       core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job);
 
        MALI_DEBUG_ASSERT_POINTER(core);
-       MALI_ASSERT_GROUP_LOCKED(core->group);
 
-       mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME, mali_frame_registers_reset_values);
+       /* Write frame registers */
+       num_frame_registers = (_MALI_PRODUCT_ID_MALI200 == mali_kernel_core_get_product_id()) ? MALI_PP_MALI200_NUM_FRAME_REGISTERS : MALI_PP_MALI400_NUM_FRAME_REGISTERS;
 
-       _mali_osk_mem_barrier();
+       /*
+        * There are two frame registers which are different for each sub job:
+        * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME)
+        * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK)
+        */
+       mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]);
 
-       if (0 != sub_job)
+       /* For virtual jobs, the stack address shouldn't be broadcast but written individually */
+       if (!mali_pp_job_is_virtual(job) || restart_virtual)
        {
-               /*
-                * 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_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK/4]);
+               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]);
        }
 
+       /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */
+       relative_address = MALI200_REG_ADDR_RSW;
+       start_index = MALI200_REG_ADDR_RSW / sizeof(u32);
+       nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32);
+
+       mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core,
+               relative_address, &frame_registers[start_index],
+               nr_of_regs, &mali_frame_registers_reset_values[start_index]);
+
+       /* MALI200_REG_ADDR_STACK_SIZE */
+       relative_address = MALI200_REG_ADDR_STACK_SIZE;
+       start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32);
+
+       mali_hw_core_register_write_relaxed_conditional(&core->hw_core,
+               relative_address, frame_registers[start_index],
+               mali_frame_registers_reset_values[start_index]);
+
+       /* Skip 2 reserved registers */
+
+       /* Write remaining registers */
+       relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X;
+       start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
+       nr_of_regs = num_frame_registers - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
+
+       mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core,
+               relative_address, &frame_registers[start_index],
+               nr_of_regs, &mali_frame_registers_reset_values[start_index]);
+
+       /* Write WBx registers */
        if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */
        {
-               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values);
-       }
-       else
-       {
-               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, 0, mali_wb_registers_reset_values[0] );
+               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
        }
 
        if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */
        {
-               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values);
-       }
-       else
-       {
-               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, 0, mali_wb_registers_reset_values[0] );
+               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
        }
 
        if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */
        {
-               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values);
-       }
-       else
-       {
-               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, 0, mali_wb_registers_reset_values[0] );
+               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
        }
 
-       /* 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)
+       if (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_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
-                       mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
-
-               }
-               if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
-               {
-                       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
-                       mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
-               }
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
+               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
        }
-       else
+       if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
        {
-               /* 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_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
-                               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
-                       }
-
-                       if (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_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
-                               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
-                       }
-               }
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
+               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
        }
 
        MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description));
@@ -466,18 +396,6 @@ void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 s
 
        /* 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, mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
-       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 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)
@@ -486,40 +404,6 @@ u32 mali_pp_core_get_version(struct mali_pp_core *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)
@@ -535,153 +419,11 @@ 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;
-}
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-int PP0_int_cnt = 0;
-int mali_PP0_int_cnt(void)
-{
-    return PP0_int_cnt;
-}
-EXPORT_SYMBOL(mali_PP0_int_cnt);
-
-int PP1_int_cnt = 0;
-int mali_PP1_int_cnt(void)
-{
-    return PP1_int_cnt;
-}
-EXPORT_SYMBOL(mali_PP1_int_cnt);
-#endif
-
 /* ------------- 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)
-       {
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-               if (core->core_id == 0)
-                       PP0_int_cnt++;
-               else if (core->core_id == 1)
-                       PP1_int_cnt++;
-#endif
-
-               /* 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
-       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
-#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);
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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 */
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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 */
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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;
-#if MALI_TIMELINE_PROFILING_ENABLED
-               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#endif
-               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
-       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
-#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_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
        mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG);
        _mali_osk_mem_barrier();
 }
@@ -703,80 +445,6 @@ static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data)
 }
 
 
-/* ------ 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)
 {
@@ -803,6 +471,38 @@ void mali_pp_print_state(struct mali_pp_core *core)
 }
 #endif
 
+void mali_pp_update_performance_counters(struct mali_pp_core *core, struct mali_pp_job *job, u32 subjob)
+{
+       u32 val0 = 0;
+       u32 val1 = 0;
+#if defined(CONFIG_MALI400_PROFILING)
+       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);
+
+               mali_pp_job_set_perf_counter_value0(job, subjob, val0);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               /*todo: check if the group is virtual - in such case, does it make sense to send a HW counter ?*/
+               _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);
+               mali_pp_job_set_perf_counter_value1(job, subjob, val1);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               /*todo: check if the group is virtual - in such case, does it make sense to send a HW counter ?*/
+               _mali_osk_profiling_report_hw_counter(counter_index + 1, val1);
+#endif
+       }
+}
+
 #if MALI_STATE_TRACKING
 u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size)
 {
index 9b425a08d36f02df7e3123b3af3384ab341be033..c1b989d7df79d7ef6b8c8489de3a08cad23c6e1f 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_PP_H__
 
 #include "mali_osk.h"
 #include "mali_pp_job.h"
+#include "mali_hw_core.h"
 
-struct mali_pp_core;
 struct mali_group;
 
+#define MALI_MAX_NUMBER_OF_PP_CORES        9
+
+/**
+ * Definition of the PP core struct
+ * Used to track a PP core in the system.
+ */
+struct mali_pp_core
+{
+       struct mali_hw_core  hw_core;           /**< Common for all HW cores */
+       _mali_osk_irq_t     *irq;               /**< IRQ handler */
+       u32                  core_id;           /**< Unique core ID */
+       u32                  counter_src0_used; /**< The selected performance counter 0 when a job is running */
+       u32                  counter_src1_used; /**< The selected performance counter 1 when a job is running */
+};
+
 _mali_osk_errcode_t mali_pp_initialize(void);
 void mali_pp_terminate(void);
 
-struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group);
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group, mali_bool is_virtual);
 void mali_pp_delete(struct mali_pp_core *core);
 
 void mali_pp_stop_bus(struct mali_pp_core *core);
 _mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core);
+void mali_pp_reset_async(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core);
 _mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core);
 _mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core);
 
-void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job);
+void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual);
 
 u32 mali_pp_core_get_version(struct mali_pp_core *core);
 
-u32 mali_pp_core_get_id(struct mali_pp_core *core);
+MALI_STATIC_INLINE u32 mali_pp_core_get_id(struct mali_pp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+       return core->core_id;
+}
 
-mali_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);
 
+void mali_pp_update_performance_counters(struct mali_pp_core *core, struct mali_pp_job *job, u32 subjob);
+
+MALI_STATIC_INLINE const char *mali_pp_get_hw_core_desc(struct mali_pp_core *core)
+{
+       return core->hw_core.description;
+}
+
+/*** Register reading/writing functions ***/
+MALI_STATIC_INLINE u32 mali_pp_get_int_stat(struct mali_pp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+}
+
+MALI_STATIC_INLINE u32 mali_pp_read_rawstat(struct mali_pp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
+}
+
+MALI_STATIC_INLINE void mali_pp_mask_all_interrupts(struct mali_pp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
+}
+
+MALI_STATIC_INLINE void mali_pp_clear_hang_interrupt(struct mali_pp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG);
+}
+
+MALI_STATIC_INLINE void mali_pp_enable_interrupts(struct mali_pp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+}
+
+MALI_STATIC_INLINE void mali_pp_write_addr_stack(struct mali_pp_core *core, struct mali_pp_job *job)
+{
+       u32 addr = mali_pp_job_get_addr_stack(job, core->core_id);
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, addr);
+}
+
 #endif /* __MALI_PP_H__ */
index 3c23637dda8f68d1466ee4a4c3e397e3880b60e1..feab75f03facde5cea4660f6961f2cb6dd6b01a9 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_pp_job.h"
 #include "mali_kernel_common.h"
 #include "mali_uk_types.h"
 
+static u32 pp_counter_src0 = MALI_HW_CORE_NO_COUNTER;      /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+static u32 pp_counter_src1 = MALI_HW_CORE_NO_COUNTER;      /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+
 struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id)
 {
        struct mali_pp_job *job;
+       u32 perf_counter_flag;
 
        job = _mali_osk_malloc(sizeof(struct mali_pp_job));
        if (NULL != job)
        {
                u32 i;
 
+               job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
+               if (NULL == job->finished_notification)
+               {
+                       _mali_osk_free(job);
+                       return NULL;
+               }
+
                if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s)))
                {
+                       _mali_osk_notification_delete(job->finished_notification);
                        _mali_osk_free(job);
                        return NULL;
                }
@@ -32,23 +44,60 @@ struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_
                if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS)
                {
                        MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
+                       _mali_osk_notification_delete(job->finished_notification);
                        _mali_osk_free(job);
                        return NULL;
                }
 
+               perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);
+               /* set counters got from user space only if no counters were set through debugfs / DS-5 */
+               if (MALI_HW_CORE_NO_COUNTER == mali_pp_job_get_pp_counter_src0())
+               {
+                       if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
+                       {
+                               mali_pp_job_set_pp_counter_src0(job->uargs.perf_counter_src0);
+                               mali_pp_job_set_perf_counter_src0(job, mali_pp_job_get_pp_counter_src0());
+                       }
+               }
+               else
+               {
+                       mali_pp_job_set_perf_counter_src0(job, mali_pp_job_get_pp_counter_src0());
+               }
+
+               if (MALI_HW_CORE_NO_COUNTER == mali_pp_job_get_pp_counter_src1())
+               {
+                       if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
+                       {
+                                       mali_pp_job_set_pp_counter_src1(job->uargs.perf_counter_src1);
+                                       mali_pp_job_set_perf_counter_src1(job, mali_pp_job_get_pp_counter_src1());
+                       }
+               }
+               else
+               {
+                       mali_pp_job_set_perf_counter_src1(job, mali_pp_job_get_pp_counter_src1());
+               }
+
                _mali_osk_list_init(&job->list);
                job->session = session;
+               _mali_osk_list_init(&job->session_list);
                job->id = id;
+
                for (i = 0; i < job->uargs.num_cores; i++)
                {
                        job->perf_counter_value0[i] = 0;
                        job->perf_counter_value1[i] = 0;
                }
+               job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1;
                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();
+#if defined(CONFIG_SYNC)
+               job->sync_point = NULL;
+               job->pre_fence = NULL;
+               job->sync_work = NULL;
+#endif
 
                return job;
        }
@@ -58,5 +107,37 @@ struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_
 
 void mali_pp_job_delete(struct mali_pp_job *job)
 {
+#ifdef CONFIG_SYNC
+       if (NULL != job->pre_fence) sync_fence_put(job->pre_fence);
+       if (NULL != job->sync_point) sync_fence_put(job->sync_point->fence);
+#endif
+       if (NULL != job->finished_notification)
+       {
+               _mali_osk_notification_delete(job->finished_notification);
+       }
        _mali_osk_free(job);
 }
+
+u32 mali_pp_job_get_pp_counter_src0(void)
+{
+       return pp_counter_src0;
+}
+
+mali_bool mali_pp_job_set_pp_counter_src0(u32 counter)
+{
+       pp_counter_src0 = counter;
+
+       return MALI_TRUE;
+}
+
+u32 mali_pp_job_get_pp_counter_src1(void)
+{
+       return pp_counter_src1;
+}
+
+mali_bool mali_pp_job_set_pp_counter_src1(u32 counter)
+{
+       pp_counter_src1 = counter;
+
+       return MALI_TRUE;
+}
index 7e25504f7f15914e66dda45d466a935748596621..8057c56a25650e399820251112033fc7e62c2599 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_PP_JOB_H__
 #include "mali_session.h"
 #include "mali_kernel_common.h"
 #include "regs/mali_200_regs.h"
+#include "mali_kernel_core.h"
+#ifdef CONFIG_SYNC
+#include <linux/sync.h>
+#endif
+#include "mali_dlbu.h"
 
 /**
- * The structure represends a PP job, including all sub-jobs
- * (This struct unfortunatly needs to be public because of how the _mali_osk_list_*
+ * The structure represents a PP job, including all sub-jobs
+ * (This struct unfortunately needs to be public because of how the _mali_osk_list_*
  * mechanism works)
  */
 struct mali_pp_job
 {
        _mali_osk_list_t list;                             /**< Used to link jobs together in the scheduler queue */
        struct mali_session_data *session;                 /**< Session which submitted this job */
+       _mali_osk_list_t session_list;                     /**< Used to link jobs together in the session job list */
        _mali_uk_pp_start_job_s uargs;                     /**< Arguments from user space */
-       u32 id;                                            /**< identifier for this job in kernel space (sequencial numbering) */
+       u32 id;                                            /**< Identifier for this job in kernel space (sequential numbering) */
        u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS];    /**< Value of performance counter 0 (to be returned to user space), one for each sub job */
        u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS];    /**< Value of performance counter 1 (to be returned to user space), one for each sub job */
+       u32 sub_jobs_num;                                  /**< Number of subjobs; set to 1 for Mali-450 if DLBU is used, otherwise equals number of PP cores */
        u32 sub_jobs_started;                              /**< Total number of sub-jobs started (always started in ascending order) */
        u32 sub_jobs_completed;                            /**< Number of completed sub-jobs in this superjob */
        u32 sub_job_errors;                                /**< Bitfield with errors (errors for each single sub-job is or'ed together) */
        u32 pid;                                           /**< Process ID of submitting process */
        u32 tid;                                           /**< Thread ID of submitting thread */
+       _mali_osk_notification_t *finished_notification;   /**< Notification sent back to userspace on job complete */
+#ifdef CONFIG_SYNC
+       mali_sync_pt *sync_point;                          /**< Sync point to signal on completion */
+       struct sync_fence_waiter sync_waiter;              /**< Sync waiter for async wait */
+       _mali_osk_wq_work_t *sync_work;                    /**< Work to schedule in callback */
+       struct sync_fence *pre_fence;                      /**< Sync fence this job must wait for */
+#endif
 };
 
 struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id);
 void mali_pp_job_delete(struct mali_pp_job *job);
 
-MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job)
-{
-       if ((0 == job->uargs.frame_registers[0]) || (0 == job->uargs.frame_registers[1]))
-       {
-               return _MALI_OSK_ERR_FAULT;
-       }
-       return _MALI_OSK_ERR_OK;
-}
+u32 mali_pp_job_get_pp_counter_src0(void);
+mali_bool mali_pp_job_set_pp_counter_src0(u32 counter);
+u32 mali_pp_job_get_pp_counter_src1(void);
+mali_bool mali_pp_job_set_pp_counter_src1(u32 counter);
 
 MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job)
 {
@@ -85,9 +95,23 @@ MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job)
        return job->uargs.frame_registers;
 }
 
+MALI_STATIC_INLINE u32* mali_pp_job_get_dlbu_registers(struct mali_pp_job *job)
+{
+       return job->uargs.dlbu_registers;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_is_virtual(struct mali_pp_job *job)
+{
+       return 0 == job->uargs.num_cores;
+}
+
 MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job)
 {
-       if (sub_job == 0)
+       if (mali_pp_job_is_virtual(job))
+       {
+               return MALI_DLBU_VIRT_ADDR;
+       }
+       else if (0 == sub_job)
        {
                return job->uargs.frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)];
        }
@@ -101,7 +125,7 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 s
 
 MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job)
 {
-       if (sub_job == 0)
+       if (0 == sub_job)
        {
                return job->uargs.frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)];
        }
@@ -150,37 +174,22 @@ MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali
 
 MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job)
 {
-       return (job->sub_jobs_started < job->uargs.num_cores) ? MALI_TRUE : MALI_FALSE;
+       return (job->sub_jobs_started < job->sub_jobs_num) ? MALI_TRUE : MALI_FALSE;
 }
 
 /* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job.
-   Makes sure that no new subjobs is started. */
-MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(struct mali_pp_job *job)
+   Makes sure that no new subjobs are started. */
+MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_failed(struct mali_pp_job *job)
 {
-       /* All can not be started, since then it would not be in the job queue */
-       MALI_DEBUG_ASSERT( job->sub_jobs_started != job->uargs.num_cores );
-
-       /* 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->uargs.num_cores - job->sub_jobs_started;
-                       job->sub_jobs_started   += jobs_remaining;
-                       job->sub_jobs_completed += jobs_remaining;
-                       job->sub_job_errors     += jobs_remaining;
-                       /* Returning TRUE indicating that we can not delete this job which is being redered */
-                       return MALI_TRUE;
-               }
-       }
-       /* The job is not being rendered to at the moment and can then safely be deleted */
-       return MALI_FALSE;
+       u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started;
+       job->sub_jobs_started   += jobs_remaining;
+       job->sub_jobs_completed += jobs_remaining;
+       job->sub_job_errors     += jobs_remaining;
 }
 
 MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job)
 {
-       return (job->uargs.num_cores == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE;
+       return (job->sub_jobs_num == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE;
 }
 
 MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job)
@@ -190,7 +199,7 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_jo
 
 MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job)
 {
-       return job->uargs.num_cores;
+       return job->sub_jobs_num;
 }
 
 MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job)
@@ -203,9 +212,8 @@ MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job
 MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_not_stated(struct mali_pp_job *job, u32 sub_job)
 {
        /* This is only safe on Mali-200. */
-#if !defined(USING_MALI200)
-       MALI_DEBUG_ASSERT(0);
-#endif
+       MALI_DEBUG_ASSERT(_MALI_PRODUCT_ID_MALI200 == mali_kernel_core_get_product_id());
+
        job->sub_jobs_started--;
 }
 
@@ -267,6 +275,16 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *j
        return job->perf_counter_value1[sub_job];
 }
 
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_src0(struct mali_pp_job *job, u32 src)
+{
+       job->uargs.perf_counter_src0 = src;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_src1(struct mali_pp_job *job, u32 src)
+{
+       job->uargs.perf_counter_src1 = src;
+}
+
 MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value)
 {
        job->perf_counter_value0[sub_job] = value;
@@ -277,4 +295,13 @@ MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *
        job->perf_counter_value1[sub_job] = value;
 }
 
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job)
+{
+       if (mali_pp_job_is_virtual(job) && job->sub_jobs_num != 1)
+       {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
 #endif /* __MALI_PP_JOB_H__ */
index 37ce51b18af1e8ace707eaf4a88afe08ebe75d3b..7af05ea75df208ae75ae27d16dadba0506728d62 100644 (file)
@@ -1,57 +1,50 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_pp_scheduler.h"
 #include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
 #include "mali_osk.h"
 #include "mali_osk_list.h"
 #include "mali_scheduler.h"
 #include "mali_pp.h"
 #include "mali_pp_job.h"
 #include "mali_group.h"
-#include "mali_cluster.h"
-#include "mali_osk_profiling.h"
+#include "mali_pm.h"
 
 
 /* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */
-#define MALI_MAX_NUMBER_OF_PP_GROUPS 8
+#define MALI_MAX_NUMBER_OF_PP_GROUPS 9
 
 static mali_bool mali_pp_scheduler_is_suspended(void);
 
-enum mali_pp_slot_state
-{
-       MALI_PP_SLOT_STATE_IDLE,
-       MALI_PP_SLOT_STATE_WORKING,
-};
+static u32 pp_version = 0;
 
-/* A render slot is an entity which jobs can be scheduled onto */
-struct mali_pp_slot
-{
-       struct mali_group *group;
-       /*
-        * We keep track of the state here as well as in the group object
-        * so we don't need to take the group lock so often (and also avoid clutter with the working lock)
-        */
-       enum mali_pp_slot_state state;
-       struct mali_session_data *session;
-       struct mali_pp_job *job;
-       u32 subjob;
-};
+/* Physical job queue */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(job_queue);              /* List of physical jobs with some unscheduled work */
+static u32 job_queue_depth = 0;
 
-static u32 pp_version = 0;
-static _MALI_OSK_LIST_HEAD(job_queue);                          /* List of jobs with some unscheduled work */
-static u32 job_queue_depth;
+/* Physical groups */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_working);     /* List of physical groups with working jobs on the pp core */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_idle);        /* List of physical groups with idle jobs on the pp core */
+
+/* Virtual job queue (Mali-450 only) */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(virtual_job_queue);      /* List of unstarted jobs for the virtual group */
+static u32 virtual_job_queue_depth = 0;
 
-static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS];
-static u32 num_slots = 0;
-static u32 num_slots_idle = 0;
+/* Virtual group (Mali-450 only) */
+static struct mali_group *virtual_group = NULL;                 /* Virtual group (if any) */
+static mali_bool virtual_group_working = MALI_FALSE;            /* Flag which indicates whether the virtual group is working or idle */
+
+/* Number of physical cores */
+static u32 num_cores = 0;
 
 /* Variables to allow safe pausing of the scheduler */
 static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL;
@@ -61,11 +54,20 @@ 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_wq_work_t *pp_scheduler_wq = NULL;
+
 _mali_osk_errcode_t mali_pp_scheduler_initialize(void)
 {
+       struct mali_group *group;
+       struct mali_pp_core *pp_core;
+       u32 num_groups;
        u32 i;
 
        _MALI_OSK_INIT_LIST_HEAD(&job_queue);
+       _MALI_OSK_INIT_LIST_HEAD(&group_list_working);
+       _MALI_OSK_INIT_LIST_HEAD(&group_list_idle);
+
+       _MALI_OSK_INIT_LIST_HEAD(&virtual_job_queue);
 
        pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER);
        if (NULL == pp_scheduler_lock)
@@ -80,30 +82,58 @@ _mali_osk_errcode_t mali_pp_scheduler_initialize(void)
                return _MALI_OSK_ERR_NOMEM;
        }
 
+       pp_scheduler_wq = _mali_osk_wq_create_work(mali_pp_scheduler_do_schedule, NULL);
+       if (NULL == pp_scheduler_wq)
+       {
+               _mali_osk_lock_term(pp_scheduler_lock);
+               _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       num_groups = mali_group_get_glob_num_groups();
+
+       /* Do we have a virtual group? */
+       for (i = 0; i < num_groups; i++)
+       {
+               group = mali_group_get_glob_group(i);
+
+               if (mali_group_is_virtual(group))
+               {
+                       MALI_DEBUG_PRINT(3, ("Found virtual group %p\n", group));
+
+                       virtual_group = group;
+                       break;
+               }
+       }
+
        /* Find all the available PP cores */
-       for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++)
+       for (i = 0; i < num_groups; 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)
+               group = mali_group_get_glob_group(i);
+               pp_core = mali_group_get_pp_core(group);
+
+               if (NULL != pp_core && !mali_group_is_virtual(group))
                {
-                       struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
-                       if (NULL != pp_core)
+                       if (0 == pp_version)
                        {
-                               if (0 == pp_version)
-                               {
-                                       /* Retrieve PP version from first avaiable PP core */
-                                       pp_version = mali_pp_core_get_version(pp_core);
-                               }
-                               slots[num_slots].group = group;
-                               slots[num_slots].state = MALI_PP_SLOT_STATE_IDLE;
-                               slots[num_slots].session = NULL;
-                               num_slots++;
-                               num_slots_idle++;
+                               /* Retrieve PP version from the first available PP core */
+                               pp_version = mali_pp_core_get_version(pp_core);
                        }
-                       group_id++;
-                       group = mali_cluster_get_group(curr_cluster, group_id);
+
+                       if (NULL != virtual_group)
+                       {
+                               /* Add all physical PP cores to the virtual group */
+                               mali_group_lock(virtual_group);
+                               group->state = MALI_GROUP_STATE_JOINING_VIRTUAL;
+                               mali_group_add_group(virtual_group, group);
+                               mali_group_unlock(virtual_group);
+                       }
+                       else
+                       {
+                               _mali_osk_list_add(&group->pp_scheduler_list, &group_list_idle);
+                       }
+
+                       num_cores++;
                }
        }
 
@@ -112,6 +142,20 @@ _mali_osk_errcode_t mali_pp_scheduler_initialize(void)
 
 void mali_pp_scheduler_terminate(void)
 {
+       struct mali_group *group, *temp;
+
+       /* Delete all groups owned by scheduler */
+       if (NULL != virtual_group)
+       {
+               mali_group_delete(virtual_group);
+       }
+
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list)
+       {
+               mali_group_delete(group);
+       }
+
        _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue);
        _mali_osk_lock_term(pp_scheduler_lock);
 }
@@ -146,148 +190,294 @@ MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void)
 #define MALI_ASSERT_PP_SCHEDULER_LOCKED()
 #endif
 
-static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_data *session)
+/**
+ * Returns a physical job if a physical job is ready to run (no barrier present)
+ */
+MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_physical_job(void)
 {
-       u32 i;
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
 
+       if (!_mali_osk_list_empty(&job_queue))
+       {
+               struct mali_pp_job *job;
+
+               MALI_DEBUG_ASSERT(job_queue_depth > 0);
+               job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list);
+
+               if (!mali_pp_job_has_active_barrier(job))
+               {
+                       return job;
+               }
+       }
+
+       return NULL;
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_physical_job(struct mali_pp_job *job)
+{
        MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT(job_queue_depth > 0);
 
-       if (num_slots_idle == num_slots)
+       /* Remove job from queue */
+       if (!mali_pp_job_has_unstarted_sub_jobs(job))
        {
-               return MALI_FALSE;
+               /* All sub jobs have been started: remove job from queue */
+               _mali_osk_list_del(&job->list);
        }
 
-       for (i = 0; i < num_slots; i++)
+       --job_queue_depth;
+}
+
+/**
+ * Returns a virtual job if a virtual job is ready to run (no barrier present)
+ */
+MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_virtual_job(void)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT_POINTER(virtual_group);
+
+       if (!_mali_osk_list_empty(&virtual_job_queue))
        {
-               if (MALI_PP_SLOT_STATE_WORKING == slots[i].state)
+               struct mali_pp_job *job;
+
+               MALI_DEBUG_ASSERT(virtual_job_queue_depth > 0);
+               job = _MALI_OSK_LIST_ENTRY(virtual_job_queue.next, struct mali_pp_job, list);
+
+               if (!mali_pp_job_has_active_barrier(job))
                {
-                       if (slots[i].session == session)
-                       {
-                               return MALI_TRUE;
-                       }
+                       return job;
                }
        }
 
-       return MALI_FALSE;
+       return NULL;
 }
 
-static mali_bool slots_available(void)
+MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_virtual_job(struct mali_pp_job *job)
 {
-       return num_slots_idle > 0;
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT(virtual_job_queue_depth > 0);
+
+       /* Remove job from queue */
+       _mali_osk_list_del(&job->list);
+       --virtual_job_queue_depth;
 }
 
-static void mali_pp_scheduler_schedule(void)
+/**
+ * Checks if the criteria is met for removing a physical core from virtual group
+ */
+MALI_STATIC_INLINE mali_bool mali_pp_scheduler_can_move_virtual_to_physical(void)
 {
-       struct mali_pp_job *job;
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT(NULL != virtual_group);
+       MALI_ASSERT_GROUP_LOCKED(virtual_group);
+       /*
+        * The criteria for taking out a physical group from a virtual group are the following:
+        * - There virtual group is idle
+        * - There are currently no physical groups (idle and working)
+        * - There are physical jobs to be scheduled (without a barrier)
+        */
+       return (!virtual_group_working) &&
+              _mali_osk_list_empty(&group_list_idle) &&
+              _mali_osk_list_empty(&group_list_working) &&
+              (NULL != mali_pp_scheduler_get_physical_job());
+}
 
-       if (0 < pause_count || 0 == num_slots_idle || 0 == job_queue_depth)
+MALI_STATIC_INLINE struct mali_group *mali_pp_scheduler_acquire_physical_group(void)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+
+       if (!_mali_osk_list_empty(&group_list_idle))
        {
-               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
-                                    pause_count, num_slots_idle));
-               return; /* Nothing to do, so early out */
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from idle list\n"));
+               return _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list);
        }
+       else if (NULL != virtual_group)
+       {
+               MALI_ASSERT_GROUP_LOCKED(virtual_group);
+               if (mali_pp_scheduler_can_move_virtual_to_physical())
+               {
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from virtual group\n"));
+                       return mali_group_acquire_group(virtual_group);
+               }
+       }
+
+       return NULL;
+}
 
-       while(slots_available() && 0 < job_queue_depth)
+static void mali_pp_scheduler_schedule(void)
+{
+       struct mali_group* physical_groups_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1];
+       struct mali_pp_job* physical_jobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1];
+       u32 physical_subjobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS-1];
+       int num_physical_jobs_to_start = 0;
+       int i;
+
+       if (NULL != virtual_group)
        {
-               u32 i, slot_count;
-               struct mali_pp_slot *reserved_slots[num_slots];
-               struct mali_session_data *session;
+               /* Need to lock the virtual group because we might need to grab a physical group from it */
+               mali_group_lock(virtual_group);
+       }
 
-               mali_pp_scheduler_lock();
-               /* Get job */
-               if (_mali_osk_list_empty(&job_queue) || !slots_available())
+       mali_pp_scheduler_lock();
+       if (pause_count > 0)
+       {
+               /* Scheduler is suspended, don't schedule any jobs */
+               mali_pp_scheduler_unlock();
+               if (NULL != virtual_group)
                {
-                       mali_pp_scheduler_unlock();
-                       break; /* No more jobs to schedule, so early out */
+                       mali_group_unlock(virtual_group);
                }
-               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 */
-               session = mali_pp_job_get_session(job);
+               return;
+       }
+
+       /* Find physical job(s) to schedule first */
+       while (1)
+       {
+               struct mali_group *group;
+               struct mali_pp_job *job;
+               u32 subjob;
 
-               if (MALI_TRUE == mali_pp_job_has_active_barrier(job))
+               job = mali_pp_scheduler_get_physical_job();
+               if (NULL == job)
                {
-                       if (MALI_TRUE == mali_pp_scheduler_session_has_running_jobs(mali_pp_job_get_session(job)))
-                       {
-                               /* There is already a running job from this
-                                * session, so we need to enforce the barrier */
-                               mali_pp_scheduler_unlock();
-                               return;
-                       }
-                       else
-                       {
-                               /* Barrier is now enforced, update job object
-                                * so we don't delay execution of sub-jobs */
-                               mali_pp_job_barrier_enforced(job);
-                       }
+                       break; /* No job, early out */
                }
 
-               /* Reserve slots */
-               for (i = 0, slot_count = 0; i < num_slots; i++)
+               MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual(job));
+               MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
+               MALI_DEBUG_ASSERT(1 <= mali_pp_job_get_sub_job_count(job));
+
+               /* Acquire a physical group, either from the idle list or from the virtual group.
+                * In case the group was acquired from the virtual group, it's state will be
+                * LEAVING_VIRTUAL and must be set to IDLE before it can be used. */
+               group = mali_pp_scheduler_acquire_physical_group();
+               if (NULL == group)
                {
-                       struct mali_pp_slot *slot = &slots[i];
+                       /* Could not get a group to run the job on, early out */
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: No more physical groups available.\n"));
+                       break;
+               }
 
-                       if (MALI_PP_SLOT_STATE_IDLE != slot->state) continue;
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquired physical group %p\n", group));
 
-                       slot->state = MALI_PP_SLOT_STATE_WORKING;
-                       slot->session = session;
-                       slot->job = job;
-                       slot->subjob = mali_pp_job_get_first_unstarted_sub_job(job);
-                       mali_pp_job_mark_sub_job_started(job, slot->subjob);
-                       --job_queue_depth;
+               /* Mark subjob as started */
+               subjob = mali_pp_job_get_first_unstarted_sub_job(job);
+               mali_pp_job_mark_sub_job_started(job, subjob);
 
-                       --num_slots_idle;
-                       reserved_slots[slot_count++] = slot;
+               /* Remove job from queue (if we now got the last subjob) */
+               mali_pp_scheduler_dequeue_physical_job(job);
 
-                       if (!mali_pp_job_has_unstarted_sub_jobs(job))
-                       {
-                               _mali_osk_list_del(&job->list);
-                               break;
-                       }
-               }
+               /* Move group to working list */
+               _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_working);
 
-               MALI_DEBUG_ASSERT(0 < slot_count);
+               /* Keep track of this group, so that we actually can start the job once we are done with the scheduler lock we are now holding */
+               physical_groups_to_start[num_physical_jobs_to_start] = group;
+               physical_jobs_to_start[num_physical_jobs_to_start] = job;
+               physical_subjobs_to_start[num_physical_jobs_to_start] = subjob;
+               ++num_physical_jobs_to_start;
 
-               mali_pp_scheduler_unlock();
+               MALI_DEBUG_ASSERT(num_physical_jobs_to_start < MALI_MAX_NUMBER_OF_PP_GROUPS);
+       }
 
-               /* Start (sub)job(s) on core(s) */
-               for(i = 0; i < slot_count; i++)
+       /* See if we have a virtual job to schedule */
+       if (NULL != virtual_group)
+       {
+               if (!virtual_group_working)
                {
-                       struct mali_pp_slot *slot = reserved_slots[i];
-                       struct mali_pp_job *job;
-                       u32 subjob;
+                       struct mali_pp_job *job = mali_pp_scheduler_get_virtual_job();
+                       if (NULL != job)
+                       {
+                               MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job));
+                               MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
+                               MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job));
 
-                       MALI_DEBUG_ASSERT_POINTER(slot);
-                       MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slot->state);
-                       MALI_DEBUG_ASSERT_POINTER(slot->job);
+                               /* Mark the one and only subjob as started */
+                               mali_pp_job_mark_sub_job_started(job, 0);
 
-                       job = slot->job;
-                       subjob = slot->subjob;
+                               /* Remove job from queue */
+                               mali_pp_scheduler_dequeue_virtual_job(job);
 
-                       if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slot->group, slot->job, slot->subjob))
-                       {
-                               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n",
-                                                mali_pp_job_get_id(job), job, subjob + 1,
-                                                mali_pp_job_get_sub_job_count(job)));
+                               /* Virtual group is now working */
+                               virtual_group_working = MALI_TRUE;
+
+                               /*
+                                * We no longer need the scheduler lock,
+                                * but we still need the virtual lock in order to start the virtual job
+                                */
+                               mali_pp_scheduler_unlock();
+
+                               /* Start job */
+                               if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(virtual_group, job, 0))
+                               {
+                                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from schedule)\n",
+                                                            mali_pp_job_get_id(job), job, 1,
+                                                            mali_pp_job_get_sub_job_count(job)));
+                               }
+                               else
+                               {
+                                       MALI_DEBUG_ASSERT(0);
+                               }
+
+                               /* And now we are all done with the virtual_group lock as well */
+                               mali_group_unlock(virtual_group);
                        }
                        else
                        {
-                               MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n"));
-                               /* This can only happen on Mali-200 */
-#if !defined(USING_MALI200)
-                               MALI_DEBUG_ASSERT(0);
-#endif
-                               mali_pp_scheduler_lock();
-                               /* Put job back on queue */
-                               mali_pp_job_mark_sub_job_not_stated(job, subjob);
-                               _mali_osk_list_add(&job->list, &job_queue);
-                               /* Set slot idle */
-                                slot->state = MALI_PP_SLOT_STATE_IDLE;
-                                slot->session = NULL;
-                                slot->job = NULL;
-                                slot->subjob = 0;
-                                mali_pp_scheduler_unlock();
+                               /* No virtual job, release the two locks we are holding */
+                               mali_pp_scheduler_unlock();
+                               mali_group_unlock(virtual_group);
                        }
                }
+               else
+               {
+                       /* Virtual core busy, release the two locks we are holding */
+                       mali_pp_scheduler_unlock();
+                       mali_group_unlock(virtual_group);
+               }
+
+       }
+       else
+       {
+               /* There is no virtual group, release the only lock we are holding */
+               mali_pp_scheduler_unlock();
+       }
+
+       /*
+        * Now we have released the scheduler lock, and we are ready to kick of the actual starting of the
+        * physical jobs.
+        * The reason we want to wait until we have released the scheduler lock is that job start actually
+        * may take quite a bit of time (quite many registers needs to be written). This will allow new jobs
+        * from user space to come in, and post processing of other PP jobs to happen at the same time as we
+        * start jobs.
+        */
+       for (i = 0; i < num_physical_jobs_to_start; i++)
+       {
+               struct mali_group *group = physical_groups_to_start[i];
+               struct mali_pp_job *job  = physical_jobs_to_start[i];
+               u32 sub_job              = physical_subjobs_to_start[i];
+
+               MALI_DEBUG_ASSERT_POINTER(group);
+               MALI_DEBUG_ASSERT_POINTER(job);
+
+               mali_group_lock(group);
+
+               /* In case this group was acquired from a virtual core, update it's state to IDLE */
+               group->state = MALI_GROUP_STATE_IDLE;
+
+               if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(group, job, sub_job))
+               {
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from schedule)\n",
+                                            mali_pp_job_get_id(job), job, sub_job + 1,
+                                            mali_pp_job_get_sub_job_count(job)));
+               }
+               else
+               {
+                       MALI_DEBUG_ASSERT(0);
+               }
+
+               mali_group_unlock(group);
+
+               /* @@@@ todo: remove the return value from mali_group_start_xx_job, since we can't fail on Mali-300++ */
        }
 }
 
@@ -295,79 +485,102 @@ static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job)
 {
        if (MALI_FALSE == mali_pp_job_use_no_notification(job))
        {
-               _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
-               if (NULL != notobj)
+               u32 i;
+               u32 sub_jobs = mali_pp_job_get_sub_job_count(job);
+               mali_bool success = mali_pp_job_was_success(job);
+
+               _mali_uk_pp_job_finished_s *jobres = job->finished_notification->result_buffer;
+               _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */
+               jobres->user_job_ptr = mali_pp_job_get_user_id(job);
+               if (MALI_TRUE == success)
                {
-                       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);
+                       jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS;
                }
                else
                {
-                       MALI_PRINT_ERROR(("Mali PP scheduler: Unable to allocate notification object\n"));
+                       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), job->finished_notification);
+               job->finished_notification = NULL;
        }
 
        mali_pp_job_delete(job);
 }
 
-void mali_pp_scheduler_do_schedule(void)
+void mali_pp_scheduler_do_schedule(void *arg)
 {
+       MALI_IGNORE(arg);
+
        mali_pp_scheduler_schedule();
 }
 
+void mali_pp_scheduler_schedule_async(void)
+{
+       _mali_osk_wq_schedule_work(pp_scheduler_wq);
+}
+
 void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success)
 {
-       u32 i;
-       struct mali_pp_slot *slot = NULL;
        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_bool barrier_enforced = MALI_FALSE;
+
+       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) part %u/%u completed (%s)\n",
+                            mali_pp_job_is_virtual(job) ? "Virtual" : "Physical",
+                            mali_pp_job_get_id(job),
+                            job, sub_job + 1,
+                            mali_pp_job_get_sub_job_count(job),
+                            success ? "success" : "failure"));
        mali_pp_scheduler_lock();
 
        mali_pp_job_mark_sub_job_completed(job, success);
 
-       /* Find slot which was running this job */
-       for (i = 0; i < num_slots; i++)
+       MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job) == mali_group_is_virtual(group));
+
+       job_is_done = mali_pp_job_is_complete(job);
+
+       if (job_is_done)
        {
-               slot = &slots[i];
-               if (slot->group == group)
-                       break;
-       }
+               struct mali_session_data *session = mali_pp_job_get_session(job);
+               struct mali_pp_job *job_head;
 
-       MALI_DEBUG_ASSERT_POINTER(slot);
+               /* Remove job from session list */
+               _mali_osk_list_del(&job->session_list);
 
-       slot->state = MALI_PP_SLOT_STATE_IDLE;
-       slot->session = NULL;
-       slot->job = NULL;
-       slot->subjob = 0;
+               /* Send notification back to user space */
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for %s job %u (0x%08X)\n",
+                                    mali_pp_job_is_virtual(job) ? "virtual" : "physical",
+                                    mali_pp_job_get_id(job), job));
+#if defined(CONFIG_SYNC)
+               /* TODO propagate error */
+               if (job->sync_point)
+               {
+                       MALI_DEBUG_PRINT(2, ("Sync: Signal point for job %d\n", mali_pp_job_get_id(job)));
+                       mali_sync_signal_pt(job->sync_point);
+               }
+#endif
+               mali_pp_scheduler_return_job_to_user(job);
 
-       num_slots_idle++;
+               /* TODO: Should we do PM here? */
+               mali_pm_core_event(MALI_CORE_EVENT_PP_STOP);
+
+               /* Resolve any barriers */
+               if (!_mali_osk_list_empty(&session->job_list))
+               {
+                       job_head = _MALI_OSK_LIST_ENTRY(session->job_list.next, struct mali_pp_job, session_list);
+                       if (mali_pp_job_has_active_barrier(job_head))
+                       {
+                               barrier_enforced = MALI_TRUE;
+                               mali_pp_job_barrier_enforced(job_head);
+                       }
+               }
+       }
 
        /* If paused, then this was the last job, so wake up sleeping workers */
        if (pause_count > 0)
@@ -377,20 +590,174 @@ void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *jo
                 * threads will actually be woken up.
                 */
                _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue);
+               mali_pp_scheduler_unlock();
+               return;
        }
 
-       job_is_done = mali_pp_job_is_complete(job);
+       if (barrier_enforced)
+       {
+               /* A barrier was resolved, so schedule previously blocked jobs */
+               mali_pp_scheduler_schedule_async();
 
-       mali_pp_scheduler_unlock();
+               /* TODO: Subjob optimisation */
+       }
 
-       if (job_is_done)
+       /* Recycle variables */
+       job = NULL;
+       sub_job = 0;
+
+       if (mali_group_is_virtual(group))
        {
-               /* 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);
+               /* Virtual group */
+
+               /* Now that the virtual group is idle, check if we should reconfigure */
+               struct mali_pp_job *physical_job = NULL;
+               struct mali_group *physical_group = NULL;
+
+               /* Obey the policy */
+               virtual_group_working = MALI_FALSE;
+
+               if (mali_pp_scheduler_can_move_virtual_to_physical())
+               {
+                       /* There is a runnable physical job and we can acquire a physical group */
+                       physical_job = mali_pp_scheduler_get_physical_job();
+                       MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(physical_job));
+
+                       /* Mark subjob as started */
+                       sub_job = mali_pp_job_get_first_unstarted_sub_job(physical_job);
+                       mali_pp_job_mark_sub_job_started(physical_job, sub_job);
+
+                       /* Remove job from queue (if we now got the last subjob) */
+                       mali_pp_scheduler_dequeue_physical_job(physical_job);
+
+                       /* Acquire a physical group from the virtual group
+                        * It's state will be LEAVING_VIRTUAL and must be set to IDLE before it can be used */
+                       physical_group = mali_group_acquire_group(virtual_group);
+
+                       /* Move physical group to the working list, as we will soon start a job on it */
+                       _mali_osk_list_move(&(physical_group->pp_scheduler_list), &group_list_working);
+               }
+
+               /* Start the next virtual job */
+               job = mali_pp_scheduler_get_virtual_job();
+               if (NULL != job)
+               {
+                       /* There is a runnable virtual job */
+                       MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job));
+                       MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
+                       MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job));
+
+                       mali_pp_job_mark_sub_job_started(job, 0);
+
+                       /* Remove job from queue */
+                       mali_pp_scheduler_dequeue_virtual_job(job);
+
+                       /* Virtual group is now working */
+                       virtual_group_working = MALI_TRUE;
+
+                       mali_pp_scheduler_unlock();
+
+                       /* Start job */
+                       if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(group, job, 0))
+                       {
+                               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from job_done)\n",
+                                                    mali_pp_job_get_id(job), job, 1,
+                                                    mali_pp_job_get_sub_job_count(job)));
+                       }
+                       else
+                       {
+                               MALI_DEBUG_ASSERT(0);
+                       }
+               }
+               else
+               {
+                       mali_pp_scheduler_unlock();
+               }
+
+               /* Start a physical job (if we acquired a physical group earlier) */
+               if (NULL != physical_job && NULL != physical_group)
+               {
+                       mali_group_lock(physical_group);
+
+                       /* Set the group state from LEAVING_VIRTUAL to IDLE to complete the transition */
+                       physical_group->state = MALI_GROUP_STATE_IDLE;
+
+                       /* Start job on core */
+                       if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(physical_group, physical_job, sub_job))
+                       {
+                               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done)\n",
+                                                    mali_pp_job_get_id(physical_job), physical_job, sub_job + 1,
+                                                    mali_pp_job_get_sub_job_count(physical_job)));
+                       }
+                       else
+                       {
+                               /* @@@@ todo: this cant fail on Mali-300+, no need to implement put back of job */
+                               MALI_DEBUG_ASSERT(0);
+                       }
+
+                       mali_group_unlock(physical_group);
+               }
        }
+       else
+       {
+               /* Physical group */
+               job = mali_pp_scheduler_get_physical_job();
+               if (NULL != job)
+               {
+                       /* There is a runnable physical job */
+                       MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
 
-       mali_pp_scheduler_schedule();
+                       /* Mark subjob as started */
+                       sub_job = mali_pp_job_get_first_unstarted_sub_job(job);
+                       mali_pp_job_mark_sub_job_started(job, sub_job);
+
+                       /* Remove job from queue (if we now got the last subjob) */
+                       mali_pp_scheduler_dequeue_physical_job(job);
+
+                       mali_pp_scheduler_unlock();
+
+                       /* Group is already on the working list, so start the job */
+                       if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(group, job, sub_job))
+                       {
+                               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done)\n",
+                                                    mali_pp_job_get_id(job), job, sub_job + 1,
+                                                    mali_pp_job_get_sub_job_count(job)));
+                       }
+                       else
+                       {
+                               MALI_DEBUG_ASSERT(0);
+                       }
+               }
+               else if (NULL != virtual_group)
+               {
+                       /* Rejoin virtual group */
+                       /* TODO: In the future, a policy check might be useful here */
+
+                       /* We're no longer needed on the scheduler list */
+                       _mali_osk_list_delinit(&(group->pp_scheduler_list));
+
+                       /* Make sure no interrupts are handled for this group during
+                        * the transition from physical to virtual */
+                       group->state = MALI_GROUP_STATE_JOINING_VIRTUAL;
+
+                       mali_pp_scheduler_unlock();
+                       mali_group_unlock(group);
+
+                       mali_group_lock(virtual_group);
+                       /* TODO: Take group lock also? */
+                       mali_group_add_group(virtual_group, group);
+                       mali_group_unlock(virtual_group);
+
+                       /* We need to return from this function with the group lock held */
+                       /* TODO: optimise! */
+                       mali_group_lock(group);
+               }
+               else
+               {
+                       _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle);
+                       mali_pp_scheduler_unlock();
+               }
+       }
 }
 
 void mali_pp_scheduler_suspend(void)
@@ -411,17 +778,98 @@ void mali_pp_scheduler_resume(void)
 {
        mali_pp_scheduler_lock();
        pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
+       mali_pp_scheduler_unlock();
        if (0 == pause_count)
        {
                mali_pp_scheduler_schedule();
        }
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_queue_job(struct mali_pp_job *job, struct mali_session_data *session)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       mali_pm_core_event(MALI_CORE_EVENT_PP_START);
+
+       mali_pp_scheduler_lock();
+
+       if (mali_pp_job_is_virtual(job))
+       {
+               /* Virtual job */
+               virtual_job_queue_depth += 1;
+               _mali_osk_list_addtail(&job->list, &virtual_job_queue);
+       }
+       else
+       {
+               job_queue_depth += mali_pp_job_get_sub_job_count(job);
+               _mali_osk_list_addtail(&job->list, &job_queue);
+       }
+
+       if (mali_pp_job_has_active_barrier(job) && _mali_osk_list_empty(&session->job_list))
+       {
+               /* No running jobs on this session, so barrier condition already met */
+               mali_pp_job_barrier_enforced(job);
+       }
+
+       /* Add job to session list */
+       _mali_osk_list_addtail(&job->session_list, &session->job_list);
+
+       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) with %u parts queued\n",
+                            mali_pp_job_is_virtual(job) ? "Virtual" : "Physical",
+                            mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job)));
+
        mali_pp_scheduler_unlock();
 }
 
-_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs)
+#if defined(CONFIG_SYNC)
+static void sync_callback(struct sync_fence *fence, struct sync_fence_waiter *waiter)
+{
+       struct mali_pp_job *job = _MALI_OSK_CONTAINER_OF(waiter, struct mali_pp_job, sync_waiter);
+
+       /* Schedule sync_callback_work */
+       _mali_osk_wq_schedule_work(job->sync_work);
+}
+
+static void sync_callback_work(void *arg)
+{
+       struct mali_pp_job *job = (struct mali_pp_job *)arg;
+       struct mali_session_data *session;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       session = job->session;
+
+       /* Remove job from session pending job list */
+       _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+       _mali_osk_list_del(&job->list);
+       _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+
+       if (likely(0 == sync_fence_wait(job->pre_fence, 0)))
+       {
+               MALI_DEBUG_PRINT(3, ("Mali sync: Job %d ready to run\n", mali_pp_job_get_id(job)));
+
+               mali_pp_scheduler_queue_job(job, session);
+
+               if (0 == _mali_osk_list_empty(&group_list_idle)) mali_pp_scheduler_schedule();
+       }
+       else
+       {
+               /* Fence signaled error */
+               MALI_DEBUG_PRINT(3, ("Mali sync: Job %d abort due to sync error\n", mali_pp_job_get_id(job)));
+
+               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 */
+       }
+}
+#endif
+
+_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs, int *fence)
 {
        struct mali_session_data *session;
        struct mali_pp_job *job;
+#if defined(CONFIG_SYNC)
+       int post_fence = -1;
+#endif
 
        MALI_DEBUG_ASSERT_POINTER(uargs);
        MALI_DEBUG_ASSERT_POINTER(ctx);
@@ -431,6 +879,7 @@ _mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *u
        job = mali_pp_job_create(session, uargs, mali_scheduler_get_new_id());
        if (NULL == job)
        {
+               MALI_PRINT_ERROR(("Failed to create job!\n"));
                return _MALI_OSK_ERR_NOMEM;
        }
 
@@ -448,17 +897,107 @@ _mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *u
        return _MALI_OSK_ERR_OK;
 #endif
 
-       mali_pp_scheduler_lock();
+#if defined(CONFIG_SYNC)
+       if (_MALI_PP_JOB_FLAG_FENCE & job->uargs.flags)
+       {
+               job->sync_point = mali_stream_create_point(job->uargs.stream);
 
-       job_queue_depth += mali_pp_job_get_sub_job_count(job);
-       _mali_osk_list_addtail(&job->list, &job_queue);
+               if (unlikely(NULL == job->sync_point))
+               {
+                       /* Fence creation failed. */
+                       MALI_DEBUG_PRINT(2, ("Failed to create sync point for job %d\n", mali_pp_job_get_id(job)));
+                       mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+                       mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */
+                       return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */
+               }
 
-       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)));
+               post_fence = mali_stream_create_fence(job->sync_point);
 
-       mali_pp_scheduler_unlock();
+               if (unlikely(0 > post_fence))
+               {
+                       /* Fence creation failed. */
+                       /* mali_stream_create_fence already freed the sync_point */
+                       MALI_DEBUG_PRINT(2, ("Failed to create fence for job %d\n", mali_pp_job_get_id(job)));
+                       mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+                       mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */
+                       return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */
+               }
+
+               /* Grab a reference to the fence. It must be around when the
+                * job is completed, so the point can be signalled. */
+               sync_fence_fdget(post_fence);
+
+               *fence = post_fence;
+
+               MALI_DEBUG_PRINT(3, ("Sync: Created fence %d for job %d\n", post_fence, mali_pp_job_get_id(job)));
+       }
+
+       if (0 < job->uargs.fence)
+       {
+               int pre_fence_fd = job->uargs.fence;
+               int err;
+
+               MALI_DEBUG_PRINT(2, ("Sync: Job %d waiting for fence %d\n", mali_pp_job_get_id(job), pre_fence_fd));
+
+               job->pre_fence = sync_fence_fdget(pre_fence_fd); /* Reference will be released when job is deleted. */
+               if (NULL == job->pre_fence)
+               {
+                       MALI_DEBUG_PRINT(2, ("Failed to import fence %d\n", pre_fence_fd));
+                       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 */
+               }
+
+               job->sync_work = _mali_osk_wq_create_work(sync_callback_work, (void*)job);
+               if (NULL == job->sync_work)
+               {
+                       mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+                       mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */
+                       return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */
+               }
 
-       if (slots_available()) mali_pp_scheduler_schedule();
+               /* Add pending job to session pending job list */
+               _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+               _mali_osk_list_addtail(&job->list, &session->pending_jobs);
+               _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+
+               sync_fence_waiter_init(&job->sync_waiter, sync_callback);
+               err = sync_fence_wait_async(job->pre_fence, &job->sync_waiter);
+
+               if (0 != err)
+               {
+                       /* No async wait started, remove job from session pending job list */
+                       _mali_osk_lock_wait(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+                       _mali_osk_list_delinit(&job->list);
+                       _mali_osk_lock_signal(session->pending_jobs_lock, _MALI_OSK_LOCKMODE_RW);
+               }
+
+               if (1 == err)
+               {
+                       /* Fence has already signalled */
+                       mali_pp_scheduler_queue_job(job, session);
+                       if (0 == _mali_osk_list_empty(&group_list_idle)) mali_pp_scheduler_schedule();
+                       return _MALI_OSK_ERR_OK;
+               }
+               else if (0 > err)
+               {
+                       /* Sync fail */
+                       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 */
+               }
+
+       }
+       else
+#endif /* CONFIG_SYNC */
+       {
+               mali_pp_scheduler_queue_job(job, session);
+
+               if (!_mali_osk_list_empty(&group_list_idle) || !virtual_group_working)
+               {
+                       mali_pp_scheduler_schedule();
+               }
+       }
 
        return _MALI_OSK_ERR_OK;
 }
@@ -467,7 +1006,7 @@ _mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_c
 {
        MALI_DEBUG_ASSERT_POINTER(args);
        MALI_DEBUG_ASSERT_POINTER(args->ctx);
-       args->number_of_cores = num_slots;
+       args->number_of_cores = num_cores;
        return _MALI_OSK_ERR_OK;
 }
 
@@ -518,42 +1057,67 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args)
 
 void mali_pp_scheduler_abort_session(struct mali_session_data *session)
 {
-       struct mali_pp_job *job, *tmp;
-       int i;
+       struct mali_pp_job *job, *tmp_job;
+       struct mali_group *group, *tmp_group;
+       struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS];
+       s32 i = 0;
 
        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)
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &session->job_list, struct mali_pp_job, session_list)
        {
-               if (mali_pp_job_get_session(job) == session)
-               {
-                       _mali_osk_list_del(&(job->list));
-                       job_queue_depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job);
+               /* Remove job from queue (if it's not queued, list_del has no effect) */
+               _mali_osk_list_del(&job->list);
 
-                       if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) )
+               if (mali_pp_job_is_virtual(job))
+               {
+                       MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job));
+                       if (0 == mali_pp_job_get_first_unstarted_sub_job(job))
                        {
-                               /* 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;
+                               --virtual_job_queue_depth;
                        }
-                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Removing PP job 0x%08x from queue\n", job));
+               }
+               else
+               {
+                       job_queue_depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job);
+               }
+
+               /* Mark all unstarted jobs as failed */
+               mali_pp_job_mark_unstarted_failed(job);
+
+               if (mali_pp_job_is_complete(job))
+               {
+                       _mali_osk_list_del(&job->session_list);
+
+                       /* It is safe to delete the job, since it won't land in job_done() */
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborted PP job 0x%08x\n", job));
                        mali_pp_job_delete(job);
+
+                       mali_pm_core_event(MALI_CORE_EVENT_PP_STOP);
+               }
+               else
+               {
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in session\n", job));
                }
        }
 
+       _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_working, struct mali_group, pp_scheduler_list)
+       {
+               groups[i++] = group;
+       }
+
        mali_pp_scheduler_unlock();
 
        /* Abort running jobs from this session */
-       for (i = 0; i < num_slots; i++)
+       while (i > 0)
        {
-               struct mali_group *group = slots[i].group;
-
-               MALI_DEBUG_PRINT(5, ("PP sched abort: Attempting abort for session 0x%08x on group 0x%08x\n", session, group));
+               mali_group_abort_session(groups[--i], session);
+       }
 
-               mali_group_abort_session(group, session);
+       if (NULL != virtual_group)
+       {
+               mali_group_abort_session(virtual_group, session);
        }
 }
 
@@ -562,7 +1126,7 @@ 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;
+       ret = pause_count > 0 && _mali_osk_list_empty(&group_list_working) && !virtual_group_working;
        mali_pp_scheduler_unlock();
 
        return ret;
@@ -577,18 +1141,74 @@ int mali_pp_scheduler_get_queue_depth(void)
 u32 mali_pp_scheduler_dump_state(char *buf, u32 size)
 {
        int n = 0;
-       int i;
+       struct mali_group *group;
+       struct mali_group *temp;
 
        n += _mali_osk_snprintf(buf + n, size - n, "PP:\n");
        n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty");
        n += _mali_osk_snprintf(buf + n, size - n, "\n");
 
-       for (i = 0; i < num_slots; i++)
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list)
+       {
+               n += mali_group_dump_state(group, buf + n, size - n);
+       }
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list)
+       {
+               n += mali_group_dump_state(group, buf + n, size - n);
+       }
+
+       if (NULL != virtual_group)
        {
-               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);
+               n += mali_group_dump_state(virtual_group, buf + n, size -n);
        }
 
+       n += _mali_osk_snprintf(buf + n, size - n, "\n");
        return n;
 }
 #endif
+
+/* This function is intended for power on reset of all cores.
+ * No locking is done for the list iteration, which can only be safe if the
+ * scheduler is paused and all cores idle. That is always the case on init and
+ * power on. */
+void mali_pp_scheduler_reset_all_groups(void)
+{
+       struct mali_group *group, *temp;
+
+       if (NULL != virtual_group)
+       {
+               mali_group_reset(virtual_group);
+       }
+
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list)
+       {
+               mali_group_reset(group);
+       }
+}
+
+void mali_pp_scheduler_zap_all_active(struct mali_session_data *session)
+{
+       struct mali_group *group, *temp;
+       struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS];
+       s32 i = 0;
+
+       if (NULL != virtual_group)
+       {
+               mali_group_zap_session(virtual_group, session);
+       }
+
+       mali_pp_scheduler_lock();
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list)
+       {
+               groups[i++] = group;
+       }
+       mali_pp_scheduler_unlock();
+
+       while (i > 0)
+       {
+               mali_group_zap_session(groups[--i], session);
+       }
+}
index 59bf403d8ed1805453f417a0753523c033c4339f..afa540aca9f1b7e6b752eb72208212f3b9e153fe 100644 (file)
@@ -1,24 +1,24 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_PP_SCHEDULER_H__
 #define __MALI_PP_SCHEDULER_H__
 
 #include "mali_osk.h"
-#include "mali_cluster.h"
 #include "mali_pp_job.h"
+#include "mali_group.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_do_schedule(void *arg);
 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);
@@ -33,6 +33,25 @@ void mali_pp_scheduler_resume(void);
  */
 void mali_pp_scheduler_abort_session(struct mali_session_data *session);
 
+/**
+ * @brief Reset all groups
+ *
+ * This function resets all groups known by the PP scheuduler. This must be
+ * called after the Mali HW has been powered on in order to reset the HW.
+ *
+ * This function is intended for power on reset of all cores.
+ * No locking is done, which can only be safe if the scheduler is paused and
+ * all cores idle. That is always the case on init and power on.
+ */
+void mali_pp_scheduler_reset_all_groups(void);
+
+/**
+ * @brief Zap TLB on all groups with \a session active
+ *
+ * The scheculer will zap the session on all groups it owns.
+ */
+void mali_pp_scheduler_zap_all_active(struct mali_session_data *session);
+
 int mali_pp_scheduler_get_queue_depth(void);
 u32 mali_pp_scheduler_dump_state(char *buf, u32 size);
 
index f36020937e9ec9e5df8641a3cb47013a2ab6ba6f..ea6ad29cfc39773bddf7e090bfed42fba0a36902 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
index 74f0947b5516e736d2fffb82d75f24f7a77ae67c..3b5a173bc1fbbd340f050988f2ad709172e5aa81 100644 (file)
@@ -1,21 +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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_SCHEDULER_H__
 #define __MALI_SCHEDULER_H__
 
 #include "mali_osk.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
 
 _mali_osk_errcode_t mali_scheduler_initialize(void);
 void mali_scheduler_terminate(void);
 
 u32 mali_scheduler_get_new_id(void);
 
+/**
+ * @brief Reset all groups
+ *
+ * This function resets all groups known by the both the PP and GP scheuduler.
+ * This must be called after the Mali HW has been powered on in order to reset
+ * the HW.
+ */
+MALI_STATIC_INLINE void mali_scheduler_reset_all_groups(void)
+{
+       mali_gp_scheduler_reset_all_groups();
+       mali_pp_scheduler_reset_all_groups();
+}
+
+/**
+ * @brief Zap TLB on all active groups running \a session
+ *
+ * @param session Pointer to the session to zap
+ */
+MALI_STATIC_INLINE void mali_scheduler_zap_all_active(struct mali_session_data *session)
+{
+       mali_gp_scheduler_zap_all_active(session);
+       mali_pp_scheduler_zap_all_active(session);
+}
+
 #endif /* __MALI_SCHEDULER_H__ */
index 2394bb90889e71d6af486690022c94e35b1fb9a9..04d1ae855f57cbeaaa2b9908a1d764de3802ed2d 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_osk.h"
index c8640b5f9dea5575f1f36daf63b7a5f56ac65c3a..2df5e722e1df1f1198fc68e2a460cc4ce0727bf1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_SESSION_H__
@@ -20,6 +20,11 @@ struct mali_session_data
 {
        _mali_osk_notification_queue_t * ioctl_queue;
 
+#ifdef CONFIG_SYNC
+       _mali_osk_list_t pending_jobs;
+       _mali_osk_lock_t *pending_jobs_lock;
+#endif
+
        _mali_osk_lock_t *memory_lock; /**< Lock protecting the vm manipulation */
        mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
        _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */
@@ -27,6 +32,8 @@ struct mali_session_data
        struct mali_page_directory *page_directory; /**< MMU page directory for this session */
 
        _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */
+
+       _MALI_OSK_LIST_HEAD(job_list); /**< List of all jobs on this session */
 };
 
 _mali_osk_errcode_t mali_session_initialize(void);
index 6d41b6e0971eda5be9ab8cd4b245d3f1b29331f7..4c74f6512d172f21fff8e2385d451ff3dc5c3922 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -369,7 +369,7 @@ _mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *arg
  */
 _mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args );
 
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 /** @brief Map UMP memory into Mali
  * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h
  * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
@@ -380,7 +380,7 @@ _mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args );
  * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
  */
 _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args );
-#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
+#endif /* CONFIG_MALI400_UMP */
 
 /** @brief Determine virtual-to-physical mapping of a contiguous memory range
  * (optional)
@@ -453,7 +453,7 @@ _mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args );
  * @param uargs see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data!
  * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
  */
-_mali_osk_errcode_t _mali_ukk_pp_start_job( void *ctx, _mali_uk_pp_start_job_s *uargs );
+_mali_osk_errcode_t _mali_ukk_pp_start_job( void *ctx, _mali_uk_pp_start_job_s *uargs, int *fence );
 
 /** @brief Returns the number of Fragment Processors in the system
  *
@@ -538,7 +538,7 @@ _mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_
 
 /** @} */ /* end group _mali_uk_gp */
 
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
 /** @addtogroup _mali_uk_profiling U/K Timeline profiling module
  * @{ */
 
@@ -607,6 +607,12 @@ _mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *
 
 u32 _mali_ukk_report_memory_usage(void);
 
+u32 _mali_ukk_utilization_gp_pp(void);
+
+u32 _mali_ukk_utilization_gp(void);
+
+u32 _mali_ukk_utilization_pp(void);
+
 #ifdef __cplusplus
 }
 #endif
index d3f1e5007e9596f651ca69958138e448eefb0d63..9eb8e4e0bdbe27508e616177e1b1a65a59ea227e 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_osk.h"
index fbb9415729c64c1d81701b39503332512b74eea4..2a40ce334a9c3bfb174eb9b79076ef5e18895f8a 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_USER_SETTINGS_DB_H__
index 7c78947e70d3ae9de2e752b9509e0059ef4eefcd..d2f87ab6ac18e70545e702382597b91c5880c5da 100644 (file)
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_utgard.h
+ * Defines types and interface exposed by the Mali Utgard device driver
  */
 
 #ifndef __MALI_UTGARD_H__
-#define        __MALI_UTGARD_H__ 
+#define __MALI_UTGARD_H__
+
+#define MALI_GPU_NAME_UTGARD "mali-utgard"
+
+/* Mali-200 */
+
+#define MALI_GPU_RESOURCES_MALI200(base_addr, gp_irq, pp_irq, mmu_irq) \
+       MALI_GPU_RESOURCE_PP(base_addr + 0x0000, pp_irq) \
+       MALI_GPU_RESOURCE_GP(base_addr + 0x2000, gp_irq) \
+       MALI_GPU_RESOURCE_MMU(base_addr + 0x3000, mmu_irq)
+
+/* Mali-300 */
+
+#define MALI_GPU_RESOURCES_MALI300(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI300_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq)
+
+/* Mali-400 */
+
+#define MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+#define MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+#define MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+#define MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0xE000, pp3_irq, base_addr + 0x7000, pp3_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+/* Mali-450 */
+#define MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+
+#define MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+
+#define MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x28000, pp3_irq, base_addr + 0x1C000, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x2A000, pp4_irq, base_addr + 0x1D000, pp4_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2C000, pp5_irq, base_addr + 0x1E000, pp5_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP6_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+
+#define MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x28000, pp4_irq, base_addr + 0x1C000, pp4_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2A000, pp5_irq, base_addr + 0x1D000, pp5_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(6, base_addr + 0x2C000, pp6_irq, base_addr + 0x1E000, pp6_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(7, base_addr + 0x2E000, pp7_irq, base_addr + 0x1F000, pp7_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP8_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+
+#define MALI_GPU_RESOURCE_L2(addr) \
+       { \
+               .name = "Mali_L2", \
+               .flags = IORESOURCE_MEM, \
+               .start = addr, \
+               .end   = addr + 0x200, \
+       },
+
+#define MALI_GPU_RESOURCE_GP(gp_addr, gp_irq) \
+       { \
+               .name = "Mali_GP", \
+               .flags = IORESOURCE_MEM, \
+               .start = gp_addr, \
+               .end =   gp_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_GP_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = gp_irq, \
+               .end   = gp_irq, \
+       }, \
+
+#define MALI_GPU_RESOURCE_GP_WITH_MMU(gp_addr, gp_irq, gp_mmu_addr, gp_mmu_irq) \
+       { \
+               .name = "Mali_GP", \
+               .flags = IORESOURCE_MEM, \
+               .start = gp_addr, \
+               .end =   gp_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_GP_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = gp_irq, \
+               .end   = gp_irq, \
+       }, \
+       { \
+               .name = "Mali_GP_MMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = gp_mmu_addr, \
+               .end =   gp_mmu_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_GP_MMU_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = gp_mmu_irq, \
+               .end =   gp_mmu_irq, \
+       },
+
+#define MALI_GPU_RESOURCE_PP(pp_addr, pp_irq) \
+       { \
+               .name = "Mali_PP", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_addr, \
+               .end =   pp_addr + 0x1100, \
+       }, \
+       { \
+               .name = "Mali_PP_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_irq, \
+               .end =   pp_irq, \
+       }, \
+
+#define MALI_GPU_RESOURCE_PP_WITH_MMU(id, pp_addr, pp_irq, pp_mmu_addr, pp_mmu_irq) \
+       { \
+               .name = "Mali_PP" #id, \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_addr, \
+               .end =   pp_addr + 0x1100, \
+       }, \
+       { \
+               .name = "Mali_PP" #id "_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_irq, \
+               .end =   pp_irq, \
+       }, \
+       { \
+               .name = "Mali_PP" #id "_MMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_mmu_addr, \
+               .end =   pp_mmu_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_PP" #id "_MMU_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_mmu_irq, \
+               .end =   pp_mmu_irq, \
+       },
+
+#define MALI_GPU_RESOURCE_MMU(mmu_addr, mmu_irq) \
+       { \
+               .name = "Mali_MMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = mmu_addr, \
+               .end =   mmu_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_MMU_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = mmu_irq, \
+               .end =   mmu_irq, \
+       },
+
+#define MALI_GPU_RESOURCE_PMU(pmu_addr) \
+       { \
+               .name = "Mali_PMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = pmu_addr, \
+               .end =   pmu_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_DLBU(dlbu_addr) \
+       { \
+               .name = "Mali_DLBU", \
+               .flags = IORESOURCE_MEM, \
+               .start = dlbu_addr, \
+               .end = dlbu_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_BCAST(bcast_addr) \
+       { \
+               .name = "Mali_Broadcast", \
+               .flags = IORESOURCE_MEM, \
+               .start = bcast_addr, \
+               .end = bcast_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_PP_BCAST(pp_addr, pp_irq) \
+       { \
+               .name = "Mali_PP_Broadcast", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_addr, \
+               .end =   pp_addr + 0x1100, \
+       }, \
+       { \
+               .name = "Mali_PP_Broadcast_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_irq, \
+               .end =   pp_irq, \
+       }, \
+
+#define MALI_GPU_RESOURCE_PP_MMU_BCAST(pp_mmu_bcast_addr) \
+       { \
+               .name = "Mali_PP_MMU_Broadcast", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_mmu_bcast_addr, \
+               .end = pp_mmu_bcast_addr + 0x100, \
+       },
+
+struct mali_gpu_device_data
+{
+       /* Dedicated GPU memory range (physical). */
+       unsigned long dedicated_mem_start;
+       unsigned long dedicated_mem_size;
+
+       /* Shared GPU memory */
+       unsigned long shared_mem_size;
+
+       /* Frame buffer memory to be accessible by Mali GPU (physical) */
+       unsigned long fb_start;
+       unsigned long fb_size;
+
+       /* Report GPU utilization in this interval (specified in ms) */
+       unsigned long utilization_interval;
+
+       /* Function that will receive periodic GPU utilization numbers */
+       void (*utilization_handler)(unsigned int);
+};
 
 /** @brief MALI GPU power down using MALI in-built PMU
  * 
@@ -24,5 +333,5 @@ int mali_pmu_powerdown(void);
  */
 int mali_pmu_powerup(void);
 
-#endif /* __MALI_UTGARD_H__ */
 
+#endif
index 40822f739722aca19fbef2bcd70a79dc5da258d3..6b8e0a8e637b34413812a36a796bfaa2943a9293 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef _MALI_UTGARD_COUNTERS_H_
@@ -212,7 +212,7 @@ typedef enum
        MALI_CINSTR_PP_RSW_READS                                             = MALI_CINSTR_COUNTER_SOURCE_PP + 15,
        MALI_CINSTR_PP_VERTEX_CACHE_READS                                    = MALI_CINSTR_COUNTER_SOURCE_PP + 16,
        MALI_CINSTR_PP_UNIFORM_REMAPPING_READS                               = MALI_CINSTR_COUNTER_SOURCE_PP + 17,
-       MALI_CINSTR_PP_PROGRAM_CACHE_READS                                   = MALI_CINSTR_COUNTER_SOURCE_PP + 19,
+       MALI_CINSTR_PP_PROGRAM_CACHE_READS                                   = MALI_CINSTR_COUNTER_SOURCE_PP + 18,
        MALI_CINSTR_PP_VARYING_READS                                         = MALI_CINSTR_COUNTER_SOURCE_PP + 19,
        MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS                             = MALI_CINSTR_COUNTER_SOURCE_PP + 20,
        MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS                   = MALI_CINSTR_COUNTER_SOURCE_PP + 21,
index 7935448e63d4e97f9ea35902a3afa4704f9f0eb6..f9eed54d28096cde646072a7404bc4360f601039 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_UTGARD_IOCTL_H__
@@ -44,6 +44,8 @@ extern "C"
 #define MALI_IOC_POST_NOTIFICATION          _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *)
 #define MALI_IOC_GET_USER_SETTING           _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *)
 #define MALI_IOC_GET_USER_SETTINGS          _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *)
+#define MALI_IOC_STREAM_CREATE              _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_STREAM_CREATE, _mali_uk_stream_create_s *)
+#define MALI_IOC_FENCE_VALIDATE             _IOR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_VALIDATE, _mali_uk_fence_validate_s *)
 
 #define MALI_IOC_MEM_GET_BIG_BLOCK          _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *)
 #define MALI_IOC_MEM_FREE_BIG_BLOCK         _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *)
index 92ca058d05dbb7fec8ce992d78e3da9929067942..5e0e545912c6168342be574259d42f816c67b04a 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef _MALI_UTGARD_PROFILING_EVENTS_H_
@@ -76,12 +76,25 @@ typedef enum
 
 /**
  * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel
+ * to inform whether the core is physical or virtual
  */
 typedef enum
 {
-       MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE      = 0,
-       MALI_PROFILING_EVENT_REASON_START_STOP_MALI         = 1,
-       MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF  = 2,
+       MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL  = 0,
+       MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL   = 1,
+} cinstr_profiling_event_reason_start_stop_hw_t;
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel
+ */
+typedef enum
+{
+       /*MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE            = 0,*/
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_MALI            = 1,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_CALLBACK_THREAD = 2,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_WORKER_THREAD   = 3,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF     = 4,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF      = 5,
 } cinstr_profiling_event_reason_start_stop_sw_t;
 
 /**
@@ -89,7 +102,7 @@ typedef enum
  */
 typedef enum
 {
-       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE                   =  0, /* NOT used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE                   =  0, /* used */
        MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL          =  1, /* NOT used */
        MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC                  = 26, /* used in some build configurations */
        MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT         = 27, /* USED */
index b35a7150ac25c8d6d1afb64f14ed9b9c5918a2e9..430a0d8d85fa757662a862903622d141bc4e8279 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -68,6 +68,8 @@ typedef enum
     _MALI_UK_POST_NOTIFICATION,           /**< _mali_ukk_post_notification() */
        _MALI_UK_GET_USER_SETTING,       /**< _mali_ukk_get_user_setting() *//**< [out] */
        _MALI_UK_GET_USER_SETTINGS,       /**< _mali_ukk_get_user_settings() *//**< [out] */
+       _MALI_UK_STREAM_CREATE,           /**< _mali_ukk_stream_create() */
+       _MALI_UK_FENCE_VALIDATE,          /**< _mali_ukk_fence_validate() */
 
        /** Memory functions */
 
@@ -417,9 +419,12 @@ typedef struct
 
 #define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1)
 
+#define _MALI_DLBU_MAX_REGISTERS 4
+
 /** Flag for _mali_uk_pp_start_job_s */
 #define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0)
 #define _MALI_PP_JOB_FLAG_BARRIER         (1<<1)
+#define _MALI_PP_JOB_FLAG_FENCE           (1<<2)
 
 /** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job
  * @{ */
@@ -476,6 +481,7 @@ typedef struct
     u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS];
     u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS];
     u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS];
+       u32 dlbu_registers[_MALI_DLBU_MAX_REGISTERS]; /**< [in] Dynamic load balancing unit registers */
        u32 num_cores;                      /**< [in] Number of cores to set up (valid range: 1-4) */
     u32 perf_counter_flag;              /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */
     u32 perf_counter_src0;              /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
@@ -483,6 +489,8 @@ typedef struct
        u32 frame_builder_id;               /**< [in] id of the originating frame builder */
        u32 flush_id;                       /**< [in] flush id within the originating frame builder */
        u32 flags;                          /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */
+       s32 fence;                          /**< [in,out] Fence to wait on / fence that will be signalled on job completion, if _MALI_PP_JOB_FLAG_FENCE is set */
+       s32 stream;                         /**< [in] Steam identifier */
 } _mali_uk_pp_start_job_s;
 /** @} */ /* end group _mali_uk_ppstartjob_s */
 
@@ -700,7 +708,7 @@ typedef struct
  * The 16bit integer is stored twice in a 32bit integer
  * For example, for version 1 the value would be 0x00010001
  */
-#define _MALI_API_VERSION 17
+#define _MALI_API_VERSION 18
 #define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION)
 
 /**
@@ -1084,6 +1092,35 @@ typedef struct
 
 /** @} */ /* end group _mali_uk_sw_counters_report */
 
+/** @defgroup _mali_uk_stream U/K Mali stream module
+ * @{ */
+
+/** @brief Create stream
+ */
+typedef struct
+{
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       int fd;                         /**< [out] file descriptor describing stream */
+} _mali_uk_stream_create_s;
+
+/** @brief Destroy stream
+*/
+typedef struct
+{
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       int fd;                         /**< [in] file descriptor describing stream */
+} _mali_uk_stream_destroy_s;
+
+/** @brief Check fence validity
+ */
+typedef struct
+{
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       int fd;                         /**< [in] file descriptor describing fence */
+} _mali_uk_fence_validate_s;
+
+/** @} */ /* end group _mali_uk_stream */
+
 /** @} */ /* end group u_k_api */
 
 /** @} */ /* end group uddapi */
index 4dd711f1d7bfb51a3321ccee27eab8883aa01967..f9ca0e782fd97147703efe187f26bd5546d63f3c 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include <linux/fs.h>     /* file system operations */
@@ -13,6 +13,7 @@
 #include <linux/dma-buf.h>
 #include <linux/scatterlist.h>
 #include <linux/rbtree.h>
+#include <linux/platform_device.h>
 
 #include "mali_ukk.h"
 #include "mali_osk.h"
@@ -23,8 +24,6 @@
 #include "mali_kernel_memory_engine.h"
 #include "mali_memory.h"
 
-#include "mali_kernel_sysfs.h"
-
 
 struct mali_dma_buf_attachment {
        struct dma_buf *buf;
@@ -100,8 +99,6 @@ static void mali_dma_buf_release(void *ctx, void *handle)
        spin_lock(&mali_dma_bufs_lock);
        ref = _mali_osk_atomic_dec_return(&mem->ref);
 
-       MALI_DEBUG_ASSERT(ref >= 0);
-
        if (0 == ref)
        {
                rb_erase(&mem->rb_node, &mali_dma_bufs);
@@ -234,13 +231,13 @@ int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_b
                if (NULL == mem)
                {
                        MALI_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n"));
-                       dma_buf_put(mem->buf);
+                       dma_buf_put(buf);
                        return -ENOMEM;
                }
                _mali_osk_atomic_init(&mem->ref, 1);
                mem->buf = buf;
 
-               mem->attachment = dma_buf_attach(mem->buf, mali_device);
+               mem->attachment = dma_buf_attach(mem->buf, &mali_platform_device->dev);
                if (NULL == mem->attachment)
                {
                        MALI_DEBUG_PRINT(2, ("Failed to attach to dma-buf %d\n", fd));
index ee9a0edd6d8ae435a29c394f0e12a23f3cc49a90..0970b19c48489443fbef3a8460ec3d69a37bf239 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_DMA_BUF_H__
index 8367515638e002568a30fc1ea44486be0efd56d5..6aa441d6de6aeb20c6d3ed81315693931ca70e38 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
 #include <linux/cdev.h>     /* character device definitions */
 #include <linux/mm.h>       /* memory manager definitions */
 #include <linux/mali/mali_utgard_ioctl.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include "mali_kernel_license.h"
+#include <linux/platform_device.h>
+#if MALI_LICENSE_IS_GPL
+#include <linux/miscdevice.h>
+#endif
+#include <linux/mali/mali_utgard.h>
 #include "mali_kernel_common.h"
 #include "mali_session.h"
 #include "mali_kernel_core.h"
 #include "mali_kernel_linux.h"
 #include "mali_ukk.h"
 #include "mali_ukk_wrappers.h"
-#include "mali_kernel_pm.h"
 #include "mali_kernel_sysfs.h"
-#include "mali_platform.h"
+#include "mali_pm.h"
 #include "mali_kernel_license.h"
 #include "mali_dma_buf.h"
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
 #include "mali_profiling_internal.h"
 #endif
 
 /* Streamline support for the Mali driver */
-#if defined(CONFIG_TRACEPOINTS) && MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_MALI400_PROFILING)
 /* Ask Linux to create the tracepoints */
 #define CREATE_TRACE_POINTS
 #include "mali_linux_trace.h"
 #endif /* CONFIG_TRACEPOINTS */
 
-static _mali_osk_errcode_t initialize_kernel_device(void);
-static int initialize_sysfs(void);
-static void terminate_kernel_device(void);
-
-
 /* from the __malidrv_build_info.c file that is generated during build */
 extern const char *__malidrv_build_info(void);
 
@@ -53,11 +55,6 @@ int mali_debug_level = 2;
 module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
 MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output");
 
-/* By default the module uses any available major, but it's possible to set it at load time to a specific number */
-int mali_major = 0;
-module_param(mali_major, int, S_IRUGO); /* r--r--r-- */
-MODULE_PARM_DESC(mali_major, "Device major number");
-
 module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
 MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what");
 
@@ -65,7 +62,19 @@ extern int mali_l2_max_reads;
 module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH);
 MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache");
 
-#if MALI_TIMELINE_PROFILING_ENABLED
+extern int mali_dedicated_mem_start;
+module_param(mali_dedicated_mem_start, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory.");
+
+extern int mali_dedicated_mem_size;
+module_param(mali_dedicated_mem_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory.");
+
+extern int mali_shared_mem_size;
+module_param(mali_shared_mem_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory.");
+
+#if defined(CONFIG_MALI400_PROFILING)
 extern int mali_boot_profiling;
 module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH);
 MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization");
@@ -78,9 +87,14 @@ EXPORT_SYMBOL(mali_get_user_setting);
 
 static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
 
-/* the mali device */
-static struct mali_dev device;
+/* This driver only supports one Mali device, and this variable stores this single platform device */
+struct platform_device *mali_platform_device = NULL;
 
+/* This driver only supports one Mali device, and this variable stores the exposed misc device (/dev/mali) */
+static struct miscdevice mali_miscdevice = { 0, };
+
+static int mali_miscdevice_register(struct platform_device *pdev);
+static void mali_miscdevice_unregister(void);
 
 static int mali_open(struct inode *inode, struct file *filp);
 static int mali_release(struct inode *inode, struct file *filp);
@@ -89,10 +103,72 @@ static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 #else
 static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
 #endif
-
 static int mali_mmap(struct file * filp, struct vm_area_struct * vma);
 
-/* Linux char file operations provided by the Mali module */
+static int mali_probe(struct platform_device *pdev);
+static int mali_remove(struct platform_device *pdev);
+
+static int mali_driver_suspend_scheduler(struct device *dev);
+static int mali_driver_resume_scheduler(struct device *dev);
+
+#ifdef CONFIG_PM_RUNTIME
+static int mali_driver_runtime_suspend(struct device *dev);
+static int mali_driver_runtime_resume(struct device *dev);
+static int mali_driver_runtime_idle(struct device *dev);
+#endif
+
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+extern int mali_platform_device_register(void);
+extern int mali_platform_device_unregister(void);
+#endif
+
+/* Linux power management operations provided by the Mali device driver */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+struct pm_ext_ops mali_dev_ext_pm_ops =
+{
+       .base =
+       {
+               .suspend = mali_driver_suspend_scheduler,
+               .resume = mali_driver_resume_scheduler,
+               .freeze = mali_driver_suspend_scheduler,
+               .thaw =   mali_driver_resume_scheduler,
+       },
+};
+#else
+static const struct dev_pm_ops mali_dev_pm_ops =
+{
+#ifdef CONFIG_PM_RUNTIME
+       .runtime_suspend = mali_driver_runtime_suspend,
+       .runtime_resume = mali_driver_runtime_resume,
+       .runtime_idle = mali_driver_runtime_idle,
+#endif
+       .suspend = mali_driver_suspend_scheduler,
+       .resume = mali_driver_resume_scheduler,
+       .freeze = mali_driver_suspend_scheduler,
+       .thaw = mali_driver_resume_scheduler,
+};
+#endif
+
+/* The Mali device driver struct */
+static struct platform_driver mali_platform_driver =
+{
+       .probe  = mali_probe,
+       .remove = mali_remove,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+       .pm = &mali_dev_ext_pm_ops,
+#endif
+       .driver =
+       {
+               .name   = MALI_GPU_NAME_UTGARD,
+               .owner  = THIS_MODULE,
+               .bus = &platform_bus_type,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+               .pm = &mali_dev_pm_ops,
+#endif
+       },
+};
+
+/* Linux misc device operations (/dev/mali) */
 struct file_operations mali_fops =
 {
        .owner = THIS_MODULE,
@@ -107,154 +183,199 @@ struct file_operations mali_fops =
 };
 
 
-int mali_driver_init(void)
+
+
+
+
+int mali_module_init(void)
 {
-       int ret = 0;
+       int err = 0;
 
-       MALI_DEBUG_PRINT(2, ("\n"));
        MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION));
        MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__));
        MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING));
 
-       ret = _mali_dev_platform_register();
-       if (0 != ret) goto platform_register_failed;
-       ret = map_errcode(initialize_kernel_device());
-       if (0 != ret) goto initialize_kernel_device_failed;
+       /* Initialize module wide settings */
+       mali_osk_low_level_mem_init();
+
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+       MALI_DEBUG_PRINT(2, ("mali_module_init() registering device\n"));
+       err = mali_platform_device_register();
+       if (0 != err)
+       {
+               return err;
+       }
+#endif
 
-       ret = map_errcode(mali_platform_init());
-       if (0 != ret) goto platform_init_failed;
+       MALI_DEBUG_PRINT(2, ("mali_module_init() registering driver\n"));
 
-       mali_osk_low_level_mem_init();
+       err = platform_driver_register(&mali_platform_driver);
 
-       ret = map_errcode(mali_initialize_subsystems());
-       if (0 != ret) goto initialize_subsystems_failed;
+       if (0 != err)
+       {
+               MALI_DEBUG_PRINT(2, ("mali_module_init() Failed to register driver (%d)\n", err));
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+               mali_platform_device_unregister();
+#endif
+               mali_platform_device = NULL;
+               return err;
+       }
 
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
-        ret = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
-        if (0 != ret)
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+        err = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
+        if (0 != err)
         {
                 /* No biggie if we wheren't able to initialize the profiling */
                 MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
         }
 #endif
 
-       ret = initialize_sysfs();
-       if (0 != ret) goto initialize_sysfs_failed;
-
        MALI_PRINT(("Mali device driver loaded\n"));
 
        return 0; /* Success */
-
-       /* Error handling */
-initialize_sysfs_failed:
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
-        _mali_internal_profiling_term();
-#endif
-       mali_terminate_subsystems();
-initialize_subsystems_failed:
-       mali_osk_low_level_mem_term();
-       mali_platform_deinit();
-platform_init_failed:
-       terminate_kernel_device();
-initialize_kernel_device_failed:
-       _mali_dev_platform_unregister();
-platform_register_failed:
-       return ret;
 }
 
-void mali_driver_exit(void)
+void mali_module_exit(void)
 {
-       MALI_DEBUG_PRINT(2, ("\n"));
        MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION));
 
-       /* No need to terminate sysfs, this will be done automatically along with device termination */
+       MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering driver\n"));
 
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
         _mali_internal_profiling_term();
 #endif
 
-       mali_terminate_subsystems();
+       platform_driver_unregister(&mali_platform_driver);
 
-       mali_osk_low_level_mem_term();
-
-       mali_platform_deinit();
-
-       terminate_kernel_device();
-       _mali_dev_platform_unregister();
-
-#if MALI_LICENSE_IS_GPL
-       /* @@@@ clean up the work queues! This should not be terminated here, since it isn't inited in the function above! */
-       flush_workqueue(mali_wq);
-       destroy_workqueue(mali_wq);
-       mali_wq = NULL;
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+       MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering device\n"));
+       mali_platform_device_unregister();
 #endif
 
+       mali_osk_low_level_mem_term();
+
        MALI_PRINT(("Mali device driver unloaded\n"));
 }
 
-static int initialize_kernel_device(void)
+static int mali_probe(struct platform_device *pdev)
 {
        int err;
-       dev_t dev = 0;
-       if (0 == mali_major)
-       {
-               /* auto select a major */
-               err = alloc_chrdev_region(&dev, 0/*first minor*/, 1/*count*/, mali_dev_name);
-               mali_major = MAJOR(dev);
-       }
-       else
+
+       MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name));
+
+       if (NULL != mali_platform_device)
        {
-               /* use load time defined major number */
-               dev = MKDEV(mali_major, 0);
-               err = register_chrdev_region(dev, 1/*count*/, mali_dev_name);
+               /* Already connected to a device, return error */
+               MALI_PRINT_ERROR(("mali_probe(): The Mali driver is already connected with a Mali device."));
+               return -EEXIST;
        }
 
-       if (err)
+       mali_platform_device = pdev;
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_wq_init())
        {
-                       goto init_chrdev_err;
+               /* Initialize the Mali GPU HW specified by pdev */
+               if (_MALI_OSK_ERR_OK == mali_initialize_subsystems())
+               {
+                       /* Register a misc device (so we are accessible from user space) */
+                       err = mali_miscdevice_register(pdev);
+                       if (0 == err)
+                       {
+                               /* Setup sysfs entries */
+                               err = mali_sysfs_register(mali_dev_name);
+                               if (0 == err)
+                               {
+                                       MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name));
+                                       return 0;
+                               }
+                               else
+                               {
+                                       MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries"));
+                               }
+                               mali_miscdevice_unregister();
+                       }
+                       else
+                       {
+                               MALI_PRINT_ERROR(("mali_probe(): failed to register Mali misc device."));
+                       }
+                       mali_terminate_subsystems();
+               }
+               else
+               {
+                       MALI_PRINT_ERROR(("mali_probe(): Failed to initialize Mali device driver."));
+               }
+               _mali_osk_wq_term();
        }
 
-       memset(&device, 0, sizeof(device));
+       mali_platform_device = NULL;
+       return -EFAULT;
+}
+
+static int mali_remove(struct platform_device *pdev)
+{
+       MALI_DEBUG_PRINT(2, ("mali_remove() called for platform device %s\n", pdev->name));
+       mali_sysfs_unregister();
+       mali_miscdevice_unregister();
+       mali_terminate_subsystems();
+       _mali_osk_wq_term();
+       mali_platform_device = NULL;
+       return 0;
+}
 
-       /* initialize our char dev data */
-       cdev_init(&device.cdev, &mali_fops);
-       device.cdev.owner = THIS_MODULE;
-       device.cdev.ops = &mali_fops;
+static int mali_miscdevice_register(struct platform_device *pdev)
+{
+       int err;
 
-       /* register char dev with the kernel */
-       err = cdev_add(&device.cdev, dev, 1/*count*/);
-       if (err)
+       mali_miscdevice.minor = MISC_DYNAMIC_MINOR;
+       mali_miscdevice.name = mali_dev_name;
+       mali_miscdevice.fops = &mali_fops;
+       mali_miscdevice.parent = get_device(&pdev->dev);
+
+       err = misc_register(&mali_miscdevice);
+       if (0 != err)
        {
-                       goto init_cdev_err;
+               MALI_PRINT_ERROR(("Failed to register misc device, misc_register() returned %d\n", err));
        }
 
-       /* Success! */
-       return 0;
-
-init_cdev_err:
-       unregister_chrdev_region(dev, 1/*count*/);
-init_chrdev_err:
        return err;
 }
 
-static int initialize_sysfs(void)
+static void mali_miscdevice_unregister(void)
+{
+       misc_deregister(&mali_miscdevice);
+}
+
+static int mali_driver_suspend_scheduler(struct device *dev)
 {
-       dev_t dev = MKDEV(mali_major, 0);
-       return mali_sysfs_register(&device, dev, mali_dev_name);
+       mali_pm_os_suspend();
+       return 0;
 }
 
-static void terminate_kernel_device(void)
+static int mali_driver_resume_scheduler(struct device *dev)
 {
-       dev_t dev = MKDEV(mali_major, 0);
+       mali_pm_os_resume();
+       return 0;
+}
 
-       mali_sysfs_unregister(&device, dev, mali_dev_name);
+#ifdef CONFIG_PM_RUNTIME
+static int mali_driver_runtime_suspend(struct device *dev)
+{
+       mali_pm_runtime_suspend();
+       return 0;
+}
 
-       /* unregister char device */
-       cdev_del(&device.cdev);
-       /* free major */
-       unregister_chrdev_region(dev, 1/*count*/);
-       return;
+static int mali_driver_runtime_resume(struct device *dev)
+{
+       mali_pm_runtime_resume();
+       return 0;
+}
+
+static int mali_driver_runtime_idle(struct device *dev)
+{
+       /* Nothing to do */
+       return 0;
 }
+#endif
 
 /** @note munmap handler is done by vma close handler */
 static int mali_mmap(struct file * filp, struct vm_area_struct * vma)
@@ -302,7 +423,11 @@ static int mali_open(struct inode *inode, struct file *filp)
     _mali_osk_errcode_t err;
 
        /* input validation */
-       if (0 != MINOR(inode->i_rdev)) return -ENODEV;
+       if (mali_miscdevice.minor != iminor(inode))
+       {
+               MALI_PRINT_ERROR(("mali_open() Minor does not match\n"));
+               return -ENODEV;
+       }
 
        /* allocated struct to track this session */
     err = _mali_ukk_open((void **)&session_data);
@@ -321,8 +446,12 @@ static int mali_release(struct inode *inode, struct file *filp)
 {
     _mali_osk_errcode_t err;
 
-    /* input validation */
-       if (0 != MINOR(inode->i_rdev)) return -ENODEV;
+       /* input validation */
+       if (mali_miscdevice.minor != iminor(inode))
+       {
+               MALI_PRINT_ERROR(("mali_release() Minor does not match\n"));
+               return -ENODEV;
+       }
 
     err = _mali_ukk_close((void **)&filp->private_data);
     if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
@@ -393,7 +522,7 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
                        break;
 
-#if MALI_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_PROFILING)
                case MALI_IOC_PROFILING_START:
                        err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg);
                        break;
@@ -462,7 +591,7 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg);
                        break;
 
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 
                case MALI_IOC_MEM_ATTACH_UMP:
                        err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg);
@@ -495,6 +624,8 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        break;
 #else
 
+               case MALI_IOC_MEM_ATTACH_DMA_BUF:   /* FALL-THROUGH */
+               case MALI_IOC_MEM_RELEASE_DMA_BUF:  /* FALL-THROUGH */
                case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */
                        MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n"));
                        err = -ENOTTY;
@@ -537,6 +668,21 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
                        break;
 
+               case MALI_IOC_STREAM_CREATE:
+#if defined(CONFIG_SYNC)
+                       err = stream_create_wrapper(session_data, (_mali_uk_stream_create_s __user *)arg);
+                       break;
+#endif
+               case MALI_IOC_FENCE_VALIDATE:
+#if defined(CONFIG_SYNC)
+                       err = sync_fence_validate_wrapper(session_data, (_mali_uk_fence_validate_s __user *)arg);
+                       break;
+#else
+                       MALI_DEBUG_PRINT(2, ("Sync objects not supported\n"));
+                       err = -ENOTTY;
+                       break;
+#endif
+
                case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */
                case MALI_IOC_MEM_FREE_BIG_BLOCK:
                        MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n"));
@@ -552,8 +698,8 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 }
 
 
-module_init(mali_driver_init);
-module_exit(mali_driver_exit);
+module_init(mali_module_init);
+module_exit(mali_module_exit);
 
 MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
 MODULE_AUTHOR("ARM Ltd.");
index 22dc9a431b15c68445318ed98f154c882d4768a9..468d408f858ef55283128a3fba57fd776070f197 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_LINUX_H__
@@ -20,13 +20,7 @@ extern "C"
 #include "mali_kernel_license.h"
 #include "mali_osk.h"
 
-struct mali_dev
-{
-       struct cdev cdev;
-#if MALI_LICENSE_IS_GPL
-       struct class *  mali_class;
-#endif
-};
+extern struct platform_device *mali_platform_device;
 
 #if MALI_LICENSE_IS_GPL
 /* Defined in mali_osk_irq.h */
index 77ebc9d1f40e7fe6c00e3bae14a01ae985545d3a..110664a6214cd64189df401ab88d4881b857f4d5 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include "mali_kernel_license.h"
 #include "mali_kernel_common.h"
-#include "mali_kernel_linux.h"
 #include "mali_ukk.h"
 
 #if MALI_LICENSE_IS_GPL
 #include <asm/uaccess.h>
 #include <linux/module.h>
 #include "mali_kernel_sysfs.h"
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
 #include <linux/slab.h>
 #include "mali_osk_profiling.h"
 #endif
 #include "mali_pm.h"
-#include "mali_cluster.h"
 #include "mali_group.h"
 #include "mali_gp.h"
 #include "mali_pp.h"
 #include "mali_user_settings_db.h"
 #include "mali_device_pause_resume.h"
 #include "mali_profiling_internal.h"
+#include "mali_gp_job.h"
+#include "mali_pp_job.h"
 
 #define POWER_BUFFER_SIZE 3
 
-struct device *mali_device;
 static struct dentry *mali_debugfs_dir = NULL;
 
 typedef enum
@@ -67,9 +66,10 @@ static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
         [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
 };
 
-static u32 virtual_power_status_register=0;
+static u32 virtual_power_status_register = 0;
 static char pwr_buf[POWER_BUFFER_SIZE];
 
+static mali_bool power_always_on_enabled = MALI_FALSE;
 
 static int open_copy_private_data(struct inode *inode, struct file *filp)
 {
@@ -82,15 +82,14 @@ static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, si
        char buf[64];
        int r;
        u32 val;
-       struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
 
        if (0 == src_id)
        {
-               val = mali_gp_core_get_counter_src0(gp_core);
+               val = mali_gp_job_get_gp_counter_src0();
        }
        else
        {
-               val = mali_gp_core_get_counter_src1(gp_core);
+               val = mali_gp_job_get_gp_counter_src1();
        }
 
        if (MALI_HW_CORE_NO_COUNTER == val)
@@ -106,7 +105,6 @@ static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, si
 
 static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
 {
-       struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
        char buf[64];
        long val;
        int ret;
@@ -137,14 +135,14 @@ static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *u
 
        if (0 == src_id)
        {
-               if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
+               if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val))
                {
                        return 0;
                }
        }
        else
        {
-               if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
+               if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val))
                {
                        return 0;
                }
@@ -159,8 +157,8 @@ static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *u
        char buf[64];
        long val;
        int ret;
-       u32 ci;
-       struct mali_cluster *cluster;
+       u32 num_groups;
+       int i;
 
        if (cnt >= sizeof(buf))
        {
@@ -186,41 +184,29 @@ static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *u
                val = MALI_HW_CORE_NO_COUNTER;
        }
 
-       ci = 0;
-       cluster = mali_cluster_get_global_cluster(ci);
-       while (NULL != cluster)
+       num_groups = mali_group_get_glob_num_groups();
+       for (i = 0; i < num_groups; i++)
        {
-               u32 gi = 0;
-               struct mali_group *group = mali_cluster_get_group(cluster, gi);
-               while (NULL != group)
+               struct mali_group *group = mali_group_get_glob_group(i);
+
+               struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+               if (NULL != gp_core)
                {
-                       struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
-                       if (NULL != gp_core)
+                       if (0 == src_id)
                        {
-                               if (0 == src_id)
+                               if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val))
                                {
-                                       if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
-                                       {
-                                               return 0;
-                                       }
+                                       return 0;
                                }
-                               else
+                       }
+                       else
+                       {
+                               if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val))
                                {
-                                       if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
-                                       {
-                                               return 0;
-                                       }
-                               }                               
+                                       return 0;
+                               }
                        }
-
-                       /* try next group */
-                       gi++;
-                       group = mali_cluster_get_group(cluster, gi);
                }
-
-               /* try next cluster */
-               ci++;
-               cluster = mali_cluster_get_global_cluster(ci);
        }
 
        *gpos += cnt;
@@ -286,15 +272,14 @@ static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, si
        char buf[64];
        int r;
        u32 val;
-       struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
 
        if (0 == src_id)
        {
-               val = mali_pp_core_get_counter_src0(pp_core);
+               val = mali_pp_job_get_pp_counter_src0();
        }
        else
        {
-               val = mali_pp_core_get_counter_src1(pp_core);
+               val = mali_pp_job_get_pp_counter_src1();
        }
 
        if (MALI_HW_CORE_NO_COUNTER == val)
@@ -310,7 +295,6 @@ static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, si
 
 static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 {
-       struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
        char buf[64];
        long val;
        int ret;
@@ -341,14 +325,14 @@ static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *u
 
        if (0 == src_id)
        {
-               if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
+               if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val))
                {
                        return 0;
                }
        }
        else
        {
-               if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
+               if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val))
                {
                        return 0;
                }
@@ -363,8 +347,8 @@ static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *u
        char buf[64];
        long val;
        int ret;
-       u32 ci;
-       struct mali_cluster *cluster;
+       u32 num_groups;
+       int i;
 
        if (cnt >= sizeof(buf))
        {
@@ -390,41 +374,29 @@ static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *u
                val = MALI_HW_CORE_NO_COUNTER;
        }
 
-       ci = 0;
-       cluster = mali_cluster_get_global_cluster(ci);
-       while (NULL != cluster)
+       num_groups = mali_group_get_glob_num_groups();
+       for (i = 0; i < num_groups; i++)
        {
-               u32 gi = 0;
-               struct mali_group *group = mali_cluster_get_group(cluster, gi);
-               while (NULL != group)
+               struct mali_group *group = mali_group_get_glob_group(i);
+
+               struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+               if (NULL != pp_core)
                {
-                       struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
-                       if (NULL != pp_core)
+                       if (0 == src_id)
                        {
-                               if (0 == src_id)
+                               if (MALI_TRUE != mali_pp_job_set_pp_counter_src0((u32)val))
                                {
-                                       if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
-                                       {
-                                               return 0;
-                                       }
+                                       return 0;
                                }
-                               else
+                       }
+                       else
+                       {
+                               if (MALI_TRUE != mali_pp_job_set_pp_counter_src1((u32)val))
                                {
-                                       if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
-                                       {
-                                               return 0;
-                                       }
-                               }                               
+                                       return 0;
+                               }
                        }
-
-                       /* try next group */
-                       gi++;
-                       group = mali_cluster_get_group(cluster, gi);
                }
-
-               /* try next cluster */
-               ci++;
-               cluster = mali_cluster_get_global_cluster(ci);
        }
 
        *ppos += cnt;
@@ -485,11 +457,6 @@ static const struct file_operations pp_all_counter_src1_fops = {
        .write = pp_all_counter_src1_write,
 };
 
-
-
-
-
-
 static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 {
        char buf[64];
@@ -681,11 +648,62 @@ static const struct file_operations l2_all_counter_src1_fops = {
        .write = l2_all_counter_src1_write,
 };
 
-static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 {
-       
-       memset(pwr_buf,0,POWER_BUFFER_SIZE);
-       virtual_power_status_register = 0;
+       unsigned long val;
+       int ret;
+       char buf[32];
+
+       cnt = min(cnt, sizeof(buf) - 1);
+       if (copy_from_user(buf, ubuf, cnt))
+       {
+               return -EFAULT;
+       }
+       buf[cnt] = '\0';
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (0 != ret)
+       {
+               return ret;
+       }
+
+       /* Update setting (not exactly thread safe) */
+       if (1 == val && MALI_FALSE == power_always_on_enabled)
+       {
+               power_always_on_enabled = MALI_TRUE;
+               _mali_osk_pm_dev_ref_add();
+       }
+       else if (0 == val && MALI_TRUE == power_always_on_enabled)
+       {
+               power_always_on_enabled = MALI_FALSE;
+               _mali_osk_pm_dev_ref_dec();
+       }
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       if (MALI_TRUE == power_always_on_enabled)
+       {
+               return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2);
+       }
+       else
+       {
+               return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
+       }
+}
+
+static const struct file_operations power_always_on_fops = {
+       .owner = THIS_MODULE,
+       .read  = power_always_on_read,
+       .write = power_always_on_write,
+};
+
+static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+
        if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND])))
        {
                mali_pm_os_suspend();
@@ -727,25 +745,24 @@ static ssize_t power_events_write(struct file *filp, const char __user *ubuf, si
        return cnt;
 }
 
-static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+static ssize_t power_power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 {
        return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE);
 }
 
-static loff_t power_events_seek(struct file *file, loff_t offset, int orig)
+static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig)
 {
        file->f_pos = offset;
         return 0;
 }
 
-static const struct file_operations power_events_fops = {
+static const struct file_operations power_power_events_fops = {
        .owner = THIS_MODULE,
-       .read  = power_events_read,
-       .write = power_events_write,
-       .llseek = power_events_seek,
+       .read  = power_power_events_read,
+       .write = power_power_events_write,
+       .llseek = power_power_events_seek,
 };
 
-
 #if MALI_STATE_TRACKING
 static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
 {
@@ -785,8 +802,7 @@ static const struct file_operations mali_seq_internal_state_fops = {
 };
 #endif /* MALI_STATE_TRACKING */
 
-
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
 static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 {
        char buf[64];
@@ -938,6 +954,128 @@ static int profiling_events_show(struct seq_file *seq_file, void *v)
        return 0;
 }
 
+static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v)
+{
+       #define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7))
+
+       static u64 start_time = 0;
+       loff_t *spos = v;
+       u32 index;
+       u64 timestamp;
+       u32 event_id;
+       u32 data[5];
+
+       index = (u32)*spos;
+
+       /* Retrieve all events */
+       if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data))
+       {
+               seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
+
+               if (0 == index)
+               {
+                       start_time = timestamp;
+               }
+
+               seq_printf(seq_file, "[%06u] ", index);
+
+               switch(event_id & 0x0F000000)
+               {
+               case MALI_PROFILING_EVENT_TYPE_SINGLE:
+                       seq_printf(seq_file, "SINGLE | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_START:
+                       seq_printf(seq_file, "START | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_STOP:
+                       seq_printf(seq_file, "STOP | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_SUSPEND:
+                       seq_printf(seq_file, "SUSPEND | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_RESUME:
+                       seq_printf(seq_file, "RESUME | ");
+                       break;
+               default:
+                       seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24);
+                       break;
+               }
+
+               switch(event_id & 0x00FF0000)
+               {
+               case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE:
+                       seq_printf(seq_file, "SW | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_GP0:
+                       seq_printf(seq_file, "GP0 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP0:
+                       seq_printf(seq_file, "PP0 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP1:
+                       seq_printf(seq_file, "PP1 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP2:
+                       seq_printf(seq_file, "PP2 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP3:
+                       seq_printf(seq_file, "PP3 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP4:
+                       seq_printf(seq_file, "PP4 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP5:
+                       seq_printf(seq_file, "PP5 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP6:
+                       seq_printf(seq_file, "PP6 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP7:
+                       seq_printf(seq_file, "PP7 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_GPU:
+                       seq_printf(seq_file, "GPU | ");
+                       break;
+               default:
+                       seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16);
+                       break;
+               }
+
+               if (MALI_EVENT_ID_IS_HW(event_id))
+               {
+                       if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP))
+                       {
+                               switch(event_id & 0x0000FFFF)
+                               {
+                               case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL:
+                                       seq_printf(seq_file, "PHYSICAL | ");
+                                       break;
+                               case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL:
+                                       seq_printf(seq_file, "VIRTUAL | ");
+                                       break;
+                               default:
+                                       seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
+                       }
+               }
+               else
+               {
+                       seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
+               }
+
+               seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time);
+
+               return 0;
+       }
+
+       return 0;
+}
+
 static const struct seq_operations profiling_events_seq_ops = {
        .start = profiling_events_start,
        .next  = profiling_events_next,
@@ -957,6 +1095,27 @@ static const struct file_operations profiling_events_fops = {
        .llseek = seq_lseek,
        .release = seq_release,
 };
+
+static const struct seq_operations profiling_events_human_readable_seq_ops = {
+       .start = profiling_events_start,
+       .next  = profiling_events_next,
+       .stop  = profiling_events_stop,
+       .show  = profiling_events_show_human_readable
+};
+
+static int profiling_events_human_readable_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &profiling_events_human_readable_seq_ops);
+}
+
+static const struct file_operations profiling_events_human_readable_fops = {
+       .owner = THIS_MODULE,
+       .open = profiling_events_human_readable_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
 #endif
 
 static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
@@ -974,6 +1133,51 @@ static const struct file_operations memory_usage_fops = {
        .read = memory_used_read,
 };
 
+static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 uval= _mali_ukk_utilization_gp_pp();
+
+       r = snprintf(buf, 64, "%u\n", uval);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 uval= _mali_ukk_utilization_gp();
+
+       r = snprintf(buf, 64, "%u\n", uval);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 uval= _mali_ukk_utilization_pp();
+
+       r = snprintf(buf, 64, "%u\n", uval);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+
+static const struct file_operations utilization_gp_pp_fops = {
+       .owner = THIS_MODULE,
+       .read = utilization_gp_pp_read,
+};
+
+static const struct file_operations utilization_gp_fops = {
+       .owner = THIS_MODULE,
+       .read = utilization_gp_read,
+};
+
+static const struct file_operations utilization_pp_fops = {
+       .owner = THIS_MODULE,
+       .read = utilization_pp_read,
+};
 
 static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 {
@@ -1040,23 +1244,8 @@ static int mali_sysfs_user_settings_register(void)
        return 0;
 }
 
-int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+int mali_sysfs_register(const char *mali_dev_name)
 {
-       int err = 0;
-
-       device->mali_class = class_create(THIS_MODULE, mali_dev_name);
-       if (IS_ERR(device->mali_class))
-       {
-               err = PTR_ERR(device->mali_class);
-               goto init_class_err;
-       }
-       mali_device = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name);
-       if (IS_ERR(mali_device))
-       {
-               err = PTR_ERR(mali_device);
-               goto init_mdev_err;
-       }
-
        mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
        if(ERR_PTR(-ENODEV) == mali_debugfs_dir)
        {
@@ -1072,22 +1261,23 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
                        struct dentry *mali_gp_dir;
                        struct dentry *mali_pp_dir;
                        struct dentry *mali_l2_dir;
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
                        struct dentry *mali_profiling_dir;
 #endif
 
                        mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
                        if (mali_power_dir != NULL)
                        {
-                               debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops);
+                               debugfs_create_file("always_on", 0400, mali_power_dir, NULL, &power_always_on_fops);
+                               debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_power_events_fops);
                        }
 
                        mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
                        if (mali_gp_dir != NULL)
                        {
                                struct dentry *mali_gp_all_dir;
-                               u32 ci;
-                               struct mali_cluster *cluster;
+                               u32 num_groups;
+                               int i;
 
                                mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir);
                                if (mali_gp_all_dir != NULL)
@@ -1096,35 +1286,24 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
                                        debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops);
                                }
 
-                               ci = 0;
-                               cluster = mali_cluster_get_global_cluster(ci);
-                               while (NULL != cluster)
+                               num_groups = mali_group_get_glob_num_groups();
+                               for (i = 0; i < num_groups; i++)
                                {
-                                       u32 gi = 0;
-                                       struct mali_group *group = mali_cluster_get_group(cluster, gi);
-                                       while (NULL != group)
+                                       struct mali_group *group = mali_group_get_glob_group(i);
+
+                                       struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+                                       if (NULL != gp_core)
                                        {
-                                               struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
-                                               if (NULL != gp_core)
+                                               struct dentry *mali_gp_gpx_dir;
+                                               mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
+                                               if (NULL != mali_gp_gpx_dir)
                                                {
-                                                       struct dentry *mali_gp_gpx_dir;
-                                                       mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
-                                                       if (NULL != mali_gp_gpx_dir)
-                                                       {
-                                                               debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops);
-                                                               debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops);
-                                                       }
-                                                       break; /* no need to look for any other GP cores */
+                                                       debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops);
+                                                       debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops);
                                                }
-
-                                               /* try next group */
-                                               gi++;
-                                               group = mali_cluster_get_group(cluster, gi);
+                                               break; /* no need to look for any other GP cores */
                                        }
 
-                                       /* try next cluster */
-                                       ci++;
-                                       cluster = mali_cluster_get_global_cluster(ci);
                                }
                        }
 
@@ -1132,8 +1311,8 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
                        if (mali_pp_dir != NULL)
                        {
                                struct dentry *mali_pp_all_dir;
-                               u32 ci;
-                               struct mali_cluster *cluster;
+                               u32 num_groups;
+                               int i;
 
                                mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir);
                                if (mali_pp_all_dir != NULL)
@@ -1142,36 +1321,24 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
                                        debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops);
                                }
 
-                               ci = 0;
-                               cluster = mali_cluster_get_global_cluster(ci);
-                               while (NULL != cluster)
+                               num_groups = mali_group_get_glob_num_groups();
+                               for (i = 0; i < num_groups; i++)
                                {
-                                       u32 gi = 0;
-                                       struct mali_group *group = mali_cluster_get_group(cluster, gi);
-                                       while (NULL != group)
+                                       struct mali_group *group = mali_group_get_glob_group(i);
+
+                                       struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+                                       if (NULL != pp_core)
                                        {
-                                               struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
-                                               if (NULL != pp_core)
+                                               char buf[16];
+                                               struct dentry *mali_pp_ppx_dir;
+                                               _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
+                                               mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
+                                               if (NULL != mali_pp_ppx_dir)
                                                {
-                                                       char buf[16];
-                                                       struct dentry *mali_pp_ppx_dir;
-                                                       _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
-                                                       mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
-                                                       if (NULL != mali_pp_ppx_dir)
-                                                       {
-                                                               debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops);
-                                                               debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops);
-                                                       }
+                                                       debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops);
+                                                       debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops);
                                                }
-
-                                               /* try next group */
-                                               gi++;
-                                               group = mali_cluster_get_group(cluster, gi);
                                        }
-
-                                       /* try next cluster */
-                                       ci++;
-                                       cluster = mali_cluster_get_global_cluster(ci);
                                }
                        }
 
@@ -1211,7 +1378,11 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
 
                        debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
 
-#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+                       debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
+                       debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
+                       debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
+
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
                        mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
                        if (mali_profiling_dir != NULL)
                        {
@@ -1226,6 +1397,7 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
                                }
                                debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
                                debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
+                               debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
                        }
 #endif
 
@@ -1243,24 +1415,14 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
 
        /* Success! */
        return 0;
-
-       /* Error handling */
-init_mdev_err:
-       class_destroy(device->mali_class);
-init_class_err:
-
-       return err;
 }
 
-int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+int mali_sysfs_unregister(void)
 {
        if(NULL != mali_debugfs_dir)
        {
                debugfs_remove_recursive(mali_debugfs_dir);
        }
-       device_destroy(device->mali_class, dev);
-       class_destroy(device->mali_class);
-
        return 0;
 }
 
@@ -1273,7 +1435,7 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
        return 0;
 }
 
-int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+int mali_sysfs_unregister(void)
 {
        return 0;
 }
index 24acca9586696a3a1a6918424212cedacd4fe2ad..2b243a6a2b290307b6e4677d78b0edddd7251519 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_KERNEL_SYSFS_H__
@@ -20,13 +20,8 @@ extern "C"
 
 #define MALI_PROC_DIR "driver/mali"
 
-extern struct device *mali_device;
-struct mali_dev;
-
-int mali_sysfs_register(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name);
-
-int mali_sysfs_unregister(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name);
-
+int mali_sysfs_register(const char *mali_dev_name);
+int mali_sysfs_unregister(void);
 
 #ifdef __cplusplus
 }
index 7d811bd787da034a23efdfa2eed29b7dcab843bf..ccbf363d77ca0511b060ef141635c1fa7efc8462 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #ifndef __MALI_LINUX_PM_TESTSUITE_H__
 #define __MALI_LINUX_PM_TESTSUITE_H__
index 5329ba360704e7d0fc878441e60a941afde5e008..c503179bdcb755dd34740e621de49ffc6542df88 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ)
index 32f8e6bdac7ce45dd6e2b56f717a70b0edc3e7f4..16be304721b7b51c6e0fe010be7d12fb86cfab6c 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index ddfe5642a5ca6499dd7a8949d0b5d4c58b91bad9..39d92e90e4ca31257715367eddc65a43482f25ca 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
  */
 
 #include <linux/slab.h>        /* For memory allocation */
-#include <linux/workqueue.h>
-#include <linux/version.h>
 
 #include "mali_osk.h"
 #include "mali_kernel_common.h"
-#include "mali_kernel_license.h"
-#include "mali_kernel_linux.h"
 #include "linux/interrupt.h"
 
 typedef struct _mali_osk_irq_t_struct
@@ -28,65 +24,20 @@ typedef struct _mali_osk_irq_t_struct
        u32 irqnum;
        void *data;
        _mali_osk_irq_uhandler_t uhandler;
-       _mali_osk_irq_bhandler_t bhandler;
-       struct work_struct work_queue_irq_handle; /* Workqueue for the bottom half of the IRQ-handling. This job is activated when this core gets an IRQ.*/
 } mali_osk_irq_object_t;
 
-#if MALI_LICENSE_IS_GPL
-static struct workqueue_struct *pmm_wq = NULL;
-struct workqueue_struct *mali_wq = NULL;
-#endif
-
-typedef void (*workqueue_func_t)(void *);
 typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *);
 static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/
 
-#if defined(INIT_DELAYED_WORK)
-static void irq_handler_bottom_half ( struct work_struct *work );
-#else
-static void irq_handler_bottom_half ( void *  input );
-#endif
-
-/**
- * Linux kernel version has marked SA_SHIRQ as deprecated, IRQF_SHARED should be used.
- * This is to handle older kernels which haven't done this swap.
- */
-#ifndef IRQF_SHARED
-#define IRQF_SHARED SA_SHIRQ
-#endif /* IRQF_SHARED */
-
-_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler,    _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description )
+_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description )
 {
        mali_osk_irq_object_t *irq_object;
 
        irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
-       if (NULL == irq_object) return NULL;
-
-#if MALI_LICENSE_IS_GPL
-       if (NULL == mali_wq)
+       if (NULL == irq_object)
        {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
-               mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0);
-#else
-               mali_wq = create_workqueue("mali");
-#endif
-               if(NULL == mali_wq)
-               {
-                       MALI_PRINT_ERROR(("Unable to create Mali workqueue\n"));
-                       kfree(irq_object);
-                       return NULL;
-               }
+               return NULL;
        }
-#endif
-
-       /* workqueue API changed in 2.6.20, support both versions: */
-#if defined(INIT_DELAYED_WORK)
-       /* New syntax: INIT_WORK( struct work_struct *work, void (*function)(struct work_struct *)) */
-       INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half);
-#else
-       /* Old syntax: INIT_WORK( struct work_struct *work, void (*function)(void *), void *data) */
-       INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half, irq_object);
-#endif /* defined(INIT_DELAYED_WORK) */
 
        if (-1 == irqnum)
        {
@@ -104,12 +55,12 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
                                unsigned long mask;
 
                                mask = probe_irq_on();
-                               trigger_func(data);
+                               trigger_func(probe_data);
 
                                _mali_osk_time_ubusydelay(5);
 
                                irq = probe_irq_off(mask);
-                               err = ack_func(data);
+                               err = ack_func(probe_data);
                        }
                        while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--);
 
@@ -131,90 +82,30 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
        
        irq_object->irqnum = irqnum;
        irq_object->uhandler = uhandler;
-       irq_object->bhandler = bhandler;
-       irq_object->data = data;
+       irq_object->data = int_data;
 
-       /* Is this a real IRQ handler we need? */
-       if (irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM)
+       if (-1 == irqnum)
        {
-               if (-1 == irqnum)
-               {
-                       MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
-                       kfree(irq_object);
-                       return NULL;
-               }
-
-               if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object))
-               {
-                       MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
-                       kfree(irq_object);
-                       return NULL;
-               }
+               MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
+               kfree(irq_object);
+               return NULL;
        }
 
-#if MALI_LICENSE_IS_GPL
-       if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum )
+       if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object))
        {
-               pmm_wq = create_singlethread_workqueue("mali-pmm-wq");
+               MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
+               kfree(irq_object);
+               return NULL;
        }
-#endif
 
        return irq_object;
 }
 
-void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq )
-{
-       mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
-#if MALI_LICENSE_IS_GPL
-       if ( irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
-       {
-               queue_work( pmm_wq,&irq_object->work_queue_irq_handle );
-       }
-       else
-       {
-               queue_work(mali_wq, &irq_object->work_queue_irq_handle);
-       }
-#else
-       schedule_work(&irq_object->work_queue_irq_handle);
-#endif
-}
-
-void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq )
-{
-#if MALI_LICENSE_IS_GPL
-       if (NULL != irq)
-       {
-               mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
-               if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
-               {
-                       flush_workqueue(pmm_wq);
-               }
-               else
-               {
-                       flush_workqueue(mali_wq);
-               }
-       }
-       else
-       {
-               flush_workqueue(mali_wq);
-       }
-#endif
-}
-
 void _mali_osk_irq_term( _mali_osk_irq_t *irq )
 {
        mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
-
-#if MALI_LICENSE_IS_GPL
-       if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
-       {
-               flush_workqueue(pmm_wq);
-               destroy_workqueue(pmm_wq);
-       }
-#endif
        free_irq(irq_object->irqnum, irq_object);
        kfree(irq_object);
-       flush_scheduled_work();
 }
 
 
@@ -240,27 +131,3 @@ static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , st
        return IRQ_NONE;
 }
 
-/* Is executed when an interrupt occur on one core */
-/* workqueue API changed in 2.6.20, support both versions: */
-#if defined(INIT_DELAYED_WORK)
-static void irq_handler_bottom_half ( struct work_struct *work )
-#else
-static void irq_handler_bottom_half ( void *  input )
-#endif
-{
-       mali_osk_irq_object_t *irq_object;
-
-#if defined(INIT_DELAYED_WORK)
-       irq_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_irq_object_t, work_queue_irq_handle);
-#else
-       if ( NULL == input )
-       {
-               MALI_PRINT_ERROR(("IRQ: Null pointer! Illegal!"));
-               return; /* Error */
-       }
-       irq_object = (mali_osk_irq_object_t *) input;
-#endif
-
-       irq_object->bhandler(irq_object->data);
-}
-
index d007d937f432067167b07e3c2209a7efb5091e3b..fa124ffc5e1d23aff5f1ff002608f1a26e8e7816 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 02558a09fa9f65005516161dbc93b55f1535a67f..5949403e96342e58d2cf6cfa6ef4256837783b79 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -48,6 +48,7 @@ typedef struct mali_vma_usage_tracker
        u32 cookie;
 } mali_vma_usage_tracker;
 
+#define INVALID_PAGE 0xffffffff
 
 /* Linked list structure to hold details of all OS allocations in a particular
  * mapping
@@ -188,7 +189,7 @@ static u32 _kernel_page_allocate(void)
 
        if ( NULL == new_page )
        {
-               return 0;
+               return INVALID_PAGE;
        }
 
        /* Ensure page is flushed from CPU caches. */
@@ -234,7 +235,7 @@ static AllocationList * _allocation_list_item_get(void)
        }
 
        item->physaddr = _kernel_page_allocate();
-       if ( 0 == item->physaddr )
+       if ( INVALID_PAGE == item->physaddr )
        {
                /* Non-fatal error condition, out of memory. Upper levels will handle this. */
                _mali_osk_free( item );
@@ -390,12 +391,18 @@ void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt )
 
 _mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description )
 {
+#if MALI_LICENSE_IS_GPL
+       return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */
+#else
        return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK);
+#endif
 }
 
 void inline _mali_osk_mem_unreqregion( u32 phys, u32 size )
 {
+#if !MALI_LICENSE_IS_GPL
        release_mem_region(phys, size);
+#endif
 }
 
 void inline _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val )
index 8a347a7835ae1a013de87710b89d5688affd077a..eb096aae9f8d222c7e67ff13e87fd52aad2dbd09 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
  */
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mali/mali_utgard.h>
 
+#include "mali_osk_mali.h"
 #include "mali_kernel_common.h" /* MALI_xxx macros */
 #include "mali_osk.h"           /* kernel side OS functions */
 #include "mali_uk_types.h"
-#include "arch/config.h"        /* contains the configuration of the arch we are compiling for */
+#include "mali_kernel_linux.h"
 
-_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources )
+_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
 {
-    *num_resources = sizeof(arch_configuration) / sizeof(arch_configuration[0]);
-    *arch_config = arch_configuration;
-    return _MALI_OSK_ERR_OK;
+       int i;
+
+       if (NULL == mali_platform_device)
+       {
+               /* Not connected to a device */
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       for (i = 0; i < mali_platform_device->num_resources; i++)
+       {
+               if (IORESOURCE_MEM == resource_type(&(mali_platform_device->resource[i])) &&
+                   mali_platform_device->resource[i].start == addr)
+               {
+                       if (NULL != res)
+                       {
+                               res->base = addr;
+                               res->description = mali_platform_device->resource[i].name;
+
+                               /* Any (optional) IRQ resource belonging to this resource will follow */
+                               if ((i + 1) < mali_platform_device->num_resources &&
+                                   IORESOURCE_IRQ == resource_type(&(mali_platform_device->resource[i+1])))
+                               {
+                                       res->irq = mali_platform_device->resource[i+1].start;
+                               }
+                               else
+                               {
+                                       res->irq = -1;
+                               }
+                       }
+                       return _MALI_OSK_ERR_OK;
+               }
+       }
+
+       return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+}
+
+u32 _mali_osk_resource_base_address(void)
+{
+       u32 lowest_addr = 0xFFFFFFFF;
+       u32 ret = 0;
+
+       if (NULL != mali_platform_device)
+       {
+               int i;
+               for (i = 0; i < mali_platform_device->num_resources; i++)
+               {
+                       if (mali_platform_device->resource[i].flags & IORESOURCE_MEM &&
+                           mali_platform_device->resource[i].start < lowest_addr)
+                       {
+                               lowest_addr = mali_platform_device->resource[i].start;
+                               ret = lowest_addr;
+                       }
+               }
+       }
+
+       return ret;
 }
 
-void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources )
+_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data)
 {
-    /* Nothing to do */
+       MALI_DEBUG_ASSERT_POINTER(data);
+
+       if (NULL != mali_platform_device)
+       {
+               struct mali_gpu_device_data* os_data = NULL;
+
+               os_data = (struct mali_gpu_device_data*)mali_platform_device->dev.platform_data;
+               if (NULL != os_data)
+               {
+                       /* Copy data from OS dependant struct to Mali neutral struct (identical!) */
+                       data->dedicated_mem_start = os_data->dedicated_mem_start;
+                       data->dedicated_mem_size = os_data->dedicated_mem_size;
+                       data->shared_mem_size = os_data->shared_mem_size;
+                       data->fb_start = os_data->fb_start;
+                       data->fb_size = os_data->fb_size;
+                       data->utilization_interval = os_data->utilization_interval;
+                       data->utilization_handler = os_data->utilization_handler;
+                       return _MALI_OSK_ERR_OK;
+               }
+       }
+
+       return _MALI_OSK_ERR_ITEM_NOT_FOUND;
 }
index bb25e7dc7ddc0458abf54eac0be4091e157f1ffa..e909da2e723b8b492b84a6b2d13e69e83913b4c4 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 5354e855e8dc171abcf4fea9f6fb09f018a31ed6..fde5e112b2a519e0637b53dd11d5a743534d4317 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index ad486db6f5e44bf925c0755ec3f4bad6e480ae26..66885bfe652c7661ccd778254ac41f7be5257017 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 2cfb5ef64f9226ac410d041a8605695c934d3594..e8428ba14f5ed7f64ecf85e7ba12d64f56d249e1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -16,9 +16,6 @@
 #include "mali_osk.h"
 #include "mali_kernel_common.h"
 
-/* needed to detect kernel version specific code */
-#include <linux/version.h>
-
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -38,8 +35,8 @@ struct _mali_osk_notification_queue_t_struct
 
 typedef struct _mali_osk_notification_wrapper_t_struct
 {
-    struct list_head list;           /**< Internal linked list variable */
-    _mali_osk_notification_t data;   /**< Notification data */
+       struct list_head list;           /**< Internal linked list variable */
+       _mali_osk_notification_t data;   /**< Notification data */
 } _mali_osk_notification_wrapper_t;
 
 _mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void )
@@ -59,15 +56,15 @@ _mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void )
 _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
 {
        /* OPT Recycling of notification objects */
-    _mali_osk_notification_wrapper_t *notification;
+       _mali_osk_notification_wrapper_t *notification;
 
        notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size,
                                                                    GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT);
-    if (NULL == notification)
-    {
+       if (NULL == notification)
+       {
                MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n"));
                return NULL;
-    }
+       }
 
        /* Init the list */
        INIT_LIST_HEAD(&notification->list);
@@ -86,7 +83,7 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
        notification->data.result_buffer_size = size;
 
        /* all ok */
-    return &(notification->data);
+       return &(notification->data);
 }
 
 void _mali_osk_notification_delete( _mali_osk_notification_t *object )
@@ -94,7 +91,7 @@ void _mali_osk_notification_delete( _mali_osk_notification_t *object )
        _mali_osk_notification_wrapper_t *notification;
        MALI_DEBUG_ASSERT_POINTER( object );
 
-    notification = container_of( object, _mali_osk_notification_wrapper_t, data );
+       notification = container_of( object, _mali_osk_notification_wrapper_t, data );
 
        /* Free the container */
        kfree(notification);
@@ -110,18 +107,17 @@ void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue )
 
 void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object )
 {
+       unsigned long irq_flags;
+
        _mali_osk_notification_wrapper_t *notification;
        MALI_DEBUG_ASSERT_POINTER( queue );
        MALI_DEBUG_ASSERT_POINTER( object );
 
-    notification = container_of( object, _mali_osk_notification_wrapper_t, data );
+       notification = container_of( object, _mali_osk_notification_wrapper_t, data );
 
-       /* lock queue access */
-       spin_lock(&queue->mutex);
-       /* add to list */
+       spin_lock_irqsave(&queue->mutex, irq_flags);
        list_add_tail(&notification->list, &queue->head);
-       /* unlock the queue */
-       spin_unlock(&queue->mutex);
+       spin_unlock_irqrestore(&queue->mutex, irq_flags);
 
        /* and wake up one possible exclusive waiter */
        wake_up(&queue->receive_queue);
@@ -129,10 +125,12 @@ void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _
 
 _mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result )
 {
+       unsigned long irq_flags;
+
        _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND;
        _mali_osk_notification_wrapper_t *wrapper_object;
 
-       spin_lock(&queue->mutex);
+       spin_lock_irqsave(&queue->mutex, irq_flags);
 
        if (!list_empty(&queue->head))
        {
@@ -142,7 +140,7 @@ _mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification
                ret = _MALI_OSK_ERR_OK;
        }
 
-       spin_unlock(&queue->mutex);
+       spin_unlock_irqrestore(&queue->mutex, irq_flags);
 
        return ret;
 }
@@ -153,7 +151,7 @@ _mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification
        MALI_DEBUG_ASSERT_POINTER( queue );
        MALI_DEBUG_ASSERT_POINTER( result );
 
-    /* default result */
+       /* default result */
        *result = NULL;
 
        if (wait_event_interruptible(queue->receive_queue,
index 491a6038dd448e251ced3f1523c6be30801e3186..db87bce77a833e2dfe365b74b46db6334cc8e6fd 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
 #include <linux/pm_runtime.h>
 #endif /* CONFIG_PM_RUNTIME */
 #include <linux/platform_device.h>
-#include "mali_platform.h"
+#include <linux/version.h>
 #include "mali_osk.h"
-#include "mali_uk_types.h"
 #include "mali_kernel_common.h"
-#include "mali_kernel_license.h"
-#include "mali_linux_pm.h"
-#include "mali_kernel_license.h"
+#include "mali_kernel_linux.h"
 
-#if ! MALI_LICENSE_IS_GPL
-#undef CONFIG_PM_RUNTIME
-#endif
+static _mali_osk_atomic_t mali_pm_ref_count;
 
-extern struct platform_device mali_gpu_device;
+void _mali_osk_pm_dev_enable(void) /* @@@@ todo: change to init of some kind.. or change the way or where atomics are initialized? */
+{
+       _mali_osk_atomic_init(&mali_pm_ref_count, 0);
+}
+
+void _mali_osk_pm_dev_disable(void) /* @@@@ todo: change to term of some kind */
+{
+       _mali_osk_atomic_term(&mali_pm_ref_count);
+}
 
+/* Can NOT run in atomic context */
+_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void)
+{
 #ifdef CONFIG_PM_RUNTIME
-static mali_bool have_runtime_reference = MALI_FALSE;
+       int err;
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       err = pm_runtime_get_sync(&(mali_platform_device->dev));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+       pm_runtime_mark_last_busy(&(mali_platform_device->dev));
+#endif
+       if (0 > err)
+       {
+               MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get_sync() returned error code %d\n", err));
+               return _MALI_OSK_ERR_FAULT;
+       }
+       _mali_osk_atomic_inc(&mali_pm_ref_count);
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
 #endif
+       return _MALI_OSK_ERR_OK;
+}
 
-void _mali_osk_pm_dev_enable(void)
+/* Can run in atomic context */
+void _mali_osk_pm_dev_ref_dec(void)
 {
 #ifdef CONFIG_PM_RUNTIME
-       pm_runtime_enable(&(mali_gpu_device.dev));
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       _mali_osk_atomic_dec(&mali_pm_ref_count);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+       pm_runtime_mark_last_busy(&(mali_platform_device->dev));
+       pm_runtime_put_autosuspend(&(mali_platform_device->dev));
+#else
+       pm_runtime_put(&(mali_platform_device->dev));
+#endif
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
 #endif
 }
 
-/* NB: Function is not thread safe */
-_mali_osk_errcode_t _mali_osk_pm_dev_idle(void)
+/* Can run in atomic context */
+mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void)
 {
 #ifdef CONFIG_PM_RUNTIME
-       if (MALI_TRUE == have_runtime_reference)
-       {
-               int err;
-               err = pm_runtime_put_sync(&(mali_gpu_device.dev));      
-               if (0 > err)
-               {
-                       MALI_PRINT_ERROR(("OSK PM: pm_runtime_put_sync() returned error code %d\n", err));      
-                       return _MALI_OSK_ERR_FAULT;
-               }
-               have_runtime_reference = MALI_FALSE;
-       }
+       u32 ref;
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       pm_runtime_get_noresume(&(mali_platform_device->dev));
+       ref = _mali_osk_atomic_read(&mali_pm_ref_count);
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
+       return ref > 0 ? MALI_TRUE : MALI_FALSE;
+#else
+       return MALI_TRUE;
 #endif
-       return _MALI_OSK_ERR_OK;
 }
 
-/* NB: Function is not thread safe */
-_mali_osk_errcode_t _mali_osk_pm_dev_activate(void)
+/* Can run in atomic context */
+void _mali_osk_pm_dev_ref_dec_no_power_on(void)
 {
 #ifdef CONFIG_PM_RUNTIME
-       if (MALI_TRUE != have_runtime_reference)
-       {
-               int err;
-               err = pm_runtime_get_sync(&(mali_gpu_device.dev));
-               if (0 > err)
-               {
-                       MALI_PRINT_ERROR(("OSK PM: pm_runtime_get_sync() returned error code %d\n", err));      
-                       return _MALI_OSK_ERR_FAULT;
-               }
-               have_runtime_reference = MALI_TRUE;
-       }
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+       pm_runtime_put_autosuspend(&(mali_platform_device->dev));
+#else
+       pm_runtime_put(&(mali_platform_device->dev));
+#endif
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
 #endif
-       return _MALI_OSK_ERR_OK;
 }
index 95bee5351e4b707512aee5762ce4eea510b87f68..023f64b6b63e8d83ccbcaaad586b8aea47729ee1 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include <linux/module.h>
@@ -125,27 +125,18 @@ _mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *
  */
 int _mali_profiling_set_event(u32 counter_id, s32 event_id)
 {
-
        if (COUNTER_VP_C0 == counter_id)
        {
-               struct mali_gp_core* gp_core = mali_gp_get_global_gp_core();
-               if (NULL != gp_core)
+               if (MALI_TRUE == mali_gp_job_set_gp_counter_src0(event_id))
                {
-                       if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id))
-                       {
-                               return 1;
-                       }
+                       return 1;
                }
        }
        if (COUNTER_VP_C1 == counter_id)
        {
-               struct mali_gp_core* gp_core = mali_gp_get_global_gp_core();
-               if (NULL != gp_core)
+               if (MALI_TRUE == mali_gp_job_set_gp_counter_src1(event_id))
                {
-                       if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id))
-                       {
-                               return 1;
-                       }
+                       return 1;
                }
        }
        if (COUNTER_FP0_C0 <= counter_id && COUNTER_FP3_C1 >= counter_id)
@@ -154,19 +145,29 @@ int _mali_profiling_set_event(u32 counter_id, s32 event_id)
                struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id);
                if (NULL != pp_core)
                {
-                       u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1;
-                       if (0 == counter_src)
+                       /*todo: this is a hack!!!
+                                * we account only for the counters set for the first PP core
+                                * others are just silently ignored or,
+                                * if the first core coutners are not set, we take the second etc.
+                                * - need further discussion!!!*/
+
+                       if ((COUNTER_FP0_C0 == counter_id) || (COUNTER_FP0_C1 == counter_id))
                        {
-                               if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id))
+                               u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1;
+                               if (0 == counter_src)
                                {
-                                       return 1;
+                                       if (MALI_TRUE == mali_pp_job_set_pp_counter_src0(event_id))
+                                       {
+                                               return 1;
+                                       }
                                }
-                       }
-                       else
-                       {
-                               if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id))
+                               else
                                {
+                                       if (MALI_TRUE == mali_pp_job_set_pp_counter_src1(event_id))
+                                       {
+                                       MALI_DEBUG_PRINT(2, ("MALI PROFILING SET EVENT core 0 counter_id = %d\n",counter_id));
                                        return 1;
+                                       }
                                }
                        }
                }
index 157368b944639364b5044c8b42a529571695c733..74095bbd9824b8123731b8a89bcfb96526367323 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
 
 #include <asm/uaccess.h>
 
+#include "mali_sync.h"
+
 #define MALI_STATIC_INLINE static inline
 #define MALI_NON_STATIC_INLINE inline
 
+#ifdef CONFIG_SYNC
+typedef struct sync_timeline mali_sync_tl;
+typedef struct sync_pt mali_sync_pt;
+
+MALI_STATIC_INLINE mali_sync_pt *_mali_osk_sync_pt_create(mali_sync_tl *parent)
+{
+       return (mali_sync_pt*)mali_sync_pt_alloc(parent);
+}
+
+MALI_STATIC_INLINE void _mali_osk_sync_pt_signal(mali_sync_pt *pt)
+{
+       mali_sync_signal_pt(pt);
+}
+#endif /* CONFIG_SYNC */
+
 MALI_STATIC_INLINE u32 _mali_osk_copy_from_user(void *to, void *from, u32 n)
 {
        return (u32)copy_from_user(to, from, (unsigned long)n);
index b399b874880158b5b1c1c6edbd7bc4640702c656..f7ddb65023ae640df3f55fc7d4d24fc0077411ec 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index e5829a3e734c08df0612353d37080f31e0e40cca..dc6e4530361962c2a9e748ac54f905e105893940 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -35,14 +35,14 @@ _mali_osk_timer_t *_mali_osk_timer_init(void)
 void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire )
 {
        MALI_DEBUG_ASSERT_POINTER(tim);
-    tim->timer.expires = _mali_osk_time_tickcount() + ticks_to_expire;
+    tim->timer.expires = jiffies + ticks_to_expire;
     add_timer(&(tim->timer));
 }
 
-void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick)
+void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire)
 {
     MALI_DEBUG_ASSERT_POINTER(tim);
-    mod_timer(&(tim->timer), expiry_tick);
+    mod_timer(&(tim->timer), jiffies + ticks_to_expire);
 }
 
 void _mali_osk_timer_del( _mali_osk_timer_t *tim )
@@ -51,6 +51,18 @@ void _mali_osk_timer_del( _mali_osk_timer_t *tim )
     del_timer_sync(&(tim->timer));
 }
 
+void _mali_osk_timer_del_async( _mali_osk_timer_t *tim )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       del_timer(&(tim->timer));
+}
+
+mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       return 1 == timer_pending(&(tim->timer));
+}
+
 void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data )
 {
     MALI_DEBUG_ASSERT_POINTER(tim);
index ce0561d51832ba4c2eda84c63feee9e3805244ef..dd3c8d7b77e561ff7465ecc1cb1b9a737b2d45fc 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
diff --git a/mali/linux/mali_osk_wq.c b/mali/linux/mali_osk_wq.c
new file mode 100644 (file)
index 0000000..6515f05
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_wq.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <linux/slab.h>        /* For memory allocation */
+#include <linux/workqueue.h>
+#include <linux/version.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_license.h"
+#include "mali_kernel_linux.h"
+
+typedef struct _mali_osk_wq_work_t_struct
+{
+       _mali_osk_wq_work_handler_t handler;
+       void *data;
+       struct work_struct work_handle;
+} mali_osk_wq_work_object_t;
+
+#if MALI_LICENSE_IS_GPL
+struct workqueue_struct *mali_wq = NULL;
+#endif
+
+static void _mali_osk_wq_work_func ( struct work_struct *work );
+
+_mali_osk_errcode_t _mali_osk_wq_init(void)
+{
+#if MALI_LICENSE_IS_GPL
+       MALI_DEBUG_ASSERT(NULL == mali_wq);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+       mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0);
+#else
+       mali_wq = create_workqueue("mali");
+#endif
+       if(NULL == mali_wq)
+       {
+               MALI_PRINT_ERROR(("Unable to create Mali workqueue\n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+#endif
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_wq_flush(void)
+{
+#if MALI_LICENSE_IS_GPL
+       flush_workqueue(mali_wq);
+#else
+       flush_scheduled_work();
+#endif
+}
+
+void _mali_osk_wq_term(void)
+{
+#if MALI_LICENSE_IS_GPL
+       MALI_DEBUG_ASSERT(NULL != mali_wq);
+
+       flush_workqueue(mali_wq);
+       destroy_workqueue(mali_wq);
+       mali_wq = NULL;
+#else
+       flush_scheduled_work();
+#endif
+}
+
+_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data )
+{
+       mali_osk_wq_work_object_t *work = kmalloc(sizeof(mali_osk_wq_work_object_t), GFP_KERNEL);
+
+       if (NULL == work) return NULL;
+
+       work->handler = handler;
+       work->data = data;
+
+       INIT_WORK( &work->work_handle, _mali_osk_wq_work_func );
+
+       return work;
+}
+
+void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work )
+{
+       mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+       _mali_osk_wq_flush();
+       kfree(work_object);
+}
+
+void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work )
+{
+       mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+#if MALI_LICENSE_IS_GPL
+       queue_work(mali_wq, &work_object->work_handle);
+#else
+       schedule_work(&work_object->work_handle);
+#endif
+}
+
+static void _mali_osk_wq_work_func ( struct work_struct *work )
+{
+       mali_osk_wq_work_object_t *work_object;
+
+       work_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_wq_work_object_t, work_handle);
+       work_object->handler(work_object->data);
+}
+
index f3b0a2c95a0139d45aa1005d7bc6b62dd9632d24..2df34bb579a457f2e965610131d2c1610fabf2ed 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
index 2639a404d47578c7f477f2c9261a88e951227701..0164e8135f67d92770aae7c6cdc4bfda19d182ab 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_PROFILING_EVENTS_H__
index 8202497e96bb8d3862b55a7eda4d48dd67c9531a..0c7356686db9258a398ed576081bdf1b5d0e5c7e 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_kernel_common.h"
@@ -52,7 +52,7 @@ _mali_osk_errcode_t _mali_internal_profiling_init(mali_bool auto_start)
        profile_mask = 0;
        _mali_osk_atomic_init(&profile_insert_index, 0);
 
-       lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING);
+       lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING);
        if (NULL == lock)
        {
                return _MALI_OSK_ERR_FAULT;
@@ -99,11 +99,24 @@ void _mali_internal_profiling_term(void)
 _mali_osk_errcode_t _mali_internal_profiling_start(u32 * limit)
 {
        _mali_osk_errcode_t ret;
-
        mali_profiling_entry *new_profile_entries;
 
        _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
 
+       if (MALI_PROFILING_STATE_RUNNING == prof_state)
+       {
+               _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+               return _MALI_OSK_ERR_BUSY;
+       }
+
+       new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry));
+
+       if (NULL == new_profile_entries)
+       {
+               _mali_osk_vfree(new_profile_entries);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
        if (MALI_PROFILING_MAX_BUFFER_ENTRIES < *limit)
        {
                *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES;
@@ -120,14 +133,6 @@ _mali_osk_errcode_t _mali_internal_profiling_start(u32 * limit)
 
        profile_mask--; /* turns the power of two into a mask of one less */
 
-       new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry));
-
-       if (NULL == new_profile_entries)
-       {
-               _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
-               return _MALI_OSK_ERR_NOMEM;
-       }
-
        if (MALI_PROFILING_STATE_IDLE != prof_state)
        {
                _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
@@ -190,10 +195,11 @@ _mali_osk_errcode_t _mali_internal_profiling_stop(u32 * count)
        prof_state = MALI_PROFILING_STATE_RETURN;
 
        unregister_trace_mali_timeline_event(probe_mali_timeline_event, NULL);
-       tracepoint_synchronize_unregister();
 
        _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
 
+       tracepoint_synchronize_unregister();
+
        *count = _mali_osk_atomic_read(&profile_insert_index);
        if (*count > profile_mask) *count = profile_mask;
 
index 092b9b05369f36ec548d4930d8fa5e60a24dd5da..b6c3410be63eaab9169db2b2afa8f176b57e13ae 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_PROFILING_INTERNAL_H__
diff --git a/mali/linux/mali_sync.c b/mali/linux/mali_sync.c
new file mode 100644 (file)
index 0000000..7f6cc4d
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_sync.c
+ *
+ */
+
+#include <linux/seq_file.h>
+#include <linux/sync.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+struct mali_sync_timeline
+{
+       struct sync_timeline timeline;
+       atomic_t counter;
+       atomic_t signalled;
+};
+
+struct mali_sync_pt
+{
+       struct sync_pt pt;
+       u32 order;
+};
+
+static inline struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline)
+{
+       return container_of(timeline, struct mali_sync_timeline, timeline);
+}
+
+static inline struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt)
+{
+       return container_of(pt, struct mali_sync_pt, pt);
+}
+
+static struct sync_pt *timeline_dup(struct sync_pt *pt)
+{
+       struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
+       struct mali_sync_pt *new_mpt;
+       struct sync_pt *new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt));
+
+       if (!new_pt)
+       {
+               return NULL;
+       }
+
+       new_mpt = to_mali_sync_pt(new_pt);
+       new_mpt->order = mpt->order;
+
+       return new_pt;
+
+}
+
+static int timeline_has_signaled(struct sync_pt *pt)
+{
+       struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
+       struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent);
+
+       long diff = atomic_read(&mtl->signalled) - mpt->order;
+
+       return diff >= 0;
+}
+
+static int timeline_compare(struct sync_pt *a, struct sync_pt *b)
+{
+       struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt);
+       struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt);
+
+       long diff = ma->order - mb->order;
+
+       if (diff < 0)
+       {
+               return -1;
+       }
+       else if (diff == 0)
+       {
+               return 0;
+       }
+       else
+       {
+               return 1;
+       }
+}
+
+static void timeline_print_tl(struct seq_file *s, struct sync_timeline *sync_timeline)
+{
+       struct mali_sync_timeline *mtl = to_mali_sync_timeline(sync_timeline);
+
+       seq_printf(s, "%u, %u", atomic_read(&mtl->signalled), atomic_read(&mtl->counter));
+}
+
+static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
+{
+       struct mali_sync_pt *mpt = to_mali_sync_pt(sync_pt);
+
+       seq_printf(s, "%u", mpt->order);
+
+}
+
+static struct sync_timeline_ops mali_timeline_ops = {
+       .driver_name    = "Mali",
+       .dup            = timeline_dup,
+       .has_signaled   = timeline_has_signaled,
+       .compare        = timeline_compare,
+       .print_obj      = timeline_print_tl,
+       .print_pt       = timeline_print_pt
+};
+
+int mali_sync_timeline_is_ours(struct sync_timeline *timeline)
+{
+       return (timeline->ops == &mali_timeline_ops);
+}
+
+struct sync_timeline *mali_sync_timeline_alloc(const char * name)
+{
+       struct sync_timeline *tl;
+       struct mali_sync_timeline *mtl;
+
+       tl = sync_timeline_create(&mali_timeline_ops,
+                                 sizeof(struct mali_sync_timeline), name);
+       if (!tl)
+       {
+               return NULL;
+       }
+
+       /* Set the counter in our private struct */
+       mtl = to_mali_sync_timeline(tl);
+       atomic_set(&mtl->counter, 0);
+       atomic_set(&mtl->signalled, 0);
+
+       return tl;
+}
+
+struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent)
+{
+       struct sync_pt *pt = sync_pt_create(parent, sizeof(struct mali_sync_pt));
+       struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent);
+       struct mali_sync_pt *mpt;
+
+       if (!pt)
+       {
+               return NULL;
+       }
+
+       mpt = to_mali_sync_pt(pt);
+       mpt->order = atomic_inc_return(&mtl->counter);
+
+       return pt;
+}
+
+void mali_sync_signal_pt(struct sync_pt *pt)
+{
+       struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
+       struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent);
+       int signalled;
+       long diff;
+
+       do {
+
+               signalled = atomic_read(&mtl->signalled);
+
+               diff = signalled - mpt->order;
+
+               if (diff > 0)
+               {
+                       /* The timeline is already at or ahead of this point. This should not happen unless userspace
+                        * has been signalling fences out of order, so warn but don't violate the sync_pt API.
+                        * The warning is only in debug builds to prevent a malicious user being able to spam dmesg.
+                        */
+                       MALI_DEBUG_PRINT_ERROR(("Sync points were triggerd in a different order to allocation!\n"));
+                       return;
+               }
+       } while (atomic_cmpxchg(&mtl->signalled, signalled, mpt->order) != signalled);
+
+       sync_timeline_signal(pt->parent);
+}
diff --git a/mali/linux/mali_sync.h b/mali/linux/mali_sync.h
new file mode 100644 (file)
index 0000000..0dfa13a
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_sync.h
+ *
+ */
+
+#ifndef _MALI_SYNC_H_
+#define _MALI_SYNC_H_
+
+#ifdef CONFIG_SYNC
+
+#include <linux/seq_file.h>
+#include <linux/sync.h>
+
+/*
+ * Create a stream object.
+ * Built on top of timeline object.
+ * Exposed as a file descriptor.
+ * Life-time controlled via the file descriptor:
+ * - dup to add a ref
+ * - close to remove a ref
+ */
+_mali_osk_errcode_t mali_stream_create(const char * name, int * out_fd);
+
+/*
+ * Create a fence in a stream object
+ */
+struct sync_pt *mali_stream_create_point(int tl_fd);
+int mali_stream_create_fence(struct sync_pt *pt);
+
+/*
+ * Validate a fd to be a valid fence
+ * No reference is taken.
+ *
+ * This function is only usable to catch unintentional user errors early,
+ * it does not stop malicious code changing the fd after this function returns.
+ */
+_mali_osk_errcode_t mali_fence_validate(int fd);
+
+
+/* Returns true if the specified timeline is allocated by Mali */
+int mali_sync_timeline_is_ours(struct sync_timeline *timeline);
+
+/* Allocates a timeline for Mali
+ *
+ * One timeline should be allocated per API context.
+ */
+struct sync_timeline *mali_sync_timeline_alloc(const char *name);
+
+/* Allocates a sync point within the timeline.
+ *
+ * The timeline must be the one allocated by mali_sync_timeline_alloc
+ *
+ * Sync points must be triggered in *exactly* the same order as they are allocated.
+ */
+struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent);
+
+/* Signals a particular sync point
+ *
+ * Sync points must be triggered in *exactly* the same order as they are allocated.
+ *
+ * If they are signalled in the wrong order then a message will be printed in debug
+ * builds and otherwise attempts to signal order sync_pts will be ignored.
+ */
+void mali_sync_signal_pt(struct sync_pt *pt);
+
+#endif /* CONFIG_SYNC */
+#endif /* _MALI_SYNC_H_ */
diff --git a/mali/linux/mali_sync_user.c b/mali/linux/mali_sync_user.c
new file mode 100644 (file)
index 0000000..28d7d5c
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_sync_user.c
+ *
+ */
+
+#ifdef CONFIG_SYNC
+
+#include <linux/sched.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/anon_inodes.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_sync.h"
+
+static int mali_stream_close(struct inode * inode, struct file * file)
+{
+       struct sync_timeline * tl;
+       tl = (struct sync_timeline*)file->private_data;
+       BUG_ON(!tl);
+       sync_timeline_destroy(tl);
+       return 0;
+}
+
+static struct file_operations stream_fops =
+{
+       .owner = THIS_MODULE,
+       .release = mali_stream_close,
+};
+
+_mali_osk_errcode_t mali_stream_create(const char * name, int *out_fd)
+{
+       struct sync_timeline * tl;
+       BUG_ON(!out_fd);
+
+       tl = mali_sync_timeline_alloc(name);
+       if (!tl)
+       {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC);
+
+       if (*out_fd < 0)
+       {
+               sync_timeline_destroy(tl);
+               return _MALI_OSK_ERR_FAULT;
+       }
+       else
+       {
+               return _MALI_OSK_ERR_OK;
+       }
+}
+
+mali_sync_pt *mali_stream_create_point(int tl_fd)
+{
+       struct sync_timeline *tl;
+       struct sync_pt * pt;
+       struct file *tl_file;
+
+       tl_file = fget(tl_fd);
+       if (tl_file == NULL)
+               return NULL;
+
+       if (tl_file->f_op != &stream_fops)
+       {
+               pt = NULL;
+               goto out;
+       }
+
+       tl = tl_file->private_data;
+
+       pt = mali_sync_pt_alloc(tl);
+       if (!pt)
+       {
+               pt = NULL;
+               goto out;
+       }
+
+out:
+       fput(tl_file);
+
+       return pt;
+}
+
+int mali_stream_create_fence(mali_sync_pt *pt)
+{
+       struct sync_fence *fence;
+       struct fdtable * fdt;
+       struct files_struct * files;
+       int fd = -1;
+
+       fence = sync_fence_create("mali_fence", pt);
+       if (!fence)
+       {
+               sync_pt_free(pt);
+               fd = -EFAULT;
+               goto out;
+       }
+
+       /* create a fd representing the fence */
+       fd = get_unused_fd();
+       if (fd < 0)
+       {
+               sync_fence_put(fence);
+               goto out;
+       }
+
+       files = current->files;
+       spin_lock(&files->file_lock);
+       fdt = files_fdtable(files);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+       __set_close_on_exec(fd, fdt);
+#else
+       FD_SET(fd, fdt->close_on_exec);
+#endif
+       spin_unlock(&files->file_lock);
+
+       /* bind fence to the new fd */
+       sync_fence_install(fence, fd);
+
+out:
+       return fd;
+}
+
+_mali_osk_errcode_t mali_fence_validate(int fd)
+{
+       struct sync_fence * fence;
+       fence = sync_fence_fdget(fd);
+       if (NULL != fence)
+       {
+               sync_fence_put(fence);
+               return _MALI_OSK_ERR_OK;
+       }
+       else
+       {
+               return _MALI_OSK_ERR_FAULT;
+       }
+}
+
+#endif /* CONFIG_SYNC */
index fbe902a02d43296a603cf17c36fe13ea39c95c27..fac43ae4a848a1261187e95c596ad0d0cdd40400 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_UK_TYPES_H__
index 22262fed709589c93095a3c67d68b128909d5288..5802957d96f3e56344d437df48c06dcea055fb06 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include <linux/fs.h>       /* file system operations */
 #include <linux/slab.h>     /* memort allocation functions */
@@ -16,6 +16,7 @@
 #include "mali_kernel_common.h"
 #include "mali_session.h"
 #include "mali_ukk_wrappers.h"
+#include "mali_sync.h"
 
 int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs)
 {
@@ -102,3 +103,48 @@ int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_g
 
        return 0;
 }
+
+#ifdef CONFIG_SYNC
+int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs)
+{
+       _mali_uk_stream_create_s kargs;
+       _mali_osk_errcode_t err;
+       char name[32];
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       snprintf(name, 32, "mali-%u", _mali_osk_get_pid());
+
+       kargs.ctx = session_data;
+       err = mali_stream_create(name, &kargs.fd);
+       if (_MALI_OSK_ERR_OK != err)
+       {
+               return map_errcode(err);
+       }
+
+       kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+       if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_stream_create_s))) return -EFAULT;
+
+       return 0;
+}
+
+int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs)
+{
+       int fd;
+       _mali_osk_errcode_t err;
+
+       if (0 != get_user(fd, &uargs->fd))
+       {
+               return -EFAULT;
+       }
+
+       err = mali_fence_validate(fd);
+
+       if (_MALI_OSK_ERR_OK == err)
+       {
+               return 0;
+       }
+
+       return -EINVAL;
+}
+#endif
index 4ee4a81b2a7a84deebf5178d3d6c503e24b2d316..989074359528becdd6ce789584dd6a101687a678 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include <linux/fs.h>       /* file system operations */
 #include <asm/uaccess.h>    /* user space access */
index 260f257c2bab6bffcb0f0c52c4269377b6db0935..f6ca748ae53cd950e61d839ad401353ea8847b47 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include <linux/fs.h>       /* file system operations */
 #include <asm/uaccess.h>    /* user space access */
@@ -127,7 +127,7 @@ int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap
        return map_errcode(err_code);
 }
 
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument)
 {
        _mali_uk_release_ump_mem_s uk_args;
@@ -189,7 +189,7 @@ int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_atta
     /* Return the error that _mali_ukk_map_external_ump_mem produced */
        return map_errcode(err_code);
 }
-#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
+#endif /* CONFIG_MALI400_UMP */
 
 int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs)
 {
index 00a84f7c8a711d7e21c8fd6faef752fd23ef76bf..a4db9871e7c2ba0de7d335cda7ff167081007c93 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include <linux/fs.h>       /* file system operations */
 #include <asm/uaccess.h>    /* user space access */
 int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs)
 {
        _mali_osk_errcode_t err;
+       int fence = -1;
 
        MALI_CHECK_NON_NULL(uargs, -EINVAL);
        MALI_CHECK_NON_NULL(session_data, -EINVAL);
 
-       err = _mali_ukk_pp_start_job(session_data, uargs);
+       err = _mali_ukk_pp_start_job(session_data, uargs, &fence);
        if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
 
+       if (-1 != fence)
+       {
+               if (0 != put_user(fence, &uargs->fence)) return -EFAULT;
+       }
+
        return 0;
 }
 
index f4e31c92723e9d2ec0a9dc0f1a619e56666db0c9..755facc6760138df38c38d62ea0602aa7b4aae23 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include <linux/fs.h>       /* file system operations */
 #include <asm/uaccess.h>    /* user space access */
index f9b5a3e3851876f0c950e598417e23d6ea190978..b76007b869a98654f214f323a95efa422e0e6993 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 #include <linux/fs.h>       /* file system operations */
 #include <asm/uaccess.h>    /* user space access */
index 65857fd402c034e89e4ee6f431c64fc78d78d280..66783ed709095425ce17d51b427cfb4d661c4740 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 /**
@@ -27,6 +27,10 @@ extern "C"
 int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs);
 int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs);
 int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs);
+#if defined(CONFIG_SYNC)
+int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs);
+int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs);
+#endif
 int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs);
 int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs);
 int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs);
@@ -35,10 +39,10 @@ int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap
 int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs);
 int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs);
 
-#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#if defined(CONFIG_MALI400_UMP)
 int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument);
 int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument);
-#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
+#endif
 
 int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs);
 int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs);
index c8cc2ef6ccda84e70c54bb716b9703949cca71c1..db99aceca5902587690adf4745e38aa8304cc0aa 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/ioport.h>
 #include <linux/dma-mapping.h>
 
+#include <linux/module.h>
+
 #include <mach/am_regs.h>
 #include <mach/clock.h>
 
index a6b25032f5c0666dddb994e77c1cbd2f2b410827..96cdcfb77426209898f82087a2036854f6a78e3a 100644 (file)
@@ -28,6 +28,7 @@
 #include "mali_platform.h"
 #include "mali_poweron_reg.h"
 #include "mali_fix.h"
+#include "mali_platform.h"
 
 static int last_power_mode = -1;
 static int mali_init_flag = 0;
@@ -157,9 +158,9 @@ static void mali_meson_poweron(int first_poweron)
        
        MALI_DEBUG_PRINT(2, ("mali_meson_poweron: Mali APB bus accessing\n"));
        if (READ_MALI_REG(MALI_PP_PP_VERSION) != MALI_PP_PP_VERSION_MAGIC) {
-               MALI_DEBUG_PRINT(3, ("mali_meson_poweron: Mali APB bus access failed\n"));
-               //printk("mali_meson_poweron: Mali APB bus access failed.");
-               return;
+       MALI_DEBUG_PRINT(3, ("mali_meson_poweron: Mali APB bus access failed\n"));
+       //printk("mali_meson_poweron: Mali APB bus access failed.");
+       return;
        }
        MALI_DEBUG_PRINT(2, ("..........accessing done.\n"));
        if (READ_MALI_REG(MALI_MMU_DTE_ADDR) != 0) {
diff --git a/mali/platform/meson_platform/mali_platform.h b/mali/platform/meson_platform/mali_platform.h
new file mode 100644 (file)
index 0000000..8c51a97
--- /dev/null
@@ -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.
+ */
+
+/**
+ * @file mali_platform.h
+ * Platform specific Mali driver functions
+ */
+
+#ifndef __MALI_PLATFORM_H__
+#define __MALI_PLATFORM_H__
+
+#include "mali_osk.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief description of power change reasons
+ */
+typedef enum mali_power_mode_tag
+{
+       MALI_POWER_MODE_ON,           /**< Power Mali on */
+       MALI_POWER_MODE_LIGHT_SLEEP,  /**< Mali has been idle for a short time, or runtime PM suspend */
+       MALI_POWER_MODE_DEEP_SLEEP,   /**< Mali has been idle for a long time, or OS suspend */
+} mali_power_mode;
+
+/** @brief Platform specific setup and initialisation of MALI
+ *
+ * This is called from the entrypoint of the driver to initialize the platform
+ *
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_platform_init(void);
+
+/** @brief Platform specific deinitialisation of MALI
+ *
+ * This is called on the exit of the driver to terminate the platform
+ *
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_platform_deinit(void);
+
+/** @brief Platform specific powerdown sequence of MALI
+ *
+ * Notification from the Mali device driver stating the new desired power mode.
+ * MALI_POWER_MODE_ON must be obeyed, while the other modes are optional.
+ * @param power_mode defines the power modes
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode);
+
+
+/** @brief Platform specific handling of GPU utilization data
+ *
+ * When GPU utilization data is enabled, this function will be
+ * periodically called.
+ *
+ * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization.
+ */
+void mali_gpu_utilization_handler(u32 utilization);
+
+/** @brief Setting the power domain of MALI
+ *
+ * This function sets the power domain of MALI if Linux run time power management is enabled
+ *
+ * @param dev Reference to struct platform_device (defined in linux) used by MALI GPU
+ */
+void set_mali_parent_power_domain(void* dev);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/mali/platform/meson_platform/meson_main.c b/mali/platform/meson_platform/meson_main.c
new file mode 100644 (file)
index 0000000..c7d8e46
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_platform.c
+ * Platform specific Mali driver functions for:
+ * - Realview Versatile platforms with ARM11 Mpcore and virtex 5.
+ * - Versatile Express platforms with ARM Cortex-A9 and virtex 6.
+ */
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#include <linux/module.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+#include <asm/io.h>
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <mach/am_regs.h>
+#include <linux/module.h>
+#include "mali_platform.h"
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)
+extern struct platform_device meson_device_pd[];
+#else
+extern struct platform_device meson_device_pd[];
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) */
+
+static void mali_platform_device_release(struct device *device);
+static int mali_os_suspend(struct device *device);
+static int mali_os_resume(struct device *device);
+static int mali_os_freeze(struct device *device);
+static int mali_os_thaw(struct device *device);
+#ifdef CONFIG_PM_RUNTIME
+static int mali_runtime_suspend(struct device *device);
+static int mali_runtime_resume(struct device *device);
+static int mali_runtime_idle(struct device *device);
+#endif
+
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TV
+
+#define INT_MALI_GP      (48+32)
+#define INT_MALI_GP_MMU  (49+32)
+#define INT_MALI_PP      (50+32)
+#define INT_MALI_PP2     (58+32)
+#define INT_MALI_PP3     (60+32)
+#define INT_MALI_PP4     (62+32)
+#define INT_MALI_PP_MMU  (51+32)
+#define INT_MALI_PP2_MMU (59+32)
+#define INT_MALI_PP3_MMU (61+32)
+#define INT_MALI_PP4_MMU (63+32)
+
+static struct resource meson_mali_resources[] =
+{
+       MALI_GPU_RESOURCES_MALI400_MP2(0xd0060000, 
+                       INT_MALI_GP, INT_MALI_GP_MMU, 
+                       INT_MALI_PP, INT_MALI_PP_MMU, 
+                       INT_MALI_PP2, INT_MALI_PP2_MMU)
+};
+
+#elif MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+
+int static_pp_mmu_cnt;
+
+#define INT_MALI_GP      (48+32)
+#define INT_MALI_GP_MMU  (49+32)
+#define INT_MALI_PP      (50+32)
+#define INT_MALI_PP_MMU  (51+32)
+#define INT_MALI_PP2_MMU ( 6+32)
+
+static struct resource meson_mali_resources[] =
+{
+       MALI_GPU_RESOURCES_MALI400_MP2(0xd0060000, 
+                       INT_MALI_GP, INT_MALI_GP_MMU, 
+                       INT_MALI_PP, INT_MALI_PP2_MMU, 
+                       INT_MALI_PP_MMU, INT_MALI_PP2_MMU)
+};
+
+#else
+
+#define INT_MALI_GP    48
+#define INT_MALI_GP_MMU 49
+#define INT_MALI_PP    50
+#define INT_MALI_PP_MMU 51
+
+static struct resource meson_mali_resources[] =
+{
+       MALI_GPU_RESOURCES_MALI400_MP1(0xd0060000, 
+                       INT_MALI_GP, INT_MALI_GP_MMU, INT_MALI_PP, INT_MALI_PP_MMU)
+};
+#endif
+
+static struct dev_pm_ops mali_gpu_device_type_pm_ops =
+{
+       .suspend = mali_os_suspend,
+       .resume = mali_os_resume,
+       .freeze = mali_os_freeze,
+       .thaw = mali_os_thaw,
+#ifdef CONFIG_PM_RUNTIME
+       .runtime_suspend = mali_runtime_suspend,
+       .runtime_resume = mali_runtime_resume,
+       .runtime_idle = mali_runtime_idle,
+#endif
+};
+
+static struct device_type mali_gpu_device_device_type =
+{
+       .pm = &mali_gpu_device_type_pm_ops,
+};
+
+static struct platform_device mali_gpu_device =
+{
+       .name = MALI_GPU_NAME_UTGARD,
+       .id = 0,
+
+       .dev.parent = NULL,
+
+       .dev.release = mali_platform_device_release,
+       /*
+        * We temporarily make use of a device type so that we can control the Mali power
+        * from within the mali.ko (since the default platform bus implementation will not do that).
+        * Ideally .dev.pm_domain should be used instead, as this is the new framework designed
+        * to control the power of devices.
+        */
+       .dev.type = &mali_gpu_device_device_type, /* We should probably use the pm_domain instead of type on newer kernels */
+};
+
+static struct mali_gpu_device_data mali_gpu_data =
+{
+       .shared_mem_size =512 * 1024 * 1024, /* 256MB */
+       .fb_start = 0x84000000,
+       .fb_size = 0x06000000,
+};
+
+int mali_platform_device_register(void)
+{
+       int err = -1;
+
+#      if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+       static_pp_mmu_cnt = 1;
+#      endif
+
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n"));
+
+       /* Detect present Mali GPU and connect the correct resources to the device */
+       
+       MALI_DEBUG_PRINT(4, ("Registering Mali-450 MP8 device\n"));
+       err = platform_device_add_resources(&mali_gpu_device, meson_mali_resources, sizeof(meson_mali_resources) / sizeof(meson_mali_resources[0]));
+
+       if (0 == err)
+       {
+               err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data));
+               if (0 == err)
+               {
+                       /* Register the platform device */
+                       err = platform_device_register(&mali_gpu_device);
+                       if (0 == err)
+                       {
+                               mali_platform_init();
+#ifdef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+                               pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000);
+                               pm_runtime_use_autosuspend(&(mali_gpu_device.dev));
+#endif
+                               pm_runtime_enable(&(mali_gpu_device.dev));
+#endif
+
+                               return 0;
+                       }
+               }
+
+               platform_device_unregister(&mali_gpu_device);
+       }
+
+       return err;
+}
+
+void mali_platform_device_unregister(void)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
+
+       mali_platform_deinit();
+
+       platform_device_unregister(&mali_gpu_device);
+}
+
+static void mali_platform_device_release(struct device *device)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
+}
+
+static int mali_os_suspend(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_os_suspend() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->suspend)
+       {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->suspend(device);
+       }
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
+
+       return ret;
+}
+
+static int mali_os_resume(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_os_resume() called\n"));
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->resume)
+       {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->resume(device);
+       }
+
+       return ret;
+}
+
+static int mali_os_freeze(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->freeze)
+       {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->freeze(device);
+       }
+
+       return ret;
+}
+
+static int mali_os_thaw(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->thaw)
+       {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->thaw(device);
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int mali_runtime_suspend(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->runtime_suspend)
+       {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->runtime_suspend(device);
+       }
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
+
+       return ret;
+}
+
+static int mali_runtime_resume(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->runtime_resume)
+       {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->runtime_resume(device);
+       }
+
+       return ret;
+}
+
+static int mali_runtime_idle(struct device *device)
+{
+       MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->runtime_idle)
+       {
+               /* Need to notify Mali driver about this event */
+               int ret = device->driver->pm->runtime_idle(device);
+               if (0 != ret)
+               {
+                       return ret;
+               }
+       }
+
+       pm_runtime_suspend(device);
+
+       return 0;
+}
+#endif
index 59e92c858cd2553189f447d1ae61cf02eb87c933..e42023a1e0785dc160ad71c4e18743fb09272935 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef _MALI200_REGS_H_
@@ -46,14 +46,10 @@ enum mali200_mgmt_reg
 
 enum mali200_mgmt_ctrl_mgmt {
        MALI200_REG_VAL_CTRL_MGMT_STOP_BUS         = (1<<0),
-#if defined(USING_MALI200)
        MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES     = (1<<3),
-#endif
        MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET      = (1<<5),
        MALI200_REG_VAL_CTRL_MGMT_START_RENDERING  = (1<<6),
-#if defined(USING_MALI400) || defined(USING_MALI450)
-       MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET     = (1<<7),
-#endif
+       MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET     = (1<<7), /* Only valid for Mali-300 and later */
 };
 
 enum mali200_mgmt_irq {
@@ -72,18 +68,6 @@ enum mali200_mgmt_irq {
        MALI400PP_REG_VAL_IRQ_RESET_COMPLETED       = (1<<12),
 };
 
-#if defined(USING_MALI200)
-#define MALI200_REG_VAL_IRQ_MASK_ALL  ((enum mali200_mgmt_irq) (\
-    MALI200_REG_VAL_IRQ_END_OF_FRAME                           |\
-    MALI200_REG_VAL_IRQ_END_OF_TILE                            |\
-    MALI200_REG_VAL_IRQ_HANG                                   |\
-    MALI200_REG_VAL_IRQ_FORCE_HANG                             |\
-    MALI200_REG_VAL_IRQ_BUS_ERROR                              |\
-    MALI200_REG_VAL_IRQ_BUS_STOP                               |\
-    MALI200_REG_VAL_IRQ_CNT_0_LIMIT                            |\
-    MALI200_REG_VAL_IRQ_CNT_1_LIMIT                            |\
-    MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR))
-#elif defined(USING_MALI400) || defined(USING_MALI450)
 #define MALI200_REG_VAL_IRQ_MASK_ALL  ((enum mali200_mgmt_irq) (\
     MALI200_REG_VAL_IRQ_END_OF_FRAME                           |\
     MALI200_REG_VAL_IRQ_END_OF_TILE                            |\
@@ -98,31 +82,15 @@ enum mali200_mgmt_irq {
     MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW                   |\
     MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW                    |\
     MALI400PP_REG_VAL_IRQ_RESET_COMPLETED))
-#else
-#error "No supported mali core defined"
-#endif
 
-#if defined(USING_MALI200)
 #define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\
     MALI200_REG_VAL_IRQ_END_OF_FRAME                           |\
-    MALI200_REG_VAL_IRQ_HANG                                   |\
     MALI200_REG_VAL_IRQ_FORCE_HANG                             |\
     MALI200_REG_VAL_IRQ_BUS_ERROR                              |\
-    MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR))
-#elif defined(USING_MALI400) || defined(USING_MALI450)
-#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\
-    MALI200_REG_VAL_IRQ_END_OF_FRAME                           |\
-    MALI200_REG_VAL_IRQ_HANG                                   |\
-    MALI200_REG_VAL_IRQ_FORCE_HANG                             |\
-    MALI200_REG_VAL_IRQ_BUS_ERROR                              |\
-    MALI200_REG_VAL_IRQ_BUS_STOP                               |\
     MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR                   |\
     MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND                  |\
     MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW                   |\
     MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW))
-#else
-#error "No supported mali core defined"
-#endif
 
 #define MALI200_REG_VAL_IRQ_MASK_NONE ((enum mali200_mgmt_irq)(0))
 
@@ -134,19 +102,12 @@ enum mali200_mgmt_status {
 enum mali200_render_unit
 {
        MALI200_REG_ADDR_FRAME = 0x0000,
-       MALI200_REG_ADDR_STACK = 0x0030
+       MALI200_REG_ADDR_RSW   = 0x0004,
+       MALI200_REG_ADDR_STACK = 0x0030,
+       MALI200_REG_ADDR_STACK_SIZE = 0x0034,
+       MALI200_REG_ADDR_ORIGIN_OFFSET_X  = 0x0040
 };
 
-#if defined(USING_MALI200)
-#define MALI200_NUM_REGS_FRAME ((0x04C/4)+1)
-#elif defined(USING_MALI400)
-#define MALI200_NUM_REGS_FRAME ((0x058/4)+1)
-#elif defined(USING_MALI450)
-#define MALI200_NUM_REGS_FRAME ((0x058/4)+1)
-#else
-#error "No supported mali core defined"
-#endif
-
 enum mali200_wb_unit {
     MALI200_REG_ADDR_WB0 = 0x0100,
     MALI200_REG_ADDR_WB1 = 0x0200,
@@ -157,11 +118,6 @@ enum mali200_wb_unit_regs {
        MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000,
 };
 
-/** The number of registers in one single writeback unit */
-#ifndef MALI200_NUM_REGS_WBx
-#define MALI200_NUM_REGS_WBx ((0x02C/4)+1)
-#endif
-
 /* This should be in the top 16 bit of the version register of Mali PP */
 #define MALI200_PP_PRODUCT_ID 0xC807
 #define MALI300_PP_PRODUCT_ID 0xCE07
index 21c83c0246a5259442ddc5a725ec2787807ddaa4..f4f017ae54638e2bf5148e781c1b39fb7e503512 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef _MALIGP2_CONROL_REGS_H_
@@ -60,9 +60,7 @@ typedef enum
        MALIGP2_REG_VAL_CMD_RESET                               = (1<< 5),
        MALIGP2_REG_VAL_CMD_FORCE_HANG                  = (1<< 6),
        MALIGP2_REG_VAL_CMD_STOP_BUS                    = (1<< 9),
-#if defined(USING_MALI400) || defined(USING_MALI450)
-       MALI400GP_REG_VAL_CMD_SOFT_RESET                = (1<<10),
-#endif
+       MALI400GP_REG_VAL_CMD_SOFT_RESET                = (1<<10), /* only valid for Mali-300 and later */
 } mgp_contr_reg_val_cmd;
 
 
@@ -84,7 +82,6 @@ typedef enum
 #define MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     (1 << 9)
 #define MALIGP2_REG_VAL_IRQ_SYNC_ERROR          (1 << 10)
 #define MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR       (1 << 11)
-#if defined(USING_MALI400) || defined(USING_MALI450)
 #define MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED     (1 << 12)
 #define MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD      (1 << 13)
 #define MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD     (1 << 14)
@@ -92,27 +89,8 @@ typedef enum
 #define MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW (1 << 20)
 #define MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW  (1 << 21)
 #define MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS  (1 << 22)
-#elif !defined USING_MALI200
-#error "No supported mali core defined"
-#endif
 
-/* Mask defining all IRQs in MaliGP2 */
-#if defined(USING_MALI200)
-#define MALIGP2_REG_VAL_IRQ_MASK_ALL \
-       (\
-               MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      | \
-               MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST    | \
-               MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM     | \
-               MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ          | \
-               MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ        | \
-               MALIGP2_REG_VAL_IRQ_HANG                | \
-               MALIGP2_REG_VAL_IRQ_FORCE_HANG          | \
-               MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT    | \
-               MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT    | \
-               MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     | \
-               MALIGP2_REG_VAL_IRQ_SYNC_ERROR          | \
-               MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR)
-#elif defined(USING_MALI400) || defined(USING_MALI450)
+/* Mask defining all IRQs in Mali GP */
 #define MALIGP2_REG_VAL_IRQ_MASK_ALL \
        (\
                MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      | \
@@ -134,41 +112,22 @@ typedef enum
                MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \
                MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW  | \
                MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS)
-#else
-#error "No supported mali core defined"
-#endif
 
-/* Mask defining the IRQs in MaliGP2 which we use*/
-#if defined(USING_MALI200)
+/* Mask defining the IRQs in Mali GP which we use */
 #define MALIGP2_REG_VAL_IRQ_MASK_USED \
        (\
                MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      | \
                MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST    | \
                MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM     | \
-               MALIGP2_REG_VAL_IRQ_HANG                | \
                MALIGP2_REG_VAL_IRQ_FORCE_HANG          | \
                MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     | \
-               MALIGP2_REG_VAL_IRQ_SYNC_ERROR                  | \
-               MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR)
-#elif defined(USING_MALI400) || defined(USING_MALI450)
-#define MALIGP2_REG_VAL_IRQ_MASK_USED \
-       (\
-               MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      | \
-               MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST    | \
-               MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM     | \
-               MALIGP2_REG_VAL_IRQ_HANG                | \
-               MALIGP2_REG_VAL_IRQ_FORCE_HANG          | \
-               MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     | \
-               MALIGP2_REG_VAL_IRQ_SYNC_ERROR                  | \
+               MALIGP2_REG_VAL_IRQ_SYNC_ERROR          | \
                MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR       | \
                MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD      | \
                MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD     | \
                MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \
                MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW  | \
                MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS)
-#else
-#error "No supported mali core defined"
-#endif
 
 /* Mask defining non IRQs on MaliGP2*/
 #define MALIGP2_REG_VAL_IRQ_MASK_NONE 0
index 242685348218a405dbab1c325d59111bd370ae9d..562ae2be69688f88ffaf0e2870f08a4c6dc19da8 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_timestamp.h"
index 05517260cad6631ef31e86e6880bad5172940f1c..c47b61dae2d280e9dc0f9e2b8b297c654680ea42 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_TIMESTAMP_H__
index 242685348218a405dbab1c325d59111bd370ae9d..562ae2be69688f88ffaf0e2870f08a4c6dc19da8 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #include "mali_timestamp.h"
index e6d3f2aaf5167bd8fe2f9c5eff0c69fbb921b127..598fd0e9ab70adea2fd272786b19377ec53c7f87 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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.
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
  */
 
 #ifndef __MALI_TIMESTAMP_H__
index 9ca27e1b4ae6b706dbf20d6d30a4ce9defe23f34..00471647395f6a4356eb2acbb404c51bb18e27c9 100644 (file)
@@ -14,9 +14,7 @@ CONFIG ?= aml-meson-m400-1
 TARGET_PLATFORM ?= aml-meson
 
 ifneq ($(KBUILD_SRC),)
-       ifneq ($(wildcard $(KBUILD_SRC)/$(src)),)
-               TOP_KBUILD_SRC := $(KBUILD_SRC)/
-       endif
+TOP_KBUILD_SRC := $(KBUILD_SRC)/
 endif
 
 # Validate selected config
index 6bc5044f93456d76284a6112bf6359186076a9df..eb737963729d4315aea7cf0b783a7c02f6e75a51 100644 (file)
@@ -3,6 +3,7 @@ config UMP
        tristate "UMP support"
        depends on m
        default m
+       select MALI400_UMP
        ---help---
          This enables support for the UMP memory allocation and sharing API.
 
index 3b370a102604812c689653d01cd2c3250e703e2e..83c516cf154380ba1635cef81189bba265d2e623 100644 (file)
@@ -8,9 +8,6 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 #
 
-# Skip this Makefile when included from modpost
-ifeq ($(KBUILD_EXTMOD),)
-
 # For each arch check: CROSS_COMPILE , KDIR , CFLAGS += -DARCH
 
 export ARCH ?= arm
@@ -64,5 +61,3 @@ kernelrelease:
 clean:
        $(MAKE) -C $(KDIR) M=$(CURDIR) clean
        $(MAKE) -C $(KDIR) M=$(CURDIR)/../mali clean
-
-endif
index c7545e0a9a0466997e2eb7187a38d3f39c012ad4..a8d19914387a00fd04b05e1f10cbf56653c75327 100644 (file)
@@ -13,6 +13,6 @@
 
 #define ARCH_UMP_BACKEND_DEFAULT          1
 #define ARCH_UMP_MEMORY_ADDRESS_DEFAULT   0
-#define ARCH_UMP_MEMORY_SIZE_DEFAULT 128UL * 1024UL * 1024UL
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT 256UL * 1024UL * 1024UL
 
 #endif /* __ARCH_CONFIG_H__ */