aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2005-06-01 03:39:44 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2005-06-01 03:39:44 -0400
commit04df1925fcda9a35c716423ad2b73abd70eb0913 (patch)
tree6094c0e71b5d17a62211cd56da7bb0ecb97a3df6 /drivers/input/serio
parent8121152c1770ef1cd029030d51802c65c489950d (diff)
Input: pmouse - introduce proper locking so state-changing
operations do not iterfere with each other. Also make sure that serio core takes serio->drv_sem not only for connect/disconnect but for reconnect too. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/serio')
-rw-r--r--drivers/input/serio/serio.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 2c93ceab831a..b82815a0b65b 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -67,6 +67,37 @@ static void serio_destroy_port(struct serio *serio);
67static void serio_reconnect_port(struct serio *serio); 67static void serio_reconnect_port(struct serio *serio);
68static void serio_disconnect_port(struct serio *serio); 68static void serio_disconnect_port(struct serio *serio);
69 69
70static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
71{
72 int retval;
73
74 down(&serio->drv_sem);
75 retval = drv->connect(serio, drv);
76 up(&serio->drv_sem);
77
78 return retval;
79}
80
81static int serio_reconnect_driver(struct serio *serio)
82{
83 int retval = -1;
84
85 down(&serio->drv_sem);
86 if (serio->drv && serio->drv->reconnect)
87 retval = serio->drv->reconnect(serio);
88 up(&serio->drv_sem);
89
90 return retval;
91}
92
93static void serio_disconnect_driver(struct serio *serio)
94{
95 down(&serio->drv_sem);
96 if (serio->drv)
97 serio->drv->disconnect(serio);
98 up(&serio->drv_sem);
99}
100
70static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) 101static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
71{ 102{
72 while (ids->type || ids->proto) { 103 while (ids->type || ids->proto) {
@@ -90,7 +121,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
90 121
91 if (serio_match_port(drv->id_table, serio)) { 122 if (serio_match_port(drv->id_table, serio)) {
92 serio->dev.driver = &drv->driver; 123 serio->dev.driver = &drv->driver;
93 if (drv->connect(serio, drv)) { 124 if (serio_connect_driver(serio, drv)) {
94 serio->dev.driver = NULL; 125 serio->dev.driver = NULL;
95 goto out; 126 goto out;
96 } 127 }
@@ -550,7 +581,7 @@ static void serio_destroy_port(struct serio *serio)
550static void serio_reconnect_port(struct serio *serio) 581static void serio_reconnect_port(struct serio *serio)
551{ 582{
552 do { 583 do {
553 if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { 584 if (serio_reconnect_driver(serio)) {
554 serio_disconnect_port(serio); 585 serio_disconnect_port(serio);
555 serio_find_driver(serio); 586 serio_find_driver(serio);
556 /* Ok, old children are now gone, we are done */ 587 /* Ok, old children are now gone, we are done */
@@ -679,15 +710,14 @@ static int serio_driver_probe(struct device *dev)
679 struct serio *serio = to_serio_port(dev); 710 struct serio *serio = to_serio_port(dev);
680 struct serio_driver *drv = to_serio_driver(dev->driver); 711 struct serio_driver *drv = to_serio_driver(dev->driver);
681 712
682 return drv->connect(serio, drv); 713 return serio_connect_driver(serio, drv);
683} 714}
684 715
685static int serio_driver_remove(struct device *dev) 716static int serio_driver_remove(struct device *dev)
686{ 717{
687 struct serio *serio = to_serio_port(dev); 718 struct serio *serio = to_serio_port(dev);
688 struct serio_driver *drv = to_serio_driver(dev->driver);
689 719
690 drv->disconnect(serio); 720 serio_disconnect_driver(serio);
691 return 0; 721 return 0;
692} 722}
693 723
@@ -723,11 +753,9 @@ start_over:
723 753
724static void serio_set_drv(struct serio *serio, struct serio_driver *drv) 754static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
725{ 755{
726 down(&serio->drv_sem);
727 serio_pause_rx(serio); 756 serio_pause_rx(serio);
728 serio->drv = drv; 757 serio->drv = drv;
729 serio_continue_rx(serio); 758 serio_continue_rx(serio);
730 up(&serio->drv_sem);
731} 759}
732 760
733static int serio_bus_match(struct device *dev, struct device_driver *drv) 761static int serio_bus_match(struct device *dev, struct device_driver *drv)
@@ -787,7 +815,7 @@ static int serio_resume(struct device *dev)
787{ 815{
788 struct serio *serio = to_serio_port(dev); 816 struct serio *serio = to_serio_port(dev);
789 817
790 if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { 818 if (serio_reconnect_driver(serio)) {
791 /* 819 /*
792 * Driver re-probing can take a while, so better let kseriod 820 * Driver re-probing can take a while, so better let kseriod
793 * deal with it. 821 * deal with it.