Commit 3c803e8e authored by Linus Torvalds's avatar Linus Torvalds

Commit the manual part of the input layer merge.

git did actually warn me about the fact that I hadn't actually done an
"update-cache" on these two files, but the warning was at the bottom of
a list of all the files that _did_ change in the merge, so I never
noticed.  My bad.
parent c47abbbf
...@@ -17,11 +17,10 @@ ...@@ -17,11 +17,10 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/gameport.h> #include <linux/gameport.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/completion.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kthread.h>
/*#include <asm/io.h>*/ /*#include <asm/io.h>*/
...@@ -238,8 +237,7 @@ struct gameport_event { ...@@ -238,8 +237,7 @@ struct gameport_event {
static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
static LIST_HEAD(gameport_event_list); static LIST_HEAD(gameport_event_list);
static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
static DECLARE_COMPLETION(gameport_exited); static struct task_struct *gameport_task;
static int gameport_pid;
static void gameport_queue_event(void *object, struct module *owner, static void gameport_queue_event(void *object, struct module *owner,
enum gameport_event_type event_type) enum gameport_event_type event_type)
...@@ -250,12 +248,12 @@ static void gameport_queue_event(void *object, struct module *owner, ...@@ -250,12 +248,12 @@ static void gameport_queue_event(void *object, struct module *owner,
spin_lock_irqsave(&gameport_event_lock, flags); spin_lock_irqsave(&gameport_event_lock, flags);
/* /*
* Scan event list for the other events for the same gameport port, * Scan event list for the other events for the same gameport port,
* starting with the most recent one. If event is the same we * starting with the most recent one. If event is the same we
* do not need add new one. If event is of different type we * do not need add new one. If event is of different type we
* need to add this event and should not look further because * need to add this event and should not look further because
* we need to preseve sequence of distinct events. * we need to preseve sequence of distinct events.
*/ */
list_for_each_entry_reverse(event, &gameport_event_list, node) { list_for_each_entry_reverse(event, &gameport_event_list, node) {
if (event->object == object) { if (event->object == object) {
if (event->type == event_type) if (event->type == event_type)
...@@ -432,20 +430,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) ...@@ -432,20 +430,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)
static int gameport_thread(void *nothing) static int gameport_thread(void *nothing)
{ {
lock_kernel();
daemonize("kgameportd");
allow_signal(SIGTERM);
do { do {
gameport_handle_events(); gameport_handle_events();
wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list)); wait_event_interruptible(gameport_wait,
kthread_should_stop() || !list_empty(&gameport_event_list));
try_to_freeze(); try_to_freeze();
} while (!signal_pending(current)); } while (!kthread_should_stop());
printk(KERN_DEBUG "gameport: kgameportd exiting\n"); printk(KERN_DEBUG "gameport: kgameportd exiting\n");
return 0;
unlock_kernel();
complete_and_exit(&gameport_exited, 0);
} }
...@@ -773,9 +766,10 @@ void gameport_close(struct gameport *gameport) ...@@ -773,9 +766,10 @@ void gameport_close(struct gameport *gameport)
static int __init gameport_init(void) static int __init gameport_init(void)
{ {
if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) { gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
if (IS_ERR(gameport_task)) {
printk(KERN_ERR "gameport: Failed to start kgameportd\n"); printk(KERN_ERR "gameport: Failed to start kgameportd\n");
return -1; return PTR_ERR(gameport_task);
} }
gameport_bus.dev_attrs = gameport_device_attrs; gameport_bus.dev_attrs = gameport_device_attrs;
...@@ -789,8 +783,7 @@ static int __init gameport_init(void) ...@@ -789,8 +783,7 @@ static int __init gameport_init(void)
static void __exit gameport_exit(void) static void __exit gameport_exit(void)
{ {
bus_unregister(&gameport_bus); bus_unregister(&gameport_bus);
kill_proc(gameport_pid, SIGTERM, 1); kthread_stop(gameport_task);
wait_for_completion(&gameport_exited);
} }
module_init(gameport_init); module_init(gameport_init);
......
...@@ -31,10 +31,9 @@ ...@@ -31,10 +31,9 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/completion.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core"); MODULE_DESCRIPTION("Serio abstraction core");
...@@ -43,6 +42,7 @@ MODULE_LICENSE("GPL"); ...@@ -43,6 +42,7 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_child_port);
EXPORT_SYMBOL(__serio_unregister_port_delayed); EXPORT_SYMBOL(__serio_unregister_port_delayed);
EXPORT_SYMBOL(__serio_register_driver); EXPORT_SYMBOL(__serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver); EXPORT_SYMBOL(serio_unregister_driver);
...@@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio); ...@@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio);
static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
{
int retval;
down(&serio->drv_sem);
retval = drv->connect(serio, drv);
up(&serio->drv_sem);
return retval;
}
static int serio_reconnect_driver(struct serio *serio)
{
int retval = -1;
down(&serio->drv_sem);
if (serio->drv && serio->drv->reconnect)
retval = serio->drv->reconnect(serio);
up(&serio->drv_sem);
return retval;
}
static void serio_disconnect_driver(struct serio *serio)
{
down(&serio->drv_sem);
if (serio->drv)
serio->drv->disconnect(serio);
up(&serio->drv_sem);
}
static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
{ {
while (ids->type || ids->proto) { while (ids->type || ids->proto) {
...@@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) ...@@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
if (serio_match_port(drv->id_table, serio)) { if (serio_match_port(drv->id_table, serio)) {
serio->dev.driver = &drv->driver; serio->dev.driver = &drv->driver;
if (drv->connect(serio, drv)) { if (serio_connect_driver(serio, drv)) {
serio->dev.driver = NULL; serio->dev.driver = NULL;
goto out; goto out;
} }
...@@ -138,8 +169,7 @@ struct serio_event { ...@@ -138,8 +169,7 @@ struct serio_event {
static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
static LIST_HEAD(serio_event_list); static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait); static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited); static struct task_struct *serio_task;
static int serio_pid;
static void serio_queue_event(void *object, struct module *owner, static void serio_queue_event(void *object, struct module *owner,
enum serio_event_type event_type) enum serio_event_type event_type)
...@@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner, ...@@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner,
spin_lock_irqsave(&serio_event_lock, flags); spin_lock_irqsave(&serio_event_lock, flags);
/* /*
* Scan event list for the other events for the same serio port, * Scan event list for the other events for the same serio port,
* starting with the most recent one. If event is the same we * starting with the most recent one. If event is the same we
* do not need add new one. If event is of different type we * do not need add new one. If event is of different type we
* need to add this event and should not look further because * need to add this event and should not look further because
* we need to preseve sequence of distinct events. * we need to preseve sequence of distinct events.
*/ */
list_for_each_entry_reverse(event, &serio_event_list, node) { list_for_each_entry_reverse(event, &serio_event_list, node) {
if (event->object == object) { if (event->object == object) {
if (event->type == event_type) if (event->type == event_type)
...@@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent) ...@@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent)
static int serio_thread(void *nothing) static int serio_thread(void *nothing)
{ {
lock_kernel();
daemonize("kseriod");
allow_signal(SIGTERM);
do { do {
serio_handle_events(); serio_handle_events();
wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); wait_event_interruptible(serio_wait,
kthread_should_stop() || !list_empty(&serio_event_list));
try_to_freeze(); try_to_freeze();
} while (!signal_pending(current)); } while (!kthread_should_stop());
printk(KERN_DEBUG "serio: kseriod exiting\n"); printk(KERN_DEBUG "serio: kseriod exiting\n");
return 0;
unlock_kernel();
complete_and_exit(&serio_exited, 0);
} }
...@@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio) ...@@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio)
static void serio_reconnect_port(struct serio *serio) static void serio_reconnect_port(struct serio *serio)
{ {
do { do {
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { if (serio_reconnect_driver(serio)) {
serio_disconnect_port(serio); serio_disconnect_port(serio);
serio_find_driver(serio); serio_find_driver(serio);
/* Ok, old children are now gone, we are done */ /* Ok, old children are now gone, we are done */
...@@ -629,6 +654,19 @@ void serio_unregister_port(struct serio *serio) ...@@ -629,6 +654,19 @@ void serio_unregister_port(struct serio *serio)
up(&serio_sem); up(&serio_sem);
} }
/*
* Safely unregisters child port if one is present.
*/
void serio_unregister_child_port(struct serio *serio)
{
down(&serio_sem);
if (serio->child) {
serio_disconnect_port(serio->child);
serio_destroy_port(serio->child);
}
up(&serio_sem);
}
/* /*
* Submits register request to kseriod for subsequent execution. * Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is * Can be used when it is not obvious whether the serio_sem is
...@@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev) ...@@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev)
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
struct serio_driver *drv = to_serio_driver(dev->driver); struct serio_driver *drv = to_serio_driver(dev->driver);
return drv->connect(serio, drv); return serio_connect_driver(serio, drv);
} }
static int serio_driver_remove(struct device *dev) static int serio_driver_remove(struct device *dev)
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
struct serio_driver *drv = to_serio_driver(dev->driver);
drv->disconnect(serio); serio_disconnect_driver(serio);
return 0; return 0;
} }
...@@ -730,11 +767,9 @@ start_over: ...@@ -730,11 +767,9 @@ start_over:
static void serio_set_drv(struct serio *serio, struct serio_driver *drv) static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
{ {
down(&serio->drv_sem);
serio_pause_rx(serio); serio_pause_rx(serio);
serio->drv = drv; serio->drv = drv;
serio_continue_rx(serio); serio_continue_rx(serio);
up(&serio->drv_sem);
} }
static int serio_bus_match(struct device *dev, struct device_driver *drv) static int serio_bus_match(struct device *dev, struct device_driver *drv)
...@@ -794,7 +829,7 @@ static int serio_resume(struct device *dev) ...@@ -794,7 +829,7 @@ static int serio_resume(struct device *dev)
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { if (serio_reconnect_driver(serio)) {
/* /*
* Driver re-probing can take a while, so better let kseriod * Driver re-probing can take a while, so better let kseriod
* deal with it. * deal with it.
...@@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio, ...@@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void) static int __init serio_init(void)
{ {
if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { serio_task = kthread_run(serio_thread, NULL, "kseriod");
if (IS_ERR(serio_task)) {
printk(KERN_ERR "serio: Failed to start kseriod\n"); printk(KERN_ERR "serio: Failed to start kseriod\n");
return -1; return PTR_ERR(serio_task);
} }
serio_bus.dev_attrs = serio_device_attrs; serio_bus.dev_attrs = serio_device_attrs;
...@@ -866,8 +902,7 @@ static int __init serio_init(void) ...@@ -866,8 +902,7 @@ static int __init serio_init(void)
static void __exit serio_exit(void) static void __exit serio_exit(void)
{ {
bus_unregister(&serio_bus); bus_unregister(&serio_bus);
kill_proc(serio_pid, SIGTERM, 1); kthread_stop(serio_task);
wait_for_completion(&serio_exited);
} }
module_init(serio_init); module_init(serio_init);
......
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