Commit 29bb1bdb authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  hwmon: (lm75) Drop legacy i2c driver
  i2c: correct some size_t printk formats
  i2c: Check for address business before creating clients
  i2c: Let users select algorithm drivers manually again
  i2c: Fix NULL pointer dereference in i2c_new_probed_device
  i2c: Fix oops on bus multiplexer driver loading
parents 3f1ae223 8ff69eeb
...@@ -54,11 +54,11 @@ enum lm75_type { /* keep sorted in alphabetical order */ ...@@ -54,11 +54,11 @@ enum lm75_type { /* keep sorted in alphabetical order */
tmp75, tmp75,
}; };
/* Addresses scanned by legacy style driver binding */ /* Addresses scanned */
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
/* Insmod parameters (only for legacy style driver binding) */ /* Insmod parameters */
I2C_CLIENT_INSMOD_1(lm75); I2C_CLIENT_INSMOD_1(lm75);
...@@ -72,7 +72,6 @@ static const u8 LM75_REG_TEMP[3] = { ...@@ -72,7 +72,6 @@ static const u8 LM75_REG_TEMP[3] = {
/* Each client has this additional data */ /* Each client has this additional data */
struct lm75_data { struct lm75_data {
struct i2c_client *client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct mutex update_lock; struct mutex update_lock;
u8 orig_conf; u8 orig_conf;
...@@ -138,7 +137,7 @@ static const struct attribute_group lm75_group = { ...@@ -138,7 +137,7 @@ static const struct attribute_group lm75_group = {
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* "New style" I2C driver binding -- following the driver model */ /* device probe and removal */
static int static int
lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
...@@ -157,8 +156,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -157,8 +156,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
data->client = client;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Set to LM75 resolution (9 bits, 1/2 degree C) and range. /* Set to LM75 resolution (9 bits, 1/2 degree C) and range.
...@@ -236,45 +233,16 @@ static const struct i2c_device_id lm75_ids[] = { ...@@ -236,45 +233,16 @@ static const struct i2c_device_id lm75_ids[] = {
}; };
MODULE_DEVICE_TABLE(i2c, lm75_ids); MODULE_DEVICE_TABLE(i2c, lm75_ids);
static struct i2c_driver lm75_driver = { /* Return 0 if detection is successful, -ENODEV otherwise */
.driver = { static int lm75_detect(struct i2c_client *new_client, int kind,
.name = "lm75", struct i2c_board_info *info)
},
.probe = lm75_probe,
.remove = lm75_remove,
.id_table = lm75_ids,
};
/*-----------------------------------------------------------------------*/
/* "Legacy" I2C driver binding */
static struct i2c_driver lm75_legacy_driver;
/* This function is called by i2c_probe */
static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
struct i2c_adapter *adapter = new_client->adapter;
int i; int i;
struct i2c_client *new_client;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
goto exit; return -ENODEV;
/* OK. For now, we presume we have a valid address. We create the
client structure, even though there may be no sensor present.
But it allows us to use i2c_smbus_read_*_data() calls. */
new_client = kzalloc(sizeof *new_client, GFP_KERNEL);
if (!new_client) {
err = -ENOMEM;
goto exit;
}
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm75_legacy_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. There is no identification- /* Now, we do the remaining detection. There is no identification-
dedicated register so we have to rely on several tricks: dedicated register so we have to rely on several tricks:
...@@ -294,71 +262,44 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -294,71 +262,44 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
|| i2c_smbus_read_word_data(new_client, 5) != hyst || i2c_smbus_read_word_data(new_client, 5) != hyst
|| i2c_smbus_read_word_data(new_client, 6) != hyst || i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst) || i2c_smbus_read_word_data(new_client, 7) != hyst)
goto exit_free; return -ENODEV;
os = i2c_smbus_read_word_data(new_client, 3); os = i2c_smbus_read_word_data(new_client, 3);
if (i2c_smbus_read_word_data(new_client, 4) != os if (i2c_smbus_read_word_data(new_client, 4) != os
|| i2c_smbus_read_word_data(new_client, 5) != os || i2c_smbus_read_word_data(new_client, 5) != os
|| i2c_smbus_read_word_data(new_client, 6) != os || i2c_smbus_read_word_data(new_client, 6) != os
|| i2c_smbus_read_word_data(new_client, 7) != os) || i2c_smbus_read_word_data(new_client, 7) != os)
goto exit_free; return -ENODEV;
/* Unused bits */ /* Unused bits */
if (conf & 0xe0) if (conf & 0xe0)
goto exit_free; return -ENODEV;
/* Addresses cycling */ /* Addresses cycling */
for (i = 8; i < 0xff; i += 8) for (i = 8; i < 0xff; i += 8)
if (i2c_smbus_read_byte_data(new_client, i + 1) != conf if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
|| i2c_smbus_read_word_data(new_client, i + 2) != hyst || i2c_smbus_read_word_data(new_client, i + 2) != hyst
|| i2c_smbus_read_word_data(new_client, i + 3) != os) || i2c_smbus_read_word_data(new_client, i + 3) != os)
goto exit_free; return -ENODEV;
} }
/* NOTE: we treat "force=..." and "force_lm75=..." the same. /* NOTE: we treat "force=..." and "force_lm75=..." the same.
* Only new-style driver binding distinguishes chip types. * Only new-style driver binding distinguishes chip types.
*/ */
strlcpy(new_client->name, "lm75", I2C_NAME_SIZE); strlcpy(info->type, "lm75", I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */
err = i2c_attach_client(new_client);
if (err)
goto exit_free;
err = lm75_probe(new_client, NULL);
if (err < 0)
goto exit_detach;
return 0; return 0;
exit_detach:
i2c_detach_client(new_client);
exit_free:
kfree(new_client);
exit:
return err;
}
static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_probe(adapter, &addr_data, lm75_detect);
} }
static int lm75_detach_client(struct i2c_client *client) static struct i2c_driver lm75_driver = {
{ .class = I2C_CLASS_HWMON,
lm75_remove(client);
i2c_detach_client(client);
kfree(client);
return 0;
}
static struct i2c_driver lm75_legacy_driver = {
.driver = { .driver = {
.name = "lm75_legacy", .name = "lm75",
}, },
.attach_adapter = lm75_attach_adapter, .probe = lm75_probe,
.detach_client = lm75_detach_client, .remove = lm75_remove,
.id_table = lm75_ids,
.detect = lm75_detect,
.address_data = &addr_data,
}; };
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
...@@ -424,22 +365,11 @@ static struct lm75_data *lm75_update_device(struct device *dev) ...@@ -424,22 +365,11 @@ static struct lm75_data *lm75_update_device(struct device *dev)
static int __init sensors_lm75_init(void) static int __init sensors_lm75_init(void)
{ {
int status; return i2c_add_driver(&lm75_driver);
status = i2c_add_driver(&lm75_driver);
if (status < 0)
return status;
status = i2c_add_driver(&lm75_legacy_driver);
if (status < 0)
i2c_del_driver(&lm75_driver);
return status;
} }
static void __exit sensors_lm75_exit(void) static void __exit sensors_lm75_exit(void)
{ {
i2c_del_driver(&lm75_legacy_driver);
i2c_del_driver(&lm75_driver); i2c_del_driver(&lm75_driver);
} }
......
...@@ -38,6 +38,20 @@ config I2C_CHARDEV ...@@ -38,6 +38,20 @@ config I2C_CHARDEV
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-dev. will be called i2c-dev.
config I2C_HELPER_AUTO
bool "Autoselect pertinent helper modules"
default y
help
Some I2C bus drivers require so-called "I2C algorithm" modules
to work. These are basically software-only abstractions of generic
I2C interfaces. This option will autoselect them so that you don't
have to care.
Unselect this only if you need to enable additional helper
modules, for example for use with external I2C bus drivers.
In doubt, say Y.
source drivers/i2c/algos/Kconfig source drivers/i2c/algos/Kconfig
source drivers/i2c/busses/Kconfig source drivers/i2c/busses/Kconfig
source drivers/i2c/chips/Kconfig source drivers/i2c/chips/Kconfig
......
...@@ -2,15 +2,20 @@ ...@@ -2,15 +2,20 @@
# I2C algorithm drivers configuration # I2C algorithm drivers configuration
# #
menu "I2C Algorithms"
depends on !I2C_HELPER_AUTO
config I2C_ALGOBIT config I2C_ALGOBIT
tristate tristate "I2C bit-banging interfaces"
config I2C_ALGOPCF config I2C_ALGOPCF
tristate tristate "I2C PCF 8584 interfaces"
config I2C_ALGOPCA config I2C_ALGOPCA
tristate tristate "I2C PCA 9564 interfaces"
config I2C_ALGO_SGI config I2C_ALGO_SGI
tristate tristate
depends on SGI_IP22 || SGI_IP32 || X86_VISWS depends on SGI_IP22 || SGI_IP32 || X86_VISWS
endmenu
...@@ -155,6 +155,9 @@ static int __init amd756_s4882_init(void) ...@@ -155,6 +155,9 @@ static int __init amd756_s4882_init(void)
int i, error; int i, error;
union i2c_smbus_data ioconfig; union i2c_smbus_data ioconfig;
if (!amd756_smbus.dev.parent)
return -ENODEV;
/* Configure the PCA9556 multiplexer */ /* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */ ioconfig.byte = 0x00; /* All I/O to output mode */
error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
...@@ -168,11 +171,7 @@ static int __init amd756_s4882_init(void) ...@@ -168,11 +171,7 @@ static int __init amd756_s4882_init(void)
/* Unregister physical bus */ /* Unregister physical bus */
error = i2c_del_adapter(&amd756_smbus); error = i2c_del_adapter(&amd756_smbus);
if (error) { if (error) {
if (error == -EINVAL) dev_err(&amd756_smbus.dev, "Physical bus removal failed\n");
error = -ENODEV;
else
dev_err(&amd756_smbus.dev, "Physical bus removal "
"failed\n");
goto ERROR0; goto ERROR0;
} }
......
...@@ -150,6 +150,9 @@ static int __init nforce2_s4985_init(void) ...@@ -150,6 +150,9 @@ static int __init nforce2_s4985_init(void)
int i, error; int i, error;
union i2c_smbus_data ioconfig; union i2c_smbus_data ioconfig;
if (!nforce2_smbus)
return -ENODEV;
/* Configure the PCA9556 multiplexer */ /* Configure the PCA9556 multiplexer */
ioconfig.byte = 0x00; /* All I/O to output mode */ ioconfig.byte = 0x00; /* All I/O to output mode */
error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
...@@ -161,8 +164,6 @@ static int __init nforce2_s4985_init(void) ...@@ -161,8 +164,6 @@ static int __init nforce2_s4985_init(void)
} }
/* Unregister physical bus */ /* Unregister physical bus */
if (!nforce2_smbus)
return -ENODEV;
error = i2c_del_adapter(nforce2_smbus); error = i2c_del_adapter(nforce2_smbus);
if (error) { if (error) {
dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n"); dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n");
......
...@@ -188,7 +188,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, ...@@ -188,7 +188,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
count = I2C_SMBUS_BLOCK_MAX; count = I2C_SMBUS_BLOCK_MAX;
status = i2c_smbus_read_i2c_block_data(client, offset, status = i2c_smbus_read_i2c_block_data(client, offset,
count, buf); count, buf);
dev_dbg(&client->dev, "smbus read %zd@%d --> %d\n", dev_dbg(&client->dev, "smbus read %zu@%d --> %d\n",
count, offset, status); count, offset, status);
return (status < 0) ? -EIO : status; return (status < 0) ? -EIO : status;
} }
...@@ -214,7 +214,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, ...@@ -214,7 +214,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
msg[1].len = count; msg[1].len = count;
status = i2c_transfer(client->adapter, msg, 2); status = i2c_transfer(client->adapter, msg, 2);
dev_dbg(&client->dev, "i2c read %zd@%d --> %d\n", dev_dbg(&client->dev, "i2c read %zu@%d --> %d\n",
count, offset, status); count, offset, status);
if (status == 2) if (status == 2)
...@@ -334,7 +334,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf, ...@@ -334,7 +334,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
if (status == 1) if (status == 1)
status = count; status = count;
} }
dev_dbg(&client->dev, "write %zd@%d --> %zd (%ld)\n", dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
count, offset, status, jiffies); count, offset, status, jiffies);
if (status == count) if (status == count)
...@@ -512,7 +512,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -512,7 +512,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
i2c_set_clientdata(client, at24); i2c_set_clientdata(client, at24);
dev_info(&client->dev, "%Zd byte %s EEPROM %s\n", dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
at24->bin.size, client->name, at24->bin.size, client->name,
writable ? "(writable)" : "(read-only)"); writable ? "(writable)" : "(read-only)");
dev_dbg(&client->dev, dev_dbg(&client->dev,
......
...@@ -813,7 +813,12 @@ static int i2c_check_addr(struct i2c_adapter *adapter, int addr) ...@@ -813,7 +813,12 @@ static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
int i2c_attach_client(struct i2c_client *client) int i2c_attach_client(struct i2c_client *client)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int res = 0; int res;
/* Check for address business */
res = i2c_check_addr(adapter, client->addr);
if (res)
return res;
client->dev.parent = &client->adapter->dev; client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type; client->dev.bus = &i2c_bus_type;
...@@ -1451,9 +1456,11 @@ i2c_new_probed_device(struct i2c_adapter *adap, ...@@ -1451,9 +1456,11 @@ i2c_new_probed_device(struct i2c_adapter *adap,
if ((addr_list[i] & ~0x07) == 0x30 if ((addr_list[i] & ~0x07) == 0x30
|| (addr_list[i] & ~0x0f) == 0x50 || (addr_list[i] & ~0x0f) == 0x50
|| !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) { || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
union i2c_smbus_data data;
if (i2c_smbus_xfer(adap, addr_list[i], 0, if (i2c_smbus_xfer(adap, addr_list[i], 0,
I2C_SMBUS_READ, 0, I2C_SMBUS_READ, 0,
I2C_SMBUS_BYTE, NULL) >= 0) I2C_SMBUS_BYTE, &data) >= 0)
break; break;
} else { } else {
if (i2c_smbus_xfer(adap, addr_list[i], 0, if (i2c_smbus_xfer(adap, addr_list[i], 0,
......
...@@ -147,7 +147,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, ...@@ -147,7 +147,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
if (tmp==NULL) if (tmp==NULL)
return -ENOMEM; return -ENOMEM;
pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n", pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
iminor(file->f_path.dentry->d_inode), count); iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_recv(client,tmp,count); ret = i2c_master_recv(client,tmp,count);
...@@ -175,7 +175,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c ...@@ -175,7 +175,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
return -EFAULT; return -EFAULT;
} }
pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n", pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",
iminor(file->f_path.dentry->d_inode), count); iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_send(client,tmp,count); ret = i2c_master_send(client,tmp,count);
......
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