summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2009-12-23 14:56:12 -0800
committerGary King <gking@nvidia.com>2009-12-23 17:54:07 -0800
commit69c7efe0d7c958fb17d891ce28259c21e1df9179 (patch)
tree26ce9e13a1fa5cd2c9117117b037f3961ffc464e
parentbe8031fedcb3fa0841f8aab14fca5e5f872ca3c7 (diff)
tegra rm: check amount of received I2C data before copying to client
in certain cases, it was possible for an I2C error to go undetected and the data that was being copied to the return buffer was not actually data returned from the slave. Change-Id: I7442e02fcb87a3010a867670ee3c3fe13c955fc4
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c30
-rw-r--r--arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c_private.h50
2 files changed, 27 insertions, 53 deletions
diff --git a/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c b/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c
index 0043b7410542..52c66879a16e 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c
@@ -669,6 +669,8 @@ DoOneReceiveTransaction(
NvU32 PacketHeader3;
NvU32 IntMaskReg;
NvRmDmaModuleID DmaModuleId = NvRmDmaModuleID_I2c;
+ NvU32 BytesRead;
+
hRmI2cCont->WordTransferred = 0;
hRmI2cCont->WordRemaining = 0;
@@ -802,15 +804,29 @@ WaitForCompletion:
hRmI2cCont->I2cTransferStatus = NvError_I2cDeviceNotFound;
goto ReadExitWithReset;
}
- }
- if (pBytesTransferred != NULL)
- *pBytesTransferred = pTransaction->NumBytes;
-
+ }
// Memcopy fifo back to actual buffer given by client
if (hRmI2cCont->IsUsingApbDma)
- NvOsMemcpy(pBuffer, (NvU8* )hRmI2cCont->pDmaBuffer, *pBytesTransferred);
+ {
+ BytesRead = NV_MIN(pTransaction->NumBytes,
+ hRmI2cCont->RxDmaReq.TransferSize);
+ NvOsMemcpy(pBuffer, (NvU8* )hRmI2cCont->pDmaBuffer, BytesRead);
+ }
else
- NvOsMemcpy(pBuffer, (NvU8* )hRmI2cCont->pDataBuffer, *pBytesTransferred);
+ {
+ BytesRead = NV_MIN(pTransaction->NumBytes,
+ (4*hRmI2cCont->WordTransferred));
+ if (BytesRead != pTransaction->NumBytes)
+ {
+ hRmI2cCont->I2cTransferStatus = NvError_I2cReadFailed;
+ goto ReadExitWithReset;
+ }
+ NvOsMemcpy(pBuffer, (NvU8* )hRmI2cCont->pDataBuffer, BytesRead);
+ }
+
+ if (pBytesTransferred != NULL)
+ *pBytesTransferred = BytesRead;
+
hRmI2cCont->I2cTransferStatus = NvSuccess;
goto ReadExit;
@@ -1096,7 +1112,7 @@ DoMultiReceiveTransaction(
I2C_REGW(hRmI2cCont, INTERRUPT_MASK_REGISTER, 0);
}
*pPacketId = PacketId;
- *pBytesTransferred = BytesTransferred;
+ *pBytesTransferred = BytesTransferredYet;
return Error;
}
diff --git a/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c_private.h b/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c_private.h
index a5836bd1ab69..e7af0aa7c09c 100644
--- a/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c_private.h
+++ b/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c_private.h
@@ -74,32 +74,6 @@ typedef struct SocI2cCapabilityRec
NvBool IsNewMasterAvailable;
} SocI2cCapability;
-typedef enum
-{
- /** No Error */
- I2cControllerStatus_None = 0,
- /** Receive Fifo Data Request */
- I2cControllerStatus_RFifo_data_Request = 0x1,
- /** Transmit Fifo Data Request */
- I2cControllerStatus_TFifo_data_Request = 0x2,
- /** Arbitration Lost */
- I2cControllerStatus_Arb_Lost = 0x4,
- /** No Acknowledge error */
- I2cControllerStatus_NoAck = 0x8,
- /** Receive Fifo Underflow */
- I2cControllerStatus_RFifo_UFlow = 0x10,
- /** Transmit Fifo Overflow */
- I2cControllerStatus_TFifo_OFlow = 0x20,
- /** All Packets Transfer Complete */
- I2cControllerStatus_All_Packets_Xfer_Complete = 0x40,
- /** Packet Transfer Complete */
- I2cControllerStatus_Packet_Xfer_Complete = 0x80,
- /** Force to 32 bit */
- I2cControllerStatus_Force32 = 0x7FFFFFFF
-}I2cControllerStatus;
-
-struct NvRmI2cControllerRec;
-
/* I2C controller state. There are will one instance of this structure for each
* I2C controller instance */
typedef struct NvRmI2cControllerRec
@@ -184,28 +158,14 @@ typedef struct NvRmI2cControllerRec
// I2C capabiity for this SOC only.
SocI2cCapability SocI2cCaps;
- /* Flag to hold int for tfifoReq */
- volatile NvBool IntForTFIFOReq;
- /* Flag to hold int for rifoReq */
- volatile NvBool IntForRFIFOReq;
- /* Flag to hold all packet complete */
- volatile NvBool AllPktComplete;
- /* Flag to hold packet complete */
- volatile NvBool PktXferComplte;
/* Repeat start transfer */
volatile NvBool RsTransfer;
- /* Holds no. of Repeat start transations */
- volatile NvU32 NoOfRSTransactions;
- /* pointer to transfer buffer */
- NvU8 * pTransferBuffer;
- /* repeat start transations */
- NvRmI2cTransactionInfo * RSTransactions;
- volatile NvU32 CurrentReadPktId;
- volatile NvU32 BytesAlreadyRead;
+
/* Clock period in micro-seconds */
NvU32 I2cClockPeriod;
/* I2c Controller Status variable */
- I2cControllerStatus ControllerStatus;
+ NvU32 ControllerStatus;
+
/* indicates whether to enable new master or not */
NvBool EnableNewMaster;
@@ -229,7 +189,7 @@ typedef struct NvRmI2cControllerRec
// Tells whether the current transfer is with NO STOP
NvBool IsCurrentTransferNoStop;
- // TElls whether the current transfer is with ack or not
+ // Tells whether the current transfer is with ack or not
NvBool IsCurrentTransferNoAck;
// Tells whether current transfer is a read or write type.
@@ -301,5 +261,3 @@ NvError AP15RmI2cOpen(NvRmI2cController *c);
NvError AP20RmI2cOpen(NvRmI2cController *c);
#endif // INCLUDED_NVRM_I2C_PRIVATE_H
-
-