All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <42418D47.1070605@acm.org>

diff --git a/a/1.txt b/N1/1.txt
index b2f9c16..8b13789 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,8 +1 @@
 
--------------- next part --------------
-A non-text attachment was scrubbed...
-Name: i2c_add_op_q.diff
-Type: text/x-patch
-Size: 17639 bytes
-Desc: not available
-Url : http://lists.lm-sensors.org/pipermail/lm-sensors/attachments/20050323/d78096be/i2c_add_op_q.bin
diff --git a/N1/2.hdr b/N1/2.hdr
new file mode 100644
index 0000000..72d8f51
--- /dev/null
+++ b/N1/2.hdr
@@ -0,0 +1,5 @@
+Content-Type: text/x-patch;
+ name="i2c_add_op_q.diff"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline;
+ filename="i2c_add_op_q.diff"
diff --git a/N1/2.txt b/N1/2.txt
new file mode 100644
index 0000000..2201829
--- /dev/null
+++ b/N1/2.txt
@@ -0,0 +1,574 @@
+This patch adds an operation queue structure and converts over the
+passing around of data to use the operation queue.  The op queue
+entry will be used for queueing in the non-blocking case.
+
+Signed-off-by: Corey Minyard <minyard@acm.org>
+
+Index: linux-2.6.11-mm1/drivers/i2c/i2c-core.c
+===================================================================
+--- linux-2.6.11-mm1.orig/drivers/i2c/i2c-core.c
++++ linux-2.6.11-mm1/drivers/i2c/i2c-core.c
+@@ -582,24 +582,45 @@
+  * ----------------------------------------------------
+  */
+ 
+-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
++static void i2c_transfer_entry(struct i2c_adapter * adap,
++			       struct i2c_op_q_entry * entry)
+ {
+-	int ret;
+-
++	entry->xfer_type = I2C_OP_I2C;
++	entry->complete = NULL;
+ 	if (adap->algo->master_xfer) {
+- 	 	dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num);
++ 	 	dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n",
++			entry->i2c.num);
+ 
+ 		down(&adap->bus_lock);
+-		ret = adap->algo->master_xfer(adap,msgs,num);
++		entry->result = adap->algo->master_xfer(adap, entry->i2c.msgs,
++							entry->i2c.num);
+ 		up(&adap->bus_lock);
+-
+-		return ret;
++		if (entry->complete)
++		    entry->complete(adap, entry);
+ 	} else {
+ 		dev_dbg(&adap->dev, "I2C level transfers not supported\n");
+-		return -ENOSYS;
++		entry->result = -ENOSYS;
+ 	}
+ }
+ 
++int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
++{
++	struct i2c_op_q_entry *entry;
++	int                   rv;
++
++	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
++	if (!entry)
++	    return -ENOMEM;
++
++	entry->i2c.msgs = msgs;
++	entry->i2c.num = num;
++
++	i2c_transfer_entry(adap, entry);
++	rv = entry->result;
++	kfree(entry);
++	return rv;
++}
++
+ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
+ {
+ 	int ret;
+@@ -1038,185 +1059,181 @@
+ 	}
+ }
+ 
+-static int i2c_smbus_complete_entry(struct i2c_adapter * adapter, u16 addr,
+-				    unsigned short flags, char read_write,
+-				    u8 command, int size,
+-				    union i2c_smbus_data * data,
+-				    int swpec, u8 partial,
+-				    int result)
+-{
+-	if (result < 0)
+-		return result;
+-
+-	if(swpec &&
+-	   size != I2C_SMBUS_QUICK &&
+-	   size != I2C_SMBUS_I2C_BLOCK_DATA &&
+-	   (read_write == I2C_SMBUS_READ ||
+-	    size == I2C_SMBUS_PROC_CALL_PEC ||
+-	    size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
+-		if(i2c_smbus_check_pec(addr,
+-				       command,
+-				       size,
+-				       partial,
+-				       data))
+-			return -EINVAL;
+-	}
++static void i2c_smbus_complete_entry(struct i2c_adapter * adapter,
++				     struct i2c_op_q_entry * entry)
++{
++	if (entry->result < 0)
++		return;
+ 
+-	return 0;
++	if(entry->swpec &&
++	   entry->smbus.size != I2C_SMBUS_QUICK &&
++	   entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA &&
++	   (entry->smbus.read_write == I2C_SMBUS_READ ||
++	    entry->smbus.size == I2C_SMBUS_PROC_CALL_PEC ||
++	    entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
++		if(i2c_smbus_check_pec(entry->smbus.addr,
++				       entry->smbus.command,
++				       entry->smbus.size,
++				       entry->partial,
++				       entry->smbus.data))
++			entry->result = -EINVAL;
++	}
+ }
+ 
+-static void i2c_smbus_format_entry(struct i2c_adapter * adapter, u16 addr,
+-				   unsigned short *flags, char read_write,
+-				   u8 command, int *size,
+-				   union i2c_smbus_data * data,
+-				   int *swpec, u8 *partial)
+-{
+-	*swpec = 0;
+-	*partial = 0;
+-	*flags &= I2C_M_TEN | I2C_CLIENT_PEC;
+-	if((*flags & I2C_CLIENT_PEC) &&
++static void i2c_smbus_format_entry(struct i2c_adapter * adapter,
++				   struct i2c_op_q_entry * entry)
++{
++	entry->swpec = 0;
++	entry->partial = 0;
++	entry->smbus.flags &= I2C_M_TEN | I2C_CLIENT_PEC;
++	if((entry->smbus.flags & I2C_CLIENT_PEC) &&
+ 	   !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
+-		*swpec = 1;
+-		if(read_write == I2C_SMBUS_READ &&
+-		   *size == I2C_SMBUS_BLOCK_DATA)
+-			*size = I2C_SMBUS_BLOCK_DATA_PEC;
+-		else if(*size == I2C_SMBUS_PROC_CALL)
+-			*size = I2C_SMBUS_PROC_CALL_PEC;
+-		else if(*size == I2C_SMBUS_BLOCK_PROC_CALL) {
+-			unsigned char *sdata = data->block;
+-			i2c_smbus_add_pec(addr, command, I2C_SMBUS_BLOCK_DATA,
+-					  data);
+-			*partial = sdata[sdata[0] + 1];
+-			*size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
+-		} else if(read_write == I2C_SMBUS_WRITE &&
+-		          *size != I2C_SMBUS_QUICK &&
+-		          *size != I2C_SMBUS_I2C_BLOCK_DATA)
+-			*size = i2c_smbus_add_pec(addr, command, *size, data);
++		entry->swpec = 1;
++		if(entry->smbus.read_write == I2C_SMBUS_READ &&
++		   entry->smbus.size == I2C_SMBUS_BLOCK_DATA)
++			entry->smbus.size = I2C_SMBUS_BLOCK_DATA_PEC;
++		else if(entry->smbus.size == I2C_SMBUS_PROC_CALL)
++			entry->smbus.size = I2C_SMBUS_PROC_CALL_PEC;
++		else if(entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL) {
++			unsigned char *data = entry->smbus.data->block;
++			i2c_smbus_add_pec(entry->smbus.addr,
++					  entry->smbus.command,
++		                          I2C_SMBUS_BLOCK_DATA,
++					  entry->smbus.data);
++			entry->partial = data[data[0] + 1];
++			entry->smbus.size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
++		} else if(entry->smbus.read_write == I2C_SMBUS_WRITE &&
++		          entry->smbus.size != I2C_SMBUS_QUICK &&
++		          entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA)
++			entry->smbus.size =
++				i2c_smbus_add_pec(entry->smbus.addr,
++						  entry->smbus.command,
++						  entry->smbus.size,
++						  entry->smbus.data);
+ 	}
++
++	entry->complete = i2c_smbus_complete_entry;
+ }
+ 
+-static int i2c_smbus_emu_complete(struct i2c_adapter * adapter, u16 addr,
+-				  unsigned short flags, char read_write,
+-				  u8 command, int size, 
+-				  union i2c_smbus_data * data,
+-				  struct i2c_msg *msg,
+-				  int swpec, u8 partial,
+-				  int result)
++static void i2c_smbus_emu_complete(struct i2c_adapter * adapter,
++				   struct i2c_op_q_entry * entry)
+ {
+-	unsigned char *msgbuf0 = msg[0].buf;
+-	unsigned char *msgbuf1 = msg[1].buf;
++	unsigned char *msgbuf0 = entry->i2c.msgs[0].buf;
++	unsigned char *msgbuf1 = entry->i2c.msgs[1].buf;
+ 	int i;
+ 
++	if (entry->result < 0)
++		return;
+ 
+-	if (result < 0)
+-		return result;
++	if (entry->smbus.read_write != I2C_SMBUS_READ)
++		return;
+ 
+-	if (read_write != I2C_SMBUS_READ)
+-		return result;
+-
+-	switch(size) {
++	switch(entry->smbus.size) {
+ 	case I2C_SMBUS_BYTE:
+-		data->byte = msgbuf0[0];
++		entry->smbus.data->byte = msgbuf0[0];
+ 		break;
+ 	case I2C_SMBUS_BYTE_DATA:
+-		data->byte = msgbuf1[0];
++		entry->smbus.data->byte = msgbuf1[0];
+ 		break;
+ 	case I2C_SMBUS_WORD_DATA: 
+ 	case I2C_SMBUS_PROC_CALL:
+-		data->word = msgbuf1[0]|(msgbuf1[1] << 8);
++		entry->smbus.data->word = msgbuf1[0]|(msgbuf1[1] << 8);
+ 		break;
+ 	case I2C_SMBUS_I2C_BLOCK_DATA:
+ 		/* fixed at 32 for now */
+-		data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
++		entry->smbus.data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
+ 		for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
+-			data->block[i+1] = msgbuf1[i];
++			entry->smbus.data->block[i+1] = msgbuf1[i];
+ 		break;
+ 	}
+ 
+-	return i2c_smbus_complete_entry(adapter, addr, flags,
+-					read_write, command,
+-					size, data, swpec, partial, result);
++	entry->xfer_type = I2C_OP_SMBUS;
++	i2c_smbus_complete_entry(adapter, entry);
+ }
+ 
+-static int i2c_smbus_emu_format(struct i2c_adapter *adapter, u16 addr,
+-				unsigned short flags, char read_write,
+-				u8 command, int size, 
+-				union i2c_smbus_data * data,
+-				struct i2c_msg *msg)
++static int i2c_smbus_emu_format(struct i2c_adapter *adapter,
++				struct i2c_op_q_entry * entry)
+ {
+ 	/* So we need to generate a series of msgs. In the case of
+ 	   writing, we need to use only one message; when reading, we
+ 	   need two. We initialize most things with sane defaults, to
+ 	   keep the code below somewhat simpler. */
+-	unsigned char *msgbuf0 = msg[0].buf;
+-	int num = read_write == I2C_SMBUS_READ?2:1;
++	unsigned char *msgbuf0 = entry->msgbuf0;
++	int num = entry->smbus.read_write == I2C_SMBUS_READ?2:1;
++	struct i2c_msg *msg = entry->msg;
+ 	int i;
+ 
+-	msg[0].addr = addr;
+-	msg[0].flags = flags;
++	entry->i2c.msgs = msg;
++	entry->i2c.msgs[0].buf = msgbuf0;
++	entry->i2c.msgs[1].buf = entry->msgbuf1;
++
++	msg[0].addr = entry->smbus.addr;
++	msg[0].flags = entry->smbus.flags;
+ 	msg[0].len = 1;
+-	msg[1].addr = addr;
+-	msg[1].flags = flags | I2C_M_RD;
++	msg[1].addr = entry->smbus.addr;
++	msg[1].flags = entry->smbus.flags | I2C_M_RD;
+ 	msg[1].len = 0;
+ 
+-	msgbuf0[0] = command;
+-	switch(size) {
++	msgbuf0[0] = entry->smbus.command;
++	switch(entry->smbus.size) {
+ 	case I2C_SMBUS_QUICK:
+ 		msg[0].len = 0;
+ 		/* Special case: The read/write field is used as data */
+-		msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;
++		msg[0].flags = (entry->smbus.flags |
++				((entry->smbus.read_write==I2C_SMBUS_READ)
++				 ? I2C_M_RD : 0));
+ 		num = 1;
+ 		break;
+ 	case I2C_SMBUS_BYTE:
+-		if (read_write == I2C_SMBUS_READ) {
++		if (entry->smbus.read_write == I2C_SMBUS_READ) {
+ 			/* Special case: only a read! */
+-			msg[0].flags = I2C_M_RD | flags;
++			msg[0].flags = I2C_M_RD | entry->smbus.flags;
+ 			num = 1;
+ 		}
+ 		break;
+ 	case I2C_SMBUS_BYTE_DATA:
+-		if (read_write == I2C_SMBUS_READ)
++		if (entry->smbus.read_write == I2C_SMBUS_READ)
+ 			msg[1].len = 1;
+ 		else {
+ 			msg[0].len = 2;
+-			msgbuf0[1] = data->byte;
++			msgbuf0[1] = entry->smbus.data->byte;
+ 		}
+ 		break;
+ 	case I2C_SMBUS_WORD_DATA:
+-		if (read_write == I2C_SMBUS_READ)
++		if (entry->smbus.read_write == I2C_SMBUS_READ)
+ 			msg[1].len = 2;
+ 		else {
+ 			msg[0].len=3;
+-			msgbuf0[1] = data->word & 0xff;
+-			msgbuf0[2] = (data->word >> 8) & 0xff;
++			msgbuf0[1] = entry->smbus.data->word & 0xff;
++			msgbuf0[2] = (entry->smbus.data->word >> 8) & 0xff;
+ 		}
+ 		break;
+ 	case I2C_SMBUS_PROC_CALL:
+ 		num = 2; /* Special case */
+-		read_write = I2C_SMBUS_READ;
++		entry->smbus.read_write = I2C_SMBUS_READ;
+ 		msg[0].len = 3;
+ 		msg[1].len = 2;
+-		msgbuf0[1] = data->word & 0xff;
+-		msgbuf0[2] = (data->word >> 8) & 0xff;
++		msgbuf0[1] = entry->smbus.data->word & 0xff;
++		msgbuf0[2] = (entry->smbus.data->word >> 8) & 0xff;
+ 		break;
+ 	case I2C_SMBUS_BLOCK_DATA:
+ 	case I2C_SMBUS_BLOCK_DATA_PEC:
+-		if (read_write == I2C_SMBUS_READ) {
++		if (entry->smbus.read_write == I2C_SMBUS_READ) {
+ 			dev_err(&adapter->dev, "Block read not supported "
+ 			       "under I2C emulation!\n");
+ 			return -1;
+ 		} else {
+-			msg[0].len = data->block[0] + 2;
++			msg[0].len = entry->smbus.data->block[0] + 2;
+ 			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
+ 				dev_err(&adapter->dev, "smbus_access called with "
+ 				       "invalid block write size (%d)\n",
+-				       data->block[0]);
++				       entry->smbus.data->block[0]);
+ 				return -1;
+ 			}
+-			if(size == I2C_SMBUS_BLOCK_DATA_PEC)
++			if(entry->smbus.size == I2C_SMBUS_BLOCK_DATA_PEC)
+ 				(msg[0].len)++;
+ 			for (i = 1; i <= msg[0].len; i++)
+-				msgbuf0[i] = data->block[i-1];
++				msgbuf0[i] = entry->smbus.data->block[i-1];
+ 		}
+ 		break;
+ 	case I2C_SMBUS_BLOCK_PROC_CALL:
+@@ -1225,26 +1242,30 @@
+ 		       "under I2C emulation!\n");
+ 		return -1;
+ 	case I2C_SMBUS_I2C_BLOCK_DATA:
+-		if (read_write == I2C_SMBUS_READ) {
++		if (entry->smbus.read_write == I2C_SMBUS_READ) {
+ 			msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
+ 		} else {
+-			msg[0].len = data->block[0] + 1;
++			msg[0].len = entry->smbus.data->block[0] + 1;
+ 			if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
+ 				dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
+ 				       "invalid block write size (%d)\n",
+-				       data->block[0]);
++				       entry->smbus.data->block[0]);
+ 				return -1;
+ 			}
+-			for (i = 1; i <= data->block[0]; i++)
+-				msgbuf0[i] = data->block[i];
++			for (i = 1; i <= entry->smbus.data->block[0]; i++)
++				msgbuf0[i] = entry->smbus.data->block[i];
+ 		}
+ 		break;
+ 	default:
+ 		dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n",
+-		       size);
++		       entry->smbus.size);
+ 		return -1;
+ 	}
+ 
++	entry->xfer_type = I2C_OP_I2C;
++	entry->i2c.msgs = msg;
++	entry->i2c.num = num;
++	entry->complete = i2c_smbus_emu_complete;
+ 	return 0;
+ }
+ 
+@@ -1253,46 +1274,42 @@
+                    char read_write, u8 command, int size, 
+                    union i2c_smbus_data * data)
+ {
++	struct i2c_op_q_entry *entry;
+ 	s32 res;
+-	int swpec = 0;
+-	u8 partial = 0;
+ 	struct i2c_algorithm *algo = adapter->algo;
+ 
+ 
+-	i2c_smbus_format_entry(adapter, addr, &flags,
+-			       read_write, command,
+-			       &size, data, &swpec, &partial);
++	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
++	if (!entry)
++	    return -ENOMEM;
++
++	entry->xfer_type = I2C_OP_SMBUS;
++	entry->smbus.addr = addr;
++	entry->smbus.flags = flags;
++	entry->smbus.read_write = read_write;
++	entry->smbus.command = command;
++	entry->smbus.size = size;
++	entry->smbus.data = data;
++
++	i2c_smbus_format_entry(adapter, entry);
+ 
+ 	if (algo->smbus_xfer) {
+ 		down(&adapter->bus_lock);
+-		res = adapter->algo->smbus_xfer(adapter, addr, flags,
+-						read_write, command,
+-						size, data);
++		entry->result = adapter->algo->smbus_xfer
++		  (adapter, entry->smbus.addr, entry->smbus.flags,
++		   entry->smbus.read_write, entry->smbus.command,
++		   entry->smbus.size, entry->smbus.data);
+ 		up(&adapter->bus_lock);
+-		res = i2c_smbus_complete_entry(adapter, addr, flags,
+-					       read_write, command,
+-					       size, data, swpec, partial,
+-					       res);
++		if (entry->complete)
++		    entry->complete(adapter, entry);
+ 	} else {
+-		unsigned char msgbuf0[34];
+-		unsigned char msgbuf1[34];
+-		struct i2c_msg msg[2];
+-
+-		msg[0].buf = msgbuf0;
+-		msg[1].buf = msgbuf1;
+-		if (i2c_smbus_emu_format(adapter, addr, flags,
+-					 read_write, command,
+-					 size, data, msg))
+-			res = -EINVAL;
+-		else {
+-			res = i2c_transfer(adapter, msg, 2);
+-			res = i2c_smbus_emu_complete(adapter, addr, flags,
+-						     read_write, command,
+-						     size, data, msg,
+-						     swpec, partial,
+-						     res);
+-		}
++		if (i2c_smbus_emu_format(adapter, entry))
++			entry->result = -EINVAL;
++		else
++			i2c_transfer_entry(adapter, entry);
+ 	}
++	res = entry->result;
++	kfree(entry);
+ 	return res;
+ }
+ 
+Index: linux-2.6.11-mm1/include/linux/i2c.h
+===================================================================
+--- linux-2.6.11-mm1.orig/include/linux/i2c.h
++++ linux-2.6.11-mm1/include/linux/i2c.h
+@@ -32,7 +32,10 @@
+ #include <linux/types.h>
+ #include <linux/i2c-id.h>
+ #include <linux/device.h>	/* for struct device */
++#include <linux/completion.h>
++#include <linux/kref.h>
+ #include <asm/semaphore.h>
++#include <asm/atomic.h>
+ 
+ /* --- General options ------------------------------------------------	*/
+ 
+@@ -43,6 +46,7 @@
+ struct i2c_driver;
+ struct i2c_client_address_data;
+ union i2c_smbus_data;
++struct i2c_op_q_entry;
+ 
+ /*
+  * The master routines are the ones normally used to transmit data to devices
+@@ -392,6 +396,92 @@
+  	__u8 *buf;		/* pointer to msg data			*/
+ };
+ 
++/*
++ * Hold a queue of I2C operations to perform, and used to pass data
++ * around.
++ */
++typedef void (*i2c_op_done_cb)(struct i2c_op_q_entry *entry);
++
++#define I2C_OP_I2C	0
++#define I2C_OP_SMBUS	1
++struct i2c_op_q_entry {
++	/* The result will be set to the result of the operation when
++	   it completes. */
++	s32 result;
++
++	/**************************************************************/
++	/* Public interface.  The user should set these up (and the
++	   proper structure below). */
++	int            xfer_type;
++
++	/* Handler may be called from interrupt context, so be
++	   careful. */
++	i2c_op_done_cb handler;
++	void           *handler_data;
++
++	/* Note that this is not a union because an smbus operation
++	   may be converted into an i2c operation (thus both
++	   structures will be used).  The data in these may be changd
++	   by the driver. */
++	struct {
++		struct i2c_msg *msgs;
++		int num;
++	} i2c;
++	struct {
++		/* Addr and flags are filled in by the non-blocking
++		   send routine that takes a client. */
++		u16 addr;
++		unsigned short flags;
++
++		char read_write;
++		u8 command;
++
++		/* Note that the size is *not* the length of the data.
++		   It is the transaction type, like I2C_SMBUS_QUICK
++		   and the ones after that below.  If this is a block
++		   transaction, the length of the rest of the data is
++		   in the first byte of the data, for both transmit
++		   and receive. */
++		int size;
++		union i2c_smbus_data *data;
++	} smbus;
++
++	/**************************************************************/
++	/* For use by the bus interface.  The bus interface sets the
++	   timeout in microseconds until the next poll operation.
++	   This *must* be set in the start operation.  The time_left
++	   and data can be used for anything the bus interface likes.
++	   data will be set to NULL before being started so the bus
++	   interface can use that to tell if it has been set up
++	   yet. */
++	unsigned int call_again_us;
++	long         time_left;
++	void         *data;
++
++	/**************************************************************/
++	/* Internals */
++	struct list_head  link;
++	struct completion *start;
++	atomic_t          completed;
++	unsigned int      started : 1;
++	unsigned int      use_timer : 1;
++	u8                swpec;
++	u8                partial;
++	void (*complete)(struct i2c_adapter    *adap,
++			 struct i2c_op_q_entry *entry);
++
++	/* It's wierd, but we use a usecount to track if an q entry is
++	   in use and when it should be reported back to the user. */
++	struct kref usecount;
++
++	/* These are here for SMBus emulation over I2C.  I don't like
++	   them taking this much room in the data structure, but they
++	   need to be available in this case. */
++	unsigned char msgbuf0[34];
++	unsigned char msgbuf1[34];
++	struct i2c_msg msg[2];
++};
++
+ /* To determine what functionality is present */
+ 
+ #define I2C_FUNC_I2C			0x00000001
diff --git a/a/content_digest b/N1/content_digest
index 065ccff..1d31845 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,18 +1,587 @@
- "From\0minyard@acm.org (Corey Minyard)\0"
+ "From\0Corey Minyard <minyard@acm.org>\0"
  "Subject\0[PATCH] I2C Part 3 - Add an operation queue data structure\0"
- "Date\0Thu, 19 May 2005 06:25:45 +0000\0"
+ "Date\0Wed, 23 Mar 2005 09:37:43 -0600\0"
  "To\0Greg KH <greg@kroah.com>"
   lkml <linux-kernel@vger.kernel.org>
  " Sensors <sensors@stimpy.netroedge.com>\0"
- "\00:1\0"
+ "\01:1\0"
  "b\0"
+ "\01:2\0"
+ "fn\0i2c_add_op_q.diff\0"
+ "b\0"
+ "This patch adds an operation queue structure and converts over the\n"
+ "passing around of data to use the operation queue.  The op queue\n"
+ "entry will be used for queueing in the non-blocking case.\n"
+ "\n"
+ "Signed-off-by: Corey Minyard <minyard@acm.org>\n"
  "\n"
- "-------------- next part --------------\n"
- "A non-text attachment was scrubbed...\n"
- "Name: i2c_add_op_q.diff\n"
- "Type: text/x-patch\n"
- "Size: 17639 bytes\n"
- "Desc: not available\n"
- Url : http://lists.lm-sensors.org/pipermail/lm-sensors/attachments/20050323/d78096be/i2c_add_op_q.bin
+ "Index: linux-2.6.11-mm1/drivers/i2c/i2c-core.c\n"
+ "===================================================================\n"
+ "--- linux-2.6.11-mm1.orig/drivers/i2c/i2c-core.c\n"
+ "+++ linux-2.6.11-mm1/drivers/i2c/i2c-core.c\n"
+ "@@ -582,24 +582,45 @@\n"
+ "  * ----------------------------------------------------\n"
+ "  */\n"
+ " \n"
+ "-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)\n"
+ "+static void i2c_transfer_entry(struct i2c_adapter * adap,\n"
+ "+\t\t\t       struct i2c_op_q_entry * entry)\n"
+ " {\n"
+ "-\tint ret;\n"
+ "-\n"
+ "+\tentry->xfer_type = I2C_OP_I2C;\n"
+ "+\tentry->complete = NULL;\n"
+ " \tif (adap->algo->master_xfer) {\n"
+ "- \t \tdev_dbg(&adap->dev, \"master_xfer: with %d msgs.\\n\", num);\n"
+ "+ \t \tdev_dbg(&adap->dev, \"master_xfer: with %d msgs.\\n\",\n"
+ "+\t\t\tentry->i2c.num);\n"
+ " \n"
+ " \t\tdown(&adap->bus_lock);\n"
+ "-\t\tret = adap->algo->master_xfer(adap,msgs,num);\n"
+ "+\t\tentry->result = adap->algo->master_xfer(adap, entry->i2c.msgs,\n"
+ "+\t\t\t\t\t\t\tentry->i2c.num);\n"
+ " \t\tup(&adap->bus_lock);\n"
+ "-\n"
+ "-\t\treturn ret;\n"
+ "+\t\tif (entry->complete)\n"
+ "+\t\t    entry->complete(adap, entry);\n"
+ " \t} else {\n"
+ " \t\tdev_dbg(&adap->dev, \"I2C level transfers not supported\\n\");\n"
+ "-\t\treturn -ENOSYS;\n"
+ "+\t\tentry->result = -ENOSYS;\n"
+ " \t}\n"
+ " }\n"
+ " \n"
+ "+int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)\n"
+ "+{\n"
+ "+\tstruct i2c_op_q_entry *entry;\n"
+ "+\tint                   rv;\n"
+ "+\n"
+ "+\tentry = kmalloc(sizeof(*entry), GFP_KERNEL);\n"
+ "+\tif (!entry)\n"
+ "+\t    return -ENOMEM;\n"
+ "+\n"
+ "+\tentry->i2c.msgs = msgs;\n"
+ "+\tentry->i2c.num = num;\n"
+ "+\n"
+ "+\ti2c_transfer_entry(adap, entry);\n"
+ "+\trv = entry->result;\n"
+ "+\tkfree(entry);\n"
+ "+\treturn rv;\n"
+ "+}\n"
+ "+\n"
+ " int i2c_master_send(struct i2c_client *client,const char *buf ,int count)\n"
+ " {\n"
+ " \tint ret;\n"
+ "@@ -1038,185 +1059,181 @@\n"
+ " \t}\n"
+ " }\n"
+ " \n"
+ "-static int i2c_smbus_complete_entry(struct i2c_adapter * adapter, u16 addr,\n"
+ "-\t\t\t\t    unsigned short flags, char read_write,\n"
+ "-\t\t\t\t    u8 command, int size,\n"
+ "-\t\t\t\t    union i2c_smbus_data * data,\n"
+ "-\t\t\t\t    int swpec, u8 partial,\n"
+ "-\t\t\t\t    int result)\n"
+ "-{\n"
+ "-\tif (result < 0)\n"
+ "-\t\treturn result;\n"
+ "-\n"
+ "-\tif(swpec &&\n"
+ "-\t   size != I2C_SMBUS_QUICK &&\n"
+ "-\t   size != I2C_SMBUS_I2C_BLOCK_DATA &&\n"
+ "-\t   (read_write == I2C_SMBUS_READ ||\n"
+ "-\t    size == I2C_SMBUS_PROC_CALL_PEC ||\n"
+ "-\t    size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {\n"
+ "-\t\tif(i2c_smbus_check_pec(addr,\n"
+ "-\t\t\t\t       command,\n"
+ "-\t\t\t\t       size,\n"
+ "-\t\t\t\t       partial,\n"
+ "-\t\t\t\t       data))\n"
+ "-\t\t\treturn -EINVAL;\n"
+ "-\t}\n"
+ "+static void i2c_smbus_complete_entry(struct i2c_adapter * adapter,\n"
+ "+\t\t\t\t     struct i2c_op_q_entry * entry)\n"
+ "+{\n"
+ "+\tif (entry->result < 0)\n"
+ "+\t\treturn;\n"
+ " \n"
+ "-\treturn 0;\n"
+ "+\tif(entry->swpec &&\n"
+ "+\t   entry->smbus.size != I2C_SMBUS_QUICK &&\n"
+ "+\t   entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA &&\n"
+ "+\t   (entry->smbus.read_write == I2C_SMBUS_READ ||\n"
+ "+\t    entry->smbus.size == I2C_SMBUS_PROC_CALL_PEC ||\n"
+ "+\t    entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {\n"
+ "+\t\tif(i2c_smbus_check_pec(entry->smbus.addr,\n"
+ "+\t\t\t\t       entry->smbus.command,\n"
+ "+\t\t\t\t       entry->smbus.size,\n"
+ "+\t\t\t\t       entry->partial,\n"
+ "+\t\t\t\t       entry->smbus.data))\n"
+ "+\t\t\tentry->result = -EINVAL;\n"
+ "+\t}\n"
+ " }\n"
+ " \n"
+ "-static void i2c_smbus_format_entry(struct i2c_adapter * adapter, u16 addr,\n"
+ "-\t\t\t\t   unsigned short *flags, char read_write,\n"
+ "-\t\t\t\t   u8 command, int *size,\n"
+ "-\t\t\t\t   union i2c_smbus_data * data,\n"
+ "-\t\t\t\t   int *swpec, u8 *partial)\n"
+ "-{\n"
+ "-\t*swpec = 0;\n"
+ "-\t*partial = 0;\n"
+ "-\t*flags &= I2C_M_TEN | I2C_CLIENT_PEC;\n"
+ "-\tif((*flags & I2C_CLIENT_PEC) &&\n"
+ "+static void i2c_smbus_format_entry(struct i2c_adapter * adapter,\n"
+ "+\t\t\t\t   struct i2c_op_q_entry * entry)\n"
+ "+{\n"
+ "+\tentry->swpec = 0;\n"
+ "+\tentry->partial = 0;\n"
+ "+\tentry->smbus.flags &= I2C_M_TEN | I2C_CLIENT_PEC;\n"
+ "+\tif((entry->smbus.flags & I2C_CLIENT_PEC) &&\n"
+ " \t   !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {\n"
+ "-\t\t*swpec = 1;\n"
+ "-\t\tif(read_write == I2C_SMBUS_READ &&\n"
+ "-\t\t   *size == I2C_SMBUS_BLOCK_DATA)\n"
+ "-\t\t\t*size = I2C_SMBUS_BLOCK_DATA_PEC;\n"
+ "-\t\telse if(*size == I2C_SMBUS_PROC_CALL)\n"
+ "-\t\t\t*size = I2C_SMBUS_PROC_CALL_PEC;\n"
+ "-\t\telse if(*size == I2C_SMBUS_BLOCK_PROC_CALL) {\n"
+ "-\t\t\tunsigned char *sdata = data->block;\n"
+ "-\t\t\ti2c_smbus_add_pec(addr, command, I2C_SMBUS_BLOCK_DATA,\n"
+ "-\t\t\t\t\t  data);\n"
+ "-\t\t\t*partial = sdata[sdata[0] + 1];\n"
+ "-\t\t\t*size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;\n"
+ "-\t\t} else if(read_write == I2C_SMBUS_WRITE &&\n"
+ "-\t\t          *size != I2C_SMBUS_QUICK &&\n"
+ "-\t\t          *size != I2C_SMBUS_I2C_BLOCK_DATA)\n"
+ "-\t\t\t*size = i2c_smbus_add_pec(addr, command, *size, data);\n"
+ "+\t\tentry->swpec = 1;\n"
+ "+\t\tif(entry->smbus.read_write == I2C_SMBUS_READ &&\n"
+ "+\t\t   entry->smbus.size == I2C_SMBUS_BLOCK_DATA)\n"
+ "+\t\t\tentry->smbus.size = I2C_SMBUS_BLOCK_DATA_PEC;\n"
+ "+\t\telse if(entry->smbus.size == I2C_SMBUS_PROC_CALL)\n"
+ "+\t\t\tentry->smbus.size = I2C_SMBUS_PROC_CALL_PEC;\n"
+ "+\t\telse if(entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL) {\n"
+ "+\t\t\tunsigned char *data = entry->smbus.data->block;\n"
+ "+\t\t\ti2c_smbus_add_pec(entry->smbus.addr,\n"
+ "+\t\t\t\t\t  entry->smbus.command,\n"
+ "+\t\t                          I2C_SMBUS_BLOCK_DATA,\n"
+ "+\t\t\t\t\t  entry->smbus.data);\n"
+ "+\t\t\tentry->partial = data[data[0] + 1];\n"
+ "+\t\t\tentry->smbus.size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;\n"
+ "+\t\t} else if(entry->smbus.read_write == I2C_SMBUS_WRITE &&\n"
+ "+\t\t          entry->smbus.size != I2C_SMBUS_QUICK &&\n"
+ "+\t\t          entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA)\n"
+ "+\t\t\tentry->smbus.size =\n"
+ "+\t\t\t\ti2c_smbus_add_pec(entry->smbus.addr,\n"
+ "+\t\t\t\t\t\t  entry->smbus.command,\n"
+ "+\t\t\t\t\t\t  entry->smbus.size,\n"
+ "+\t\t\t\t\t\t  entry->smbus.data);\n"
+ " \t}\n"
+ "+\n"
+ "+\tentry->complete = i2c_smbus_complete_entry;\n"
+ " }\n"
+ " \n"
+ "-static int i2c_smbus_emu_complete(struct i2c_adapter * adapter, u16 addr,\n"
+ "-\t\t\t\t  unsigned short flags, char read_write,\n"
+ "-\t\t\t\t  u8 command, int size, \n"
+ "-\t\t\t\t  union i2c_smbus_data * data,\n"
+ "-\t\t\t\t  struct i2c_msg *msg,\n"
+ "-\t\t\t\t  int swpec, u8 partial,\n"
+ "-\t\t\t\t  int result)\n"
+ "+static void i2c_smbus_emu_complete(struct i2c_adapter * adapter,\n"
+ "+\t\t\t\t   struct i2c_op_q_entry * entry)\n"
+ " {\n"
+ "-\tunsigned char *msgbuf0 = msg[0].buf;\n"
+ "-\tunsigned char *msgbuf1 = msg[1].buf;\n"
+ "+\tunsigned char *msgbuf0 = entry->i2c.msgs[0].buf;\n"
+ "+\tunsigned char *msgbuf1 = entry->i2c.msgs[1].buf;\n"
+ " \tint i;\n"
+ " \n"
+ "+\tif (entry->result < 0)\n"
+ "+\t\treturn;\n"
+ " \n"
+ "-\tif (result < 0)\n"
+ "-\t\treturn result;\n"
+ "+\tif (entry->smbus.read_write != I2C_SMBUS_READ)\n"
+ "+\t\treturn;\n"
+ " \n"
+ "-\tif (read_write != I2C_SMBUS_READ)\n"
+ "-\t\treturn result;\n"
+ "-\n"
+ "-\tswitch(size) {\n"
+ "+\tswitch(entry->smbus.size) {\n"
+ " \tcase I2C_SMBUS_BYTE:\n"
+ "-\t\tdata->byte = msgbuf0[0];\n"
+ "+\t\tentry->smbus.data->byte = msgbuf0[0];\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_BYTE_DATA:\n"
+ "-\t\tdata->byte = msgbuf1[0];\n"
+ "+\t\tentry->smbus.data->byte = msgbuf1[0];\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_WORD_DATA: \n"
+ " \tcase I2C_SMBUS_PROC_CALL:\n"
+ "-\t\tdata->word = msgbuf1[0]|(msgbuf1[1] << 8);\n"
+ "+\t\tentry->smbus.data->word = msgbuf1[0]|(msgbuf1[1] << 8);\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_I2C_BLOCK_DATA:\n"
+ " \t\t/* fixed at 32 for now */\n"
+ "-\t\tdata->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;\n"
+ "+\t\tentry->smbus.data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;\n"
+ " \t\tfor (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)\n"
+ "-\t\t\tdata->block[i+1] = msgbuf1[i];\n"
+ "+\t\t\tentry->smbus.data->block[i+1] = msgbuf1[i];\n"
+ " \t\tbreak;\n"
+ " \t}\n"
+ " \n"
+ "-\treturn i2c_smbus_complete_entry(adapter, addr, flags,\n"
+ "-\t\t\t\t\tread_write, command,\n"
+ "-\t\t\t\t\tsize, data, swpec, partial, result);\n"
+ "+\tentry->xfer_type = I2C_OP_SMBUS;\n"
+ "+\ti2c_smbus_complete_entry(adapter, entry);\n"
+ " }\n"
+ " \n"
+ "-static int i2c_smbus_emu_format(struct i2c_adapter *adapter, u16 addr,\n"
+ "-\t\t\t\tunsigned short flags, char read_write,\n"
+ "-\t\t\t\tu8 command, int size, \n"
+ "-\t\t\t\tunion i2c_smbus_data * data,\n"
+ "-\t\t\t\tstruct i2c_msg *msg)\n"
+ "+static int i2c_smbus_emu_format(struct i2c_adapter *adapter,\n"
+ "+\t\t\t\tstruct i2c_op_q_entry * entry)\n"
+ " {\n"
+ " \t/* So we need to generate a series of msgs. In the case of\n"
+ " \t   writing, we need to use only one message; when reading, we\n"
+ " \t   need two. We initialize most things with sane defaults, to\n"
+ " \t   keep the code below somewhat simpler. */\n"
+ "-\tunsigned char *msgbuf0 = msg[0].buf;\n"
+ "-\tint num = read_write == I2C_SMBUS_READ?2:1;\n"
+ "+\tunsigned char *msgbuf0 = entry->msgbuf0;\n"
+ "+\tint num = entry->smbus.read_write == I2C_SMBUS_READ?2:1;\n"
+ "+\tstruct i2c_msg *msg = entry->msg;\n"
+ " \tint i;\n"
+ " \n"
+ "-\tmsg[0].addr = addr;\n"
+ "-\tmsg[0].flags = flags;\n"
+ "+\tentry->i2c.msgs = msg;\n"
+ "+\tentry->i2c.msgs[0].buf = msgbuf0;\n"
+ "+\tentry->i2c.msgs[1].buf = entry->msgbuf1;\n"
+ "+\n"
+ "+\tmsg[0].addr = entry->smbus.addr;\n"
+ "+\tmsg[0].flags = entry->smbus.flags;\n"
+ " \tmsg[0].len = 1;\n"
+ "-\tmsg[1].addr = addr;\n"
+ "-\tmsg[1].flags = flags | I2C_M_RD;\n"
+ "+\tmsg[1].addr = entry->smbus.addr;\n"
+ "+\tmsg[1].flags = entry->smbus.flags | I2C_M_RD;\n"
+ " \tmsg[1].len = 0;\n"
+ " \n"
+ "-\tmsgbuf0[0] = command;\n"
+ "-\tswitch(size) {\n"
+ "+\tmsgbuf0[0] = entry->smbus.command;\n"
+ "+\tswitch(entry->smbus.size) {\n"
+ " \tcase I2C_SMBUS_QUICK:\n"
+ " \t\tmsg[0].len = 0;\n"
+ " \t\t/* Special case: The read/write field is used as data */\n"
+ "-\t\tmsg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;\n"
+ "+\t\tmsg[0].flags = (entry->smbus.flags |\n"
+ "+\t\t\t\t((entry->smbus.read_write==I2C_SMBUS_READ)\n"
+ "+\t\t\t\t ? I2C_M_RD : 0));\n"
+ " \t\tnum = 1;\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_BYTE:\n"
+ "-\t\tif (read_write == I2C_SMBUS_READ) {\n"
+ "+\t\tif (entry->smbus.read_write == I2C_SMBUS_READ) {\n"
+ " \t\t\t/* Special case: only a read! */\n"
+ "-\t\t\tmsg[0].flags = I2C_M_RD | flags;\n"
+ "+\t\t\tmsg[0].flags = I2C_M_RD | entry->smbus.flags;\n"
+ " \t\t\tnum = 1;\n"
+ " \t\t}\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_BYTE_DATA:\n"
+ "-\t\tif (read_write == I2C_SMBUS_READ)\n"
+ "+\t\tif (entry->smbus.read_write == I2C_SMBUS_READ)\n"
+ " \t\t\tmsg[1].len = 1;\n"
+ " \t\telse {\n"
+ " \t\t\tmsg[0].len = 2;\n"
+ "-\t\t\tmsgbuf0[1] = data->byte;\n"
+ "+\t\t\tmsgbuf0[1] = entry->smbus.data->byte;\n"
+ " \t\t}\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_WORD_DATA:\n"
+ "-\t\tif (read_write == I2C_SMBUS_READ)\n"
+ "+\t\tif (entry->smbus.read_write == I2C_SMBUS_READ)\n"
+ " \t\t\tmsg[1].len = 2;\n"
+ " \t\telse {\n"
+ " \t\t\tmsg[0].len=3;\n"
+ "-\t\t\tmsgbuf0[1] = data->word & 0xff;\n"
+ "-\t\t\tmsgbuf0[2] = (data->word >> 8) & 0xff;\n"
+ "+\t\t\tmsgbuf0[1] = entry->smbus.data->word & 0xff;\n"
+ "+\t\t\tmsgbuf0[2] = (entry->smbus.data->word >> 8) & 0xff;\n"
+ " \t\t}\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_PROC_CALL:\n"
+ " \t\tnum = 2; /* Special case */\n"
+ "-\t\tread_write = I2C_SMBUS_READ;\n"
+ "+\t\tentry->smbus.read_write = I2C_SMBUS_READ;\n"
+ " \t\tmsg[0].len = 3;\n"
+ " \t\tmsg[1].len = 2;\n"
+ "-\t\tmsgbuf0[1] = data->word & 0xff;\n"
+ "-\t\tmsgbuf0[2] = (data->word >> 8) & 0xff;\n"
+ "+\t\tmsgbuf0[1] = entry->smbus.data->word & 0xff;\n"
+ "+\t\tmsgbuf0[2] = (entry->smbus.data->word >> 8) & 0xff;\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_BLOCK_DATA:\n"
+ " \tcase I2C_SMBUS_BLOCK_DATA_PEC:\n"
+ "-\t\tif (read_write == I2C_SMBUS_READ) {\n"
+ "+\t\tif (entry->smbus.read_write == I2C_SMBUS_READ) {\n"
+ " \t\t\tdev_err(&adapter->dev, \"Block read not supported \"\n"
+ " \t\t\t       \"under I2C emulation!\\n\");\n"
+ " \t\t\treturn -1;\n"
+ " \t\t} else {\n"
+ "-\t\t\tmsg[0].len = data->block[0] + 2;\n"
+ "+\t\t\tmsg[0].len = entry->smbus.data->block[0] + 2;\n"
+ " \t\t\tif (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {\n"
+ " \t\t\t\tdev_err(&adapter->dev, \"smbus_access called with \"\n"
+ " \t\t\t\t       \"invalid block write size (%d)\\n\",\n"
+ "-\t\t\t\t       data->block[0]);\n"
+ "+\t\t\t\t       entry->smbus.data->block[0]);\n"
+ " \t\t\t\treturn -1;\n"
+ " \t\t\t}\n"
+ "-\t\t\tif(size == I2C_SMBUS_BLOCK_DATA_PEC)\n"
+ "+\t\t\tif(entry->smbus.size == I2C_SMBUS_BLOCK_DATA_PEC)\n"
+ " \t\t\t\t(msg[0].len)++;\n"
+ " \t\t\tfor (i = 1; i <= msg[0].len; i++)\n"
+ "-\t\t\t\tmsgbuf0[i] = data->block[i-1];\n"
+ "+\t\t\t\tmsgbuf0[i] = entry->smbus.data->block[i-1];\n"
+ " \t\t}\n"
+ " \t\tbreak;\n"
+ " \tcase I2C_SMBUS_BLOCK_PROC_CALL:\n"
+ "@@ -1225,26 +1242,30 @@\n"
+ " \t\t       \"under I2C emulation!\\n\");\n"
+ " \t\treturn -1;\n"
+ " \tcase I2C_SMBUS_I2C_BLOCK_DATA:\n"
+ "-\t\tif (read_write == I2C_SMBUS_READ) {\n"
+ "+\t\tif (entry->smbus.read_write == I2C_SMBUS_READ) {\n"
+ " \t\t\tmsg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;\n"
+ " \t\t} else {\n"
+ "-\t\t\tmsg[0].len = data->block[0] + 1;\n"
+ "+\t\t\tmsg[0].len = entry->smbus.data->block[0] + 1;\n"
+ " \t\t\tif (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {\n"
+ " \t\t\t\tdev_err(&adapter->dev, \"i2c_smbus_xfer_emulated called with \"\n"
+ " \t\t\t\t       \"invalid block write size (%d)\\n\",\n"
+ "-\t\t\t\t       data->block[0]);\n"
+ "+\t\t\t\t       entry->smbus.data->block[0]);\n"
+ " \t\t\t\treturn -1;\n"
+ " \t\t\t}\n"
+ "-\t\t\tfor (i = 1; i <= data->block[0]; i++)\n"
+ "-\t\t\t\tmsgbuf0[i] = data->block[i];\n"
+ "+\t\t\tfor (i = 1; i <= entry->smbus.data->block[0]; i++)\n"
+ "+\t\t\t\tmsgbuf0[i] = entry->smbus.data->block[i];\n"
+ " \t\t}\n"
+ " \t\tbreak;\n"
+ " \tdefault:\n"
+ " \t\tdev_err(&adapter->dev, \"smbus_access called with invalid size (%d)\\n\",\n"
+ "-\t\t       size);\n"
+ "+\t\t       entry->smbus.size);\n"
+ " \t\treturn -1;\n"
+ " \t}\n"
+ " \n"
+ "+\tentry->xfer_type = I2C_OP_I2C;\n"
+ "+\tentry->i2c.msgs = msg;\n"
+ "+\tentry->i2c.num = num;\n"
+ "+\tentry->complete = i2c_smbus_emu_complete;\n"
+ " \treturn 0;\n"
+ " }\n"
+ " \n"
+ "@@ -1253,46 +1274,42 @@\n"
+ "                    char read_write, u8 command, int size, \n"
+ "                    union i2c_smbus_data * data)\n"
+ " {\n"
+ "+\tstruct i2c_op_q_entry *entry;\n"
+ " \ts32 res;\n"
+ "-\tint swpec = 0;\n"
+ "-\tu8 partial = 0;\n"
+ " \tstruct i2c_algorithm *algo = adapter->algo;\n"
+ " \n"
+ " \n"
+ "-\ti2c_smbus_format_entry(adapter, addr, &flags,\n"
+ "-\t\t\t       read_write, command,\n"
+ "-\t\t\t       &size, data, &swpec, &partial);\n"
+ "+\tentry = kmalloc(sizeof(*entry), GFP_KERNEL);\n"
+ "+\tif (!entry)\n"
+ "+\t    return -ENOMEM;\n"
+ "+\n"
+ "+\tentry->xfer_type = I2C_OP_SMBUS;\n"
+ "+\tentry->smbus.addr = addr;\n"
+ "+\tentry->smbus.flags = flags;\n"
+ "+\tentry->smbus.read_write = read_write;\n"
+ "+\tentry->smbus.command = command;\n"
+ "+\tentry->smbus.size = size;\n"
+ "+\tentry->smbus.data = data;\n"
+ "+\n"
+ "+\ti2c_smbus_format_entry(adapter, entry);\n"
+ " \n"
+ " \tif (algo->smbus_xfer) {\n"
+ " \t\tdown(&adapter->bus_lock);\n"
+ "-\t\tres = adapter->algo->smbus_xfer(adapter, addr, flags,\n"
+ "-\t\t\t\t\t\tread_write, command,\n"
+ "-\t\t\t\t\t\tsize, data);\n"
+ "+\t\tentry->result = adapter->algo->smbus_xfer\n"
+ "+\t\t  (adapter, entry->smbus.addr, entry->smbus.flags,\n"
+ "+\t\t   entry->smbus.read_write, entry->smbus.command,\n"
+ "+\t\t   entry->smbus.size, entry->smbus.data);\n"
+ " \t\tup(&adapter->bus_lock);\n"
+ "-\t\tres = i2c_smbus_complete_entry(adapter, addr, flags,\n"
+ "-\t\t\t\t\t       read_write, command,\n"
+ "-\t\t\t\t\t       size, data, swpec, partial,\n"
+ "-\t\t\t\t\t       res);\n"
+ "+\t\tif (entry->complete)\n"
+ "+\t\t    entry->complete(adapter, entry);\n"
+ " \t} else {\n"
+ "-\t\tunsigned char msgbuf0[34];\n"
+ "-\t\tunsigned char msgbuf1[34];\n"
+ "-\t\tstruct i2c_msg msg[2];\n"
+ "-\n"
+ "-\t\tmsg[0].buf = msgbuf0;\n"
+ "-\t\tmsg[1].buf = msgbuf1;\n"
+ "-\t\tif (i2c_smbus_emu_format(adapter, addr, flags,\n"
+ "-\t\t\t\t\t read_write, command,\n"
+ "-\t\t\t\t\t size, data, msg))\n"
+ "-\t\t\tres = -EINVAL;\n"
+ "-\t\telse {\n"
+ "-\t\t\tres = i2c_transfer(adapter, msg, 2);\n"
+ "-\t\t\tres = i2c_smbus_emu_complete(adapter, addr, flags,\n"
+ "-\t\t\t\t\t\t     read_write, command,\n"
+ "-\t\t\t\t\t\t     size, data, msg,\n"
+ "-\t\t\t\t\t\t     swpec, partial,\n"
+ "-\t\t\t\t\t\t     res);\n"
+ "-\t\t}\n"
+ "+\t\tif (i2c_smbus_emu_format(adapter, entry))\n"
+ "+\t\t\tentry->result = -EINVAL;\n"
+ "+\t\telse\n"
+ "+\t\t\ti2c_transfer_entry(adapter, entry);\n"
+ " \t}\n"
+ "+\tres = entry->result;\n"
+ "+\tkfree(entry);\n"
+ " \treturn res;\n"
+ " }\n"
+ " \n"
+ "Index: linux-2.6.11-mm1/include/linux/i2c.h\n"
+ "===================================================================\n"
+ "--- linux-2.6.11-mm1.orig/include/linux/i2c.h\n"
+ "+++ linux-2.6.11-mm1/include/linux/i2c.h\n"
+ "@@ -32,7 +32,10 @@\n"
+ " #include <linux/types.h>\n"
+ " #include <linux/i2c-id.h>\n"
+ " #include <linux/device.h>\t/* for struct device */\n"
+ "+#include <linux/completion.h>\n"
+ "+#include <linux/kref.h>\n"
+ " #include <asm/semaphore.h>\n"
+ "+#include <asm/atomic.h>\n"
+ " \n"
+ " /* --- General options ------------------------------------------------\t*/\n"
+ " \n"
+ "@@ -43,6 +46,7 @@\n"
+ " struct i2c_driver;\n"
+ " struct i2c_client_address_data;\n"
+ " union i2c_smbus_data;\n"
+ "+struct i2c_op_q_entry;\n"
+ " \n"
+ " /*\n"
+ "  * The master routines are the ones normally used to transmit data to devices\n"
+ "@@ -392,6 +396,92 @@\n"
+ "  \t__u8 *buf;\t\t/* pointer to msg data\t\t\t*/\n"
+ " };\n"
+ " \n"
+ "+/*\n"
+ "+ * Hold a queue of I2C operations to perform, and used to pass data\n"
+ "+ * around.\n"
+ "+ */\n"
+ "+typedef void (*i2c_op_done_cb)(struct i2c_op_q_entry *entry);\n"
+ "+\n"
+ "+#define I2C_OP_I2C\t0\n"
+ "+#define I2C_OP_SMBUS\t1\n"
+ "+struct i2c_op_q_entry {\n"
+ "+\t/* The result will be set to the result of the operation when\n"
+ "+\t   it completes. */\n"
+ "+\ts32 result;\n"
+ "+\n"
+ "+\t/**************************************************************/\n"
+ "+\t/* Public interface.  The user should set these up (and the\n"
+ "+\t   proper structure below). */\n"
+ "+\tint            xfer_type;\n"
+ "+\n"
+ "+\t/* Handler may be called from interrupt context, so be\n"
+ "+\t   careful. */\n"
+ "+\ti2c_op_done_cb handler;\n"
+ "+\tvoid           *handler_data;\n"
+ "+\n"
+ "+\t/* Note that this is not a union because an smbus operation\n"
+ "+\t   may be converted into an i2c operation (thus both\n"
+ "+\t   structures will be used).  The data in these may be changd\n"
+ "+\t   by the driver. */\n"
+ "+\tstruct {\n"
+ "+\t\tstruct i2c_msg *msgs;\n"
+ "+\t\tint num;\n"
+ "+\t} i2c;\n"
+ "+\tstruct {\n"
+ "+\t\t/* Addr and flags are filled in by the non-blocking\n"
+ "+\t\t   send routine that takes a client. */\n"
+ "+\t\tu16 addr;\n"
+ "+\t\tunsigned short flags;\n"
+ "+\n"
+ "+\t\tchar read_write;\n"
+ "+\t\tu8 command;\n"
+ "+\n"
+ "+\t\t/* Note that the size is *not* the length of the data.\n"
+ "+\t\t   It is the transaction type, like I2C_SMBUS_QUICK\n"
+ "+\t\t   and the ones after that below.  If this is a block\n"
+ "+\t\t   transaction, the length of the rest of the data is\n"
+ "+\t\t   in the first byte of the data, for both transmit\n"
+ "+\t\t   and receive. */\n"
+ "+\t\tint size;\n"
+ "+\t\tunion i2c_smbus_data *data;\n"
+ "+\t} smbus;\n"
+ "+\n"
+ "+\t/**************************************************************/\n"
+ "+\t/* For use by the bus interface.  The bus interface sets the\n"
+ "+\t   timeout in microseconds until the next poll operation.\n"
+ "+\t   This *must* be set in the start operation.  The time_left\n"
+ "+\t   and data can be used for anything the bus interface likes.\n"
+ "+\t   data will be set to NULL before being started so the bus\n"
+ "+\t   interface can use that to tell if it has been set up\n"
+ "+\t   yet. */\n"
+ "+\tunsigned int call_again_us;\n"
+ "+\tlong         time_left;\n"
+ "+\tvoid         *data;\n"
+ "+\n"
+ "+\t/**************************************************************/\n"
+ "+\t/* Internals */\n"
+ "+\tstruct list_head  link;\n"
+ "+\tstruct completion *start;\n"
+ "+\tatomic_t          completed;\n"
+ "+\tunsigned int      started : 1;\n"
+ "+\tunsigned int      use_timer : 1;\n"
+ "+\tu8                swpec;\n"
+ "+\tu8                partial;\n"
+ "+\tvoid (*complete)(struct i2c_adapter    *adap,\n"
+ "+\t\t\t struct i2c_op_q_entry *entry);\n"
+ "+\n"
+ "+\t/* It's wierd, but we use a usecount to track if an q entry is\n"
+ "+\t   in use and when it should be reported back to the user. */\n"
+ "+\tstruct kref usecount;\n"
+ "+\n"
+ "+\t/* These are here for SMBus emulation over I2C.  I don't like\n"
+ "+\t   them taking this much room in the data structure, but they\n"
+ "+\t   need to be available in this case. */\n"
+ "+\tunsigned char msgbuf0[34];\n"
+ "+\tunsigned char msgbuf1[34];\n"
+ "+\tstruct i2c_msg msg[2];\n"
+ "+};\n"
+ "+\n"
+ " /* To determine what functionality is present */\n"
+ " \n"
+ " #define I2C_FUNC_I2C\t\t\t0x00000001"
 
-f2a6630276df15f07bd3b937a8a0fb610ab7708fb96ac43905edbcc76ef7d38b
+0fb0b4f2b1d1a34b2a209149ad268b57bf3a9a2a0d51c56e5bc0df12f550b8f8

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.