Commit d2f119fe authored by Stefan Richter's avatar Stefan Richter Committed by Ben Collins

[PATCH] ieee1394: nodemgr: switch to kthread api, replace reset semaphore

Convert nodemgr's host thread from kernel_thread to kthread and its
sleep/restart mechanism from a counting semaphore to a schedule()/
wake_up_process() scheme.
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: default avatarBen Collins <bcollins@ubuntu.com>
parent 3a632fe2
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/completion.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <asm/atomic.h> #include <asm/atomic.h>
...@@ -163,11 +163,7 @@ static DECLARE_MUTEX(nodemgr_serialize); ...@@ -163,11 +163,7 @@ static DECLARE_MUTEX(nodemgr_serialize);
struct host_info { struct host_info {
struct hpsb_host *host; struct hpsb_host *host;
struct list_head list; struct list_head list;
struct completion exited; struct task_struct *thread;
struct semaphore reset_sem;
int pid;
char daemon_name[15];
int kill_me;
}; };
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
...@@ -1477,9 +1473,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -1477,9 +1473,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
/* If we had a bus reset while we were scanning the bus, it is /* If we had a bus reset while we were scanning the bus, it is
* possible that we did not probe all nodes. In that case, we * possible that we did not probe all nodes. In that case, we
* skip the clean up for now, since we could remove nodes that * skip the clean up for now, since we could remove nodes that
* were still on the bus. The bus reset increased hi->reset_sem, * were still on the bus. Another bus scan is pending which will
* so there's a bus scan pending which will do the clean up * do the clean up eventually.
* eventually.
* *
* Now let's tell the bus to rescan our devices. This may seem * Now let's tell the bus to rescan our devices. This may seem
* like overhead, but the driver-model core will only scan a * like overhead, but the driver-model core will only scan a
...@@ -1607,41 +1602,37 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1607,41 +1602,37 @@ static int nodemgr_host_thread(void *__hi)
{ {
struct host_info *hi = (struct host_info *)__hi; struct host_info *hi = (struct host_info *)__hi;
struct hpsb_host *host = hi->host; struct hpsb_host *host = hi->host;
int reset_cycles = 0; unsigned int g, generation = get_hpsb_generation(host) - 1;
int i, reset_cycles = 0;
/* No userlevel access needed */
daemonize(hi->daemon_name);
/* Setup our device-model entries */ /* Setup our device-model entries */
nodemgr_create_host_dev_files(host); nodemgr_create_host_dev_files(host);
/* Sit and wait for a signal to probe the nodes on the bus. This for (;;) {
* happens when we get a bus reset. */ /* Sleep until next bus reset */
while (1) { set_current_state(TASK_INTERRUPTIBLE);
unsigned int generation = 0; if (get_hpsb_generation(host) == generation)
int i; schedule();
__set_current_state(TASK_RUNNING);
if (down_interruptible(&hi->reset_sem) || /* Thread may have been woken up to freeze or to exit */
down_interruptible(&nodemgr_serialize)) {
if (try_to_freeze()) if (try_to_freeze())
continue; continue;
printk("NodeMgr: received unexpected signal?!\n" ); if (kthread_should_stop())
break; goto exit;
}
if (hi->kill_me) { if (down_interruptible(&nodemgr_serialize)) {
up(&nodemgr_serialize); if (try_to_freeze())
break; continue;
goto exit;
} }
/* Pause for 1/4 second in 1/16 second intervals, /* Pause for 1/4 second in 1/16 second intervals,
* to make sure things settle down. */ * to make sure things settle down. */
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) { for (i = 0; i < 4 ; i++) {
set_current_state(TASK_INTERRUPTIBLE); if (msleep_interruptible(63) || kthread_should_stop())
if (msleep_interruptible(63)) { goto unlock_exit;
up(&nodemgr_serialize);
goto caught_signal;
}
/* Now get the generation in which the node ID's we collect /* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation * are valid. During the bus scan we will use this generation
...@@ -1652,14 +1643,8 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1652,14 +1643,8 @@ static int nodemgr_host_thread(void *__hi)
/* If we get a reset before we are done waiting, then /* If we get a reset before we are done waiting, then
* start the the waiting over again */ * start the the waiting over again */
while (!down_trylock(&hi->reset_sem)) if (generation != g)
i = 0; g = generation, i = 0;
/* Check the kill_me again */
if (hi->kill_me) {
up(&nodemgr_serialize);
goto caught_signal;
}
} }
if (!nodemgr_check_irm_capability(host, reset_cycles) || if (!nodemgr_check_irm_capability(host, reset_cycles) ||
...@@ -1685,11 +1670,11 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1685,11 +1670,11 @@ static int nodemgr_host_thread(void *__hi)
up(&nodemgr_serialize); up(&nodemgr_serialize);
} }
unlock_exit:
caught_signal: up(&nodemgr_serialize);
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread"); HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
complete_and_exit(&hi->exited, 0);
} }
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
...@@ -1749,41 +1734,27 @@ static void nodemgr_add_host(struct hpsb_host *host) ...@@ -1749,41 +1734,27 @@ static void nodemgr_add_host(struct hpsb_host *host)
struct host_info *hi; struct host_info *hi;
hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi)); hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi));
if (!hi) { if (!hi) {
HPSB_ERR ("NodeMgr: out of memory in add host"); HPSB_ERR("NodeMgr: out of memory in add host");
return; return;
} }
hi->host = host; hi->host = host;
init_completion(&hi->exited); hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d",
sema_init(&hi->reset_sem, 0); host->id);
if (IS_ERR(hi->thread)) {
sprintf(hi->daemon_name, "knodemgrd_%d", host->id); HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_KERNEL);
if (hi->pid < 0) {
HPSB_ERR ("NodeMgr: failed to start %s thread for %s",
hi->daemon_name, host->driver->name);
hpsb_destroy_hostinfo(&nodemgr_highlevel, host); hpsb_destroy_hostinfo(&nodemgr_highlevel, host);
return;
} }
return;
} }
static void nodemgr_host_reset(struct hpsb_host *host) static void nodemgr_host_reset(struct hpsb_host *host)
{ {
struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
if (hi != NULL) { if (hi) {
HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name); HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id);
up(&hi->reset_sem); wake_up_process(hi->thread);
} else }
HPSB_ERR ("NodeMgr: could not process reset of unused host");
return;
} }
static void nodemgr_remove_host(struct hpsb_host *host) static void nodemgr_remove_host(struct hpsb_host *host)
...@@ -1791,18 +1762,9 @@ static void nodemgr_remove_host(struct hpsb_host *host) ...@@ -1791,18 +1762,9 @@ static void nodemgr_remove_host(struct hpsb_host *host)
struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
if (hi) { if (hi) {
if (hi->pid >= 0) { kthread_stop(hi->thread);
hi->kill_me = 1;
mb();
up(&hi->reset_sem);
wait_for_completion(&hi->exited);
nodemgr_remove_host_dev(&host->device); nodemgr_remove_host_dev(&host->device);
} }
} else
HPSB_ERR("NodeMgr: host %s does not exist, cannot remove",
host->driver->name);
return;
} }
static struct hpsb_highlevel nodemgr_highlevel = { static struct hpsb_highlevel nodemgr_highlevel = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment