diff options
Diffstat (limited to 'drivers/input/serio/serio.c')
-rw-r--r-- | drivers/input/serio/serio.c | 147 |
1 files changed, 85 insertions, 62 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 5f1d4032fd57..f0ce822c1028 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -45,8 +45,7 @@ EXPORT_SYMBOL(serio_interrupt); | |||
45 | EXPORT_SYMBOL(__serio_register_port); | 45 | EXPORT_SYMBOL(__serio_register_port); |
46 | EXPORT_SYMBOL(serio_unregister_port); | 46 | EXPORT_SYMBOL(serio_unregister_port); |
47 | EXPORT_SYMBOL(serio_unregister_child_port); | 47 | EXPORT_SYMBOL(serio_unregister_child_port); |
48 | EXPORT_SYMBOL(__serio_unregister_port_delayed); | 48 | EXPORT_SYMBOL(serio_register_driver); |
49 | EXPORT_SYMBOL(__serio_register_driver); | ||
50 | EXPORT_SYMBOL(serio_unregister_driver); | 49 | EXPORT_SYMBOL(serio_unregister_driver); |
51 | EXPORT_SYMBOL(serio_open); | 50 | EXPORT_SYMBOL(serio_open); |
52 | EXPORT_SYMBOL(serio_close); | 51 | EXPORT_SYMBOL(serio_close); |
@@ -63,11 +62,10 @@ static LIST_HEAD(serio_list); | |||
63 | 62 | ||
64 | static struct bus_type serio_bus; | 63 | static struct bus_type serio_bus; |
65 | 64 | ||
66 | static void serio_add_driver(struct serio_driver *drv); | ||
67 | static void serio_add_port(struct serio *serio); | 65 | static void serio_add_port(struct serio *serio); |
68 | static void serio_destroy_port(struct serio *serio); | ||
69 | static void serio_reconnect_port(struct serio *serio); | 66 | static void serio_reconnect_port(struct serio *serio); |
70 | static void serio_disconnect_port(struct serio *serio); | 67 | static void serio_disconnect_port(struct serio *serio); |
68 | static void serio_attach_driver(struct serio_driver *drv); | ||
71 | 69 | ||
72 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) | 70 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) |
73 | { | 71 | { |
@@ -171,11 +169,10 @@ static void serio_find_driver(struct serio *serio) | |||
171 | */ | 169 | */ |
172 | 170 | ||
173 | enum serio_event_type { | 171 | enum serio_event_type { |
174 | SERIO_RESCAN, | 172 | SERIO_RESCAN_PORT, |
175 | SERIO_RECONNECT, | 173 | SERIO_RECONNECT_PORT, |
176 | SERIO_REGISTER_PORT, | 174 | SERIO_REGISTER_PORT, |
177 | SERIO_UNREGISTER_PORT, | 175 | SERIO_ATTACH_DRIVER, |
178 | SERIO_REGISTER_DRIVER, | ||
179 | }; | 176 | }; |
180 | 177 | ||
181 | struct serio_event { | 178 | struct serio_event { |
@@ -190,11 +187,12 @@ static LIST_HEAD(serio_event_list); | |||
190 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | 187 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); |
191 | static struct task_struct *serio_task; | 188 | static struct task_struct *serio_task; |
192 | 189 | ||
193 | static void serio_queue_event(void *object, struct module *owner, | 190 | static int serio_queue_event(void *object, struct module *owner, |
194 | enum serio_event_type event_type) | 191 | enum serio_event_type event_type) |
195 | { | 192 | { |
196 | unsigned long flags; | 193 | unsigned long flags; |
197 | struct serio_event *event; | 194 | struct serio_event *event; |
195 | int retval = 0; | ||
198 | 196 | ||
199 | spin_lock_irqsave(&serio_event_lock, flags); | 197 | spin_lock_irqsave(&serio_event_lock, flags); |
200 | 198 | ||
@@ -213,24 +211,34 @@ static void serio_queue_event(void *object, struct module *owner, | |||
213 | } | 211 | } |
214 | } | 212 | } |
215 | 213 | ||
216 | if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { | 214 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); |
217 | if (!try_module_get(owner)) { | 215 | if (!event) { |
218 | printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type); | 216 | printk(KERN_ERR |
219 | kfree(event); | 217 | "serio: Not enough memory to queue event %d\n", |
220 | goto out; | 218 | event_type); |
221 | } | 219 | retval = -ENOMEM; |
222 | 220 | goto out; | |
223 | event->type = event_type; | 221 | } |
224 | event->object = object; | ||
225 | event->owner = owner; | ||
226 | 222 | ||
227 | list_add_tail(&event->node, &serio_event_list); | 223 | if (!try_module_get(owner)) { |
228 | wake_up(&serio_wait); | 224 | printk(KERN_WARNING |
229 | } else { | 225 | "serio: Can't get module reference, dropping event %d\n", |
230 | printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type); | 226 | event_type); |
227 | kfree(event); | ||
228 | retval = -EINVAL; | ||
229 | goto out; | ||
231 | } | 230 | } |
231 | |||
232 | event->type = event_type; | ||
233 | event->object = object; | ||
234 | event->owner = owner; | ||
235 | |||
236 | list_add_tail(&event->node, &serio_event_list); | ||
237 | wake_up(&serio_wait); | ||
238 | |||
232 | out: | 239 | out: |
233 | spin_unlock_irqrestore(&serio_event_lock, flags); | 240 | spin_unlock_irqrestore(&serio_event_lock, flags); |
241 | return retval; | ||
234 | } | 242 | } |
235 | 243 | ||
236 | static void serio_free_event(struct serio_event *event) | 244 | static void serio_free_event(struct serio_event *event) |
@@ -308,22 +316,17 @@ static void serio_handle_event(void) | |||
308 | serio_add_port(event->object); | 316 | serio_add_port(event->object); |
309 | break; | 317 | break; |
310 | 318 | ||
311 | case SERIO_UNREGISTER_PORT: | 319 | case SERIO_RECONNECT_PORT: |
312 | serio_disconnect_port(event->object); | ||
313 | serio_destroy_port(event->object); | ||
314 | break; | ||
315 | |||
316 | case SERIO_RECONNECT: | ||
317 | serio_reconnect_port(event->object); | 320 | serio_reconnect_port(event->object); |
318 | break; | 321 | break; |
319 | 322 | ||
320 | case SERIO_RESCAN: | 323 | case SERIO_RESCAN_PORT: |
321 | serio_disconnect_port(event->object); | 324 | serio_disconnect_port(event->object); |
322 | serio_find_driver(event->object); | 325 | serio_find_driver(event->object); |
323 | break; | 326 | break; |
324 | 327 | ||
325 | case SERIO_REGISTER_DRIVER: | 328 | case SERIO_ATTACH_DRIVER: |
326 | serio_add_driver(event->object); | 329 | serio_attach_driver(event->object); |
327 | break; | 330 | break; |
328 | 331 | ||
329 | default: | 332 | default: |
@@ -675,12 +678,12 @@ static void serio_disconnect_port(struct serio *serio) | |||
675 | 678 | ||
676 | void serio_rescan(struct serio *serio) | 679 | void serio_rescan(struct serio *serio) |
677 | { | 680 | { |
678 | serio_queue_event(serio, NULL, SERIO_RESCAN); | 681 | serio_queue_event(serio, NULL, SERIO_RESCAN_PORT); |
679 | } | 682 | } |
680 | 683 | ||
681 | void serio_reconnect(struct serio *serio) | 684 | void serio_reconnect(struct serio *serio) |
682 | { | 685 | { |
683 | serio_queue_event(serio, NULL, SERIO_RECONNECT); | 686 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); |
684 | } | 687 | } |
685 | 688 | ||
686 | /* | 689 | /* |
@@ -717,16 +720,6 @@ void serio_unregister_child_port(struct serio *serio) | |||
717 | mutex_unlock(&serio_mutex); | 720 | mutex_unlock(&serio_mutex); |
718 | } | 721 | } |
719 | 722 | ||
720 | /* | ||
721 | * Submits register request to kseriod for subsequent execution. | ||
722 | * Can be used when it is not obvious whether the serio_mutex is | ||
723 | * taken or not and when delayed execution is feasible. | ||
724 | */ | ||
725 | void __serio_unregister_port_delayed(struct serio *serio, struct module *owner) | ||
726 | { | ||
727 | serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT); | ||
728 | } | ||
729 | |||
730 | 723 | ||
731 | /* | 724 | /* |
732 | * Serio driver operations | 725 | * Serio driver operations |
@@ -785,28 +778,52 @@ static int serio_driver_remove(struct device *dev) | |||
785 | return 0; | 778 | return 0; |
786 | } | 779 | } |
787 | 780 | ||
788 | static struct bus_type serio_bus = { | 781 | static void serio_attach_driver(struct serio_driver *drv) |
789 | .name = "serio", | ||
790 | .probe = serio_driver_probe, | ||
791 | .remove = serio_driver_remove, | ||
792 | }; | ||
793 | |||
794 | static void serio_add_driver(struct serio_driver *drv) | ||
795 | { | 782 | { |
796 | int error; | 783 | int error; |
797 | 784 | ||
798 | error = driver_register(&drv->driver); | 785 | error = driver_attach(&drv->driver); |
799 | if (error) | 786 | if (error) |
800 | printk(KERN_ERR | 787 | printk(KERN_WARNING |
801 | "serio: driver_register() failed for %s, error: %d\n", | 788 | "serio: driver_attach() failed for %s with error %d\n", |
802 | drv->driver.name, error); | 789 | drv->driver.name, error); |
803 | } | 790 | } |
804 | 791 | ||
805 | void __serio_register_driver(struct serio_driver *drv, struct module *owner) | 792 | int serio_register_driver(struct serio_driver *drv) |
806 | { | 793 | { |
794 | int manual_bind = drv->manual_bind; | ||
795 | int error; | ||
796 | |||
807 | drv->driver.bus = &serio_bus; | 797 | drv->driver.bus = &serio_bus; |
808 | 798 | ||
809 | serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); | 799 | /* |
800 | * Temporarily disable automatic binding because probing | ||
801 | * takes long time and we are better off doing it in kseriod | ||
802 | */ | ||
803 | drv->manual_bind = 1; | ||
804 | |||
805 | error = driver_register(&drv->driver); | ||
806 | if (error) { | ||
807 | printk(KERN_ERR | ||
808 | "serio: driver_register() failed for %s, error: %d\n", | ||
809 | drv->driver.name, error); | ||
810 | return error; | ||
811 | } | ||
812 | |||
813 | /* | ||
814 | * Restore original bind mode and let kseriod bind the | ||
815 | * driver to free ports | ||
816 | */ | ||
817 | if (!manual_bind) { | ||
818 | drv->manual_bind = 0; | ||
819 | error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER); | ||
820 | if (error) { | ||
821 | driver_unregister(&drv->driver); | ||
822 | return error; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | return 0; | ||
810 | } | 827 | } |
811 | 828 | ||
812 | void serio_unregister_driver(struct serio_driver *drv) | 829 | void serio_unregister_driver(struct serio_driver *drv) |
@@ -947,15 +964,21 @@ irqreturn_t serio_interrupt(struct serio *serio, | |||
947 | return ret; | 964 | return ret; |
948 | } | 965 | } |
949 | 966 | ||
967 | static struct bus_type serio_bus = { | ||
968 | .name = "serio", | ||
969 | .dev_attrs = serio_device_attrs, | ||
970 | .drv_attrs = serio_driver_attrs, | ||
971 | .match = serio_bus_match, | ||
972 | .uevent = serio_uevent, | ||
973 | .probe = serio_driver_probe, | ||
974 | .remove = serio_driver_remove, | ||
975 | .resume = serio_resume, | ||
976 | }; | ||
977 | |||
950 | static int __init serio_init(void) | 978 | static int __init serio_init(void) |
951 | { | 979 | { |
952 | int error; | 980 | int error; |
953 | 981 | ||
954 | serio_bus.dev_attrs = serio_device_attrs; | ||
955 | serio_bus.drv_attrs = serio_driver_attrs; | ||
956 | serio_bus.match = serio_bus_match; | ||
957 | serio_bus.uevent = serio_uevent; | ||
958 | serio_bus.resume = serio_resume; | ||
959 | error = bus_register(&serio_bus); | 982 | error = bus_register(&serio_bus); |
960 | if (error) { | 983 | if (error) { |
961 | printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); | 984 | printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); |