diff options
author | David Fries <David@Fries.net> | 2014-01-16 08:29:26 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-08 03:40:18 +0400 |
commit | d3a8a9dbb903c73a7ec2deae4c9b7d74b6834f4c (patch) | |
tree | 49128d16abf121d8ae8c555a17a1339a09ff7585 /drivers/w1/w1_netlink.c | |
parent | b3be177a19f0f9e4f0deb473cef0e95e1254f2e9 (diff) | |
download | linux-d3a8a9dbb903c73a7ec2deae4c9b7d74b6834f4c.tar.xz |
w1: hold bus_mutex in netlink and search
The bus_mutex needs to be taken to serialize access to a specific bus.
netlink wasn't updated when bus_mutex was added and was calling
without that lock held, and not all of the masters were holding the
bus_mutex in a search. This was causing the ds2490 hardware to stop
responding when both netlink and /sys slaves were executing bus
commands at the same time.
Signed-off-by: David Fries <David@Fries.net>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/w1/w1_netlink.c')
-rw-r--r-- | drivers/w1/w1_netlink.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index a5dc21934cf2..5234964fe001 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c @@ -246,11 +246,16 @@ static int w1_process_command_master(struct w1_master *dev, { int err = -EINVAL; + /* drop bus_mutex for search (does it's own locking), and add/remove + * which doesn't use the bus + */ switch (req_cmd->cmd) { case W1_CMD_SEARCH: case W1_CMD_ALARM_SEARCH: case W1_CMD_LIST_SLAVES: + mutex_unlock(&dev->bus_mutex); err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd); + mutex_lock(&dev->bus_mutex); break; case W1_CMD_READ: case W1_CMD_WRITE: @@ -262,8 +267,12 @@ static int w1_process_command_master(struct w1_master *dev, break; case W1_CMD_SLAVE_ADD: case W1_CMD_SLAVE_REMOVE: + mutex_unlock(&dev->bus_mutex); + mutex_lock(&dev->mutex); err = w1_process_command_addremove(dev, req_msg, req_hdr, req_cmd); + mutex_unlock(&dev->mutex); + mutex_lock(&dev->bus_mutex); break; default: err = -EINVAL; @@ -400,7 +409,7 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) struct w1_slave *sl = node->sl; struct w1_netlink_cmd *cmd = NULL; - mutex_lock(&dev->mutex); + mutex_lock(&dev->bus_mutex); dev->portid = node->block->portid; if (sl && w1_reset_select_slave(sl)) err = -ENODEV; @@ -437,7 +446,7 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) else atomic_dec(&dev->refcnt); dev->portid = 0; - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->bus_mutex); mutex_lock(&dev->list_mutex); list_del(&async_cmd->async_entry); |