* [PATCH 1/2] input: make serio_register_driver() return error code
@ 2006-11-07 12:06 Akinobu Mita
2006-11-07 14:20 ` Dmitry Torokhov
0 siblings, 1 reply; 10+ messages in thread
From: Akinobu Mita @ 2006-11-07 12:06 UTC (permalink / raw)
To: linux-kernel; +Cc: Dmitry Torokhov
serio_register_driver() may fail under memory shortage.
When serio_register_driver() called, it queues SERIO_REGISTER_DRIVER
event into global serio_event_list, and then kseriod kernel thread
handles that event and do driver_register().
But event allocation by serio_register_driver() may fail.
Because it is GFP_ATOMIC allocation. It will cause the problem
by serio_unregister_driver() with not being registered driver
at module_exit() time
This patch makes serio_register_driver() call driver_register()
directly instead of kseriod so that it can check whether
driver_register() is succeeded or not.
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
drivers/input/serio/serio.c | 18 ++++--------------
include/linux/serio.h | 7 +------
2 files changed, 5 insertions(+), 20 deletions(-)
Index: work-fault-inject/drivers/input/serio/serio.c
===================================================================
--- work-fault-inject.orig/drivers/input/serio/serio.c
+++ work-fault-inject/drivers/input/serio/serio.c
@@ -46,7 +46,7 @@ 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_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
@@ -175,7 +175,6 @@ enum serio_event_type {
SERIO_RECONNECT,
SERIO_REGISTER_PORT,
SERIO_UNREGISTER_PORT,
- SERIO_REGISTER_DRIVER,
};
struct serio_event {
@@ -322,10 +321,6 @@ static void serio_handle_event(void)
serio_find_driver(event->object);
break;
- case SERIO_REGISTER_DRIVER:
- serio_add_driver(event->object);
- break;
-
default:
break;
}
@@ -791,22 +786,17 @@ static struct bus_type serio_bus = {
.remove = serio_driver_remove,
};
-static void serio_add_driver(struct serio_driver *drv)
+int serio_register_driver(struct serio_driver *drv)
{
int error;
+ drv->driver.bus = &serio_bus;
error = driver_register(&drv->driver);
if (error)
printk(KERN_ERR
"serio: driver_register() failed for %s, error: %d\n",
drv->driver.name, error);
-}
-
-void __serio_register_driver(struct serio_driver *drv, struct module *owner)
-{
- drv->driver.bus = &serio_bus;
-
- serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
+ return error;
}
void serio_unregister_driver(struct serio_driver *drv)
Index: work-fault-inject/include/linux/serio.h
===================================================================
--- work-fault-inject.orig/include/linux/serio.h
+++ work-fault-inject/include/linux/serio.h
@@ -91,12 +91,7 @@ static inline void serio_unregister_port
__serio_unregister_port_delayed(serio, THIS_MODULE);
}
-void __serio_register_driver(struct serio_driver *drv, struct module *owner);
-static inline void serio_register_driver(struct serio_driver *drv)
-{
- __serio_register_driver(drv, THIS_MODULE);
-}
-
+int serio_register_driver(struct serio_driver *drv);
void serio_unregister_driver(struct serio_driver *drv);
static inline int serio_write(struct serio *serio, unsigned char data)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] input: make serio_register_driver() return error code
2006-11-07 12:06 [PATCH 1/2] input: make serio_register_driver() return error code Akinobu Mita
@ 2006-11-07 14:20 ` Dmitry Torokhov
2006-11-08 12:36 ` Akinobu Mita
0 siblings, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2006-11-07 14:20 UTC (permalink / raw)
To: Akinobu Mita, linux-kernel
On 11/7/06, Akinobu Mita <akinobu.mita@gmail.com> wrote:
> serio_register_driver() may fail under memory shortage.
>
> When serio_register_driver() called, it queues SERIO_REGISTER_DRIVER
> event into global serio_event_list, and then kseriod kernel thread
> handles that event and do driver_register().
>
> But event allocation by serio_register_driver() may fail.
> Because it is GFP_ATOMIC allocation. It will cause the problem
> by serio_unregister_driver() with not being registered driver
> at module_exit() time
>
> This patch makes serio_register_driver() call driver_register()
> directly instead of kseriod so that it can check whether
> driver_register() is succeeded or not.
>
This slows down boot process because probing for mice and keyboards
takes too long (for some touchpads it takes about 4 seconds to do
reset). We could change allocation from GFP_ATOMIC to GFP_KERNEL for
SERIO_REGISTER_DRIVER events to make it more robust but otherwise I'd
leave serio_register_driver return void. You could also add a flag to
serio driver indicating whether registration is complete and check
that flag in serio_unregister_driver so it does not do stupid things.
--
Dmitry
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] input: make serio_register_driver() return error code
2006-11-07 14:20 ` Dmitry Torokhov
@ 2006-11-08 12:36 ` Akinobu Mita
2006-11-08 12:38 ` [PATCH 1/4] input: make serio_register_driver() return error Akinobu Mita
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Akinobu Mita @ 2006-11-08 12:36 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-kernel
On Tue, Nov 07, 2006 at 09:20:07AM -0500, Dmitry Torokhov wrote:
> >This patch makes serio_register_driver() call driver_register()
> >directly instead of kseriod so that it can check whether
> >driver_register() is succeeded or not.
> >
>
> This slows down boot process because probing for mice and keyboards
> takes too long (for some touchpads it takes about 4 seconds to do
I understand the reason why driver_register() is done by kseriod.
> reset). We could change allocation from GFP_ATOMIC to GFP_KERNEL for
> SERIO_REGISTER_DRIVER events to make it more robust but otherwise I'd
> leave serio_register_driver return void. You could also add a flag to
> serio driver indicating whether registration is complete and check
> that flag in serio_unregister_driver so it does not do stupid things.
I reorganzed the patch set.
serio driver registration can fail in two different ways.
1) serio_event allocation failure by serio_register_driver().
It happens in module_init() context. It is possible to check this
allocation failure by making serio_register_driver() return error.
2) driver_register() failure by kseriod.
This failure cannot be checked by serio_register_driver().
But it is necessary to prevent serio_unregister_driver() from
trying to call driver_unregister() with not registered driver
by adding flag to serio driver indicating whether registration is
complete.
1/4: make serio_register_driver() return error -- 1)
2/4: check serio_register_driver() error -- 1)
3/4: check whether serio dirver registration is completed -- 2)
4/4: change to GFP_KERNEL for SERIO_REGISTER_DRIVER event allocation
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] input: make serio_register_driver() return error
2006-11-08 12:36 ` Akinobu Mita
@ 2006-11-08 12:38 ` Akinobu Mita
2006-11-08 12:39 ` [PATCH 2/4] input: check serio_register_driver() error Akinobu Mita
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Akinobu Mita @ 2006-11-08 12:38 UTC (permalink / raw)
To: Dmitry Torokhov, linux-kernel
This patch makes serio_register_driver() return error
when serio_event allocation is failed or unable to get module reference.
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
drivers/input/serio/serio.c | 12 ++++++++----
include/linux/serio.h | 6 +++---
2 files changed, 11 insertions(+), 7 deletions(-)
Index: work-fault-inject/drivers/input/serio/serio.c
===================================================================
--- work-fault-inject.orig/drivers/input/serio/serio.c
+++ work-fault-inject/drivers/input/serio/serio.c
@@ -190,11 +190,12 @@ static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static struct task_struct *serio_task;
-static void serio_queue_event(void *object, struct module *owner,
- enum serio_event_type event_type)
+static int serio_queue_event(void *object, struct module *owner,
+ enum serio_event_type event_type)
{
unsigned long flags;
struct serio_event *event;
+ int err = 0;
spin_lock_irqsave(&serio_event_lock, flags);
@@ -215,6 +216,7 @@ static void serio_queue_event(void *obje
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
if (!try_module_get(owner)) {
+ err = -EINVAL;
printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
kfree(event);
goto out;
@@ -227,10 +229,12 @@ static void serio_queue_event(void *obje
list_add_tail(&event->node, &serio_event_list);
wake_up(&serio_wait);
} else {
+ err = -ENOMEM;
printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type);
}
out:
spin_unlock_irqrestore(&serio_event_lock, flags);
+ return err;
}
static void serio_free_event(struct serio_event *event)
@@ -802,11 +806,11 @@ static void serio_add_driver(struct seri
drv->driver.name, error);
}
-void __serio_register_driver(struct serio_driver *drv, struct module *owner)
+int __serio_register_driver(struct serio_driver *drv, struct module *owner)
{
drv->driver.bus = &serio_bus;
- serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
+ return serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
}
void serio_unregister_driver(struct serio_driver *drv)
Index: work-fault-inject/include/linux/serio.h
===================================================================
--- work-fault-inject.orig/include/linux/serio.h
+++ work-fault-inject/include/linux/serio.h
@@ -91,10 +91,10 @@ static inline void serio_unregister_port
__serio_unregister_port_delayed(serio, THIS_MODULE);
}
-void __serio_register_driver(struct serio_driver *drv, struct module *owner);
-static inline void serio_register_driver(struct serio_driver *drv)
+int __serio_register_driver(struct serio_driver *drv, struct module *owner);
+static inline int serio_register_driver(struct serio_driver *drv)
{
- __serio_register_driver(drv, THIS_MODULE);
+ return __serio_register_driver(drv, THIS_MODULE);
}
void serio_unregister_driver(struct serio_driver *drv);
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/4] input: check serio_register_driver() error
2006-11-08 12:36 ` Akinobu Mita
2006-11-08 12:38 ` [PATCH 1/4] input: make serio_register_driver() return error Akinobu Mita
@ 2006-11-08 12:39 ` Akinobu Mita
2006-11-08 12:40 ` [PATCH 3/4] input: check whether serio dirver registration is completed Akinobu Mita
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Akinobu Mita @ 2006-11-08 12:39 UTC (permalink / raw)
To: Dmitry Torokhov, linux-kernel
Now serio_register_driver() returns error.
This patch checks serio_register_driver() error
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
drivers/input/joystick/iforce/iforce-main.c | 14 +++++++++++---
drivers/input/joystick/magellan.c | 3 +--
drivers/input/joystick/spaceball.c | 3 +--
drivers/input/joystick/spaceorb.c | 3 +--
drivers/input/joystick/stinger.c | 3 +--
drivers/input/joystick/twidjoy.c | 3 +--
drivers/input/joystick/warrior.c | 3 +--
drivers/input/keyboard/atkbd.c | 3 +--
drivers/input/keyboard/hil_kbd.c | 3 +--
drivers/input/keyboard/lkkbd.c | 3 +--
drivers/input/keyboard/newtonkbd.c | 3 +--
drivers/input/keyboard/stowaway.c | 3 +--
drivers/input/keyboard/sunkbd.c | 3 +--
drivers/input/keyboard/xtkbd.c | 3 +--
drivers/input/mouse/hil_ptr.c | 3 +--
drivers/input/mouse/psmouse-base.c | 8 ++++++--
drivers/input/mouse/sermouse.c | 3 +--
drivers/input/mouse/vsxxxaa.c | 3 +--
drivers/input/touchscreen/elo.c | 3 +--
drivers/input/touchscreen/gunze.c | 3 +--
drivers/input/touchscreen/h3600_ts_input.c | 3 +--
drivers/input/touchscreen/mtouch.c | 3 +--
drivers/input/touchscreen/penmount.c | 3 +--
drivers/input/touchscreen/touchright.c | 3 +--
drivers/input/touchscreen/touchwin.c | 3 +--
25 files changed, 40 insertions(+), 51 deletions(-)
Index: work-fault-inject/drivers/input/mouse/vsxxxaa.c
===================================================================
--- work-fault-inject.orig/drivers/input/mouse/vsxxxaa.c
+++ work-fault-inject/drivers/input/mouse/vsxxxaa.c
@@ -571,8 +571,7 @@ static struct serio_driver vsxxxaa_drv =
static int __init
vsxxxaa_init (void)
{
- serio_register_driver(&vsxxxaa_drv);
- return 0;
+ return serio_register_driver(&vsxxxaa_drv);
}
static void __exit
Index: work-fault-inject/drivers/input/mouse/psmouse-base.c
===================================================================
--- work-fault-inject.orig/drivers/input/mouse/psmouse-base.c
+++ work-fault-inject/drivers/input/mouse/psmouse-base.c
@@ -1509,15 +1509,19 @@ static int psmouse_get_maxproto(char *bu
static int __init psmouse_init(void)
{
+ int err;
+
kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
if (!kpsmoused_wq) {
printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
return -ENOMEM;
}
- serio_register_driver(&psmouse_drv);
+ err = serio_register_driver(&psmouse_drv);
+ if (err)
+ destroy_workqueue(kpsmoused_wq);
- return 0;
+ return err;
}
static void __exit psmouse_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/elo.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/elo.c
+++ work-fault-inject/drivers/input/touchscreen/elo.c
@@ -397,8 +397,7 @@ static struct serio_driver elo_drv = {
static int __init elo_init(void)
{
- serio_register_driver(&elo_drv);
- return 0;
+ return serio_register_driver(&elo_drv);
}
static void __exit elo_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/gunze.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/gunze.c
+++ work-fault-inject/drivers/input/touchscreen/gunze.c
@@ -190,8 +190,7 @@ static struct serio_driver gunze_drv = {
static int __init gunze_init(void)
{
- serio_register_driver(&gunze_drv);
- return 0;
+ return serio_register_driver(&gunze_drv);
}
static void __exit gunze_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/h3600_ts_input.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/h3600_ts_input.c
+++ work-fault-inject/drivers/input/touchscreen/h3600_ts_input.c
@@ -478,8 +478,7 @@ static struct serio_driver h3600ts_drv =
static int __init h3600ts_init(void)
{
- serio_register_driver(&h3600ts_drv);
- return 0;
+ return serio_register_driver(&h3600ts_drv);
}
static void __exit h3600ts_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/mtouch.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/mtouch.c
+++ work-fault-inject/drivers/input/touchscreen/mtouch.c
@@ -205,8 +205,7 @@ static struct serio_driver mtouch_drv =
static int __init mtouch_init(void)
{
- serio_register_driver(&mtouch_drv);
- return 0;
+ return serio_register_driver(&mtouch_drv);
}
static void __exit mtouch_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/penmount.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/penmount.c
+++ work-fault-inject/drivers/input/touchscreen/penmount.c
@@ -171,8 +171,7 @@ static struct serio_driver pm_drv = {
static int __init pm_init(void)
{
- serio_register_driver(&pm_drv);
- return 0;
+ return serio_register_driver(&pm_drv);
}
static void __exit pm_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/touchright.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/touchright.c
+++ work-fault-inject/drivers/input/touchscreen/touchright.c
@@ -182,8 +182,7 @@ static struct serio_driver tr_drv = {
static int __init tr_init(void)
{
- serio_register_driver(&tr_drv);
- return 0;
+ return serio_register_driver(&tr_drv);
}
static void __exit tr_exit(void)
Index: work-fault-inject/drivers/input/touchscreen/touchwin.c
===================================================================
--- work-fault-inject.orig/drivers/input/touchscreen/touchwin.c
+++ work-fault-inject/drivers/input/touchscreen/touchwin.c
@@ -189,8 +189,7 @@ static struct serio_driver tw_drv = {
static int __init tw_init(void)
{
- serio_register_driver(&tw_drv);
- return 0;
+ return serio_register_driver(&tw_drv);
}
static void __exit tw_exit(void)
Index: work-fault-inject/drivers/input/keyboard/atkbd.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/atkbd.c
+++ work-fault-inject/drivers/input/keyboard/atkbd.c
@@ -1293,8 +1293,7 @@ static ssize_t atkbd_show_err_count(stru
static int __init atkbd_init(void)
{
- serio_register_driver(&atkbd_drv);
- return 0;
+ return serio_register_driver(&atkbd_drv);
}
static void __exit atkbd_exit(void)
Index: work-fault-inject/drivers/input/keyboard/hil_kbd.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/hil_kbd.c
+++ work-fault-inject/drivers/input/keyboard/hil_kbd.c
@@ -381,8 +381,7 @@ struct serio_driver hil_kbd_serio_drv =
static int __init hil_kbd_init(void)
{
- serio_register_driver(&hil_kbd_serio_drv);
- return 0;
+ return serio_register_driver(&hil_kbd_serio_drv);
}
static void __exit hil_kbd_exit(void)
Index: work-fault-inject/drivers/input/keyboard/lkkbd.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/lkkbd.c
+++ work-fault-inject/drivers/input/keyboard/lkkbd.c
@@ -754,8 +754,7 @@ static struct serio_driver lkkbd_drv = {
static int __init
lkkbd_init (void)
{
- serio_register_driver(&lkkbd_drv);
- return 0;
+ return serio_register_driver(&lkkbd_drv);
}
static void __exit
Index: work-fault-inject/drivers/input/keyboard/newtonkbd.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/newtonkbd.c
+++ work-fault-inject/drivers/input/keyboard/newtonkbd.c
@@ -165,8 +165,7 @@ static struct serio_driver nkbd_drv = {
static int __init nkbd_init(void)
{
- serio_register_driver(&nkbd_drv);
- return 0;
+ return serio_register_driver(&nkbd_drv);
}
static void __exit nkbd_exit(void)
Index: work-fault-inject/drivers/input/keyboard/stowaway.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/stowaway.c
+++ work-fault-inject/drivers/input/keyboard/stowaway.c
@@ -173,8 +173,7 @@ static struct serio_driver skbd_drv = {
static int __init skbd_init(void)
{
- serio_register_driver(&skbd_drv);
- return 0;
+ return serio_register_driver(&skbd_drv);
}
static void __exit skbd_exit(void)
Index: work-fault-inject/drivers/input/keyboard/sunkbd.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/sunkbd.c
+++ work-fault-inject/drivers/input/keyboard/sunkbd.c
@@ -346,8 +346,7 @@ static struct serio_driver sunkbd_drv =
static int __init sunkbd_init(void)
{
- serio_register_driver(&sunkbd_drv);
- return 0;
+ return serio_register_driver(&sunkbd_drv);
}
static void __exit sunkbd_exit(void)
Index: work-fault-inject/drivers/input/keyboard/xtkbd.c
===================================================================
--- work-fault-inject.orig/drivers/input/keyboard/xtkbd.c
+++ work-fault-inject/drivers/input/keyboard/xtkbd.c
@@ -170,8 +170,7 @@ static struct serio_driver xtkbd_drv = {
static int __init xtkbd_init(void)
{
- serio_register_driver(&xtkbd_drv);
- return 0;
+ return serio_register_driver(&xtkbd_drv);
}
static void __exit xtkbd_exit(void)
Index: work-fault-inject/drivers/input/mouse/hil_ptr.c
===================================================================
--- work-fault-inject.orig/drivers/input/mouse/hil_ptr.c
+++ work-fault-inject/drivers/input/mouse/hil_ptr.c
@@ -417,8 +417,7 @@ static struct serio_driver hil_ptr_serio
static int __init hil_ptr_init(void)
{
- serio_register_driver(&hil_ptr_serio_driver);
- return 0;
+ return serio_register_driver(&hil_ptr_serio_driver);
}
static void __exit hil_ptr_exit(void)
Index: work-fault-inject/drivers/input/mouse/sermouse.c
===================================================================
--- work-fault-inject.orig/drivers/input/mouse/sermouse.c
+++ work-fault-inject/drivers/input/mouse/sermouse.c
@@ -348,8 +348,7 @@ static struct serio_driver sermouse_drv
static int __init sermouse_init(void)
{
- serio_register_driver(&sermouse_drv);
- return 0;
+ return serio_register_driver(&sermouse_drv);
}
static void __exit sermouse_exit(void)
Index: work-fault-inject/drivers/input/joystick/iforce/iforce-main.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/iforce/iforce-main.c
+++ work-fault-inject/drivers/input/joystick/iforce/iforce-main.c
@@ -464,13 +464,21 @@ int iforce_init_device(struct iforce *if
static int __init iforce_init(void)
{
+ int err = 0;
+
#ifdef CONFIG_JOYSTICK_IFORCE_USB
- usb_register(&iforce_usb_driver);
+ err = usb_register(&iforce_usb_driver);
+ if (err)
+ return err;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
- serio_register_driver(&iforce_serio_drv);
+ err = serio_register_driver(&iforce_serio_drv);
+#ifdef CONFIG_JOYSTICK_IFORCE_USB
+ if (err)
+ usb_deregister(&iforce_usb_driver);
+#endif
#endif
- return 0;
+ return err;
}
static void __exit iforce_exit(void)
Index: work-fault-inject/drivers/input/joystick/magellan.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/magellan.c
+++ work-fault-inject/drivers/input/joystick/magellan.c
@@ -227,8 +227,7 @@ static struct serio_driver magellan_drv
static int __init magellan_init(void)
{
- serio_register_driver(&magellan_drv);
- return 0;
+ return serio_register_driver(&magellan_drv);
}
static void __exit magellan_exit(void)
Index: work-fault-inject/drivers/input/joystick/spaceball.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/spaceball.c
+++ work-fault-inject/drivers/input/joystick/spaceball.c
@@ -296,8 +296,7 @@ static struct serio_driver spaceball_drv
static int __init spaceball_init(void)
{
- serio_register_driver(&spaceball_drv);
- return 0;
+ return serio_register_driver(&spaceball_drv);
}
static void __exit spaceball_exit(void)
Index: work-fault-inject/drivers/input/joystick/spaceorb.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/spaceorb.c
+++ work-fault-inject/drivers/input/joystick/spaceorb.c
@@ -242,8 +242,7 @@ static struct serio_driver spaceorb_drv
static int __init spaceorb_init(void)
{
- serio_register_driver(&spaceorb_drv);
- return 0;
+ return serio_register_driver(&spaceorb_drv);
}
static void __exit spaceorb_exit(void)
Index: work-fault-inject/drivers/input/joystick/stinger.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/stinger.c
+++ work-fault-inject/drivers/input/joystick/stinger.c
@@ -212,8 +212,7 @@ static struct serio_driver stinger_drv =
static int __init stinger_init(void)
{
- serio_register_driver(&stinger_drv);
- return 0;
+ return serio_register_driver(&stinger_drv);
}
static void __exit stinger_exit(void)
Index: work-fault-inject/drivers/input/joystick/twidjoy.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/twidjoy.c
+++ work-fault-inject/drivers/input/joystick/twidjoy.c
@@ -265,8 +265,7 @@ static struct serio_driver twidjoy_drv =
static int __init twidjoy_init(void)
{
- serio_register_driver(&twidjoy_drv);
- return 0;
+ return serio_register_driver(&twidjoy_drv);
}
static void __exit twidjoy_exit(void)
Index: work-fault-inject/drivers/input/joystick/warrior.c
===================================================================
--- work-fault-inject.orig/drivers/input/joystick/warrior.c
+++ work-fault-inject/drivers/input/joystick/warrior.c
@@ -220,8 +220,7 @@ static struct serio_driver warrior_drv =
static int __init warrior_init(void)
{
- serio_register_driver(&warrior_drv);
- return 0;
+ return serio_register_driver(&warrior_drv);
}
static void __exit warrior_exit(void)
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/4] input: check whether serio dirver registration is completed
2006-11-08 12:36 ` Akinobu Mita
2006-11-08 12:38 ` [PATCH 1/4] input: make serio_register_driver() return error Akinobu Mita
2006-11-08 12:39 ` [PATCH 2/4] input: check serio_register_driver() error Akinobu Mita
@ 2006-11-08 12:40 ` Akinobu Mita
2006-11-11 16:12 ` Alexey Dobriyan
2006-11-08 12:41 ` [PATCH 4/4] input: change to GFP_KERNEL for SERIO_REGISTER_DRIVER event allocation Akinobu Mita
2006-11-17 6:37 ` [PATCH 1/2] input: make serio_register_driver() return error code Dmitry Torokhov
4 siblings, 1 reply; 10+ messages in thread
From: Akinobu Mita @ 2006-11-08 12:40 UTC (permalink / raw)
To: Dmitry Torokhov, linux-kernel
This patch adds a flag to serio driver indicating whether registration is
complete and check that flag in serio_unregister_driver.
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
drivers/input/serio/serio.c | 7 ++++++-
include/linux/serio.h | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
Index: work-fault-inject/include/linux/serio.h
===================================================================
--- work-fault-inject.orig/include/linux/serio.h
+++ work-fault-inject/include/linux/serio.h
@@ -68,6 +68,7 @@ struct serio_driver {
void (*cleanup)(struct serio *);
struct device_driver driver;
+ int registered;
};
#define to_serio_driver(d) container_of(d, struct serio_driver, driver)
Index: work-fault-inject/drivers/input/serio/serio.c
===================================================================
--- work-fault-inject.orig/drivers/input/serio/serio.c
+++ work-fault-inject/drivers/input/serio/serio.c
@@ -804,6 +804,8 @@ static void serio_add_driver(struct seri
printk(KERN_ERR
"serio: driver_register() failed for %s, error: %d\n",
drv->driver.name, error);
+ else
+ drv->registered = 1;
}
int __serio_register_driver(struct serio_driver *drv, struct module *owner)
@@ -830,7 +832,10 @@ start_over:
}
}
- driver_unregister(&drv->driver);
+ if (drv->registered) {
+ driver_unregister(&drv->driver);
+ drv->registered = 0;
+ }
mutex_unlock(&serio_mutex);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/4] input: change to GFP_KERNEL for SERIO_REGISTER_DRIVER event allocation
2006-11-08 12:36 ` Akinobu Mita
` (2 preceding siblings ...)
2006-11-08 12:40 ` [PATCH 3/4] input: check whether serio dirver registration is completed Akinobu Mita
@ 2006-11-08 12:41 ` Akinobu Mita
2006-11-17 6:37 ` [PATCH 1/2] input: make serio_register_driver() return error code Dmitry Torokhov
4 siblings, 0 replies; 10+ messages in thread
From: Akinobu Mita @ 2006-11-08 12:41 UTC (permalink / raw)
To: Dmitry Torokhov, linux-kernel
This patch changes allocation from GFP_ATOMIC to GFP_KERNEL for
SERIO_REGISTER_DRIVER events to make it more robust.
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
drivers/input/serio/serio.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
Index: work-fault-inject/drivers/input/serio/serio.c
===================================================================
--- work-fault-inject.orig/drivers/input/serio/serio.c
+++ work-fault-inject/drivers/input/serio/serio.c
@@ -191,12 +191,15 @@ static DECLARE_WAIT_QUEUE_HEAD(serio_wai
static struct task_struct *serio_task;
static int serio_queue_event(void *object, struct module *owner,
- enum serio_event_type event_type)
+ enum serio_event_type event_type, gfp_t gfp_flags)
{
unsigned long flags;
struct serio_event *event;
+ struct serio_event *new_event;
int err = 0;
+ new_event = kmalloc(sizeof(struct serio_event), gfp_flags);
+
spin_lock_irqsave(&serio_event_lock, flags);
/*
@@ -208,25 +211,27 @@ static int serio_queue_event(void *objec
*/
list_for_each_entry_reverse(event, &serio_event_list, node) {
if (event->object == object) {
- if (event->type == event_type)
+ if (event->type == event_type) {
+ kfree(new_event);
goto out;
+ }
break;
}
}
- if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+ if (new_event) {
if (!try_module_get(owner)) {
err = -EINVAL;
printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
- kfree(event);
+ kfree(new_event);
goto out;
}
- event->type = event_type;
- event->object = object;
- event->owner = owner;
+ new_event->type = event_type;
+ new_event->object = object;
+ new_event->owner = owner;
- list_add_tail(&event->node, &serio_event_list);
+ list_add_tail(&new_event->node, &serio_event_list);
wake_up(&serio_wait);
} else {
err = -ENOMEM;
@@ -679,12 +684,12 @@ static void serio_disconnect_port(struct
void serio_rescan(struct serio *serio)
{
- serio_queue_event(serio, NULL, SERIO_RESCAN);
+ serio_queue_event(serio, NULL, SERIO_RESCAN, GFP_ATOMIC);
}
void serio_reconnect(struct serio *serio)
{
- serio_queue_event(serio, NULL, SERIO_RECONNECT);
+ serio_queue_event(serio, NULL, SERIO_RECONNECT, GFP_ATOMIC);
}
/*
@@ -694,7 +699,7 @@ void serio_reconnect(struct serio *serio
void __serio_register_port(struct serio *serio, struct module *owner)
{
serio_init_port(serio);
- serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
+ serio_queue_event(serio, owner, SERIO_REGISTER_PORT, GFP_ATOMIC);
}
/*
@@ -728,7 +733,7 @@ void serio_unregister_child_port(struct
*/
void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
{
- serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT);
+ serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT, GFP_ATOMIC);
}
@@ -812,7 +817,7 @@ int __serio_register_driver(struct serio
{
drv->driver.bus = &serio_bus;
- return serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
+ return serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER, GFP_KERNEL);
}
void serio_unregister_driver(struct serio_driver *drv)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/4] input: check whether serio dirver registration is completed
2006-11-08 12:40 ` [PATCH 3/4] input: check whether serio dirver registration is completed Akinobu Mita
@ 2006-11-11 16:12 ` Alexey Dobriyan
0 siblings, 0 replies; 10+ messages in thread
From: Alexey Dobriyan @ 2006-11-11 16:12 UTC (permalink / raw)
To: Akinobu Mita, Dmitry Torokhov, linux-kernel
On Wed, Nov 08, 2006 at 09:40:10PM +0900, Akinobu Mita wrote:
> This patch adds a flag to serio driver indicating whether registration is
> complete and check that flag in serio_unregister_driver.
> --- work-fault-inject.orig/include/linux/serio.h
> +++ work-fault-inject/include/linux/serio.h
> @@ -68,6 +68,7 @@ struct serio_driver {
> void (*cleanup)(struct serio *);
>
> struct device_driver driver;
> + int registered;
bitfield please.
> --- work-fault-inject.orig/drivers/input/serio/serio.c
> +++ work-fault-inject/drivers/input/serio/serio.c
> @@ -804,6 +804,8 @@ static void serio_add_driver(struct seri
> printk(KERN_ERR
> "serio: driver_register() failed for %s, error: %d\n",
> drv->driver.name, error);
> + else
> + drv->registered = 1;
> }
>
> int __serio_register_driver(struct serio_driver *drv, struct module *owne
> @@ -830,7 +832,10 @@ start_over:
> }
> }
>
> - driver_unregister(&drv->driver);
> + if (drv->registered) {
> + driver_unregister(&drv->driver);
> + drv->registered = 0;
> + }
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] input: make serio_register_driver() return error code
2006-11-08 12:36 ` Akinobu Mita
` (3 preceding siblings ...)
2006-11-08 12:41 ` [PATCH 4/4] input: change to GFP_KERNEL for SERIO_REGISTER_DRIVER event allocation Akinobu Mita
@ 2006-11-17 6:37 ` Dmitry Torokhov
2006-11-18 6:51 ` Akinobu Mita
4 siblings, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2006-11-17 6:37 UTC (permalink / raw)
To: Akinobu Mita; +Cc: linux-kernel
On Wednesday 08 November 2006 07:36, Akinobu Mita wrote:
>
> 2) driver_register() failure by kseriod.
>
> This failure cannot be checked by serio_register_driver().
> But it is necessary to prevent serio_unregister_driver() from
> trying to call driver_unregister() with not registered driver
> by adding flag to serio driver indicating whether registration is
> complete.
>
Hi Akinobu,
I think I found a way to handle all errors when registering serio driver.
What do you think about the patch below?
--
Dmitry
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/serio/serio.c | 109 ++++++++++++++++++++++++++++++--------------
include/linux/serio.h | 7 --
2 files changed, 76 insertions(+), 40 deletions(-)
Index: work/drivers/input/serio/serio.c
===================================================================
--- work.orig/drivers/input/serio/serio.c
+++ work/drivers/input/serio/serio.c
@@ -44,7 +44,7 @@ EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_child_port);
-EXPORT_SYMBOL(__serio_register_driver);
+EXPORT_SYMBOL(serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
@@ -61,10 +61,10 @@ static LIST_HEAD(serio_list);
static struct bus_type serio_bus;
-static void serio_add_driver(struct serio_driver *drv);
static void serio_add_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio);
+static void serio_attach_driver(struct serio_driver *drv);
static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
{
@@ -168,10 +168,10 @@ static void serio_find_driver(struct ser
*/
enum serio_event_type {
- SERIO_RESCAN,
- SERIO_RECONNECT,
+ SERIO_RESCAN_PORT,
+ SERIO_RECONNECT_PORT,
SERIO_REGISTER_PORT,
- SERIO_REGISTER_DRIVER,
+ SERIO_ATTACH_DRIVER,
};
struct serio_event {
@@ -186,11 +186,12 @@ static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static struct task_struct *serio_task;
-static void serio_queue_event(void *object, struct module *owner,
- enum serio_event_type event_type)
+static int serio_queue_event(void *object, struct module *owner,
+ enum serio_event_type event_type)
{
unsigned long flags;
struct serio_event *event;
+ int retval = 0;
spin_lock_irqsave(&serio_event_lock, flags);
@@ -209,24 +210,34 @@ static void serio_queue_event(void *obje
}
}
- if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
- if (!try_module_get(owner)) {
- printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
- kfree(event);
- goto out;
- }
-
- event->type = event_type;
- event->object = object;
- event->owner = owner;
+ event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
+ if (!event) {
+ printk(KERN_ERR
+ "serio: Not enough memory to queue event %d\n",
+ event_type);
+ retval = -ENOMEM;
+ goto out;
+ }
- list_add_tail(&event->node, &serio_event_list);
- wake_up(&serio_wait);
- } else {
- printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type);
+ if (!try_module_get(owner)) {
+ printk(KERN_WARNING
+ "serio: Can't get module reference, dropping event %d\n",
+ event_type);
+ kfree(event);
+ retval = -EINVAL;
+ goto out;
}
+
+ event->type = event_type;
+ event->object = object;
+ event->owner = owner;
+
+ list_add_tail(&event->node, &serio_event_list);
+ wake_up(&serio_wait);
+
out:
spin_unlock_irqrestore(&serio_event_lock, flags);
+ return retval;
}
static void serio_free_event(struct serio_event *event)
@@ -304,17 +315,17 @@ static void serio_handle_event(void)
serio_add_port(event->object);
break;
- case SERIO_RECONNECT:
+ case SERIO_RECONNECT_PORT:
serio_reconnect_port(event->object);
break;
- case SERIO_RESCAN:
+ case SERIO_RESCAN_PORT:
serio_disconnect_port(event->object);
serio_find_driver(event->object);
break;
- case SERIO_REGISTER_DRIVER:
- serio_add_driver(event->object);
+ case SERIO_ATTACH_DRIVER:
+ serio_attach_driver(event->object);
break;
default:
@@ -666,12 +677,12 @@ static void serio_disconnect_port(struct
void serio_rescan(struct serio *serio)
{
- serio_queue_event(serio, NULL, SERIO_RESCAN);
+ serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
}
void serio_reconnect(struct serio *serio)
{
- serio_queue_event(serio, NULL, SERIO_RECONNECT);
+ serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
}
/*
@@ -766,22 +777,52 @@ static int serio_driver_remove(struct de
return 0;
}
-static void serio_add_driver(struct serio_driver *drv)
+static void serio_attach_driver(struct serio_driver *drv)
{
int error;
- error = driver_register(&drv->driver);
+ error = driver_attach(&drv->driver);
if (error)
- printk(KERN_ERR
- "serio: driver_register() failed for %s, error: %d\n",
- drv->driver.name, error);
+ printk(KERN_WARNING
+ "serio: driver_attach() failed with error %d\n",
+ error);
}
-void __serio_register_driver(struct serio_driver *drv, struct module *owner)
+int serio_register_driver(struct serio_driver *drv)
{
+ int manual_bind = drv->manual_bind;
+ int error;
+
drv->driver.bus = &serio_bus;
- serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
+ /*
+ * Temporarily disable automatic binding because probing
+ * takes long time and we are better off doing it in kseriod
+ */
+ drv->manual_bind = 1;
+
+ error = driver_register(&drv->driver);
+ if (error) {
+ printk(KERN_ERR
+ "serio: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+ return error;
+ }
+
+ /*
+ * Restore original bind mode and let kseriod bind the
+ * driver to free ports
+ */
+ if (!manual_bind) {
+ drv->manual_bind = 0;
+ error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
+ if (error) {
+ driver_unregister(&drv->driver);
+ return error;
+ }
+ }
+
+ return 0;
}
void serio_unregister_driver(struct serio_driver *drv)
Index: work/include/linux/serio.h
===================================================================
--- work.orig/include/linux/serio.h
+++ work/include/linux/serio.h
@@ -86,12 +86,7 @@ static inline void serio_register_port(s
void serio_unregister_port(struct serio *serio);
void serio_unregister_child_port(struct serio *serio);
-void __serio_register_driver(struct serio_driver *drv, struct module *owner);
-static inline void serio_register_driver(struct serio_driver *drv)
-{
- __serio_register_driver(drv, THIS_MODULE);
-}
-
+int serio_register_driver(struct serio_driver *drv);
void serio_unregister_driver(struct serio_driver *drv);
static inline int serio_write(struct serio *serio, unsigned char data)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] input: make serio_register_driver() return error code
2006-11-17 6:37 ` [PATCH 1/2] input: make serio_register_driver() return error code Dmitry Torokhov
@ 2006-11-18 6:51 ` Akinobu Mita
0 siblings, 0 replies; 10+ messages in thread
From: Akinobu Mita @ 2006-11-18 6:51 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-kernel
On Fri, Nov 17, 2006 at 01:37:34AM -0500, Dmitry Torokhov wrote:
> I think I found a way to handle all errors when registering serio driver.
> What do you think about the patch below?
>
Looks good to me.
I also tested this patch with my patch 2/4 (which actually checking
the return code of serio_register_driver() for each input driver).
Acked-by: Akinobu Mita <akinobu.mita@gmail.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2006-11-18 6:57 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-07 12:06 [PATCH 1/2] input: make serio_register_driver() return error code Akinobu Mita
2006-11-07 14:20 ` Dmitry Torokhov
2006-11-08 12:36 ` Akinobu Mita
2006-11-08 12:38 ` [PATCH 1/4] input: make serio_register_driver() return error Akinobu Mita
2006-11-08 12:39 ` [PATCH 2/4] input: check serio_register_driver() error Akinobu Mita
2006-11-08 12:40 ` [PATCH 3/4] input: check whether serio dirver registration is completed Akinobu Mita
2006-11-11 16:12 ` Alexey Dobriyan
2006-11-08 12:41 ` [PATCH 4/4] input: change to GFP_KERNEL for SERIO_REGISTER_DRIVER event allocation Akinobu Mita
2006-11-17 6:37 ` [PATCH 1/2] input: make serio_register_driver() return error code Dmitry Torokhov
2006-11-18 6:51 ` Akinobu Mita
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).