Re: [PATCH] i2c-intel-mid: I2C FIFO buffer size setting and fragmentation

2011-01-26 Thread Ben Dooks
On Tue, Jan 25, 2011 at 02:28:07PM +, Alan Cox wrote:
 From: Major Lee major_...@wistron.com
 
 The FIFO buffer size is different with different CPU stepping.
 Define it as 32-byte; it is safe for all CPU stepping.
 
 There is a problem when xfer size is greater then FIFO buffer size.
 Implement software fragmentation in host bus driver so that the
 I²C slave device drivers need not to be modified or to know about the
 limits.

This is quite a big change, does it need to go into a -rc, or can it
wait for the next kernel merge window?

-- 
Ben Dooks, b...@fluff.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] i2c-intel-mid: I2C FIFO buffer size setting and fragmentation

2011-01-25 Thread Alan Cox
From: Major Lee major_...@wistron.com

The FIFO buffer size is different with different CPU stepping.
Define it as 32-byte; it is safe for all CPU stepping.

There is a problem when xfer size is greater then FIFO buffer size.
Implement software fragmentation in host bus driver so that the
I²C slave device drivers need not to be modified or to know about the
limits.

Signed-off-by: Major Lee major_...@wistron.com
Signed-off-by: Alan Cox a...@linux.intel.com
---

 drivers/i2c/busses/i2c-intel-mid.c |   95 +---
 1 files changed, 46 insertions(+), 49 deletions(-)


diff --git a/drivers/i2c/busses/i2c-intel-mid.c 
b/drivers/i2c/busses/i2c-intel-mid.c
index 3975736..da4bbdd 100644
--- a/drivers/i2c/busses/i2c-intel-mid.c
+++ b/drivers/i2c/busses/i2c-intel-mid.c
@@ -54,6 +54,10 @@ enum mid_i2c_status {
STATUS_STANDBY
 };
 
+/* The FIFO buffer size is different with different CPU stepping */
+/* Define it as 32-byte; it is safe for all CPU stepping */
+#define I2C_FIFO_SIZE  32
+
 /**
  * struct intel_mid_i2c_private- per device I²C context
  * @adap: core i2c layer adapter information
@@ -62,7 +66,6 @@ enum mid_i2c_status {
  * @speed: speed mode for this port
  * @complete: completion object for transaction wait
  * @abort: reason for last abort
- * @rx_buf: pointer into working receive buffer
  * @rx_buf_len: receive buffer length
  * @status: adapter state machine
  * @msg: the message we are currently processing
@@ -79,7 +82,6 @@ struct intel_mid_i2c_private {
int speed;
struct completion complete;
u32 abort;
-   u8 *rx_buf;
int rx_buf_len;
enum mid_i2c_status status;
struct i2c_msg *msg;
@@ -560,17 +562,15 @@ static int xfer_read(struct i2c_adapter *adap, unsigned 
char *buf, int length)
int i = length;
int err;
 
-   if (length = 256) {
-   dev_err(adap-dev,
-   I2C FIFO cannot support larger than 256 bytes\n);
-   return -EMSGSIZE;
-   }
-
INIT_COMPLETION(i2c-complete);
 
readl(i2c-base + IC_CLR_INTR);
writel(0x0044, i2c-base + IC_INTR_MASK);
 
+   i2c-rx_buf_len = length;
+   /* set receive FIFO threshold */
+   writel((uint16_t)(length - 1), i2c-base + IC_RX_TL);
+
i2c-status = STATUS_READ_START;
 
while (i--)
@@ -614,12 +614,6 @@ static int xfer_write(struct i2c_adapter *adap,
struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
int i, err;
 
-   if (length = 256) {
-   dev_err(adap-dev,
-   I2C FIFO cannot support larger than 256 bytes\n);
-   return -EMSGSIZE;
-   }
-
INIT_COMPLETION(i2c-complete);
 
readl(i2c-base + IC_CLR_INTR);
@@ -748,6 +742,9 @@ static int intel_mid_i2c_xfer(struct i2c_adapter *adap,
 {
struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
int i, err = 0;
+   u16 len;
+   u8 *buf;
+   u16 xfer_len;
 
/* if number of messages equal 0*/
if (num == 0)
@@ -785,13 +782,35 @@ static int intel_mid_i2c_xfer(struct i2c_adapter *adap,
for (i = 0; i  num; i++) {
i2c-msg = pmsg;
i2c-status = STATUS_IDLE;
-   /* Read or Write */
-   if (pmsg-flags  I2C_M_RD) {
-   dev_dbg(adap-dev, I2C_M_RD\n);
-   err = xfer_read(adap, pmsg-buf, pmsg-len);
-   } else {
-   dev_dbg(adap-dev, I2C_M_WR\n);
-   err = xfer_write(adap, pmsg-buf, pmsg-len);
+
+   if (pmsg-len  pmsg-buf) {
+   len = pmsg-len;
+   buf = pmsg-buf;
+   xfer_len = 0;
+
+   while (len  buf) {
+   /* Fragment xfer data */
+   if (len = I2C_FIFO_SIZE)
+   xfer_len = I2C_FIFO_SIZE;
+   else
+   xfer_len = len;
+   /* Read or Write */
+   if (pmsg-flags  I2C_M_RD) {
+   dev_dbg(adap-dev, I2C_M_RD\n);
+   err = xfer_read(adap, buf, xfer_len);
+   } else {
+   dev_dbg(adap-dev, I2C_M_WR\n);
+   err = xfer_write(adap, buf, xfer_len);
+   }
+   if (err  0)
+   break;
+
+   len -= xfer_len;
+   if (len)
+   buf += xfer_len;
+   else /* len == 0 */
+   break;
+   }
}
if (err  0)