aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2008-06-06 01:33:22 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-07-30 00:41:15 -0400
commit6902c0bead4ce266226fc0c5b3828b850bdc884a (patch)
treec3e8e280e56089dc4e9f4410128e17c8de0f8bee
parent6e86841d05f371b5b9b86ce76c02aaee83352298 (diff)
Input: gameport - make gameport_register_driver() return errors
Perform actual driver registration right in gameport_register_driver() instead of offloading it to kgameportd and return proper error code to callers if driver registration fails. Note that driver <-> port matching is still done by kgameportd. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/gameport/gameport.c88
-rw-r--r--include/linux/gameport.h7
2 files changed, 71 insertions, 24 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 078e4eed089..2880eaae157 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport)
231enum gameport_event_type { 231enum gameport_event_type {
232 GAMEPORT_REGISTER_PORT, 232 GAMEPORT_REGISTER_PORT,
233 GAMEPORT_REGISTER_DRIVER, 233 GAMEPORT_REGISTER_DRIVER,
234 GAMEPORT_ATTACH_DRIVER,
234}; 235};
235 236
236struct gameport_event { 237struct gameport_event {
@@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list);
245static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); 246static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
246static struct task_struct *gameport_task; 247static struct task_struct *gameport_task;
247 248
248static void gameport_queue_event(void *object, struct module *owner, 249static int gameport_queue_event(void *object, struct module *owner,
249 enum gameport_event_type event_type) 250 enum gameport_event_type event_type)
250{ 251{
251 unsigned long flags; 252 unsigned long flags;
252 struct gameport_event *event; 253 struct gameport_event *event;
254 int retval = 0;
253 255
254 spin_lock_irqsave(&gameport_event_lock, flags); 256 spin_lock_irqsave(&gameport_event_lock, flags);
255 257
@@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner,
268 } 270 }
269 } 271 }
270 272
271 if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) { 273 event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
272 if (!try_module_get(owner)) { 274 if (!event) {
273 printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type); 275 printk(KERN_ERR
274 kfree(event); 276 "gameport: Not enough memory to queue event %d\n",
275 goto out; 277 event_type);
276 } 278 retval = -ENOMEM;
277 279 goto out;
278 event->type = event_type; 280 }
279 event->object = object;
280 event->owner = owner;
281 281
282 list_add_tail(&event->node, &gameport_event_list); 282 if (!try_module_get(owner)) {
283 wake_up(&gameport_wait); 283 printk(KERN_WARNING
284 } else { 284 "gameport: Can't get module reference, dropping event %d\n",
285 printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type); 285 event_type);
286 kfree(event);
287 retval = -EINVAL;
288 goto out;
286 } 289 }
290
291 event->type = event_type;
292 event->object = object;
293 event->owner = owner;
294
295 list_add_tail(&event->node, &gameport_event_list);
296 wake_up(&gameport_wait);
297
287out: 298out:
288 spin_unlock_irqrestore(&gameport_event_lock, flags); 299 spin_unlock_irqrestore(&gameport_event_lock, flags);
300 return retval;
289} 301}
290 302
291static void gameport_free_event(struct gameport_event *event) 303static void gameport_free_event(struct gameport_event *event)
@@ -378,9 +390,10 @@ static void gameport_handle_event(void)
378} 390}
379 391
380/* 392/*
381 * Remove all events that have been submitted for a given gameport port. 393 * Remove all events that have been submitted for a given object,
394 * be it a gameport port or a driver.
382 */ 395 */
383static void gameport_remove_pending_events(struct gameport *gameport) 396static void gameport_remove_pending_events(void *object)
384{ 397{
385 struct list_head *node, *next; 398 struct list_head *node, *next;
386 struct gameport_event *event; 399 struct gameport_event *event;
@@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport)
390 403
391 list_for_each_safe(node, next, &gameport_event_list) { 404 list_for_each_safe(node, next, &gameport_event_list) {
392 event = list_entry(node, struct gameport_event, node); 405 event = list_entry(node, struct gameport_event, node);
393 if (event->object == gameport) { 406 if (event->object == object) {
394 list_del_init(node); 407 list_del_init(node);
395 gameport_free_event(event); 408 gameport_free_event(event);
396 } 409 }
@@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv)
705 drv->driver.name, error); 718 drv->driver.name, error);
706} 719}
707 720
708void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) 721int __gameport_register_driver(struct gameport_driver *drv, struct module *owner,
722 const char *mod_name)
709{ 723{
724 int error;
725
710 drv->driver.bus = &gameport_bus; 726 drv->driver.bus = &gameport_bus;
711 gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); 727 drv->driver.owner = owner;
728 drv->driver.mod_name = mod_name;
729
730 /*
731 * Temporarily disable automatic binding because probing
732 * takes long time and we are better off doing it in kgameportd
733 */
734 drv->ignore = 1;
735
736 error = driver_register(&drv->driver);
737 if (error) {
738 printk(KERN_ERR
739 "gameport: driver_register() failed for %s, error: %d\n",
740 drv->driver.name, error);
741 return error;
742 }
743
744 /*
745 * Reset ignore flag and let kgameportd bind the driver to free ports
746 */
747 drv->ignore = 0;
748 error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
749 if (error) {
750 driver_unregister(&drv->driver);
751 return error;
752 }
753
754 return 0;
712} 755}
713 756
714void gameport_unregister_driver(struct gameport_driver *drv) 757void gameport_unregister_driver(struct gameport_driver *drv)
@@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv)
716 struct gameport *gameport; 759 struct gameport *gameport;
717 760
718 mutex_lock(&gameport_mutex); 761 mutex_lock(&gameport_mutex);
762
719 drv->ignore = 1; /* so gameport_find_driver ignores it */ 763 drv->ignore = 1; /* so gameport_find_driver ignores it */
764 gameport_remove_pending_events(drv);
720 765
721start_over: 766start_over:
722 list_for_each_entry(gameport, &gameport_list, node) { 767 list_for_each_entry(gameport, &gameport_list, node) {
@@ -729,6 +774,7 @@ start_over:
729 } 774 }
730 775
731 driver_unregister(&drv->driver); 776 driver_unregister(&drv->driver);
777
732 mutex_unlock(&gameport_mutex); 778 mutex_unlock(&gameport_mutex);
733} 779}
734 780
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index f64e29c0ef3..5126125afd4 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -146,10 +146,11 @@ static inline void gameport_unpin_driver(struct gameport *gameport)
146 mutex_unlock(&gameport->drv_mutex); 146 mutex_unlock(&gameport->drv_mutex);
147} 147}
148 148
149void __gameport_register_driver(struct gameport_driver *drv, struct module *owner); 149int __gameport_register_driver(struct gameport_driver *drv,
150static inline void gameport_register_driver(struct gameport_driver *drv) 150 struct module *owner, const char *mod_name);
151static inline int gameport_register_driver(struct gameport_driver *drv)
151{ 152{
152 __gameport_register_driver(drv, THIS_MODULE); 153 return __gameport_register_driver(drv, THIS_MODULE, KBUILD_MODNAME);
153} 154}
154 155
155void gameport_unregister_driver(struct gameport_driver *drv); 156void gameport_unregister_driver(struct gameport_driver *drv);