diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-parport.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-parport.c | 61 | 
1 files changed, 31 insertions, 30 deletions
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 0eb1515541e..a27aae2d675 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -1,14 +1,14 @@  /* ------------------------------------------------------------------------ *   * i2c-parport.c I2C bus over parallel port                                 *   * ------------------------------------------------------------------------ * -   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> -    +   Copyright (C) 2003-2011 Jean Delvare <jdelvare@suse.de> +     Based on older i2c-philips-par.c driver     Copyright (C) 1995-2000 Simon G. Vogl     With some changes from:     Frodo Looijaard <frodol@dds.nl>     Kyösti Mälkki <kmalkki@cc.hut.fi> -    +     This program is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by     the Free Software Foundation; either version 2 of the License, or @@ -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 ----------------------------------- */ @@ -75,13 +78,13 @@ static unsigned char port_read_control(struct parport *p)  	return parport_read_control(p);  } -static void (*port_write[])(struct parport *, unsigned char) = { +static void (* const port_write[])(struct parport *, unsigned char) = {  	port_write_data,  	NULL,  	port_write_control,  }; -static unsigned char (*port_read[])(struct parport *) = { +static unsigned char (* const port_read[])(struct parport *) = {  	port_read_data,  	port_read_status,  	port_read_control, @@ -144,11 +147,11 @@ static const struct i2c_algo_bit_data parport_algo_data = {  	.getscl		= parport_getscl,  	.udelay		= 10, /* ~50 kbps */  	.timeout	= HZ, -};  +};  /* ----- I2c and parallel port call-back functions and structures --------- */ -void i2c_parport_irq(void *data) +static void i2c_parport_irq(void *data)  {  	struct i2c_par *adapter = data;  	struct i2c_client *ara = adapter->ara; @@ -161,10 +164,10 @@ void i2c_parport_irq(void *data)  			"SMBus alert received but no ARA client!\n");  } -static void i2c_parport_attach (struct parport *port) +static void i2c_parport_attach(struct parport *port)  {  	struct i2c_par *adapter; -	 +  	adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);  	if (adapter == NULL) {  		printk(KERN_ERR "i2c-parport: Failed to kzalloc\n"); @@ -177,7 +180,7 @@ static void i2c_parport_attach (struct parport *port)  		NULL, NULL, i2c_parport_irq, PARPORT_FLAG_EXCL, adapter);  	if (!adapter->pdev) {  		printk(KERN_ERR "i2c-parport: Unable to register with parport\n"); -		goto ERROR0; +		goto err_free;  	}  	/* Fill the rest of the structure */ @@ -197,7 +200,7 @@ static void i2c_parport_attach (struct parport *port)  	if (parport_claim_or_block(adapter->pdev) < 0) {  		printk(KERN_ERR "i2c-parport: Could not claim parallel port\n"); -		goto ERROR1; +		goto err_unregister;  	}  	/* Reset hardware to a sane state (SCL and SDA high) */ @@ -212,7 +215,7 @@ static void i2c_parport_attach (struct parport *port)  	if (i2c_bit_add_bus(&adapter->adapter) < 0) {  		printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); -		goto ERROR1; +		goto err_unregister;  	}  	/* Setup SMBus alert if supported */ @@ -228,24 +231,25 @@ static void i2c_parport_attach (struct parport *port)  	}  	/* Add the new adapter to the list */ -	adapter->next = adapter_list; -	adapter_list = adapter; -        return; +	mutex_lock(&adapter_list_lock); +	list_add_tail(&adapter->node, &adapter_list); +	mutex_unlock(&adapter_list_lock); +	return; -ERROR1: + err_unregister:  	parport_release(adapter->pdev);  	parport_unregister_device(adapter->pdev); -ERROR0: + err_free:  	kfree(adapter);  } -static void i2c_parport_detach (struct parport *port) +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); @@ -256,17 +260,14 @@ static void i2c_parport_detach (struct parport *port)  			/* Un-init if needed (power off...) */  			if (adapter_parm[type].init.val)  				line_set(port, 0, &adapter_parm[type].init); -				 +  			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 = { @@ -297,7 +298,7 @@ static void __exit i2c_parport_exit(void)  	parport_unregister_driver(&i2c_parport_driver);  } -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");  MODULE_DESCRIPTION("I2C bus over parallel port");  MODULE_LICENSE("GPL");  | 
