summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-02-17 09:17:44 -0800
committerGary King <gking@nvidia.com>2010-02-17 14:32:31 -0800
commit2bf197dc9780028c7d160750a65163cb419e91c8 (patch)
tree7af908676b7d5245557b9e7bacfc31166480cbca
parent7e7449fe722791d5ec61eb705881248154954965 (diff)
nvrm transport: eliminate double-copying of messages
with the change to allocate messages < MAX_SIZE on the stack inside the dispatcher, there were actually 2 on-stack copies of the message being maintained: one in the dispatcher, and one in the RM transport code itself. the transport code copied the message in order to prepend a 3-word header; however, since the entire message was then copied into a memory handle to send it to the AVP, the internal copy is unnecessary; the message header can be written directly to the memory handle and then the buffer provided by the dispatcher can be copied directly into the memory handle Change-Id: I3a748192d7e45445bc821456e170670cc3fb0e98
-rw-r--r--arch/arm/mach-tegra/nvos/nvos.c10
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c71
2 files changed, 52 insertions, 29 deletions
diff --git a/arch/arm/mach-tegra/nvos/nvos.c b/arch/arm/mach-tegra/nvos/nvos.c
index 3e98dfc03063..08f30ebb0d2f 100644
--- a/arch/arm/mach-tegra/nvos/nvos.c
+++ b/arch/arm/mach-tegra/nvos/nvos.c
@@ -349,9 +349,12 @@ void NvOsMemmove(void *dest, const void *src, size_t size)
NvError NvOsCopyIn(void *pDst, const void *pSrc, size_t Bytes)
{
+ if (!Bytes)
+ return NvSuccess;
+
if( access_ok( VERIFY_READ, pSrc, Bytes ) )
{
- copy_from_user(pDst, pSrc, Bytes);
+ __copy_from_user(pDst, pSrc, Bytes);
return NvSuccess;
}
@@ -360,9 +363,12 @@ NvError NvOsCopyIn(void *pDst, const void *pSrc, size_t Bytes)
NvError NvOsCopyOut(void *pDst, const void *pSrc, size_t Bytes)
{
+ if (!Bytes)
+ return NvSuccess;
+
if( access_ok( VERIFY_WRITE, pDst, Bytes ) )
{
- copy_to_user(pDst, pSrc, Bytes);
+ __copy_to_user(pDst, pSrc, Bytes);
return NvSuccess;
}
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 e056832d8134..1b6625d33df2 100644
--- a/arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c
+++ b/arch/arm/mach-tegra/nvrm/core/common/nvrm_transport.c
@@ -269,8 +269,9 @@ static NvOsInterruptHandle s_TransportInterruptHandle = NULL;
static NvRmTransportHandle
FindPort(NvRmDeviceHandle hDevice, char *pPortName);
-static NvError
-NvRmPrivTransportSendMessage(NvRmDeviceHandle hDevice, NvU32 *message, NvU32 MessageLength);
+static NvError NvRmPrivTransportSendMessage(NvRmDeviceHandle hDevice,
+ NvU32 *messagehdr, NvU32 MessageHdrLength,
+ NvU32 *Message, NvU32 MessageLength);
static void HandleAVPResetMessage(NvRmDeviceHandle hDevice);
@@ -1027,7 +1028,8 @@ void NvRmTransportClose(NvRmTransportHandle hPort)
{
RemoteMessage[0] = TransportCmd_Disconnect;
RemoteMessage[1] = hPort->RemotePort;
- NvRmPrivTransportSendMessage(hPort->hRmDevice, RemoteMessage, 2*sizeof(NvU32));
+ NvRmPrivTransportSendMessage(hPort->hRmDevice, RemoteMessage,
+ 2*sizeof(NvU32), NULL, 0);
}
NvOsSemaphoreDestroy(hPort->hOnPushMsgSem);
@@ -1169,8 +1171,9 @@ NvRmPrivTransportWaitResponse(NvRmDeviceHandle hDevice, NvU32 *response, NvU32 R
}
-static NvError
-NvRmPrivTransportSendMessage(NvRmDeviceHandle hDevice, NvU32 *message, NvU32 MessageLength)
+static NvError NvRmPrivTransportSendMessage(NvRmDeviceHandle hDevice,
+ NvU32 *MessageHdr, NvU32 MessageHdrLength,
+ NvU32 *Message, NvU32 MessageLength)
{
NvU32 ReadData;
@@ -1188,7 +1191,7 @@ NvRmPrivTransportSendMessage(NvRmDeviceHandle hDevice, NvU32 *message, NvU32 Mes
}
else
{
- ReadData = ((NvU32*)s_TransportInfo.pTransmitMem)[0];
+ ReadData = ((volatile NvU32*)s_TransportInfo.pTransmitMem)[0];
}
// Check for clear to send
@@ -1198,39 +1201,50 @@ NvRmPrivTransportSendMessage(NvRmDeviceHandle hDevice, NvU32 *message, NvU32 Mes
if (s_TransportInfo.pTransmitMem == NULL)
{
/* QT/EMUTRANS takes this code path */
- NvRmMemWrite(s_TransportInfo.hMessageMem, 0, message, MessageLength);
+ NvRmMemWrite(s_TransportInfo.hMessageMem, 0, MessageHdr, MessageHdrLength);
+ if (Message && MessageLength)
+ {
+ NvRmMemWrite(s_TransportInfo.hMessageMem, MessageHdrLength,
+ Message, MessageLength);
+ }
}
else
{
- NvOsMemcpy(s_TransportInfo.pTransmitMem, message, MessageLength);
+ NvOsMemcpy(s_TransportInfo.pTransmitMem, MessageHdr, MessageHdrLength);
+ if (Message && MessageLength)
+ {
+ NvOsMemcpy(s_TransportInfo.pTransmitMem + MessageHdrLength,
+ Message, MessageLength);
+ }
NvOsFlushWriteCombineBuffer();
}
NvRmPrivXpcSendMessage(s_TransportInfo.hXpc, s_TransportInfo.MessageMemPhysAddr);
return NvSuccess;
}
-NvError
-NvRmTransportSendMsgInLP0(NvRmTransportHandle hPort, void *pMessageBuffer, NvU32 MessageSize)
+NvError NvRmTransportSendMsgInLP0(NvRmTransportHandle hPort,
+ void *pMessageBuffer, NvU32 MessageSize)
{
NvU32 ReadData;
- NvU32 Message[3 + ((MAX_MESSAGE_LENGTH) / sizeof(NvU32))];
+ NvU32 MessageHdr[3];
NV_ASSERT(pMessageBuffer);
- Message[0] = TransportCmd_Message;
- Message[1] = hPort->RemotePort;
- Message[2] = MessageSize;
+ MessageHdr[0] = TransportCmd_Message;
+ MessageHdr[1] = hPort->RemotePort;
+ MessageHdr[2] = MessageSize;
- if (MessageSize)
- NvOsMemcpy(&Message[3], pMessageBuffer, MessageSize);
-
- ReadData = ((NvU32*)s_TransportInfo.pTransmitMem)[0];
+ ReadData = ((volatile NvU32*)s_TransportInfo.pTransmitMem)[0];
// Check for clear to send
if ( ReadData != 0)
return NvError_TransportMessageBoxFull; // someone else is sending a message
- NvOsMemcpy(s_TransportInfo.pTransmitMem, Message, MessageSize + 3*sizeof(NvU32));
+ NvOsMemcpy(s_TransportInfo.pTransmitMem, MessageHdr, sizeof(MessageHdr));
+ if (MessageSize) {
+ NvOsMemcpy(s_TransportInfo.pTransmitMem + sizeof(MessageHdr),
+ pMessageBuffer, MessageSize);
+ }
NvOsFlushWriteCombineBuffer();
NvRmPrivXpcSendMessage(s_TransportInfo.hXpc, s_TransportInfo.MessageMemPhysAddr);
@@ -1305,7 +1319,8 @@ NvError NvRmTransportConnect(NvRmTransportHandle hPort, NvU32 TimeoutMS)
ConnectMessage[1] = (NvU32)hPort;
NvOsMemcpy(&ConnectMessage[2], hPort->PortName, MAX_PORT_NAME_LENGTH);
- err = NvRmPrivTransportSendMessage(hPort->hRmDevice, ConnectMessage, sizeof(ConnectMessage));
+ err = NvRmPrivTransportSendMessage(hPort->hRmDevice,
+ ConnectMessage, sizeof(ConnectMessage), NULL, 0);
if (!err)
{
// should send back 2 words of data. Give remote side 1000ms to respond, which should be about 100x more
@@ -1414,22 +1429,22 @@ NvRmPrivTransportSendRemoteMsg(
NvError err;
NvU32 StartTime;
NvU32 CurrentTime;
- NvU32 Message[3 + ((MAX_MESSAGE_LENGTH) / sizeof(NvU32))];
+ NvU32 MessageHdr[3];
NV_ASSERT((MAX_MESSAGE_LENGTH) >= MessageSize);
StartTime = NvOsGetTimeMS();
- Message[0] = TransportCmd_Message;
- Message[1] = hPort->RemotePort;
- Message[2] = MessageSize;
+ MessageHdr[0] = TransportCmd_Message;
+ MessageHdr[1] = hPort->RemotePort;
+ MessageHdr[2] = MessageSize;
- NvOsMemcpy(&Message[3], pMessageBuffer, MessageSize);
-
for (;;)
{
NvOsMutexLock(s_TransportInfo.mutex);
- err = NvRmPrivTransportSendMessage(hPort->hRmDevice, Message, MessageSize + 3*sizeof(NvU32));
+ err = NvRmPrivTransportSendMessage(hPort->hRmDevice,
+ MessageHdr, sizeof(MessageHdr),
+ pMessageBuffer, MessageSize);
NvOsMutexUnlock(s_TransportInfo.mutex);
if (err == NvSuccess)
{
@@ -1576,6 +1591,7 @@ NvRmTransportRecvMsg(
NV_ASSERT(pMessageSize);
+ *pMessageSize = 0;
NvOsMutexLock(s_TransportInfo.mutex);
if (hPort->RecvMessageQueue.ReadIndex == hPort->RecvMessageQueue.WriteIndex)
{
@@ -1589,6 +1605,7 @@ NvRmTransportRecvMsg(
// not enough room to copy the message
NvOsMutexUnlock(s_TransportInfo.mutex);
NV_ASSERT(!" RM Transport: Illegal message size. ");
+ return NvError_InvalidSize;
}