Commit 22f0b1c0 authored by Gerd Knorr's avatar Gerd Knorr Committed by Greg Kroah-Hartman

[PATCH] i2c #1/3: listify i2c core

This is the first of tree patches for i2c.  Trying to get the i2c
cleanups finshed before 2.6.x, so we (hopefully) don't have a
ever-changing i2c subsystem in 2.7.x again (which is very annonying for
driver maintainance).

Changes:

 * listify i2c-core, i.e. make it use <linux/list.h> instead of
   statically-sized arrays, removed lots of ugly code :)
 * added i2c_(get|put)_adapter, changed i2c-dev.c to use these
   functions instead maintaining is own adapter list.
 * killed the I2C_DF_DUMMY flag which had the strange semantics to
   make the i2c subsystem call driver->attach_adapter on detaches.
   Added a detach_adapter() callback instead.
 * some other minor cleanups along the way ...
parent 6230bb01
This diff is collapsed.
......@@ -58,6 +58,7 @@ static int i2cdev_open (struct inode *inode, struct file *file);
static int i2cdev_release (struct inode *inode, struct file *file);
static int i2cdev_attach_adapter(struct i2c_adapter *adap);
static int i2cdev_detach_adapter(struct i2c_adapter *adap);
static int i2cdev_detach_client(struct i2c_client *client);
static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
void *arg);
......@@ -72,15 +73,13 @@ static struct file_operations i2cdev_fops = {
.release = i2cdev_release,
};
#define I2CDEV_ADAPS_MAX I2C_ADAP_MAX
static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];
static struct i2c_driver i2cdev_driver = {
.owner = THIS_MODULE,
.name = "dev driver",
.id = I2C_DRIVERID_I2CDEV,
.flags = I2C_DF_DUMMY,
.flags = I2C_DF_NOTIFY,
.attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter,
.detach_client = i2cdev_detach_client,
.command = i2cdev_command,
};
......@@ -340,35 +339,31 @@ static int i2cdev_open(struct inode *inode, struct file *file)
{
unsigned int minor = minor(inode->i_rdev);
struct i2c_client *client;
struct i2c_adapter *adap;
if ((minor >= I2CDEV_ADAPS_MAX) || !(i2cdev_adaps[minor]))
adap = i2c_get_adapter(minor);
if (NULL == adap)
return -ENODEV;
client = kmalloc(sizeof(*client), GFP_KERNEL);
if (!client)
if (!client) {
i2c_put_adapter(adap);
return -ENOMEM;
}
memcpy(client, &i2cdev_client_template, sizeof(*client));
/* registered with adapter, passed as client to user */
client->adapter = i2cdev_adaps[minor];
client->adapter = adap;
file->private_data = client;
/* use adapter module, i2c-dev handled with fops */
if (!try_module_get(client->adapter->owner))
goto out_kfree;
return 0;
out_kfree:
kfree(client);
return -ENODEV;
}
static int i2cdev_release(struct inode *inode, struct file *file)
{
struct i2c_client *client = file->private_data;
module_put(client->adapter->owner);
i2c_put_adapter(client->adapter);
kfree(client);
file->private_data = NULL;
......@@ -377,33 +372,28 @@ static int i2cdev_release(struct inode *inode, struct file *file)
int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
int i;
char name[12];
int i;
if ((i = i2c_adapter_id(adap)) < 0) {
dev_dbg(&adap->dev, "Unknown adapter ?!?\n");
return -ENODEV;
}
if (i >= I2CDEV_ADAPS_MAX) {
dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i);
return -ENODEV;
}
i = i2c_adapter_id(adap);
sprintf (name, "i2c/%d", i);
if (! i2cdev_adaps[i]) {
i2cdev_adaps[i] = adap;
devfs_register (NULL, name,
devfs_register (NULL, name,
DEVFS_FL_DEFAULT, I2C_MAJOR, i,
S_IFCHR | S_IRUSR | S_IWUSR,
&i2cdev_fops, NULL);
dev_dbg(&adap->dev, "Registered as minor %d\n", i);
} else {
/* This is actually a detach_adapter call! */
devfs_remove("i2c/%d", i);
i2cdev_adaps[i] = NULL;
dev_dbg(&adap->dev, "Adapter unregistered\n");
}
dev_dbg(&adap->dev, "Registered as minor %d\n", i);
return 0;
}
int i2cdev_detach_adapter(struct i2c_adapter *adap)
{
int i;
i = i2c_adapter_id(adap);
devfs_remove("i2c/%d", i);
dev_dbg(&adap->dev, "Adapter unregistered\n");
return 0;
}
......
......@@ -96,7 +96,8 @@ struct dpc
static int dpc_probe(struct saa7146_dev* dev)
{
struct dpc* dpc = 0;
int i = 0;
struct i2c_client *client;
struct list_head *item;
dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL);
if( NULL == dpc ) {
......@@ -117,12 +118,10 @@ static int dpc_probe(struct saa7146_dev* dev)
}
/* loop through all i2c-devices on the bus and look who is there */
for(i = 0; i < I2C_CLIENT_MAX; i++) {
if( NULL == dpc->i2c_adapter.clients[i] ) {
continue;
}
if( I2C_SAA7111A == dpc->i2c_adapter.clients[i]->addr )
dpc->saa7111a = dpc->i2c_adapter.clients[i];
list_for_each(item,&dpc->i2c_adapter.clients) {
client = list_entry(item, struct i2c_client, list);
if( I2C_SAA7111A == client->addr )
dpc->saa7111a = client;
}
/* check if all devices are present */
......
......@@ -208,7 +208,8 @@ static int mxb_vbi_bypass(struct saa7146_dev* dev)
static int mxb_probe(struct saa7146_dev* dev)
{
struct mxb* mxb = 0;
int i = 0;
struct i2c_client *client;
struct list_head *item;
request_module("tuner");
request_module("tea6420");
......@@ -235,22 +236,20 @@ static int mxb_probe(struct saa7146_dev* dev)
}
/* loop through all i2c-devices on the bus and look who is there */
for(i = 0; i < I2C_CLIENT_MAX; i++) {
if( NULL == mxb->i2c_adapter.clients[i] ) {
continue;
}
if( I2C_TEA6420_1 == mxb->i2c_adapter.clients[i]->addr )
mxb->tea6420_1 = mxb->i2c_adapter.clients[i];
if( I2C_TEA6420_2 == mxb->i2c_adapter.clients[i]->addr )
mxb->tea6420_2 = mxb->i2c_adapter.clients[i];
if( I2C_TEA6415C_2 == mxb->i2c_adapter.clients[i]->addr )
mxb->tea6415c = mxb->i2c_adapter.clients[i];
if( I2C_TDA9840 == mxb->i2c_adapter.clients[i]->addr )
mxb->tda9840 = mxb->i2c_adapter.clients[i];
if( I2C_SAA7111A == mxb->i2c_adapter.clients[i]->addr )
mxb->saa7111a = mxb->i2c_adapter.clients[i];
if( 0x60 == mxb->i2c_adapter.clients[i]->addr )
mxb->tuner = mxb->i2c_adapter.clients[i];
list_for_each(item,&mxb->i2c_adapter.clients) {
client = list_entry(item, struct i2c_client, list);
if( I2C_TEA6420_1 == client->addr )
mxb->tea6420_1 = client;
if( I2C_TEA6420_2 == client->addr )
mxb->tea6420_2 = client;
if( I2C_TEA6415C_2 == client->addr )
mxb->tea6415c = client;
if( I2C_TDA9840 == client->addr )
mxb->tda9840 = client;
if( I2C_SAA7111A == client->addr )
mxb->saa7111a = client;
if( 0x60 == client->addr )
mxb->tuner = client;
}
/* check if all devices are present */
......
......@@ -217,8 +217,9 @@ static struct i2c_driver driver = {
.owner = THIS_MODULE,
.name = "tv card mixer driver",
.id = I2C_DRIVERID_TVMIXER,
.flags = I2C_DF_DUMMY,
.flags = I2C_DF_NOTIFY,
.attach_adapter = tvmixer_adapters,
.detach_adapter = tvmixer_adapters,
.detach_client = tvmixer_clients,
};
......@@ -234,14 +235,15 @@ static struct file_operations tvmixer_fops = {
static int tvmixer_adapters(struct i2c_adapter *adap)
{
int i;
struct list_head *item;
struct i2c_client *client;
if (debug)
printk("tvmixer: adapter %s\n",adap->dev.name);
for (i=0; i<I2C_CLIENT_MAX; i++) {
if (!adap->clients[i])
continue;
tvmixer_clients(adap->clients[i]);
list_for_each(item,&adap->clients) {
client = list_entry(item, struct i2c_client, list);
tvmixer_clients(client);
}
return 0;
}
......@@ -264,7 +266,8 @@ static int tvmixer_clients(struct i2c_client *client)
client->adapter->dev.name);
return -1;
}
printk("tvmixer: debug: %s\n",client->dev.name);
if (debug)
printk("tvmixer: debug: %s\n",client->dev.name);
/* unregister ?? */
for (i = 0; i < DEV_MAX; i++) {
......
......@@ -39,12 +39,6 @@
/* --- General options ------------------------------------------------ */
#define I2C_ALGO_MAX 4 /* control memory consumption */
#define I2C_ADAP_MAX 16
#define I2C_DRIVER_MAX 16
#define I2C_CLIENT_MAX 32
#define I2C_DUMMY_MAX 4
struct i2c_msg;
struct i2c_algorithm;
struct i2c_adapter;
......@@ -131,6 +125,7 @@ struct i2c_driver {
* i2c_attach_client.
*/
int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);
/* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private data. Also, if the client struct
......@@ -145,6 +140,7 @@ struct i2c_driver {
int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
struct device_driver driver;
struct list_head list;
};
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
......@@ -169,6 +165,7 @@ struct i2c_client {
int usage_count; /* How many accesses currently */
/* to the client */
struct device dev; /* the device structure */
struct list_head list;
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
......@@ -236,12 +233,10 @@ struct i2c_adapter {
int (*client_unregister)(struct i2c_client *);
/* data fields that are valid for all devices */
struct semaphore bus;
struct semaphore list;
struct semaphore bus_lock;
struct semaphore clist_lock;
unsigned int flags;/* flags specifying div. data */
struct i2c_client *clients[I2C_CLIENT_MAX];
int timeout;
int retries;
struct device dev; /* the adapter device */
......@@ -250,6 +245,10 @@ struct i2c_adapter {
/* No need to set this when you initialize the adapter */
int inode;
#endif /* def CONFIG_PROC_FS */
int nr;
struct list_head clients;
struct list_head list;
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
......@@ -265,7 +264,11 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
/*flags for the driver struct: */
#define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */
#define I2C_DF_DUMMY 0x02 /* do not connect any clients */
#if 0
/* this flag is gone -- there is a (optional) driver->detach_adapter
* callback now which can be used instead */
# define I2C_DF_DUMMY 0x02
#endif
/*flags for the client struct: */
#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */
......@@ -352,7 +355,8 @@ extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
* or -1 if the adapter was not registered.
*/
extern int i2c_adapter_id(struct i2c_adapter *adap);
extern struct i2c_adapter* i2c_get_adapter(int id);
extern void i2c_put_adapter(struct i2c_adapter *adap);
/* Return the functionality mask */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment