aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_port.c36
-rw-r--r--drivers/usb/serial/usb-serial.c49
-rw-r--r--include/linux/tty.h10
3 files changed, 64 insertions, 31 deletions
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index c63f3d33914a..b22a61a4fbe5 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -99,10 +99,11 @@ EXPORT_SYMBOL(tty_port_tty_set);
99 99
100static void tty_port_shutdown(struct tty_port *port) 100static void tty_port_shutdown(struct tty_port *port)
101{ 101{
102 mutex_lock(&port->mutex);
102 if (port->ops->shutdown && 103 if (port->ops->shutdown &&
103 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) 104 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
104 port->ops->shutdown(port); 105 port->ops->shutdown(port);
105 106 mutex_unlock(&port->mutex);
106} 107}
107 108
108/** 109/**
@@ -381,3 +382,36 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
381 tty_port_tty_set(port, NULL); 382 tty_port_tty_set(port, NULL);
382} 383}
383EXPORT_SYMBOL(tty_port_close); 384EXPORT_SYMBOL(tty_port_close);
385
386int tty_port_open(struct tty_port *port, struct tty_struct *tty,
387 struct file *filp)
388{
389 spin_lock_irq(&port->lock);
390 if (!tty_hung_up_p(filp))
391 ++port->count;
392 spin_unlock_irq(&port->lock);
393 tty_port_tty_set(port, tty);
394
395 /*
396 * Do the device-specific open only if the hardware isn't
397 * already initialized. Serialize open and shutdown using the
398 * port mutex.
399 */
400
401 mutex_lock(&port->mutex);
402
403 if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
404 if (port->ops->activate) {
405 int retval = port->ops->activate(port, tty);
406 if (retval) {
407 mutex_unlock(&port->mutex);
408 return retval;
409 }
410 }
411 set_bit(ASYNCB_INITIALIZED, &port->flags);
412 }
413 mutex_unlock(&port->mutex);
414 return tty_port_block_til_ready(port, tty, filp);
415}
416
417EXPORT_SYMBOL(tty_port_open);
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index bd3fa7ff15b1..b0649d92251f 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -247,41 +247,31 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
247 return retval; 247 return retval;
248} 248}
249 249
250static int serial_open(struct tty_struct *tty, struct file *filp) 250static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
251{ 251{
252 struct usb_serial_port *port = tty->driver_data; 252 struct usb_serial_port *port =
253 container_of(tport, struct usb_serial_port, port);
253 struct usb_serial *serial = port->serial; 254 struct usb_serial *serial = port->serial;
254 int retval; 255 int retval;
255 256
256 dbg("%s - port %d", __func__, port->number); 257 if (mutex_lock_interruptible(&port->mutex))
257 258 return -ERESTARTSYS;
258 spin_lock_irq(&port->port.lock); 259 mutex_lock(&serial->disc_mutex);
259 if (!tty_hung_up_p(filp)) 260 if (serial->disconnected)
260 ++port->port.count; 261 retval = -ENODEV;
261 spin_unlock_irq(&port->port.lock); 262 else
262 tty_port_tty_set(&port->port, tty); 263 retval = port->serial->type->open(tty, port);
264 mutex_unlock(&serial->disc_mutex);
265 mutex_unlock(&port->mutex);
266 return retval;
267}
263 268
264 /* Do the device-specific open only if the hardware isn't 269static int serial_open(struct tty_struct *tty, struct file *filp)
265 * already initialized. 270{
266 */ 271 struct usb_serial_port *port = tty->driver_data;
267 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
268 if (mutex_lock_interruptible(&port->mutex))
269 return -ERESTARTSYS;
270 mutex_lock(&serial->disc_mutex);
271 if (serial->disconnected)
272 retval = -ENODEV;
273 else
274 retval = port->serial->type->open(tty, port);
275 mutex_unlock(&serial->disc_mutex);
276 mutex_unlock(&port->mutex);
277 if (retval)
278 return retval;
279 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
280 }
281 272
282 /* Now do the correct tty layer semantics */ 273 dbg("%s - port %d", __func__, port->number);
283 retval = tty_port_block_til_ready(&port->port, tty, filp); 274 return tty_port_open(&port->port, tty, filp);
284 return retval;
285} 275}
286 276
287/** 277/**
@@ -725,6 +715,7 @@ static void serial_dtr_rts(struct tty_port *port, int on)
725static const struct tty_port_operations serial_port_ops = { 715static const struct tty_port_operations serial_port_ops = {
726 .carrier_raised = serial_carrier_raised, 716 .carrier_raised = serial_carrier_raised,
727 .dtr_rts = serial_dtr_rts, 717 .dtr_rts = serial_dtr_rts,
718 .activate = serial_activate,
728}; 719};
729 720
730int usb_serial_probe(struct usb_interface *interface, 721int usb_serial_probe(struct usb_interface *interface,
diff --git a/include/linux/tty.h b/include/linux/tty.h
index f0f43d08d8b8..6352ac257fcb 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -190,9 +190,15 @@ struct tty_port_operations {
190 /* Control the DTR line */ 190 /* Control the DTR line */
191 void (*dtr_rts)(struct tty_port *port, int raise); 191 void (*dtr_rts)(struct tty_port *port, int raise);
192 /* Called when the last close completes or a hangup finishes 192 /* Called when the last close completes or a hangup finishes
193 IFF the port was initialized. Do not use to free resources */ 193 IFF the port was initialized. Do not use to free resources. Called
194 under the port mutex to serialize against activate/shutdowns */
194 void (*shutdown)(struct tty_port *port); 195 void (*shutdown)(struct tty_port *port);
195 void (*drop)(struct tty_port *port); 196 void (*drop)(struct tty_port *port);
197 /* Called under the port mutex from tty_port_open, serialized using
198 the port mutex */
199 /* FIXME: long term getting the tty argument *out* of this would be
200 good for consoles */
201 int (*activate)(struct tty_port *port, struct tty_struct *tty);
196}; 202};
197 203
198struct tty_port { 204struct tty_port {
@@ -467,6 +473,8 @@ extern int tty_port_close_start(struct tty_port *port,
467extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); 473extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
468extern void tty_port_close(struct tty_port *port, 474extern void tty_port_close(struct tty_port *port,
469 struct tty_struct *tty, struct file *filp); 475 struct tty_struct *tty, struct file *filp);
476extern int tty_port_open(struct tty_port *port,
477 struct tty_struct *tty, struct file *filp);
470extern inline int tty_port_users(struct tty_port *port) 478extern inline int tty_port_users(struct tty_port *port)
471{ 479{
472 return port->count + port->blocked_open; 480 return port->count + port->blocked_open;