Commit e3fe0e89 authored by Christian Vogel's avatar Christian Vogel Committed by Greg Kroah-Hartman
Browse files

w1/masters/ds2490: queue up found IDs during scan



Queue up found IDs in a buffer and run the callback once for each found ID
at the end. This is necessary because we hold the bus_mutex during the
whole scan, and some of the "add-device" callbacks deadlock as they
themselves want to mutex_lock(bus_mutex).

Acked-by: default avatarEvgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: default avatarChristian Vogel <vogelchr@vogel.cx>
Link: https://lore.kernel.org/r/20210113195018.7498-3-vogelchr@vogel.cx


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 48b7de66
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -688,12 +688,22 @@ static void ds9490r_search(void *data, struct w1_master *master,
	 * packet size.
	 */
	const size_t bufsize = 2 * 64;
	u64 *buf;
	u64 *buf, *found_ids;

	buf = kmalloc(bufsize, GFP_KERNEL);
	if (!buf)
		return;

	/*
	 * We are holding the bus mutex during the scan, but adding devices via the
	 * callback needs the bus to be unlocked. So we queue up found ids here.
	 */
	found_ids = kmalloc_array(master->max_slave_count, sizeof(u64), GFP_KERNEL);
	if (!found_ids) {
		kfree(buf);
		return;
	}

	mutex_lock(&master->bus_mutex);

	/* address to start searching at */
@@ -729,13 +739,13 @@ static void ds9490r_search(void *data, struct w1_master *master,
			if (err < 0)
				break;
			for (i = 0; i < err/8; ++i) {
				++found;
				if (found <= search_limit)
					callback(master, buf[i]);
				found_ids[found++] = buf[i];
				/* can't know if there will be a discrepancy
				 * value after until the next id */
				if (found == search_limit)
				if (found == search_limit) {
					master->search_id = buf[i];
					break;
				}
			}
		}

@@ -759,9 +769,14 @@ static void ds9490r_search(void *data, struct w1_master *master,
			master->max_slave_count);
		set_bit(W1_WARN_MAX_COUNT, &master->flags);
	}

search_out:
	mutex_unlock(&master->bus_mutex);
	kfree(buf);

	for (i = 0; i < found; i++) /* run callback for all queued up IDs */
		callback(master, found_ids[i]);
	kfree(found_ids);
}

#if 0