xref: /kernel/linux/linux-6.6/drivers/w1/w1.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/delay.h>
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/moduleparam.h>
1062306a36Sopenharmony_ci#include <linux/list.h>
1162306a36Sopenharmony_ci#include <linux/interrupt.h>
1262306a36Sopenharmony_ci#include <linux/spinlock.h>
1362306a36Sopenharmony_ci#include <linux/timer.h>
1462306a36Sopenharmony_ci#include <linux/device.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/sched.h>
1762306a36Sopenharmony_ci#include <linux/kthread.h>
1862306a36Sopenharmony_ci#include <linux/freezer.h>
1962306a36Sopenharmony_ci#include <linux/hwmon.h>
2062306a36Sopenharmony_ci#include <linux/of.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <linux/atomic.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "w1_internal.h"
2562306a36Sopenharmony_ci#include "w1_netlink.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define W1_FAMILY_DEFAULT	0
2862306a36Sopenharmony_ci#define W1_FAMILY_DS28E04       0x1C /* for crc quirk */
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic int w1_timeout = 10;
3262306a36Sopenharmony_cimodule_param_named(timeout, w1_timeout, int, 0);
3362306a36Sopenharmony_ciMODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches");
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic int w1_timeout_us;
3662306a36Sopenharmony_cimodule_param_named(timeout_us, w1_timeout_us, int, 0);
3762306a36Sopenharmony_ciMODULE_PARM_DESC(timeout_us,
3862306a36Sopenharmony_ci		 "time in microseconds between automatic slave searches");
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/* A search stops when w1_max_slave_count devices have been found in that
4162306a36Sopenharmony_ci * search.  The next search will start over and detect the same set of devices
4262306a36Sopenharmony_ci * on a static 1-wire bus.  Memory is not allocated based on this number, just
4362306a36Sopenharmony_ci * on the number of devices known to the kernel.  Having a high number does not
4462306a36Sopenharmony_ci * consume additional resources.  As a special case, if there is only one
4562306a36Sopenharmony_ci * device on the network and w1_max_slave_count is set to 1, the device id can
4662306a36Sopenharmony_ci * be read directly skipping the normal slower search process.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ciint w1_max_slave_count = 64;
4962306a36Sopenharmony_cimodule_param_named(max_slave_count, w1_max_slave_count, int, 0);
5062306a36Sopenharmony_ciMODULE_PARM_DESC(max_slave_count,
5162306a36Sopenharmony_ci	"maximum number of slaves detected in a search");
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciint w1_max_slave_ttl = 10;
5462306a36Sopenharmony_cimodule_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
5562306a36Sopenharmony_ciMODULE_PARM_DESC(slave_ttl,
5662306a36Sopenharmony_ci	"Number of searches not seeing a slave before it will be removed");
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ciDEFINE_MUTEX(w1_mlock);
5962306a36Sopenharmony_ciLIST_HEAD(w1_masters);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic int w1_master_probe(struct device *dev)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	return -ENODEV;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic void w1_master_release(struct device *dev)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
7162306a36Sopenharmony_ci	memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
7262306a36Sopenharmony_ci	kfree(md);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic void w1_slave_release(struct device *dev)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct w1_slave *sl = dev_to_w1_slave(dev);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	dev_dbg(dev, "%s: Releasing %s [%p]\n", __func__, sl->name, sl);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	w1_family_put(sl->family);
8262306a36Sopenharmony_ci	sl->master->slave_count--;
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	struct w1_slave *sl = dev_to_w1_slave(dev);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	return sprintf(buf, "%s\n", sl->name);
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(name);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic ssize_t id_show(struct device *dev,
9462306a36Sopenharmony_ci	struct device_attribute *attr, char *buf)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct w1_slave *sl = dev_to_w1_slave(dev);
9762306a36Sopenharmony_ci	ssize_t count = sizeof(sl->reg_num);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	memcpy(buf, (u8 *)&sl->reg_num, count);
10062306a36Sopenharmony_ci	return count;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_cistatic DEVICE_ATTR_RO(id);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic struct attribute *w1_slave_attrs[] = {
10562306a36Sopenharmony_ci	&dev_attr_name.attr,
10662306a36Sopenharmony_ci	&dev_attr_id.attr,
10762306a36Sopenharmony_ci	NULL,
10862306a36Sopenharmony_ci};
10962306a36Sopenharmony_ciATTRIBUTE_GROUPS(w1_slave);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/* Default family */
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic ssize_t rw_write(struct file *filp, struct kobject *kobj,
11462306a36Sopenharmony_ci			struct bin_attribute *bin_attr, char *buf, loff_t off,
11562306a36Sopenharmony_ci			size_t count)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct w1_slave *sl = kobj_to_w1_slave(kobj);
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	mutex_lock(&sl->master->mutex);
12062306a36Sopenharmony_ci	if (w1_reset_select_slave(sl)) {
12162306a36Sopenharmony_ci		count = 0;
12262306a36Sopenharmony_ci		goto out_up;
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	w1_write_block(sl->master, buf, count);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciout_up:
12862306a36Sopenharmony_ci	mutex_unlock(&sl->master->mutex);
12962306a36Sopenharmony_ci	return count;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic ssize_t rw_read(struct file *filp, struct kobject *kobj,
13362306a36Sopenharmony_ci		       struct bin_attribute *bin_attr, char *buf, loff_t off,
13462306a36Sopenharmony_ci		       size_t count)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct w1_slave *sl = kobj_to_w1_slave(kobj);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	mutex_lock(&sl->master->mutex);
13962306a36Sopenharmony_ci	w1_read_block(sl->master, buf, count);
14062306a36Sopenharmony_ci	mutex_unlock(&sl->master->mutex);
14162306a36Sopenharmony_ci	return count;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic BIN_ATTR_RW(rw, PAGE_SIZE);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic struct bin_attribute *w1_slave_bin_attrs[] = {
14762306a36Sopenharmony_ci	&bin_attr_rw,
14862306a36Sopenharmony_ci	NULL,
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic const struct attribute_group w1_slave_default_group = {
15262306a36Sopenharmony_ci	.bin_attrs = w1_slave_bin_attrs,
15362306a36Sopenharmony_ci};
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic const struct attribute_group *w1_slave_default_groups[] = {
15662306a36Sopenharmony_ci	&w1_slave_default_group,
15762306a36Sopenharmony_ci	NULL,
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic const struct w1_family_ops w1_default_fops = {
16162306a36Sopenharmony_ci	.groups		= w1_slave_default_groups,
16262306a36Sopenharmony_ci};
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic struct w1_family w1_default_family = {
16562306a36Sopenharmony_ci	.fops = &w1_default_fops,
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic int w1_uevent(const struct device *dev, struct kobj_uevent_env *env);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic struct bus_type w1_bus_type = {
17162306a36Sopenharmony_ci	.name = "w1",
17262306a36Sopenharmony_ci	.uevent = w1_uevent,
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistruct device_driver w1_master_driver = {
17662306a36Sopenharmony_ci	.name = "w1_master_driver",
17762306a36Sopenharmony_ci	.bus = &w1_bus_type,
17862306a36Sopenharmony_ci	.probe = w1_master_probe,
17962306a36Sopenharmony_ci};
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistruct device w1_master_device = {
18262306a36Sopenharmony_ci	.parent = NULL,
18362306a36Sopenharmony_ci	.bus = &w1_bus_type,
18462306a36Sopenharmony_ci	.init_name = "w1 bus master",
18562306a36Sopenharmony_ci	.driver = &w1_master_driver,
18662306a36Sopenharmony_ci	.release = &w1_master_release
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic struct device_driver w1_slave_driver = {
19062306a36Sopenharmony_ci	.name = "w1_slave_driver",
19162306a36Sopenharmony_ci	.bus = &w1_bus_type,
19262306a36Sopenharmony_ci};
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#if 0
19562306a36Sopenharmony_cistruct device w1_slave_device = {
19662306a36Sopenharmony_ci	.parent = NULL,
19762306a36Sopenharmony_ci	.bus = &w1_bus_type,
19862306a36Sopenharmony_ci	.init_name = "w1 bus slave",
19962306a36Sopenharmony_ci	.driver = &w1_slave_driver,
20062306a36Sopenharmony_ci	.release = &w1_slave_release
20162306a36Sopenharmony_ci};
20262306a36Sopenharmony_ci#endif  /*  0  */
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
20762306a36Sopenharmony_ci	ssize_t count;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	mutex_lock(&md->mutex);
21062306a36Sopenharmony_ci	count = sprintf(buf, "%s\n", md->name);
21162306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	return count;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic ssize_t w1_master_attribute_store_search(struct device * dev,
21762306a36Sopenharmony_ci						struct device_attribute *attr,
21862306a36Sopenharmony_ci						const char * buf, size_t count)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	long tmp;
22162306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
22262306a36Sopenharmony_ci	int ret;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	ret = kstrtol(buf, 0, &tmp);
22562306a36Sopenharmony_ci	if (ret)
22662306a36Sopenharmony_ci		return ret;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	mutex_lock(&md->mutex);
22962306a36Sopenharmony_ci	md->search_count = tmp;
23062306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
23162306a36Sopenharmony_ci	/* Only wake if it is going to be searching. */
23262306a36Sopenharmony_ci	if (tmp)
23362306a36Sopenharmony_ci		wake_up_process(md->thread);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	return count;
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_search(struct device *dev,
23962306a36Sopenharmony_ci					       struct device_attribute *attr,
24062306a36Sopenharmony_ci					       char *buf)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
24362306a36Sopenharmony_ci	ssize_t count;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	mutex_lock(&md->mutex);
24662306a36Sopenharmony_ci	count = sprintf(buf, "%d\n", md->search_count);
24762306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return count;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistatic ssize_t w1_master_attribute_store_pullup(struct device *dev,
25362306a36Sopenharmony_ci						struct device_attribute *attr,
25462306a36Sopenharmony_ci						const char *buf, size_t count)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	long tmp;
25762306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
25862306a36Sopenharmony_ci	int ret;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	ret = kstrtol(buf, 0, &tmp);
26162306a36Sopenharmony_ci	if (ret)
26262306a36Sopenharmony_ci		return ret;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	mutex_lock(&md->mutex);
26562306a36Sopenharmony_ci	md->enable_pullup = tmp;
26662306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	return count;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_pullup(struct device *dev,
27262306a36Sopenharmony_ci					       struct device_attribute *attr,
27362306a36Sopenharmony_ci					       char *buf)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
27662306a36Sopenharmony_ci	ssize_t count;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	mutex_lock(&md->mutex);
27962306a36Sopenharmony_ci	count = sprintf(buf, "%d\n", md->enable_pullup);
28062306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	return count;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
28862306a36Sopenharmony_ci	ssize_t count;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	mutex_lock(&md->mutex);
29162306a36Sopenharmony_ci	count = sprintf(buf, "0x%p\n", md->bus_master);
29262306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
29362306a36Sopenharmony_ci	return count;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_timeout(struct device *dev, struct device_attribute *attr, char *buf)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	return sprintf(buf, "%d\n", w1_timeout);
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_timeout_us(struct device *dev,
30262306a36Sopenharmony_ci	struct device_attribute *attr, char *buf)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	return sprintf(buf, "%d\n", w1_timeout_us);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic ssize_t w1_master_attribute_store_max_slave_count(struct device *dev,
30862306a36Sopenharmony_ci	struct device_attribute *attr, const char *buf, size_t count)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	int tmp;
31162306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (kstrtoint(buf, 0, &tmp) || tmp < 1)
31462306a36Sopenharmony_ci		return -EINVAL;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	mutex_lock(&md->mutex);
31762306a36Sopenharmony_ci	md->max_slave_count = tmp;
31862306a36Sopenharmony_ci	/* allow each time the max_slave_count is updated */
31962306a36Sopenharmony_ci	clear_bit(W1_WARN_MAX_COUNT, &md->flags);
32062306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	return count;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
32862306a36Sopenharmony_ci	ssize_t count;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	mutex_lock(&md->mutex);
33162306a36Sopenharmony_ci	count = sprintf(buf, "%d\n", md->max_slave_count);
33262306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
33362306a36Sopenharmony_ci	return count;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
33962306a36Sopenharmony_ci	ssize_t count;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	mutex_lock(&md->mutex);
34262306a36Sopenharmony_ci	count = sprintf(buf, "%lu\n", md->attempts);
34362306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
34462306a36Sopenharmony_ci	return count;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
35062306a36Sopenharmony_ci	ssize_t count;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	mutex_lock(&md->mutex);
35362306a36Sopenharmony_ci	count = sprintf(buf, "%d\n", md->slave_count);
35462306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
35562306a36Sopenharmony_ci	return count;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_slaves(struct device *dev,
35962306a36Sopenharmony_ci	struct device_attribute *attr, char *buf)
36062306a36Sopenharmony_ci{
36162306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
36262306a36Sopenharmony_ci	int c = PAGE_SIZE;
36362306a36Sopenharmony_ci	struct list_head *ent, *n;
36462306a36Sopenharmony_ci	struct w1_slave *sl = NULL;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	mutex_lock(&md->list_mutex);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	list_for_each_safe(ent, n, &md->slist) {
36962306a36Sopenharmony_ci		sl = list_entry(ent, struct w1_slave, w1_slave_entry);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci		c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci	if (!sl)
37462306a36Sopenharmony_ci		c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	mutex_unlock(&md->list_mutex);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	return PAGE_SIZE - c;
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_add(struct device *dev,
38262306a36Sopenharmony_ci	struct device_attribute *attr, char *buf)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	int c = PAGE_SIZE;
38562306a36Sopenharmony_ci	c -= snprintf(buf+PAGE_SIZE - c, c,
38662306a36Sopenharmony_ci		"write device id xx-xxxxxxxxxxxx to add slave\n");
38762306a36Sopenharmony_ci	return PAGE_SIZE - c;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic int w1_atoreg_num(struct device *dev, const char *buf, size_t count,
39162306a36Sopenharmony_ci	struct w1_reg_num *rn)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	unsigned int family;
39462306a36Sopenharmony_ci	unsigned long long id;
39562306a36Sopenharmony_ci	int i;
39662306a36Sopenharmony_ci	u64 rn64_le;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	/* The CRC value isn't read from the user because the sysfs directory
39962306a36Sopenharmony_ci	 * doesn't include it and most messages from the bus search don't
40062306a36Sopenharmony_ci	 * print it either.  It would be unreasonable for the user to then
40162306a36Sopenharmony_ci	 * provide it.
40262306a36Sopenharmony_ci	 */
40362306a36Sopenharmony_ci	const char *error_msg = "bad slave string format, expecting "
40462306a36Sopenharmony_ci		"ff-dddddddddddd\n";
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (buf[2] != '-') {
40762306a36Sopenharmony_ci		dev_err(dev, "%s", error_msg);
40862306a36Sopenharmony_ci		return -EINVAL;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci	i = sscanf(buf, "%02x-%012llx", &family, &id);
41162306a36Sopenharmony_ci	if (i != 2) {
41262306a36Sopenharmony_ci		dev_err(dev, "%s", error_msg);
41362306a36Sopenharmony_ci		return -EINVAL;
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci	rn->family = family;
41662306a36Sopenharmony_ci	rn->id = id;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	rn64_le = cpu_to_le64(*(u64 *)rn);
41962306a36Sopenharmony_ci	rn->crc = w1_calc_crc8((u8 *)&rn64_le, 7);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci#if 0
42262306a36Sopenharmony_ci	dev_info(dev, "With CRC device is %02x.%012llx.%02x.\n",
42362306a36Sopenharmony_ci		  rn->family, (unsigned long long)rn->id, rn->crc);
42462306a36Sopenharmony_ci#endif
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	return 0;
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci/* Searches the slaves in the w1_master and returns a pointer or NULL.
43062306a36Sopenharmony_ci * Note: must not hold list_mutex
43162306a36Sopenharmony_ci */
43262306a36Sopenharmony_cistruct w1_slave *w1_slave_search_device(struct w1_master *dev,
43362306a36Sopenharmony_ci	struct w1_reg_num *rn)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	struct w1_slave *sl;
43662306a36Sopenharmony_ci	mutex_lock(&dev->list_mutex);
43762306a36Sopenharmony_ci	list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
43862306a36Sopenharmony_ci		if (sl->reg_num.family == rn->family &&
43962306a36Sopenharmony_ci				sl->reg_num.id == rn->id &&
44062306a36Sopenharmony_ci				sl->reg_num.crc == rn->crc) {
44162306a36Sopenharmony_ci			mutex_unlock(&dev->list_mutex);
44262306a36Sopenharmony_ci			return sl;
44362306a36Sopenharmony_ci		}
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci	mutex_unlock(&dev->list_mutex);
44662306a36Sopenharmony_ci	return NULL;
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic ssize_t w1_master_attribute_store_add(struct device *dev,
45062306a36Sopenharmony_ci						struct device_attribute *attr,
45162306a36Sopenharmony_ci						const char *buf, size_t count)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
45462306a36Sopenharmony_ci	struct w1_reg_num rn;
45562306a36Sopenharmony_ci	struct w1_slave *sl;
45662306a36Sopenharmony_ci	ssize_t result = count;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	if (w1_atoreg_num(dev, buf, count, &rn))
45962306a36Sopenharmony_ci		return -EINVAL;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	mutex_lock(&md->mutex);
46262306a36Sopenharmony_ci	sl = w1_slave_search_device(md, &rn);
46362306a36Sopenharmony_ci	/* It would be nice to do a targeted search one the one-wire bus
46462306a36Sopenharmony_ci	 * for the new device to see if it is out there or not.  But the
46562306a36Sopenharmony_ci	 * current search doesn't support that.
46662306a36Sopenharmony_ci	 */
46762306a36Sopenharmony_ci	if (sl) {
46862306a36Sopenharmony_ci		dev_info(dev, "Device %s already exists\n", sl->name);
46962306a36Sopenharmony_ci		result = -EINVAL;
47062306a36Sopenharmony_ci	} else {
47162306a36Sopenharmony_ci		w1_attach_slave_device(md, &rn);
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	return result;
47662306a36Sopenharmony_ci}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_cistatic ssize_t w1_master_attribute_show_remove(struct device *dev,
47962306a36Sopenharmony_ci	struct device_attribute *attr, char *buf)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	int c = PAGE_SIZE;
48262306a36Sopenharmony_ci	c -= snprintf(buf+PAGE_SIZE - c, c,
48362306a36Sopenharmony_ci		"write device id xx-xxxxxxxxxxxx to remove slave\n");
48462306a36Sopenharmony_ci	return PAGE_SIZE - c;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic ssize_t w1_master_attribute_store_remove(struct device *dev,
48862306a36Sopenharmony_ci						struct device_attribute *attr,
48962306a36Sopenharmony_ci						const char *buf, size_t count)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct w1_master *md = dev_to_w1_master(dev);
49262306a36Sopenharmony_ci	struct w1_reg_num rn;
49362306a36Sopenharmony_ci	struct w1_slave *sl;
49462306a36Sopenharmony_ci	ssize_t result;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	if (w1_atoreg_num(dev, buf, count, &rn))
49762306a36Sopenharmony_ci		return -EINVAL;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	mutex_lock(&md->mutex);
50062306a36Sopenharmony_ci	sl = w1_slave_search_device(md, &rn);
50162306a36Sopenharmony_ci	if (sl) {
50262306a36Sopenharmony_ci		result = w1_slave_detach(sl);
50362306a36Sopenharmony_ci		/* refcnt 0 means it was detached in the call */
50462306a36Sopenharmony_ci		if (result == 0)
50562306a36Sopenharmony_ci			result = count;
50662306a36Sopenharmony_ci	} else {
50762306a36Sopenharmony_ci		dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family,
50862306a36Sopenharmony_ci			(unsigned long long)rn.id);
50962306a36Sopenharmony_ci		result = -EINVAL;
51062306a36Sopenharmony_ci	}
51162306a36Sopenharmony_ci	mutex_unlock(&md->mutex);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	return result;
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci#define W1_MASTER_ATTR_RO(_name, _mode)				\
51762306a36Sopenharmony_ci	struct device_attribute w1_master_attribute_##_name =	\
51862306a36Sopenharmony_ci		__ATTR(w1_master_##_name, _mode,		\
51962306a36Sopenharmony_ci		       w1_master_attribute_show_##_name, NULL)
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci#define W1_MASTER_ATTR_RW(_name, _mode)				\
52262306a36Sopenharmony_ci	struct device_attribute w1_master_attribute_##_name =	\
52362306a36Sopenharmony_ci		__ATTR(w1_master_##_name, _mode,		\
52462306a36Sopenharmony_ci		       w1_master_attribute_show_##_name,	\
52562306a36Sopenharmony_ci		       w1_master_attribute_store_##_name)
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(name, S_IRUGO);
52862306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(slaves, S_IRUGO);
52962306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(slave_count, S_IRUGO);
53062306a36Sopenharmony_cistatic W1_MASTER_ATTR_RW(max_slave_count, S_IRUGO | S_IWUSR | S_IWGRP);
53162306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(attempts, S_IRUGO);
53262306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(timeout, S_IRUGO);
53362306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(timeout_us, S_IRUGO);
53462306a36Sopenharmony_cistatic W1_MASTER_ATTR_RO(pointer, S_IRUGO);
53562306a36Sopenharmony_cistatic W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUSR | S_IWGRP);
53662306a36Sopenharmony_cistatic W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUSR | S_IWGRP);
53762306a36Sopenharmony_cistatic W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUSR | S_IWGRP);
53862306a36Sopenharmony_cistatic W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUSR | S_IWGRP);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_cistatic struct attribute *w1_master_default_attrs[] = {
54162306a36Sopenharmony_ci	&w1_master_attribute_name.attr,
54262306a36Sopenharmony_ci	&w1_master_attribute_slaves.attr,
54362306a36Sopenharmony_ci	&w1_master_attribute_slave_count.attr,
54462306a36Sopenharmony_ci	&w1_master_attribute_max_slave_count.attr,
54562306a36Sopenharmony_ci	&w1_master_attribute_attempts.attr,
54662306a36Sopenharmony_ci	&w1_master_attribute_timeout.attr,
54762306a36Sopenharmony_ci	&w1_master_attribute_timeout_us.attr,
54862306a36Sopenharmony_ci	&w1_master_attribute_pointer.attr,
54962306a36Sopenharmony_ci	&w1_master_attribute_search.attr,
55062306a36Sopenharmony_ci	&w1_master_attribute_pullup.attr,
55162306a36Sopenharmony_ci	&w1_master_attribute_add.attr,
55262306a36Sopenharmony_ci	&w1_master_attribute_remove.attr,
55362306a36Sopenharmony_ci	NULL
55462306a36Sopenharmony_ci};
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic const struct attribute_group w1_master_defattr_group = {
55762306a36Sopenharmony_ci	.attrs = w1_master_default_attrs,
55862306a36Sopenharmony_ci};
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ciint w1_create_master_attributes(struct w1_master *master)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_civoid w1_destroy_master_attributes(struct w1_master *master)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_cistatic int w1_uevent(const struct device *dev, struct kobj_uevent_env *env)
57162306a36Sopenharmony_ci{
57262306a36Sopenharmony_ci	const struct w1_master *md = NULL;
57362306a36Sopenharmony_ci	const struct w1_slave *sl = NULL;
57462306a36Sopenharmony_ci	const char *event_owner, *name;
57562306a36Sopenharmony_ci	int err = 0;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	if (dev->driver == &w1_master_driver) {
57862306a36Sopenharmony_ci		md = container_of(dev, struct w1_master, dev);
57962306a36Sopenharmony_ci		event_owner = "master";
58062306a36Sopenharmony_ci		name = md->name;
58162306a36Sopenharmony_ci	} else if (dev->driver == &w1_slave_driver) {
58262306a36Sopenharmony_ci		sl = container_of(dev, struct w1_slave, dev);
58362306a36Sopenharmony_ci		event_owner = "slave";
58462306a36Sopenharmony_ci		name = sl->name;
58562306a36Sopenharmony_ci	} else {
58662306a36Sopenharmony_ci		dev_dbg(dev, "Unknown event.\n");
58762306a36Sopenharmony_ci		return -EINVAL;
58862306a36Sopenharmony_ci	}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n",
59162306a36Sopenharmony_ci			event_owner, name, dev_name(dev));
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	if (dev->driver != &w1_slave_driver || !sl)
59462306a36Sopenharmony_ci		goto end;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family);
59762306a36Sopenharmony_ci	if (err)
59862306a36Sopenharmony_ci		goto end;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	err = add_uevent_var(env, "W1_SLAVE_ID=%024LX",
60162306a36Sopenharmony_ci			     (unsigned long long)sl->reg_num.id);
60262306a36Sopenharmony_ciend:
60362306a36Sopenharmony_ci	return err;
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_cistatic int w1_family_notify(unsigned long action, struct w1_slave *sl)
60762306a36Sopenharmony_ci{
60862306a36Sopenharmony_ci	const struct w1_family_ops *fops;
60962306a36Sopenharmony_ci	int err;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	fops = sl->family->fops;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	if (!fops)
61462306a36Sopenharmony_ci		return 0;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	switch (action) {
61762306a36Sopenharmony_ci	case BUS_NOTIFY_ADD_DEVICE:
61862306a36Sopenharmony_ci		/* if the family driver needs to initialize something... */
61962306a36Sopenharmony_ci		if (fops->add_slave) {
62062306a36Sopenharmony_ci			err = fops->add_slave(sl);
62162306a36Sopenharmony_ci			if (err < 0) {
62262306a36Sopenharmony_ci				dev_err(&sl->dev,
62362306a36Sopenharmony_ci					"add_slave() call failed. err=%d\n",
62462306a36Sopenharmony_ci					err);
62562306a36Sopenharmony_ci				return err;
62662306a36Sopenharmony_ci			}
62762306a36Sopenharmony_ci		}
62862306a36Sopenharmony_ci		if (fops->groups) {
62962306a36Sopenharmony_ci			err = sysfs_create_groups(&sl->dev.kobj, fops->groups);
63062306a36Sopenharmony_ci			if (err) {
63162306a36Sopenharmony_ci				dev_err(&sl->dev,
63262306a36Sopenharmony_ci					"sysfs group creation failed. err=%d\n",
63362306a36Sopenharmony_ci					err);
63462306a36Sopenharmony_ci				return err;
63562306a36Sopenharmony_ci			}
63662306a36Sopenharmony_ci		}
63762306a36Sopenharmony_ci		if (IS_REACHABLE(CONFIG_HWMON) && fops->chip_info) {
63862306a36Sopenharmony_ci			struct device *hwmon
63962306a36Sopenharmony_ci				= hwmon_device_register_with_info(&sl->dev,
64062306a36Sopenharmony_ci						"w1_slave_temp", sl,
64162306a36Sopenharmony_ci						fops->chip_info,
64262306a36Sopenharmony_ci						NULL);
64362306a36Sopenharmony_ci			if (IS_ERR(hwmon)) {
64462306a36Sopenharmony_ci				dev_warn(&sl->dev,
64562306a36Sopenharmony_ci					 "could not create hwmon device\n");
64662306a36Sopenharmony_ci			} else {
64762306a36Sopenharmony_ci				sl->hwmon = hwmon;
64862306a36Sopenharmony_ci			}
64962306a36Sopenharmony_ci		}
65062306a36Sopenharmony_ci		break;
65162306a36Sopenharmony_ci	case BUS_NOTIFY_DEL_DEVICE:
65262306a36Sopenharmony_ci		if (IS_REACHABLE(CONFIG_HWMON) && fops->chip_info &&
65362306a36Sopenharmony_ci			    sl->hwmon)
65462306a36Sopenharmony_ci			hwmon_device_unregister(sl->hwmon);
65562306a36Sopenharmony_ci		if (fops->remove_slave)
65662306a36Sopenharmony_ci			sl->family->fops->remove_slave(sl);
65762306a36Sopenharmony_ci		if (fops->groups)
65862306a36Sopenharmony_ci			sysfs_remove_groups(&sl->dev.kobj, fops->groups);
65962306a36Sopenharmony_ci		break;
66062306a36Sopenharmony_ci	}
66162306a36Sopenharmony_ci	return 0;
66262306a36Sopenharmony_ci}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_cistatic int __w1_attach_slave_device(struct w1_slave *sl)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	int err;
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	sl->dev.parent = &sl->master->dev;
66962306a36Sopenharmony_ci	sl->dev.driver = &w1_slave_driver;
67062306a36Sopenharmony_ci	sl->dev.bus = &w1_bus_type;
67162306a36Sopenharmony_ci	sl->dev.release = &w1_slave_release;
67262306a36Sopenharmony_ci	sl->dev.groups = w1_slave_groups;
67362306a36Sopenharmony_ci	sl->dev.of_node = of_find_matching_node(sl->master->dev.of_node,
67462306a36Sopenharmony_ci						sl->family->of_match_table);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	dev_set_name(&sl->dev, "%02x-%012llx",
67762306a36Sopenharmony_ci		 (unsigned int) sl->reg_num.family,
67862306a36Sopenharmony_ci		 (unsigned long long) sl->reg_num.id);
67962306a36Sopenharmony_ci	snprintf(&sl->name[0], sizeof(sl->name),
68062306a36Sopenharmony_ci		 "%02x-%012llx",
68162306a36Sopenharmony_ci		 (unsigned int) sl->reg_num.family,
68262306a36Sopenharmony_ci		 (unsigned long long) sl->reg_num.id);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__,
68562306a36Sopenharmony_ci		dev_name(&sl->dev), sl);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	/* suppress for w1_family_notify before sending KOBJ_ADD */
68862306a36Sopenharmony_ci	dev_set_uevent_suppress(&sl->dev, true);
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	err = device_register(&sl->dev);
69162306a36Sopenharmony_ci	if (err < 0) {
69262306a36Sopenharmony_ci		dev_err(&sl->dev,
69362306a36Sopenharmony_ci			"Device registration [%s] failed. err=%d\n",
69462306a36Sopenharmony_ci			dev_name(&sl->dev), err);
69562306a36Sopenharmony_ci		of_node_put(sl->dev.of_node);
69662306a36Sopenharmony_ci		put_device(&sl->dev);
69762306a36Sopenharmony_ci		return err;
69862306a36Sopenharmony_ci	}
69962306a36Sopenharmony_ci	w1_family_notify(BUS_NOTIFY_ADD_DEVICE, sl);
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	dev_set_uevent_suppress(&sl->dev, false);
70262306a36Sopenharmony_ci	kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	mutex_lock(&sl->master->list_mutex);
70562306a36Sopenharmony_ci	list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
70662306a36Sopenharmony_ci	mutex_unlock(&sl->master->list_mutex);
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	return 0;
70962306a36Sopenharmony_ci}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ciint w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	struct w1_slave *sl;
71462306a36Sopenharmony_ci	struct w1_family *f;
71562306a36Sopenharmony_ci	int err;
71662306a36Sopenharmony_ci	struct w1_netlink_msg msg;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	sl = kzalloc(sizeof(struct w1_slave), GFP_KERNEL);
71962306a36Sopenharmony_ci	if (!sl) {
72062306a36Sopenharmony_ci		dev_err(&dev->dev,
72162306a36Sopenharmony_ci			 "%s: failed to allocate new slave device.\n",
72262306a36Sopenharmony_ci			 __func__);
72362306a36Sopenharmony_ci		return -ENOMEM;
72462306a36Sopenharmony_ci	}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	sl->owner = THIS_MODULE;
72862306a36Sopenharmony_ci	sl->master = dev;
72962306a36Sopenharmony_ci	set_bit(W1_SLAVE_ACTIVE, &sl->flags);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	memset(&msg, 0, sizeof(msg));
73262306a36Sopenharmony_ci	memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
73362306a36Sopenharmony_ci	atomic_set(&sl->refcnt, 1);
73462306a36Sopenharmony_ci	atomic_inc(&sl->master->refcnt);
73562306a36Sopenharmony_ci	dev->slave_count++;
73662306a36Sopenharmony_ci	dev_info(&dev->dev, "Attaching one wire slave %02x.%012llx crc %02x\n",
73762306a36Sopenharmony_ci		  rn->family, (unsigned long long)rn->id, rn->crc);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	/* slave modules need to be loaded in a context with unlocked mutex */
74062306a36Sopenharmony_ci	mutex_unlock(&dev->mutex);
74162306a36Sopenharmony_ci	request_module("w1-family-0x%02X", rn->family);
74262306a36Sopenharmony_ci	mutex_lock(&dev->mutex);
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	spin_lock(&w1_flock);
74562306a36Sopenharmony_ci	f = w1_family_registered(rn->family);
74662306a36Sopenharmony_ci	if (!f) {
74762306a36Sopenharmony_ci		f= &w1_default_family;
74862306a36Sopenharmony_ci		dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
74962306a36Sopenharmony_ci			  rn->family, rn->family,
75062306a36Sopenharmony_ci			  (unsigned long long)rn->id, rn->crc);
75162306a36Sopenharmony_ci	}
75262306a36Sopenharmony_ci	__w1_family_get(f);
75362306a36Sopenharmony_ci	spin_unlock(&w1_flock);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	sl->family = f;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	err = __w1_attach_slave_device(sl);
75862306a36Sopenharmony_ci	if (err < 0) {
75962306a36Sopenharmony_ci		dev_err(&dev->dev, "%s: Attaching %s failed.\n", __func__,
76062306a36Sopenharmony_ci			 sl->name);
76162306a36Sopenharmony_ci		dev->slave_count--;
76262306a36Sopenharmony_ci		w1_family_put(sl->family);
76362306a36Sopenharmony_ci		atomic_dec(&sl->master->refcnt);
76462306a36Sopenharmony_ci		kfree(sl);
76562306a36Sopenharmony_ci		return err;
76662306a36Sopenharmony_ci	}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	sl->ttl = dev->slave_ttl;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	memcpy(msg.id.id, rn, sizeof(msg.id));
77162306a36Sopenharmony_ci	msg.type = W1_SLAVE_ADD;
77262306a36Sopenharmony_ci	w1_netlink_send(dev, &msg);
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	return 0;
77562306a36Sopenharmony_ci}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ciint w1_unref_slave(struct w1_slave *sl)
77862306a36Sopenharmony_ci{
77962306a36Sopenharmony_ci	struct w1_master *dev = sl->master;
78062306a36Sopenharmony_ci	int refcnt;
78162306a36Sopenharmony_ci	mutex_lock(&dev->list_mutex);
78262306a36Sopenharmony_ci	refcnt = atomic_sub_return(1, &sl->refcnt);
78362306a36Sopenharmony_ci	if (refcnt == 0) {
78462306a36Sopenharmony_ci		struct w1_netlink_msg msg;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci		dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__,
78762306a36Sopenharmony_ci			sl->name, sl);
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci		list_del(&sl->w1_slave_entry);
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci		memset(&msg, 0, sizeof(msg));
79262306a36Sopenharmony_ci		memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
79362306a36Sopenharmony_ci		msg.type = W1_SLAVE_REMOVE;
79462306a36Sopenharmony_ci		w1_netlink_send(sl->master, &msg);
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci		w1_family_notify(BUS_NOTIFY_DEL_DEVICE, sl);
79762306a36Sopenharmony_ci		device_unregister(&sl->dev);
79862306a36Sopenharmony_ci		#ifdef DEBUG
79962306a36Sopenharmony_ci		memset(sl, 0, sizeof(*sl));
80062306a36Sopenharmony_ci		#endif
80162306a36Sopenharmony_ci		kfree(sl);
80262306a36Sopenharmony_ci	}
80362306a36Sopenharmony_ci	atomic_dec(&dev->refcnt);
80462306a36Sopenharmony_ci	mutex_unlock(&dev->list_mutex);
80562306a36Sopenharmony_ci	return refcnt;
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ciint w1_slave_detach(struct w1_slave *sl)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	/* Only detach a slave once as it decreases the refcnt each time. */
81162306a36Sopenharmony_ci	int destroy_now;
81262306a36Sopenharmony_ci	mutex_lock(&sl->master->list_mutex);
81362306a36Sopenharmony_ci	destroy_now = !test_bit(W1_SLAVE_DETACH, &sl->flags);
81462306a36Sopenharmony_ci	set_bit(W1_SLAVE_DETACH, &sl->flags);
81562306a36Sopenharmony_ci	mutex_unlock(&sl->master->list_mutex);
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	if (destroy_now)
81862306a36Sopenharmony_ci		destroy_now = !w1_unref_slave(sl);
81962306a36Sopenharmony_ci	return destroy_now ? 0 : -EBUSY;
82062306a36Sopenharmony_ci}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_cistruct w1_master *w1_search_master_id(u32 id)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	struct w1_master *dev = NULL, *iter;
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	mutex_lock(&w1_mlock);
82762306a36Sopenharmony_ci	list_for_each_entry(iter, &w1_masters, w1_master_entry) {
82862306a36Sopenharmony_ci		if (iter->id == id) {
82962306a36Sopenharmony_ci			dev = iter;
83062306a36Sopenharmony_ci			atomic_inc(&iter->refcnt);
83162306a36Sopenharmony_ci			break;
83262306a36Sopenharmony_ci		}
83362306a36Sopenharmony_ci	}
83462306a36Sopenharmony_ci	mutex_unlock(&w1_mlock);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	return dev;
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cistruct w1_slave *w1_search_slave(struct w1_reg_num *id)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	struct w1_master *dev;
84262306a36Sopenharmony_ci	struct w1_slave *sl = NULL, *iter;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	mutex_lock(&w1_mlock);
84562306a36Sopenharmony_ci	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
84662306a36Sopenharmony_ci		mutex_lock(&dev->list_mutex);
84762306a36Sopenharmony_ci		list_for_each_entry(iter, &dev->slist, w1_slave_entry) {
84862306a36Sopenharmony_ci			if (iter->reg_num.family == id->family &&
84962306a36Sopenharmony_ci			    iter->reg_num.id == id->id &&
85062306a36Sopenharmony_ci			    iter->reg_num.crc == id->crc) {
85162306a36Sopenharmony_ci				sl = iter;
85262306a36Sopenharmony_ci				atomic_inc(&dev->refcnt);
85362306a36Sopenharmony_ci				atomic_inc(&iter->refcnt);
85462306a36Sopenharmony_ci				break;
85562306a36Sopenharmony_ci			}
85662306a36Sopenharmony_ci		}
85762306a36Sopenharmony_ci		mutex_unlock(&dev->list_mutex);
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci		if (sl)
86062306a36Sopenharmony_ci			break;
86162306a36Sopenharmony_ci	}
86262306a36Sopenharmony_ci	mutex_unlock(&w1_mlock);
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	return sl;
86562306a36Sopenharmony_ci}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_civoid w1_reconnect_slaves(struct w1_family *f, int attach)
86862306a36Sopenharmony_ci{
86962306a36Sopenharmony_ci	struct w1_slave *sl, *sln;
87062306a36Sopenharmony_ci	struct w1_master *dev;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	mutex_lock(&w1_mlock);
87362306a36Sopenharmony_ci	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
87462306a36Sopenharmony_ci		dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
87562306a36Sopenharmony_ci			"for family %02x.\n", dev->name, f->fid);
87662306a36Sopenharmony_ci		mutex_lock(&dev->mutex);
87762306a36Sopenharmony_ci		mutex_lock(&dev->list_mutex);
87862306a36Sopenharmony_ci		list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
87962306a36Sopenharmony_ci			/* If it is a new family, slaves with the default
88062306a36Sopenharmony_ci			 * family driver and are that family will be
88162306a36Sopenharmony_ci			 * connected.  If the family is going away, devices
88262306a36Sopenharmony_ci			 * matching that family are reconneced.
88362306a36Sopenharmony_ci			 */
88462306a36Sopenharmony_ci			if ((attach && sl->family->fid == W1_FAMILY_DEFAULT
88562306a36Sopenharmony_ci				&& sl->reg_num.family == f->fid) ||
88662306a36Sopenharmony_ci				(!attach && sl->family->fid == f->fid)) {
88762306a36Sopenharmony_ci				struct w1_reg_num rn;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci				mutex_unlock(&dev->list_mutex);
89062306a36Sopenharmony_ci				memcpy(&rn, &sl->reg_num, sizeof(rn));
89162306a36Sopenharmony_ci				/* If it was already in use let the automatic
89262306a36Sopenharmony_ci				 * scan pick it up again later.
89362306a36Sopenharmony_ci				 */
89462306a36Sopenharmony_ci				if (!w1_slave_detach(sl))
89562306a36Sopenharmony_ci					w1_attach_slave_device(dev, &rn);
89662306a36Sopenharmony_ci				mutex_lock(&dev->list_mutex);
89762306a36Sopenharmony_ci			}
89862306a36Sopenharmony_ci		}
89962306a36Sopenharmony_ci		dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
90062306a36Sopenharmony_ci			"has been finished.\n", dev->name);
90162306a36Sopenharmony_ci		mutex_unlock(&dev->list_mutex);
90262306a36Sopenharmony_ci		mutex_unlock(&dev->mutex);
90362306a36Sopenharmony_ci	}
90462306a36Sopenharmony_ci	mutex_unlock(&w1_mlock);
90562306a36Sopenharmony_ci}
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_cistatic int w1_addr_crc_is_valid(struct w1_master *dev, u64 rn)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	u64 rn_le = cpu_to_le64(rn);
91062306a36Sopenharmony_ci	struct w1_reg_num *tmp = (struct w1_reg_num *)&rn;
91162306a36Sopenharmony_ci	u8 crc;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	crc = w1_calc_crc8((u8 *)&rn_le, 7);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	/* quirk:
91662306a36Sopenharmony_ci	 *   DS28E04 (1w eeprom) has strapping pins to change
91762306a36Sopenharmony_ci	 *   address, but will not update the crc. So normal rules
91862306a36Sopenharmony_ci	 *   for consistent w1 addresses are violated. We test
91962306a36Sopenharmony_ci	 *   with the 7 LSBs of the address forced high.
92062306a36Sopenharmony_ci	 *
92162306a36Sopenharmony_ci	 *   (char*)&rn_le = { family, addr_lsb, ..., addr_msb, crc }.
92262306a36Sopenharmony_ci	 */
92362306a36Sopenharmony_ci	if (crc != tmp->crc && tmp->family == W1_FAMILY_DS28E04) {
92462306a36Sopenharmony_ci		u64 corr_le = rn_le;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci		((u8 *)&corr_le)[1] |= 0x7f;
92762306a36Sopenharmony_ci		crc = w1_calc_crc8((u8 *)&corr_le, 7);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci		dev_info(&dev->dev, "DS28E04 crc workaround on %02x.%012llx.%02x\n",
93062306a36Sopenharmony_ci			tmp->family, (unsigned long long)tmp->id, tmp->crc);
93162306a36Sopenharmony_ci	}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	if (crc != tmp->crc) {
93462306a36Sopenharmony_ci		dev_dbg(&dev->dev, "w1 addr crc mismatch: %02x.%012llx.%02x != 0x%02x.\n",
93562306a36Sopenharmony_ci			tmp->family, (unsigned long long)tmp->id, tmp->crc, crc);
93662306a36Sopenharmony_ci		return 0;
93762306a36Sopenharmony_ci	}
93862306a36Sopenharmony_ci	return 1;
93962306a36Sopenharmony_ci}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_civoid w1_slave_found(struct w1_master *dev, u64 rn)
94262306a36Sopenharmony_ci{
94362306a36Sopenharmony_ci	struct w1_slave *sl;
94462306a36Sopenharmony_ci	struct w1_reg_num *tmp;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	atomic_inc(&dev->refcnt);
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	tmp = (struct w1_reg_num *) &rn;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	sl = w1_slave_search_device(dev, tmp);
95162306a36Sopenharmony_ci	if (sl) {
95262306a36Sopenharmony_ci		set_bit(W1_SLAVE_ACTIVE, &sl->flags);
95362306a36Sopenharmony_ci	} else {
95462306a36Sopenharmony_ci		if (rn && w1_addr_crc_is_valid(dev, rn))
95562306a36Sopenharmony_ci			w1_attach_slave_device(dev, tmp);
95662306a36Sopenharmony_ci	}
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	atomic_dec(&dev->refcnt);
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci/**
96262306a36Sopenharmony_ci * w1_search() - Performs a ROM Search & registers any devices found.
96362306a36Sopenharmony_ci * @dev: The master device to search
96462306a36Sopenharmony_ci * @search_type: W1_SEARCH to search all devices, or W1_ALARM_SEARCH
96562306a36Sopenharmony_ci * to return only devices in the alarmed state
96662306a36Sopenharmony_ci * @cb: Function to call when a device is found
96762306a36Sopenharmony_ci *
96862306a36Sopenharmony_ci * The 1-wire search is a simple binary tree search.
96962306a36Sopenharmony_ci * For each bit of the address, we read two bits and write one bit.
97062306a36Sopenharmony_ci * The bit written will put to sleep all devies that don't match that bit.
97162306a36Sopenharmony_ci * When the two reads differ, the direction choice is obvious.
97262306a36Sopenharmony_ci * When both bits are 0, we must choose a path to take.
97362306a36Sopenharmony_ci * When we can scan all 64 bits without having to choose a path, we are done.
97462306a36Sopenharmony_ci *
97562306a36Sopenharmony_ci * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
97662306a36Sopenharmony_ci *
97762306a36Sopenharmony_ci */
97862306a36Sopenharmony_civoid w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
97962306a36Sopenharmony_ci{
98062306a36Sopenharmony_ci	u64 last_rn, rn, tmp64;
98162306a36Sopenharmony_ci	int i, slave_count = 0;
98262306a36Sopenharmony_ci	int last_zero, last_device;
98362306a36Sopenharmony_ci	int search_bit, desc_bit;
98462306a36Sopenharmony_ci	u8  triplet_ret = 0;
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	search_bit = 0;
98762306a36Sopenharmony_ci	rn = dev->search_id;
98862306a36Sopenharmony_ci	last_rn = 0;
98962306a36Sopenharmony_ci	last_device = 0;
99062306a36Sopenharmony_ci	last_zero = -1;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	desc_bit = 64;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	while ( !last_device && (slave_count++ < dev->max_slave_count) ) {
99562306a36Sopenharmony_ci		last_rn = rn;
99662306a36Sopenharmony_ci		rn = 0;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci		/*
99962306a36Sopenharmony_ci		 * Reset bus and all 1-wire device state machines
100062306a36Sopenharmony_ci		 * so they can respond to our requests.
100162306a36Sopenharmony_ci		 *
100262306a36Sopenharmony_ci		 * Return 0 - device(s) present, 1 - no devices present.
100362306a36Sopenharmony_ci		 */
100462306a36Sopenharmony_ci		mutex_lock(&dev->bus_mutex);
100562306a36Sopenharmony_ci		if (w1_reset_bus(dev)) {
100662306a36Sopenharmony_ci			mutex_unlock(&dev->bus_mutex);
100762306a36Sopenharmony_ci			dev_dbg(&dev->dev, "No devices present on the wire.\n");
100862306a36Sopenharmony_ci			break;
100962306a36Sopenharmony_ci		}
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci		/* Do fast search on single slave bus */
101262306a36Sopenharmony_ci		if (dev->max_slave_count == 1) {
101362306a36Sopenharmony_ci			int rv;
101462306a36Sopenharmony_ci			w1_write_8(dev, W1_READ_ROM);
101562306a36Sopenharmony_ci			rv = w1_read_block(dev, (u8 *)&rn, 8);
101662306a36Sopenharmony_ci			mutex_unlock(&dev->bus_mutex);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci			if (rv == 8 && rn)
101962306a36Sopenharmony_ci				cb(dev, rn);
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci			break;
102262306a36Sopenharmony_ci		}
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci		/* Start the search */
102562306a36Sopenharmony_ci		w1_write_8(dev, search_type);
102662306a36Sopenharmony_ci		for (i = 0; i < 64; ++i) {
102762306a36Sopenharmony_ci			/* Determine the direction/search bit */
102862306a36Sopenharmony_ci			if (i == desc_bit)
102962306a36Sopenharmony_ci				search_bit = 1;	  /* took the 0 path last time, so take the 1 path */
103062306a36Sopenharmony_ci			else if (i > desc_bit)
103162306a36Sopenharmony_ci				search_bit = 0;	  /* take the 0 path on the next branch */
103262306a36Sopenharmony_ci			else
103362306a36Sopenharmony_ci				search_bit = ((last_rn >> i) & 0x1);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci			/* Read two bits and write one bit */
103662306a36Sopenharmony_ci			triplet_ret = w1_triplet(dev, search_bit);
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci			/* quit if no device responded */
103962306a36Sopenharmony_ci			if ( (triplet_ret & 0x03) == 0x03 )
104062306a36Sopenharmony_ci				break;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci			/* If both directions were valid, and we took the 0 path... */
104362306a36Sopenharmony_ci			if (triplet_ret == 0)
104462306a36Sopenharmony_ci				last_zero = i;
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci			/* extract the direction taken & update the device number */
104762306a36Sopenharmony_ci			tmp64 = (triplet_ret >> 2);
104862306a36Sopenharmony_ci			rn |= (tmp64 << i);
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci			if (test_bit(W1_ABORT_SEARCH, &dev->flags)) {
105162306a36Sopenharmony_ci				mutex_unlock(&dev->bus_mutex);
105262306a36Sopenharmony_ci				dev_dbg(&dev->dev, "Abort w1_search\n");
105362306a36Sopenharmony_ci				return;
105462306a36Sopenharmony_ci			}
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci		mutex_unlock(&dev->bus_mutex);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci		if ( (triplet_ret & 0x03) != 0x03 ) {
105962306a36Sopenharmony_ci			if ((desc_bit == last_zero) || (last_zero < 0)) {
106062306a36Sopenharmony_ci				last_device = 1;
106162306a36Sopenharmony_ci				dev->search_id = 0;
106262306a36Sopenharmony_ci			} else {
106362306a36Sopenharmony_ci				dev->search_id = rn;
106462306a36Sopenharmony_ci			}
106562306a36Sopenharmony_ci			desc_bit = last_zero;
106662306a36Sopenharmony_ci			cb(dev, rn);
106762306a36Sopenharmony_ci		}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci		if (!last_device && slave_count == dev->max_slave_count &&
107062306a36Sopenharmony_ci			!test_bit(W1_WARN_MAX_COUNT, &dev->flags)) {
107162306a36Sopenharmony_ci			/* Only max_slave_count will be scanned in a search,
107262306a36Sopenharmony_ci			 * but it will start where it left off next search
107362306a36Sopenharmony_ci			 * until all ids are identified and then it will start
107462306a36Sopenharmony_ci			 * over.  A continued search will report the previous
107562306a36Sopenharmony_ci			 * last id as the first id (provided it is still on the
107662306a36Sopenharmony_ci			 * bus).
107762306a36Sopenharmony_ci			 */
107862306a36Sopenharmony_ci			dev_info(&dev->dev, "%s: max_slave_count %d reached, "
107962306a36Sopenharmony_ci				"will continue next search.\n", __func__,
108062306a36Sopenharmony_ci				dev->max_slave_count);
108162306a36Sopenharmony_ci			set_bit(W1_WARN_MAX_COUNT, &dev->flags);
108262306a36Sopenharmony_ci		}
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_civoid w1_search_process_cb(struct w1_master *dev, u8 search_type,
108762306a36Sopenharmony_ci	w1_slave_found_callback cb)
108862306a36Sopenharmony_ci{
108962306a36Sopenharmony_ci	struct w1_slave *sl, *sln;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	mutex_lock(&dev->list_mutex);
109262306a36Sopenharmony_ci	list_for_each_entry(sl, &dev->slist, w1_slave_entry)
109362306a36Sopenharmony_ci		clear_bit(W1_SLAVE_ACTIVE, &sl->flags);
109462306a36Sopenharmony_ci	mutex_unlock(&dev->list_mutex);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	w1_search_devices(dev, search_type, cb);
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	mutex_lock(&dev->list_mutex);
109962306a36Sopenharmony_ci	list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
110062306a36Sopenharmony_ci		if (!test_bit(W1_SLAVE_ACTIVE, &sl->flags) && !--sl->ttl) {
110162306a36Sopenharmony_ci			mutex_unlock(&dev->list_mutex);
110262306a36Sopenharmony_ci			w1_slave_detach(sl);
110362306a36Sopenharmony_ci			mutex_lock(&dev->list_mutex);
110462306a36Sopenharmony_ci		}
110562306a36Sopenharmony_ci		else if (test_bit(W1_SLAVE_ACTIVE, &sl->flags))
110662306a36Sopenharmony_ci			sl->ttl = dev->slave_ttl;
110762306a36Sopenharmony_ci	}
110862306a36Sopenharmony_ci	mutex_unlock(&dev->list_mutex);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	if (dev->search_count > 0)
111162306a36Sopenharmony_ci		dev->search_count--;
111262306a36Sopenharmony_ci}
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_cistatic void w1_search_process(struct w1_master *dev, u8 search_type)
111562306a36Sopenharmony_ci{
111662306a36Sopenharmony_ci	w1_search_process_cb(dev, search_type, w1_slave_found);
111762306a36Sopenharmony_ci}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci/**
112062306a36Sopenharmony_ci * w1_process_callbacks() - execute each dev->async_list callback entry
112162306a36Sopenharmony_ci * @dev: w1_master device
112262306a36Sopenharmony_ci *
112362306a36Sopenharmony_ci * The w1 master list_mutex must be held.
112462306a36Sopenharmony_ci *
112562306a36Sopenharmony_ci * Return: 1 if there were commands to executed 0 otherwise
112662306a36Sopenharmony_ci */
112762306a36Sopenharmony_ciint w1_process_callbacks(struct w1_master *dev)
112862306a36Sopenharmony_ci{
112962306a36Sopenharmony_ci	int ret = 0;
113062306a36Sopenharmony_ci	struct w1_async_cmd *async_cmd, *async_n;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/* The list can be added to in another thread, loop until it is empty */
113362306a36Sopenharmony_ci	while (!list_empty(&dev->async_list)) {
113462306a36Sopenharmony_ci		list_for_each_entry_safe(async_cmd, async_n, &dev->async_list,
113562306a36Sopenharmony_ci			async_entry) {
113662306a36Sopenharmony_ci			/* drop the lock, if it is a search it can take a long
113762306a36Sopenharmony_ci			 * time */
113862306a36Sopenharmony_ci			mutex_unlock(&dev->list_mutex);
113962306a36Sopenharmony_ci			async_cmd->cb(dev, async_cmd);
114062306a36Sopenharmony_ci			ret = 1;
114162306a36Sopenharmony_ci			mutex_lock(&dev->list_mutex);
114262306a36Sopenharmony_ci		}
114362306a36Sopenharmony_ci	}
114462306a36Sopenharmony_ci	return ret;
114562306a36Sopenharmony_ci}
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ciint w1_process(void *data)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	struct w1_master *dev = (struct w1_master *) data;
115062306a36Sopenharmony_ci	/* As long as w1_timeout is only set by a module parameter the sleep
115162306a36Sopenharmony_ci	 * time can be calculated in jiffies once.
115262306a36Sopenharmony_ci	 */
115362306a36Sopenharmony_ci	const unsigned long jtime =
115462306a36Sopenharmony_ci	  usecs_to_jiffies(w1_timeout * 1000000 + w1_timeout_us);
115562306a36Sopenharmony_ci	/* remainder if it woke up early */
115662306a36Sopenharmony_ci	unsigned long jremain = 0;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	atomic_inc(&dev->refcnt);
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	for (;;) {
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci		if (!jremain && dev->search_count) {
116362306a36Sopenharmony_ci			mutex_lock(&dev->mutex);
116462306a36Sopenharmony_ci			w1_search_process(dev, W1_SEARCH);
116562306a36Sopenharmony_ci			mutex_unlock(&dev->mutex);
116662306a36Sopenharmony_ci		}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci		mutex_lock(&dev->list_mutex);
116962306a36Sopenharmony_ci		/* Note, w1_process_callback drops the lock while processing,
117062306a36Sopenharmony_ci		 * but locks it again before returning.
117162306a36Sopenharmony_ci		 */
117262306a36Sopenharmony_ci		if (!w1_process_callbacks(dev) && jremain) {
117362306a36Sopenharmony_ci			/* a wake up is either to stop the thread, process
117462306a36Sopenharmony_ci			 * callbacks, or search, it isn't process callbacks, so
117562306a36Sopenharmony_ci			 * schedule a search.
117662306a36Sopenharmony_ci			 */
117762306a36Sopenharmony_ci			jremain = 1;
117862306a36Sopenharmony_ci		}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci		__set_current_state(TASK_INTERRUPTIBLE);
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci		/* hold list_mutex until after interruptible to prevent loosing
118362306a36Sopenharmony_ci		 * the wakeup signal when async_cmd is added.
118462306a36Sopenharmony_ci		 */
118562306a36Sopenharmony_ci		mutex_unlock(&dev->list_mutex);
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci		if (kthread_should_stop()) {
118862306a36Sopenharmony_ci			__set_current_state(TASK_RUNNING);
118962306a36Sopenharmony_ci			break;
119062306a36Sopenharmony_ci		}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci		/* Only sleep when the search is active. */
119362306a36Sopenharmony_ci		if (dev->search_count) {
119462306a36Sopenharmony_ci			if (!jremain)
119562306a36Sopenharmony_ci				jremain = jtime;
119662306a36Sopenharmony_ci			jremain = schedule_timeout(jremain);
119762306a36Sopenharmony_ci		}
119862306a36Sopenharmony_ci		else
119962306a36Sopenharmony_ci			schedule();
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	atomic_dec(&dev->refcnt);
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	return 0;
120562306a36Sopenharmony_ci}
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_cistatic int __init w1_init(void)
120862306a36Sopenharmony_ci{
120962306a36Sopenharmony_ci	int retval;
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	pr_info("Driver for 1-wire Dallas network protocol.\n");
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	w1_init_netlink();
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	retval = bus_register(&w1_bus_type);
121662306a36Sopenharmony_ci	if (retval) {
121762306a36Sopenharmony_ci		pr_err("Failed to register bus. err=%d.\n", retval);
121862306a36Sopenharmony_ci		goto err_out_exit_init;
121962306a36Sopenharmony_ci	}
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	retval = driver_register(&w1_master_driver);
122262306a36Sopenharmony_ci	if (retval) {
122362306a36Sopenharmony_ci		pr_err("Failed to register master driver. err=%d.\n",
122462306a36Sopenharmony_ci			retval);
122562306a36Sopenharmony_ci		goto err_out_bus_unregister;
122662306a36Sopenharmony_ci	}
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	retval = driver_register(&w1_slave_driver);
122962306a36Sopenharmony_ci	if (retval) {
123062306a36Sopenharmony_ci		pr_err("Failed to register slave driver. err=%d.\n",
123162306a36Sopenharmony_ci			retval);
123262306a36Sopenharmony_ci		goto err_out_master_unregister;
123362306a36Sopenharmony_ci	}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	return 0;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci#if 0
123862306a36Sopenharmony_ci/* For undoing the slave register if there was a step after it. */
123962306a36Sopenharmony_cierr_out_slave_unregister:
124062306a36Sopenharmony_ci	driver_unregister(&w1_slave_driver);
124162306a36Sopenharmony_ci#endif
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_cierr_out_master_unregister:
124462306a36Sopenharmony_ci	driver_unregister(&w1_master_driver);
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_cierr_out_bus_unregister:
124762306a36Sopenharmony_ci	bus_unregister(&w1_bus_type);
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_cierr_out_exit_init:
125062306a36Sopenharmony_ci	return retval;
125162306a36Sopenharmony_ci}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_cistatic void __exit w1_fini(void)
125462306a36Sopenharmony_ci{
125562306a36Sopenharmony_ci	struct w1_master *dev, *n;
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	/* Set netlink removal messages and some cleanup */
125862306a36Sopenharmony_ci	list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry)
125962306a36Sopenharmony_ci		__w1_remove_master_device(dev);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	w1_fini_netlink();
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	driver_unregister(&w1_slave_driver);
126462306a36Sopenharmony_ci	driver_unregister(&w1_master_driver);
126562306a36Sopenharmony_ci	bus_unregister(&w1_bus_type);
126662306a36Sopenharmony_ci}
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_cimodule_init(w1_init);
126962306a36Sopenharmony_cimodule_exit(w1_fini);
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ciMODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
127262306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
127362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1274