W1: split master mutex to avoid deadlocks.
authorNeilBrown <neilb@suse.de>
Fri, 18 May 2012 05:59:52 +0000 (15:59 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Jun 2012 23:38:40 +0000 (16:38 -0700)
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: NeilBrown <neilb@suse.de>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
17 files changed:
drivers/power/ds2780_battery.c
drivers/power/ds2781_battery.c
drivers/w1/masters/ds1wm.c
drivers/w1/slaves/w1_bq27000.c
drivers/w1/slaves/w1_ds2408.c
drivers/w1/slaves/w1_ds2423.c
drivers/w1/slaves/w1_ds2431.c
drivers/w1/slaves/w1_ds2433.c
drivers/w1/slaves/w1_ds2760.c
drivers/w1/slaves/w1_ds2780.c
drivers/w1/slaves/w1_ds2780.h
drivers/w1/slaves/w1_ds2781.c
drivers/w1/slaves/w1_ds2781.h
drivers/w1/slaves/w1_therm.c
drivers/w1/w1.c
drivers/w1/w1.h
drivers/w1/w1_int.c

index de31cae1ba53cc4d2dbc6eb661b9d741be4bca19..74fad941c56c226c2d20ae667c37bd36191d65a7 100644 (file)
@@ -39,7 +39,6 @@ struct ds2780_device_info {
        struct device *dev;
        struct power_supply bat;
        struct device *w1_dev;
-       struct task_struct *mutex_holder;
 };
 
 enum current_types {
@@ -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,
        char *buf, int addr, size_t count, int io)
 {
-       if (dev_info->mutex_holder == current)
-               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);
+       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,
@@ -779,7 +775,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
        dev_info->bat.properties        = ds2780_battery_props;
        dev_info->bat.num_properties    = ARRAY_SIZE(ds2780_battery_props);
        dev_info->bat.get_property      = ds2780_battery_get_property;
-       dev_info->mutex_holder          = current;
 
        ret = power_supply_register(&pdev->dev, &dev_info->bat);
        if (ret) {
@@ -809,8 +804,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
                goto fail_remove_bin_file;
        }
 
-       dev_info->mutex_holder = NULL;
-
        return 0;
 
 fail_remove_bin_file:
@@ -830,8 +823,6 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
 {
        struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
 
-       dev_info->mutex_holder = current;
-
        /* remove attributes */
        sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
 
index 975684a40f1519ad33e5f630ecfa82020d71d960..5f92a4bb33f95aaafe772c3aeea1b2bc54a00186 100644 (file)
@@ -37,7 +37,6 @@ struct ds2781_device_info {
        struct device *dev;
        struct power_supply bat;
        struct device *w1_dev;
-       struct task_struct *mutex_holder;
 };
 
 enum current_types {
@@ -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,
        char *buf, int addr, size_t count, int io)
 {
-       if (dev_info->mutex_holder == current)
-               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);
+       return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io);
 }
 
 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)
        dev_info->bat.properties        = ds2781_battery_props;
        dev_info->bat.num_properties    = ARRAY_SIZE(ds2781_battery_props);
        dev_info->bat.get_property      = ds2781_battery_get_property;
-       dev_info->mutex_holder          = current;
 
        ret = power_supply_register(&pdev->dev, &dev_info->bat);
        if (ret) {
@@ -805,8 +799,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev)
                goto fail_remove_bin_file;
        }
 
-       dev_info->mutex_holder = NULL;
-
        return 0;
 
 fail_remove_bin_file:
@@ -826,8 +818,6 @@ static int __devexit ds2781_battery_remove(struct platform_device *pdev)
 {
        struct ds2781_device_info *dev_info = platform_get_drvdata(pdev);
 
-       dev_info->mutex_holder = current;
-
        /* remove attributes */
        sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
 
index a0c8965c1a793cb00f157eaa506355dedbd8ca00..530a2d30906308fbbc864ecf421ecd8ae47f60f3 100644 (file)
@@ -334,7 +334,9 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
                        return;
                }
 
+               mutex_lock(&master_dev->bus_mutex);
                if (ds1wm_reset(ds1wm_data)) {
+                       mutex_unlock(&master_dev->bus_mutex);
                        dev_dbg(&ds1wm_data->pdev->dev,
                                "pass: %d reset error (or no slaves)\n", pass);
                        break;
@@ -387,6 +389,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
 
                }
                if (ds1wm_data->read_error) {
+                       mutex_unlock(&master_dev->bus_mutex);
                        dev_err(&ds1wm_data->pdev->dev,
                                "pass: %d read error, retrying\n", pass);
                        break;
@@ -400,6 +403,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
                dev_dbg(&ds1wm_data->pdev->dev,
                        "pass: %d resetting bus\n", pass);
                ds1wm_reset(ds1wm_data);
+               mutex_unlock(&master_dev->bus_mutex);
                if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) {
                        dev_err(&ds1wm_data->pdev->dev,
                                "pass: %d bus error, retrying\n", pass);
index 52ad812fa1e7e73c8bc07545b82e967c73ff6a50..773dca5beafe7e2f7e77f3046870148c514d75ce 100644 (file)
@@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg)
        u8 val;
        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);
        val = w1_read_8(sl->master);
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return val;
 }
index 8e813eed0f0ae8167304dae1c62faf974498dbcc..441ad3a3b586b05b6a993a58fff0eb22bdadb0db 100644 (file)
@@ -52,11 +52,11 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
        if (!buf)
                return -EINVAL;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
        dev_dbg(&sl->dev, "mutex locked");
 
        if (w1_reset_select_slave(sl)) {
-               mutex_unlock(&sl->master->mutex);
+               mutex_unlock(&sl->master->bus_mutex);
                return -EIO;
        }
 
@@ -66,7 +66,7 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
        w1_write_block(sl->master, wrbuf, 3);
        *buf = w1_read_8(sl->master);
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
        dev_dbg(&sl->dev, "mutex unlocked");
        return 1;
 }
@@ -165,7 +165,7 @@ static ssize_t w1_f29_write_output(
                return -EFAULT;
 
        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");
 
        if (w1_reset_select_slave(sl))
@@ -200,14 +200,14 @@ static ssize_t w1_f29_write_output(
                /* read the result of the READ_PIO_REGS command */
                if (w1_read_8(sl->master) == *buf) {
                        /* success! */
-                       mutex_unlock(&sl->master->mutex);
+                       mutex_unlock(&sl->master->bus_mutex);
                        dev_dbg(&sl->dev,
                                "mutex unlocked, retries:%d", retries);
                        return 1;
                }
        }
 error:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
        dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
 
        return -EIO;
@@ -228,7 +228,7 @@ static ssize_t w1_f29_write_activity(
        if (count != 1 || off != 0)
                return -EFAULT;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        if (w1_reset_select_slave(sl))
                goto error;
@@ -236,7 +236,7 @@ static ssize_t w1_f29_write_activity(
        while (retries--) {
                w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
                if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
-                       mutex_unlock(&sl->master->mutex);
+                       mutex_unlock(&sl->master->bus_mutex);
                        return 1;
                }
                if (w1_reset_resume_command(sl->master))
@@ -244,7 +244,7 @@ static ssize_t w1_f29_write_activity(
        }
 
 error:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
        return -EIO;
 }
 
@@ -263,7 +263,7 @@ static ssize_t w1_f29_write_status_control(
        if (count != 1 || off != 0)
                return -EFAULT;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        if (w1_reset_select_slave(sl))
                goto error;
@@ -285,12 +285,12 @@ static ssize_t w1_f29_write_status_control(
                w1_write_block(sl->master, w1_buf, 3);
                if (w1_read_8(sl->master) == *buf) {
                        /* success! */
-                       mutex_unlock(&sl->master->mutex);
+                       mutex_unlock(&sl->master->bus_mutex);
                        return 1;
                }
        }
 error:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return -EIO;
 }
index 7a7dbe5026f1f0495efa8451a004fb41e4374eb6..40a10b5ed120c134d14e77481d1fdf70101ed2ef 100644 (file)
@@ -66,7 +66,7 @@ static ssize_t w1_counter_read(struct device *device,
        wrbuf[0]        = 0xA5;
        wrbuf[1]        = rom_addr & 0xFF;
        wrbuf[2]        = rom_addr >> 8;
-       mutex_lock(&dev->mutex);
+       mutex_lock(&dev->bus_mutex);
        if (!w1_reset_select_slave(sl)) {
                w1_write_block(dev, wrbuf, 3);
                read_byte_count = 0;
@@ -124,7 +124,7 @@ static ssize_t w1_counter_read(struct device *device,
        } else {
                c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error");
        }
-       mutex_unlock(&dev->mutex);
+       mutex_unlock(&dev->bus_mutex);
        return PAGE_SIZE - c;
 }
 
index 84e2410aec1dd5b187d9e60487d1e0a993989afe..984b30331a45be06e3f307753f5ee26fe3f82a98 100644 (file)
@@ -107,7 +107,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj,
        if (count == 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 */
        while (todo > 0) {
@@ -126,7 +126,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj,
                off += W1_F2D_READ_MAXLEN;
        }
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return count;
 }
@@ -214,7 +214,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj,
        if (count == 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 */
        addr = off;
@@ -259,7 +259,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj,
        }
 
 out_up:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return count;
 }
index 0f7b8f9c509a87577a76daad431447fe0f97375c..85f2cdb27fa2dd258b8ee3c72d32dcdc73ba1010 100644 (file)
@@ -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)
                return 0;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
 
@@ -138,7 +138,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj,
 #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 
 out_up:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return count;
 }
@@ -233,7 +233,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj,
        }
 #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 */
        idx = 0;
@@ -251,7 +251,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj,
        }
 
 out_up:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return count;
 }
index 5754c9a4f58b49be5237ac50b70234779f0b07bd..aa7bd5fa2fa8e5bb79aefe265636651eae7da8e4 100644 (file)
@@ -31,7 +31,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
        if (!dev)
                return 0;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        if (addr > DS2760_DATA_SIZE || addr < 0) {
                count = 0;
@@ -54,7 +54,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
        }
 
 out:
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return count;
 }
@@ -76,14 +76,14 @@ static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd)
        if (!dev)
                return -EINVAL;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        if (w1_reset_select_slave(sl) == 0) {
                w1_write_8(sl->master, cmd);
                w1_write_8(sl->master, addr);
        }
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
        return 0;
 }
 
index 39f78c0b143cb495a15eff9d67f5e4b7eb6ce4be..7b09307de0ef418f7f670038f7a3e5a923ff4f3c 100644 (file)
@@ -60,30 +60,16 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
        if (!dev)
                return -ENODEV;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        ret = w1_ds2780_do_io(dev, buf, addr, count, io);
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return ret;
 }
 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)
 {
        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)
        if (!dev)
                return -EINVAL;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        if (w1_reset_select_slave(sl) == 0) {
                w1_write_8(sl->master, cmd);
                w1_write_8(sl->master, addr);
        }
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
        return 0;
 }
 EXPORT_SYMBOL(w1_ds2780_eeprom_cmd);
index 7373793650216cca9eed315cf9875c40863aa726..a1fba79eb1b54ea990dc9cf6923452e482a6e3e2 100644 (file)
 
 extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
                        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);
 
 #endif /* !_W1_DS2780_H */
index 0d0c7985293fb02ca0a6f76292b8e32738e2acde..877daf74159c98b7c8a77284d6ce31105b6fb9d3 100644 (file)
@@ -58,30 +58,16 @@ int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count,
        if (!dev)
                return -ENODEV;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        ret = w1_ds2781_do_io(dev, buf, addr, count, io);
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
 
        return ret;
 }
 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)
 {
        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)
        if (!dev)
                return -EINVAL;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&sl->master->bus_mutex);
 
        if (w1_reset_select_slave(sl) == 0) {
                w1_write_8(sl->master, cmd);
                w1_write_8(sl->master, addr);
        }
 
-       mutex_unlock(&sl->master->mutex);
+       mutex_unlock(&sl->master->bus_mutex);
        return 0;
 }
 EXPORT_SYMBOL(w1_ds2781_eeprom_cmd);
index 82bc66497b43a8c0c7116163eb7d1c8808718bca..557dfb0b4f6479d117314d0d6ce1372f37ad6236 100644 (file)
 
 extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count,
                        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);
 
 #endif /* !_W1_DS2781_H */
index ff29ae747ee82e41455d5db1b49bbd4b0fbebbf9..d90062b211f8a107a142f439129a6f8d699aa1de 100644 (file)
@@ -179,7 +179,7 @@ static ssize_t w1_therm_read(struct device *device,
        int i, max_trying = 10;
        ssize_t c = PAGE_SIZE;
 
-       i = mutex_lock_interruptible(&dev->mutex);
+       i = mutex_lock_interruptible(&dev->bus_mutex);
        if (i != 0)
                return i;
 
@@ -207,19 +207,19 @@ static ssize_t w1_therm_read(struct device *device,
                        w1_write_8(dev, W1_CONVERT_TEMP);
 
                        if (external_power) {
-                               mutex_unlock(&dev->mutex);
+                               mutex_unlock(&dev->bus_mutex);
 
                                sleep_rem = msleep_interruptible(tm);
                                if (sleep_rem != 0)
                                        return -EINTR;
 
-                               i = mutex_lock_interruptible(&dev->mutex);
+                               i = mutex_lock_interruptible(&dev->bus_mutex);
                                if (i != 0)
                                        return i;
                        } else if (!w1_strong_pullup) {
                                sleep_rem = msleep_interruptible(tm);
                                if (sleep_rem != 0) {
-                                       mutex_unlock(&dev->mutex);
+                                       mutex_unlock(&dev->bus_mutex);
                                        return -EINTR;
                                }
                        }
@@ -258,7 +258,7 @@ static ssize_t w1_therm_read(struct device *device,
 
        c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
                w1_convert_temp(rom, sl->family->fid));
-       mutex_unlock(&dev->mutex);
+       mutex_unlock(&dev->bus_mutex);
 
        return PAGE_SIZE - c;
 }
index bfb898641029f963f05bb019b4b21a198c33d4be..1a574370d2cd22ec4686604520c9f139052afba9 100644 (file)
@@ -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.
                 */
+               mutex_lock(&dev->bus_mutex);
                if (w1_reset_bus(dev)) {
+                       mutex_unlock(&dev->bus_mutex);
                        dev_dbg(&dev->dev, "No devices present on the wire.\n");
                        break;
                }
 
                /* Do fast search on single slave bus */
                if (dev->max_slave_count == 1) {
+                       int rv;
                        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);
 
                        break;
@@ -927,10 +932,12 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
                        rn |= (tmp64 << i);
 
                        if (kthread_should_stop()) {
+                               mutex_unlock(&dev->bus_mutex);
                                dev_dbg(&dev->dev, "Abort w1_search\n");
                                return;
                        }
                }
+               mutex_unlock(&dev->bus_mutex);
 
                if ( (triplet_ret & 0x03) != 0x03 ) {
                        if ( (desc_bit == last_zero) || (last_zero < 0))
index 4d012ca3f32c42a27c2ccd54b9b506907abd597e..45908e56c2f834180ca0b166e44bd9fca50a5e2d 100644 (file)
@@ -180,6 +180,7 @@ struct w1_master
 
        struct task_struct      *thread;
        struct mutex            mutex;
+       struct mutex            bus_mutex;
 
        struct device_driver    *driver;
        struct device           dev;
index 68288355727a13377d97652727c97d448431b0b2..531434180afd1670cdd1db718615e0397cfdaf8a 100644 (file)
@@ -76,6 +76,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 
        INIT_LIST_HEAD(&dev->slist);
        mutex_init(&dev->mutex);
+       mutex_init(&dev->bus_mutex);
 
        memcpy(&dev->dev, device, sizeof(struct device));
        dev_set_name(&dev->dev, "w1_bus_master%u", dev->id);