summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2011-05-01 20:18:49 +0400
committerJean Delvare <khali@endymion.delvare>2011-05-01 20:18:49 +0400
commit56acc7a39ac4ac7638cdc32cd3d0832ebbc834e4 (patch)
treec2f1b47a7ff678de38413b05016cb0ded3e8f714
parenta6e5e2be44616c8400f9ec2f635b10f8e579217c (diff)
downloadlinux-56acc7a39ac4ac7638cdc32cd3d0832ebbc834e4.tar.xz
i2c-parport: Fix adapter list handling
Use a standard list with proper locking to handle the list of adapters. Thankfully it only matters on systems with more than one parallel port, which are very rare. Thanks to Lukasz Kapiec for reporting the problem to me. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: stable@kernel.org
-rw-r--r--drivers/i2c/busses/i2c-parport.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 0eb1515541e7..2dbba163b102 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------ *
* i2c-parport.c I2C bus over parallel port *
* ------------------------------------------------------------------------ *
- Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
+ Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org>
Based on older i2c-philips-par.c driver
Copyright (C) 1995-2000 Simon G. Vogl
@@ -33,6 +33,8 @@
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-smbus.h>
#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
#include "i2c-parport.h"
/* ----- Device list ------------------------------------------------------ */
@@ -43,10 +45,11 @@ struct i2c_par {
struct i2c_algo_bit_data algo_data;
struct i2c_smbus_alert_setup alert_data;
struct i2c_client *ara;
- struct i2c_par *next;
+ struct list_head node;
};
-static struct i2c_par *adapter_list;
+static LIST_HEAD(adapter_list);
+static DEFINE_MUTEX(adapter_list_lock);
/* ----- Low-level parallel port access ----------------------------------- */
@@ -228,8 +231,9 @@ static void i2c_parport_attach (struct parport *port)
}
/* Add the new adapter to the list */
- adapter->next = adapter_list;
- adapter_list = adapter;
+ mutex_lock(&adapter_list_lock);
+ list_add_tail(&adapter->node, &adapter_list);
+ mutex_unlock(&adapter_list_lock);
return;
ERROR1:
@@ -241,11 +245,11 @@ ERROR0:
static void i2c_parport_detach (struct parport *port)
{
- struct i2c_par *adapter, *prev;
+ struct i2c_par *adapter, *_n;
/* Walk the list */
- for (prev = NULL, adapter = adapter_list; adapter;
- prev = adapter, adapter = adapter->next) {
+ mutex_lock(&adapter_list_lock);
+ list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
if (adapter->pdev->port == port) {
if (adapter->ara) {
parport_disable_irq(port);
@@ -259,14 +263,11 @@ static void i2c_parport_detach (struct parport *port)
parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
- if (prev)
- prev->next = adapter->next;
- else
- adapter_list = adapter->next;
+ list_del(&adapter->node);
kfree(adapter);
- return;
}
}
+ mutex_unlock(&adapter_list_lock);
}
static struct parport_driver i2c_parport_driver = {