All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <42261B8A.9070409@acm.org>

diff --git a/a/1.txt b/N1/1.txt
index 0673ec8..a2cc655 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,201 +1 @@
 See part 1 for details on what this does...
-
--------------- next part --------------
-This patch adds handling of the op q to the I2C main code
-in preparation for the non-blocking changes.
-
-Signed-off-by: Corey Minyard <minyard@acm.org>
-
-Index: linux-2.6.11-rc5-mm1/drivers/i2c/i2c-core.c
-=================================--- linux-2.6.11-rc5-mm1.orig/drivers/i2c/i2c-core.c
-+++ linux-2.6.11-rc5-mm1/drivers/i2c/i2c-core.c
-@@ -85,6 +85,8 @@
- 	complete(&adap->dev_released);
- }
- 
-+#define entry_completed(e) (atomic_read(&(e)->completed) <= 0)
-+
- static struct device_driver i2c_adapter_driver = {
- 	.name =	"i2c_adapter",
- 	.bus = &i2c_bus_type,
-@@ -165,6 +167,8 @@
- 	}
- 
- 	adap->nr =  id & MAX_ID_MASK;
-+	spin_lock_init(&adap->q_lock);
-+	INIT_LIST_HEAD(&adap->q);
- 	init_MUTEX(&adap->bus_lock);
- 	init_MUTEX(&adap->clist_lock);
- 	list_add_tail(&adap->list,&adapters);
-@@ -587,6 +591,7 @@
- {
- 	entry->xfer_type = I2C_OP_I2C;
- 	entry->complete = NULL;
-+	kref_init(&entry->usecount);
- 	if (adap->algo->master_xfer) {
-  	 	dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n",
- 			entry->i2c.num);
-@@ -1284,6 +1289,7 @@
- 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- 	if (!entry)
- 	    return -ENOMEM;
-+	kref_init(&entry->usecount);
- 
- 	entry->xfer_type = I2C_OP_SMBUS;
- 	entry->smbus.addr = addr;
-@@ -1335,6 +1341,91 @@
- 	return (func & adap_func) = func;
- }
- 
-+/* ----------------------------------------------------
-+ * Entry handling
-+ * ----------------------------------------------------
-+ */
-+
-+/* Get the first entry off the head of the queue and lock it there.
-+   The entry is guaranteed to remain first in the list and the handler
-+   not be called until i2c_entry_put() is called. */
-+static struct i2c_op_q_entry *_i2c_entry_get(struct i2c_adapter * adap)
-+{
-+	struct i2c_op_q_entry * entry = NULL;
-+
-+	if (!list_empty(&adap->q)) {
-+		struct list_head * link = adap->q.next;
-+		entry = list_entry(link, struct i2c_op_q_entry, link);
-+		if (entry_completed(entry))
-+			entry = NULL;
-+		else
-+			kref_get(&entry->usecount);
-+	}
-+	pr_debug("_i2c_entry_get %p %p\n", adap, entry);
-+	return entry;
-+}
-+
-+struct i2c_op_q_entry *i2c_entry_get(struct i2c_adapter * adap)
-+{
-+	unsigned long flags;
-+	struct i2c_op_q_entry * entry;
-+
-+	spin_lock_irqsave(&adap->q_lock, flags);
-+	entry = _i2c_entry_get(adap);
-+	spin_unlock_irqrestore(&adap->q_lock, flags);
-+	return entry;
-+}
-+
-+static void i2c_op_release(struct kref *ref)
-+{
-+	/* Nothing to do here, all handling is from the kref_put return
-+	   code. */
-+}
-+
-+void i2c_entry_put(struct i2c_adapter * adap,
-+		   struct i2c_op_q_entry * entry)
-+{
-+	unsigned long flags;
-+	struct i2c_op_q_entry * new_entry;
-+
-+ restart:
-+	pr_debug("i2c_put %p %p\n", adap, entry);
-+
-+	spin_lock_irqsave(&adap->q_lock, flags);
-+	if (kref_put(&entry->usecount, i2c_op_release)) {
-+		list_del(&entry->link);
-+
-+		/* Get the next entry to start. */
-+		new_entry = _i2c_entry_get(adap);
-+		spin_unlock_irqrestore(&adap->q_lock, flags);
-+
-+		entry->handler(entry);
-+
-+		if (new_entry) {
-+			/* start entry will go here. */
-+			if (new_entry->start)
-+				complete(new_entry->start);
-+			/* Do tail recursion ourself. */
-+			entry = new_entry;
-+			goto restart;
-+		}
-+	} else
-+		spin_unlock_irqrestore(&adap->q_lock, flags);
-+}
-+
-+void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *e)
-+{
-+	pr_debug("i2c_op_done: %p %p\n", adap, e);
-+	if (atomic_dec_and_test(&e->completed)) {
-+		/* We are the lucky winner!  We get to clean up the
-+		   entry. */
-+		if (e->complete)
-+			e->complete(adap, e);
-+	}
-+
-+	i2c_entry_put(adap, e);
-+}
-+
- EXPORT_SYMBOL(i2c_add_adapter);
- EXPORT_SYMBOL(i2c_del_adapter);
- EXPORT_SYMBOL(i2c_add_driver);
-@@ -1346,6 +1437,7 @@
- EXPORT_SYMBOL(i2c_clients_command);
- EXPORT_SYMBOL(i2c_check_addr);
- 
-+EXPORT_SYMBOL(i2c_op_done);
- EXPORT_SYMBOL(i2c_master_send);
- EXPORT_SYMBOL(i2c_master_recv);
- EXPORT_SYMBOL(i2c_control);
-Index: linux-2.6.11-rc5-mm1/include/linux/i2c.h
-=================================--- linux-2.6.11-rc5-mm1.orig/include/linux/i2c.h
-+++ linux-2.6.11-rc5-mm1/include/linux/i2c.h
-@@ -34,6 +34,8 @@
- #include <linux/device.h>	/* for struct device */
- #include <linux/completion.h>
- #include <linux/kref.h>
-+#include <linux/list.h>
-+#include <linux/spinlock.h>
- #include <asm/semaphore.h>
- #include <asm/atomic.h>
- 
-@@ -182,6 +184,33 @@
- }
- 
- /*
-+ * About locking and the non-blocking interface.
-+ *
-+ * The poll operations are called single-threaded (along with the
-+ * xxx_start operations), so if the driver is only polled then there
-+ * is no need to do any locking.  If you are using interrupts, then
-+ * the timer operations and interrupts can race and you need to lock
-+ * appropriately.
-+ * 
-+ * i2c_op_done() can be called multiple times on the same entry (as
-+ * long as each one has a get operation).  This handles poll and
-+ * interrupt races calling i2c_op_done().  It will do the right thing.
-+ */
-+
-+/* Called from an non-blocking interface to get the current working
-+   entry.  Returns NULL if there is none.  This is primarily for
-+   interrupt handlers to determine what they should be working on.
-+   Note that if you call i2c_entry_get() and get a non-null entry, you
-+   must call i2c_entry_put() on it. */
-+struct i2c_op_q_entry *i2c_entry_get(struct i2c_adapter * adap);
-+void i2c_entry_put(struct i2c_adapter * adap,
-+		   struct i2c_op_q_entry * entry);
-+
-+/* Called from an non-blocking interface to report that an operation
-+   has completed.  Can be called from interrupt context. */
-+void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *entry);
-+
-+/*
-  * The following structs are for those who like to implement new bus drivers:
-  * i2c_algorithm is the interface to a class of hardware solutions which can
-  * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
-@@ -229,6 +258,9 @@
- 	int (*client_unregister)(struct i2c_client *);
- 
- 	/* data fields that are valid for all devices	*/
-+	struct list_head q;
-+	spinlock_t q_lock;
-+
- 	struct semaphore bus_lock;
- 
- 	int timeout;
diff --git a/N1/2.hdr b/N1/2.hdr
new file mode 100644
index 0000000..3468fa9
--- /dev/null
+++ b/N1/2.hdr
@@ -0,0 +1,5 @@
+Content-Type: text/plain;
+ name="i2c_opq_handling.diff"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline;
+ filename="i2c_opq_handling.diff"
diff --git a/N1/2.txt b/N1/2.txt
new file mode 100644
index 0000000..e0190f4
--- /dev/null
+++ b/N1/2.txt
@@ -0,0 +1,200 @@
+This patch adds handling of the op q to the I2C main code
+in preparation for the non-blocking changes.
+
+Signed-off-by: Corey Minyard <minyard@acm.org>
+
+Index: linux-2.6.11-rc5-mm1/drivers/i2c/i2c-core.c
+===================================================================
+--- linux-2.6.11-rc5-mm1.orig/drivers/i2c/i2c-core.c
++++ linux-2.6.11-rc5-mm1/drivers/i2c/i2c-core.c
+@@ -85,6 +85,8 @@
+ 	complete(&adap->dev_released);
+ }
+ 
++#define entry_completed(e) (atomic_read(&(e)->completed) <= 0)
++
+ static struct device_driver i2c_adapter_driver = {
+ 	.name =	"i2c_adapter",
+ 	.bus = &i2c_bus_type,
+@@ -165,6 +167,8 @@
+ 	}
+ 
+ 	adap->nr =  id & MAX_ID_MASK;
++	spin_lock_init(&adap->q_lock);
++	INIT_LIST_HEAD(&adap->q);
+ 	init_MUTEX(&adap->bus_lock);
+ 	init_MUTEX(&adap->clist_lock);
+ 	list_add_tail(&adap->list,&adapters);
+@@ -587,6 +591,7 @@
+ {
+ 	entry->xfer_type = I2C_OP_I2C;
+ 	entry->complete = NULL;
++	kref_init(&entry->usecount);
+ 	if (adap->algo->master_xfer) {
+  	 	dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n",
+ 			entry->i2c.num);
+@@ -1284,6 +1289,7 @@
+ 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ 	if (!entry)
+ 	    return -ENOMEM;
++	kref_init(&entry->usecount);
+ 
+ 	entry->xfer_type = I2C_OP_SMBUS;
+ 	entry->smbus.addr = addr;
+@@ -1335,6 +1341,91 @@
+ 	return (func & adap_func) == func;
+ }
+ 
++/* ----------------------------------------------------
++ * Entry handling
++ * ----------------------------------------------------
++ */
++
++/* Get the first entry off the head of the queue and lock it there.
++   The entry is guaranteed to remain first in the list and the handler
++   not be called until i2c_entry_put() is called. */
++static struct i2c_op_q_entry *_i2c_entry_get(struct i2c_adapter * adap)
++{
++	struct i2c_op_q_entry * entry = NULL;
++
++	if (!list_empty(&adap->q)) {
++		struct list_head * link = adap->q.next;
++		entry = list_entry(link, struct i2c_op_q_entry, link);
++		if (entry_completed(entry))
++			entry = NULL;
++		else
++			kref_get(&entry->usecount);
++	}
++	pr_debug("_i2c_entry_get %p %p\n", adap, entry);
++	return entry;
++}
++
++struct i2c_op_q_entry *i2c_entry_get(struct i2c_adapter * adap)
++{
++	unsigned long flags;
++	struct i2c_op_q_entry * entry;
++
++	spin_lock_irqsave(&adap->q_lock, flags);
++	entry = _i2c_entry_get(adap);
++	spin_unlock_irqrestore(&adap->q_lock, flags);
++	return entry;
++}
++
++static void i2c_op_release(struct kref *ref)
++{
++	/* Nothing to do here, all handling is from the kref_put return
++	   code. */
++}
++
++void i2c_entry_put(struct i2c_adapter * adap,
++		   struct i2c_op_q_entry * entry)
++{
++	unsigned long flags;
++	struct i2c_op_q_entry * new_entry;
++
++ restart:
++	pr_debug("i2c_put %p %p\n", adap, entry);
++
++	spin_lock_irqsave(&adap->q_lock, flags);
++	if (kref_put(&entry->usecount, i2c_op_release)) {
++		list_del(&entry->link);
++
++		/* Get the next entry to start. */
++		new_entry = _i2c_entry_get(adap);
++		spin_unlock_irqrestore(&adap->q_lock, flags);
++
++		entry->handler(entry);
++
++		if (new_entry) {
++			/* start entry will go here. */
++			if (new_entry->start)
++				complete(new_entry->start);
++			/* Do tail recursion ourself. */
++			entry = new_entry;
++			goto restart;
++		}
++	} else
++		spin_unlock_irqrestore(&adap->q_lock, flags);
++}
++
++void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *e)
++{
++	pr_debug("i2c_op_done: %p %p\n", adap, e);
++	if (atomic_dec_and_test(&e->completed)) {
++		/* We are the lucky winner!  We get to clean up the
++		   entry. */
++		if (e->complete)
++			e->complete(adap, e);
++	}
++
++	i2c_entry_put(adap, e);
++}
++
+ EXPORT_SYMBOL(i2c_add_adapter);
+ EXPORT_SYMBOL(i2c_del_adapter);
+ EXPORT_SYMBOL(i2c_add_driver);
+@@ -1346,6 +1437,7 @@
+ EXPORT_SYMBOL(i2c_clients_command);
+ EXPORT_SYMBOL(i2c_check_addr);
+ 
++EXPORT_SYMBOL(i2c_op_done);
+ EXPORT_SYMBOL(i2c_master_send);
+ EXPORT_SYMBOL(i2c_master_recv);
+ EXPORT_SYMBOL(i2c_control);
+Index: linux-2.6.11-rc5-mm1/include/linux/i2c.h
+===================================================================
+--- linux-2.6.11-rc5-mm1.orig/include/linux/i2c.h
++++ linux-2.6.11-rc5-mm1/include/linux/i2c.h
+@@ -34,6 +34,8 @@
+ #include <linux/device.h>	/* for struct device */
+ #include <linux/completion.h>
+ #include <linux/kref.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
+ #include <asm/semaphore.h>
+ #include <asm/atomic.h>
+ 
+@@ -182,6 +184,33 @@
+ }
+ 
+ /*
++ * About locking and the non-blocking interface.
++ *
++ * The poll operations are called single-threaded (along with the
++ * xxx_start operations), so if the driver is only polled then there
++ * is no need to do any locking.  If you are using interrupts, then
++ * the timer operations and interrupts can race and you need to lock
++ * appropriately.
++ * 
++ * i2c_op_done() can be called multiple times on the same entry (as
++ * long as each one has a get operation).  This handles poll and
++ * interrupt races calling i2c_op_done().  It will do the right thing.
++ */
++
++/* Called from an non-blocking interface to get the current working
++   entry.  Returns NULL if there is none.  This is primarily for
++   interrupt handlers to determine what they should be working on.
++   Note that if you call i2c_entry_get() and get a non-null entry, you
++   must call i2c_entry_put() on it. */
++struct i2c_op_q_entry *i2c_entry_get(struct i2c_adapter * adap);
++void i2c_entry_put(struct i2c_adapter * adap,
++		   struct i2c_op_q_entry * entry);
++
++/* Called from an non-blocking interface to report that an operation
++   has completed.  Can be called from interrupt context. */
++void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *entry);
++
++/*
+  * The following structs are for those who like to implement new bus drivers:
+  * i2c_algorithm is the interface to a class of hardware solutions which can
+  * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
+@@ -229,6 +258,9 @@
+ 	int (*client_unregister)(struct i2c_client *);
+ 
+ 	/* data fields that are valid for all devices	*/
++	struct list_head q;
++	spinlock_t q_lock;
++
+ 	struct semaphore bus_lock;
+ 
+ 	int timeout;
diff --git a/a/content_digest b/N1/content_digest
index a8f0b55..d7d331d 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,22 +1,23 @@
- "ref\042261AFB.40001@acm.org\0"
- "From\0minyard@acm.org (Corey Minyard)\0"
+ "From\0Corey Minyard <minyard@acm.org>\0"
  "Subject\0[PATCH] Add a non-blocking interface to the I2C code, part3\0"
- "Date\0Thu, 19 May 2005 06:25:40 +0000\0"
+ "Date\0Wed, 02 Mar 2005 14:01:14 -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"
+ See part 1 for details on what this does...
+ "\01:2\0"
+ "fn\0i2c_opq_handling.diff\0"
  "b\0"
- "See part 1 for details on what this does...\n"
- "\n"
- "-------------- next part --------------\n"
  "This patch adds handling of the op q to the I2C main code\n"
  "in preparation for the non-blocking changes.\n"
  "\n"
  "Signed-off-by: Corey Minyard <minyard@acm.org>\n"
  "\n"
  "Index: linux-2.6.11-rc5-mm1/drivers/i2c/i2c-core.c\n"
- "=================================--- linux-2.6.11-rc5-mm1.orig/drivers/i2c/i2c-core.c\n"
+ "===================================================================\n"
+ "--- linux-2.6.11-rc5-mm1.orig/drivers/i2c/i2c-core.c\n"
  "+++ linux-2.6.11-rc5-mm1/drivers/i2c/i2c-core.c\n"
  "@@ -85,6 +85,8 @@\n"
  " \tcomplete(&adap->dev_released);\n"
@@ -53,7 +54,7 @@
  " \tentry->xfer_type = I2C_OP_SMBUS;\n"
  " \tentry->smbus.addr = addr;\n"
  "@@ -1335,6 +1341,91 @@\n"
- " \treturn (func & adap_func) = func;\n"
+ " \treturn (func & adap_func) == func;\n"
  " }\n"
  " \n"
  "+/* ----------------------------------------------------\n"
@@ -153,7 +154,8 @@
  " EXPORT_SYMBOL(i2c_master_recv);\n"
  " EXPORT_SYMBOL(i2c_control);\n"
  "Index: linux-2.6.11-rc5-mm1/include/linux/i2c.h\n"
- "=================================--- linux-2.6.11-rc5-mm1.orig/include/linux/i2c.h\n"
+ "===================================================================\n"
+ "--- linux-2.6.11-rc5-mm1.orig/include/linux/i2c.h\n"
  "+++ linux-2.6.11-rc5-mm1/include/linux/i2c.h\n"
  "@@ -34,6 +34,8 @@\n"
  " #include <linux/device.h>\t/* for struct device */\n"
@@ -209,4 +211,4 @@
  " \n"
  " \tint timeout;"
 
-21144afd872d5be8005dee5b7df5b773efb4dcf9fede0aee6b7b2932e4f6c32a
+8ebf6ffa606e1267aaed21279a2051dc10cee1af0ccab7a9022ab55a9773663f

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.