aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/serial/usb-serial.c59
1 files changed, 22 insertions, 37 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 9a3258046c8c..9d7ca4868d37 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -245,55 +245,40 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
245 return retval; 245 return retval;
246} 246}
247 247
248static int serial_open (struct tty_struct *tty, struct file *filp) 248static int serial_open(struct tty_struct *tty, struct file *filp)
249{ 249{
250 struct usb_serial *serial; 250 struct usb_serial_port *port = tty->driver_data;
251 struct usb_serial_port *port; 251 struct usb_serial *serial = port->serial;
252 int retval = 0; 252 int retval;
253 int first = 0;
254
255 port = tty->driver_data;
256 serial = port->serial;
257 253
258 dbg("%s - port %d", __func__, port->number); 254 dbg("%s - port %d", __func__, port->number);
259 255
260 if (mutex_lock_interruptible(&port->mutex)) 256 spin_lock_irq(&port->port.lock);
261 return -ERESTARTSYS; 257 if (!tty_hung_up_p(filp))
262 258 ++port->port.count;
263 ++port->port.count; 259 spin_unlock_irq(&port->port.lock);
264 tty_port_tty_set(&port->port, tty); 260 tty_port_tty_set(&port->port, tty);
265 261
266 /* If the console is attached, the device is already open */ 262 /* Do the device-specific open only if the hardware isn't
267 if (port->port.count == 1 && !port->console) { 263 * already initialized.
268 first = 1; 264 */
265 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
266 if (mutex_lock_interruptible(&port->mutex))
267 return -ERESTARTSYS;
269 mutex_lock(&serial->disc_mutex); 268 mutex_lock(&serial->disc_mutex);
270 269 if (serial->disconnected)
271 /* only call the device specific open if this 270 retval = -ENODEV;
272 * is the first time the port is opened */ 271 else
273 retval = serial->type->open(tty, port); 272 retval = port->serial->type->open(tty, port);
274 if (retval)
275 goto bailout_module_put;
276 mutex_unlock(&serial->disc_mutex); 273 mutex_unlock(&serial->disc_mutex);
274 mutex_unlock(&port->mutex);
275 if (retval)
276 return retval;
277 set_bit(ASYNCB_INITIALIZED, &port->port.flags); 277 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
278 } 278 }
279 mutex_unlock(&port->mutex); 279
280 /* Now do the correct tty layer semantics */ 280 /* Now do the correct tty layer semantics */
281 retval = tty_port_block_til_ready(&port->port, tty, filp); 281 retval = tty_port_block_til_ready(&port->port, tty, filp);
282 if (retval == 0) {
283 if (!first)
284 usb_serial_put(serial);
285 return 0;
286 }
287 mutex_lock(&port->mutex);
288 if (first == 0)
289 goto bailout_mutex_unlock;
290 /* Undo the initial port actions */
291 mutex_lock(&serial->disc_mutex);
292bailout_module_put:
293 mutex_unlock(&serial->disc_mutex);
294bailout_mutex_unlock:
295 port->port.count = 0;
296 mutex_unlock(&port->mutex);
297 return retval; 282 return retval;
298} 283}
299 284