Commit 9fb1cce0 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

USB serial driver core

- Moved all manipulation of port->open_count into the core.  Now the
  individual driver's open and close functions are called only when the
  first open() and last close() is called.  Making the drivers a bit
  smaller and simpler.
- Fixed a bug if a driver didn't have the owner field set.
parent 16c12b0b
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
* *
* See Documentation/usb/usb-serial.txt for more information on using this driver * See Documentation/usb/usb-serial.txt for more information on using this driver
* *
* (03/21/2002) gkh
* Moved all manipulation of port->open_count into the core. Now the
* individual driver's open and close functions are called only when the
* first open() and last close() is called. Making the drivers a bit
* smaller and simpler.
* Fixed a bug if a driver didn't have the owner field set.
*
* (02/26/2002) gkh * (02/26/2002) gkh
* Moved all locking into the main serial_* functions, instead of having * Moved all locking into the main serial_* functions, instead of having
* the individual drivers have to grab the port semaphore. This should * the individual drivers have to grab the port semaphore. This should
...@@ -500,7 +507,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) ...@@ -500,7 +507,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
struct usb_serial *serial; struct usb_serial *serial;
struct usb_serial_port *port; struct usb_serial_port *port;
unsigned int portNumber; unsigned int portNumber;
int retval; int retval = 0;
dbg(__FUNCTION__); dbg(__FUNCTION__);
...@@ -525,14 +532,21 @@ static int serial_open (struct tty_struct *tty, struct file * filp) ...@@ -525,14 +532,21 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
if (serial->type->owner) if (serial->type->owner)
__MOD_INC_USE_COUNT(serial->type->owner); __MOD_INC_USE_COUNT(serial->type->owner);
/* pass on to the driver specific version of this function if it is available */ ++port->open_count;
if (port->open_count == 1) {
/* only call the device specific open if this
* is the first time the port is opened */
if (serial->type->open) if (serial->type->open)
retval = serial->type->open(port, filp); retval = serial->type->open(port, filp);
else else
retval = generic_open(port, filp); retval = generic_open(port, filp);
}
if (retval) if (retval) {
port->open_count = 0;
if (serial->type->owner)
__MOD_DEC_USE_COUNT(serial->type->owner); __MOD_DEC_USE_COUNT(serial->type->owner);
}
up (&port->sem); up (&port->sem);
return retval; return retval;
...@@ -559,11 +573,16 @@ static void serial_close(struct tty_struct *tty, struct file * filp) ...@@ -559,11 +573,16 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
goto exit_no_mod_dec; goto exit_no_mod_dec;
} }
/* pass on to the driver specific version of this function if it is available */ --port->open_count;
if (port->open_count <= 0) {
/* only call the device specific close if this
* port is being closed by the last owner */
if (serial->type->close) if (serial->type->close)
serial->type->close(port, filp); serial->type->close(port, filp);
else else
generic_close(port, filp); generic_close(port, filp);
port->open_count = 0;
}
exit: exit:
if (serial->type->owner) if (serial->type->owner)
...@@ -791,6 +810,8 @@ static void serial_break (struct tty_struct *tty, int break_state) ...@@ -791,6 +810,8 @@ static void serial_break (struct tty_struct *tty, int break_state)
static void serial_shutdown (struct usb_serial *serial) static void serial_shutdown (struct usb_serial *serial)
{ {
dbg(__FUNCTION__);
if (serial->type->shutdown) if (serial->type->shutdown)
serial->type->shutdown(serial); serial->type->shutdown(serial);
else else
...@@ -810,9 +831,6 @@ static int generic_open (struct usb_serial_port *port, struct file *filp) ...@@ -810,9 +831,6 @@ static int generic_open (struct usb_serial_port *port, struct file *filp)
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
++port->open_count;
if (port->open_count == 1) {
/* force low_latency on so that our tty_push actually forces the data through, /* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates (like with OHCI) data otherwise it is scheduled, and with high data rates (like with OHCI) data
can get lost. */ can get lost. */
...@@ -833,20 +851,16 @@ static int generic_open (struct usb_serial_port *port, struct file *filp) ...@@ -833,20 +851,16 @@ static int generic_open (struct usb_serial_port *port, struct file *filp)
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
} }
}
return result; return result;
} }
static void generic_close (struct usb_serial_port *port, struct file * filp) static void generic_cleanup (struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
--port->open_count;
if (port->open_count <= 0) {
if (serial->dev) { if (serial->dev) {
/* shutdown any bulk reads that might be going on */ /* shutdown any bulk reads that might be going on */
if (serial->num_bulk_out) if (serial->num_bulk_out)
...@@ -854,8 +868,12 @@ static void generic_close (struct usb_serial_port *port, struct file * filp) ...@@ -854,8 +868,12 @@ static void generic_close (struct usb_serial_port *port, struct file * filp)
if (serial->num_bulk_in) if (serial->num_bulk_in)
usb_unlink_urb (port->read_urb); usb_unlink_urb (port->read_urb);
} }
port->open_count = 0; }
}
static void generic_close (struct usb_serial_port *port, struct file * filp)
{
dbg(__FUNCTION__ " - port %d", port->number);
generic_cleanup (port);
} }
static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
...@@ -1025,10 +1043,7 @@ static void generic_shutdown (struct usb_serial *serial) ...@@ -1025,10 +1043,7 @@ static void generic_shutdown (struct usb_serial *serial)
/* stop reads and writes on all ports */ /* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) { for (i=0; i < serial->num_ports; ++i) {
down (&serial->port[i].sem); generic_cleanup (&serial->port[i]);
while (serial->port[i].open_count > 0)
generic_close (&serial->port[i], NULL);
up (&serial->port[i].sem);
} }
} }
...@@ -1040,11 +1055,13 @@ static void port_softint(void *private) ...@@ -1040,11 +1055,13 @@ static void port_softint(void *private)
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
if (!serial) { if (!serial)
return; return;
}
tty = port->tty; tty = port->tty;
if (!tty)
return;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
dbg(__FUNCTION__ " - write wakeup call."); dbg(__FUNCTION__ " - write wakeup call.");
(tty->ldisc.write_wakeup)(tty); (tty->ldisc.write_wakeup)(tty);
...@@ -1334,6 +1351,7 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) ...@@ -1334,6 +1351,7 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
struct usb_serial_port *port; struct usb_serial_port *port;
int i; int i;
dbg(__FUNCTION__);
if (serial) { if (serial) {
/* fail all future close/read/write/ioctl/etc calls */ /* fail all future close/read/write/ioctl/etc calls */
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment