From: Nokia Date: Sat, 19 May 2012 12:52:35 +0000 (+0300) Subject: 20093908+0m5+flat+Lindent X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8cf00338a81422d2c31c40b980a0b116ef949d1;p=sgx.git 20093908+0m5+flat+Lindent * Fixes: NB#129392 - fix object reference counting in the PVR video driver * Fixes: NB#132086 - Framebuffer resets are ignored by the PVR driver * Preparation for a change in the SGX library * Fixes: NB#129389 - fix random PVR driver breakage * Fixes: NB#128247 - fix size checking for PVR memory mapping requests * Fixes: NB#126777 - PVR module can cause dead-lock at reboot time * Fixes: NB#125756 - PVR triggers a lockdep warning * Fixes: NB#111084 - SGX compilation warnings * Fixes: NB#122294 - Performance regression in SGX operations caused by DVFS * Fixes: NB#121668 - PVR: error returned by drm_ttm_create is ignored * Fixes: NB#121947 - PVR: memory should not be released twice * Fixes: NB#119655 - PVR: random allocation failure for sizes > 4k * Introduce a patch related to NB#108042 - PVR: wrapped memory space runs out (not a complete fix) * Fixes: NB#112118 - Fix PVR breakage when using DVFS * Fix crashes due to power/clock state transitions in PVR * Fixes: NB#110835 - PVR: lock dependency bug * Enable dynamic power management for SGX * upgrade to SGX 1.3 (fingers crossed) --- diff --git a/pvr/Kbuild b/pvr/Kbuild deleted file mode 100644 index 19f9a24..0000000 --- a/pvr/Kbuild +++ /dev/null @@ -1,53 +0,0 @@ -obj-m := pvrsrvkm.o - -FILES := \ -services4/srvkm/common/queue.c \ -services4/srvkm/common/hash.c \ -services4/srvkm/common/perproc.c \ -services4/srvkm/common/mem.c \ -services4/srvkm/common/power.c \ -services4/srvkm/common/deviceclass.c \ -services4/srvkm/common/metrics.c \ -services4/srvkm/common/resman.c \ -services4/srvkm/common/buffer_manager.c \ -services4/srvkm/common/pvrsrv.c \ -services4/srvkm/common/handle.c \ -services4/srvkm/common/ra.c \ -services4/srvkm/common/devicemem.c \ -services4/srvkm/env/linux/pvr_debug.c \ -services4/srvkm/env/linux/mm.c \ -services4/srvkm/env/linux/mutex.c \ -services4/srvkm/env/linux/mmap.c \ -services4/srvkm/env/linux/module.c \ -services4/srvkm/env/linux/proc.c \ -services4/srvkm/env/linux/event.c \ -services4/srvkm/env/linux/osfunc.c \ -services4/srvkm/env/linux/pvr_bridge_k.c \ -services4/srvkm/env/linux/pdump.c \ -services4/srvkm/devices/sgx/sgxtransfer.c \ -services4/srvkm/devices/sgx/sgxinit.c \ -services4/srvkm/devices/sgx/sgxutils.c \ -services4/srvkm/devices/sgx/pb.c \ -services4/srvkm/devices/sgx/sgxkick.c \ -services4/srvkm/devices/sgx/mmu.c \ -services4/srvkm/devices/sgx/sgxreset.c \ -services4/srvkm/bridged/bridged_pvr_bridge.c \ -services4/system/omap3430/sysutils_linux.c \ -services4/system/omap3430/sysconfig.c - -EXTRA_CFLAGS += -I$(src)/include4 -EXTRA_CFLAGS += -I$(src)/services4/include -EXTRA_CFLAGS += -I$(src)/services4/srvkm/include -EXTRA_CFLAGS += -I$(src)/services4/srvkm/hwdefs -EXTRA_CFLAGS += -I$(src)/services4/srvkm/bridged -EXTRA_CFLAGS += -I$(src)/services4/srvkm/devices/sgx -EXTRA_CFLAGS += -I$(src)/services4/srvkm/env/linux -EXTRA_CFLAGS += -I$(src)/services4/system/include -EXTRA_CFLAGS += -I$(src)/services4/system/omap3430 - -EXTRA_CFLAGS += $(ALL_CFLAGS) - -pvrsrvkm-y := $(FILES:.c=.o) - -obj-y := services4/3rdparty/dc_omap3430_linux/ - diff --git a/pvr/Kconfig b/pvr/Kconfig new file mode 100644 index 0000000..1a826ab --- /dev/null +++ b/pvr/Kconfig @@ -0,0 +1,4 @@ +menuconfig PVR + tristate "PowerVR Services" + depends on OMAP2_DSS + diff --git a/pvr/Makefile b/pvr/Makefile index 7f5271d..994c427 100644 --- a/pvr/Makefile +++ b/pvr/Makefile @@ -1,22 +1,77 @@ -export DISCIMAGE = /home/pratheesh/nfsexport/glibc_rootfs - -export KERNELDIR = /home1/pratheesh/workdir/opt/linux/kernel_org/REL_OMAP35x_02.01.00.04/src/kernel/linux-02.01.00.04 -export KERNEL_PATH=$(KERNELDIR) -export KERNEL_SRC=$(KERNELDIR) -export KDIR=$(KERNELDIR) - -export BUILD = debug - -export KBUILD_EXTRA_SYMBOLS = `pwd`/services4/srvkm/env/linux/kbuild/Module.symvers +PVR_SYSTEM := omap3430 + +EXTRA_CFLAGS += -D__linux__ + +obj-$(CONFIG_PVR) += \ + omaplfb.o \ + pvrsrvkm.o + +omaplfb-objs := \ + services4/3rdparty/dc_omap3430_linux/omaplfb_displayclass.o \ + services4/3rdparty/dc_omap3430_linux/omaplfb_linux.o + +pvrsrvkm-objs := \ + services4/srvkm/env/linux/osfunc.o \ + services4/srvkm/env/linux/mmap.o \ + services4/srvkm/env/linux/module.o \ + services4/srvkm/env/linux/pdump.o \ + services4/srvkm/env/linux/proc.o \ + services4/srvkm/env/linux/pvr_bridge_k.o \ + services4/srvkm/env/linux/pvr_debug.o \ + services4/srvkm/env/linux/mm.o \ + services4/srvkm/env/linux/mutex.o \ + services4/srvkm/env/linux/event.o \ + services4/srvkm/common/buffer_manager.o \ + services4/srvkm/common/devicemem.o \ + services4/srvkm/common/deviceclass.o \ + services4/srvkm/common/handle.o \ + services4/srvkm/common/hash.o \ + services4/srvkm/common/metrics.o \ + services4/srvkm/common/pvrsrv.o \ + services4/srvkm/common/queue.o \ + services4/srvkm/common/ra.o \ + services4/srvkm/common/resman.o \ + services4/srvkm/common/power.o \ + services4/srvkm/common/mem.o \ + services4/srvkm/bridged/bridged_pvr_bridge.o \ + services4/srvkm/devices/sgx/sgxinit.o \ + services4/srvkm/devices/sgx/sgxreset.o \ + services4/srvkm/devices/sgx/sgxutils.o \ + services4/srvkm/devices/sgx/sgxkick.o \ + services4/srvkm/devices/sgx/sgxtransfer.o \ + services4/srvkm/devices/sgx/mmu.o \ + services4/srvkm/devices/sgx/pb.o \ + services4/srvkm/common/perproc.o \ + services4/system/$(PVR_SYSTEM)/sysconfig.o \ + services4/system/$(PVR_SYSTEM)/sysutils.o + +ccflags-y := \ + -I$(src)/include4 \ + -I$(src)/services4/include \ + -I$(src)/services4/srvkm/env/linux \ + -I$(src)/services4/srvkm/include \ + -I$(src)/services4/srvkm/bridged \ + -I$(src)/services4/srvkm/devices/sgx \ + -I$(src)/services4/system/$(PVR_SYSTEM) \ + -I$(src)/services4/system/include \ + -I$(src)/services4/srvkm/hwdefs \ + -Iarch/arm/plat-omap/include/mach + +# Work out our origins. eurasiacon.pj is not supplied to end-users +# so instead we supply pvrversion.h. We produce pvrversion.h if +# if doesn't exist. +# +DATE := $(shell date "+%a %B %d %Z %Y" ) SGXCORE = 530 -CORE = -DSGX530 -DSUPPORT_SGX530 -DSGX_CORE_REV=103 +CORE = -DSGX530 -DSUPPORT_SGX530 -DSGX_CORE_REV=121 + +# -------------------------------------------------------------------------------- SUPPORT_SGX = 1 SUPPORT_HW_RECOVERY = 1 SUPPORT_SGX_HWPERF = 1 SYS_USING_INTERRUPTS = 1 -SUPPORT_TI_PM = 0 PVR2D_ALT_2DHW = 1 @@ -34,40 +89,47 @@ else SUPPORT_ACTIVE_POWER_MANAGEMENT = 0 endif -export PVR_BUILD_DIR := $(shell pwd) - -DATE := $(shell date "+%a %B %d %Z %Y" ) +BUILD ?= release +# The standard CFLAGS macro can be overridden on the 'make' command line. We +# put CBUILD in a separate macro so its setting doesn't get lost when a user +# *does* override CFLAGS. +# CBUILD = -DPVR_BUILD_DIR="\"$(PVR_BUILD_DIR)\"" \ - -DPVR_BUILD_DATE="\"$(DATE)\"" \ - -DPVR_BUILD_TYPE="\"$(BUILD)\"" + -DPVR_BUILD_DATE="\"$(DATE)\"" \ + -DPVR_BUILD_TYPE="\"$(BUILD)\"" + +# OPTIM contains the optimisation level in timing and release builds +OPTIM = -O2 # Don't support HW recovery on debug builds CBUILD.debug = -DDEBUG CBUILD.timing = -DTIMING CBUILD.release = -DRELEASE -CFLAGS.debug = -g -O0 -DDLL_METRIC=1 -CFLAGS.timing = $(OPTIM) -g -DDLL_METRIC=1 -DTIMING -CFLAGS.release = $(OPTIM) -g -CFLAGS = $(CFLAGS.$(BUILD)) +_CFLAGS.debug = -g -O0 -DDLL_METRIC=1 +_CFLAGS.timing = $(OPTIM) -g -DDLL_METRIC=1 -DTIMING +_CFLAGS.release = $(OPTIM) -g +_CFLAGS = $(_CFLAGS.$(BUILD)) -DSGX_DYNAMIC_TIMING_INFO +# Defaults for useful things. +# ifeq ("$(BUILD)", "debug") -DEBUG_LINUX_MEMORY_ALLOCATIONS ?= 1 -DEBUG_LINUX_MEM_AREAS ?= 1 -DEBUG_LINUX_MMAP_AREAS ?= 1 -DEBUG_LINUX_XML_PROC_FILES ?= 0 -DEBUG_LINUX_SLAB_ALLOCATIONS ?= 0 -DEBUG_BRIDGE_KM ?= 1 -DEBUG_TRACE_BRIDGE_KM ?= 0 -DEBUG_BRIDGE_KM_DISPATCH_TABLE ?= 0 +DEBUG_LINUX_MEMORY_ALLOCATIONS ?= 1 +DEBUG_LINUX_MEM_AREAS ?= 1 +DEBUG_LINUX_MMAP_AREAS ?= 1 +DEBUG_LINUX_XML_PROC_FILES ?= 0 +DEBUG_LINUX_SLAB_ALLOCATIONS ?= 0 +DEBUG_BRIDGE_KM ?= 1 +DEBUG_TRACE_BRIDGE_KM ?= 0 +DEBUG_BRIDGE_KM_DISPATCH_TABLE ?= 0 endif -TRANSFER_QUEUE ?= 1 -SUPPORT_SGX_EVENT_OBJECT ?= 1 +TRANSFER_QUEUE ?= 1 +SUPPORT_SGX_EVENT_OBJECT ?=1 SUPPORT_SECURE_HANDLES ?= 1 -SUPPORT_SRVINIT = 1 -SUPPORT_PERCONTEXT_PB = 1 +SUPPORT_SRVINIT = 1 +SUPPORT_PERCONTEXT_PB = 1 SYS_CFLAGS += -DSERVICES4 -D_XOPEN_SOURCE=600 -DPVR2D_VALIDATE_INPUT_PARAMS @@ -81,77 +143,79 @@ DISABLE_THREADS ?= 0 SYS_CFLAGS.$(SUPPORT_SRVINIT) += -DSUPPORT_SRVINIT -SYS_CFLAGS.$(SUPPORT_SGX) += -DSUPPORT_SGX -SYS_CFLAGS.$(SUPPORT_XWS) += -DSUPPORT_XWS -SYS_CFLAGS.$(PDUMP) += -DPDUMP -SYS_CFLAGS.$(SUPPORT_POWER_MANAGEMENT) += -DSUPPORT_POWER_MANAGEMENT +SYS_CFLAGS.$(SUPPORT_SGX) += -DSUPPORT_SGX +SYS_CFLAGS.$(SUPPORT_XWS) += -DSUPPORT_XWS +SYS_CFLAGS.$(PDUMP) += -DPDUMP +SYS_CFLAGS.$(SUPPORT_POWER_MANAGEMENT) += -DSUPPORT_POWER_MANAGEMENT SYS_CFLAGS.$(SUPPORT_BUFFER_CLASS) += -DSUPPORT_BUFFER_CLASS SYS_CFLAGS.$(SUPPORT_PERCONTEXT_PB) += -DSUPPORT_PERCONTEXT_PB -SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE) += -DSUPPORT_DYNAMIC_PBRESIZE +SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE) += -DSUPPORT_DYNAMIC_PBRESIZE -SYS_CFLAGS.$(USE_FBDEV) += -DUSE_FBDEV -SYS_CFLAGS.$(USE_FBDEV) += -DFBDEV_NAME="\"$(FBDEV_NAME)\"" -SYS_CFLAGS.$(SUPPORT_DYNAMIC_3DCLOCKGATING) += -DSUPPORT_DYNAMIC_3DCLOCKGATING +SYS_CFLAGS.$(USE_FBDEV) += -DUSE_FBDEV +SYS_CFLAGS.$(USE_FBDEV) += -DFBDEV_NAME="\"$(FBDEV_NAME)\"" +SYS_CFLAGS.$(SUPPORT_DYNAMIC_3DCLOCKGATING) += -DSUPPORT_DYNAMIC_3DCLOCKGATING SYS_CFLAGS.$(REENTRANCY_PROTECTION) += -DREENTRANCY_PROTECTION -SYS_CFLAGS.$(SCHEDULER_CONTROL_SUPPORT) += -DSCHEDULER_CONTROL_SUPPORT -SYS_CFLAGS.$(USE_IMG_POWER_DOMAIN_FUNCTION) += -DUSE_IMG_POWER_DOMAIN_FUNCTION +SYS_CFLAGS.$(SCHEDULER_CONTROL_SUPPORT) += -DSCHEDULER_CONTROL_SUPPORT +SYS_CFLAGS.$(USE_IMG_POWER_DOMAIN_FUNCTION) += -DUSE_IMG_POWER_DOMAIN_FUNCTION -SYS_CFLAGS.$(USE_DMALLOC) += -DDMALLOC +SYS_CFLAGS.$(USE_DMALLOC) += -DDMALLOC -SYS_CFLAGS.$(DEBUG_LINUX_MEMORY_ALLOCATIONS) += -DDEBUG_LINUX_MEMORY_ALLOCATIONS -SYS_CFLAGS.$(DEBUG_LINUX_MEM_AREAS) += -DDEBUG_LINUX_MEM_AREAS +SYS_CFLAGS.$(DEBUG_LINUX_MEMORY_ALLOCATIONS) += -DDEBUG_LINUX_MEMORY_ALLOCATIONS +SYS_CFLAGS.$(DEBUG_LINUX_MEM_AREAS) += -DDEBUG_LINUX_MEM_AREAS SYS_CFLAGS.$(DEBUG_LINUX_MMAP_AREAS) += -DDEBUG_LINUX_MMAP_AREAS SYS_CFLAGS.$(DEBUG_LINUX_XML_PROC_FILES) += -DDEBUG_LINUX_XML_PROC_FILES SYS_CFLAGS.$(DEBUG_LINUX_SLAB_ALLOCATIONS) += -DDEBUG_LINUX_SLAB_ALLOCATIONS -SYS_CFLAGS.$(DEBUG_BRIDGE_KM) += -DDEBUG_BRIDGE_KM -SYS_CFLAGS.$(DEBUG_TRACE_BRIDGE_KM) += -DDEBUG_TRACE_BRIDGE_KM -SYS_CFLAGS.$(DEBUG_BRIDGE_KM_DISPATCH_TABLE) += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE +SYS_CFLAGS.$(DEBUG_BRIDGE_KM) += -DDEBUG_BRIDGE_KM +SYS_CFLAGS.$(DEBUG_TRACE_BRIDGE_KM) += -DDEBUG_TRACE_BRIDGE_KM +SYS_CFLAGS.$(DEBUG_BRIDGE_KM_DISPATCH_TABLE) += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE -SYS_CFLAGS.$(SUPPORT_LINUX_X86_WRITECOMBINE) += -DSUPPORT_LINUX_X86_WRITECOMBINE +SYS_CFLAGS.$(SUPPORT_LINUX_X86_WRITECOMBINE) += -DSUPPORT_LINUX_X86_WRITECOMBINE SYS_CFLAGS.$(SGX_PDS_EVENTS_DISABLED) += -DSGX_PDS_EVENTS_DISABLED SYS_CFLAGS.$(USE_SUPPORT_NO_TA3D_OVERLAP) += -DUSE_SUPPORT_NO_TA3D_OVERLAP -SYS_CFLAGS.$(SUPPORT_SGX_TILING) += -DSUPPORT_SGX_TILING -SYS_CFLAGS.$(TRANSFER_QUEUE) += -DTRANSFER_QUEUE +SYS_CFLAGS.$(SUPPORT_SGX_TILING) += -DSUPPORT_SGX_TILING +SYS_CFLAGS.$(TRANSFER_QUEUE) += -DTRANSFER_QUEUE SYS_CFLAGS.$(SUPPORT_SGX_MMU_DUMMY_PAGE) += -DSUPPORT_SGX_MMU_DUMMY_PAGE SYS_CFLAGS.$(PVRSRV_USSE_EDM_STATUS_DEBUG) += -DPVRSRV_USSE_EDM_STATUS_DEBUG +SYS_CFLAGS.$(NO_HARDWARE) += -DNO_HARDWARE + SYS_CFLAGS.$(SUPPORT_DRI_DRM) += -DSUPPORT_DRI_DRM -SYS_CFLAGS.$(SYS_USING_INTERRUPTS) += -DSYS_USING_INTERRUPTS -SYS_CFLAGS.$(SUPPORT_HW_RECOVERY) += -DSUPPORT_HW_RECOVERY -SYS_CFLAGS.$(SUPPORT_ACTIVE_POWER_MANAGEMENT) += -DSUPPORT_ACTIVE_POWER_MANAGEMENT +ifneq ("$(NO_HARDWARE)", "1") +SYS_CFLAGS.$(SYS_USING_INTERRUPTS) += -DSYS_USING_INTERRUPTS +SYS_CFLAGS.$(SUPPORT_HW_RECOVERY) += -DSUPPORT_HW_RECOVERY +SYS_CFLAGS.$(SUPPORT_ACTIVE_POWER_MANAGEMENT) += -DSUPPORT_ACTIVE_POWER_MANAGEMENT +endif -SYS_CFLAGS.$(SUPPORT_SECURE_HANDLES) += -DPVR_SECURE_HANDLES +SYS_CFLAGS.$(SUPPORT_SECURE_HANDLES) += -DPVR_SECURE_HANDLES SYS_CFLAGS.$(USE_PTHREADS) += -DUSE_PTHREADS -SYS_CFLAGS.$(USE_GCC__thread_KEYWORD) += -DUSE_GCC__thread_KEYWORD -SYS_CFLAGS.$(OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP) += -DOPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP -SYS_CFLAGS.$(DISABLE_THREADS) += -DDISABLE_THREADS +SYS_CFLAGS.$(USE_GCC__thread_KEYWORD) += -DUSE_GCC__thread_KEYWORD +SYS_CFLAGS.$(OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP) += -DOPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP +SYS_CFLAGS.$(DISABLE_THREADS) += -DDISABLE_THREADS SYS_CFLAGS.$(SUPPORT_SGX_EVENT_OBJECT) += -DSUPPORT_SGX_EVENT_OBJECT -SYS_CFLAGS.$(LDM_PLATFORM) += -DLDM_PLATFORM -SYS_CFLAGS.$(LDM_PCI) += -DLDM_PCI -SYS_CFLAGS.$(PVR_MANUAL_POWER_CONTROL) += -DPVR_MANUAL_POWER_CONTROL - -SYS_CFLAGS.$(PVR2D_ALT_2DHW) += -DPVR2D_ALT_2DHW - -SYS_CFLAGS.$(SUPPORT_SGX_HWPERF) += -DSUPPORT_SGX_HWPERF +SYS_CFLAGS.$(LDM_PLATFORM) += -DLDM_PLATFORM +SYS_CFLAGS.$(LDM_PCI) += -DLDM_PCI +SYS_CFLAGS.$(PVR_MANUAL_POWER_CONTROL) += -DPVR_MANUAL_POWER_CONTROL -SYS_CFLAGS.$(SUPPORT_TI_PM) += -DSUPPORT_TI_PM +SYS_CFLAGS.$(PVR2D_ALT_2DHW) += -DPVR2D_ALT_2DHW -export ALL_CFLAGS = -DLINUX \ - $(CBUILD) $(CBUILD.$(BUILD)) \ - $(SYS_CFLAGS) $(SYS_CFLAGS.1) \ - $(MODULE_CFLAGS) $(MODULE_CFLAGS.$(BUILD)) \ - $(CORE) \ - $(CFLAGS) +SYS_CFLAGS.$(SUPPORT_SGX_HWPERF) += -DSUPPORT_SGX_HWPERF -all: - $(MAKE) -C $(KERNELDIR) M=`pwd` $* +SYS_INCLUDES = -I$(EURASIAROOT)/include4 \ + -I$(EURASIAROOT)/eurasiacon/includeext \ + -isystem $(KERNELDIR)/include -clean: - $(MAKE) -C $(KERNELDIR) M=`pwd` clean +ALL_CFLAGS_kbuild = -DLINUX \ + $(CBUILD) $(CBUILD.$(BUILD)) \ + $(SYS_CFLAGS) $(SYS_CFLAGS.1) \ + $(MODULE_CFLAGS) $(MODULE_CFLAGS.$(BUILD)) \ + $(CORE) \ + -Wall -fno-strict-aliasing \ + $(_CFLAGS) +ccflags-y += $(ALL_CFLAGS_kbuild) diff --git a/pvr/README.keep b/pvr/README.keep new file mode 100644 index 0000000..788a703 --- /dev/null +++ b/pvr/README.keep @@ -0,0 +1,48 @@ + +SGX Embedded Systems DDK for Linux kernel. +Copyright (C) 2008 Imagination Technologies Ltd. All rights reserved. +====================================================================== + + +About +------------------------------------------- + +This is the Imagination Technologies SGX DDK for the Linux kernel. + + +License +------------------------------------------- + +You may use, distribute and copy this software under the terms of +GNU General Public License version 2. + +The full GNU General Public License version 2 is included in this +distribution in the file called "COPYING". + + +Build and Install Instructions +------------------------------------------- + +For details see the "INSTALL" file. + +To build for, change to the appropriate target directory, e.g.: +$ cd eurasiacon/build/linux/platform/kbuild + +Issue the make command: +$ make BUILD=debug all + +The DDK software must be installed by the root user. Become the root user: +$ su + +Install the DDK software: +$ make install + +Become an ordinary user again: +$ exit + + +Contact information: +------------------------------------------- + +Imagination Technologies Ltd. +Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK diff --git a/pvr/bridged_pvr_bridge.c b/pvr/bridged_pvr_bridge.c index f651cf7..1e878b5 100644 --- a/pvr/bridged_pvr_bridge.c +++ b/pvr/bridged_pvr_bridge.c @@ -48,6 +48,10 @@ #define PVRMMapKVIndexAddressToMMapData(A,B,C,D,E) PVRSRV_OK #endif +#ifdef __KERNEL__ +#include /* for cache flush */ +#endif /* __KERNEL__ */ + #ifndef ENOMEM #define ENOMEM 12 #endif @@ -836,6 +840,52 @@ PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID, return 0; } +static int +FlushCacheDRI(IMG_UINT32 ui32Type, IMG_UINT32 ui32Virt, IMG_UINT32 ui32Length) +{ + switch (ui32Type) { + case DRM_PVR2D_CFLUSH_FROM_GPU: + PVR_DPF((PVR_DBG_MESSAGE, + "DRM_PVR2D_CFLUSH_FROM_GPU 0x%08x, length 0x%08x\n", + ui32Virt, ui32Length)); +#ifdef CONFIG_ARM + dmac_inv_range((const void *)ui32Virt, + (const void *)(ui32Virt + ui32Length)); +#endif + return 0; + case DRM_PVR2D_CFLUSH_TO_GPU: + PVR_DPF((PVR_DBG_MESSAGE, + "DRM_PVR2D_CFLUSH_TO_GPU 0x%08x, length 0x%08x\n", + ui32Virt, ui32Length)); +#ifdef CONFIG_ARM + dmac_clean_range((const void *)ui32Virt, + (const void *)(ui32Virt + ui32Length)); +#endif + return 0; + default: + PVR_DPF((PVR_DBG_ERROR, "Invalid cflush type 0x%x\n", + ui32Type)); + return -EINVAL; + } + + return 0; +} + +static int +PVRSRVCacheFlushDRIBW(IMG_UINT32 ui32BridgeID, + PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER * psCacheFlushIN, + PVRSRV_BRIDGE_RETURN * psRetOUT, + PVRSRV_PER_PROCESS_DATA * psPerProc) +{ + PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CACHE_FLUSH_DRM); + + psRetOUT->eError = FlushCacheDRI(psCacheFlushIN->ui32Type, + psCacheFlushIN->ui32Virt, + psCacheFlushIN->ui32Length); + + return 0; +} + static int PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID, PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY * @@ -1041,11 +1091,12 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID, psWrapExtMemIN->bPhysContig, psSysPAddr, psWrapExtMemIN->pvLinAddr, &psMemInfo); - if (psWrapExtMemIN->ui32NumPageTableEntries) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, - ui32PageTableSize, (IMG_VOID *) psSysPAddr, 0); - } if (psWrapExtMemOUT->eError != PVRSRV_OK) { + /* PVRSRVWrapExtMemoryKM failed, so clean up page list */ + if (psWrapExtMemIN->ui32NumPageTableEntries) + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32PageTableSize, + (IMG_VOID *) psSysPAddr, 0); return 0; } @@ -1089,7 +1140,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID, hKernelSyncInfo, (IMG_HANDLE) psMemInfo->psKernelSyncInfo, PVRSRV_HANDLE_TYPE_SYNC_INFO, - PVRSRV_HANDLE_ALLOC_FLAG_NONE, + PVRSRV_HANDLE_ALLOC_FLAG_MULTI, psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo); COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc); @@ -4694,6 +4745,8 @@ PVRSRV_ERROR CommonBridgeInit(IMG_VOID) PVRSRVUnmapDeviceClassMemoryBW); SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW); SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW); + SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE_FLUSH_DRM, + PVRSRVCacheFlushDRIBW); SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW); SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW); diff --git a/pvr/buffer_manager.c b/pvr/buffer_manager.c index d293915..4e0eb12 100644 --- a/pvr/buffer_manager.c +++ b/pvr/buffer_manager.c @@ -23,7 +23,6 @@ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK * ******************************************************************************/ - #include "services_headers.h" #include "sysconfig.h" @@ -611,7 +610,8 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam, psBMHeap = psBMHeap->psNext; - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psTmpBMHeap, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), + psTmpBMHeap, IMG_NULL); } if (pBMContext->psMMUContext) { @@ -638,7 +638,8 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam, } } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pBMContext, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, + IMG_NULL); return PVRSRV_OK; } @@ -855,7 +856,7 @@ ErrorExit: psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext); } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBMHeap, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL); return IMG_NULL; } @@ -889,8 +890,8 @@ IMG_VOID BM_DestroyHeap(IMG_HANDLE hDevMemHeap) if (*ppsBMHeap == psBMHeap) { *ppsBMHeap = psBMHeap->psNext; - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBMHeap, - IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(BM_HEAP), psBMHeap, IMG_NULL); break; } ppsBMHeap = &((*ppsBMHeap)->psNext); @@ -970,12 +971,29 @@ BM_Alloc(IMG_HANDLE hDevMemHeap, return IMG_TRUE; } +IMG_BOOL +BM_IsWrapped(IMG_HANDLE hDevMemHeap, + IMG_UINT32 ui32Offset, IMG_SYS_PHYADDR sSysAddr) +{ + BM_BUF *pBuf; + BM_CONTEXT *psBMContext; + BM_HEAP *psBMHeap; + + psBMHeap = (BM_HEAP *) hDevMemHeap; + psBMContext = psBMHeap->pBMContext; + sSysAddr.uiAddr += ui32Offset; + pBuf = (BM_BUF *) HASH_Retrieve(psBMContext->pBufferHash, + (IMG_UINTPTR_T) sSysAddr.uiAddr); + return pBuf != IMG_NULL; +} + IMG_BOOL BM_Wrap(IMG_HANDLE hDevMemHeap, IMG_UINT32 ui32Size, IMG_UINT32 ui32Offset, IMG_BOOL bPhysContig, IMG_SYS_PHYADDR * psSysAddr, + IMG_BOOL bFreePageList, IMG_VOID * pvCPUVAddr, IMG_UINT32 * pui32Flags, BM_HANDLE * phBuf) { BM_BUF *pBuf; @@ -1017,7 +1035,9 @@ BM_Wrap(IMG_HANDLE hDevMemHeap, if (pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == - hm_wrapped_virtaddr)) { + hm_wrapped_virtaddr + || pBuf->pMapping->eCpuMemoryOrigin == + hm_wrapped_scatter)) { PVR_DPF((PVR_DBG_MESSAGE, "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)", ui32Size, ui32Offset, sHashAddress.uiAddr)); @@ -1027,6 +1047,12 @@ BM_Wrap(IMG_HANDLE hDevMemHeap, if (pui32Flags) *pui32Flags = uFlags; + /* reusing previous mapping, free the page list */ + if (bFreePageList && psSysAddr) + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32MappingSize / HOST_PAGESIZE() * + sizeof(IMG_SYS_PHYADDR), + (IMG_VOID *) psSysAddr, 0); return IMG_TRUE; } } @@ -1049,18 +1075,13 @@ BM_Wrap(IMG_HANDLE hDevMemHeap, } if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped - || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) { - - PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == - pBuf->CpuPAddr.uiAddr); - + || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr + || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_scatter) { + pBuf->uHashKey = (IMG_UINTPTR_T) sHashAddress.uiAddr; if (!HASH_Insert - (psBMContext->pBufferHash, - (IMG_UINTPTR_T) sHashAddress.uiAddr, + (psBMContext->pBufferHash, pBuf->uHashKey, (IMG_UINTPTR_T) pBuf)) { FreeBuf(pBuf, uFlags); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, - IMG_NULL); PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED")); return IMG_FALSE; } @@ -1075,6 +1096,9 @@ BM_Wrap(IMG_HANDLE hDevMemHeap, if (pui32Flags) *pui32Flags = uFlags; + /* take ownership of the list if requested so */ + if (bFreePageList && psSysAddr) + pBuf->pvPageList = (void *)psSysAddr; return IMG_TRUE; } @@ -1082,10 +1106,16 @@ void BM_Free(BM_HANDLE hBuf, IMG_UINT32 ui32Flags) { BM_BUF *pBuf = (BM_BUF *) hBuf; SYS_DATA *psSysData; - IMG_SYS_PHYADDR sHashAddr; PVR_DPF((PVR_DBG_MESSAGE, "BM_Free (h=%08X)", hBuf)); + /* Calling BM_Free with NULL hBuf is either a bug or out-of-memory condition. + * Bail out if in debug mode, continue in release builds */ PVR_ASSERT(pBuf != IMG_NULL); +#if !defined(DEBUG) + if (!pBuf) { + return; + } +#endif if (SysAcquireData(&psSysData) != PVRSRV_OK) return; @@ -1093,16 +1123,20 @@ void BM_Free(BM_HANDLE hBuf, IMG_UINT32 ui32Flags) pBuf->ui32RefCount--; if (pBuf->ui32RefCount == 0) { + void *pPageList = pBuf->pvPageList; + IMG_UINT32 ui32ListSize = + pBuf->pMapping->uSize / HOST_PAGESIZE() * + sizeof(IMG_SYS_PHYADDR); if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped - || pBuf->pMapping->eCpuMemoryOrigin == - hm_wrapped_virtaddr) { - sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr); - + || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr + || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_scatter) { HASH_Remove(pBuf->pMapping->pBMHeap->pBMContext-> - pBufferHash, - (IMG_UINTPTR_T) sHashAddr.uiAddr); + pBufferHash, pBuf->uHashKey); } FreeBuf(pBuf, ui32Flags); + if (pPageList) + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32ListSize, + pPageList, 0); } } diff --git a/pvr/buffer_manager.h b/pvr/buffer_manager.h index 1523bce..709b59f 100644 --- a/pvr/buffer_manager.h +++ b/pvr/buffer_manager.h @@ -67,6 +67,10 @@ extern "C" { BM_MAPPING *pMapping; IMG_UINT32 ui32RefCount; + IMG_UINTPTR_T uHashKey; + void *pvKernelSyncInfo; + void *pvPageList; + IMG_HANDLE hOSWrapMem; } BM_BUF; struct _BM_HEAP_ { @@ -132,12 +136,17 @@ extern "C" { IMG_UINT32 * pui32Flags, IMG_UINT32 uDevVAddrAlignment, BM_HANDLE * phBuf); + IMG_BOOL + BM_IsWrapped(IMG_HANDLE hDevMemHeap, + IMG_UINT32 ui32Offset, IMG_SYS_PHYADDR sSysAddr); + IMG_BOOL BM_Wrap(IMG_HANDLE hDevMemHeap, IMG_UINT32 ui32Size, IMG_UINT32 ui32Offset, IMG_BOOL bPhysContig, IMG_SYS_PHYADDR * psSysAddr, + IMG_BOOL bFreePageList, IMG_VOID * pvCPUVAddr, IMG_UINT32 * pui32Flags, BM_HANDLE * phBuf); diff --git a/pvr/deviceclass.c b/pvr/deviceclass.c index 1385115..f041255 100644 --- a/pvr/deviceclass.c +++ b/pvr/deviceclass.c @@ -217,11 +217,13 @@ PVRSRV_ERROR PVRSRVRegisterDCDeviceKM(PVRSRV_DC_SRV2DISP_KMJTABLE * psFuncTable, ErrorExit: if (psDCInfo->psFuncTable) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo->psFuncTable, - IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), + psDCInfo->psFuncTable, IMG_NULL); } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), + psDCInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } @@ -273,9 +275,12 @@ FoundDevice: psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice; PVR_ASSERT(psDCInfo->ui32RefCount == 0); FreeDeviceID(psSysData, ui32DevIndex); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo->psFuncTable, IMG_NULL); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo, IMG_NULL); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDeviceNode, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), + psDCInfo->psFuncTable, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), + psDCInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), + psDeviceNode, IMG_NULL); return PVRSRV_OK; } @@ -344,11 +349,13 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM(PVRSRV_BC_SRV2BUFFER_KMJTABLE * ErrorExit: if (psBCInfo->psFuncTable) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psFuncTable, - IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), + psBCInfo->psFuncTable, IMG_NULL); } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), + psBCInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } @@ -397,9 +404,13 @@ FoundDevice: FreeDeviceID(psSysData, ui32DevIndex); psBCInfo = (PVRSRV_BUFFERCLASS_INFO *) psDevNode->pvDevice; - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psFuncTable, IMG_NULL); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo, IMG_NULL); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDevNode, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, + IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), + psBCInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), + psDevNode, IMG_NULL); return PVRSRV_OK; } @@ -442,7 +453,9 @@ static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam, psDCInfo->hExtDevice = IMG_NULL; } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCPerContextInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), + psDCPerContextInfo, IMG_NULL); return PVRSRV_OK; } @@ -716,7 +729,8 @@ static PVRSRV_ERROR DestroyDCSwapChainCallBack(IMG_PVOID pvParam, } } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), + psSwapChain, IMG_NULL); return eError; } @@ -856,7 +870,8 @@ ErrorExit: } if (psSwapChain) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), + psSwapChain, IMG_NULL); } return eError; @@ -1338,12 +1353,16 @@ static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam, } if (psBCInfo->psBuffer) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, - psBCInfo->psBuffer, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_BC_BUFFER) * + psBCInfo->ui32BufferCount, psBCInfo->psBuffer, + IMG_NULL); } } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCPerContextInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), + psBCPerContextInfo, IMG_NULL); return PVRSRV_OK; } @@ -1360,6 +1379,7 @@ IMG_EXPORT SYS_DATA *psSysData; IMG_UINT32 i; PVRSRV_ERROR eError; + BUFFER_INFO sBufferInfo; if (!phDeviceKM) { PVR_DPF((PVR_DBG_ERROR, @@ -1405,8 +1425,6 @@ FoundDevice: OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); if (psBCInfo->ui32RefCount++ == 0) { - BUFFER_INFO sBufferInfo; - psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie; PVR_ASSERT(psDeviceNode != IMG_NULL); @@ -1510,7 +1528,9 @@ ErrorExit: } if (psBCInfo->psBuffer) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psBuffer, + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_BC_BUFFER) * + sBufferInfo.ui32BufferCount, psBCInfo->psBuffer, IMG_NULL); } diff --git a/pvr/devicemem.c b/pvr/devicemem.c index 88cc6f3..d6a2de5 100644 --- a/pvr/devicemem.c +++ b/pvr/devicemem.c @@ -33,6 +33,8 @@ #include "sgxapi_km.h" #include "pvr_bridge_km.h" +#include "linux/kernel.h" + static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie, IMG_HANDLE hDevMemHeap, IMG_UINT32 ui32Flags, @@ -306,7 +308,8 @@ static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie, if (!bBMError) { PVR_DPF((PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed")); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } @@ -321,8 +324,6 @@ static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie, psMemInfo->ui32AllocSize = ui32Size; - psMemInfo->pvSysBackupBuffer = IMG_NULL; - *ppsMemInfo = psMemInfo; return (PVRSRV_OK); @@ -340,13 +341,8 @@ static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO * psMemInfo) BM_Free(hBuffer, psMemInfo->ui32Flags); - if (psMemInfo->pvSysBackupBuffer) { - - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, - psMemInfo->pvSysBackupBuffer, IMG_NULL); - } - - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), + psMemInfo, IMG_NULL); return (PVRSRV_OK); } @@ -391,7 +387,8 @@ IMG_EXPORT PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSyncInfoKM: Failed to alloc memory")); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psKernelSyncInfo, + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } @@ -426,7 +423,8 @@ IMG_EXPORT psKernelSyncInfo) { FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psKernelSyncInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO), + psKernelSyncInfo, IMG_NULL); return PVRSRV_OK; } @@ -592,19 +590,16 @@ static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam, { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam; - IMG_HANDLE hOSWrapMem; + IMG_HANDLE hOSWrapMem = IMG_NULL; + BM_BUF *psBMBuf; PVR_UNREFERENCED_PARAMETER(ui32Param); - hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem; + psBMBuf = (BM_BUF *) psMemInfo->sMemBlk.hBuffer; - if (psMemInfo->psKernelSyncInfo) { + if ((psBMBuf->ui32RefCount == 1) && (psMemInfo->psKernelSyncInfo)) { eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo); - } - - if (psMemInfo->sMemBlk.psIntSysPAddr) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, - psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL); + hOSWrapMem = psBMBuf->hOSWrapMem; } if (eError == PVRSRV_OK) { @@ -644,16 +639,21 @@ IMG_EXPORT IMG_VOID *pvPageAlignedCPUVAddr; IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL; IMG_HANDLE hOSWrapMem = IMG_NULL; + BM_BUF *psBMBuf; + IMG_SYS_PHYADDR *pPageList = psExtSysPAddr; + IMG_UINT32 ui32PageCount; psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie; PVR_ASSERT(psDeviceNode != IMG_NULL); + psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; + hDevMemHeap = + psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo-> + ui32MappingHeapID].hDevMemHeap; - if (pvLinAddr) { - IMG_UINT32 ui32PageCount; + ui32PageCount = + HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize; - ui32PageCount = - HOST_PAGEALIGN(ui32ByteSize + - ui32PageOffset) / ui32HostPageSize; + if (pvLinAddr) { pvPageAlignedCPUVAddr = (IMG_VOID *) ((IMG_UINT8 *) pvLinAddr - ui32PageOffset); @@ -666,8 +666,9 @@ IMG_EXPORT return PVRSRV_ERROR_OUT_OF_MEMORY; } + /* let's start by getting the address of the first page */ eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, - ui32PageCount * ui32HostPageSize, + ui32HostPageSize, psIntSysPAddr, &hOSWrapMem); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, @@ -675,17 +676,34 @@ IMG_EXPORT eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase1; } + /* now check if this memory address is already wrapped */ + if (BM_IsWrapped(hDevMemHeap, ui32PageOffset, psIntSysPAddr[0])) { + /* already wrapped */ + OSReleasePhysPageAddr(hOSWrapMem); + hOSWrapMem = IMG_NULL; + } else if (ui32PageCount > 1) { + OSReleasePhysPageAddr(hOSWrapMem); + hOSWrapMem = IMG_NULL; + /* the memory is going to wrapped for the first time, + * so we need full page list */ + eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, + ui32PageCount * + ui32HostPageSize, + psIntSysPAddr, + &hOSWrapMem); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); + eError = PVRSRV_ERROR_OUT_OF_MEMORY; + goto ErrorExitPhase1; + } + } psExtSysPAddr = psIntSysPAddr; } else { } - psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; - hDevMemHeap = - psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo-> - ui32MappingHeapID].hDevMemHeap; - if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **) & psMemInfo, IMG_NULL) != PVRSRV_OK) { @@ -704,18 +722,34 @@ IMG_EXPORT ui32PageOffset, bPhysContig, psExtSysPAddr, - IMG_NULL, &psMemInfo->ui32Flags, &hBuffer); + IMG_TRUE, IMG_NULL, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { - PVR_DPF((PVR_DBG_ERROR, - "PVRSRVWrapExtMemoryKM: BM_Wrap Failed")); - eError = PVRSRV_ERROR_BAD_MAPPING; - goto ErrorExitPhase2; + /* Alloc failed from current mapping heap, try the other one */ + psDevMemoryInfo->ui32MappingHeapID = + psDevMemoryInfo->ui32MappingHeapID == + SGX_GENERAL_MAPPING_HEAP_ID ? SGX_ALT_MAPPING_HEAP_ID : + SGX_GENERAL_MAPPING_HEAP_ID; + hDevMemHeap = + psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo-> + ui32MappingHeapID]. + hDevMemHeap; + bBMError = + BM_Wrap(hDevMemHeap, ui32ByteSize, ui32PageOffset, + bPhysContig, psExtSysPAddr, IMG_TRUE, IMG_NULL, + &psMemInfo->ui32Flags, &hBuffer); + if (!bBMError) { + PVR_DPF((PVR_DBG_ERROR, + "PVRSRVWrapExtMemoryKM: BM_Wrap Failed")); + eError = PVRSRV_ERROR_BAD_MAPPING; + goto ErrorExitPhase2; + } } + /* wrap was successful and BM_Wrap has taken ownership of the page list, + * clear psIntSysPAddr here, so we don't double free the memory */ + psIntSysPAddr = IMG_NULL; psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); - psMemBlock->hOSWrapMem = hOSWrapMem; - psMemBlock->psIntSysPAddr = psIntSysPAddr; psMemBlock->hBuffer = (IMG_HANDLE) hBuffer; @@ -723,21 +757,33 @@ IMG_EXPORT psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; - psMemInfo->pvSysBackupBuffer = IMG_NULL; - psBMHeap = (BM_HEAP *) hDevMemHeap; hDevMemContext = (IMG_HANDLE) psBMHeap->pBMContext; - eError = PVRSRVAllocSyncInfoKM(hDevCookie, - hDevMemContext, - &psMemInfo->psKernelSyncInfo); - if (eError != PVRSRV_OK) { - goto ErrorExitPhase2; + psBMBuf = (BM_BUF *) hBuffer; + if (psBMBuf->ui32RefCount == 1) { + eError = PVRSRVAllocSyncInfoKM(hDevCookie, + hDevMemContext, + &psMemInfo->psKernelSyncInfo); + if (eError != PVRSRV_OK) { + goto ErrorExitPhase2; + } + psBMBuf->pvKernelSyncInfo = psMemInfo->psKernelSyncInfo; + psBMBuf->hOSWrapMem = hOSWrapMem; + } else { + psMemInfo->psKernelSyncInfo = psBMBuf->pvKernelSyncInfo; } psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0, UnwrapExtMemoryCallBack); + /* check if we were passed a page list + * but we didn't use use it */ + if (pPageList && (pPageList != psExtSysPAddr)) { + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32PageCount * sizeof(IMG_SYS_PHYADDR), + (IMG_VOID *) pPageList, 0); + } *ppsMemInfo = psMemInfo; @@ -748,13 +794,13 @@ ErrorExitPhase2: FreeDeviceMem(psMemInfo); } - if (psIntSysPAddr) { + if (hOSWrapMem) OSReleasePhysPageAddr(hOSWrapMem); - } - ErrorExitPhase1: if (psIntSysPAddr) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psIntSysPAddr, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32PageCount * sizeof(IMG_SYS_PHYADDR), + psIntSysPAddr, IMG_NULL); } return eError; @@ -778,11 +824,6 @@ static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam, PVR_UNREFERENCED_PARAMETER(ui32Param); - if (psMemInfo->sMemBlk.psIntSysPAddr) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, - psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL); - } - return FreeDeviceMem(psMemInfo); } @@ -874,6 +915,7 @@ IMG_EXPORT ui32PageOffset, IMG_FALSE, psSysPAddr, + IMG_TRUE, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); @@ -889,16 +931,12 @@ IMG_EXPORT psMemBlock->hBuffer = (IMG_HANDLE) hBuffer; - psMemBlock->psIntSysPAddr = psSysPAddr; - psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM; psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize; psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo; - psMemInfo->pvSysBackupBuffer = IMG_NULL; - psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_MAPPING, psMemInfo, 0, @@ -912,12 +950,15 @@ ErrorExit: if (psSysPAddr) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSysPAddr, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + ui32PageCount * sizeof(IMG_SYS_PHYADDR), psSysPAddr, + IMG_NULL); } if (psMemInfo) { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } return eError; @@ -991,8 +1032,8 @@ PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc, psBMContext = (BM_CONTEXT *) psDeviceClassBuffer->hDevMemContext; psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo; hDevMemHeap = - psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo-> - ui32MappingHeapID].hDevMemHeap; + psDevMemoryInfo->psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID]. + hDevMemHeap; ui32Offset = ((IMG_UINT32) pvCPUVAddr) & (ui32PageSize - 1); pvPageAlignedCPUVAddr = @@ -1015,13 +1056,15 @@ PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc, ui32Offset, bPhysContig, psSysPAddr, + IMG_FALSE, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed")); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); return PVRSRV_ERROR_BAD_MAPPING; } @@ -1036,8 +1079,6 @@ PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc, psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo; - psMemInfo->pvSysBackupBuffer = IMG_NULL; - psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0, diff --git a/pvr/env_data.h b/pvr/env_data.h index ecfaa59..a535a0f 100644 --- a/pvr/env_data.h +++ b/pvr/env_data.h @@ -29,6 +29,7 @@ #include #include +#include #define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000 #define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000 @@ -46,7 +47,11 @@ typedef struct _ENV_DATA_TAG { IMG_BOOL bMISRInstalled; IMG_UINT32 ui32IRQ; IMG_VOID *pvISRCookie; - struct tasklet_struct sMISRTasklet; + struct workqueue_struct *psMISRWorkqueue; + struct work_struct sMISRWork; + struct workqueue_struct *psPerfWorkqueue; + struct delayed_work sPerfWork; + IMG_VOID *pvSysData; /*for MISR work */ } ENV_DATA; #endif diff --git a/pvr/event.c b/pvr/event.c index 61bcc5a..cb152c3 100644 --- a/pvr/event.c +++ b/pvr/event.c @@ -69,7 +69,7 @@ typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG { typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG { atomic_t sTimeStamp; IMG_UINT32 ui32TimeStampPrevious; -#if DEBUG +#ifdef DEBUG unsigned int ui32Stats; #endif wait_queue_head_t sWait; @@ -126,7 +126,7 @@ PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, if (hOSEventObject) { PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject; -#if DEBUG +#ifdef DEBUG PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %lu", psLinuxEventObject->ui32Stats)); @@ -154,7 +154,7 @@ static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, list_del(&psLinuxEventObject->sList); write_unlock_bh(&psLinuxEventObjectList->sLock); -#if DEBUG +#ifdef DEBUG PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %lu", psLinuxEventObject->ui32Stats)); @@ -196,7 +196,7 @@ PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, atomic_set(&psLinuxEventObject->sTimeStamp, 0); psLinuxEventObject->ui32TimeStampPrevious = 0; -#if DEBUG +#ifdef DEBUG psLinuxEventObject->ui32Stats = 0; #endif init_waitqueue_head(&psLinuxEventObject->sWait); @@ -261,7 +261,7 @@ PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, ui32TimeOutJiffies = schedule_timeout(ui32TimeOutJiffies); -#if DEBUG +#ifdef DEBUG psLinuxEventObject->ui32Stats++; #endif LinuxLockMutex(&gPVRSRVLock); diff --git a/pvr/hash.c b/pvr/hash.c index 92acdeb..3058f2c 100644 --- a/pvr/hash.c +++ b/pvr/hash.c @@ -166,7 +166,8 @@ static IMG_BOOL _Resize(HASH_TABLE * pHash, IMG_UINT32 uNewSize) ppNewTable[uIndex] = IMG_NULL; _Rehash(pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pHash->ppBucketTable, + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(BUCKET *) * pHash->uSize, pHash->ppBucketTable, IMG_NULL); pHash->ppBucketTable = ppNewTable; pHash->uSize = uNewSize; @@ -224,7 +225,8 @@ IMG_VOID HASH_Delete(HASH_TABLE * pHash) PVR_DPF((PVR_DBG_MESSAGE, "HASH_Delete")); PVR_ASSERT(pHash->uCount == 0); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pHash->ppBucketTable, + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(BUCKET *) * pHash->uSize, pHash->ppBucketTable, IMG_NULL); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(HASH_TABLE), pHash, IMG_NULL); diff --git a/pvr/mmap.c b/pvr/mmap.c index 8c5b2e5..09c9431 100644 --- a/pvr/mmap.c +++ b/pvr/mmap.c @@ -53,7 +53,6 @@ #include "pvr_debug.h" #include "osfunc.h" #include "proc.h" -#include "mutex.h" static PKV_OFFSET_STRUCT FindOffsetStructFromLinuxMemArea(LinuxMemArea * psLinuxMemArea); @@ -70,6 +69,7 @@ static PKV_OFFSET_STRUCT FindOffsetStructByMMapOffset(IMG_UINT32 ui32Offset); static IMG_BOOL DoMapToUser(LinuxMemArea * psLinuxMemArea, struct vm_area_struct *ps_vma, IMG_UINT32 ui32ByteOffset, IMG_UINT32 ui32Size); +static IMG_BOOL CheckSize(LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32Size); #if defined(DEBUG_LINUX_MMAP_AREAS) static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off); @@ -83,8 +83,6 @@ open: MMapVOpen, close: MMapVClose }; -extern PVRSRV_LINUX_MUTEX gPVRSRVLock; - static PKV_OFFSET_STRUCT g_psKVOffsetTable = 0; static LinuxKMemCache *g_psMemmapCache = 0; #if defined(DEBUG_LINUX_MMAP_AREAS) @@ -92,6 +90,8 @@ static IMG_UINT32 g_ui32RegisteredAreas = 0; static IMG_UINT32 g_ui32TotalByteSize = 0; #endif +static struct rw_semaphore g_mmap_sem; + IMG_VOID PVRMMapInit(IMG_VOID) { g_psKVOffsetTable = 0; @@ -106,6 +106,7 @@ IMG_VOID PVRMMapInit(IMG_VOID) PVR_DPF((PVR_DBG_ERROR, "%s: failed to allocate kmem_cache", __FUNCTION__)); } + init_rwsem(&g_mmap_sem); } IMG_VOID PVRMMapCleanup(void) @@ -143,24 +144,27 @@ PVRMMapRegisterArea(const IMG_CHAR * pszName, LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32AllocFlags) { PKV_OFFSET_STRUCT psOffsetStruct; - + PVRSRV_ERROR iError = PVRSRV_OK; PVR_DPF((PVR_DBG_MESSAGE, "%s(%s, psLinuxMemArea=%p, ui32AllocFlags=0x%8lx)", __FUNCTION__, pszName, psLinuxMemArea, ui32AllocFlags)); + down_write(&g_mmap_sem); psOffsetStruct = FindOffsetStructFromLinuxMemArea(psLinuxMemArea); if (psOffsetStruct) { PVR_DPF((PVR_DBG_ERROR, "PVRMMapRegisterArea: psLinuxMemArea=%p is already registered", psOffsetStruct->psLinuxMemArea)); - return PVRSRV_ERROR_INVALID_PARAMS; + iError = PVRSRV_ERROR_INVALID_PARAMS; + goto register_exit; } psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL); if (!psOffsetStruct) { PVR_DPF((PVR_DBG_ERROR, "PVRMMapRegisterArea: Couldn't alloc another mapping record from cache")); - return PVRSRV_ERROR_OUT_OF_MEMORY; + iError = PVRSRV_ERROR_OUT_OF_MEMORY; + goto register_exit; } psOffsetStruct->ui32MMapOffset = GetFirstFreePageAlignedNumber(); @@ -195,14 +199,17 @@ PVRMMapRegisterArea(const IMG_CHAR * pszName, psOffsetStruct->psNext = g_psKVOffsetTable; g_psKVOffsetTable = psOffsetStruct; - - return PVRSRV_OK; +register_exit: + up_write(&g_mmap_sem); + return iError; } PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea) { PKV_OFFSET_STRUCT *ppsOffsetStruct, psOffsetStruct; + PVRSRV_ERROR iError = PVRSRV_OK; + down_write(&g_mmap_sem); for (ppsOffsetStruct = &g_psKVOffsetTable; (psOffsetStruct = *ppsOffsetStruct); ppsOffsetStruct = &(*ppsOffsetStruct)->psNext) { @@ -215,7 +222,8 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea) PVR_DPF((PVR_DBG_ERROR, "%s: Registration for psLinuxMemArea = 0x%p not found", __FUNCTION__, psLinuxMemArea)); - return PVRSRV_ERROR_BAD_MAPPING; + iError = PVRSRV_ERROR_BAD_MAPPING; + goto unregister_exit; } #if defined(DEBUG_LINUX_MMAP_AREAS) @@ -223,7 +231,8 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea) PVR_DPF((PVR_DBG_ERROR, "%s: Unregistering still-mapped area! (psLinuxMemArea=0x%p)\n", __FUNCTION__, psOffsetStruct->psLinuxMemArea)); - return PVRSRV_ERROR_BAD_MAPPING; + iError = PVRSRV_ERROR_BAD_MAPPING; + goto unregister_exit; } g_ui32RegisteredAreas--; @@ -243,7 +252,9 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea) KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct); - return PVRSRV_OK; +unregister_exit: + up_write(&g_mmap_sem); + return iError; } static PKV_OFFSET_STRUCT @@ -291,11 +302,14 @@ PVRMMapKVIndexAddressToMMapData(IMG_VOID * pvKVIndexAddress, IMG_UINT32 * pui32RealByteSize) { PKV_OFFSET_STRUCT psOffsetStruct; + PVRSRV_ERROR iError = PVRSRV_OK; + down_read(&g_mmap_sem); psOffsetStruct = FindOffsetStructByKVIndexAddress(pvKVIndexAddress, ui32Size); if (!psOffsetStruct) { - return PVRSRV_ERROR_BAD_MAPPING; + iError = PVRSRV_ERROR_BAD_MAPPING; + goto indexaddress_exit; } *pui32MMapOffset = psOffsetStruct->ui32MMapOffset; @@ -304,7 +318,9 @@ PVRMMapKVIndexAddressToMMapData(IMG_VOID * pvKVIndexAddress, psOffsetStruct->psLinuxMemArea, pui32RealByteSize, pui32ByteOffset); - return PVRSRV_OK; +indexaddress_exit: + up_read(&g_mmap_sem); + return iError; } static PKV_OFFSET_STRUCT @@ -398,10 +414,8 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma) PKV_OFFSET_STRUCT psCurrentRec = NULL; int iRetVal = 0; - LinuxLockMutex(&gPVRSRVLock); - ulBytes = ps_vma->vm_end - ps_vma->vm_start; - + down_read(&g_mmap_sem); PVR_DPF((PVR_DBG_MESSAGE, "%s: Recieved mmap(2) request with a ui32MMapOffset=0x%08lx," " and ui32ByteSize=%ld(0x%08lx)\n", __FUNCTION__, @@ -412,7 +426,7 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma) PVR_DPF((PVR_DBG_ERROR, "PVRMMap: Error - Cannot mmap non-shareable writable areas.")); iRetVal = -EINVAL; - goto unlock_and_return; + goto pvrmmap_exit; } psCurrentRec = @@ -422,10 +436,14 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma) "PVRMMap: Error - Attempted to mmap unregistered area at vm_pgoff=%ld", ps_vma->vm_pgoff)); iRetVal = -EINVAL; - goto unlock_and_return; + goto pvrmmap_exit; } PVR_DPF((PVR_DBG_MESSAGE, "%s: > psCurrentRec->psLinuxMemArea=%p\n", __FUNCTION__, psCurrentRec->psLinuxMemArea)); + if (!CheckSize(psCurrentRec->psLinuxMemArea, ulBytes)) { + iRetVal = -EINVAL; + goto pvrmmap_exit; + } ps_vma->vm_flags |= VM_RESERVED; ps_vma->vm_flags |= VM_IO; @@ -476,7 +494,7 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma) if (!DoMapToUser(psCurrentRec->psLinuxMemArea, ps_vma, 0, ulBytes)) { iRetVal = -EAGAIN; - goto unlock_and_return; + goto pvrmmap_exit; } MMapVOpen(ps_vma); @@ -484,10 +502,8 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma) PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n", __FUNCTION__, ps_vma->vm_pgoff)); -unlock_and_return: - - LinuxUnLockMutex(&gPVRSRVLock); - +pvrmmap_exit: + up_read(&g_mmap_sem); return iRetVal; } @@ -565,6 +581,30 @@ DoMapToUser(LinuxMemArea * psLinuxMemArea, return IMG_TRUE; } +static IMG_BOOL +CheckSize(LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32ByteSize) +{ + IMG_CPU_PHYADDR CpuPAddr; + IMG_UINT32 ui32PageAlignmentOffset; + IMG_UINT32 ui32RealByteSize; + CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0); + ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr); + ui32RealByteSize = + PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset); + if (ui32RealByteSize < ui32ByteSize) { + PVR_DPF((PVR_DBG_ERROR, + "Cannot mmap %ld bytes from: %-8p %-8p %08lx %-8ld %-24s\n", + ui32ByteSize, + psLinuxMemArea, + LinuxMemAreaToCpuVAddr(psLinuxMemArea), + LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0).uiAddr, + psLinuxMemArea->ui32ByteSize, + LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType))); + return IMG_FALSE; + } + return IMG_TRUE; +} + static void MMapVOpen(struct vm_area_struct *ps_vma) { #if defined(DEBUG_LINUX_MMAP_AREAS) @@ -613,8 +653,7 @@ static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off) PKV_OFFSET_STRUCT psOffsetStruct; off_t Ret; - LinuxLockMutex(&gPVRSRVLock); - + down_read(&g_mmap_sem); if (!off) { Ret = printAppend(buffer, size, 0, #if !defined(DEBUG_LINUX_XML_PROC_FILES) @@ -682,8 +721,7 @@ static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off) HAPFlagsToString(psOffsetStruct->ui32AllocFlags)); unlock_and_return: - - LinuxUnLockMutex(&gPVRSRVLock); + up_read(&g_mmap_sem); return Ret; } #endif diff --git a/pvr/mmu.c b/pvr/mmu.c index 17c4a1f..5b638b1 100644 --- a/pvr/mmu.c +++ b/pvr/mmu.c @@ -1171,7 +1171,8 @@ MMU_HEAP *MMU_Create(MMU_CONTEXT * psMMUContext, if (!bRes) { PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to _AllocPageTables failed")); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, + IMG_NULL); return IMG_NULL; } @@ -1187,7 +1188,8 @@ MMU_HEAP *MMU_Create(MMU_CONTEXT * psMMUContext, PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed")); _DeferredFreePageTables(pMMUHeap); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), + pMMUHeap, IMG_NULL); return IMG_NULL; } #if 0 @@ -1234,7 +1236,8 @@ IMG_VOID MMU_Delete(MMU_HEAP * pMMUHeap) DisableHostAccess(pMMUHeap->psMMUContext); #endif - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), + pMMUHeap, IMG_NULL); } } diff --git a/pvr/module.c b/pvr/module.c index 2084705..ae6e03b 100644 --- a/pvr/module.c +++ b/pvr/module.c @@ -90,8 +90,8 @@ EXPORT_SYMBOL(PVRGetBufferClassJTable); static int AssignedMajorNumber; -extern int PVRSRV_BridgeDispatchKM(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +extern long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, + unsigned long arg); static int PVRSRVOpen(struct inode *pInode, struct file *pFile); static int PVRSRVRelease(struct inode *pInode, struct file *pFile); @@ -99,7 +99,7 @@ PVRSRV_LINUX_MUTEX gPVRSRVLock; static struct file_operations pvrsrv_fops = { owner: THIS_MODULE, -ioctl: PVRSRV_BridgeDispatchKM, +unlocked_ioctl:PVRSRV_BridgeDispatchKM, open: PVRSRVOpen, release:PVRSRVRelease, mmap: PVRMMap, @@ -192,6 +192,8 @@ static int __devinit PVRSRVDriverProbe(LDM_DEV * pDevice, PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice)); + pDevice->dev.driver_data = NULL; + #if 0 if (PerDeviceSysInitialise((IMG_PVOID) pDevice) != PVRSRV_OK) { @@ -415,6 +417,8 @@ static int __init PVRCore_Init(void) goto init_failed; } + powervr_device.dev.devt = MKDEV(AssignedMajorNumber, 0); + if ((error = platform_device_register(&powervr_device)) != 0) { platform_driver_unregister(&powervr_driver); diff --git a/pvr/modules.order b/pvr/modules.order deleted file mode 100644 index 33eed37..0000000 --- a/pvr/modules.order +++ /dev/null @@ -1,2 +0,0 @@ -kernel//home/pratheesh/webkit/release_work/omap3-sgx-modules-1.3.13.1607/services4/3rdparty/dc_omap3430_linux/omaplfb.ko -kernel//home/pratheesh/webkit/release_work/omap3-sgx-modules-1.3.13.1607/pvrsrvkm.ko diff --git a/pvr/omaplfb.h b/pvr/omaplfb.h index d10cdd7..43241bb 100644 --- a/pvr/omaplfb.h +++ b/pvr/omaplfb.h @@ -159,7 +159,7 @@ typedef struct OMAPLFB_DEVINFO_TAG { IMG_BOOL bDeviceSuspended; - spinlock_t *psSwapChainLock; + spinlock_t SwapChainLock; } OMAPLFB_DEVINFO; #define OMAPLFB_PAGE_SIZE 4096 @@ -196,13 +196,8 @@ PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain); IMG_BOOL OMAPLFBVSyncIHandler(OMAPLFB_SWAPCHAIN * psSwapChain); IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain); IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain); -#if defined (SUPPORT_TI_DSS_FW) IMG_VOID OMAPLFBEnableDisplayRegisterAccess(IMG_VOID); IMG_VOID OMAPLFBDisableDisplayRegisterAccess(IMG_VOID); -#endif -#if defined (CONFIG_OMAP2_DSS) -IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr); -#endif IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr); #endif diff --git a/pvr/omaplfb_displayclass.c b/pvr/omaplfb_displayclass.c index 55e6f81..5e3d6d9 100644 --- a/pvr/omaplfb_displayclass.c +++ b/pvr/omaplfb_displayclass.c @@ -140,11 +140,11 @@ static IMG_VOID SetFlushStateInternal(OMAPLFB_DEVINFO * psDevInfo, { unsigned long ulLockFlags; - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); SetFlushStateInternalNoLock(psDevInfo, bFlushState); - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); } static IMG_VOID SetFlushStateExternal(OMAPLFB_DEVINFO * psDevInfo, @@ -152,14 +152,14 @@ static IMG_VOID SetFlushStateExternal(OMAPLFB_DEVINFO * psDevInfo, { unsigned long ulLockFlags; - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); if (psDevInfo->bFlushCommands != bFlushState) { psDevInfo->bFlushCommands = bFlushState; SetFlushStateInternalNoLock(psDevInfo, bFlushState); } - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); } static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State) @@ -219,40 +219,15 @@ static PVRSRV_ERROR UnblankDisplay(OMAPLFB_DEVINFO * psDevInfo) acquire_console_sem(); res = fb_blank(psDevInfo->psLINFBInfo, 0); release_console_sem(); -#if !defined (CONFIG_OMAP2_DSS) - /* DSS2 returns error if unblank from a non-suspend state - ignore the error status for timebeing */ if (res != 0) { printk(KERN_WARNING DRIVER_PREFIX ": fb_blank failed (%d)", res); return PVRSRV_ERROR_GENERIC; } -#endif return PVRSRV_OK; } -#if defined (CONFIG_OMAP2_DSS) - -/* - Flip implementation for DSS2 using fb_pan_display -*/ -IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr) -{ - OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr(); - struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo; - struct fb_var_screeninfo var; - memcpy(&var, &psLINFBInfo->var, sizeof(struct fb_var_screeninfo)); - var.yoffset = - (aPhyAddr - - psLINFBInfo->fix.smem_start) / psLINFBInfo->fix.line_length; - if (psLINFBInfo->fbops->fb_pan_display != NULL) { - psLINFBInfo->fbops->fb_pan_display(&var, psLINFBInfo); - - } -} -#endif - static PVRSRV_ERROR EnableLFBEventNotification(OMAPLFB_DEVINFO * psDevInfo) { int res; @@ -555,7 +530,7 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice, psSwapChain->ui32InsertIndex = 0; psSwapChain->ui32RemoveIndex = 0; psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable; - psSwapChain->psSwapChainLock = psDevInfo->psSwapChainLock; + psSwapChain->psSwapChainLock = &psDevInfo->SwapChainLock; for (i = 0; i < ui32BufferCount - 1; i++) { psBuffer[i].psNext = &psBuffer[i + 1]; @@ -581,7 +556,7 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice, psVSyncFlips[i].bFlipped = IMG_FALSE; psVSyncFlips[i].bCmdCompleted = IMG_FALSE; } -#if defined (SUPPORT_TI_DSS_FW) + OMAPLFBEnableDisplayRegisterAccess(); psSwapChain->pvRegs = @@ -592,14 +567,14 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice, ": Couldn't map registers needed for flipping\n"); goto ErrorDisableDisplayRegisters; } -#endif + if (OMAPLFBInstallVSyncISR(psSwapChain) != PVRSRV_OK) { printk(KERN_WARNING DRIVER_PREFIX ": ISR handler failed to register\n"); goto ErrorUnmapRegisters; } - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); psDevInfo->psSwapChain = psSwapChain; @@ -612,7 +587,7 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice, OMAPLFBEnableVSyncInterrupt(psSwapChain); } - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); eError = EnableLFBEventNotification(psDevInfo); if (eError != PVRSRV_OK) { @@ -631,11 +606,9 @@ ErrorUninstallVSyncInterrupt: ": Couldn't uninstall VSync ISR\n"); } ErrorUnmapRegisters: -#if defined (SUPPORT_TI_DSS_FW) iounmap(psSwapChain->pvRegs); ErrorDisableDisplayRegisters: OMAPLFBDisableDisplayRegisterAccess(); -#endif OMAPLFBFreeKernelMem(psVSyncFlips); ErrorFreeBuffers: OMAPLFBFreeKernelMem(psBuffer); @@ -669,7 +642,7 @@ static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice, ": Couldn't disable framebuffer event notification\n"); } - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); OMAPLFBDisableVSyncInterrupt(psSwapChain); @@ -679,19 +652,17 @@ static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice, psDevInfo->psSwapChain = IMG_NULL; - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); if (OMAPLFBUninstallVSyncISR(psSwapChain) != PVRSRV_OK) { printk(KERN_WARNING DRIVER_PREFIX ": Couldn't uninstall VSync ISR\n"); return PVRSRV_ERROR_GENERIC; } -#if defined (SUPPORT_TI_DSS_FW) iounmap(psSwapChain->pvRegs); OMAPLFBDisableDisplayRegisterAccess(); -#endif OMAPLFBFreeKernelMem(psSwapChain->psVSyncFlips); OMAPLFBFreeKernelMem(psSwapChain->psBuffer); @@ -810,13 +781,13 @@ static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice, IMG_HANDLE hSwapChain) return PVRSRV_ERROR_INVALID_PARAMS; } - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); FlushInternalVSyncQueue(psSwapChain); OMAPLFBFlip(psSwapChain, psDevInfo->sFBInfo.sSysAddr.uiAddr); - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); return PVRSRV_OK; } @@ -885,6 +856,7 @@ IMG_BOOL OMAPLFBVSyncIHandler(OMAPLFB_SWAPCHAIN * psSwapChain) ExitUnlock: spin_unlock_irqrestore(psSwapChain->psSwapChainLock, ulLockFlags); + return bStatus; } @@ -916,7 +888,7 @@ static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie, psBuffer = (OMAPLFB_BUFFER *) psFlipCmd->hExtBuffer; psSwapChain = (OMAPLFB_SWAPCHAIN *) psFlipCmd->hExtSwapChain; - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); if (psDevInfo->bDeviceSuspended) { psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, @@ -965,54 +937,21 @@ static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie, goto ExitTrueUnlock; } - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); return IMG_FALSE; #endif ExitTrueUnlock: - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); return IMG_TRUE; } -static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo) +static void SetDevinfo(OMAPLFB_DEVINFO * psDevInfo) { - struct fb_info *psLINFBInfo; - struct module *psLINFBOwner; OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo; - PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC; + struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo; unsigned long FBSize; - acquire_console_sem(); - - if (fb_idx < 0 || fb_idx >= num_registered_fb) { - eError = PVRSRV_ERROR_INVALID_DEVICE; - goto errRelSem; - } - - psLINFBInfo = registered_fb[fb_idx]; - - psLINFBOwner = psLINFBInfo->fbops->owner; - if (!try_module_get(psLINFBOwner)) { - printk(KERN_INFO DRIVER_PREFIX - ": Couldn't get framebuffer module\n"); - - goto errRelSem; - } - - if (psLINFBInfo->fbops->fb_open != NULL) { - int res; - - res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0); - if (res != 0) { - printk(KERN_INFO DRIVER_PREFIX - ": Couldn't open framebuffer: %d\n", res); - - goto errModPut; - } - } - - psDevInfo->psLINFBInfo = psLINFBInfo; - FBSize = (psLINFBInfo->screen_size) != 0 ? psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len; DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX @@ -1045,7 +984,8 @@ static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo) psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length; psPVRFBInfo->ui32FBSize = FBSize; psPVRFBInfo->ui32BufferSize = - psPVRFBInfo->ui32Height * psPVRFBInfo->ui32ByteStride; + max(psPVRFBInfo->ui32Height, psPVRFBInfo->ui32Width) + * psPVRFBInfo->ui32ByteStride; psPVRFBInfo->ui32RoundedBufferSize = OMAPLFB_PAGE_ROUNDUP(psPVRFBInfo->ui32BufferSize); @@ -1058,48 +998,96 @@ static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo) (psLINFBInfo->var.green.offset == 5) && (psLINFBInfo->var.blue.offset == 0) && (psLINFBInfo->var.red.msb_right == 0)) { - printk("PVRSRV_PIXEL_FORMAT_RGB565\n"); psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565; } else { printk("Unknown FB format\n"); } - } else { - if (psLINFBInfo->var.bits_per_pixel == 32) { - if ((psLINFBInfo->var.red.length == 8) && - (psLINFBInfo->var.green.length == 8) && - (psLINFBInfo->var.blue.length == 8) && - (psLINFBInfo->var.transp.length == 8) && - (psLINFBInfo->var.red.offset == 16) && - (psLINFBInfo->var.green.offset == 8) && - (psLINFBInfo->var.blue.offset == 0) && - (psLINFBInfo->var.transp.offset == 24) && - (psLINFBInfo->var.red.msb_right == 0)) { - printk("PVRSRV_PIXEL_FORMAT_ARGB8888\n"); - psPVRFBInfo->ePixelFormat = - PVRSRV_PIXEL_FORMAT_ARGB8888; - } else { - if ((psLINFBInfo->var.red.length == 8) && - (psLINFBInfo->var.green.length == 8) && - (psLINFBInfo->var.blue.length == 8) && - (psLINFBInfo->var.transp.length == 0) && - (psLINFBInfo->var.red.offset == 16) && - (psLINFBInfo->var.green.offset == 8) && - (psLINFBInfo->var.blue.offset == 0) && - (psLINFBInfo->var.transp.offset == 0) && - (psLINFBInfo->var.red.msb_right == 0)) { - printk("PVRSRV_PIXEL_FORMAT_RGB888\n"); - printk - ("EGL library does not support RGB888 !!!\n"); - psPVRFBInfo->ePixelFormat = - PVRSRV_PIXEL_FORMAT_RGB888; - } else { - printk("Unknown FB format\n"); - } - } + } else if (psLINFBInfo->var.bits_per_pixel == 32) { + if ((psLINFBInfo->var.red.length == 8) && + (psLINFBInfo->var.green.length == 8) && + (psLINFBInfo->var.blue.length == 8) && + (psLINFBInfo->var.red.offset == 16) && + (psLINFBInfo->var.green.offset == 8) && + (psLINFBInfo->var.blue.offset == 0) && + (psLINFBInfo->var.red.msb_right == 0)) { + psPVRFBInfo->ePixelFormat = + PVRSRV_PIXEL_FORMAT_ARGB8888; } else { printk("Unknown FB format\n"); } + } else { + printk("Unknown FB format\n"); + } + psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat; + psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width; + psDevInfo->sDisplayDim.ui32Height = psDevInfo->sFBInfo.ui32Height; + psDevInfo->sDisplayDim.ui32ByteStride = + psDevInfo->sFBInfo.ui32ByteStride; + psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr; + psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr; + psDevInfo->sSystemBuffer.ui32BufferSize = + psDevInfo->sFBInfo.ui32RoundedBufferSize; +} + +static struct FB_EVENTS { + struct notifier_block notif; + OMAPLFB_DEVINFO *psDevInfo; +} gFBEventsData; + +static int FBEvents(struct notifier_block *psNotif, + unsigned long event, void *data) +{ + if (event == FB_EVENT_MODE_CHANGE) { + struct FB_EVENTS *psEvents = + container_of(psNotif, struct FB_EVENTS, notif); + SetDevinfo(psEvents->psDevInfo); } + return 0; +} + +static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo) +{ + struct fb_info *psLINFBInfo; + struct module *psLINFBOwner; + OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo; + PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC; + + acquire_console_sem(); + + if (fb_idx < 0 || fb_idx >= num_registered_fb) { + eError = PVRSRV_ERROR_INVALID_DEVICE; + goto errRelSem; + } + + psLINFBInfo = registered_fb[fb_idx]; + + psLINFBOwner = psLINFBInfo->fbops->owner; + if (!try_module_get(psLINFBOwner)) { + printk(KERN_INFO DRIVER_PREFIX + ": Couldn't get framebuffer module\n"); + + goto errRelSem; + } + + if (psLINFBInfo->fbops->fb_open != NULL) { + int res; + + res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0); + if (res != 0) { + printk(KERN_INFO DRIVER_PREFIX + ": Couldn't open framebuffer: %d\n", res); + + goto errModPut; + } + } + + psDevInfo->psLINFBInfo = psLINFBInfo; + + SetDevinfo(psDevInfo); + + gFBEventsData.notif.notifier_call = FBEvents; + gFBEventsData.psDevInfo = psDevInfo; + fb_register_client(&gFBEventsData.notif); psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr; psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr; @@ -1170,19 +1158,15 @@ PVRSRV_ERROR OMAPLFBInit(IMG_VOID) return PVRSRV_ERROR_INIT_FAILURE; } - spin_lock_init(psDevInfo->psSwapChainLock); + spin_lock_init(&psDevInfo->SwapChainLock); psDevInfo->psSwapChain = IMG_NULL; psDevInfo->bFlushCommands = IMG_FALSE; psDevInfo->bDeviceSuspended = IMG_FALSE; + psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = psDevInfo->sFBInfo.ui32FBSize / psDevInfo->sFBInfo.ui32RoundedBufferSize; -#if !defined (SUPPORT_TI_DSS_FW) - /* DSS2 have trouble with ui32MaxSwapChainBuffers > 3 */ - if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers > 3) - psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 3; -#endif if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) { psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0; psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0; @@ -1195,24 +1179,10 @@ PVRSRV_ERROR OMAPLFBInit(IMG_VOID) strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE); - psDevInfo->sDisplayFormat.pixelformat = - psDevInfo->sFBInfo.ePixelFormat; - psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width; - psDevInfo->sDisplayDim.ui32Height = - psDevInfo->sFBInfo.ui32Height; - psDevInfo->sDisplayDim.ui32ByteStride = - psDevInfo->sFBInfo.ui32ByteStride; - DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Maximum number of swap chain buffers: %lu\n", psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)); - psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr; - psDevInfo->sSystemBuffer.sCPUVAddr = - psDevInfo->sFBInfo.sCPUVAddr; - psDevInfo->sSystemBuffer.ui32BufferSize = - (psDevInfo->sFBInfo.ui32RoundedBufferSize); - psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE); psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice; @@ -1310,7 +1280,7 @@ IMG_VOID OMAPLFBDriverSuspend(IMG_VOID) OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr(); unsigned long ulLockFlags; - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); if (psDevInfo->bDeviceSuspended) { goto ExitUnlock; @@ -1319,17 +1289,16 @@ IMG_VOID OMAPLFBDriverSuspend(IMG_VOID) SetFlushStateInternalNoLock(psDevInfo, IMG_TRUE); - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); -#if defined (SUPPORT_TI_DSS_FW) if (psDevInfo->psSwapChain != IMG_NULL) { OMAPLFBDisableDisplayRegisterAccess(); } -#endif + return; ExitUnlock: - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); } IMG_VOID OMAPLFBDriverResume(IMG_VOID) @@ -1340,17 +1309,17 @@ IMG_VOID OMAPLFBDriverResume(IMG_VOID) if (!psDevInfo->bDeviceSuspended) { return; } -#if defined (SUPPORT_TI_DSS_FW) + if (psDevInfo->psSwapChain != IMG_NULL) { OMAPLFBEnableDisplayRegisterAccess(); } -#endif - spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags); + + spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags); SetFlushStateInternalNoLock(psDevInfo, IMG_FALSE); psDevInfo->bDeviceSuspended = IMG_FALSE; - spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags); + spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags); } #endif diff --git a/pvr/omaplfb_linux.c b/pvr/omaplfb_linux.c index fa96a19..5d4ddd8 100644 --- a/pvr/omaplfb_linux.c +++ b/pvr/omaplfb_linux.c @@ -41,30 +41,29 @@ #include #endif +#include + +/*#include */ + #include "img_defs.h" #include "servicesext.h" #include "kerneldisplay.h" #include "omaplfb.h" #include "pvrmodule.h" -#if defined (SUPPORT_TI_DSS_FW) -#include -#include -#else -#if !defined (CONFIG_OMAP2_DSS) -#define DISPC_IRQ_VSYNC 0x0002 -extern int omap_dispc_request_irq(unsigned long, void (*)(void *), void *); -extern void omap_dispc_free_irq(unsigned long, void (*)(void *), void *); +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) extern void omap_dispc_set_plane_base(int plane, IMG_UINT32 phys_addr); -#else +#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) #include -#include -#include -#endif +#else +#error "PVR needs OMAPFB, but it's disabled" #endif MODULE_SUPPORTED_DEVICE(DEVNAME); +extern int omap_dispc_request_irq(unsigned long, void (*)(void *), void *); +extern void omap_dispc_free_irq(unsigned long, void (*)(void *), void *); + #define unref__ __attribute__ ((unused)) IMG_VOID *OMAPLFBAllocKernelMem(IMG_UINT32 ui32Size) @@ -88,157 +87,77 @@ PVRSRV_ERROR OMAPLFBGetLibFuncAddr(IMG_CHAR * szFunctionName, return PVRSRV_OK; } -#if !defined (SUPPORT_TI_DSS_FW) IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain) { - OMAPLFBInstallVSyncISR(psSwapChain); } IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain) { - OMAPLFBUninstallVSyncISR(psSwapChain); -} -#else -static IMG_VOID OMAPLFBVSyncWriteReg(OMAPLFB_SWAPCHAIN * psSwapChain, - IMG_UINT32 ui32Offset, - IMG_UINT32 ui32Value) -{ - IMG_VOID *pvRegAddr = - (IMG_VOID *) ((IMG_UINT8 *) psSwapChain->pvRegs + ui32Offset); - - writel(ui32Value, pvRegAddr); -} - -static IMG_UINT32 OMAPLFBVSyncReadReg(OMAPLFB_SWAPCHAIN * psSwapChain, - IMG_UINT32 ui32Offset) -{ - return readl((IMG_UINT8 *) psSwapChain->pvRegs + ui32Offset); } -IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain) -{ #if defined(SYS_USING_INTERRUPTS) - - IMG_UINT32 ui32InterruptEnable = - OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_IRQENABLE); - ui32InterruptEnable |= OMAPLCD_INTMASK_VSYNC; - OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_IRQENABLE, - ui32InterruptEnable); +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) +static void OMAPLFBVSyncISR(void *arg) +#else +static void OMAPLFBVSyncISR(void *arg, u32 mask) #endif -} - -IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain) { -#if defined(SYS_USING_INTERRUPTS) - - IMG_UINT32 ui32InterruptEnable = - OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_IRQENABLE); - ui32InterruptEnable &= ~(OMAPLCD_INTMASK_VSYNC); - OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_IRQENABLE, - ui32InterruptEnable); -#endif + (void)OMAPLFBVSyncIHandler((OMAPLFB_SWAPCHAIN *) arg); } #endif -#if defined(SYS_USING_INTERRUPTS) -static void -#if defined (SUPPORT_TI_DSS_FW) -OMAPLFBVSyncISR(void *arg, struct pt_regs unref__ * regs) -#else -#if defined (CONFIG_OMAP2_DSS) -OMAPLFBVSyncISR(void *arg, u32 mask) -#else -OMAPLFBVSyncISR(void *arg) -#endif -#endif -{ - OMAPLFB_SWAPCHAIN *psSwapChain = (OMAPLFB_SWAPCHAIN *) arg; - (void)OMAPLFBVSyncIHandler(psSwapChain); -} +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) +#define DISPC_IRQ_VSYNC 0x0002 #endif -#if !defined (SUPPORT_TI_DSS_FW) PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain) { -#if !defined (CONFIG_OMAP2_DSS) +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) if (omap_dispc_request_irq (DISPC_IRQ_VSYNC, OMAPLFBVSyncISR, psSwapChain) != 0) + return PVRSRV_ERROR_OUT_OF_MEMORY; #else if (omap_dispc_register_isr - ((omap_dispc_isr_t) OMAPLFBVSyncISR, psSwapChain, - DISPC_IRQ_VSYNC) != 0) + (OMAPLFBVSyncISR, psSwapChain, DISPC_IRQ_VSYNC) != 0) + return PVRSRV_ERROR_OUT_OF_MEMORY; #endif - return PVRSRV_ERROR_OUT_OF_MEMORY; /* not worth a proper mapping */ + return PVRSRV_OK; } PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain) { -#if !defined (CONFIG_OMAP2_DSS) +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) omap_dispc_free_irq(DISPC_IRQ_VSYNC, OMAPLFBVSyncISR, psSwapChain); #else - omap_dispc_unregister_isr(OMAPLFBVSyncISR); -#endif - return PVRSRV_OK; -} - -IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr) -{ -#if !defined (CONFIG_OMAP2_DSS) - omap_dispc_set_plane_base(0, aPhyAddr); -#else - OMAPLFBFlipDSS2(psSwapChain, aPhyAddr); -#endif -} -#else -PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain) -{ -#if defined(SYS_USING_INTERRUPTS) - OMAPLFBDisableVSyncInterrupt(psSwapChain); - - if (omap2_disp_register_isr(OMAPLFBVSyncISR, psSwapChain, - DISPC_IRQSTATUS_VSYNC)) { - printk(KERN_INFO DRIVER_PREFIX - ": OMAPLFBInstallVSyncISR: Request OMAPLCD IRQ failed\n"); - return PVRSRV_ERROR_INIT_FAILURE; - } -#endif - return PVRSRV_OK; -} - -PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain) -{ -#if defined(SYS_USING_INTERRUPTS) - OMAPLFBDisableVSyncInterrupt(psSwapChain); - - omap2_disp_unregister_isr(OMAPLFBVSyncISR); - + omap_dispc_unregister_isr(OMAPLFBVSyncISR, psSwapChain, + DISPC_IRQ_VSYNC); #endif return PVRSRV_OK; } IMG_VOID OMAPLFBEnableDisplayRegisterAccess(IMG_VOID) { - omap2_disp_get_dss(); + printk(KERN_WARNING DRIVER_PREFIX + ": Attempting to call OMAPLFBEnableDisplayRegisterAccess\n"); + /*omap2_disp_get_dss(); */ } IMG_VOID OMAPLFBDisableDisplayRegisterAccess(IMG_VOID) { - omap2_disp_put_dss(); + printk(KERN_WARNING DRIVER_PREFIX + ": Attempting to call OMAPLFBDisableDisplayRegisterAccess\n"); + /*omap2_disp_put_dss(); */ } IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr) { - IMG_UINT32 control; - - OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_GFX_BA0, aPhyAddr); - OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_GFX_BA1, aPhyAddr); - - control = OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_CONTROL); - control |= OMAP_CONTROL_GOLCD; - OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_CONTROL, control); -} +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) + omap_dispc_set_plane_base(0, aPhyAddr); +#else + omap_dispc_set_plane_ba0(OMAP_DSS_CHANNEL_LCD, OMAP_DSS_GFX, aPhyAddr); #endif +} #if defined(LDM_PLATFORM) diff --git a/pvr/osfunc.c b/pvr/osfunc.c index 8370e1a..68b441d 100644 --- a/pvr/osfunc.c +++ b/pvr/osfunc.c @@ -67,6 +67,8 @@ extern PVRSRV_LINUX_MUTEX gPVRSRVLock; #define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0) #define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1) +#define LINUX_KMALLOC_LIMIT PAGE_SIZE /* 4k */ + #if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) PVRSRV_ERROR OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID * ppvCpuVAddr, IMG_HANDLE * phBlockAlloc) @@ -76,35 +78,40 @@ PVRSRV_ERROR _OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_CHAR * pszFilename, IMG_UINT32 ui32Line) #endif { + IMG_UINT32 ui32Threshold; + PVR_UNREFERENCED_PARAMETER(ui32Flags); + /* determine whether to go straight to vmalloc */ + ui32Threshold = LINUX_KMALLOC_LIMIT; + + if (ui32Size > ui32Threshold) { #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line); + *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, + pszFilename, ui32Line); #else - *ppvCpuVAddr = KMallocWrapper(ui32Size); + *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED); #endif - if (*ppvCpuVAddr) { - if (phBlockAlloc) { + if (!*ppvCpuVAddr) + return PVRSRV_ERROR_OUT_OF_MEMORY; - *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC; - } + if (phBlockAlloc) + *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC; } else { - if (!phBlockAlloc) { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } + /* default - try kmalloc first */ #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - *ppvCpuVAddr = - _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, - ui32Line); + *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line); #else - *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED); + *ppvCpuVAddr = KMallocWrapper(ui32Size); #endif - if (!*ppvCpuVAddr) { + + if (!*ppvCpuVAddr) return PVRSRV_ERROR_OUT_OF_MEMORY; - } - *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC; + if (phBlockAlloc) + *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC; + } return PVRSRV_OK; @@ -120,9 +127,8 @@ PVRSRV_ERROR _OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, #endif { PVR_UNREFERENCED_PARAMETER(ui32Flags); - PVR_UNREFERENCED_PARAMETER(ui32Size); - if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC) { + if (ui32Size > LINUX_KMALLOC_LIMIT) { #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line); #else @@ -415,6 +421,8 @@ PVRSRV_ERROR OSInitEnvData(IMG_PVOID * ppvEnvSpecificData) return PVRSRV_ERROR_GENERIC; } + memset(psEnvData, 0, sizeof(*psEnvData)); + if (OSAllocMem (PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, @@ -439,8 +447,9 @@ PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData) PVR_ASSERT(!psEnvData->bMISRInstalled); PVR_ASSERT(!psEnvData->bLISRInstalled); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0x1000, psEnvData->pvBridgeData, - IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, + psEnvData->pvBridgeData, IMG_NULL); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL); @@ -519,7 +528,7 @@ static irqreturn_t DeviceISRWrapper(int irq, void *dev_id SYS_DATA *psSysData = psDeviceNode->psSysData; ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData; - tasklet_schedule(&psEnvData->sMISRTasklet); + queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork); } out: @@ -551,7 +560,7 @@ static irqreturn_t SystemISRWrapper(int irq, void *dev_id if (bStatus) { ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData; - tasklet_schedule(&psEnvData->sMISRTasklet); + queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork); } out: @@ -676,12 +685,10 @@ PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID * pvSysData) return PVRSRV_OK; } -static void MISRWrapper(unsigned long data) +static void MISRWrapper(struct work_struct *work) { - SYS_DATA *psSysData; - - psSysData = (SYS_DATA *) data; - + ENV_DATA *psEnvData = container_of(work, ENV_DATA, sMISRWork); + SYS_DATA *psSysData = (SYS_DATA *) psEnvData->pvSysData; PVRSRVMISR(psSysData); } @@ -698,8 +705,9 @@ PVRSRV_ERROR OSInstallMISR(IMG_VOID * pvSysData) PVR_TRACE(("Installing MISR with cookie %x", pvSysData)); - tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, - (unsigned long)pvSysData); + psEnvData->pvSysData = pvSysData; + psEnvData->psMISRWorkqueue = create_singlethread_workqueue("sgx_misr"); + INIT_WORK(&psEnvData->sMISRWork, MISRWrapper); psEnvData->bMISRInstalled = IMG_TRUE; @@ -719,7 +727,8 @@ PVRSRV_ERROR OSUninstallMISR(IMG_VOID * pvSysData) PVR_TRACE(("Uninstalling MISR")); - tasklet_kill(&psEnvData->sMISRTasklet); + flush_workqueue(psEnvData->psMISRWorkqueue); + destroy_workqueue(psEnvData->psMISRWorkqueue); psEnvData->bMISRInstalled = IMG_FALSE; @@ -732,7 +741,7 @@ PVRSRV_ERROR OSScheduleMISR(IMG_VOID * pvSysData) ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData; if (psEnvData->bMISRInstalled) { - tasklet_schedule(&psEnvData->sMISRTasklet); + queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork); } return PVRSRV_OK; diff --git a/pvr/osfunc.h b/pvr/osfunc.h index f8b91e9..c0fbd69 100644 --- a/pvr/osfunc.h +++ b/pvr/osfunc.h @@ -67,6 +67,8 @@ extern "C" { PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID * pvSysData); PVRSRV_ERROR OSInstallMISR(IMG_VOID * pvSysData); PVRSRV_ERROR OSUninstallMISR(IMG_VOID * pvSysData); + PVRSRV_ERROR OSInitPerf(IMG_VOID * pvSysData); + PVRSRV_ERROR OSCleanupPerf(IMG_VOID * pvSysData); IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID * pvLinAddr); IMG_VOID OSMemCopy(IMG_VOID * pvDst, IMG_VOID * pvSrc, IMG_UINT32 ui32Size); diff --git a/pvr/power.c b/pvr/power.c index 00a7957..2b016ee 100644 --- a/pvr/power.c +++ b/pvr/power.c @@ -23,12 +23,18 @@ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK * ******************************************************************************/ - #include "services_headers.h" +#include +#include +#include +#include static IMG_BOOL gbInitServerRunning = IMG_FALSE; static IMG_BOOL gbInitServerRan = IMG_FALSE; static IMG_BOOL gbInitSuccessful = IMG_FALSE; +static DEFINE_MUTEX(hPowerAndFreqLock); +static DECLARE_WAIT_QUEUE_HEAD(hDvfsWq); +static IMG_BOOL gbDvfsActive; IMG_EXPORT PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE @@ -85,53 +91,43 @@ static IMG_BOOL _IsSystemStatePowered(PVR_POWER_STATE eSystemPowerState) return (IMG_BOOL) (eSystemPowerState < PVRSRV_POWER_STATE_D2); } +IMG_EXPORT IMG_VOID PVRSRVDvfsLock(IMG_VOID) +{ + mutex_lock(&hPowerAndFreqLock); + gbDvfsActive = 1; + mutex_unlock(&hPowerAndFreqLock); +} + +IMG_EXPORT IMG_VOID PVRSRVDvfsUnlock(IMG_VOID) +{ + mutex_lock(&hPowerAndFreqLock); + gbDvfsActive = 0; + wake_up(&hDvfsWq); + mutex_unlock(&hPowerAndFreqLock); +} + IMG_EXPORT PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID, IMG_BOOL bSystemPowerEvent) { - PVRSRV_ERROR eError; - SYS_DATA *psSysData; - IMG_UINT32 ui32Timeout = 1000000; - -#if defined(SUPPORT_LMA) - - ui32Timeout *= 60; -#endif - - eError = SysAcquireData(&psSysData); - if (eError != PVRSRV_OK) { - return eError; + if ((ui32CallerID == TIMER_ID) && + (mutex_is_locked(&hPowerAndFreqLock) || gbDvfsActive)) + return PVRSRV_ERROR_RETRY; + mutex_lock(&hPowerAndFreqLock); + while (gbDvfsActive) { + DEFINE_WAIT(__wait); + prepare_to_wait(&hDvfsWq, &__wait, TASK_UNINTERRUPTIBLE); + mutex_unlock(&hPowerAndFreqLock); + schedule(); + mutex_lock(&hPowerAndFreqLock); + finish_wait(&hDvfsWq, &__wait); } - - do { - eError = OSLockResource(&psSysData->sPowerStateChangeResource, - ui32CallerID); - if (eError == PVRSRV_OK) { - break; - } else if (ui32CallerID == ISR_ID) { - - eError = PVRSRV_ERROR_RETRY; - break; - } - - OSWaitus(1); - ui32Timeout--; - } while (ui32Timeout > 0); - - if ((eError == PVRSRV_OK) && - !bSystemPowerEvent && - !_IsSystemStatePowered(psSysData->eCurrentPowerState)) { - - PVRSRVPowerUnlock(ui32CallerID); - eError = PVRSRV_ERROR_RETRY; - } - - return eError; + return PVRSRV_OK; } IMG_EXPORT IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID) { - OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID); + mutex_unlock(&hPowerAndFreqLock); } static @@ -170,6 +166,9 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices, psPowerDevice-> eCurrentPowerState); if (eError != PVRSRV_OK) { + pr_err + ("pfnPrePower failed (%u)\n", + eError); return eError; } } @@ -181,6 +180,9 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices, psPowerDevice-> eCurrentPowerState); if (eError != PVRSRV_OK) { + pr_err + ("SysDevicePrePowerState failed (%u)\n", + eError); return eError; } } @@ -226,6 +228,9 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices, psPowerDevice-> eCurrentPowerState); if (eError != PVRSRV_OK) { + pr_err + ("SysDevicePostPowerState failed (%u)\n", + eError); return eError; } @@ -239,6 +244,9 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices, psPowerDevice-> eCurrentPowerState); if (eError != PVRSRV_OK) { + pr_err + ("pfnPostPower failed (%u)\n", + eError); return eError; } } @@ -254,23 +262,6 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices, return PVRSRV_OK; } -PVRSRV_ERROR PVRSRVSetDevicePowerStateCoreKM(IMG_UINT32 ui32DeviceIndex, - PVR_POWER_STATE eNewPowerState) -{ - PVRSRV_ERROR eError; - eError = - PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, - eNewPowerState); - if (eError != PVRSRV_OK) { - return eError; - } - - eError = - PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, - eNewPowerState); - return eError; -} - IMG_EXPORT PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex, PVR_POWER_STATE eNewPowerState, @@ -537,7 +528,8 @@ PVRSRV_ERROR PVRSRVRemovePowerDevice(IMG_UINT32 ui32DeviceIndex) psCurrent->psNext; } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psCurrent, + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, + sizeof(PVRSRV_POWER_DEV), psCurrent, IMG_NULL); break; @@ -580,11 +572,11 @@ IMG_EXPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex) return IMG_FALSE; } -IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, - IMG_BOOL bIdleDevice, - IMG_VOID * pvInfo) +PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, + IMG_BOOL bIdleDevice, + IMG_VOID * pvInfo) { - PVRSRV_ERROR eError; + PVRSRV_ERROR eError = PVRSRV_OK; SYS_DATA *psSysData; PVRSRV_POWER_DEV *psPowerDevice; @@ -600,8 +592,12 @@ IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, psPowerDevice-> pfnPreClockSpeedChange(psPowerDevice-> hDevCookie, - bIdleDevice); + bIdleDevice, + psPowerDevice-> + eCurrentPowerState); if (eError != PVRSRV_OK) { + pr_err + ("pfnPreClockSpeedChange failed\n"); PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx", ui32DeviceIndex, eError)); @@ -611,13 +607,14 @@ IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, psPowerDevice = psPowerDevice->psNext; } + return eError; } IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex, IMG_BOOL bIdleDevice, IMG_VOID * pvInfo) { - PVRSRV_ERROR eError; + PVRSRV_ERROR eError = PVRSRV_OK; SYS_DATA *psSysData; PVRSRV_POWER_DEV *psPowerDevice; @@ -633,8 +630,12 @@ IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex, psPowerDevice-> pfnPostClockSpeedChange(psPowerDevice-> hDevCookie, - bIdleDevice); + bIdleDevice, + psPowerDevice-> + eCurrentPowerState); if (eError != PVRSRV_OK) { + pr_err + ("pfnPostClockSpeedChange failed\n"); PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePostClockSpeedChange : Device %lu failed, error:0x%lx", ui32DeviceIndex, eError)); diff --git a/pvr/power.h b/pvr/power.h index a3fefd9..20270b2 100644 --- a/pvr/power.h +++ b/pvr/power.h @@ -67,6 +67,10 @@ extern "C" { IMG_BOOL bSystemPowerEvent); IMG_IMPORT IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID); + IMG_IMPORT IMG_VOID PVRSRVDvfsLock(IMG_VOID); + + IMG_IMPORT IMG_VOID PVRSRVDvfsUnlock(IMG_VOID); + IMG_IMPORT PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex, PVR_POWER_STATE @@ -103,9 +107,10 @@ extern "C" { IMG_IMPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex); IMG_IMPORT - IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, - IMG_BOOL bIdleDevice, - IMG_VOID * pvInfo); + PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 + ui32DeviceIndex, + IMG_BOOL bIdleDevice, + IMG_VOID * pvInfo); IMG_IMPORT IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 diff --git a/pvr/pvr_bridge.h b/pvr/pvr_bridge.h index abbe9c7..1168999 100644 --- a/pvr/pvr_bridge.h +++ b/pvr/pvr_bridge.h @@ -82,7 +82,8 @@ extern "C" { #define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23) #define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24) #define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25) -#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+25) +#define PVRSRV_BRIDGE_CACHE_FLUSH_DRM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26) +#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+26) #define PVRSRV_BRIDGE_SIM_CMD_FIRST (PVRSRV_BRIDGE_CORE_CMD_LAST+1) #define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0) @@ -320,6 +321,17 @@ extern "C" { } PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER; +#define DRM_PVR2D_CFLUSH_FROM_GPU 1 +#define DRM_PVR2D_CFLUSH_TO_GPU 2 + + typedef struct PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER_TAG { + IMG_UINT32 ui32BridgeFlags; + IMG_UINT32 ui32Type; + IMG_UINT32 ui32Virt; + IMG_UINT32 ui32Length; + + } PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER; + typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG { IMG_UINT32 ui32BridgeFlags; IMG_HANDLE hDevCookie; diff --git a/pvr/pvr_bridge_k.c b/pvr/pvr_bridge_k.c index bf668fb..1037cd7 100644 --- a/pvr/pvr_bridge_k.c +++ b/pvr/pvr_bridge_k.c @@ -127,9 +127,8 @@ unlock_and_return: } #endif -int -PVRSRV_BridgeDispatchKM(struct inode *inode, - struct file *file, unsigned int cmd, unsigned long arg) +long +PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg) { IMG_UINT32 ui32BridgeID = PVRSRV_GET_BRIDGE_ID(cmd); PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = diff --git a/pvr/pvrsrv.c b/pvr/pvrsrv.c index 50e39e7..4539b44 100644 --- a/pvr/pvrsrv.c +++ b/pvr/pvrsrv.c @@ -260,7 +260,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData, eError = pfnRegisterDevice(psDeviceNode); if (eError != PVRSRV_OK) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, - 0, psDeviceNode, IMG_NULL); + sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); PVR_DPF((PVR_DBG_ERROR, "PVRSRVRegisterDevice : Failed to register device")); return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED); @@ -495,7 +495,8 @@ FoundDevice: *ppsDevNode = psDeviceNode->psNext; FreeDeviceID(psSysData, ui32DevIndex); - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, psDeviceNode, IMG_NULL); + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), + psDeviceNode, IMG_NULL); return (PVRSRV_OK); } diff --git a/pvr/queue.c b/pvr/queue.c index 9bb8360..c49cb4e 100644 --- a/pvr/queue.c +++ b/pvr/queue.c @@ -783,6 +783,10 @@ IMG_EXPORT "PVRSRVRegisterCmdProcListKM: Failed to alloc CC data")); goto ErrorExit; } + /* clear the list to ensure that we don't try to access uninitialised pointer + * in the 'error' execution path */ + OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex], 0x00, + ui32AllocSize); for (i = 0; i < ui32CmdCount; i++) { @@ -815,6 +819,7 @@ IMG_EXPORT psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT *) (((IMG_UINT32) psCmdCompleteData->psDstSync) + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0])); + psCmdCompleteData->ui32AllocSize = ui32AllocSize; } return PVRSRV_OK; @@ -825,20 +830,24 @@ ErrorExit: for (i = 0; i < ui32CmdCount; i++) { if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL) { - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, - psSysData-> - ppsCmdCompleteData[ui32DevIndex][i], - IMG_NULL); + psCmdCompleteData = + psSysData-> + ppsCmdCompleteData[ui32DevIndex][i]; + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + psCmdCompleteData->ui32AllocSize, + psCmdCompleteData, IMG_NULL); } } - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *), psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL); } if (psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) { - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + ui32CmdCount * sizeof(PFN_CMD_PROC), psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL); } @@ -872,20 +881,24 @@ IMG_EXPORT if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL) { - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, - psSysData-> - ppsCmdCompleteData[ui32DevIndex][i], - IMG_NULL); + COMMAND_COMPLETE_DATA *psCmdCompleteData = + psSysData-> + ppsCmdCompleteData[ui32DevIndex][i]; + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + psCmdCompleteData->ui32AllocSize, + psCmdCompleteData, IMG_NULL); } } - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *), psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL); } if (psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) { - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, + OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, + ui32CmdCount * sizeof(PFN_CMD_PROC), psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL); } diff --git a/pvr/queue.h b/pvr/queue.h index 687b36b..a380a9f 100644 --- a/pvr/queue.h +++ b/pvr/queue.h @@ -42,6 +42,7 @@ extern "C" { IMG_UINT32 ui32SrcSyncCount; PVRSRV_SYNC_OBJECT *psDstSync; PVRSRV_SYNC_OBJECT *psSrcSync; + IMG_UINT32 ui32AllocSize; } COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA; #if !defined(USE_CODE) diff --git a/pvr/ra.c b/pvr/ra.c index e7253bf..e6e5850 100644 --- a/pvr/ra.c +++ b/pvr/ra.c @@ -676,7 +676,7 @@ RA_ARENA *RA_Create(IMG_CHAR * name, insert_fail: HASH_Delete(pArena->pSegmentHash); hash_fail: - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pArena, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); arena_fail: return IMG_NULL; } @@ -705,7 +705,7 @@ void RA_Delete(RA_ARENA * pArena) RemoveProcEntry(pArena->szProcSegsName); #endif HASH_Delete(pArena->pSegmentHash); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pArena, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); } IMG_BOOL RA_Add(RA_ARENA * pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) diff --git a/pvr/resman.c b/pvr/resman.c index d503b0e..e6fc1f8 100644 --- a/pvr/resman.c +++ b/pvr/resman.c @@ -270,7 +270,8 @@ IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext, psResManContext->psNext->ppsThis = psResManContext->ppsThis; } - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psResManContext, IMG_NULL); + OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), + psResManContext, IMG_NULL); VALIDATERESLIST(); @@ -495,8 +496,9 @@ static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM * psItem, ACQUIRE_SYNC_OBJ; - if (OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psItem, IMG_NULL) != - PVRSRV_OK) { + if (OSFreeMem + (PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL) + != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR freeing resource list item memory")); eError = PVRSRV_ERROR_GENERIC; diff --git a/pvr/services.h b/pvr/services.h index 8e10c83..c151f54 100644 --- a/pvr/services.h +++ b/pvr/services.h @@ -165,11 +165,8 @@ extern "C" { typedef struct _PVRSRV_MEMBLK_ { IMG_DEV_VIRTADDR sDevVirtAddr; IMG_HANDLE hOSMemHandle; - IMG_HANDLE hOSWrapMem; IMG_HANDLE hBuffer; IMG_HANDLE hResItem; - IMG_SYS_PHYADDR *psIntSysPAddr; - } PVRSRV_MEMBLK; typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO; diff --git a/pvr/servicesext.h b/pvr/servicesext.h index cd35306..1f05e4d 100644 --- a/pvr/servicesext.h +++ b/pvr/servicesext.h @@ -94,8 +94,10 @@ typedef PVRSRV_ERROR(*PFN_PRE_POWER) (IMG_HANDLE, PVR_POWER_STATE, typedef PVRSRV_ERROR(*PFN_POST_POWER) (IMG_HANDLE, PVR_POWER_STATE, PVR_POWER_STATE); -typedef PVRSRV_ERROR(*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL); -typedef PVRSRV_ERROR(*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL); +typedef PVRSRV_ERROR(*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL, + PVR_POWER_STATE); +typedef PVRSRV_ERROR(*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL, + PVR_POWER_STATE); typedef enum _PVRSRV_PIXEL_FORMAT_ { PVRSRV_PIXEL_FORMAT_UNKNOWN = 0, diff --git a/pvr/servicesint.h b/pvr/servicesint.h index 8ccdd45..49269e2 100644 --- a/pvr/servicesint.h +++ b/pvr/servicesint.h @@ -50,8 +50,6 @@ extern "C" { PVRSRV_MEMBLK sMemBlk; - IMG_PVOID pvSysBackupBuffer; - struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo; } PVRSRV_KERNEL_MEM_INFO; diff --git a/pvr/sgx2dcore.c b/pvr/sgx2dcore.c new file mode 100644 index 0000000..fcf4dfa --- /dev/null +++ b/pvr/sgx2dcore.c @@ -0,0 +1,846 @@ +/********************************************************************** + * + * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful but, except + * as otherwise stated in writing, without any warranty; without even the + * implied warranty of merchantability or fitness for a particular purpose. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Imagination Technologies Ltd. + * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK + * + ******************************************************************************/ + +#include "sgxdefs.h" +#include "services_headers.h" +#include "sgxinfo.h" +#include "sgxinfokm.h" + +#if defined(SGX_FEATURE_2D_HARDWARE) + +#include "sgx2dcore.h" + +#define SGX2D_FLUSH_BH 0xF0000000 +#define SGX2D_FENCE_BH 0x70000000 + +#define SGX2D_QUEUED_BLIT_PAD 4 + +#define SGX2D_COMMAND_QUEUE_SIZE 1024 + +#define SGX2D_2D_NOT_IDLE(psDevInfo) ((psDevInfo)->ui322DFifoSize > SGX2DFifoFreeSpace(psDevInfo) || SGX2DIsBusy(psDevInfo)) + +static IMG_VOID SGX2DHardwareKick(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + + OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS, + EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK | + EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK); +} + +IMG_VOID SGX2DHWRecoveryStart(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + psDevInfo->b2DHWRecoveryInProgress = IMG_TRUE; + psDevInfo->b2DHWRecoveryEndPending = IMG_FALSE; +} + +IMG_VOID SGX2DHWRecoveryEnd(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + psDevInfo->b2DHWRecoveryEndPending = IMG_TRUE; + psDevInfo->b2DHWRecoveryInProgress = IMG_FALSE; + SGX2DHardwareKick(psDevInfo); +} + +#if !defined(NO_HARDWARE) +static IMG_VOID SGX2DKick(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + IMG_BOOL bStart = IMG_FALSE; + IMG_UINT32 uiStart = 0; + + PVR_UNREFERENCED_PARAMETER(psDevInfo); + + do { + if (PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != + PVRSRV_ERROR_PROCESSING_BLOCKED) { + break; + } + + if (bStart == IMG_FALSE) { + uiStart = OSClockus(); + bStart = IMG_TRUE; + } + OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT); + } while ((OSClockus() - uiStart) < MAX_HW_TIME_US); +} +#endif + +IMG_BOOL SGX2DIsBusy(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + IMG_UINT32 ui32BlitStatus; + + ui32BlitStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, + EUR_CR_2D_BLIT_STATUS); + + return (ui32BlitStatus & EUR_CR_2D_BLIT_STATUS_BUSY_MASK) != 0; +} + +IMG_UINT32 SGX2DCompletedBlits(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + IMG_UINT32 ui32BlitStatus; + + ui32BlitStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, + EUR_CR_2D_BLIT_STATUS); + + return (ui32BlitStatus & EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK) >> + EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT; +} + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DAcquireSlavePort) +#endif +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DAcquireSlavePort) +#endif +static INLINE + PVRSRV_ERROR SGX2DAcquireSlavePort(PVRSRV_SGXDEV_INFO * psDevInfo, + IMG_BOOL bBlock) +{ +#if defined(SGX2D_DIRECT_BLITS) + PVR_UNREFERENCED_PARAMETER(bBlock); + return OSLockResource(&psDevInfo->s2DSlaveportResource, ISR_ID); +#else + PVR_UNREFERENCED_PARAMETER(psDevInfo); + PVR_UNREFERENCED_PARAMETER(bBlock); + + return PVRSRV_OK; +#endif +} + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DReleaseSlavePort) +#endif +static INLINE PVRSRV_ERROR SGX2DReleaseSlavePort(PVRSRV_SGXDEV_INFO * psDevInfo) +{ +#if defined(SGX2D_DIRECT_BLITS) + return OSUnlockResource(&psDevInfo->s2DSlaveportResource, ISR_ID); +#else + PVR_UNREFERENCED_PARAMETER(psDevInfo); + + return PVRSRV_OK; +#endif +} + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DAcquireFifoSpace) +#endif +static INLINE + PVRSRV_ERROR SGX2DAcquireFifoSpace(PVRSRV_SGXDEV_INFO * psDevInfo, + IMG_UINT32 ui32MinBytesRequired, + IMG_UINT32 * pui32BytesObtained) +{ + PVRSRV_ERROR eError = PVRSRV_ERROR_FIFO_SPACE; + IMG_UINT32 ui32FifoBytes; + +#if defined(DEBUG) && defined(SGX2D_DIRECT_BLITS) + + if (OSIsResourceLocked(&psDevInfo->s2DSlaveportResource, ISR_ID) == + IMG_FALSE) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DAcquireFifoSpace: 2D slaveport is not locked")); + return PVRSRV_ERROR_PROCESSING_BLOCKED; + } +#endif + + ui32FifoBytes = SGX2DFifoFreeSpace(psDevInfo); + + if (ui32FifoBytes >= ui32MinBytesRequired) { + if (pui32BytesObtained) + *pui32BytesObtained = ui32FifoBytes; + + eError = PVRSRV_OK; + } + + return eError; +} + +#if defined(DEBUG) && defined (SGX2D_TRACE_BLIT) +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DTraceBlt) +#endif +FORCE_INLINE + IMG_VOID SGX2DTraceBlt(IMG_UINT32 * pui32BltData, IMG_UINT32 ui32Count) +{ + IMG_UINT32 i; + + PVR_TRACE(("----SGX 2D BLIT----")); + + for (i = 0; i < ui32Count; i++) { + PVR_TRACE(("word[%02d]: 0x%08x", i, pui32BltData[i])); + } +} +#else +#define SGX2DTraceBlt(pui32BltData, ui32Count) +#endif + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DWriteSlavePort) +#endif +FORCE_INLINE + IMG_VOID SGX2DWriteSlavePort(PVRSRV_SGXDEV_INFO * psDevInfo, + IMG_UINT32 ui32Value) +{ + SGX_SLAVE_PORT *psSlavePort = &psDevInfo->s2DSlavePortKM; +#if defined(SGX2D_INCREMENTING_SP_WRITES) + IMG_UINT32 *pui32Offset = psSlavePort->pui32Offset; + + if (*pui32Offset > (psSlavePort->ui32DataRange >> 1)) { + + *pui32Offset = 0; + } +#endif + + SGX2DTraceBlt(&ui32Value, 1); + +#if defined(SGX2D_INCREMENTING_SP_WRITES) + *((IMG_UINT32 *) ((IMG_UINT32) psSlavePort->pvData + *pui32Offset)) = + ui32Value; +#else + *((IMG_UINT32 *) psSlavePort->pvData) = ui32Value; +#endif + +#if defined(SGX2D_INCREMENTING_SP_WRITES) + *pui32Offset += 4; +#endif +} + +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DWriteSlavePortBatch) +#endif +FORCE_INLINE + PVRSRV_ERROR SGX2DWriteSlavePortBatch(PVRSRV_SGXDEV_INFO * psDevInfo, + IMG_UINT32 * pui32LinDataAddr, + IMG_UINT32 ui32Bytes) +{ + IMG_INT32 i; + SGX_SLAVE_PORT *psSlavePort = &psDevInfo->s2DSlavePortKM; + IMG_UINT32 *pui32LinPortAddrBase = (IMG_UINT32 *) psSlavePort->pvData; + IMG_UINT32 ui32DWORDs = ui32Bytes >> 2; +#if defined(SGX2D_INCREMENTING_SP_WRITES) + IMG_UINT32 *pui32Offset = psSlavePort->pui32Offset; + IMG_UINT32 *pui32LinPortAddr; + + if (ui32Bytes > (psSlavePort->ui32DataRange >> 1)) { + return PVRSRV_ERROR_CMD_TOO_BIG; + } + + if (*pui32Offset > (psSlavePort->ui32DataRange >> 1)) { + + *pui32Offset = 0; + } + + pui32LinPortAddr = + (IMG_UINT32 *) ((IMG_UINT32) pui32LinPortAddrBase + *pui32Offset); +#endif + + SGX2DTraceBlt(pui32LinDataAddr, ui32DWORDs); + + for (i = ui32DWORDs; i != 0; i -= ui32DWORDs) { + ui32DWORDs = (i < 32) ? i : 32; + + switch (ui32DWORDs) { +#if defined(SGX2D_INCREMENTING_SP_WRITES) + case 32: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 31: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 30: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 29: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 28: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 27: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 26: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 25: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 24: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 23: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 22: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 21: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 20: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 19: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 18: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 17: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 16: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 15: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 14: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 13: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 12: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 11: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 10: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 9: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 8: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 7: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 6: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 5: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 4: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 3: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 2: + *pui32LinPortAddr++ = *pui32LinDataAddr++; + case 1: + *pui32LinPortAddr++ = *pui32LinDataAddr++; +#else + case 32: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 31: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 30: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 29: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 28: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 27: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 26: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 25: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 24: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 23: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 22: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 21: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 20: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 19: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 18: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 17: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 16: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 15: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 14: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 13: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 12: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 11: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 10: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 9: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 8: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 7: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 6: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 5: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 4: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 3: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 2: + *pui32LinPortAddrBase = *pui32LinDataAddr++; + case 1: + *pui32LinPortAddrBase = *pui32LinDataAddr++; +#endif + } + } + +#if defined(SGX2D_INCREMENTING_SP_WRITES) + + *pui32Offset += ui32Bytes; +#endif + + return PVRSRV_OK; +} + +IMG_BOOL SGX2DProcessBlit(IMG_HANDLE hCmdCookie, + IMG_UINT32 ui32DataSize, IMG_VOID * pvData) +{ + PVRSRV_BLT_CMD_INFO *psBltCmd; + PVRSRV_SGXDEV_INFO *psDevInfo; + IMG_UINT32 ui32BytesRequired; + IMG_UINT32 ui32BytesObtained = 0; + IMG_BOOL bError = IMG_TRUE; + PVRSRV_ERROR eError; + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DProcessBlit: Start")); + + psBltCmd = (PVRSRV_BLT_CMD_INFO *) pvData; + + if (psBltCmd == IMG_NULL || psBltCmd->ui32CmdSize != ui32DataSize) { + PVR_DPF((PVR_DBG_ERROR, + "ProcessBlit: Data packet size is incorrect")); + return IMG_FALSE; + } + + psDevInfo = psBltCmd->psDevInfo; + + if (psDevInfo->h2DCmdCookie != IMG_NULL) { + return IMG_FALSE; + } + + if (psDevInfo->b2DHWRecoveryInProgress) { + psDevInfo->h2DCmdCookie = hCmdCookie; + SGX2DHardwareKick(psDevInfo); + return IMG_TRUE; + } + + if (SGX2DAcquireSlavePort(psDevInfo, IMG_FALSE) != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "ProcessBlit: Couldn't acquire slaveport")); + return IMG_FALSE; + } +#ifdef FIXME + +#endif + + if (psDevInfo->b2DHWRecoveryEndPending && SGX2D_2D_NOT_IDLE(psDevInfo)) { + psDevInfo->h2DCmdCookie = hCmdCookie; + SGX2DHardwareKick(psDevInfo); + PVR_ASSERT(bError); + goto ErrorExit; + } + psDevInfo->b2DHWRecoveryEndPending = IMG_FALSE; + + ui32BytesRequired = psBltCmd->ui32DataByteSize + SGX2D_QUEUED_BLIT_PAD; + + eError = + SGX2DAcquireFifoSpace(psDevInfo, ui32BytesRequired, + &ui32BytesObtained); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, "ProcessBlit: Get Fifo Space failed")); + bError = IMG_FALSE; + goto ErrorExit; + } + + SGX2DWriteSlavePortBatch(psDevInfo, + psBltCmd->aui32BltData, + psBltCmd->ui32DataByteSize); + + psDevInfo->h2DCmdCookie = hCmdCookie; + + SGX2DWriteSlavePort(psDevInfo, SGX2D_FLUSH_BH); + + PVR_ASSERT(bError); +ErrorExit: + + if (SGX2DReleaseSlavePort(psDevInfo) != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DReleaseSlavePort: failed to release slaveport")); + } + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DProcessBlit: Exit. Error %d", + (int)bError)); + + return bError; +} + +IMG_VOID SGX2DHandle2DComplete(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + IMG_HANDLE hCmdCookie; + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DHandle2DComplete: Start")); + + hCmdCookie = psDevInfo->h2DCmdCookie; + psDevInfo->h2DCmdCookie = IMG_NULL; + + if (hCmdCookie != IMG_NULL) { + PVRSRVCommandCompleteKM(hCmdCookie, IMG_TRUE); + } + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DHandle2DComplete: Exit")); +} + +IMG_EXPORT + PVRSRV_ERROR SGX2DQueueBlitKM(PVRSRV_SGXDEV_INFO * psDevInfo, + PVRSRV_KERNEL_SYNC_INFO * psDstSync, + IMG_UINT32 ui32NumSrcSyncs, + PVRSRV_KERNEL_SYNC_INFO * apsSrcSync[], + IMG_UINT32 ui32DataByteSize, + IMG_UINT32 * pui32BltData) +{ +#if defined(NO_HARDWARE) + PVR_UNREFERENCED_PARAMETER(psDevInfo); + PVR_UNREFERENCED_PARAMETER(psDstSync); + PVR_UNREFERENCED_PARAMETER(ui32NumSrcSyncs); + PVR_UNREFERENCED_PARAMETER(apsSrcSync); + PVR_UNREFERENCED_PARAMETER(ui32DataByteSize); + PVR_UNREFERENCED_PARAMETER(pui32BltData); + + return PVRSRV_OK; +#else + PVRSRV_COMMAND *psCommand; + PVRSRV_BLT_CMD_INFO *psBltCmd; + IMG_UINT32 ui32CmdByteSize; + IMG_UINT32 i; + PVRSRV_ERROR eError; + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueueBlitKM: Start")); + + if (psDevInfo->b2DHWRecoveryInProgress == IMG_TRUE) { + return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE; + } + + if ((ui32DataByteSize + SGX2D_QUEUED_BLIT_PAD) > + psDevInfo->ui322DFifoSize) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DQueueBlitKM: Blit too big for FIFO. Blit size: %d (+ padding %d), FIFO size: %d", + ui32DataByteSize, SGX2D_QUEUED_BLIT_PAD, + psDevInfo->ui322DFifoSize)); + + return PVRSRV_ERROR_CMD_TOO_BIG; + } + + ui32CmdByteSize = sizeof(PVRSRV_BLT_CMD_INFO) + + ui32DataByteSize - sizeof(IMG_UINT32); + + eError = + PVRSRVInsertCommandKM((PVRSRV_QUEUE_INFO *) psDevInfo->h2DQueue, + &psCommand, SYS_DEVICE_SGX, + SGX_2D_BLT_COMMAND, + (psDstSync == IMG_NULL) ? 0 : 1, &psDstSync, + ui32NumSrcSyncs, apsSrcSync, ui32CmdByteSize); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DQueueBlitKM: PVRSRVInsertCommandKM failed. Error %d", + eError)); +#ifdef DEBUG + if (eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) { + if (!SGX2DIsBusy(psDevInfo)) { + + PVR_DPF((PVR_DBG_ERROR, + "SGX2DQueueBlitKM: 2D core not busy, command queue full - lockup suspected")); + } + } +#endif + return eError; + } + + psBltCmd = (PVRSRV_BLT_CMD_INFO *) psCommand->pvData; + psBltCmd->ui32CmdSize = ui32CmdByteSize; + psBltCmd->psDevInfo = psDevInfo; + + psBltCmd->psDstSync = psDstSync; + + psBltCmd->ui32NumSrcSyncInfos = ui32NumSrcSyncs; + for (i = 0; i < ui32NumSrcSyncs; i++) { + + psBltCmd->apsSrcSync[i] = apsSrcSync[i]; + } + + if (pui32BltData != IMG_NULL) { + for (i = 0; i < (ui32DataByteSize >> 2); i++) { + psBltCmd->aui32BltData[i] = pui32BltData[i]; + } + } + + psBltCmd->ui32DataByteSize = ui32DataByteSize; + + eError = + PVRSRVSubmitCommandKM((PVRSRV_QUEUE_INFO *) psDevInfo->h2DQueue, + psCommand); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DQueueBlitKM: PVRSRVSubmitCommandKM failed. Error %d", + eError)); + } + + SGX2DKick(psDevInfo); + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueueBlitKM: Exit. Error: %d", + eError)); + + return eError; +#endif +} + +#if defined(SGX2D_DIRECT_BLITS) +IMG_EXPORT + PVRSRV_ERROR SGX2DDirectBlitKM(PVRSRV_SGXDEV_INFO * psDevInfo, + IMG_UINT32 ui32DataByteSize, + IMG_UINT32 * pui32BltData) +{ +#if defined(NO_HARDWARE) + PVR_UNREFERENCED_PARAMETER(psDevInfo); + PVR_UNREFERENCED_PARAMETER(ui32DataByteSize); + PVR_UNREFERENCED_PARAMETER(pui32BltData); + + return PVRSRV_OK; +#else + PVRSRV_ERROR eError; + PVRSRV_ERROR eSrvErr; + + IMG_UINT32 ui32CmdByteSize = ui32DataByteSize + 4; + IMG_BOOL bStart = IMG_FALSE; + IMG_UINT32 uiStart = 0; + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DDirectBlitKM: Start")); + + if (psDevInfo->b2DHWRecoveryInProgress == IMG_TRUE) { + return PVRSRV_ERROR_FIFO_SPACE; + } + + if (ui32CmdByteSize > psDevInfo->ui322DFifoSize) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DDirectBlitKM: Blit too big for FIFO. Blit size: %d (+ padding %d), FIFO size: %d", + ui32DataByteSize, 4, psDevInfo->ui322DFifoSize)); + + return PVRSRV_ERROR_CMD_TOO_BIG; + } + + eSrvErr = SGX2DAcquireSlavePort(psDevInfo, IMG_TRUE); + if (eSrvErr != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DDirectBlitKM: Cannot acquire slaveport. Error %d", + eSrvErr)); + return eSrvErr; + } +#ifdef FIXME + +#endif + do { + eSrvErr = SGX2DAcquireFifoSpace(psDevInfo, + ui32CmdByteSize, IMG_NULL); + if (eSrvErr == PVRSRV_OK) { + break; + } + + if (bStart == IMG_FALSE) { + uiStart = OSClockus(); + bStart = IMG_TRUE; + } + + OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT); + } while ((OSClockus() - uiStart) < MAX_HW_TIME_US); + + if (eSrvErr != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DDirectBlitKM: Cannot acquire FIFO space. Error %d", + eSrvErr)); + + eError = eSrvErr; + } else { + + if (psDevInfo->b2DHWRecoveryEndPending + && SGX2D_2D_NOT_IDLE(psDevInfo)) { + eError = PVRSRV_ERROR_FIFO_SPACE; + } else { + eError = PVRSRV_OK; + + psDevInfo->b2DHWRecoveryEndPending = IMG_FALSE; + + SGX2DWriteSlavePortBatch(psDevInfo, pui32BltData, + ui32DataByteSize); + + SGX2DWriteSlavePort(psDevInfo, SGX2D_FENCE_BH); + } + } + + eSrvErr = SGX2DReleaseSlavePort(psDevInfo); + if (eSrvErr != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DDirectBlitKM: Cannot release slave port. Error %d", + eSrvErr)); + + if (eError != PVRSRV_OK) { + eError = eSrvErr; + } + } + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DDirectBlitKM: Exit. Error: %d", + eError)); + + SGX2DKick(psDevInfo); + + return eError; +#endif +} +#endif + +#endif + +#if defined(SGX_FEATURE_2D_HARDWARE) || defined(PVR2D_ALT_2DHW) +#ifdef INLINE_IS_PRAGMA +#pragma inline(SGX2DQuerySyncOpsComplete) +#endif +static INLINE + IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO * psSyncInfo) +{ + PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData; + + return (IMG_BOOL) ((psSyncData->ui32ReadOpsComplete == + psSyncData->ui32ReadOpsPending) + && (psSyncData->ui32WriteOpsComplete == + psSyncData->ui32WriteOpsPending) + ); +} + +IMG_EXPORT + PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO * psDevInfo, + PVRSRV_KERNEL_SYNC_INFO * psSyncInfo, + IMG_BOOL bWaitForComplete) +{ + IMG_BOOL bStart = IMG_FALSE; + IMG_UINT32 uiStart = 0; + + PVR_UNREFERENCED_PARAMETER(psDevInfo); + + PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start")); + + if (SGX2DQuerySyncOpsComplete(psSyncInfo)) { + + PVR_DPF((PVR_DBG_CALLTRACE, + "SGX2DQueryBlitsCompleteKM: No wait. Blits complete.")); + return PVRSRV_OK; + } + + if (!bWaitForComplete) { + + PVR_DPF((PVR_DBG_CALLTRACE, + "SGX2DQueryBlitsCompleteKM: No wait. Ops pending.")); + return PVRSRV_ERROR_CMD_NOT_PROCESSED; + } + + PVR_DPF((PVR_DBG_MESSAGE, + "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling.")); + do { + OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT); + + if (SGX2DQuerySyncOpsComplete(psSyncInfo)) { + + PVR_DPF((PVR_DBG_CALLTRACE, + "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete.")); + return PVRSRV_OK; + } + + if (bStart == IMG_FALSE) { + uiStart = OSClockus(); + bStart = IMG_TRUE; + } + + OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT); + } while ((OSClockus() - uiStart) < MAX_HW_TIME_US); + + PVR_DPF((PVR_DBG_ERROR, + "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending.")); + +#if defined(DEBUG) + { + PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData; + + PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: %p, Syncdata: %p", psSyncInfo, psSyncData)); + + PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending)); + PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending)); + + } +#endif + + return PVRSRV_ERROR_TIMEOUT; +} +#endif + +#if defined(SGX_FEATURE_2D_HARDWARE) +PVRSRV_ERROR SGX2DInit(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + PVRSRV_ERROR eError; + + PVR_ASSERT(psDevInfo->ui322DFifoSize == 0); + psDevInfo->ui322DFifoSize = SGX2DFifoFreeSpace(psDevInfo); + + PVR_TRACE(("SGX2DInit: 2D FIFO size: %d", psDevInfo->ui322DFifoSize)); + + PVR_ASSERT(psDevInfo->s2DSlavePortKM.pui32Offset == 0); + PVR_ASSERT(psDevInfo->ui322DFifoOffset == 0); + psDevInfo->s2DSlavePortKM.pui32Offset = &psDevInfo->ui322DFifoOffset; + + PVR_ASSERT(psDevInfo->h2DQueue == IMG_NULL); + eError = PVRSRVCreateCommandQueueKM(SGX2D_COMMAND_QUEUE_SIZE, + (PVRSRV_QUEUE_INFO **) & psDevInfo-> + h2DQueue); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DInit: PVRSRVCreateCommandQueueKM failed (%d)", + eError)); + + return eError; + } + + PVR_ASSERT(psDevInfo->h2DCmdCookie == IMG_NULL); + PVR_ASSERT(!psDevInfo->b2DHWRecoveryInProgress); + PVR_ASSERT(!psDevInfo->b2DHWRecoveryEndPending); + PVR_ASSERT(psDevInfo->ui322DCompletedBlits == 0); + + return PVRSRV_OK; +} + +PVRSRV_ERROR SGX2DDeInit(PVRSRV_SGXDEV_INFO * psDevInfo) +{ + PVRSRV_ERROR eError; + + if (psDevInfo->h2DQueue != IMG_NULL) { + eError = + PVRSRVDestroyCommandQueueKM((PVRSRV_QUEUE_INFO *) + psDevInfo->h2DQueue); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGX2DDeInit: PVRSRVDestroyCommandQueueKM failed (%d)", + eError)); + + return eError; + } + } + + return PVRSRV_OK; +} + +#endif diff --git a/pvr/sgxapi_km.h b/pvr/sgxapi_km.h index ea7ba9b..4ce6525 100644 --- a/pvr/sgxapi_km.h +++ b/pvr/sgxapi_km.h @@ -57,9 +57,11 @@ extern "C" { #if defined(SGX_FEATURE_2D_HARDWARE) #define SGX_2D_HEAP_ID 12 -#define SGX_MAX_HEAP_ID 13 +#define SGX_ALT_MAPPING_HEAP_ID 13 +#define SGX_MAX_HEAP_ID 14 #else -#define SGX_MAX_HEAP_ID 12 +#define SGX_ALT_MAPPING_HEAP_ID 12 +#define SGX_MAX_HEAP_ID 13 #endif #define SGX_MAX_TA_STATUS_VALS 32 diff --git a/pvr/sgxconfig.h b/pvr/sgxconfig.h index 5f0d4d2..9f8da2d 100644 --- a/pvr/sgxconfig.h +++ b/pvr/sgxconfig.h @@ -81,8 +81,11 @@ #if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28 #define SGX_ADDRESS_SPACE_SIZE 28 -#define SGX_GENERAL_HEAP_BASE 0x00400000 -#define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00401000) +#define SGX_GENERAL_HEAP_BASE 0x00400000 +#define SGX_GENERAL_HEAP_SIZE (0x05000000-0x00401000) + +#define SGX_GENERAL_MAPPING_HEAP_BASE 0x05000000 +#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x07000000-0x05001000) #define SGX_TADATA_HEAP_BASE 0x07000000 #define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000) @@ -90,8 +93,8 @@ #define SGX_3DPARAMETERS_HEAP_BASE 0x08000000 #define SGX_3DPARAMETERS_HEAP_SIZE (0x04000000-0x00001000) -#define SGX_GENERAL_MAPPING_HEAP_BASE 0x0C000000 -#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01000000-0x00001000) +#define SGX_ALT_MAPPING_HEAP_BASE (0x0C000000) +#define SGX_ALT_MAPPING_HEAP_SIZE (0x0D000000 - 0x0C001000) #define SGX_PIXELSHADER_HEAP_BASE 0x0D000000 #define SGX_PIXELSHADER_HEAP_SIZE 0x00500000 diff --git a/pvr/sgxinfokm.h b/pvr/sgxinfokm.h index 3c413a4..0a84a86 100644 --- a/pvr/sgxinfokm.h +++ b/pvr/sgxinfokm.h @@ -39,10 +39,12 @@ extern "C" { #define SGX_HOSTPORT_PRESENT 0x00000001UL -#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST (1UL << 0) -#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 1) -#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 2) -#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 3) +#define PVRSRV_USSE_EDM_POWMAN_IDLE_REQUEST (1UL << 0) +#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST (1UL << 1) +#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2) +#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3) +#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4) +#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5) #define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0) #define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1) @@ -210,7 +212,10 @@ extern "C" { IMG_UINT32 ui32IRQ; +#if !defined(SGX_DYNAMIC_TIMING_INFO) + SGX_TIMING_INFORMATION sTimingInfo; +#endif } SGX_DEVICE_MAP; typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC; @@ -241,6 +246,11 @@ extern "C" { IMG_VOID SGXOSTimer(IMG_VOID * pvData); +#if defined(SGX_DYNAMIC_TIMING_INFO) + IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION * + psSGXTimingInfo); +#endif + #if defined(NO_HARDWARE) static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO * psDevInfo, diff --git a/pvr/sgxinit.c b/pvr/sgxinit.c index 18bbe1f..e80e94f 100644 --- a/pvr/sgxinit.c +++ b/pvr/sgxinit.c @@ -25,6 +25,8 @@ ******************************************************************************/ #include +#include +#include #include "sgxdefs.h" #include "sgxmmu.h" @@ -59,6 +61,43 @@ static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo, IMG_BOOL bHardwareRecovery); PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie); +typedef enum _PVR_DEVICE_POWER_STATE_ { + PVR_DEVICE_POWER_STATE_ON = 0, + PVR_DEVICE_POWER_STATE_IDLE = 1, + PVR_DEVICE_POWER_STATE_OFF = 2, + + PVR_DEVICE_POWER_STATE_FORCE_I32 = 0x7fffffff +} PVR_DEVICE_POWER_STATE, *PPVR_DEVICE_POWER_STATE; + +static PVR_DEVICE_POWER_STATE MapDevicePowerState(PVR_POWER_STATE ePowerState) +{ + PVR_DEVICE_POWER_STATE eDevicePowerState; + + switch (ePowerState) { + case PVRSRV_POWER_STATE_D0: + { + eDevicePowerState = PVR_DEVICE_POWER_STATE_ON; + break; + } + case PVRSRV_POWER_STATE_D3: + { + eDevicePowerState = PVR_DEVICE_POWER_STATE_OFF; + break; + } + default: + { + PVR_DPF((PVR_DBG_ERROR, + "MapDevicePowerState: Invalid state: %ld", + ePowerState)); + eDevicePowerState = PVR_DEVICE_POWER_STATE_FORCE_I32; + PVR_ASSERT(eDevicePowerState != + PVR_DEVICE_POWER_STATE_FORCE_I32); + } + } + + return eDevicePowerState; +} + static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE * psDeviceNode) { SGXScheduleProcessQueues(psDeviceNode); @@ -173,228 +212,337 @@ failed_allockernelccb: return eError; } -static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo) +static IMG_VOID SGXGetTimingInfo(PVRSRV_DEVICE_NODE * psDeviceNode) +{ + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; +#if defined(SGX_DYNAMIC_TIMING_INFO) + SGX_TIMING_INFORMATION sSGXTimingInfo = { 0 }; +#else + SGX_DEVICE_MAP *psSGXDeviceMap; +#endif + IMG_UINT32 ui32ActivePowManSampleRate; + SGX_TIMING_INFORMATION *psSGXTimingInfo; + +#if defined(SGX_DYNAMIC_TIMING_INFO) + psSGXTimingInfo = &sSGXTimingInfo; + SysGetSGXTimingInformation(psSGXTimingInfo); +#else + SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, + (IMG_VOID **) & psSGXDeviceMap); + psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo; +#endif + +#if defined(SUPPORT_HW_RECOVERY) + { + PVRSRV_ERROR eError; + IMG_UINT32 ui32OlduKernelFreq; + + if (psDevInfo->hTimer != IMG_NULL) { + ui32OlduKernelFreq = + psDevInfo->ui32CoreClockSpeed / + psDevInfo->ui32uKernelTimerClock; + if (ui32OlduKernelFreq != + psSGXTimingInfo->ui32uKernelFreq) { + eError = OSRemoveTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGXGetTimingInfo: Failed to remove timer")); + } + psDevInfo->hTimer = IMG_NULL; + } + } + if (psDevInfo->hTimer == IMG_NULL) { + + psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode, + 1000 * 50 / + psSGXTimingInfo-> + ui32uKernelFreq); + if (psDevInfo->hTimer == IMG_NULL) { + PVR_DPF((PVR_DBG_ERROR, + "SGXGetTimingInfo : Failed to register timer callback function")); + } + } + + psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate = + psSGXTimingInfo->ui32uKernelFreq / + psSGXTimingInfo->ui32HWRecoveryFreq; + } +#endif + + psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed; + psDevInfo->ui32uKernelTimerClock = + psSGXTimingInfo->ui32CoreClockSpeed / + psSGXTimingInfo->ui32uKernelFreq; + + ui32ActivePowManSampleRate = + psSGXTimingInfo->ui32uKernelFreq * + psSGXTimingInfo->ui32ActivePowManLatencyms / 1000; + ui32ActivePowManSampleRate += 1; + psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = + ui32ActivePowManSampleRate; +} + +static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo, + IMG_BOOL bStartOSTimer) { - IMG_UINT32 ui32RegVal = + IMG_UINT32 ui32RegVal; + +#if !defined(SUPPORT_HW_RECOVERY) + PVR_UNREFERENCED_PARAMETER(bStartOSTimer); +#endif + + ui32RegVal = EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock; OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal); PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal, PDUMP_FLAGS_CONTINUOUS); + +#if defined(SUPPORT_HW_RECOVERY) + if (bStartOSTimer) { + PVRSRV_ERROR eError; + eError = OSEnableTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGXStartTimer : Failed to enable host timer")); + } + } +#endif } -PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle, - PVR_POWER_STATE eNewPowerState, - PVR_POWER_STATE eCurrentPowerState) +static PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle, + PVR_DEVICE_POWER_STATE eNewPowerState, + PVR_DEVICE_POWER_STATE eCurrentPowerState) { - if (eNewPowerState != eCurrentPowerState) { - PVRSRV_DEVICE_NODE *psDeviceNode = - (PVRSRV_DEVICE_NODE *) hDevHandle; - PVRSRV_SGXDEV_INFO *psDevInfo = - (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice; - - if (eNewPowerState == PVRSRV_POWER_STATE_D3) { - PVRSRV_SGX_HOST_CTL *psSGXHostCtl = - psDevInfo->psSGXHostCtl; - -#if defined (SGX_FEATURE_AUTOCLOCKGATING) && (!defined(NO_HARDWARE) || defined(PDUMP)) - IMG_UINT32 ui32ClockMask = - psDevInfo->ui32ClkGateStatusMask; -#endif + if ((eNewPowerState != eCurrentPowerState) && + (eNewPowerState != PVR_DEVICE_POWER_STATE_ON)) { + PVRSRV_ERROR eError; + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; + IMG_UINT32 ui32PowManRequest, ui32PowManComplete; #if defined(SUPPORT_HW_RECOVERY) - - if (OSDisableTimer(psDevInfo->hTimer) != PVRSRV_OK) { - PVR_DPF((PVR_DBG_ERROR, - "SGXPrePowerState: Failed to disable timer")); - return PVRSRV_ERROR_GENERIC; - } + eError = OSDisableTimer(psDevInfo->hTimer); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGXPrePowerState: Failed to disable timer")); + return eError; + } #endif - psSGXHostCtl->ui32PowManFlags |= + if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) { + ui32PowManRequest = PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST; - + ui32PowManComplete = + PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE; PDUMPCOMMENT - ("TA/3D CCB Control - Trigger power down event on uKernel..."); - PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, - offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags), - sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, - MAKEUNIQUETAG(psDevInfo-> - psKernelSGXHostCtlMemInfo)); + ("TA/3D CCB Control - SGX power off request"); + } else { + ui32PowManRequest = PVRSRV_USSE_EDM_POWMAN_IDLE_REQUEST; + ui32PowManComplete = + PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE; + PDUMPCOMMENT("TA/3D CCB Control - SGX idle request"); + } -#if !defined(NO_HARDWARE) - if (PollForValueKM - ((volatile IMG_UINT32 *)(&psSGXHostCtl-> - ui32PowManFlags), - PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE, - PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE, - MAX_HW_TIME_US / WAIT_TRY_COUNT, - WAIT_TRY_COUNT) != PVRSRV_OK) { - PVR_DPF((PVR_DBG_ERROR, - "SGXPrePowerState: Wait for chip power off failed.")); - } + psSGXHostCtl->ui32PowManFlags |= ui32PowManRequest; +#if defined(PDUMP) + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); #endif -#ifdef PDUMP - - PDUMPCOMMENT - ("TA/3D CCB Control - Wait for power down event on uKernel..."); - PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo, - offsetof(PVRSRV_SGX_HOST_CTL, - ui32PowManFlags), - PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE, - PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE, - PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, - IMG_FALSE, - MAKEUNIQUETAG(psDevInfo-> - psKernelSGXHostCtlMemInfo)); +#if !defined(NO_HARDWARE) + if (PollForValueKM(&psSGXHostCtl->ui32PowManFlags, + ui32PowManComplete, + ui32PowManComplete, + MAX_HW_TIME_US / WAIT_TRY_COUNT, + WAIT_TRY_COUNT) != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGXPrePowerState: Wait for SGX ukernel power transition failed.")); + } #endif - SGXDeinitialise(psDevInfo); +#if defined(PDUMP) + PDUMPCOMMENT + ("TA/3D CCB Control - Wait for power event on uKernel."); + PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags), + ui32PowManComplete, ui32PowManComplete, + PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE, + MAKEUNIQUETAG(psDevInfo-> + psKernelSGXHostCtlMemInfo)); +#endif #if defined(SGX_FEATURE_AUTOCLOCKGATING) + { #if !defined(NO_HARDWARE) if (PollForValueKM - ((volatile IMG_UINT32 *)((IMG_UINT8 *) psDevInfo-> - pvRegsBaseKM + - EUR_CR_CLKGATESTATUS), 0, - ui32ClockMask, MAX_HW_TIME_US / WAIT_TRY_COUNT, + ((IMG_UINT32 *) psDevInfo->pvRegsBaseKM + + (EUR_CR_CLKGATESTATUS >> 2), 0, + psDevInfo->ui32ClkGateStatusMask, + MAX_HW_TIME_US / WAIT_TRY_COUNT, WAIT_TRY_COUNT) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, - "SGXPrePowerState: Wait for chip idle failed.")); + "SGXPrePowerState: Wait for SGX clock gating failed.")); } #endif - PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0, ui32ClockMask); + + PDUMPCOMMENT("Wait for SGX clock gating."); + PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0, + psDevInfo->ui32ClkGateStatusMask); + } #endif + + if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) { + eError = SGXDeinitialise(psDevInfo); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SGXPrePowerState: SGXDeinitialise failed: %lu", + eError)); + return eError; + } } } return PVRSRV_OK; } -PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle, - PVR_POWER_STATE eNewPowerState, - PVR_POWER_STATE eCurrentPowerState) +static PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle, + PVR_DEVICE_POWER_STATE eNewPowerState, + PVR_DEVICE_POWER_STATE eCurrentPowerState) { - if (eNewPowerState != eCurrentPowerState) { + if ((eNewPowerState != eCurrentPowerState) && + (eCurrentPowerState != PVR_DEVICE_POWER_STATE_ON)) { PVRSRV_ERROR eError; - PVRSRV_DEVICE_NODE *psDeviceNode = - (PVRSRV_DEVICE_NODE *) hDevHandle; - PVRSRV_SGXDEV_INFO *psDevInfo = - (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice; - SYS_DATA *psSysData; - - eError = SysAcquireData(&psSysData); - if (eError != PVRSRV_OK) { - return eError; - } + PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; + PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; - if (eCurrentPowerState == PVRSRV_POWER_STATE_D3) { - PVRSRV_SGX_HOST_CTL *psSGXHostCtl = - psDevInfo->psSGXHostCtl; + psSGXHostCtl->ui32PowManFlags = 0; + PDUMPCOMMENT("TA/3D CCB Control - Reset Power Manager flags"); +#if defined(PDUMP) + PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, + offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags), + sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, + MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo)); +#endif - psSGXHostCtl->ui32PowManFlags = 0; + if (eCurrentPowerState == PVR_DEVICE_POWER_STATE_OFF) { - PDUMPCOMMENT - ("TA/3D CCB Control - Reset Power Manager flags"); - PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo, - offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags), - sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS, - MAKEUNIQUETAG(psDevInfo-> - psKernelSGXHostCtlMemInfo)); + SGXGetTimingInfo(psDeviceNode); eError = SGXInitialise(psDevInfo, IMG_FALSE); - if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXPostPowerState: SGXInitialise failed")); return eError; } -#if defined(SUPPORT_HW_RECOVERY) - eError = OSEnableTimer(psDevInfo->hTimer); - if (eError != PVRSRV_OK) { - PVR_DPF((PVR_DBG_ERROR, - "SGXPostPowerState : Failed to enable host timer")); - return PVRSRV_ERROR_GENERIC; - } -#endif } - - PVR_DPF((PVR_DBG_WARNING, - "SGXPostPowerState : SGX Power Transition from %d to %d OK", - eCurrentPowerState, eNewPowerState)); } return PVRSRV_OK; } -static IMG_VOID SGXGetTimingInfo(PVRSRV_SGXDEV_INFO * psDevInfo, - SGX_TIMING_INFORMATION * psSGXTimingInfo) +PVRSRV_ERROR SGXPrePowerStateExt(IMG_HANDLE hDevHandle, + PVR_POWER_STATE eNewPowerState, + PVR_POWER_STATE eCurrentPowerState) { - IMG_UINT32 ui32ActivePowManSampleRate; + PVR_DEVICE_POWER_STATE eNewDevicePowerState = + MapDevicePowerState(eNewPowerState); + PVR_DEVICE_POWER_STATE eCurrentDevicePowerState = + MapDevicePowerState(eCurrentPowerState); - psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed; - psDevInfo->ui32uKernelTimerClock = - psSGXTimingInfo->ui32CoreClockSpeed / - psSGXTimingInfo->ui32uKernelFreq; + return SGXPrePowerState(hDevHandle, eNewDevicePowerState, + eCurrentDevicePowerState); +} -#if defined(SUPPORT_HW_RECOVERY) - psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate = - psSGXTimingInfo->ui32uKernelFreq / - psSGXTimingInfo->ui32HWRecoveryFreq; -#endif +PVRSRV_ERROR SGXPostPowerStateExt(IMG_HANDLE hDevHandle, + PVR_POWER_STATE eNewPowerState, + PVR_POWER_STATE eCurrentPowerState) +{ + PVRSRV_ERROR eError; + PVR_DEVICE_POWER_STATE eNewDevicePowerState = + MapDevicePowerState(eNewPowerState); + PVR_DEVICE_POWER_STATE eCurrentDevicePowerState = + MapDevicePowerState(eCurrentPowerState); - ui32ActivePowManSampleRate = - psSGXTimingInfo->ui32uKernelFreq * - psSGXTimingInfo->ui32ActivePowManLatencyms / 1000; + eError = + SGXPostPowerState(hDevHandle, eNewDevicePowerState, + eCurrentDevicePowerState); + if (eError != PVRSRV_OK) { + return eError; + } - ui32ActivePowManSampleRate += 1; + PVR_DPF((PVR_DBG_WARNING, + "SGXPostPowerState : SGX Power Transition from %d to %d OK", + eCurrentPowerState, eNewPowerState)); - psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = - ui32ActivePowManSampleRate; + return eError; } static PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle, - IMG_BOOL bIdleDevice) + IMG_BOOL bIdleDevice, + PVR_POWER_STATE eCurrentPowerState) { PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; - SGX_DEVICE_MAP *psSGXDeviceMap; - eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX, - (IMG_VOID **) & psSGXDeviceMap); - if (eError != PVRSRV_OK) { - PVR_DPF((PVR_DBG_ERROR, - "DevInitSGXPart2KM: Failed to get device memory map!")); - return PVRSRV_ERROR_INIT_FAILURE; - } + PVR_UNREFERENCED_PARAMETER(psDevInfo); - if (bIdleDevice) { + if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) { + if (bIdleDevice) { - } + eError = + SGXPrePowerState(hDevHandle, + PVR_DEVICE_POWER_STATE_IDLE, + PVR_DEVICE_POWER_STATE_ON); - SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo); + if (eError != PVRSRV_OK) { + return eError; + } + } + } PVR_DPF((PVR_DBG_MESSAGE, - "SGXPreClockSpeedChange: SGX clock speed now %luHz", + "SGXPreClockSpeedChange: SGX clock speed was %luHz", psDevInfo->ui32CoreClockSpeed)); return PVRSRV_OK; } static PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle, - IMG_BOOL bIdleDevice) + IMG_BOOL bIdleDevice, + PVR_POWER_STATE eCurrentPowerState) { + PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle; PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; + IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed; - if (bIdleDevice) { + PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed); - } else { - SGXStartTimer(psDevInfo); + if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) { + SGXGetTimingInfo(psDeviceNode); + if (bIdleDevice) { + eError = + SGXPostPowerState(hDevHandle, + PVR_DEVICE_POWER_STATE_ON, + PVR_DEVICE_POWER_STATE_IDLE); + + if (eError != PVRSRV_OK) { + return eError; + } + } + SGXStartTimer(psDevInfo, IMG_TRUE); } + PVR_DPF((PVR_DBG_MESSAGE, + "SGXPostClockSpeedChange: SGX clock speed changed from %luHz to %luHz", + ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed)); + return PVRSRV_OK; } @@ -514,7 +662,7 @@ static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo, return (PVRSRV_ERROR_GENERIC); } - SGXStartTimer(psDevInfo); + SGXStartTimer(psDevInfo, !bHardwareRecovery); if (bHardwareRecovery) { PVRSRV_SGX_HOST_CTL *psSGXHostCtl = @@ -748,8 +896,6 @@ IMG_EXPORT psDevInfo->s2DSlavePortKM.sPhysBase = psSGXDeviceMap->sSPSysPBase; #endif - SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo); - #if defined (SYS_USING_INTERRUPTS) psDeviceNode->pvISRData = psDeviceNode; @@ -767,7 +913,8 @@ IMG_EXPORT eDefaultPowerState = PVRSRV_POWER_STATE_D0; #endif eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex, - SGXPrePowerState, SGXPostPowerState, + SGXPrePowerStateExt, + SGXPostPowerStateExt, SGXPreClockSpeedChange, SGXPostClockSpeedChange, (IMG_HANDLE) psDeviceNode, @@ -797,19 +944,6 @@ IMG_EXPORT PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo)); -#if defined(SUPPORT_HW_RECOVERY) - - psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode, - 1000 * 50 / - psSGXDeviceMap->sTimingInfo. - ui32uKernelFreq); - if (psDevInfo->hTimer == IMG_NULL) { - PVR_DPF((PVR_DBG_ERROR, - "DevInitSGXPart2KM : Failed to register timer callback function")); - return PVRSRV_ERROR_GENERIC; - } -#endif - return PVRSRV_OK; failed_init_dev_info: @@ -994,6 +1128,21 @@ IMG_VOID HWRecoveryResetSGX(PVRSRV_DEVICE_NODE * psDeviceNode, } #endif +static struct workdata { + PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_UINT32 ui32Component; + IMG_UINT32 ui32CallerID; +} gHWRecoveryParams; + +static void HWRecoveryWrapper(struct work_struct *work) +{ + HWRecoveryResetSGX(gHWRecoveryParams.psDeviceNode, + gHWRecoveryParams.ui32Component, + gHWRecoveryParams.ui32CallerID); +} + +DECLARE_WORK(gWork, HWRecoveryWrapper); + #if defined(SUPPORT_HW_RECOVERY) IMG_VOID SGXOSTimer(IMG_VOID * pvData) { @@ -1046,7 +1195,14 @@ IMG_VOID SGXOSTimer(IMG_VOID * pvData) psSGXHostCtl->ui32HostDetectedLockups++; - HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID); + /* + * schedule HWRecoveryResetSGX from a work + * in the shared queue + */ + gHWRecoveryParams.psDeviceNode = psDeviceNode; + gHWRecoveryParams.ui32Component = 0; + gHWRecoveryParams.ui32CallerID = TIMER_ID; + schedule_work(&gWork); } } #endif @@ -1094,9 +1250,6 @@ IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData) OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear); - //Read back to flush posted write to fix spurious IRQ - OSReadHWReg(psDevInfo->pvRegsBaseKM, - EUR_CR_EVENT_HOST_CLEAR); } } @@ -1384,6 +1537,20 @@ PVRSRV_ERROR SGXRegisterDevice(PVRSRV_DEVICE_NODE * psDeviceNode) psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32HeapID = + HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_ALT_MAPPING_HEAP_ID); + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr = + SGX_ALT_MAPPING_HEAP_BASE; + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32HeapSize = + SGX_ALT_MAPPING_HEAP_SIZE; + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32Attribs = + PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS; + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].pszName = "AltMapping"; + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].pszBSName = "AltMapping BS"; + + psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].DevMemHeapType = + DEVICE_MEMORY_HEAP_SHARED_EXPORTED; + #if defined(SGX_FEATURE_2D_HARDWARE) psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32HeapID = diff --git a/pvr/sysconfig.c b/pvr/sysconfig.c index 6a6fa74..3ef2dc4 100644 --- a/pvr/sysconfig.c +++ b/pvr/sysconfig.c @@ -37,6 +37,7 @@ SYS_DATA *gpsSysData = (SYS_DATA *) IMG_NULL; SYS_DATA gsSysData; static SYS_SPECIFIC_DATA gsSysSpecificData; +SYS_SPECIFIC_DATA *gpsSysSpecificData; static IMG_UINT32 gui32SGXDeviceID; static SGX_DEVICE_MAP gsSGXDeviceMap; @@ -167,13 +168,17 @@ PVRSRV_ERROR SysInitialise(IMG_VOID) PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode; IMG_CPU_PHYADDR TimerRegPhysBase; +#if !defined(SGX_DYNAMIC_TIMING_INFO) SGX_TIMING_INFORMATION *psTimingInfo; +#endif gpsSysData = &gsSysData; OSMemSet(gpsSysData, 0, sizeof(SYS_DATA)); - gpsSysData->pvSysSpecificData = &gsSysSpecificData; - gsSysSpecificData.ui32SysSpecificData = 0; + gpsSysSpecificData = &gsSysSpecificData; + OSMemSet(gpsSysSpecificData, 0, sizeof(SYS_SPECIFIC_DATA)); + + gpsSysData->pvSysSpecificData = gpsSysSpecificData; eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData); if (eError != PVRSRV_OK) { @@ -205,7 +210,8 @@ PVRSRV_ERROR SysInitialise(IMG_VOID) return eError; } - TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE; + TimerRegPhysBase.uiAddr = + SYS_OMAP3430_GP11TIMER_PHYS_BASE + SYS_OMAP3430_GPTIMER_REGS; gpsSysData->pvSOCTimerRegisterKM = IMG_NULL; gpsSysData->hSOCTimerRegisterOSMemHandle = 0; OSReservePhys(TimerRegPhysBase, @@ -214,12 +220,15 @@ PVRSRV_ERROR SysInitialise(IMG_VOID) (IMG_VOID **) & gpsSysData->pvSOCTimerRegisterKM, &gpsSysData->hSOCTimerRegisterOSMemHandle); +#if !defined(SGX_DYNAMIC_TIMING_INFO) + psTimingInfo = &gsSGXDeviceMap.sTimingInfo; psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED; psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ; psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS; psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ; +#endif eError = SysLocateDevices(gpsSysData); if (eError != PVRSRV_OK) { @@ -283,7 +292,17 @@ PVRSRV_ERROR SysInitialise(IMG_VOID) SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT); - eError = EnableSystemClocks(gpsSysData, &gsSGXDeviceMap.sTimingInfo); + eError = InitSystemClocks(gpsSysData); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SysInitialise: Failed to init system clocks (%d)", + eError)); + SysDeinitialise(gpsSysData); + gpsSysData = IMG_NULL; + return eError; + } + + eError = EnableSystemClocks(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SysInitialise: Failed to Enable system clocks (%d)", @@ -294,6 +313,15 @@ PVRSRV_ERROR SysInitialise(IMG_VOID) } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS); + + eError = OSInitPerf(gpsSysData); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SysInitialise: Failed to init DVFS (%d)", eError)); + SysDeinitialise(gpsSysData); + gpsSysData = IMG_NULL; + return eError; + } #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) eError = EnableSGXClocks(gpsSysData); if (eError != PVRSRV_OK) { @@ -381,6 +409,8 @@ PVRSRV_ERROR SysFinalise(IMG_VOID) DisableSGXClocks(gpsSysData); #endif + gpsSysSpecificData->bSGXInitComplete = IMG_TRUE; + return eError; } @@ -388,14 +418,11 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData) { PVRSRV_ERROR eError; - SYS_SPECIFIC_DATA *psSysSpecData = - (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; - PVR_UNREFERENCED_PARAMETER(psSysData); #if defined(SYS_USING_INTERRUPTS) if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LISR)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR)) { eError = OSUninstallDeviceLISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, @@ -405,7 +432,7 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData) } if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_MISR)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR)) { eError = OSUninstallMISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, @@ -415,11 +442,19 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData) } #endif + eError = OSCleanupPerf(gpsSysSpecificData); + if (eError != PVRSRV_OK) { + PVR_DPF((PVR_DBG_ERROR, + "SysDeinitialise: OSCleanupDvfs failed")); + return eError; + } + if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) { #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) PVR_ASSERT(SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)); + (gpsSysSpecificData, + SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)); eError = EnableSGXClocks(gpsSysData); if (eError != PVRSRV_OK) { @@ -438,12 +473,14 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData) } if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) { DisableSystemClocks(gpsSysData); } + CleanupSystemClocks(gpsSysData); + if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) { eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, @@ -463,7 +500,7 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData) #if defined(NO_HARDWARE) if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV)) { OSBaseFreeContigMemory(SYS_OMAP3430_SGX_REGS_SIZE, gsSGXRegsCPUVAddr, @@ -472,11 +509,13 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData) #endif if (SYS_SPECIFIC_DATA_TEST - (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT)) { + (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT)) { PDUMPDEINIT(); } - psSysSpecData->ui32SysSpecificData = 0; + gpsSysSpecificData->ui32SysSpecificData = 0; + gpsSysSpecificData->bSGXInitComplete = IMG_FALSE; + gpsSysData = IMG_NULL; return PVRSRV_OK; @@ -583,6 +622,9 @@ IMG_VOID SysClearInterrupts(SYS_DATA * psSysData, IMG_UINT32 ui32ClearBits) PVR_UNREFERENCED_PARAMETER(psSysData); PVR_UNREFERENCED_PARAMETER(ui32ClearBits); + /* Flush posted write for the irq status to avoid spurious interrupts */ + OSReadHWReg(((PVRSRV_SGXDEV_INFO *) gpsSGXDevNode->pvDevice)-> + pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR); } PVRSRV_ERROR SysSystemPrePowerState(PVR_POWER_STATE eNewPowerState) @@ -633,9 +675,7 @@ PVRSRV_ERROR SysSystemPostPowerState(PVR_POWER_STATE eNewPowerState) if (SYS_SPECIFIC_DATA_TEST (&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS)) { - eError = - EnableSystemClocks(gpsSysData, - &gsSGXDeviceMap.sTimingInfo); + eError = EnableSystemClocks(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SysSystemPostPowerState: EnableSystemClocks failed (%d)", diff --git a/pvr/sysconfig.h b/pvr/sysconfig.h index 81ce9ad..2d7f474 100644 --- a/pvr/sysconfig.h +++ b/pvr/sysconfig.h @@ -44,8 +44,10 @@ #define SYS_OMAP3430_SGX_IRQ 21 -#define SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE 0x48088024 -#define SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE 0x48088028 -#define SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE 0x48088040 +#define SYS_OMAP3430_GP11TIMER_PHYS_BASE 0x48088000 +#define SYS_OMAP3430_GPTIMER_ENABLE 0x24 +#define SYS_OMAP3430_GPTIMER_REGS 0x28 +#define SYS_OMAP3430_GPTIMER_TSICR 0x40 +#define SYS_OMAP3430_GPTIMER_SIZE 1024 #endif diff --git a/pvr/syslocal.h b/pvr/syslocal.h index c541e7a..e12406a 100644 --- a/pvr/syslocal.h +++ b/pvr/syslocal.h @@ -30,13 +30,9 @@ #if defined(__linux__) #include #include -#if defined (SUPPORT_TI_PM) -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) -#include -#endif -#else #include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) +/*#include */ #endif #endif @@ -46,10 +42,10 @@ extern "C" { IMG_CHAR *SysCreateVersionString(IMG_CPU_PHYADDR sRegRegion); + PVRSRV_ERROR InitSystemClocks(SYS_DATA * psSysData); + IMG_VOID CleanupSystemClocks(SYS_DATA * psSysData); IMG_VOID DisableSystemClocks(SYS_DATA * psSysData); - PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData, - SGX_TIMING_INFORMATION * - psSGXTimingInfo); + PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData); IMG_VOID DisableSGXClocks(SYS_DATA * psSysData); PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData); @@ -75,11 +71,10 @@ extern "C" { typedef struct _SYS_SPECIFIC_DATA_TAG_ { IMG_UINT32 ui32SysSpecificData; - IMG_BOOL bSGXClocksEnabled; PVRSRV_DEVICE_NODE *psSGXDevNode; + IMG_BOOL bSGXInitComplete; + IMG_BOOL bSGXClocksEnabled; #if defined(__linux__) - IMG_BOOL bSysClocksOneTimeInit; - struct clk *psCORE_CK; struct clk *psSGX_FCK; struct clk *psSGX_ICK; @@ -87,19 +82,16 @@ extern "C" { #if defined(DEBUG) || defined(TIMING) struct clk *psGPT11_FCK; struct clk *psGPT11_ICK; + void __iomem *gpt_base; #endif -#if defined (SUPPORT_TI_PM) #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - SGX_TIMING_INFORMATION *psSGXTimingInfo; - struct constraint_handle *pVdd2Handle; #endif -#endif - - struct semaphore sConstraintNotifierLock; #endif } SYS_SPECIFIC_DATA; + extern SYS_SPECIFIC_DATA *gpsSysSpecificData; + #if defined(__cplusplus) } #endif diff --git a/pvr/sysutils_linux.c b/pvr/sysutils_linux.c index 1d1e848..0dee22f 100644 --- a/pvr/sysutils_linux.c +++ b/pvr/sysutils_linux.c @@ -28,13 +28,9 @@ #include #include #include +#include #include -#if defined (SUPPORT_TI_PM) -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) -#include -#endif -#endif +#include #include "sgxdefs.h" #include "services_headers.h" #include "sysinfo.h" @@ -42,17 +38,11 @@ #include "sysconfig.h" #include "sgxinfokm.h" #include "syslocal.h" +#include "env_data.h" #define HZ_TO_MHZ(m) ((m) / 1000000) -#define MUTEX_INIT(pl) init_MUTEX(pl) -#define MUTEX_LOCK(pl) down(pl) -#define MUTEX_UNLOCK(pl) up(pl) -#if defined (SUPPORT_TI_PM) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - -static SYS_SPECIFIC_DATA *psNotifierSysSpecData; - +#if defined(SGX_DYNAMIC_TIMING_INFO) static inline unsigned long scale_by_rate(unsigned long val, unsigned long rate1, unsigned long rate2) @@ -76,44 +66,32 @@ static inline unsigned long scale_inv_prop_to_SGX_clock(unsigned long val, return scale_by_rate(val, SYS_SGX_CLOCK_SPEED, rate); } -static void post_clock_rate_change(void) +IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION * psTimingInfo) { unsigned long rate; - SGX_TIMING_INFORMATION *psTimingInfo = - psNotifierSysSpecData->psSGXTimingInfo; - rate = clk_get_rate(psNotifierSysSpecData->psSGX_FCK); +#if defined(NO_HARDWARE) + rate = SYS_SGX_CLOCK_SPEED; +#else + PVR_ASSERT(gpsSysSpecificData->bSGXClocksEnabled); + rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK); PVR_ASSERT(rate != 0); - +#endif psTimingInfo->ui32CoreClockSpeed = rate; psTimingInfo->ui32HWRecoveryFreq = scale_prop_to_SGX_clock(SYS_SGX_HWRECOVERY_TIMEOUT_FREQ, rate); psTimingInfo->ui32uKernelFreq = scale_prop_to_SGX_clock(SYS_SGX_PDS_TIMER_FREQ, rate); - - PVR_TRACE(("post_clock_rate_change: SGX clock rate: %dMHz", - HZ_TO_MHZ(psTimingInfo->ui32CoreClockSpeed))); - -#if 0 - PVR_TRACE(("post_clock_rate_change: HW Recovery frequency: %dHz", - psTimingInfo->ui32HWRecoveryFreq)); - PVR_TRACE(("post_clock_rate_change: PDS Timer frequency: %dHz", - psTimingInfo->ui32uKernelFreq)); -#endif - - PVRSRVDevicePostClockSpeedChange(psNotifierSysSpecData->psSGXDevNode-> - sDevId.ui32DeviceIndex, IMG_FALSE, - IMG_NULL); + psTimingInfo->ui32ActivePowManLatencyms = + SYS_SGX_ACTIVE_POWER_LATENCY_MS; } +#endif -static void pre_clock_rate_change(void) -{ - PVRSRVDevicePreClockSpeedChange(psNotifierSysSpecData->psSGXDevNode-> - sDevId.ui32DeviceIndex, IMG_FALSE, - IMG_NULL); - -} +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)) +#if !defined(SGX_DYNAMIC_TIMING_INFO) +#error "SGX_DYNAMIC_TIMING_INFO must be defined for this platform" +#endif static int vdd2_post_func(struct notifier_block *n, unsigned long event, void *ptr) @@ -122,14 +100,23 @@ static int vdd2_post_func(struct notifier_block *n, unsigned long event, PVR_UNREFERENCED_PARAMETER(event); PVR_UNREFERENCED_PARAMETER(ptr); - BUG_ON(in_irq()); + if (gpsSysSpecificData->bSGXClocksEnabled + && gpsSysSpecificData->bSGXInitComplete) { +#if defined(DEBUG) + unsigned long rate; - if (psNotifierSysSpecData->bSGXClocksEnabled) { - post_clock_rate_change(); - } + rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK); - MUTEX_UNLOCK(&psNotifierSysSpecData->sConstraintNotifierLock); + PVR_ASSERT(rate != 0); + PVR_TRACE(("%s: SGX clock rate: %dMHz", __FUNCTION__, + HZ_TO_MHZ(rate))); +#endif + PVRSRVDevicePostClockSpeedChange(gpsSysSpecificData-> + psSGXDevNode->sDevId. + ui32DeviceIndex, IMG_TRUE, + IMG_NULL); + } return 0; } @@ -140,80 +127,223 @@ static int vdd2_pre_func(struct notifier_block *n, unsigned long event, PVR_UNREFERENCED_PARAMETER(event); PVR_UNREFERENCED_PARAMETER(ptr); - BUG_ON(in_irq()); + if (gpsSysSpecificData->bSGXClocksEnabled + && gpsSysSpecificData->bSGXInitComplete) { + BUG_ON(gpsSysData->eCurrentPowerState > PVRSRV_POWER_STATE_D1); + PVRSRVDevicePreClockSpeedChange(gpsSysSpecificData-> + psSGXDevNode->sDevId. + ui32DeviceIndex, IMG_TRUE, + IMG_NULL); + } - MUTEX_LOCK(&psNotifierSysSpecData->sConstraintNotifierLock); + return 0; +} - if (psNotifierSysSpecData->bSGXClocksEnabled) { - pre_clock_rate_change(); - } +static int vdd2_pre_post_func(struct notifier_block *n, unsigned long event, + void *ptr) +{ + struct clk_notifier_data *cnd; + PVR_UNREFERENCED_PARAMETER(n); + + cnd = (struct clk_notifier_data *)ptr; + + PVR_TRACE(("vdd2_pre_post_func: old clock rate = %lu", cnd->old_rate)); + PVR_TRACE(("vdd2_pre_post_func: new clock rate = %lu", cnd->new_rate)); + + if (CLK_PRE_RATE_CHANGE == event) { + PVRSRVDvfsLock(); + PVR_TRACE(("vdd2_pre_post_func: CLK_PRE_RATE_CHANGE event")); + vdd2_pre_func(n, event, ptr); + } else if (CLK_POST_RATE_CHANGE == event) { + PVR_TRACE(("vdd2_pre_post_func: CLK_POST_RATE_CHANGE event")); + vdd2_post_func(n, event, ptr); + PVRSRVDvfsUnlock(); + } else if (CLK_ABORT_RATE_CHANGE == event) { + PVR_TRACE(("vdd2_pre_post_func: CLK_ABORT_RATE_CHANGE event")); + PVRSRVDvfsUnlock(); + } else { + printk("vdd2_pre_post_func: unexpected event (%lu)\n", event); + PVR_DPF((PVR_DBG_ERROR, + "vdd2_pre_post_func: unexpected event (%lu)", event)); + } + PVR_TRACE(("vdd2_pre_post_func end.")); return 0; } -static struct notifier_block vdd2_pre = { - vdd2_pre_func, +static struct notifier_block vdd2_pre_post = { + vdd2_pre_post_func, NULL }; -static struct notifier_block vdd2_post = { - vdd2_post_func, - NULL -}; +static IMG_VOID RegisterConstraintNotifications(SYS_SPECIFIC_DATA * + psSysSpecData) +{ + PVR_TRACE(("Registering constraint notifications")); -static struct constraint_id cnstr_id_vdd2 = { - .type = RES_OPP_CO, - .data = (void *)"vdd2_opp" -}; + clk_notifier_register(psSysSpecData->psSGX_FCK, &vdd2_pre_post); + PVR_TRACE(("VDD2 constraint notifications registered")); +} -static IMG_VOID RegisterConstraintNotifications(SYS_DATA * psSysData, - SGX_TIMING_INFORMATION * - psSGXTimingInfo) +static IMG_VOID UnRegisterConstraintNotifications(SYS_SPECIFIC_DATA * + psSysSpecData) { - PVR_TRACE(("Registering constraint notifications")); + PVR_TRACE(("Unregistering constraint notifications")); - PVR_ASSERT(psNotifierSysSpecData == IMG_NULL); + clk_notifier_unregister(psSysSpecData->psSGX_FCK, &vdd2_pre_post); +} +#endif - psNotifierSysSpecData = - (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; - psNotifierSysSpecData->psSGXTimingInfo = psSGXTimingInfo; +static struct device sgx_dev; +static int sgx_clock_enabled; + +/* return value: current sgx load + * 0 - not busy + * 100 - busy + */ +static unsigned int sgx_current_load(void) +{ + PVRSRV_ERROR eError; + SYS_DATA *psSysData; + SYS_SPECIFIC_DATA *psSysSpecData; + PVRSRV_DEVICE_NODE *psDeviceNode; + static unsigned int kicks_prev; + static long time_prev; + + eError = SysAcquireData(&psSysData); + if (eError != PVRSRV_OK) + return 0; + psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; + if ((!psSysSpecData) || (!psSysSpecData->bSGXClocksEnabled)) + return 0; +#if defined(SUPPORT_SGX_HWPERF) + psDeviceNode = psSysData->psDeviceNodeList; + while (psDeviceNode) { + if ((psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_SGX) + && (psDeviceNode->pvDevice)) { + PVRSRV_SGXDEV_INFO *psDevInfo = + (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice; + unsigned int kicks = psDevInfo->ui32KickTACounter; + unsigned int load; + long time_elapsed; + + time_elapsed = jiffies - time_prev; + if (likely(time_elapsed)) + load = + 1000 * (kicks - kicks_prev) / time_elapsed; + else + load = 0; + kicks_prev = kicks; + time_prev += time_elapsed; + /* if the period between calls to this function was too long, + * then load stats are invalid + */ + if (time_elapsed > 5 * HZ) + return 0; + /*pr_err("SGX load %u\n", load); */ + + /* 'load' shows how many times sgx was kicked per 1000 jiffies + * 150 is arbitrarily chosen threshold. + * If the number of kicks is below threshold then sgx is doing + * some small jobs and we can keep the clock freq low. + */ + if (load < 150) + return 0; + else + return 100; + } + psDeviceNode = psDeviceNode->psNext; + } + return 0; +#else + return 100; +#endif +} - constraint_register_pre_notification(psNotifierSysSpecData->pVdd2Handle, - &vdd2_pre, max_vdd2_opp + 1); +static void sgx_lock_perf(struct work_struct *work) +{ + int vdd1, vdd2; + static int bHigh; + int high; + unsigned int load; + struct delayed_work *d_work = + container_of(work, struct delayed_work, work); + ENV_DATA *psEnvData = container_of(d_work, ENV_DATA, sPerfWork); + + load = sgx_current_load(); + if (load) { + vdd1 = 500000000; + vdd2 = 400000; + high = 1; + } else { + vdd1 = 0; + vdd2 = 0; + high = 0; + } + if (high != bHigh) { + omap_pm_set_min_bus_tput(&sgx_dev, OCP_INITIATOR_AGENT, vdd2); + omap_pm_set_min_mpu_freq(&sgx_dev, vdd1); + bHigh = high; + } + if (sgx_clock_enabled || load) + queue_delayed_work(psEnvData->psPerfWorkqueue, + &psEnvData->sPerfWork, HZ / 5); +} - constraint_register_post_notification(psNotifierSysSpecData-> - pVdd2Handle, &vdd2_post, - max_vdd2_opp + 1); +static void sgx_need_perf(SYS_DATA * psSysData, int ena) +{ + ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData; - PVR_TRACE(("VDD2 constraint notifications registered")); + sgx_clock_enabled = ena; + cancel_delayed_work(&psEnvData->sPerfWork); + queue_delayed_work(psEnvData->psPerfWorkqueue, &psEnvData->sPerfWork, + 0); } -static IMG_VOID UnRegisterConstraintNotifications(IMG_VOID) +PVRSRV_ERROR OSInitPerf(IMG_VOID * pvSysData) { - if (psNotifierSysSpecData == IMG_NULL) { - return; + SYS_DATA *psSysData = (SYS_DATA *) pvSysData; + ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData; + + if (psEnvData->psPerfWorkqueue) { + PVR_DPF((PVR_DBG_ERROR, "OSInitPerf: already inited")); + return PVRSRV_ERROR_GENERIC; } - PVR_TRACE(("Unregistering constraint notifications")); + PVR_TRACE(("Initing DVFS %x", pvSysData)); + + psEnvData->psPerfWorkqueue = create_singlethread_workqueue("sgx_perf"); + INIT_DELAYED_WORK(&psEnvData->sPerfWork, sgx_lock_perf); + + return PVRSRV_OK; +} - constraint_unregister_pre_notification(psNotifierSysSpecData-> - pVdd2Handle, &vdd2_pre, - max_vdd2_opp + 1); +PVRSRV_ERROR OSCleanupPerf(IMG_VOID * pvSysData) +{ + SYS_DATA *psSysData = (SYS_DATA *) pvSysData; + ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData; + + if (!psEnvData->psPerfWorkqueue) { + PVR_DPF((PVR_DBG_ERROR, "OSCleanupPerf: not inited")); + return PVRSRV_ERROR_GENERIC; + } - constraint_unregister_post_notification(psNotifierSysSpecData-> - pVdd2Handle, &vdd2_post, - max_vdd2_opp + 1); + PVR_TRACE(("Cleaning up DVFS")); - psNotifierSysSpecData = IMG_NULL; + flush_workqueue(psEnvData->psPerfWorkqueue); + destroy_workqueue(psEnvData->psPerfWorkqueue); + + return PVRSRV_OK; } -#endif -#endif + PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData) { #if !defined(NO_HARDWARE) SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; +#if defined(DEBUG) unsigned long rate; +#endif int res; if (psSysSpecData->bSGXClocksEnabled) { @@ -244,6 +374,9 @@ PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData) clk_disable(psSysSpecData->psSGX_FCK); return PVRSRV_ERROR_GENERIC; } +#if 0 + /* Code section removed for Fremnatle - + * call to clk_set_rate was causing crash */ rate = clk_get_rate(psSysSpecData->psSGX_FCK); if (rate < SYS_SGX_CLOCK_SPEED) { @@ -258,27 +391,14 @@ PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData) } PVR_TRACE(("SGX Functional Clock rate is %dMhz", HZ_TO_MHZ(clk_get_rate(psSysSpecData->psSGX_FCK)))); - -#if defined (SUPPORT_TI_PM) BUG_ON(in_irq()); #endif - MUTEX_LOCK(&psSysSpecData->sConstraintNotifierLock); psSysSpecData->bSGXClocksEnabled = IMG_TRUE; -#if defined (SUPPORT_TI_PM) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - - pre_clock_rate_change(); - - post_clock_rate_change(); -#endif -#endif - - MUTEX_UNLOCK(&psSysSpecData->sConstraintNotifierLock); - #else PVR_UNREFERENCED_PARAMETER(psSysData); #endif + sgx_need_perf(psSysData, 1); return PVRSRV_OK; } @@ -301,278 +421,282 @@ IMG_VOID DisableSGXClocks(SYS_DATA * psSysData) if (psSysSpecData->psSGX_FCK) { clk_disable(psSysSpecData->psSGX_FCK); } - MUTEX_LOCK(&psSysSpecData->sConstraintNotifierLock); psSysSpecData->bSGXClocksEnabled = IMG_FALSE; - - MUTEX_UNLOCK(&psSysSpecData->sConstraintNotifierLock); #else PVR_UNREFERENCED_PARAMETER(psSysData); #endif + sgx_need_perf(psSysData, 0); } -PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData, - SGX_TIMING_INFORMATION * psSGXTimingInfo) +static PVRSRV_ERROR InitSgxClocks(SYS_DATA * psSysData) { - SYS_SPECIFIC_DATA *psSysSpecData = - (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; struct clk *psCLK; - int res; -#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) - PVRSRV_ERROR eError; -#endif -#if defined(DEBUG) || defined(TIMING) - int rate; - struct clk *sys_ck; - IMG_CPU_PHYADDR TimerRegPhysBase; - IMG_HANDLE hTimerEnable; - IMG_UINT32 *pui32TimerEnable; + struct clk *core_ck = NULL; + + psCLK = clk_get(NULL, "sgx_fck"); + if (IS_ERR(psCLK)) + goto err0; + psSysSpecData->psSGX_FCK = psCLK; + + psCLK = clk_get(NULL, "sgx_ick"); + if (IS_ERR(psCLK)) + goto err1; + psSysSpecData->psSGX_ICK = psCLK; + + core_ck = clk_get(NULL, "core_ck"); + if (IS_ERR(core_ck)) + goto err2; + if (clk_set_parent(psSysSpecData->psSGX_FCK, core_ck) < 0) { + clk_put(core_ck); + goto err2; + } + clk_put(core_ck); -#endif + RegisterConstraintNotifications(psSysSpecData); - PVR_TRACE(("EnableSystemClocks: Enabling System Clocks")); + return PVRSRV_OK; - if (!psSysSpecData->bSysClocksOneTimeInit) { - MUTEX_INIT(&psSysSpecData->sConstraintNotifierLock); - psCLK = clk_get(NULL, "core_ck"); - if (IS_ERR(psCLK)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSsystemClocks: Couldn't get Core Clock")); - goto ExitError; - } - psSysSpecData->psCORE_CK = psCLK; +err2: + clk_put(psSysSpecData->psSGX_ICK); +err1: + clk_put(psSysSpecData->psSGX_FCK); +err0: + PVR_DPF((PVR_DBG_ERROR, + "%s: couldn't init clocks fck %p ick %p core %p", __func__, + psSysSpecData->psSGX_FCK, psSysSpecData->psSGX_ICK, core_ck)); + psSysSpecData->psSGX_FCK = NULL; + psSysSpecData->psSGX_ICK = NULL; - psCLK = clk_get(NULL, "sgx_fck"); - if (IS_ERR(psCLK)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSsystemClocks: Couldn't get SGX Functional Clock")); - goto ExitError; - } - psSysSpecData->psSGX_FCK = psCLK; + return PVRSRV_ERROR_GENERIC; +} - psCLK = clk_get(NULL, "sgx_ick"); - if (IS_ERR(psCLK)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't get SGX Interface Clock")); - goto ExitError; - } - psSysSpecData->psSGX_ICK = psCLK; +static void CleanupSgxClocks(SYS_DATA * psSysData) +{ + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; -#if defined(DEBUG) - psCLK = clk_get(NULL, "mpu_ck"); - if (IS_ERR(psCLK)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't get MPU Clock")); - goto ExitError; - } - psSysSpecData->psMPU_CK = psCLK; -#endif - res = - clk_set_parent(psSysSpecData->psSGX_FCK, - psSysSpecData->psCORE_CK); - if (res < 0) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't set SGX parent clock (%d)", - res)); - goto ExitError; - } + UnRegisterConstraintNotifications(psSysSpecData); - psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE; - } -#if defined (SUPPORT_TI_PM) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - psSysSpecData->pVdd2Handle = constraint_get("pvrsrvkm", &cnstr_id_vdd2); - if (IS_ERR(psSysSpecData->pVdd2Handle)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't get VDD2 constraint handle")); - goto ExitError; + if (psSysSpecData->psSGX_ICK) { + clk_put(psSysSpecData->psSGX_ICK); + psSysSpecData->psSGX_ICK = NULL; } - RegisterConstraintNotifications(psSysData, psSGXTimingInfo); -#endif -#endif -#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) - - eError = EnableSGXClocks(psSysData); - if (eError != PVRSRV_OK) { - goto ExitUnRegisterConstraintNotifications; + if (psSysSpecData->psSGX_FCK) { + clk_put(psSysSpecData->psSGX_FCK); + psSysSpecData->psSGX_FCK = NULL; } -#endif +} #if defined(DEBUG) || defined(TIMING) +static u32 inline gpt_read_reg(SYS_DATA * psSysData, u32 reg) +{ + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; + + return __raw_readl(psSysSpecData->gpt_base + reg); +} + +static void inline gpt_write_reg(SYS_DATA * psSysData, u32 reg, u32 val) +{ + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; + + __raw_writel(val, psSysSpecData->gpt_base + reg); +} + +static PVRSRV_ERROR InitDebugClocks(SYS_DATA * psSysData) +{ + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; + struct clk *psCLK; + struct clk *sys_ck = NULL; + u32 rate; + + psCLK = clk_get(NULL, "mpu_ck"); + if (IS_ERR(psCLK)) + goto err0; + psSysSpecData->psMPU_CK = psCLK; psCLK = clk_get(NULL, "gpt11_fck"); - if (IS_ERR(psCLK)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't get GPTIMER11 functional clock")); - goto ExitDisableSGXClocks; - } + if (IS_ERR(psCLK)) + goto err1; psSysSpecData->psGPT11_FCK = psCLK; psCLK = clk_get(NULL, "gpt11_ick"); - if (IS_ERR(psCLK)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't get GPTIMER11 interface clock")); - goto ExitDisableSGXClocks; - } + if (IS_ERR(psCLK)) + goto err2; psSysSpecData->psGPT11_ICK = psCLK; sys_ck = clk_get(NULL, "sys_ck"); - if (IS_ERR(sys_ck)) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't get System clock")); - goto ExitDisableSGXClocks; - } - + if (IS_ERR(sys_ck)) + goto err3; if (clk_get_parent(psSysSpecData->psGPT11_FCK) != sys_ck) { - PVR_TRACE(("Setting GPTIMER11 parent to System Clock")); - res = clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck); - if (res < 0) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't set GPTIMER11 parent clock (%d)", - res)); - goto ExitDisableSGXClocks; + if (clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck) < 0) { + clk_put(sys_ck); + goto err3; } } + clk_put(sys_ck); - rate = clk_get_rate(psSysSpecData->psGPT11_FCK); - PVR_TRACE(("GPTIMER11 clock is %dMHz", HZ_TO_MHZ(rate))); + PVR_TRACE(("GPTIMER11 clock is %dMHz", + HZ_TO_MHZ(clk_get_rate(psSysSpecData->psGPT11_FCK)))); - res = clk_enable(psSysSpecData->psGPT11_FCK); - if (res < 0) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't enable GPTIMER11 functional clock (%d)", - res)); - goto ExitDisableSGXClocks; - } + psSysSpecData->gpt_base = ioremap(SYS_OMAP3430_GP11TIMER_PHYS_BASE, + SYS_OMAP3430_GPTIMER_SIZE); + if (!psSysSpecData->gpt_base) + goto err3; - res = clk_enable(psSysSpecData->psGPT11_ICK); - if (res < 0) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)", - res)); - goto ExitDisableGPT11FCK; - } - - TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE; - pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase, - 4, - PVRSRV_HAP_KERNEL_ONLY | - PVRSRV_HAP_UNCACHED, &hTimerEnable); + clk_enable(psSysSpecData->psGPT11_ICK); + clk_enable(psSysSpecData->psGPT11_FCK); - if (pui32TimerEnable == IMG_NULL) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: OSMapPhysToLin failed")); - goto ExitDisableGPT11ICK; - } - - rate = *pui32TimerEnable; + rate = gpt_read_reg(psSysData, SYS_OMAP3430_GPTIMER_TSICR); if (!(rate & 4)) { PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)")); - - *pui32TimerEnable = rate | 4; + gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_TSICR, rate | 4); } - OSUnMapPhysToLin(pui32TimerEnable, - 4, - PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED, - hTimerEnable); + clk_disable(psSysSpecData->psGPT11_FCK); + clk_disable(psSysSpecData->psGPT11_ICK); + + return PVRSRV_OK; - TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE; - pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase, - 4, - PVRSRV_HAP_KERNEL_ONLY | - PVRSRV_HAP_UNCACHED, &hTimerEnable); +err3: + clk_put(psSysSpecData->psGPT11_ICK); +err2: + clk_put(psSysSpecData->psGPT11_FCK); +err1: + clk_put(psSysSpecData->psMPU_CK); +err0: + PVR_DPF((PVR_DBG_ERROR, + "%s: couldn't init clocks: mpu %p sys %p fck %p ick %p", + __func__, psSysSpecData->psMPU_CK, sys_ck, + psSysSpecData->psGPT11_FCK, psSysSpecData->psGPT11_ICK)); + + psSysSpecData->psMPU_CK = NULL; + psSysSpecData->psGPT11_FCK = NULL; + psSysSpecData->psGPT11_ICK = NULL; - if (pui32TimerEnable == IMG_NULL) { - PVR_DPF((PVR_DBG_ERROR, - "EnableSystemClocks: OSMapPhysToLin failed")); - goto ExitDisableGPT11ICK; + return PVRSRV_ERROR_GENERIC; +} + +static void CleanupDebugClocks(SYS_DATA * psSysData) +{ + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; + + if (psSysSpecData->psMPU_CK) { + clk_put(psSysSpecData->psMPU_CK); + psSysSpecData->psMPU_CK = NULL; + } + if (psSysSpecData->psGPT11_FCK) { + clk_put(psSysSpecData->psGPT11_FCK); + psSysSpecData->psGPT11_FCK = NULL; + } + if (psSysSpecData->psGPT11_ICK) { + clk_put(psSysSpecData->psGPT11_ICK); + psSysSpecData->psGPT11_ICK = NULL; } +} + +static PVRSRV_ERROR EnableDebugClocks(SYS_DATA * psSysData) +{ + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; - *pui32TimerEnable = 3; + if (clk_enable(psSysSpecData->psGPT11_FCK) < 0) + goto err0; - OSUnMapPhysToLin(pui32TimerEnable, - 4, - PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED, - hTimerEnable); + if (clk_enable(psSysSpecData->psGPT11_ICK) < 0) + goto err1; -#endif + gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_ENABLE, 3); return PVRSRV_OK; -#if defined(DEBUG) || defined(TIMING) -ExitDisableGPT11ICK: - clk_disable(psSysSpecData->psGPT11_ICK); -ExitDisableGPT11FCK: +err1: clk_disable(psSysSpecData->psGPT11_FCK); -ExitDisableSGXClocks: -#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) - DisableSGXClocks(psSysData); -#endif -#endif -#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) -ExitUnRegisterConstraintNotifications: -#endif -#if defined (SUPPORT_TI_PM) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - UnRegisterConstraintNotifications(); - constraint_put(psSysSpecData->pVdd2Handle); -#endif -#endif -ExitError: +err0: + PVR_DPF((PVR_DBG_ERROR, "%s: can't enable clocks", __func__)); + return PVRSRV_ERROR_GENERIC; } -IMG_VOID DisableSystemClocks(SYS_DATA * psSysData) +static inline void DisableDebugClocks(SYS_DATA * psSysData) { -#if defined(SUPPORT_TI_PM) || defined(DEBUG) || defined(TIMING) - SYS_SPECIFIC_DATA *psSysSpecData = - (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; -#endif -#if defined(DEBUG) || defined(TIMING) - IMG_CPU_PHYADDR TimerRegPhysBase; - IMG_HANDLE hTimerDisable; - IMG_UINT32 *pui32TimerDisable; -#endif + SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData; - PVR_TRACE(("DisableSystemClocks: Disabling System Clocks")); -#if defined (SUPPORT_TI_PM) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - UnRegisterConstraintNotifications(); -#endif -#endif + gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_ENABLE, 0); - DisableSGXClocks(psSysData); + clk_disable(psSysSpecData->psGPT11_ICK); + clk_disable(psSysSpecData->psGPT11_FCK); +} -#if defined(DEBUG) || defined(TIMING) +#else - TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE; - pui32TimerDisable = OSMapPhysToLin(TimerRegPhysBase, - 4, - PVRSRV_HAP_KERNEL_ONLY | - PVRSRV_HAP_UNCACHED, &hTimerDisable); +PVRSRV_ERROR inline InitDebugClocks(SYS_DATA * psSysData) +{ + return PVRSRV_OK; +} - if (pui32TimerDisable == IMG_NULL) { - PVR_DPF((PVR_DBG_ERROR, - "DisableSystemClocks: OSMapPhysToLin failed")); - } else { - *pui32TimerDisable = 0; +static void inline CleanupDebugClocks(SYS_DATA * psSysData) +{ +} - OSUnMapPhysToLin(pui32TimerDisable, - 4, - PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED, - hTimerDisable); - } +static inline PVRSRV_ERROR EnableDebugClocks(SYS_DATA * psSysData) +{ + return PVRSRV_OK; +} - clk_disable(psSysSpecData->psGPT11_ICK); +static inline void DisableDebugClocks(SYS_DATA * psSysData) +{ +} +#endif - clk_disable(psSysSpecData->psGPT11_FCK); +PVRSRV_ERROR InitSystemClocks(SYS_DATA * psSysData) +{ + if (InitSgxClocks(psSysData) != PVRSRV_OK) + goto err0; + if (InitDebugClocks(psSysData) != PVRSRV_OK) + goto err1; + + return PVRSRV_OK; + +err1: + CleanupSgxClocks(psSysData); +err0: + return PVRSRV_ERROR_GENERIC; +} + +void CleanupSystemClocks(SYS_DATA * psSysData) +{ + CleanupDebugClocks(psSysData); + CleanupSgxClocks(psSysData); +} + +PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData) +{ + PVR_TRACE(("EnableSystemClocks: Enabling System Clocks")); + +#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) + if (EnableSGXClocks(psSysData) != PVRSRV_OK) + goto err0; #endif -#if defined (SUPPORT_TI_PM) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) - constraint_put(psSysSpecData->pVdd2Handle); -#endif + + if (EnableDebugClocks(psSysData) != PVRSRV_OK) + goto err1; + + return PVRSRV_OK; + +err1: +#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) + DisableSGXClocks(psSysData); +err0: #endif + return PVRSRV_ERROR_GENERIC; +} + +IMG_VOID DisableSystemClocks(SYS_DATA * psSysData) +{ + PVR_TRACE(("DisableSystemClocks: Disabling System Clocks")); + + DisableSGXClocks(psSysData); + DisableDebugClocks(psSysData); }