diff options
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/serio.c | 41 |
1 files changed, 15 insertions, 26 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index a15e531ec755..5895202b972c 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -115,18 +115,18 @@ static int serio_match_port(const struct serio_device_id *ids, struct serio *ser | |||
115 | * Basic serio -> driver core mappings | 115 | * Basic serio -> driver core mappings |
116 | */ | 116 | */ |
117 | 117 | ||
118 | static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | 118 | static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) |
119 | { | 119 | { |
120 | int error; | 120 | int error; |
121 | 121 | ||
122 | down_write(&serio_bus.subsys.rwsem); | ||
123 | |||
124 | if (serio_match_port(drv->id_table, serio)) { | 122 | if (serio_match_port(drv->id_table, serio)) { |
123 | |||
125 | serio->dev.driver = &drv->driver; | 124 | serio->dev.driver = &drv->driver; |
126 | if (serio_connect_driver(serio, drv)) { | 125 | if (serio_connect_driver(serio, drv)) { |
127 | serio->dev.driver = NULL; | 126 | serio->dev.driver = NULL; |
128 | goto out; | 127 | return -ENODEV; |
129 | } | 128 | } |
129 | |||
130 | error = device_bind_driver(&serio->dev); | 130 | error = device_bind_driver(&serio->dev); |
131 | if (error) { | 131 | if (error) { |
132 | printk(KERN_WARNING | 132 | printk(KERN_WARNING |
@@ -136,31 +136,21 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | |||
136 | drv->description, error); | 136 | drv->description, error); |
137 | serio_disconnect_driver(serio); | 137 | serio_disconnect_driver(serio); |
138 | serio->dev.driver = NULL; | 138 | serio->dev.driver = NULL; |
139 | goto out; | 139 | return error; |
140 | } | 140 | } |
141 | } | 141 | } |
142 | out: | 142 | return 0; |
143 | up_write(&serio_bus.subsys.rwsem); | ||
144 | } | ||
145 | |||
146 | static void serio_release_driver(struct serio *serio) | ||
147 | { | ||
148 | down_write(&serio_bus.subsys.rwsem); | ||
149 | device_release_driver(&serio->dev); | ||
150 | up_write(&serio_bus.subsys.rwsem); | ||
151 | } | 143 | } |
152 | 144 | ||
153 | static void serio_find_driver(struct serio *serio) | 145 | static void serio_find_driver(struct serio *serio) |
154 | { | 146 | { |
155 | int error; | 147 | int error; |
156 | 148 | ||
157 | down_write(&serio_bus.subsys.rwsem); | ||
158 | error = device_attach(&serio->dev); | 149 | error = device_attach(&serio->dev); |
159 | if (error < 0) | 150 | if (error < 0) |
160 | printk(KERN_WARNING | 151 | printk(KERN_WARNING |
161 | "serio: device_attach() failed for %s (%s), error: %d\n", | 152 | "serio: device_attach() failed for %s (%s), error: %d\n", |
162 | serio->phys, serio->name, error); | 153 | serio->phys, serio->name, error); |
163 | up_write(&serio_bus.subsys.rwsem); | ||
164 | } | 154 | } |
165 | 155 | ||
166 | 156 | ||
@@ -470,13 +460,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
470 | { | 460 | { |
471 | struct serio *serio = to_serio_port(dev); | 461 | struct serio *serio = to_serio_port(dev); |
472 | struct device_driver *drv; | 462 | struct device_driver *drv; |
473 | int retval; | 463 | int error; |
474 | 464 | ||
475 | retval = mutex_lock_interruptible(&serio_mutex); | 465 | error = mutex_lock_interruptible(&serio_mutex); |
476 | if (retval) | 466 | if (error) |
477 | return retval; | 467 | return error; |
478 | 468 | ||
479 | retval = count; | ||
480 | if (!strncmp(buf, "none", count)) { | 469 | if (!strncmp(buf, "none", count)) { |
481 | serio_disconnect_port(serio); | 470 | serio_disconnect_port(serio); |
482 | } else if (!strncmp(buf, "reconnect", count)) { | 471 | } else if (!strncmp(buf, "reconnect", count)) { |
@@ -486,15 +475,15 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
486 | serio_find_driver(serio); | 475 | serio_find_driver(serio); |
487 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 476 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
488 | serio_disconnect_port(serio); | 477 | serio_disconnect_port(serio); |
489 | serio_bind_driver(serio, to_serio_driver(drv)); | 478 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
490 | put_driver(drv); | 479 | put_driver(drv); |
491 | } else { | 480 | } else { |
492 | retval = -EINVAL; | 481 | error = -EINVAL; |
493 | } | 482 | } |
494 | 483 | ||
495 | mutex_unlock(&serio_mutex); | 484 | mutex_unlock(&serio_mutex); |
496 | 485 | ||
497 | return retval; | 486 | return error ? error : count; |
498 | } | 487 | } |
499 | 488 | ||
500 | static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf) | 489 | static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -665,7 +654,7 @@ static void serio_disconnect_port(struct serio *serio) | |||
665 | do { | 654 | do { |
666 | parent = s->parent; | 655 | parent = s->parent; |
667 | 656 | ||
668 | serio_release_driver(s); | 657 | device_release_driver(&s->dev); |
669 | serio_destroy_port(s); | 658 | serio_destroy_port(s); |
670 | } while ((s = parent) != serio); | 659 | } while ((s = parent) != serio); |
671 | } | 660 | } |
@@ -673,7 +662,7 @@ static void serio_disconnect_port(struct serio *serio) | |||
673 | /* | 662 | /* |
674 | * Ok, no children left, now disconnect this port | 663 | * Ok, no children left, now disconnect this port |
675 | */ | 664 | */ |
676 | serio_release_driver(serio); | 665 | device_release_driver(&serio->dev); |
677 | } | 666 | } |
678 | 667 | ||
679 | void serio_rescan(struct serio *serio) | 668 | void serio_rescan(struct serio *serio) |