diff options
Diffstat (limited to 'drivers/usb/serial/digi_acceleport.c')
-rw-r--r-- | drivers/usb/serial/digi_acceleport.c | 75 |
1 files changed, 21 insertions, 54 deletions
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 38ba4ea8b6b..30f5140eff0 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -422,7 +422,6 @@ struct digi_port { | |||
422 | int dp_throttled; | 422 | int dp_throttled; |
423 | int dp_throttle_restart; | 423 | int dp_throttle_restart; |
424 | wait_queue_head_t dp_flush_wait; | 424 | wait_queue_head_t dp_flush_wait; |
425 | int dp_in_close; /* close in progress */ | ||
426 | wait_queue_head_t dp_close_wait; /* wait queue for close */ | 425 | wait_queue_head_t dp_close_wait; /* wait queue for close */ |
427 | struct work_struct dp_wakeup_work; | 426 | struct work_struct dp_wakeup_work; |
428 | struct usb_serial_port *dp_port; | 427 | struct usb_serial_port *dp_port; |
@@ -456,8 +455,9 @@ static int digi_write_room(struct tty_struct *tty); | |||
456 | static int digi_chars_in_buffer(struct tty_struct *tty); | 455 | static int digi_chars_in_buffer(struct tty_struct *tty); |
457 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | 456 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, |
458 | struct file *filp); | 457 | struct file *filp); |
459 | static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | 458 | static void digi_close(struct usb_serial_port *port); |
460 | struct file *filp); | 459 | static int digi_carrier_raised(struct usb_serial_port *port); |
460 | static void digi_dtr_rts(struct usb_serial_port *port, int on); | ||
461 | static int digi_startup_device(struct usb_serial *serial); | 461 | static int digi_startup_device(struct usb_serial *serial); |
462 | static int digi_startup(struct usb_serial *serial); | 462 | static int digi_startup(struct usb_serial *serial); |
463 | static void digi_shutdown(struct usb_serial *serial); | 463 | static void digi_shutdown(struct usb_serial *serial); |
@@ -510,6 +510,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { | |||
510 | .num_ports = 3, | 510 | .num_ports = 3, |
511 | .open = digi_open, | 511 | .open = digi_open, |
512 | .close = digi_close, | 512 | .close = digi_close, |
513 | .dtr_rts = digi_dtr_rts, | ||
514 | .carrier_raised = digi_carrier_raised, | ||
513 | .write = digi_write, | 515 | .write = digi_write, |
514 | .write_room = digi_write_room, | 516 | .write_room = digi_write_room, |
515 | .write_bulk_callback = digi_write_bulk_callback, | 517 | .write_bulk_callback = digi_write_bulk_callback, |
@@ -1328,6 +1330,19 @@ static int digi_chars_in_buffer(struct tty_struct *tty) | |||
1328 | 1330 | ||
1329 | } | 1331 | } |
1330 | 1332 | ||
1333 | static void digi_dtr_rts(struct usb_serial_port *port, int on) | ||
1334 | { | ||
1335 | /* Adjust DTR and RTS */ | ||
1336 | digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1); | ||
1337 | } | ||
1338 | |||
1339 | static int digi_carrier_raised(struct usb_serial_port *port) | ||
1340 | { | ||
1341 | struct digi_port *priv = usb_get_serial_port_data(port); | ||
1342 | if (priv->dp_modem_signals & TIOCM_CD) | ||
1343 | return 1; | ||
1344 | return 0; | ||
1345 | } | ||
1331 | 1346 | ||
1332 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | 1347 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, |
1333 | struct file *filp) | 1348 | struct file *filp) |
@@ -1336,7 +1351,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
1336 | unsigned char buf[32]; | 1351 | unsigned char buf[32]; |
1337 | struct digi_port *priv = usb_get_serial_port_data(port); | 1352 | struct digi_port *priv = usb_get_serial_port_data(port); |
1338 | struct ktermios not_termios; | 1353 | struct ktermios not_termios; |
1339 | unsigned long flags = 0; | ||
1340 | 1354 | ||
1341 | dbg("digi_open: TOP: port=%d, open_count=%d", | 1355 | dbg("digi_open: TOP: port=%d, open_count=%d", |
1342 | priv->dp_port_num, port->port.count); | 1356 | priv->dp_port_num, port->port.count); |
@@ -1345,26 +1359,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
1345 | if (digi_startup_device(port->serial) != 0) | 1359 | if (digi_startup_device(port->serial) != 0) |
1346 | return -ENXIO; | 1360 | return -ENXIO; |
1347 | 1361 | ||
1348 | spin_lock_irqsave(&priv->dp_port_lock, flags); | ||
1349 | |||
1350 | /* don't wait on a close in progress for non-blocking opens */ | ||
1351 | if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) { | ||
1352 | spin_unlock_irqrestore(&priv->dp_port_lock, flags); | ||
1353 | return -EAGAIN; | ||
1354 | } | ||
1355 | |||
1356 | /* wait for a close in progress to finish */ | ||
1357 | while (priv->dp_in_close) { | ||
1358 | cond_wait_interruptible_timeout_irqrestore( | ||
1359 | &priv->dp_close_wait, DIGI_RETRY_TIMEOUT, | ||
1360 | &priv->dp_port_lock, flags); | ||
1361 | if (signal_pending(current)) | ||
1362 | return -EINTR; | ||
1363 | spin_lock_irqsave(&priv->dp_port_lock, flags); | ||
1364 | } | ||
1365 | |||
1366 | spin_unlock_irqrestore(&priv->dp_port_lock, flags); | ||
1367 | |||
1368 | /* read modem signals automatically whenever they change */ | 1362 | /* read modem signals automatically whenever they change */ |
1369 | buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; | 1363 | buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; |
1370 | buf[1] = priv->dp_port_num; | 1364 | buf[1] = priv->dp_port_num; |
@@ -1387,16 +1381,11 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
1387 | not_termios.c_iflag = ~tty->termios->c_iflag; | 1381 | not_termios.c_iflag = ~tty->termios->c_iflag; |
1388 | digi_set_termios(tty, port, ¬_termios); | 1382 | digi_set_termios(tty, port, ¬_termios); |
1389 | } | 1383 | } |
1390 | |||
1391 | /* set DTR and RTS */ | ||
1392 | digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1); | ||
1393 | |||
1394 | return 0; | 1384 | return 0; |
1395 | } | 1385 | } |
1396 | 1386 | ||
1397 | 1387 | ||
1398 | static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | 1388 | static void digi_close(struct usb_serial_port *port) |
1399 | struct file *filp) | ||
1400 | { | 1389 | { |
1401 | DEFINE_WAIT(wait); | 1390 | DEFINE_WAIT(wait); |
1402 | int ret; | 1391 | int ret; |
@@ -1411,28 +1400,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
1411 | if (port->serial->disconnected) | 1400 | if (port->serial->disconnected) |
1412 | goto exit; | 1401 | goto exit; |
1413 | 1402 | ||
1414 | /* do cleanup only after final close on this port */ | ||
1415 | spin_lock_irq(&priv->dp_port_lock); | ||
1416 | priv->dp_in_close = 1; | ||
1417 | spin_unlock_irq(&priv->dp_port_lock); | ||
1418 | |||
1419 | /* tell line discipline to process only XON/XOFF */ | ||
1420 | tty->closing = 1; | ||
1421 | |||
1422 | /* wait for output to drain */ | ||
1423 | if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) | ||
1424 | tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT); | ||
1425 | |||
1426 | /* flush driver and line discipline buffers */ | ||
1427 | tty_driver_flush_buffer(tty); | ||
1428 | tty_ldisc_flush(tty); | ||
1429 | |||
1430 | if (port->serial->dev) { | 1403 | if (port->serial->dev) { |
1431 | /* wait for transmit idle */ | 1404 | /* FIXME: Transmit idle belongs in the wait_unti_sent path */ |
1432 | if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) | 1405 | digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); |
1433 | digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); | ||
1434 | /* drop DTR and RTS */ | ||
1435 | digi_set_modem_signals(port, 0, 0); | ||
1436 | 1406 | ||
1437 | /* disable input flow control */ | 1407 | /* disable input flow control */ |
1438 | buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; | 1408 | buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; |
@@ -1477,11 +1447,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
1477 | /* shutdown any outstanding bulk writes */ | 1447 | /* shutdown any outstanding bulk writes */ |
1478 | usb_kill_urb(port->write_urb); | 1448 | usb_kill_urb(port->write_urb); |
1479 | } | 1449 | } |
1480 | tty->closing = 0; | ||
1481 | exit: | 1450 | exit: |
1482 | spin_lock_irq(&priv->dp_port_lock); | 1451 | spin_lock_irq(&priv->dp_port_lock); |
1483 | priv->dp_write_urb_in_use = 0; | 1452 | priv->dp_write_urb_in_use = 0; |
1484 | priv->dp_in_close = 0; | ||
1485 | wake_up_interruptible(&priv->dp_close_wait); | 1453 | wake_up_interruptible(&priv->dp_close_wait); |
1486 | spin_unlock_irq(&priv->dp_port_lock); | 1454 | spin_unlock_irq(&priv->dp_port_lock); |
1487 | mutex_unlock(&port->serial->disc_mutex); | 1455 | mutex_unlock(&port->serial->disc_mutex); |
@@ -1560,7 +1528,6 @@ static int digi_startup(struct usb_serial *serial) | |||
1560 | priv->dp_throttled = 0; | 1528 | priv->dp_throttled = 0; |
1561 | priv->dp_throttle_restart = 0; | 1529 | priv->dp_throttle_restart = 0; |
1562 | init_waitqueue_head(&priv->dp_flush_wait); | 1530 | init_waitqueue_head(&priv->dp_flush_wait); |
1563 | priv->dp_in_close = 0; | ||
1564 | init_waitqueue_head(&priv->dp_close_wait); | 1531 | init_waitqueue_head(&priv->dp_close_wait); |
1565 | INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); | 1532 | INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); |
1566 | priv->dp_port = serial->port[i]; | 1533 | priv->dp_port = serial->port[i]; |