aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2006-11-23 23:34:49 -0500
committerDmitry Torokhov <dtor@insightbb.com>2006-11-23 23:34:49 -0500
commited7b1f6d6ea1054ea4fe293a7fd8015fc3803d93 (patch)
treeeb4d4f4e0eb07e7ae923f654ea09297b437409cc
parent9d92fe17b652f5496c97bc83fdfe925f3182f602 (diff)
Input: serio - make serio_register_driver() return errors
Perform actual driver registration right in serio_register_driver() instead of offloading it to kseriod and return proper error code to callers if driver registration fails. Note that driver <-> port matching is still done by kseriod to speed up boot process since probing for PS/2 mice and keyboards is pretty slow. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/serio/serio.c107
-rw-r--r--include/linux/serio.h7
2 files changed, 75 insertions, 39 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index cd55ddb7df4f..8c717042f611 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -44,7 +44,7 @@ EXPORT_SYMBOL(serio_interrupt);
44EXPORT_SYMBOL(__serio_register_port); 44EXPORT_SYMBOL(__serio_register_port);
45EXPORT_SYMBOL(serio_unregister_port); 45EXPORT_SYMBOL(serio_unregister_port);
46EXPORT_SYMBOL(serio_unregister_child_port); 46EXPORT_SYMBOL(serio_unregister_child_port);
47EXPORT_SYMBOL(__serio_register_driver); 47EXPORT_SYMBOL(serio_register_driver);
48EXPORT_SYMBOL(serio_unregister_driver); 48EXPORT_SYMBOL(serio_unregister_driver);
49EXPORT_SYMBOL(serio_open); 49EXPORT_SYMBOL(serio_open);
50EXPORT_SYMBOL(serio_close); 50EXPORT_SYMBOL(serio_close);
@@ -61,10 +61,10 @@ static LIST_HEAD(serio_list);
61 61
62static struct bus_type serio_bus; 62static struct bus_type serio_bus;
63 63
64static void serio_add_driver(struct serio_driver *drv);
65static void serio_add_port(struct serio *serio); 64static void serio_add_port(struct serio *serio);
66static void serio_reconnect_port(struct serio *serio); 65static void serio_reconnect_port(struct serio *serio);
67static void serio_disconnect_port(struct serio *serio); 66static void serio_disconnect_port(struct serio *serio);
67static void serio_attach_driver(struct serio_driver *drv);
68 68
69static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) 69static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
70{ 70{
@@ -168,10 +168,10 @@ static void serio_find_driver(struct serio *serio)
168 */ 168 */
169 169
170enum serio_event_type { 170enum serio_event_type {
171 SERIO_RESCAN, 171 SERIO_RESCAN_PORT,
172 SERIO_RECONNECT, 172 SERIO_RECONNECT_PORT,
173 SERIO_REGISTER_PORT, 173 SERIO_REGISTER_PORT,
174 SERIO_REGISTER_DRIVER, 174 SERIO_ATTACH_DRIVER,
175}; 175};
176 176
177struct serio_event { 177struct serio_event {
@@ -186,11 +186,12 @@ static LIST_HEAD(serio_event_list);
186static DECLARE_WAIT_QUEUE_HEAD(serio_wait); 186static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
187static struct task_struct *serio_task; 187static struct task_struct *serio_task;
188 188
189static void serio_queue_event(void *object, struct module *owner, 189static int serio_queue_event(void *object, struct module *owner,
190 enum serio_event_type event_type) 190 enum serio_event_type event_type)
191{ 191{
192 unsigned long flags; 192 unsigned long flags;
193 struct serio_event *event; 193 struct serio_event *event;
194 int retval = 0;
194 195
195 spin_lock_irqsave(&serio_event_lock, flags); 196 spin_lock_irqsave(&serio_event_lock, flags);
196 197
@@ -209,24 +210,34 @@ static void serio_queue_event(void *object, struct module *owner,
209 } 210 }
210 } 211 }
211 212
212 if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { 213 event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
213 if (!try_module_get(owner)) { 214 if (!event) {
214 printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type); 215 printk(KERN_ERR
215 kfree(event); 216 "serio: Not enough memory to queue event %d\n",
216 goto out; 217 event_type);
217 } 218 retval = -ENOMEM;
218 219 goto out;
219 event->type = event_type; 220 }
220 event->object = object;
221 event->owner = owner;
222 221
223 list_add_tail(&event->node, &serio_event_list); 222 if (!try_module_get(owner)) {
224 wake_up(&serio_wait); 223 printk(KERN_WARNING
225 } else { 224 "serio: Can't get module reference, dropping event %d\n",
226 printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type); 225 event_type);
226 kfree(event);
227 retval = -EINVAL;
228 goto out;
227 } 229 }
230
231 event->type = event_type;
232 event->object = object;
233 event->owner = owner;
234
235 list_add_tail(&event->node, &serio_event_list);
236 wake_up(&serio_wait);
237
228out: 238out:
229 spin_unlock_irqrestore(&serio_event_lock, flags); 239 spin_unlock_irqrestore(&serio_event_lock, flags);
240 return retval;
230} 241}
231 242
232static void serio_free_event(struct serio_event *event) 243static void serio_free_event(struct serio_event *event)
@@ -304,17 +315,17 @@ static void serio_handle_event(void)
304 serio_add_port(event->object); 315 serio_add_port(event->object);
305 break; 316 break;
306 317
307 case SERIO_RECONNECT: 318 case SERIO_RECONNECT_PORT:
308 serio_reconnect_port(event->object); 319 serio_reconnect_port(event->object);
309 break; 320 break;
310 321
311 case SERIO_RESCAN: 322 case SERIO_RESCAN_PORT:
312 serio_disconnect_port(event->object); 323 serio_disconnect_port(event->object);
313 serio_find_driver(event->object); 324 serio_find_driver(event->object);
314 break; 325 break;
315 326
316 case SERIO_REGISTER_DRIVER: 327 case SERIO_ATTACH_DRIVER:
317 serio_add_driver(event->object); 328 serio_attach_driver(event->object);
318 break; 329 break;
319 330
320 default: 331 default:
@@ -666,12 +677,12 @@ static void serio_disconnect_port(struct serio *serio)
666 677
667void serio_rescan(struct serio *serio) 678void serio_rescan(struct serio *serio)
668{ 679{
669 serio_queue_event(serio, NULL, SERIO_RESCAN); 680 serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
670} 681}
671 682
672void serio_reconnect(struct serio *serio) 683void serio_reconnect(struct serio *serio)
673{ 684{
674 serio_queue_event(serio, NULL, SERIO_RECONNECT); 685 serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
675} 686}
676 687
677/* 688/*
@@ -766,22 +777,52 @@ static int serio_driver_remove(struct device *dev)
766 return 0; 777 return 0;
767} 778}
768 779
769static void serio_add_driver(struct serio_driver *drv) 780static void serio_attach_driver(struct serio_driver *drv)
770{ 781{
771 int error; 782 int error;
772 783
773 error = driver_register(&drv->driver); 784 error = driver_attach(&drv->driver);
774 if (error) 785 if (error)
775 printk(KERN_ERR 786 printk(KERN_WARNING
776 "serio: driver_register() failed for %s, error: %d\n", 787 "serio: driver_attach() failed for %s with error %d\n",
777 drv->driver.name, error); 788 drv->driver.name, error);
778} 789}
779 790
780void __serio_register_driver(struct serio_driver *drv, struct module *owner) 791int serio_register_driver(struct serio_driver *drv)
781{ 792{
793 int manual_bind = drv->manual_bind;
794 int error;
795
782 drv->driver.bus = &serio_bus; 796 drv->driver.bus = &serio_bus;
783 797
784 serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); 798 /*
799 * Temporarily disable automatic binding because probing
800 * takes long time and we are better off doing it in kseriod
801 */
802 drv->manual_bind = 1;
803
804 error = driver_register(&drv->driver);
805 if (error) {
806 printk(KERN_ERR
807 "serio: driver_register() failed for %s, error: %d\n",
808 drv->driver.name, error);
809 return error;
810 }
811
812 /*
813 * Restore original bind mode and let kseriod bind the
814 * driver to free ports
815 */
816 if (!manual_bind) {
817 drv->manual_bind = 0;
818 error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
819 if (error) {
820 driver_unregister(&drv->driver);
821 return error;
822 }
823 }
824
825 return 0;
785} 826}
786 827
787void serio_unregister_driver(struct serio_driver *drv) 828void serio_unregister_driver(struct serio_driver *drv)
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 8f52228390ab..0f478a8791a2 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -86,12 +86,7 @@ static inline void serio_register_port(struct serio *serio)
86void serio_unregister_port(struct serio *serio); 86void serio_unregister_port(struct serio *serio);
87void serio_unregister_child_port(struct serio *serio); 87void serio_unregister_child_port(struct serio *serio);
88 88
89void __serio_register_driver(struct serio_driver *drv, struct module *owner); 89int serio_register_driver(struct serio_driver *drv);
90static inline void serio_register_driver(struct serio_driver *drv)
91{
92 __serio_register_driver(drv, THIS_MODULE);
93}
94
95void serio_unregister_driver(struct serio_driver *drv); 90void serio_unregister_driver(struct serio_driver *drv);
96 91
97static inline int serio_write(struct serio *serio, unsigned char data) 92static inline int serio_write(struct serio *serio, unsigned char data)