Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0cd30fd authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/w1-2.6

parents 94eb7f4c e5c515b4
Loading
Loading
Loading
Loading
+90 −17
Original line number Original line Diff line number Diff line
Any w1 device must be connected to w1 bus master device - for example
The 1-wire (w1) subsystem
ds9490 usb device or w1-over-GPIO or RS232 converter.
------------------------------------------------------------------
Driver for w1 bus master must provide several functions(you can find
The 1-wire bus is a simple master-slave bus that communicates via a single
them in struct w1_bus_master definition in w1.h) which then will be
signal wire (plus ground, so two wires).
called by w1 core to send various commands over w1 bus(by default it is

reset and search commands). When some device is found on the bus, w1 core
Devices communicate on the bus by pulling the signal to ground via an open
checks if driver for it's family is loaded.
drain output and by sampling the logic level of the signal line.
If driver is loaded w1 core creates new w1_slave object and registers it

in the system(creates some generic sysfs files(struct w1_family_ops in
The w1 subsystem provides the framework for managing w1 masters and
w1_family.h), notifies any registered listener and so on...).
communication with slaves.
It is device driver's business to provide any communication method

upstream.
All w1 slave devices must be connected to a w1 bus master device.
For example w1_therm driver(ds18?20 thermal sensor family driver)

Example w1 master devices:
    DS9490 usb device
    W1-over-GPIO
    DS2482 (i2c to w1 bridge)
    Emulated devices, such as a RS232 converter, parallel port adapter, etc


What does the w1 subsystem do?
------------------------------------------------------------------
When a w1 master driver registers with the w1 subsystem, the following occurs:

 - sysfs entries for that w1 master are created
 - the w1 bus is periodically searched for new slave devices

When a device is found on the bus, w1 core checks if driver for it's family is
loaded. If so, the family driver is attached to the slave.
If there is no driver for the family, a simple sysfs entry is created
for the slave device.


W1 device families
------------------------------------------------------------------
Slave devices are handled by a driver written for a family of w1 devices.

A family driver populates a struct w1_family_ops (see w1_family.h) and
registers with the w1 subsystem.

Current family drivers:
w1_therm - (ds18?20 thermal sensor family driver)
    provides temperature reading function which is bound to ->rbin() method
    provides temperature reading function which is bound to ->rbin() method
    of the above w1_family_ops structure.
    of the above w1_family_ops structure.
w1_smem - driver for simple 64bit memory cell provides ID reading

method.
w1_smem - driver for simple 64bit memory cell provides ID reading method.


You can call above methods by reading appropriate sysfs files.
You can call above methods by reading appropriate sysfs files.


What does a w1 master driver need to implement?
------------------------------------------------------------------

The driver for w1 bus master must provide at minimum two functions.

Emulated devices must provide the ability to set the output signal level
(write_bit) and sample the signal level (read_bit).

Devices that support the 1-wire natively must provide the ability to write and
sample a bit (touch_bit) and reset the bus (reset_bus).

Most hardware provides higher-level functions that offload w1 handling.
See struct w1_bus_master definition in w1.h for details.


w1 master sysfs interface
------------------------------------------------------------------
<xx-xxxxxxxxxxxxx> - a directory for a found device. The format is family-serial
bus                - (standard) symlink to the w1 bus
driver             - (standard) symlink to the w1 driver
w1_master_attempts - the number of times a search was attempted
w1_master_max_slave_count
                   - the maximum slaves that may be attached to a master
w1_master_name     - the name of the device (w1_bus_masterX)
w1_master_search   - the number of searches left to do, -1=continual (default)
w1_master_slave_count
                   - the number of slaves found
w1_master_slaves   - the names of the slaves, one per line
w1_master_timeout  - the delay in seconds between searches

If you have a w1 bus that never changes (you don't add or remove devices),
you can set w1_master_search to a positive value to disable searches.


w1 slave sysfs interface
------------------------------------------------------------------
bus                - (standard) symlink to the w1 bus
driver             - (standard) symlink to the w1 driver
name               - the device name, usually the same as the directory name
w1_slave           - (optional) a binary file whose meaning depends on the
                     family driver
+8 −8
Original line number Original line Diff line number Diff line
@@ -30,7 +30,7 @@ config W1_DS9490
	  This support is also available as a module.  If so, the module
	  This support is also available as a module.  If so, the module
	  will be called ds9490r.ko.
	  will be called ds9490r.ko.


config W1_DS9490_BRIDGE
config W1_DS9490R_BRIDGE
	tristate "DS9490R USB <-> W1 transport layer for 1-wire"
	tristate "DS9490R USB <-> W1 transport layer for 1-wire"
	depends on W1_DS9490
	depends on W1_DS9490
	help
	help
+2 −2
Original line number Original line Diff line number Diff line
@@ -83,11 +83,11 @@ static u8 ds9490r_read_byte(unsigned long data)
	return byte;
	return byte;
}
}


static void ds9490r_write_block(unsigned long data, u8 *buf, int len)
static void ds9490r_write_block(unsigned long data, const u8 *buf, int len)
{
{
	struct ds_device *dev = (struct ds_device *)data;
	struct ds_device *dev = (struct ds_device *)data;


	ds_write_block(dev, buf, len);
	ds_write_block(dev, (u8 *)buf, len);
}
}


static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
+270 −276
Original line number Original line Diff line number Diff line
@@ -59,6 +59,19 @@ static pid_t control_thread;
static int control_needs_exit;
static int control_needs_exit;
static DECLARE_COMPLETION(w1_control_complete);
static DECLARE_COMPLETION(w1_control_complete);


/* stuff for the default family */
static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
	return(sprintf(buf, "%s\n", sl->name));
}
static struct w1_family_ops w1_default_fops = {
	.rname = &w1_famdefault_read_name,
};
static struct w1_family w1_default_family = {
	.fops = &w1_default_fops,
};

static int w1_master_match(struct device *dev, struct device_driver *drv)
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
{
	return 1;
	return 1;
@@ -99,6 +112,20 @@ static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
	return sprintf(buf, "No family registered.\n");
	return sprintf(buf, "No family registered.\n");
}
}


static struct device_attribute w1_slave_attribute =
	__ATTR(name, S_IRUGO, w1_default_read_name, NULL);

static struct bin_attribute w1_slave_bin_attribute = {
	.attr = {
		.name = "w1_slave",
		.mode = S_IRUGO,
		.owner = THIS_MODULE,
	},
	.size = W1_SLAVE_DATA_SIZE,
	.read = &w1_default_read_bin,
};


static struct bus_type w1_bus_type = {
static struct bus_type w1_bus_type = {
	.name = "w1",
	.name = "w1",
	.match = w1_master_match,
	.match = w1_master_match,
@@ -119,24 +146,6 @@ struct device w1_device = {
	.release = &w1_master_release
	.release = &w1_master_release
};
};


static struct device_attribute w1_slave_attribute = {
	.attr = {
			.name = "name",
			.mode = S_IRUGO,
			.owner = THIS_MODULE
	},
	.show = &w1_default_read_name,
};

static struct device_attribute w1_slave_attribute_val = {
	.attr = {
			.name = "value",
			.mode = S_IRUGO,
			.owner = THIS_MODULE
	},
	.show = &w1_default_read_name,
};

static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
{
	struct w1_master *md = container_of(dev, struct w1_master, dev);
	struct w1_master *md = container_of(dev, struct w1_master, dev);
@@ -152,6 +161,39 @@ static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_a
	return count;
	return count;
}
}


static ssize_t w1_master_attribute_store_search(struct device * dev,
						struct device_attribute *attr,
						const char * buf, size_t count)
{
	struct w1_master *md = container_of(dev, struct w1_master, dev);

	if (down_interruptible (&md->mutex))
		return -EBUSY;

	md->search_count = simple_strtol(buf, NULL, 0);

	up(&md->mutex);

	return count;
}

static ssize_t w1_master_attribute_show_search(struct device *dev,
					       struct device_attribute *attr,
					       char *buf)
{
	struct w1_master *md = container_of(dev, struct w1_master, dev);
	ssize_t count;

	if (down_interruptible (&md->mutex))
		return -EBUSY;

	count = sprintf(buf, "%d\n", md->search_count);

	up(&md->mutex);

	return count;
}

static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
{
{
	struct w1_master *md = container_of(dev, struct w1_master, dev);
	struct w1_master *md = container_of(dev, struct w1_master, dev);
@@ -216,7 +258,6 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
}
}


static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)

{
{
	struct w1_master *md = container_of(dev, struct w1_master, dev);
	struct w1_master *md = container_of(dev, struct w1_master, dev);
	int c = PAGE_SIZE;
	int c = PAGE_SIZE;
@@ -242,73 +283,52 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device
	return PAGE_SIZE - c;
	return PAGE_SIZE - c;
}
}


static struct device_attribute w1_master_attribute_slaves = {
#define W1_MASTER_ATTR_RO(_name, _mode)				\
	.attr = {
	struct device_attribute w1_master_attribute_##_name =	\
 			.name = "w1_master_slaves",
		__ATTR(w1_master_##_name, _mode,		\
			.mode = S_IRUGO,
		       w1_master_attribute_show_##_name, NULL)
			.owner = THIS_MODULE,

	},
#define W1_MASTER_ATTR_RW(_name, _mode)				\
 	.show = &w1_master_attribute_show_slaves,
	struct device_attribute w1_master_attribute_##_name =	\
};
		__ATTR(w1_master_##_name, _mode,		\
static struct device_attribute w1_master_attribute_slave_count = {
		       w1_master_attribute_show_##_name,	\
	.attr = {
		       w1_master_attribute_store_##_name)
			.name = "w1_master_slave_count",

			.mode = S_IRUGO,
static W1_MASTER_ATTR_RO(name, S_IRUGO);
			.owner = THIS_MODULE
static W1_MASTER_ATTR_RO(slaves, S_IRUGO);
	},
static W1_MASTER_ATTR_RO(slave_count, S_IRUGO);
	.show = &w1_master_attribute_show_slave_count,
static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO);
};
static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
static struct device_attribute w1_master_attribute_attempts = {
static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
	.attr = {
static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
			.name = "w1_master_attempts",
static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
			.mode = S_IRUGO,

			.owner = THIS_MODULE
static struct attribute *w1_master_default_attrs[] = {
	},
	&w1_master_attribute_name.attr,
	.show = &w1_master_attribute_show_attempts,
	&w1_master_attribute_slaves.attr,
};
	&w1_master_attribute_slave_count.attr,
static struct device_attribute w1_master_attribute_max_slave_count = {
	&w1_master_attribute_max_slave_count.attr,
	.attr = {
	&w1_master_attribute_attempts.attr,
			.name = "w1_master_max_slave_count",
	&w1_master_attribute_timeout.attr,
			.mode = S_IRUGO,
	&w1_master_attribute_pointer.attr,
			.owner = THIS_MODULE
	&w1_master_attribute_search.attr,
	},
	NULL
	.show = &w1_master_attribute_show_max_slave_count,
};
static struct device_attribute w1_master_attribute_timeout = {
	.attr = {
			.name = "w1_master_timeout",
			.mode = S_IRUGO,
			.owner = THIS_MODULE
	},
	.show = &w1_master_attribute_show_timeout,
};
static struct device_attribute w1_master_attribute_pointer = {
	.attr = {
			.name = "w1_master_pointer",
			.mode = S_IRUGO,
			.owner = THIS_MODULE
	},
	.show = &w1_master_attribute_show_pointer,
};
static struct device_attribute w1_master_attribute_name = {
	.attr = {
			.name = "w1_master_name",
			.mode = S_IRUGO,
			.owner = THIS_MODULE
	},
	.show = &w1_master_attribute_show_name,
};
};


static struct bin_attribute w1_slave_bin_attribute = {
static struct attribute_group w1_master_defattr_group = {
	.attr = {
	.attrs = w1_master_default_attrs,
		 	.name = "w1_slave",
		 	.mode = S_IRUGO,
			.owner = THIS_MODULE,
	},
	.size = W1_SLAVE_DATA_SIZE,
	.read = &w1_default_read_bin,
};
};


int w1_create_master_attributes(struct w1_master *master)
{
	return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
}

void w1_destroy_master_attributes(struct w1_master *master)
{
	sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
}

static int __w1_attach_slave_device(struct w1_slave *sl)
static int __w1_attach_slave_device(struct w1_slave *sl)
{
{
	int err;
	int err;
@@ -340,12 +360,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl)


	memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
	memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
	memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
	memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
	memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));


	sl->attr_bin.read = sl->family->fops->rbin;
	sl->attr_bin.read = sl->family->fops->rbin;
	sl->attr_name.show = sl->family->fops->rname;
	sl->attr_name.show = sl->family->fops->rname;
	sl->attr_val.show = sl->family->fops->rval;
	sl->attr_val.attr.name = sl->family->fops->rvalname;


	err = device_create_file(&sl->dev, &sl->attr_name);
	err = device_create_file(&sl->dev, &sl->attr_name);
	if (err < 0) {
	if (err < 0) {
@@ -356,26 +373,17 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
		return err;
		return err;
	}
	}


	err = device_create_file(&sl->dev, &sl->attr_val);
	if ( sl->attr_bin.read ) {
	if (err < 0) {
		dev_err(&sl->dev,
			 "sysfs file creation for [%s] failed. err=%d\n",
			 sl->dev.bus_id, err);
		device_remove_file(&sl->dev, &sl->attr_name);
		device_unregister(&sl->dev);
		return err;
	}

		err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
		err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
		if (err < 0) {
		if (err < 0) {
			dev_err(&sl->dev,
			dev_err(&sl->dev,
				"sysfs file creation for [%s] failed. err=%d\n",
				"sysfs file creation for [%s] failed. err=%d\n",
				sl->dev.bus_id, err);
				sl->dev.bus_id, err);
			device_remove_file(&sl->dev, &sl->attr_name);
			device_remove_file(&sl->dev, &sl->attr_name);
		device_remove_file(&sl->dev, &sl->attr_val);
			device_unregister(&sl->dev);
			device_unregister(&sl->dev);
			return err;
			return err;
		}
		}
	}


	list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
	list_add_tail(&sl->w1_slave_entry, &sl->master->slist);


@@ -410,12 +418,10 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
	spin_lock(&w1_flock);
	spin_lock(&w1_flock);
	f = w1_family_registered(rn->family);
	f = w1_family_registered(rn->family);
	if (!f) {
	if (!f) {
		spin_unlock(&w1_flock);
		f= &w1_default_family;
		dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
		dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
			  rn->family, rn->family,
			  rn->family, rn->family,
			  (unsigned long long)rn->id, rn->crc);
			  (unsigned long long)rn->id, rn->crc);
		kfree(sl);
		return -ENODEV;
	}
	}
	__w1_family_get(f);
	__w1_family_get(f);
	spin_unlock(&w1_flock);
	spin_unlock(&w1_flock);
@@ -456,12 +462,15 @@ static void w1_slave_detach(struct w1_slave *sl)
			flush_signals(current);
			flush_signals(current);
	}
	}


	if ( sl->attr_bin.read ) {
		sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
		sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
	}
	device_remove_file(&sl->dev, &sl->attr_name);
	device_remove_file(&sl->dev, &sl->attr_name);
	device_remove_file(&sl->dev, &sl->attr_val);
	device_unregister(&sl->dev);
	device_unregister(&sl->dev);
	w1_family_put(sl->family);
	w1_family_put(sl->family);


	sl->master->slave_count--;

	memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
	memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
	msg.type = W1_SLAVE_REMOVE;
	msg.type = W1_SLAVE_REMOVE;
	w1_netlink_send(sl->master, &msg);
	w1_netlink_send(sl->master, &msg);
@@ -472,7 +481,7 @@ static struct w1_master *w1_search_master(unsigned long data)
	struct w1_master *dev;
	struct w1_master *dev;
	int found = 0;
	int found = 0;


	spin_lock_irq(&w1_mlock);
	spin_lock_bh(&w1_mlock);
	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
		if (dev->bus_master->data == data) {
		if (dev->bus_master->data == data) {
			found = 1;
			found = 1;
@@ -480,12 +489,26 @@ static struct w1_master *w1_search_master(unsigned long data)
			break;
			break;
		}
		}
	}
	}
	spin_unlock_irq(&w1_mlock);
	spin_unlock_bh(&w1_mlock);


	return (found)?dev:NULL;
	return (found)?dev:NULL;
}
}


void w1_slave_found(unsigned long data, u64 rn)
void w1_reconnect_slaves(struct w1_family *f)
{
	struct w1_master *dev;

	spin_lock_bh(&w1_mlock);
	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
		dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
				dev->name, f->fid);
		set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
	}
	spin_unlock_bh(&w1_mlock);
}


static void w1_slave_found(unsigned long data, u64 rn)
{
{
	int slave_count;
	int slave_count;
	struct w1_slave *sl;
	struct w1_slave *sl;
@@ -513,8 +536,7 @@ void w1_slave_found(unsigned long data, u64 rn)
		    sl->reg_num.crc == tmp->crc) {
		    sl->reg_num.crc == tmp->crc) {
			set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
			set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
			break;
			break;
		}
		} else if (sl->reg_num.family == tmp->family) {
		else if (sl->reg_num.family == tmp->family) {
			family_found = 1;
			family_found = 1;
			break;
			break;
		}
		}
@@ -532,26 +554,39 @@ void w1_slave_found(unsigned long data, u64 rn)
	atomic_dec(&dev->refcnt);
	atomic_dec(&dev->refcnt);
}
}


void w1_search(struct w1_master *dev)
/**
 * Performs a ROM Search & registers any devices found.
 * The 1-wire search is a simple binary tree search.
 * For each bit of the address, we read two bits and write one bit.
 * The bit written will put to sleep all devies that don't match that bit.
 * When the two reads differ, the direction choice is obvious.
 * When both bits are 0, we must choose a path to take.
 * When we can scan all 64 bits without having to choose a path, we are done.
 *
 * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
 *
 * @dev        The master device to search
 * @cb         Function to call when a device is found
 */
void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
{
{
	u64 last, rn, tmp;
	u64 last_rn, rn, tmp64;
	int i, count = 0;
	int i, slave_count = 0;
	int last_family_desc, last_zero, last_device;
	int last_zero, last_device;
	int search_bit, id_bit, comp_bit, desc_bit;
	int search_bit, desc_bit;
	u8  triplet_ret = 0;


	search_bit = id_bit = comp_bit = 0;
	search_bit = 0;
	rn = tmp = last = 0;
	rn = last_rn = 0;
	last_device = last_zero = last_family_desc = 0;
	last_device = 0;
	last_zero = -1;


	desc_bit = 64;
	desc_bit = 64;


	while (!(id_bit && comp_bit) && !last_device
	while ( !last_device && (slave_count++ < dev->max_slave_count) ) {
		&& count++ < dev->max_slave_count) {
		last_rn = rn;
		last = rn;
		rn = 0;
		rn = 0;


		last_family_desc = 0;

		/*
		/*
		 * Reset bus and all 1-wire device state machines
		 * Reset bus and all 1-wire device state machines
		 * so they can respond to our requests.
		 * so they can respond to our requests.
@@ -563,94 +598,46 @@ void w1_search(struct w1_master *dev)
			break;
			break;
		}
		}


#if 1
		/* Start the search */
		w1_write_8(dev, W1_SEARCH);
		w1_write_8(dev, W1_SEARCH);
		for (i = 0; i < 64; ++i) {
		for (i = 0; i < 64; ++i) {
			/*
			/* Determine the direction/search bit */
			 * Read 2 bits from bus.
			 * All who don't sleep must send ID bit and COMPLEMENT ID bit.
			 * They actually are ANDed between all senders.
			 */
			id_bit = w1_touch_bit(dev, 1);
			comp_bit = w1_touch_bit(dev, 1);

			if (id_bit && comp_bit)
				break;

			if (id_bit == 0 && comp_bit == 0) {
			if (i == desc_bit)
			if (i == desc_bit)
					search_bit = 1;
				search_bit = 1;	  /* took the 0 path last time, so take the 1 path */
			else if (i > desc_bit)
			else if (i > desc_bit)
					search_bit = 0;
				search_bit = 0;	  /* take the 0 path on the next branch */
			else
			else
					search_bit = ((last >> i) & 0x1);
				search_bit = ((last_rn >> i) & 0x1);


				if (search_bit == 0) {
			/** Read two bits and write one bit */
					last_zero = i;
			triplet_ret = w1_triplet(dev, search_bit);
					if (last_zero < 9)
						last_family_desc = last_zero;
				}

			}
			else
				search_bit = id_bit;


			tmp = search_bit;
			/* quit if no device responded */
			rn |= (tmp << i);
			if ( (triplet_ret & 0x03) == 0x03 )
				break;


			/*
			/* If both directions were valid, and we took the 0 path... */
			 * Write 1 bit to bus
			if (triplet_ret == 0)
			 * and make all who don't have "search_bit" in "i"'th position
				last_zero = i;
			 * in it's registration number sleep.
			 */
			if (dev->bus_master->touch_bit)
				w1_touch_bit(dev, search_bit);
			else
				w1_write_bit(dev, search_bit);


			/* extract the direction taken & update the device number */
			tmp64 = (triplet_ret >> 2);
			rn |= (tmp64 << i);
		}
		}
#endif


		if (desc_bit == last_zero)
		if ( (triplet_ret & 0x03) != 0x03 ) {
			if ( (desc_bit == last_zero) || (last_zero < 0))
				last_device = 1;
				last_device = 1;

			desc_bit = last_zero;
			desc_bit = last_zero;
	
			cb(dev->bus_master->data, rn);
		w1_slave_found(dev->bus_master->data, rn);
		}
		}
	}
	}

int w1_create_master_attributes(struct w1_master *dev)
{
	if (	device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
		device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
		device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
		device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
		device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
		device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
		device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
		return -EINVAL;

	return 0;
}

void w1_destroy_master_attributes(struct w1_master *dev)
{
	device_remove_file(&dev->dev, &w1_master_attribute_slaves);
	device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
	device_remove_file(&dev->dev, &w1_master_attribute_attempts);
	device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
	device_remove_file(&dev->dev, &w1_master_attribute_timeout);
	device_remove_file(&dev->dev, &w1_master_attribute_pointer);
	device_remove_file(&dev->dev, &w1_master_attribute_name);
}
}



static int w1_control(void *data)
int w1_control(void *data)
{
{
	struct w1_slave *sl;
	struct w1_slave *sl, *sln;
	struct w1_master *dev;
	struct w1_master *dev, *n;
	struct list_head *ent, *ment, *n, *mn;
	int err, have_to_wait = 0;
	int err, have_to_wait = 0;


	daemonize("w1_control");
	daemonize("w1_control");
@@ -665,10 +652,8 @@ int w1_control(void *data)
		if (signal_pending(current))
		if (signal_pending(current))
			flush_signals(current);
			flush_signals(current);


		list_for_each_safe(ment, mn, &w1_masters) {
		list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
			dev = list_entry(ment, struct w1_master, w1_master_entry);
			if (!control_needs_exit && !dev->flags)

			if (!control_needs_exit && !dev->need_exit)
				continue;
				continue;
			/*
			/*
			 * Little race: we can create thread but not set the flag.
			 * Little race: we can create thread but not set the flag.
@@ -679,12 +664,8 @@ int w1_control(void *data)
				continue;
				continue;
			}
			}


			spin_lock(&w1_mlock);
			list_del(&dev->w1_master_entry);
			spin_unlock(&w1_mlock);

			if (control_needs_exit) {
			if (control_needs_exit) {
				dev->need_exit = 1;
				set_bit(W1_MASTER_NEED_EXIT, &dev->flags);


				err = kill_proc(dev->kpid, SIGTERM, 1);
				err = kill_proc(dev->kpid, SIGTERM, 1);
				if (err)
				if (err)
@@ -693,24 +674,42 @@ int w1_control(void *data)
						 dev->kpid);
						 dev->kpid);
			}
			}


			if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
				wait_for_completion(&dev->dev_exited);
				wait_for_completion(&dev->dev_exited);
				spin_lock_bh(&w1_mlock);
				list_del(&dev->w1_master_entry);
				spin_unlock_bh(&w1_mlock);


			list_for_each_safe(ent, n, &dev->slist) {
				list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
				sl = list_entry(ent, struct w1_slave, w1_slave_entry);

				if (!sl)
					dev_warn(&dev->dev,
						  "%s: slave entry is NULL.\n",
						  __func__);
				else {
					list_del(&sl->w1_slave_entry);
					list_del(&sl->w1_slave_entry);


					w1_slave_detach(sl);
					w1_slave_detach(sl);
					kfree(sl);
					kfree(sl);
				}
				}
			}
				w1_destroy_master_attributes(dev);
				w1_destroy_master_attributes(dev);
				atomic_dec(&dev->refcnt);
				atomic_dec(&dev->refcnt);
				continue;
			}

			if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
				dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
				down(&dev->mutex);
				list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
					if (sl->family->fid == W1_FAMILY_DEFAULT) {
						struct w1_reg_num rn;
						list_del(&sl->w1_slave_entry);
						w1_slave_detach(sl);

						memcpy(&rn, &sl->reg_num, sizeof(rn));

						kfree(sl);

						w1_attach_slave_device(dev, &rn);
					}
				}
				clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
				up(&dev->mutex);
			}
		}
		}
	}
	}


@@ -720,51 +719,50 @@ int w1_control(void *data)
int w1_process(void *data)
int w1_process(void *data)
{
{
	struct w1_master *dev = (struct w1_master *) data;
	struct w1_master *dev = (struct w1_master *) data;
	struct list_head *ent, *n;
	struct w1_slave *sl, *sln;
	struct w1_slave *sl;


	daemonize("%s", dev->name);
	daemonize("%s", dev->name);
	allow_signal(SIGTERM);
	allow_signal(SIGTERM);


	while (!dev->need_exit) {
	while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
		try_to_freeze(PF_FREEZE);
		try_to_freeze(PF_FREEZE);
		msleep_interruptible(w1_timeout * 1000);
		msleep_interruptible(w1_timeout * 1000);


		if (signal_pending(current))
		if (signal_pending(current))
			flush_signals(current);
			flush_signals(current);


		if (dev->need_exit)
		if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
			break;
			break;


		if (!dev->initialized)
		if (!dev->initialized)
			continue;
			continue;


		if (down_interruptible(&dev->mutex))
		if (dev->search_count == 0)
			continue;
			continue;


		list_for_each_safe(ent, n, &dev->slist) {
		if (down_interruptible(&dev->mutex))
			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
			continue;


			if (sl)
		list_for_each_entry(sl, &dev->slist, w1_slave_entry)
			clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
			clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
		}


		w1_search_devices(dev, w1_slave_found);
		w1_search_devices(dev, w1_slave_found);


		list_for_each_safe(ent, n, &dev->slist) {
		list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
			if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {

			if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
				list_del (&sl->w1_slave_entry);
				list_del (&sl->w1_slave_entry);


				w1_slave_detach (sl);
				w1_slave_detach (sl);
				kfree (sl);
				kfree (sl);


				dev->slave_count--;
				dev->slave_count--;
			}
			} else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
			else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
				sl->ttl = dev->slave_ttl;
				sl->ttl = dev->slave_ttl;
		}
		}

		if (dev->search_count > 0)
			dev->search_count--;

		up(&dev->mutex);
		up(&dev->mutex);
	}
	}


@@ -774,7 +772,7 @@ int w1_process(void *data)
	return 0;
	return 0;
}
}


int w1_init(void)
static int w1_init(void)
{
{
	int retval;
	int retval;


@@ -814,18 +812,14 @@ int w1_init(void)
	return retval;
	return retval;
}
}


void w1_fini(void)
static void w1_fini(void)
{
{
	struct w1_master *dev;
	struct w1_master *dev;
	struct list_head *ent, *n;


	list_for_each_safe(ent, n, &w1_masters) {
	list_for_each_entry(dev, &w1_masters, w1_master_entry)
		dev = list_entry(ent, struct w1_master, w1_master_entry);
		__w1_remove_master_device(dev);
		__w1_remove_master_device(dev);
	}


	control_needs_exit = 1;
	control_needs_exit = 1;

	wait_for_completion(&w1_control_complete);
	wait_for_completion(&w1_control_complete);


	driver_unregister(&w1_driver);
	driver_unregister(&w1_driver);
+82 −31

File changed.

Preview size limit exceeded, changes collapsed.

Loading