aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2011-05-01 12:18:49 -0400
committerJean Delvare <khali@endymion.delvare>2011-05-01 12:18:49 -0400
commit56acc7a39ac4ac7638cdc32cd3d0832ebbc834e4 (patch)
treec2f1b47a7ff678de38413b05016cb0ded3e8f714 /drivers/i2c
parenta6e5e2be44616c8400f9ec2f635b10f8e579217c (diff)
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
Diffstat (limited to 'drivers/i2c')
-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 @@
1/* ------------------------------------------------------------------------ * 1/* ------------------------------------------------------------------------ *
2 * i2c-parport.c I2C bus over parallel port * 2 * i2c-parport.c I2C bus over parallel port *
3 * ------------------------------------------------------------------------ * 3 * ------------------------------------------------------------------------ *
4 Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> 4 Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org>
5 5
6 Based on older i2c-philips-par.c driver 6 Based on older i2c-philips-par.c driver
7 Copyright (C) 1995-2000 Simon G. Vogl 7 Copyright (C) 1995-2000 Simon G. Vogl
@@ -33,6 +33,8 @@
33#include <linux/i2c-algo-bit.h> 33#include <linux/i2c-algo-bit.h>
34#include <linux/i2c-smbus.h> 34#include <linux/i2c-smbus.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/list.h>
37#include <linux/mutex.h>
36#include "i2c-parport.h" 38#include "i2c-parport.h"
37 39
38/* ----- Device list ------------------------------------------------------ */ 40/* ----- Device list ------------------------------------------------------ */
@@ -43,10 +45,11 @@ struct i2c_par {
43 struct i2c_algo_bit_data algo_data; 45 struct i2c_algo_bit_data algo_data;
44 struct i2c_smbus_alert_setup alert_data; 46 struct i2c_smbus_alert_setup alert_data;
45 struct i2c_client *ara; 47 struct i2c_client *ara;
46 struct i2c_par *next; 48 struct list_head node;
47}; 49};
48 50
49static struct i2c_par *adapter_list; 51static LIST_HEAD(adapter_list);
52static DEFINE_MUTEX(adapter_list_lock);
50 53
51/* ----- Low-level parallel port access ----------------------------------- */ 54/* ----- Low-level parallel port access ----------------------------------- */
52 55
@@ -228,8 +231,9 @@ static void i2c_parport_attach (struct parport *port)
228 } 231 }
229 232
230 /* Add the new adapter to the list */ 233 /* Add the new adapter to the list */
231 adapter->next = adapter_list; 234 mutex_lock(&adapter_list_lock);
232 adapter_list = adapter; 235 list_add_tail(&adapter->node, &adapter_list);
236 mutex_unlock(&adapter_list_lock);
233 return; 237 return;
234 238
235ERROR1: 239ERROR1:
@@ -241,11 +245,11 @@ ERROR0:
241 245
242static void i2c_parport_detach (struct parport *port) 246static void i2c_parport_detach (struct parport *port)
243{ 247{
244 struct i2c_par *adapter, *prev; 248 struct i2c_par *adapter, *_n;
245 249
246 /* Walk the list */ 250 /* Walk the list */
247 for (prev = NULL, adapter = adapter_list; adapter; 251 mutex_lock(&adapter_list_lock);
248 prev = adapter, adapter = adapter->next) { 252 list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
249 if (adapter->pdev->port == port) { 253 if (adapter->pdev->port == port) {
250 if (adapter->ara) { 254 if (adapter->ara) {
251 parport_disable_irq(port); 255 parport_disable_irq(port);
@@ -259,14 +263,11 @@ static void i2c_parport_detach (struct parport *port)
259 263
260 parport_release(adapter->pdev); 264 parport_release(adapter->pdev);
261 parport_unregister_device(adapter->pdev); 265 parport_unregister_device(adapter->pdev);
262 if (prev) 266 list_del(&adapter->node);
263 prev->next = adapter->next;
264 else
265 adapter_list = adapter->next;
266 kfree(adapter); 267 kfree(adapter);
267 return;
268 } 268 }
269 } 269 }
270 mutex_unlock(&adapter_list_lock);
270} 271}
271 272
272static struct parport_driver i2c_parport_driver = { 273static struct parport_driver i2c_parport_driver = {