aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
authorDavid Fries <David@Fries.net>2014-01-15 23:29:26 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-07 18:40:18 -0500
commitd3a8a9dbb903c73a7ec2deae4c9b7d74b6834f4c (patch)
tree49128d16abf121d8ae8c555a17a1339a09ff7585 /drivers/w1
parentb3be177a19f0f9e4f0deb473cef0e95e1254f2e9 (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')
-rw-r--r--drivers/w1/masters/ds1wm.c4
-rw-r--r--drivers/w1/masters/ds2490.c8
-rw-r--r--drivers/w1/w1_netlink.c13
3 files changed, 20 insertions, 5 deletions
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 02df3b1381d2..b077b8b42758 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -326,13 +326,14 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
326 unsigned slaves_found = 0; 326 unsigned slaves_found = 0;
327 unsigned int pass = 0; 327 unsigned int pass = 0;
328 328
329 mutex_lock(&master_dev->bus_mutex);
329 dev_dbg(&ds1wm_data->pdev->dev, "search begin\n"); 330 dev_dbg(&ds1wm_data->pdev->dev, "search begin\n");
330 while (true) { 331 while (true) {
331 ++pass; 332 ++pass;
332 if (pass > 100) { 333 if (pass > 100) {
333 dev_dbg(&ds1wm_data->pdev->dev, 334 dev_dbg(&ds1wm_data->pdev->dev,
334 "too many attempts (100), search aborted\n"); 335 "too many attempts (100), search aborted\n");
335 return; 336 break;
336 } 337 }
337 338
338 mutex_lock(&master_dev->bus_mutex); 339 mutex_lock(&master_dev->bus_mutex);
@@ -439,6 +440,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,
439 dev_dbg(&ds1wm_data->pdev->dev, 440 dev_dbg(&ds1wm_data->pdev->dev,
440 "pass: %d total: %d search done ms d bit pos: %d\n", pass, 441 "pass: %d total: %d search done ms d bit pos: %d\n", pass,
441 slaves_found, ms_discrep_bit); 442 slaves_found, ms_discrep_bit);
443 mutex_unlock(&master_dev->bus_mutex);
442} 444}
443 445
444/* --------------------------------------------------------------------- */ 446/* --------------------------------------------------------------------- */
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index db0bf3229bb6..7404ad3062b7 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -727,9 +727,11 @@ static void ds9490r_search(void *data, struct w1_master *master,
727 */ 727 */
728 u64 buf[2*64/8]; 728 u64 buf[2*64/8];
729 729
730 mutex_lock(&master->bus_mutex);
731
730 /* address to start searching at */ 732 /* address to start searching at */
731 if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0) 733 if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0)
732 return; 734 goto search_out;
733 master->search_id = 0; 735 master->search_id = 0;
734 736
735 value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F | 737 value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F |
@@ -739,7 +741,7 @@ static void ds9490r_search(void *data, struct w1_master *master,
739 search_limit = 0; 741 search_limit = 0;
740 index = search_type | (search_limit << 8); 742 index = search_type | (search_limit << 8);
741 if (ds_send_control(dev, value, index) < 0) 743 if (ds_send_control(dev, value, index) < 0)
742 return; 744 goto search_out;
743 745
744 do { 746 do {
745 schedule_timeout(jtime); 747 schedule_timeout(jtime);
@@ -791,6 +793,8 @@ static void ds9490r_search(void *data, struct w1_master *master,
791 master->max_slave_count); 793 master->max_slave_count);
792 set_bit(W1_WARN_MAX_COUNT, &master->flags); 794 set_bit(W1_WARN_MAX_COUNT, &master->flags);
793 } 795 }
796search_out:
797 mutex_unlock(&master->bus_mutex);
794} 798}
795 799
796#if 0 800#if 0
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);