Skip to content

Commit

Permalink
Commit the manual part of the input layer merge.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Linus Torvalds committed Jun 28, 2005
1 parent c47abbb commit 3c803e8
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 46 deletions.
31 changes: 12 additions & 19 deletions drivers/input/gameport/gameport.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/wait.h>
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/kthread.h>

/*#include <asm/io.h>*/

Expand Down Expand Up @@ -238,8 +237,7 @@ struct gameport_event {
static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
static LIST_HEAD(gameport_event_list);
static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
static DECLARE_COMPLETION(gameport_exited);
static int gameport_pid;
static struct task_struct *gameport_task;

static void gameport_queue_event(void *object, struct module *owner,
enum gameport_event_type event_type)
Expand All @@ -250,12 +248,12 @@ static void gameport_queue_event(void *object, struct module *owner,
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
* do not need add new one. If event is of different type we
* need to add this event and should not look further because
* we need to preseve sequence of distinct events.
*/
*/
list_for_each_entry_reverse(event, &gameport_event_list, node) {
if (event->object == object) {
if (event->type == event_type)
Expand Down Expand Up @@ -432,20 +430,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)

static int gameport_thread(void *nothing)
{
lock_kernel();
daemonize("kgameportd");
allow_signal(SIGTERM);

do {
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();
} while (!signal_pending(current));
} while (!kthread_should_stop());

printk(KERN_DEBUG "gameport: kgameportd exiting\n");

unlock_kernel();
complete_and_exit(&gameport_exited, 0);
return 0;
}


Expand Down Expand Up @@ -773,9 +766,10 @@ void gameport_close(struct gameport *gameport)

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");
return -1;
return PTR_ERR(gameport_task);
}

gameport_bus.dev_attrs = gameport_device_attrs;
Expand All @@ -789,8 +783,7 @@ static int __init gameport_init(void)
static void __exit gameport_exit(void)
{
bus_unregister(&gameport_bus);
kill_proc(gameport_pid, SIGTERM, 1);
wait_for_completion(&gameport_exited);
kthread_stop(gameport_task);
}

module_init(gameport_init);
Expand Down
89 changes: 62 additions & 27 deletions drivers/input/serio/serio.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@
#include <linux/serio.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/kthread.h>

MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core");
Expand All @@ -43,6 +42,7 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_child_port);
EXPORT_SYMBOL(__serio_unregister_port_delayed);
EXPORT_SYMBOL(__serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
Expand All @@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_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)
{
while (ids->type || ids->proto) {
Expand All @@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)

if (serio_match_port(drv->id_table, serio)) {
serio->dev.driver = &drv->driver;
if (drv->connect(serio, drv)) {
if (serio_connect_driver(serio, drv)) {
serio->dev.driver = NULL;
goto out;
}
Expand Down Expand Up @@ -138,8 +169,7 @@ struct serio_event {
static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited);
static int serio_pid;
static struct task_struct *serio_task;

static void serio_queue_event(void *object, struct module *owner,
enum serio_event_type event_type)
Expand All @@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner,
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
* do not need add new one. If event is of different type we
* need to add this event and should not look further because
* we need to preseve sequence of distinct events.
*/
*/
list_for_each_entry_reverse(event, &serio_event_list, node) {
if (event->object == object) {
if (event->type == event_type)
Expand Down Expand Up @@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent)

static int serio_thread(void *nothing)
{
lock_kernel();
daemonize("kseriod");
allow_signal(SIGTERM);

do {
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();
} while (!signal_pending(current));
} while (!kthread_should_stop());

printk(KERN_DEBUG "serio: kseriod exiting\n");

unlock_kernel();
complete_and_exit(&serio_exited, 0);
return 0;
}


Expand Down Expand Up @@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio)
static void serio_reconnect_port(struct serio *serio)
{
do {
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
if (serio_reconnect_driver(serio)) {
serio_disconnect_port(serio);
serio_find_driver(serio);
/* Ok, old children are now gone, we are done */
Expand Down Expand Up @@ -629,6 +654,19 @@ void serio_unregister_port(struct serio *serio)
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.
* Can be used when it is not obvious whether the serio_sem is
Expand Down Expand Up @@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev)
struct serio *serio = to_serio_port(dev);
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)
{
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;
}

Expand Down Expand Up @@ -730,11 +767,9 @@ void serio_unregister_driver(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->drv = drv;
serio_continue_rx(serio);
up(&serio->drv_sem);
}

static int serio_bus_match(struct device *dev, struct device_driver *drv)
Expand Down Expand Up @@ -794,7 +829,7 @@ static int serio_resume(struct device *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
* deal with it.
Expand Down Expand Up @@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio,

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");
return -1;
return PTR_ERR(serio_task);
}

serio_bus.dev_attrs = serio_device_attrs;
Expand All @@ -866,8 +902,7 @@ static int __init serio_init(void)
static void __exit serio_exit(void)
{
bus_unregister(&serio_bus);
kill_proc(serio_pid, SIGTERM, 1);
wait_for_completion(&serio_exited);
kthread_stop(serio_task);
}

module_init(serio_init);
Expand Down

0 comments on commit 3c803e8

Please sign in to comment.