From: Dmitry Torokhov <dtor_core@ameritech.net>
To: sensors@Stimpy.netroedge.com
Cc: LKML <linux-kernel@vger.kernel.org>, Greg KH <gregkh@suse.de>,
Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Subject: [RFC/PATCH 16/22] W1: cleanup masters refcounting & more
Date: Thu, 21 Apr 2005 02:23:15 -0500 [thread overview]
Message-ID: <200504210223.15682.dtor_core@ameritech.net> (raw)
In-Reply-To: <200504210207.02421.dtor_core@ameritech.net>
W1: clean-up master device implementation:
- get rid of separate refcount, rely on driver model to
enforce lifetime rules;
- use atomic to generate unique master IDs;
- drop unused fields.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
w1.c | 263 ++++++++++++++++++++++++++-----------------------------------------
w1.h | 17 +---
2 files changed, 108 insertions(+), 172 deletions(-)
Index: dtor/drivers/w1/w1.h
===================================================================
--- dtor.orig/drivers/w1/w1.h
+++ dtor/drivers/w1/w1.h
@@ -103,30 +103,21 @@ struct w1_bus_ops
struct w1_master
{
+ void *private;
+
unsigned char name[W1_MAXNAMELEN];
struct list_head slist;
int max_slave_count;
int slave_ttl;
int scan_interval;
- int initialized;
- u32 id;
-
- atomic_t refcnt;
-
- void *private;
- int need_exit;
pid_t kpid;
- struct semaphore mutex;
- struct device_driver *driver;
struct device dev;
- struct completion dev_released;
- struct completion dev_exited;
+ struct completion thread_exited;
+ struct semaphore mutex;
struct w1_bus_ops *bus_ops;
-
- u32 seq, groups;
};
#define to_w1_master(dev) container_of((dev), struct w1_master, dev)
Index: dtor/drivers/w1/w1.c
===================================================================
--- dtor.orig/drivers/w1/w1.c
+++ dtor/drivers/w1/w1.c
@@ -50,49 +50,19 @@ module_param_named(scan_interval, w1_sca
module_param_named(max_slave_count, w1_max_slave_count, int, 0);
module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
-static u32 w1_ids = 1;
-
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
return 1;
}
-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 = container_of(dev, struct w1_master, dev);
-
- complete(&md->dev_released);
-}
-
-
static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
};
-struct device_driver w1_driver = {
- .name = "w1_driver",
- .bus = &w1_bus_type,
- .probe = w1_master_probe,
- .remove = w1_master_remove,
-};
-
-struct device w1_device = {
- .parent = NULL,
+struct device_driver w1_master_driver = {
+ .name = "master",
.bus = &w1_bus_type,
- .bus_id = "w1 bus master",
- .driver = &w1_driver,
- .release = &w1_master_release
};
static ssize_t w1_slave_attribute_show_family(struct device *dev, char *buf)
@@ -166,7 +136,6 @@ static int __w1_attach_slave_device(stru
int err;
sl->dev.parent = &sl->master->dev;
- sl->dev.driver = sl->master->driver;
sl->dev.bus = &w1_bus_type;
sl->dev.release = &w1_slave_release;
@@ -346,52 +315,44 @@ static void w1_slave_found(struct w1_mas
w1_attach_slave_device(dev, reg_num);
}
-
-static int w1_process(void *data)
+static void w1_master_scan_slaves(struct w1_master *master)
{
- struct w1_master *dev = (struct w1_master *) data;
struct w1_slave *slave, *next;
- daemonize("%s", dev->name);
- allow_signal(SIGTERM);
-
- while (!dev->need_exit) {
- try_to_freeze(PF_FREEZE);
- msleep_interruptible(dev->scan_interval * 1000);
-
- if (signal_pending(current))
- flush_signals(current);
-
- if (dev->need_exit)
- break;
-
- if (!dev->initialized)
- continue;
-
- if (down_interruptible(&dev->mutex))
- continue;
+ if (down_interruptible(&master->mutex))
+ return;
- list_for_each_entry(slave, &dev->slist, node)
- clear_bit(W1_SLAVE_ACTIVE, &slave->flags);
+ list_for_each_entry(slave, &master->slist, node)
+ clear_bit(W1_SLAVE_ACTIVE, &slave->flags);
- w1_search_devices(dev, w1_slave_found);
+ w1_search_devices(master, w1_slave_found);
- list_for_each_entry_safe(slave, next, &dev->slist, node) {
+ list_for_each_entry_safe(slave, next, &master->slist, node) {
- if (!test_bit(W1_SLAVE_ACTIVE, &slave->flags) &&
- !--slave->ttl) {
- list_del(&slave->node);
- w1_slave_detach(slave);
- kfree(slave);
- }
+ if (!test_bit(W1_SLAVE_ACTIVE, &slave->flags) &&
+ !--slave->ttl) {
+ list_del(&slave->node);
+ w1_slave_detach(slave);
+ kfree(slave);
}
- up(&dev->mutex);
}
+ up(&master->mutex);
+}
+
+static int w1_process(void *data)
+{
+ struct w1_master *master = (struct w1_master *) data;
- atomic_dec(&dev->refcnt);
- complete_and_exit(&dev->dev_exited, 0);
+ daemonize("%s", master->dev.bus_id);
+ allow_signal(SIGTERM);
- return 0;
+ do {
+ w1_master_scan_slaves(master);
+ msleep_interruptible(master->scan_interval * 1000);
+ try_to_freeze(PF_FREEZE);
+ } while (!signal_pending(current));
+
+ complete_and_exit(&master->thread_exited, 0);
}
static ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
@@ -497,128 +458,110 @@ static struct attribute_group w1_master_
.attrs = w1_master_default_attrs,
};
+static void w1_release_master_device(struct device *dev)
+{
+ struct w1_master *master = to_w1_master(dev);
+
+ kfree(master);
+ module_put(THIS_MODULE);
+}
+
struct w1_master *w1_allocate_master_device(void)
{
- struct w1_master *dev;
+ struct w1_master *master;
- /*
- * We are in process context(kernel thread), so can sleep.
- */
- dev = kcalloc(1, sizeof(struct w1_master), GFP_KERNEL);
- if (!dev) {
+ master = kcalloc(1, sizeof(struct w1_master), GFP_KERNEL);
+ if (!master) {
printk(KERN_ERR
- "Failed to allocate %zd bytes for new w1 device.\n",
- sizeof(struct w1_master));
+ "w1: Failed to allocate %zd bytes for new w1 device.\n",
+ sizeof(struct w1_master));
return NULL;
}
- dev->max_slave_count = w1_max_slave_count;
- dev->kpid = -1;
- dev->id = w1_ids++;
- dev->slave_ttl = w1_max_slave_ttl;
-
- atomic_set(&dev->refcnt, 2);
-
- INIT_LIST_HEAD(&dev->slist);
- init_MUTEX(&dev->mutex);
-
- init_completion(&dev->dev_released);
- init_completion(&dev->dev_exited);
-
- dev->dev = w1_device;
- snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
- "w1_bus_master%u", dev->id);
+ master->max_slave_count = w1_max_slave_count;
+ master->slave_ttl = w1_max_slave_ttl;
+ master->scan_interval = w1_scan_interval;
- dev->driver = &w1_driver;
-
- dev->groups = 23;
- dev->seq = 1;
-
- return dev;
-}
-
-static void w1_free_master_dev(struct w1_master *dev)
-{
- device_unregister(&dev->dev);
- kfree(dev);
-}
+ INIT_LIST_HEAD(&master->slist);
+ init_MUTEX(&master->mutex);
+ init_completion(&master->thread_exited);
-static void w1_stop_master_device(struct w1_master *dev)
-{
- dev->need_exit = 1;
- if (kill_proc(dev->kpid, SIGTERM, 1))
- dev_err(&dev->dev,
- "Failed to send signal to w1 kernel thread %d.\n",
- dev->kpid);
- wait_for_completion(&dev->dev_exited);
+ return master;
}
-int w1_add_master_device(struct w1_master *dev)
+int w1_add_master_device(struct w1_master *master)
{
+ static atomic_t master_no = ATOMIC_INIT(0);
int error;
- error = device_register(&dev->dev);
+ snprintf(master->dev.bus_id, sizeof(master->dev.bus_id),
+ "master%lu", (unsigned long)atomic_inc_return(&master_no));
+ master->dev.bus = &w1_bus_type;
+ master->dev.release = w1_release_master_device;
+ master->dev.driver = &w1_master_driver;
+
+ error = device_register(&master->dev);
if (error) {
- printk(KERN_ERR "Failed to register master device. err=%d\n", error);
+ printk(KERN_ERR
+ "w1: Failed to register master device. err=%d\n",
+ error);
return error;
}
- dev->kpid = kernel_thread(&w1_process, dev, 0);
- if (dev->kpid < 0) {
- dev_err(&dev->dev,
- "Failed to create new kernel thread. err=%d\n",
- dev->kpid);
- error = dev->kpid;
- goto err_out_free_dev;
- }
-
- error = sysfs_create_group(&dev->dev.kobj, &w1_master_defattr_group);
- if (error)
- goto err_out_kill_thread;
-
- dev->initialized = 1;
-
__module_get(THIS_MODULE);
- return 0;
+ error = sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
+ if (error) {
+ printk(KERN_ERR
+ "w1: Failed to create master attributes, err=%d\n",
+ error);
+ goto err_out_unregister;
+ }
-err_out_kill_thread:
- w1_stop_master_device(dev);
+ master->kpid = kernel_thread(&w1_process, master, 0);
+ if (master->kpid < 0) {
+ printk(KERN_ERR
+ "w1: Failed to create new kernel thread, err=%d\n",
+ master->kpid);
+ error = master->kpid;
+ goto err_out_remove_attrs;
+ }
-err_out_free_dev:
- w1_free_master_dev(dev);
+ return 0;
+err_out_remove_attrs:
+ sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+err_out_unregister:
+ device_unregister(&master->dev);
return error;
}
-void w1_remove_master_device(struct w1_master *dev)
+static void w1_stop_master_device(struct w1_master *master)
+{
+ if (kill_proc(master->kpid, SIGTERM, 1))
+ printk(KERN_ERR
+ "w1: Failed to send signal to w1 kernel thread %d.\n",
+ master->kpid);
+ wait_for_completion(&master->thread_exited);
+}
+
+void w1_remove_master_device(struct w1_master *master)
{
struct w1_slave *slave, *next;
- w1_stop_master_device(dev);
+ w1_stop_master_device(master);
- list_for_each_entry_safe(slave, next, &dev->slist, node) {
+ list_for_each_entry_safe(slave, next, &master->slist, node) {
list_del(&slave->node);
w1_slave_detach(slave);
kfree(slave);
}
- sysfs_remove_group(&dev->dev.kobj, &w1_master_defattr_group);
-
- while (atomic_read(&dev->refcnt)) {
- printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
- dev->name, atomic_read(&dev->refcnt));
-
- if (msleep_interruptible(1000))
- flush_signals(current);
- }
-
- w1_free_master_dev(dev);
- module_put(THIS_MODULE);
+ sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+ device_unregister(&master->dev);
}
-
-int w1_init(void)
+static int w1_init(void)
{
int error;
@@ -626,14 +569,16 @@ int w1_init(void)
error = bus_register(&w1_bus_type);
if (error) {
- printk(KERN_ERR "Failed to register bus. err=%d.\n", error);
+ printk(KERN_ERR "w1: Failed to register bus. err=%d.\n",
+ error);
return error;
}
- error = driver_register(&w1_driver);
+ error = driver_register(&w1_master_driver);
if (error) {
printk(KERN_ERR
- "Failed to register master driver. err=%d.\n", error);
+ "w1: Failed to register master driver. err=%d.\n",
+ error);
bus_unregister(&w1_bus_type);
return error;
}
@@ -641,14 +586,14 @@ int w1_init(void)
return 0;
}
-void w1_fini(void)
+static void w1_exit(void)
{
- driver_unregister(&w1_driver);
+ driver_unregister(&w1_master_driver);
bus_unregister(&w1_bus_type);
}
module_init(w1_init);
-module_exit(w1_fini);
+module_exit(w1_exit);
EXPORT_SYMBOL(w1_allocate_master_device);
EXPORT_SYMBOL(w1_add_master_device);
next prev parent reply other threads:[~2005-04-21 8:12 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-04-21 7:07 [RFC/PATCH 0/22] W1: sysfs, lifetime and other fixes Dmitry Torokhov
2005-04-21 7:08 ` [RFC/PATCH 1/22] W1: whitespace fixes Dmitry Torokhov
2005-04-21 7:08 ` [RFC/PATCH 2/22] W1: formatting fixes Dmitry Torokhov
2005-04-21 7:09 ` [RFC/PATCH 3/22] W1: use attribute group for master's attributes Dmitry Torokhov
2005-04-21 7:10 ` [RFC/PATCH 4/22] W1: use attribute group for slave's attributes Dmitry Torokhov
2005-04-21 7:11 ` [RFC/PATCH 5/22] W1: list handling cleanup Dmitry Torokhov
2005-04-21 7:13 ` [RFC/PATCH 6/22] W1: drop owner field from master and slave structures Dmitry Torokhov
2005-04-21 7:13 ` [RFC/PATCH 7/22] W1: bus operations cleanup Dmitry Torokhov
2005-04-21 7:15 ` [RFC/PATCH 8/22] W1: merge master code into one file Dmitry Torokhov
2005-04-21 7:16 ` [RFC/PATCH 9/22] W1: drop custom hotplug over netlink notification Dmitry Torokhov
2005-04-21 7:17 ` [RFC/PATCH 10/22] W1: drop main control thread Dmitry Torokhov
2005-04-21 7:18 ` [RFC/PATCH 11/22] W1: move w1_search to the rest of IO code Dmitry Torokhov
2005-04-21 7:19 ` [RFC/PATCH 12/22] W1: drop unneeded master attributes Dmitry Torokhov
2005-04-21 7:20 ` [RFC/PATCH 13/22] W1: cleanup master attributes handling Dmitry Torokhov
2005-04-21 7:21 ` [RFC/PATCH 14/22] W1: rename timeout to scan_interval Dmitry Torokhov
2005-04-21 7:22 ` [RFC/PATCH 15/22] W1: add slave_ttl master attribute Dmitry Torokhov
2005-04-21 7:23 ` Dmitry Torokhov [this message]
2005-04-21 7:23 ` [RFC/PATCH 17/22] W1: cleanup slave refcounting & more Dmitry Torokhov
2005-04-21 7:25 ` [RFC/PATCH 18/22] W1: cleanup family implementation Dmitry Torokhov
2005-04-21 7:26 ` [RFC/PATCH 19/22] W1: convert families to be proper sysfs rivers Dmitry Torokhov
2005-04-21 7:27 ` [RFC/PATCH 20/22] W1: add w1_device_id/MODULE_DEVICE_TABLE for automatic driver loading Dmitry Torokhov
2005-04-21 7:36 ` [RFC/PATCH 21/22] W1: implement standard hotplug handler Dmitry Torokhov
2005-04-21 7:38 ` [RFC/PATCH 22/22] W1: expose module parameters in sysfs Dmitry Torokhov
2005-04-21 13:18 ` [RFC/PATCH 0/22] W1: sysfs, lifetime and other fixes Evgeniy Polyakov
2005-04-21 14:31 ` Dmitry Torokhov
2005-04-25 9:08 ` Evgeniy Polyakov
2005-04-25 16:32 ` Dmitry Torokhov
2005-04-25 19:26 ` Evgeniy Polyakov
2005-04-25 21:32 ` Dmitry Torokhov
2005-04-26 7:19 ` Evgeniy Polyakov
2005-04-25 20:15 ` Evgeniy Polyakov
2005-04-25 20:22 ` Dmitry Torokhov
2005-04-26 6:43 ` Evgeniy Polyakov
2005-04-26 6:50 ` Dmitry Torokhov
2005-04-26 7:06 ` Evgeniy Polyakov
2005-04-26 7:16 ` Dmitry Torokhov
2005-04-26 7:35 ` Evgeniy Polyakov
2005-04-26 7:00 ` Greg KH
2005-04-26 7:17 ` Evgeniy Polyakov
2005-04-26 6:58 ` Greg KH
2005-04-21 16:09 ` Dmitry Torokhov
2005-04-25 9:11 ` Evgeniy Polyakov
2005-04-25 16:36 ` Dmitry Torokhov
2005-04-25 19:32 ` Evgeniy Polyakov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200504210223.15682.dtor_core@ameritech.net \
--to=dtor_core@ameritech.net \
--cc=gregkh@suse.de \
--cc=johnpol@2ka.mipt.ru \
--cc=linux-kernel@vger.kernel.org \
--cc=sensors@Stimpy.netroedge.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox