Commit b02f8bed authored by NeilBrown's avatar NeilBrown Committed by Greg Kroah-Hartman

W1: split master mutex to avoid deadlocks.

The 'mutex' in struct w1_master is use for two very different
purposes.

Firstly it protects various data structures such as the list of all
slaves.

Secondly it protects the w1 buss against concurrent accesses.

This can lead to deadlocks when the ->probe code called while adding a
slave needs to talk on the bus, as is the case for power_supply
devices.
ds2780 and ds2781 drivers contain a work around to track which
process hold the lock simply to avoid this deadlock.  bq27000 doesn't
have that work around and so deadlocks.

There are other possible deadlocks involving sysfs.
When removing a device the sysfs s_active lock is held, so the lock
that protects the slave list must take precedence over s_active.
However when access power_supply attributes via sysfs, the s_active
lock must take precedence over the lock that protects accesses to
the bus.

So to avoid deadlocks between w1 slaves and sysfs, these must be
two separate locks.  Making them separate means that the work around
in ds2780 and ds2781 can be removed.

So this patch:
 - adds a new mutex: "bus_mutex" which serialises access to the bus.
 - takes in mutex in w1_search and ds1wm_search while they access
   the bus for searching.  The mutex is dropped before calling the
   callback which adds the slave.
 - changes all slaves to use bus_mutex instead of mutex to
   protect access to the bus
 - removes w1_ds2790_io_nolock and w1_ds2781_io_nolock, and the
   related code from drivers/power/ds278[01]_battery.c which
   calls them.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Acked-by: default avatarEvgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b7e938d0
...@@ -39,7 +39,6 @@ struct ds2780_device_info { ...@@ -39,7 +39,6 @@ struct ds2780_device_info {
struct device *dev; struct device *dev;
struct power_supply bat; struct power_supply bat;
struct device *w1_dev; struct device *w1_dev;
struct task_struct *mutex_holder;
}; };
enum current_types { enum current_types {
...@@ -64,10 +63,7 @@ static inline struct power_supply *to_power_supply(struct device *dev) ...@@ -64,10 +63,7 @@ static inline struct power_supply *to_power_supply(struct device *dev)
static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, static inline int ds2780_battery_io(struct ds2780_device_info *dev_info,
char *buf, int addr, size_t count, int io) char *buf, int addr, size_t count, int io)
{ {
if (dev_info->mutex_holder == current) return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io);
return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io);
else
return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io);
} }
static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val,
...@@ -779,7 +775,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev) ...@@ -779,7 +775,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
dev_info->bat.properties = ds2780_battery_props; dev_info->bat.properties = ds2780_battery_props;
dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props);
dev_info->bat.get_property = ds2780_battery_get_property; dev_info->bat.get_property = ds2780_battery_get_property;
dev_info->mutex_holder = current;
ret = power_supply_register(&pdev->dev, &dev_info->bat); ret = power_supply_register(&pdev->dev, &dev_info->bat);
if (ret) { if (ret) {
...@@ -809,8 +804,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev) ...@@ -809,8 +804,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
goto fail_remove_bin_file; goto fail_remove_bin_file;
} }
dev_info->mutex_holder = NULL;
return 0; return 0;
fail_remove_bin_file: fail_remove_bin_file:
...@@ -830,8 +823,6 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev) ...@@ -830,8 +823,6 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
{ {
struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
dev_info->mutex_holder = current;
/* remove attributes */ /* remove attributes */
sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
......
...@@ -37,7 +37,6 @@ struct ds2781_device_info { ...@@ -37,7 +37,6 @@ struct ds2781_device_info {
struct device *dev; struct device *dev;
struct power_supply bat; struct power_supply bat;
struct device *w1_dev; struct device *w1_dev;
struct task_struct *mutex_holder;
}; };
enum current_types { enum current_types {
...@@ -62,11 +61,7 @@ static inline struct power_supply *to_power_supply(struct device *dev) ...@@ -62,11 +61,7 @@ static inline struct power_supply *to_power_supply(struct device *dev)
static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, static inline int ds2781_battery_io(struct ds2781_device_info *dev_info,
char *buf, int addr, size_t count, int io) char *buf, int addr, size_t count, int io)
{ {
if (dev_info->mutex_holder == current) return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io);
return w1_ds2781_io_nolock(dev_info->w1_dev, buf, addr,
count, io);
else
return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io);
} }
int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf,
...@@ -775,7 +770,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev) ...@@ -775,7 +770,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev)
dev_info->bat.properties = ds2781_battery_props; dev_info->bat.properties = ds2781_battery_props;
dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props); dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props);
dev_info->bat.get_property = ds2781_battery_get_property; dev_info->bat.get_property = ds2781_battery_get_property;
dev_info->mutex_holder = current;
ret = power_supply_register(&pdev->dev, &dev_info->bat); ret = power_supply_register(&pdev->dev, &dev_info->bat);
if (ret) { if (ret) {
...@@ -805,8 +799,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev) ...@@ -805,8 +799,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev)
goto fail_remove_bin_file; goto fail_remove_bin_file;
} }
dev_info->mutex_holder = NULL;
return 0; return 0;
fail_remove_bin_file: fail_remove_bin_file:
...@@ -826,8 +818,6 @@ static int __devexit ds2781_battery_remove(struct platform_device *pdev) ...@@ -826,8 +818,6 @@ static int __devexit ds2781_battery_remove(struct platform_device *pdev)
{ {
struct ds2781_device_info *dev_info = platform_get_drvdata(pdev); struct ds2781_device_info *dev_info = platform_get_drvdata(pdev);
dev_info->mutex_holder = current;
/* remove attributes */ /* remove attributes */
sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
......
...@@ -334,7 +334,9 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, ...@@ -334,7 +334,9 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
return; return;
} }
mutex_lock(&master_dev->bus_mutex);
if (ds1wm_reset(ds1wm_data)) { if (ds1wm_reset(ds1wm_data)) {
mutex_unlock(&master_dev->bus_mutex);
dev_dbg(&ds1wm_data->pdev->dev, dev_dbg(&ds1wm_data->pdev->dev,
"pass: %d reset error (or no slaves)\n", pass); "pass: %d reset error (or no slaves)\n", pass);
break; break;
...@@ -387,6 +389,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, ...@@ -387,6 +389,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
} }
if (ds1wm_data->read_error) { if (ds1wm_data->read_error) {
mutex_unlock(&master_dev->bus_mutex);
dev_err(&ds1wm_data->pdev->dev, dev_err(&ds1wm_data->pdev->dev,
"pass: %d read error, retrying\n", pass); "pass: %d read error, retrying\n", pass);
break; break;
...@@ -400,6 +403,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, ...@@ -400,6 +403,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
dev_dbg(&ds1wm_data->pdev->dev, dev_dbg(&ds1wm_data->pdev->dev,
"pass: %d resetting bus\n", pass); "pass: %d resetting bus\n", pass);
ds1wm_reset(ds1wm_data); ds1wm_reset(ds1wm_data);
mutex_unlock(&master_dev->bus_mutex);
if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) {
dev_err(&ds1wm_data->pdev->dev, dev_err(&ds1wm_data->pdev->dev,
"pass: %d bus error, retrying\n", pass); "pass: %d bus error, retrying\n", pass);
......
...@@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg) ...@@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg)
u8 val; u8 val;
struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev);
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
w1_write_8(sl->master, HDQ_CMD_READ | reg); w1_write_8(sl->master, HDQ_CMD_READ | reg);
val = w1_read_8(sl->master); val = w1_read_8(sl->master);
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return val; return val;
} }
......
...@@ -52,11 +52,11 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) ...@@ -52,11 +52,11 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
if (!buf) if (!buf)
return -EINVAL; return -EINVAL;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
dev_dbg(&sl->dev, "mutex locked"); dev_dbg(&sl->dev, "mutex locked");
if (w1_reset_select_slave(sl)) { if (w1_reset_select_slave(sl)) {
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return -EIO; return -EIO;
} }
...@@ -66,7 +66,7 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) ...@@ -66,7 +66,7 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
w1_write_block(sl->master, wrbuf, 3); w1_write_block(sl->master, wrbuf, 3);
*buf = w1_read_8(sl->master); *buf = w1_read_8(sl->master);
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
dev_dbg(&sl->dev, "mutex unlocked"); dev_dbg(&sl->dev, "mutex unlocked");
return 1; return 1;
} }
...@@ -165,7 +165,7 @@ static ssize_t w1_f29_write_output( ...@@ -165,7 +165,7 @@ static ssize_t w1_f29_write_output(
return -EFAULT; return -EFAULT;
dev_dbg(&sl->dev, "locking mutex for write_output"); dev_dbg(&sl->dev, "locking mutex for write_output");
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
dev_dbg(&sl->dev, "mutex locked"); dev_dbg(&sl->dev, "mutex locked");
if (w1_reset_select_slave(sl)) if (w1_reset_select_slave(sl))
...@@ -200,14 +200,14 @@ static ssize_t w1_f29_write_output( ...@@ -200,14 +200,14 @@ static ssize_t w1_f29_write_output(
/* read the result of the READ_PIO_REGS command */ /* read the result of the READ_PIO_REGS command */
if (w1_read_8(sl->master) == *buf) { if (w1_read_8(sl->master) == *buf) {
/* success! */ /* success! */
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
dev_dbg(&sl->dev, dev_dbg(&sl->dev,
"mutex unlocked, retries:%d", retries); "mutex unlocked, retries:%d", retries);
return 1; return 1;
} }
} }
error: error:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
return -EIO; return -EIO;
...@@ -228,7 +228,7 @@ static ssize_t w1_f29_write_activity( ...@@ -228,7 +228,7 @@ static ssize_t w1_f29_write_activity(
if (count != 1 || off != 0) if (count != 1 || off != 0)
return -EFAULT; return -EFAULT;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl)) if (w1_reset_select_slave(sl))
goto error; goto error;
...@@ -236,7 +236,7 @@ static ssize_t w1_f29_write_activity( ...@@ -236,7 +236,7 @@ static ssize_t w1_f29_write_activity(
while (retries--) { while (retries--) {
w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return 1; return 1;
} }
if (w1_reset_resume_command(sl->master)) if (w1_reset_resume_command(sl->master))
...@@ -244,7 +244,7 @@ static ssize_t w1_f29_write_activity( ...@@ -244,7 +244,7 @@ static ssize_t w1_f29_write_activity(
} }
error: error:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return -EIO; return -EIO;
} }
...@@ -263,7 +263,7 @@ static ssize_t w1_f29_write_status_control( ...@@ -263,7 +263,7 @@ static ssize_t w1_f29_write_status_control(
if (count != 1 || off != 0) if (count != 1 || off != 0)
return -EFAULT; return -EFAULT;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl)) if (w1_reset_select_slave(sl))
goto error; goto error;
...@@ -285,12 +285,12 @@ static ssize_t w1_f29_write_status_control( ...@@ -285,12 +285,12 @@ static ssize_t w1_f29_write_status_control(
w1_write_block(sl->master, w1_buf, 3); w1_write_block(sl->master, w1_buf, 3);
if (w1_read_8(sl->master) == *buf) { if (w1_read_8(sl->master) == *buf) {
/* success! */ /* success! */
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return 1; return 1;
} }
} }
error: error:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return -EIO; return -EIO;
} }
......
...@@ -66,7 +66,7 @@ static ssize_t w1_counter_read(struct device *device, ...@@ -66,7 +66,7 @@ static ssize_t w1_counter_read(struct device *device,
wrbuf[0] = 0xA5; wrbuf[0] = 0xA5;
wrbuf[1] = rom_addr & 0xFF; wrbuf[1] = rom_addr & 0xFF;
wrbuf[2] = rom_addr >> 8; wrbuf[2] = rom_addr >> 8;
mutex_lock(&dev->mutex); mutex_lock(&dev->bus_mutex);
if (!w1_reset_select_slave(sl)) { if (!w1_reset_select_slave(sl)) {
w1_write_block(dev, wrbuf, 3); w1_write_block(dev, wrbuf, 3);
read_byte_count = 0; read_byte_count = 0;
...@@ -124,7 +124,7 @@ static ssize_t w1_counter_read(struct device *device, ...@@ -124,7 +124,7 @@ static ssize_t w1_counter_read(struct device *device,
} else { } else {
c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error"); c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error");
} }
mutex_unlock(&dev->mutex); mutex_unlock(&dev->bus_mutex);
return PAGE_SIZE - c; return PAGE_SIZE - c;
} }
......
...@@ -107,7 +107,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, ...@@ -107,7 +107,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj,
if (count == 0) if (count == 0)
return 0; return 0;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
/* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */ /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */
while (todo > 0) { while (todo > 0) {
...@@ -126,7 +126,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, ...@@ -126,7 +126,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj,
off += W1_F2D_READ_MAXLEN; off += W1_F2D_READ_MAXLEN;
} }
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return count; return count;
} }
...@@ -214,7 +214,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, ...@@ -214,7 +214,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj,
if (count == 0) if (count == 0)
return 0; return 0;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
/* Can only write data in blocks of the size of the scratchpad */ /* Can only write data in blocks of the size of the scratchpad */
addr = off; addr = off;
...@@ -259,7 +259,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, ...@@ -259,7 +259,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj,
} }
out_up: out_up:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return count; return count;
} }
......
...@@ -107,7 +107,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, ...@@ -107,7 +107,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj,
if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
return 0; return 0;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
#ifdef CONFIG_W1_SLAVE_DS2433_CRC #ifdef CONFIG_W1_SLAVE_DS2433_CRC
...@@ -138,7 +138,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, ...@@ -138,7 +138,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj,
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */ #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
out_up: out_up:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return count; return count;
} }
...@@ -233,7 +233,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, ...@@ -233,7 +233,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj,
} }
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */ #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
/* Can only write data to one page at a time */ /* Can only write data to one page at a time */
idx = 0; idx = 0;
...@@ -251,7 +251,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, ...@@ -251,7 +251,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj,
} }
out_up: out_up:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return count; return count;
} }
......
...@@ -31,7 +31,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count, ...@@ -31,7 +31,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
if (!dev) if (!dev)
return 0; return 0;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
if (addr > DS2760_DATA_SIZE || addr < 0) { if (addr > DS2760_DATA_SIZE || addr < 0) {
count = 0; count = 0;
...@@ -54,7 +54,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count, ...@@ -54,7 +54,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
} }
out: out:
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return count; return count;
} }
...@@ -76,14 +76,14 @@ static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd) ...@@ -76,14 +76,14 @@ static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd)
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl) == 0) { if (w1_reset_select_slave(sl) == 0) {
w1_write_8(sl->master, cmd); w1_write_8(sl->master, cmd);
w1_write_8(sl->master, addr); w1_write_8(sl->master, addr);
} }
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return 0; return 0;
} }
......
...@@ -60,30 +60,16 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, ...@@ -60,30 +60,16 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
ret = w1_ds2780_do_io(dev, buf, addr, count, io); ret = w1_ds2780_do_io(dev, buf, addr, count, io);
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return ret; return ret;
} }
EXPORT_SYMBOL(w1_ds2780_io); EXPORT_SYMBOL(w1_ds2780_io);
int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, size_t count,
int io)
{
int ret;
if (!dev)
return -ENODEV;
ret = w1_ds2780_do_io(dev, buf, addr, count, io);
return ret;
}
EXPORT_SYMBOL(w1_ds2780_io_nolock);
int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd)
{ {
struct w1_slave *sl = container_of(dev, struct w1_slave, dev); struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
...@@ -91,14 +77,14 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) ...@@ -91,14 +77,14 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd)
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl) == 0) { if (w1_reset_select_slave(sl) == 0) {
w1_write_8(sl->master, cmd); w1_write_8(sl->master, cmd);
w1_write_8(sl->master, addr); w1_write_8(sl->master, addr);
} }
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return 0; return 0;
} }
EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); EXPORT_SYMBOL(w1_ds2780_eeprom_cmd);
......
...@@ -124,8 +124,6 @@ ...@@ -124,8 +124,6 @@
extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
int io); int io);
extern int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr,
size_t count, int io);
extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd);
#endif /* !_W1_DS2780_H */ #endif /* !_W1_DS2780_H */
...@@ -58,30 +58,16 @@ int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, ...@@ -58,30 +58,16 @@ int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count,
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
ret = w1_ds2781_do_io(dev, buf, addr, count, io); ret = w1_ds2781_do_io(dev, buf, addr, count, io);
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return ret; return ret;
} }
EXPORT_SYMBOL(w1_ds2781_io); EXPORT_SYMBOL(w1_ds2781_io);
int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, size_t count,
int io)
{
int ret;
if (!dev)
return -ENODEV;
ret = w1_ds2781_do_io(dev, buf, addr, count, io);
return ret;
}
EXPORT_SYMBOL(w1_ds2781_io_nolock);
int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd)
{ {
struct w1_slave *sl = container_of(dev, struct w1_slave, dev); struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
...@@ -89,14 +75,14 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) ...@@ -89,14 +75,14 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd)
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
mutex_lock(&sl->master->mutex); mutex_lock(&sl->master->bus_mutex);
if (w1_reset_select_slave(sl) == 0) { if (w1_reset_select_slave(sl) == 0) {
w1_write_8(sl->master, cmd); w1_write_8(sl->master, cmd);
w1_write_8(sl->master, addr); w1_write_8(sl->master, addr);
} }
mutex_unlock(&sl->master->mutex); mutex_unlock(&sl->master->bus_mutex);
return 0; return 0;
} }
EXPORT_SYMBOL(w1_ds2781_eeprom_cmd); EXPORT_SYMBOL(w1_ds2781_eeprom_cmd);
......
...@@ -129,8 +129,6 @@ ...@@ -129,8 +129,6 @@
extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count,
int io); int io);
extern int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr,
size_t count, int io);
extern int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd); extern int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd);
#endif /* !_W1_DS2781_H */ #endif /* !_W1_DS2781_H */
...@@ -179,7 +179,7 @@ static ssize_t w1_therm_read(struct device *device, ...@@ -179,7 +179,7 @@ static ssize_t w1_therm_read(struct device *device,
int i, max_trying = 10; int i, max_trying = 10;
ssize_t c = PAGE_SIZE; ssize_t c = PAGE_SIZE;
i = mutex_lock_interruptible(&dev->mutex); i = mutex_lock_interruptible(&dev->bus_mutex);
if (i != 0) if (i != 0)
return i; return i;
...@@ -207,19 +207,19 @@ static ssize_t w1_therm_read(struct device *device, ...@@ -207,19 +207,19 @@ static ssize_t w1_therm_read(struct device *device,
w1_write_8(dev, W1_CONVERT_TEMP); w1_write_8(dev, W1_CONVERT_TEMP);
if (external_power) { if (external_power) {
mutex_unlock(&dev->mutex); mutex_unlock(&dev->bus_mutex);
sleep_rem = msleep_interruptible(tm); sleep_rem = msleep_interruptible(tm);
if (sleep_rem != 0) if (sleep_rem != 0)
return -EINTR; return -EINTR;
i = mutex_lock_interruptible(&dev->mutex); i = mutex_lock_interruptible(&dev->bus_mutex);
if (i != 0) if (i != 0)
return i; return i;
} else if (!w1_strong_pullup) { } else if (!w1_strong_pullup) {
sleep_rem = msleep_interruptible(tm); sleep_rem = msleep_interruptible(tm);
if (sleep_rem != 0) { if (sleep_rem != 0) {
mutex_unlock(&dev->mutex); mutex_unlock(&dev->bus_mutex);
return -EINTR; return -EINTR;
} }
} }
...@@ -258,7 +258,7 @@ static ssize_t w1_therm_read(struct device *device, ...@@ -258,7 +258,7 @@ static ssize_t w1_therm_read(struct device *device,
c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n", c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
w1_convert_temp(rom, sl->family->fid)); w1_convert_temp(rom, sl->family->fid));
mutex_unlock(&dev->mutex); mutex_unlock(&dev->bus_mutex);
return PAGE_SIZE - c; return PAGE_SIZE - c;
} }
......
...@@ -885,16 +885,21 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb ...@@ -885,16 +885,21 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
* *
* Return 0 - device(s) present, 1 - no devices present. * Return 0 - device(s) present, 1 - no devices present.
*/ */
mutex_lock(&dev->bus_mutex);
if (w1_reset_bus(dev)) { if (w1_reset_bus(dev)) {
mutex_unlock(&dev->bus_mutex);
dev_dbg(&dev->dev, "No devices present on the wire.\n"); dev_dbg(&dev->dev, "No devices present on the wire.\n");
break; break;
} }
/* Do fast search on single slave bus */ /* Do fast search on single slave bus */
if (dev->max_slave_count == 1) { if (dev->max_slave_count == 1) {
int rv;
w1_write_8(dev, W1_READ_ROM); w1_write_8(dev, W1_READ_ROM);
rv = w1_read_block(dev, (u8 *)&rn, 8);
mutex_unlock(&dev->bus_mutex);
if (w1_read_block(dev, (u8 *)&rn, 8) == 8 && rn) if (rv == 8 && rn)
cb(dev, rn); cb(dev, rn);
break; break;
...@@ -927,10 +932,12 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb ...@@ -927,10 +932,12 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
rn |= (tmp64 << i); rn |= (tmp64 << i);
if (kthread_should_stop()) { if (kthread_should_stop()) {
mutex_unlock(&dev->bus_mutex);
dev_dbg(&dev->dev, "Abort w1_search\n"); dev_dbg(&dev->dev, "Abort w1_search\n");
return; return;
} }
} }
mutex_unlock(&dev->bus_mutex);
if ( (triplet_ret & 0x03) != 0x03 ) { if ( (triplet_ret & 0x03) != 0x03 ) {
if ( (desc_bit == last_zero) || (last_zero < 0)) if ( (desc_bit == last_zero) || (last_zero < 0))
......
...@@ -180,6 +180,7 @@ struct w1_master ...@@ -180,6 +180,7 @@ struct w1_master
struct task_struct *thread; struct task_struct *thread;
struct mutex mutex; struct mutex mutex;
struct mutex bus_mutex;
struct device_driver *driver; struct device_driver *driver;
struct device dev; struct device dev;
......
...@@ -76,6 +76,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, ...@@ -76,6 +76,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
INIT_LIST_HEAD(&dev->slist); INIT_LIST_HEAD(&dev->slist);
mutex_init(&dev->mutex); mutex_init(&dev->mutex);
mutex_init(&dev->bus_mutex);
memcpy(&dev->dev, device, sizeof(struct device)); memcpy(&dev->dev, device, sizeof(struct device));
dev_set_name(&dev->dev, "w1_bus_master%u", dev->id); dev_set_name(&dev->dev, "w1_bus_master%u", dev->id);
......
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