summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortkasivajhula <tkasivajhula@nvidia.com>2010-05-15 23:52:18 -0700
committerGary King <gking@nvidia.com>2010-05-17 11:29:37 -0700
commitb8a0f3f1d92e521fb517219daa5083363a4a57e0 (patch)
treee4b07f324ecea5df60bf6b59fc8a81aa66565c60
parente8e7b1c392c8cf7bec7a959ec0625f9bdf4e109d (diff)
tegra power: Workaround for daemon crash.
Put the AVP suspend operation in the kernel. It appears that someone in userspace is still active after nvrm_graphics has suspended. Change-Id: Ie3b67478d502c8af5fd25a141d362409f737ffc3 Reviewed-on: http://git-master/r/1404 Reviewed-by: Trivikram Kasivajhula <tkasivajhula@nvidia.com> Tested-by: Trivikram Kasivajhula <tkasivajhula@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c1
-rw-r--r--arch/arm/mach-tegra/nvrm_user.c85
2 files changed, 85 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c b/arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c
index 4504b8a01819..6f376e757062 100644
--- a/arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c
+++ b/arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c
@@ -1688,4 +1688,3 @@ NvRmTransportGetPortName(
NvOsStrncpy((char *)PortName, hPort->PortName, PortNameSize);
}
-
diff --git a/arch/arm/mach-tegra/nvrm_user.c b/arch/arm/mach-tegra/nvrm_user.c
index f649754da469..d8e5f94502fc 100644
--- a/arch/arm/mach-tegra/nvrm_user.c
+++ b/arch/arm/mach-tegra/nvrm_user.c
@@ -42,6 +42,7 @@
#include "nvos.h"
#include "nvrm_memmgr.h"
#include "nvrm_ioctls.h"
+#include "nvrm_message.h"
#include "mach/nvrm_linux.h"
#include "linux/nvos_ioctl.h"
#include "nvrm_power_private.h"
@@ -63,6 +64,11 @@ static long nvrm_unlocked_ioctl(struct file *file,
static int nvrm_mmap(struct file *file, struct vm_area_struct *vma);
extern void reset_cpu(unsigned int cpu, unsigned int reset);
+//Variables for AVP suspend operation
+extern NvRmDeviceHandle s_hRmGlobal;
+static NvRmMemHandle s_IramMemHandle;
+static NvRmTransportHandle s_AvpSuspendPort;
+
static NvOsThreadHandle s_DfsThread = NULL;
static NvRtHandle s_RtHandle = NULL;
@@ -459,8 +465,87 @@ static int nvrm_remove(struct platform_device *pdev)
return 0;
}
+NvError NvRmAvpSuspend(NvRmDeviceHandle hRmDeviceHandle)
+{
+ NvRmMessage_InitiateLP0 Msg;
+ NvError e = NvSuccess;
+ NvRmHeap Heaps[2];
+ NvU32 iramSize, iramAddr, numInstances, instSize;
+ volatile NvU32 *syncVal = NULL;
+ volatile NvU32 *bar;
+
+ if (!s_AvpSuspendPort)
+ {
+ e = NvRmTransportOpen(hRmDeviceHandle, "RPC_AVP_PORT",
+ NULL, &s_AvpSuspendPort);
+ if (e)
+ goto fail;
+ }
+
+ Heaps[0] = NvRmHeap_ExternalCarveOut;
+
+ NvRmModuleGetBaseAddress(hRmDeviceHandle,
+ NVRM_MODULE_ID(NvRmPrivModuleID_Iram, 0),&iramAddr, &instSize);
+
+ numInstances = NvRmModuleGetNumInstances(hRmDeviceHandle,
+ NVRM_MODULE_ID(NvRmPrivModuleID_Iram, 0));
+
+ iramSize = instSize * numInstances;
+ if (s_IramMemHandle == NULL)
+ {
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmMemHandleCreate(hRmDeviceHandle, &s_IramMemHandle,
+ iramSize + sizeof(NvU32))
+ );
+
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmMemAlloc(s_IramMemHandle, Heaps, 1, 16,
+ NvOsMemAttribute_Uncached)
+ );
+ }
+
+ Msg.msg = NvRmMsg_InitiateLP0;
+ Msg.sourceAddr = iramAddr;
+ Msg.bufferAddr = NvRmMemPin(s_IramMemHandle);
+ Msg.bufferSize = iramSize;
+
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmMemMap(s_IramMemHandle, iramSize,
+ sizeof(NvU32), NVOS_MEM_READ_WRITE, (void**)&syncVal)
+ );
+
+ *syncVal = 0;
+
+ //Make sure write lands in memory before AVP reads it.
+ bar = (volatile NvU32*)syncVal;
+ (void)(*bar);
+
+ //SendMsgInLP0 should never return an error in this scenario.
+ //If it does, something is seriously wrong with LP0.
+ //(No one else should be talking to the AVP at this moment)
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmTransportSendMsgInLP0(s_AvpSuspendPort, &Msg, sizeof(Msg))
+ );
+
+ //Wait for the AVP to acknowledge that LP0 call
+ while (!*syncVal);
+
+ return NvSuccess;
+fail:
+ if (s_IramMemHandle)
+ {
+ NvRmMemHandleFree(s_IramMemHandle);
+ s_IramMemHandle = NULL;
+ }
+
+ return e;
+}
+
static int nvrm_suspend(struct platform_device *pdev, pm_message_t state)
{
+ if (NvRmAvpSuspend(s_hRmGlobal))
+ return -1;
+
if(NvRmKernelPowerSuspend(s_hRmGlobal)) {
printk(KERN_INFO "%s : FAILED\n", __func__);
return -1;