diff options
author | David Fries <David@Fries.net> | 2014-01-15 23:29:26 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-07 18:40:18 -0500 |
commit | d3a8a9dbb903c73a7ec2deae4c9b7d74b6834f4c (patch) | |
tree | 49128d16abf121d8ae8c555a17a1339a09ff7585 /drivers/w1/w1_netlink.c | |
parent | b3be177a19f0f9e4f0deb473cef0e95e1254f2e9 (diff) |
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, | |||
246 | { | 246 | { |
247 | int err = -EINVAL; | 247 | int err = -EINVAL; |
248 | 248 | ||
249 | /* drop bus_mutex for search (does it's own locking), and add/remove | ||
250 | * which doesn't use the bus | ||
251 | */ | ||
249 | switch (req_cmd->cmd) { | 252 | switch (req_cmd->cmd) { |
250 | case W1_CMD_SEARCH: | 253 | case W1_CMD_SEARCH: |
251 | case W1_CMD_ALARM_SEARCH: | 254 | case W1_CMD_ALARM_SEARCH: |
252 | case W1_CMD_LIST_SLAVES: | 255 | case W1_CMD_LIST_SLAVES: |
256 | mutex_unlock(&dev->bus_mutex); | ||
253 | err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd); | 257 | err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd); |
258 | mutex_lock(&dev->bus_mutex); | ||
254 | break; | 259 | break; |
255 | case W1_CMD_READ: | 260 | case W1_CMD_READ: |
256 | case W1_CMD_WRITE: | 261 | case W1_CMD_WRITE: |
@@ -262,8 +267,12 @@ static int w1_process_command_master(struct w1_master *dev, | |||
262 | break; | 267 | break; |
263 | case W1_CMD_SLAVE_ADD: | 268 | case W1_CMD_SLAVE_ADD: |
264 | case W1_CMD_SLAVE_REMOVE: | 269 | case W1_CMD_SLAVE_REMOVE: |
270 | mutex_unlock(&dev->bus_mutex); | ||
271 | mutex_lock(&dev->mutex); | ||
265 | err = w1_process_command_addremove(dev, req_msg, req_hdr, | 272 | err = w1_process_command_addremove(dev, req_msg, req_hdr, |
266 | req_cmd); | 273 | req_cmd); |
274 | mutex_unlock(&dev->mutex); | ||
275 | mutex_lock(&dev->bus_mutex); | ||
267 | break; | 276 | break; |
268 | default: | 277 | default: |
269 | err = -EINVAL; | 278 | err = -EINVAL; |
@@ -400,7 +409,7 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) | |||
400 | struct w1_slave *sl = node->sl; | 409 | struct w1_slave *sl = node->sl; |
401 | struct w1_netlink_cmd *cmd = NULL; | 410 | struct w1_netlink_cmd *cmd = NULL; |
402 | 411 | ||
403 | mutex_lock(&dev->mutex); | 412 | mutex_lock(&dev->bus_mutex); |
404 | dev->portid = node->block->portid; | 413 | dev->portid = node->block->portid; |
405 | if (sl && w1_reset_select_slave(sl)) | 414 | if (sl && w1_reset_select_slave(sl)) |
406 | err = -ENODEV; | 415 | err = -ENODEV; |
@@ -437,7 +446,7 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) | |||
437 | else | 446 | else |
438 | atomic_dec(&dev->refcnt); | 447 | atomic_dec(&dev->refcnt); |
439 | dev->portid = 0; | 448 | dev->portid = 0; |
440 | mutex_unlock(&dev->mutex); | 449 | mutex_unlock(&dev->bus_mutex); |
441 | 450 | ||
442 | mutex_lock(&dev->list_mutex); | 451 | mutex_lock(&dev->list_mutex); |
443 | list_del(&async_cmd->async_entry); | 452 | list_del(&async_cmd->async_entry); |