From 7f772ed8df27c6941952452330c618512389c4c7 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 11 Aug 2005 13:20:07 +0400 Subject: [PATCH] w1: hotplug support. Here is W1 hotplug in addition to netlink notifications. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 11 deletions(-) (limited to 'drivers/w1/w1.c') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 0bbf029b1ef..9c7777b6bbd 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -125,27 +125,41 @@ static struct bin_attribute w1_slave_bin_attribute = { .read = &w1_default_read_bin, }; +static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); static struct bus_type w1_bus_type = { .name = "w1", .match = w1_master_match, + .hotplug = w1_hotplug, }; -struct device_driver w1_driver = { - .name = "w1_driver", +struct device_driver w1_master_driver = { + .name = "w1_master_driver", .bus = &w1_bus_type, .probe = w1_master_probe, .remove = w1_master_remove, }; -struct device w1_device = { +struct device w1_master_device = { .parent = NULL, .bus = &w1_bus_type, .bus_id = "w1 bus master", - .driver = &w1_driver, + .driver = &w1_master_driver, .release = &w1_master_release }; +struct device_driver w1_slave_driver = { + .name = "w1_slave_driver", + .bus = &w1_bus_type, +}; + +struct device w1_slave_device = { + .parent = NULL, + .bus = &w1_bus_type, + .bus_id = "w1 bus slave", + .driver = &w1_slave_driver, +}; + 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); @@ -329,12 +343,55 @@ void w1_destroy_master_attributes(struct w1_master *master) sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); } +#ifdef CONFIG_HOTPLUG +static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +{ + struct w1_master *md = NULL; + struct w1_slave *sl = NULL; + char *event_owner, *name; + int err, cur_index=0, cur_len=0; + + if (dev->driver == &w1_master_driver) { + md = container_of(dev, struct w1_master, dev); + event_owner = "master"; + name = md->name; + } else if (dev->driver == &w1_slave_driver) { + sl = container_of(dev, struct w1_slave, dev); + event_owner = "slave"; + name = sl->name; + } else { + dev_dbg(dev, "Unknown hotplug event.\n"); + return -EINVAL; + } + + dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id); + + if (dev->driver != &w1_slave_driver || !sl) + return 0; + + err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family); + if (err) + return err; + + err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024llX", sl->reg_num.id); + if (err) + return err; + + return 0; +}; +#else +static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +{ + return 0; +} +#endif + static int __w1_attach_slave_device(struct w1_slave *sl) { int err; sl->dev.parent = &sl->master->dev; - sl->dev.driver = sl->master->driver; + sl->dev.driver = &w1_slave_driver; sl->dev.bus = &w1_bus_type; sl->dev.release = &w1_slave_release; @@ -507,7 +564,6 @@ void w1_reconnect_slaves(struct w1_family *f) spin_unlock_bh(&w1_mlock); } - static void w1_slave_found(unsigned long data, u64 rn) { int slave_count; @@ -783,7 +839,7 @@ static int w1_init(void) goto err_out_exit_init; } - retval = driver_register(&w1_driver); + retval = driver_register(&w1_master_driver); if (retval) { printk(KERN_ERR "Failed to register master driver. err=%d.\n", @@ -791,18 +847,29 @@ static int w1_init(void) goto err_out_bus_unregister; } + retval = driver_register(&w1_slave_driver); + if (retval) { + printk(KERN_ERR + "Failed to register master driver. err=%d.\n", + retval); + goto err_out_master_unregister; + } + control_thread = kernel_thread(&w1_control, NULL, 0); if (control_thread < 0) { printk(KERN_ERR "Failed to create control thread. err=%d\n", control_thread); retval = control_thread; - goto err_out_driver_unregister; + goto err_out_slave_unregister; } return 0; -err_out_driver_unregister: - driver_unregister(&w1_driver); +err_out_slave_unregister: + driver_unregister(&w1_slave_driver); + +err_out_master_unregister: + driver_unregister(&w1_master_driver); err_out_bus_unregister: bus_unregister(&w1_bus_type); @@ -821,7 +888,8 @@ static void w1_fini(void) control_needs_exit = 1; wait_for_completion(&w1_control_complete); - driver_unregister(&w1_driver); + driver_unregister(&w1_slave_driver); + driver_unregister(&w1_master_driver); bus_unregister(&w1_bus_type); } -- cgit v1.2.3-70-g09d2 From 5e8eb8501212eb92826ccf191f9ca8c186f531c3 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 11 Aug 2005 13:45:54 +0400 Subject: [PATCH] w1: Fixed 64bit compilation warning. Fixed 64bit compilation warning. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/w1/w1.c') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 9c7777b6bbd..b2fe0f7b0b7 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -373,7 +373,7 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe if (err) return err; - err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024llX", sl->reg_num.id); + err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id); if (err) return err; -- cgit v1.2.3-70-g09d2 From db2d0008de519c5db6baec45f7831e08790301cf Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 11 Aug 2005 17:27:49 +0400 Subject: [PATCH] w1: Added inline functions on top of container_of(). Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 22 ++++++++++------------ drivers/w1/w1.h | 15 +++++++++++++++ drivers/w1/w1_smem.c | 6 ++---- drivers/w1/w1_therm.c | 6 ++---- 4 files changed, 29 insertions(+), 20 deletions(-) (limited to 'drivers/w1/w1.c') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index b2fe0f7b0b7..39888af6d33 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -89,15 +89,13 @@ static int w1_master_remove(struct device *dev) static void w1_master_release(struct device *dev) { - struct w1_master *md = container_of(dev, struct w1_master, dev); - + struct w1_master *md = dev_to_w1_master(dev); complete(&md->dev_released); } static void w1_slave_release(struct device *dev) { - struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - + struct w1_slave *sl = dev_to_w1_slave(dev); complete(&sl->dev_released); } @@ -162,7 +160,7 @@ struct device w1_slave_device = { 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 = dev_to_w1_master(dev); ssize_t count; if (down_interruptible (&md->mutex)) @@ -179,7 +177,7 @@ 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); + struct w1_master *md = dev_to_w1_master(dev); if (down_interruptible (&md->mutex)) return -EBUSY; @@ -195,7 +193,7 @@ 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); + struct w1_master *md = dev_to_w1_master(dev); ssize_t count; if (down_interruptible (&md->mutex)) @@ -210,7 +208,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev, 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 = dev_to_w1_master(dev); ssize_t count; if (down_interruptible(&md->mutex)) @@ -231,7 +229,7 @@ static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct devic static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_master *md = container_of(dev, struct w1_master, dev); + struct w1_master *md = dev_to_w1_master(dev); ssize_t count; if (down_interruptible(&md->mutex)) @@ -245,7 +243,7 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_master *md = container_of(dev, struct w1_master, dev); + struct w1_master *md = dev_to_w1_master(dev); ssize_t count; if (down_interruptible(&md->mutex)) @@ -259,7 +257,7 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_master *md = container_of(dev, struct w1_master, dev); + struct w1_master *md = dev_to_w1_master(dev); ssize_t count; if (down_interruptible(&md->mutex)) @@ -273,7 +271,7 @@ 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) { - struct w1_master *md = container_of(dev, struct w1_master, dev); + struct w1_master *md = dev_to_w1_master(dev); int c = PAGE_SIZE; if (down_interruptible(&md->mutex)) diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 4f0a986e33e..f8308266d8d 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -191,6 +191,21 @@ struct w1_master int w1_create_master_attributes(struct w1_master *); void w1_search(struct w1_master *dev, w1_slave_found_callback cb); +static inline struct w1_slave* dev_to_w1_slave(struct device *dev) +{ + return container_of(dev, struct w1_slave, dev); +} + +static inline struct w1_slave* kobj_to_w1_slave(struct kobject *kobj) +{ + return dev_to_w1_slave(container_of(kobj, struct device, kobj)); +} + +static inline struct w1_master* dev_to_w1_master(struct device *dev) +{ + return container_of(dev, struct w1_master, dev); +} + #endif /* __KERNEL__ */ #endif /* __W1_H */ diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c index 70d2d469963..2b6580c7e95 100644 --- a/drivers/w1/w1_smem.c +++ b/drivers/w1/w1_smem.c @@ -46,15 +46,13 @@ static struct w1_family_ops w1_smem_fops = { static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - + struct w1_slave *sl = dev_to_w1_slave(dev); return sprintf(buf, "%s\n", sl->name); } static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj), - struct w1_slave, dev); + struct w1_slave *sl = kobj_to_w1_slave(kobj); int i; atomic_inc(&sl->refcnt); diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c index 165526c9360..2259f3d851f 100644 --- a/drivers/w1/w1_therm.c +++ b/drivers/w1/w1_therm.c @@ -92,8 +92,7 @@ static struct w1_therm_family_converter w1_therm_families[] = { static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_slave *sl = container_of(dev, struct w1_slave, dev); - + struct w1_slave *sl = dev_to_w1_slave(dev); return sprintf(buf, "%s\n", sl->name); } @@ -148,8 +147,7 @@ static int w1_therm_check_rom(u8 rom[9]) static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj), - struct w1_slave, dev); + struct w1_slave *sl = kobj_to_w1_slave(kobj); struct w1_master *dev = sl->master; u8 rom[9], crc, verdict; int i, max_trying = 10; -- cgit v1.2.3-70-g09d2 From d2a4ef6a0ce4d841293b49bf2cdc17a0ebfaaf9d Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 11 Aug 2005 17:27:50 +0400 Subject: [PATCH] w1: Added add/remove slave callbacks. Patch is based on work from Ben Gardner Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 121 +++++++++++++++++++++++++++---------------------- drivers/w1/w1.h | 3 -- drivers/w1/w1_family.c | 11 ----- drivers/w1/w1_family.h | 6 ++- drivers/w1/w1_smem.c | 47 ------------------- drivers/w1/w1_therm.c | 32 +++++++++---- 6 files changed, 94 insertions(+), 126 deletions(-) (limited to 'drivers/w1/w1.c') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 39888af6d33..e592ca2edd4 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -59,19 +59,6 @@ static pid_t control_thread; static int control_needs_exit; 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) { return 1; @@ -99,30 +86,47 @@ static void w1_slave_release(struct device *dev) complete(&sl->dev_released); } -static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "No family registered.\n"); + struct w1_slave *sl = dev_to_w1_slave(dev); + + return sprintf(buf, "%s\n", sl->name); } -static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) { - return sprintf(buf, "No family registered.\n"); -} + struct w1_slave *sl = kobj_to_w1_slave(kobj); -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, + atomic_inc(&sl->refcnt); + if (off > 8) { + count = 0; + } else { + if (off + count > 8) + count = 8 - off; + + memcpy(buf, (u8 *)&sl->reg_num, count); + } + atomic_dec(&sl->refcnt); + + return count; + } + +static struct device_attribute w1_slave_attr_name = + __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); + +static struct bin_attribute w1_slave_attr_bin_id = { + .attr = { + .name = "id", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = 8, + .read = w1_slave_read_id, }; +/* Default family */ +static struct w1_family w1_default_family; + static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); static struct bus_type w1_bus_type = { @@ -413,36 +417,44 @@ static int __w1_attach_slave_device(struct w1_slave *sl) return err; } - memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin)); - memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name)); - - sl->attr_bin.read = sl->family->fops->rbin; - sl->attr_name.show = sl->family->fops->rname; + /* Create "name" entry */ + err = device_create_file(&sl->dev, &w1_slave_attr_name); + if (err < 0) { + dev_err(&sl->dev, + "sysfs file creation for [%s] failed. err=%d\n", + sl->dev.bus_id, err); + goto out_unreg; + } - err = device_create_file(&sl->dev, &sl->attr_name); + /* Create "id" entry */ + err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); if (err < 0) { dev_err(&sl->dev, "sysfs file creation for [%s] failed. err=%d\n", sl->dev.bus_id, err); - device_unregister(&sl->dev); - return err; + goto out_rem1; } - if ( sl->attr_bin.read ) { - err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin); - 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; - } + /* if the family driver needs to initialize something... */ + if (sl->family->fops && sl->family->fops->add_slave && + ((err = sl->family->fops->add_slave(sl)) < 0)) { + dev_err(&sl->dev, + "sysfs file creation for [%s] failed. err=%d\n", + sl->dev.bus_id, err); + goto out_rem2; } list_add_tail(&sl->w1_slave_entry, &sl->master->slist); return 0; + +out_rem2: + sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); +out_rem1: + device_remove_file(&sl->dev, &w1_slave_attr_name); +out_unreg: + device_unregister(&sl->dev); + return err; } static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) @@ -517,10 +529,11 @@ static void w1_slave_detach(struct w1_slave *sl) flush_signals(current); } - if ( sl->attr_bin.read ) { - sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin); - } - device_remove_file(&sl->dev, &sl->attr_name); + if (sl->family->fops && sl->family->fops->remove_slave) + sl->family->fops->remove_slave(sl); + + sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); + device_remove_file(&sl->dev, &w1_slave_attr_name); device_unregister(&sl->dev); w1_family_put(sl->family); @@ -805,8 +818,8 @@ int w1_process(void *data) if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { list_del (&sl->w1_slave_entry); - w1_slave_detach (sl); - kfree (sl); + w1_slave_detach(sl); + kfree(sl); dev->slave_count--; } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index f8308266d8d..13edc82bc7d 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -77,9 +77,6 @@ struct w1_slave struct w1_family *family; struct device dev; struct completion dev_released; - - struct bin_attribute attr_bin; - struct device_attribute attr_name; }; typedef void (* w1_slave_found_callback)(unsigned long, u64); diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c index 02eee57d3c0..88c517a4c17 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c @@ -29,23 +29,12 @@ DEFINE_SPINLOCK(w1_flock); static LIST_HEAD(w1_families); extern void w1_reconnect_slaves(struct w1_family *f); -static int w1_check_family(struct w1_family *f) -{ - if (!f->fops->rname || !f->fops->rbin) - return -EINVAL; - - return 0; -} - int w1_register_family(struct w1_family *newf) { struct list_head *ent, *n; struct w1_family *f; int ret = 0; - if (w1_check_family(newf)) - return -EINVAL; - spin_lock(&w1_flock); list_for_each_safe(ent, n, &w1_families) { f = list_entry(ent, struct w1_family, family_entry); diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index b26da01bbc3..0a564a0a69a 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h @@ -35,10 +35,12 @@ #define MAXNAMELEN 32 +struct w1_slave; + struct w1_family_ops { - ssize_t (* rname)(struct device *, struct device_attribute *, char *); - ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t); + int (* add_slave)(struct w1_slave *); + void (* remove_slave)(struct w1_slave *); }; struct w1_family diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c index 2b6580c7e95..e3209d0aca9 100644 --- a/drivers/w1/w1_smem.c +++ b/drivers/w1/w1_smem.c @@ -36,59 +36,12 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Evgeniy Polyakov "); MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); -static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *); -static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t); - -static struct w1_family_ops w1_smem_fops = { - .rname = &w1_smem_read_name, - .rbin = &w1_smem_read_bin, -}; - -static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w1_slave *sl = dev_to_w1_slave(dev); - return sprintf(buf, "%s\n", sl->name); -} - -static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) -{ - struct w1_slave *sl = kobj_to_w1_slave(kobj); - int i; - - atomic_inc(&sl->refcnt); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out_dec; - } - - if (off > W1_SLAVE_DATA_SIZE) { - count = 0; - goto out; - } - if (off + count > W1_SLAVE_DATA_SIZE) { - count = 0; - goto out; - } - for (i = 0; i < 8; ++i) - count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]); - count += sprintf(buf + count, "\n"); - -out: - up(&sl->master->mutex); -out_dec: - atomic_dec(&sl->refcnt); - - return count; -} - static struct w1_family w1_smem_family_01 = { .fid = W1_FAMILY_SMEM_01, - .fops = &w1_smem_fops, }; static struct w1_family w1_smem_family_81 = { .fid = W1_FAMILY_SMEM_81, - .fops = &w1_smem_fops, }; static int __init w1_smem_init(void) diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c index 2ed0e0f4826..4577df3cfc4 100644 --- a/drivers/w1/w1_therm.c +++ b/drivers/w1/w1_therm.c @@ -42,12 +42,31 @@ static u8 bad_roms[][9] = { {} }; -static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *); static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); +static struct bin_attribute w1_therm_bin_attr = { + .attr = { + .name = "w1_slave", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = W1_SLAVE_DATA_SIZE, + .read = w1_therm_read_bin, +}; + +static int w1_therm_add_slave(struct w1_slave *sl) +{ + return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); +} + +static void w1_therm_remove_slave(struct w1_slave *sl) +{ + sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); +} + static struct w1_family_ops w1_therm_fops = { - .rname = &w1_therm_read_name, - .rbin = &w1_therm_read_bin, + .add_slave = w1_therm_add_slave, + .remove_slave = w1_therm_remove_slave, }; static struct w1_family w1_therm_family_DS18S20 = { @@ -59,6 +78,7 @@ static struct w1_family w1_therm_family_DS18B20 = { .fid = W1_THERM_DS18B20, .fops = &w1_therm_fops, }; + static struct w1_family w1_therm_family_DS1822 = { .fid = W1_THERM_DS1822, .fops = &w1_therm_fops, @@ -90,12 +110,6 @@ static struct w1_therm_family_converter w1_therm_families[] = { }, }; -static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w1_slave *sl = dev_to_w1_slave(dev); - return sprintf(buf, "%s\n", sl->name); -} - static inline int w1_DS18B20_convert_temp(u8 rom[9]) { int t = (rom[1] << 8) | rom[0]; -- cgit v1.2.3-70-g09d2 From 3aca692d3ec7cf89da4575f598e41f74502b22d7 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 11 Aug 2005 17:27:50 +0400 Subject: [PATCH] w1: Detouching bug fixed. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 93 ++++++++++++++++++++++++++++------------------------- drivers/w1/w1.h | 3 +- drivers/w1/w1_int.c | 6 +--- 3 files changed, 51 insertions(+), 51 deletions(-) (limited to 'drivers/w1/w1.c') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index e592ca2edd4..4e98ab1aa2f 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -45,10 +45,12 @@ MODULE_AUTHOR("Evgeniy Polyakov "); MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); static int w1_timeout = 10; +static int w1_control_timeout = 1; int w1_max_slave_count = 10; int w1_max_slave_ttl = 10; module_param_named(timeout, w1_timeout, int, 0); +module_param_named(control_timeout, w1_control_timeout, int, 0); module_param_named(max_slave_count, w1_max_slave_count, int, 0); module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); @@ -69,37 +71,51 @@ static int w1_master_probe(struct device *dev) return -ENODEV; } -static int w1_master_remove(struct device *dev) -{ - return 0; -} - static void w1_master_release(struct device *dev) { struct w1_master *md = dev_to_w1_master(dev); - complete(&md->dev_released); + + dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name); + + if (md->nls && md->nls->sk_socket) + sock_release(md->nls->sk_socket); + memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); + kfree(md); } static void w1_slave_release(struct device *dev) { struct w1_slave *sl = dev_to_w1_slave(dev); - complete(&sl->dev_released); + + dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name); + + while (atomic_read(&sl->refcnt)) { + dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n", + sl->name, atomic_read(&sl->refcnt)); + if (msleep_interruptible(1000)) + flush_signals(current); + } + + w1_family_put(sl->family); + sl->master->slave_count--; + + complete(&sl->released); } static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf) { - struct w1_slave *sl = dev_to_w1_slave(dev); + struct w1_slave *sl = dev_to_w1_slave(dev); - return sprintf(buf, "%s\n", sl->name); + return sprintf(buf, "%s\n", sl->name); } static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct w1_slave *sl = kobj_to_w1_slave(kobj); + struct w1_slave *sl = kobj_to_w1_slave(kobj); - atomic_inc(&sl->refcnt); - if (off > 8) { - count = 0; + atomic_inc(&sl->refcnt); + if (off > 8) { + count = 0; } else { if (off + count > 8) count = 8 - off; @@ -109,7 +125,7 @@ static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, siz atomic_dec(&sl->refcnt); return count; - } +} static struct device_attribute w1_slave_attr_name = __ATTR(name, S_IRUGO, w1_slave_read_name, NULL); @@ -139,7 +155,6 @@ struct device_driver w1_master_driver = { .name = "w1_master_driver", .bus = &w1_bus_type, .probe = w1_master_probe, - .remove = w1_master_remove, }; struct device w1_master_device = { @@ -160,6 +175,7 @@ struct device w1_slave_device = { .bus = &w1_bus_type, .bus_id = "w1 bus slave", .driver = &w1_slave_driver, + .release = &w1_slave_release }; static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -406,8 +422,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) (unsigned int) sl->reg_num.family, (unsigned long long) sl->reg_num.id); - dev_dbg(&sl->dev, "%s: registering %s.\n", __func__, - &sl->dev.bus_id[0]); + dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]); err = device_register(&sl->dev); if (err < 0) { @@ -480,7 +495,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); atomic_set(&sl->refcnt, 0); - init_completion(&sl->dev_released); + init_completion(&sl->released); spin_lock(&w1_flock); f = w1_family_registered(rn->family); @@ -512,6 +527,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) msg.type = W1_SLAVE_ADD; w1_netlink_send(dev, &msg); + dev_info(&dev->dev, "Finished %s for sl=%p.\n", __func__, sl); + return 0; } @@ -519,29 +536,23 @@ static void w1_slave_detach(struct w1_slave *sl) { struct w1_netlink_msg msg; - dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name); + dev_info(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl); - while (atomic_read(&sl->refcnt)) { - printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n", - sl->name, atomic_read(&sl->refcnt)); - - if (msleep_interruptible(1000)) - flush_signals(current); - } + list_del(&sl->w1_slave_entry); if (sl->family->fops && sl->family->fops->remove_slave) sl->family->fops->remove_slave(sl); + memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); + msg.type = W1_SLAVE_REMOVE; + w1_netlink_send(sl->master, &msg); + sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id); device_remove_file(&sl->dev, &w1_slave_attr_name); device_unregister(&sl->dev); - w1_family_put(sl->family); - sl->master->slave_count--; - - memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); - msg.type = W1_SLAVE_REMOVE; - w1_netlink_send(sl->master, &msg); + wait_for_completion(&sl->released); + kfree(sl); } static struct w1_master *w1_search_master(unsigned long data) @@ -713,7 +724,7 @@ static int w1_control(void *data) have_to_wait = 0; try_to_freeze(); - msleep_interruptible(w1_timeout * 1000); + msleep_interruptible(w1_control_timeout * 1000); if (signal_pending(current)) flush_signals(current); @@ -746,13 +757,12 @@ static int w1_control(void *data) list_del(&dev->w1_master_entry); spin_unlock_bh(&w1_mlock); + down(&dev->mutex); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { - list_del(&sl->w1_slave_entry); - w1_slave_detach(sl); - kfree(sl); } w1_destroy_master_attributes(dev); + up(&dev->mutex); atomic_dec(&dev->refcnt); continue; } @@ -760,19 +770,17 @@ static int w1_control(void *data) 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) { + list_for_each_entry_safe(sl, sln, &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_slave_detach(sl); w1_attach_slave_device(dev, &rn); } } + dev_info(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); up(&dev->mutex); } @@ -816,10 +824,7 @@ int w1_process(void *data) list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { - list_del (&sl->w1_slave_entry); - w1_slave_detach(sl); - kfree(sl); dev->slave_count--; } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 13edc82bc7d..6cc7f0c5d43 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -76,7 +76,7 @@ struct w1_slave struct w1_master *master; struct w1_family *family; struct device dev; - struct completion dev_released; + struct completion released; }; typedef void (* w1_slave_found_callback)(unsigned long, u64); @@ -176,7 +176,6 @@ struct w1_master struct device_driver *driver; struct device dev; - struct completion dev_released; struct completion dev_exited; struct w1_bus_master *bus_master; diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index c13724fd097..c3f67eafc7e 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -76,7 +76,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, INIT_LIST_HEAD(&dev->slist); init_MUTEX(&dev->mutex); - init_completion(&dev->dev_released); init_completion(&dev->dev_exited); memcpy(&dev->dev, device, sizeof(struct device)); @@ -107,9 +106,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, void w1_free_dev(struct w1_master *dev) { device_unregister(&dev->dev); - dev_fini_netlink(dev); - memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); - kfree(dev); } int w1_add_master_device(struct w1_bus_master *master) @@ -184,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev) __func__, dev->kpid); while (atomic_read(&dev->refcnt)) { - printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n", + dev_dbg(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n", dev->name, atomic_read(&dev->refcnt)); if (msleep_interruptible(1000)) -- cgit v1.2.3-70-g09d2 From 7c8f5703de91ade517d4fd6c3cc8e08dbba2b739 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 11 Aug 2005 17:27:50 +0400 Subject: [PATCH] w1: Decreased debug level. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/w1/w1.c') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 4e98ab1aa2f..1b6b74c116a 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -527,8 +527,6 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) msg.type = W1_SLAVE_ADD; w1_netlink_send(dev, &msg); - dev_info(&dev->dev, "Finished %s for sl=%p.\n", __func__, sl); - return 0; } @@ -536,7 +534,7 @@ static void w1_slave_detach(struct w1_slave *sl) { struct w1_netlink_msg msg; - dev_info(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl); + dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl); list_del(&sl->w1_slave_entry); @@ -579,7 +577,7 @@ void w1_reconnect_slaves(struct w1_family *f) 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_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", dev->name, f->fid); set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); } @@ -768,7 +766,7 @@ static int w1_control(void *data) } if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { - dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); + dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name); down(&dev->mutex); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { if (sl->family->fid == W1_FAMILY_DEFAULT) { @@ -780,7 +778,7 @@ static int w1_control(void *data) w1_attach_slave_device(dev, &rn); } } - dev_info(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); + dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name); clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); up(&dev->mutex); } -- cgit v1.2.3-70-g09d2