diff options
author | Pete Zaitcev <zaitcev@redhat.com> | 2006-06-21 15:03:40 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-07-12 16:03:21 -0700 |
commit | bd97c4f035b47c1a3ae5cc5ceccdda028b25e9d5 (patch) | |
tree | e866962fc6f316111ad5f8d767b40b9d3890885f /drivers/usb/serial | |
parent | 34f8e761724ecbfe46246f3faa4c7dbfc3555c26 (diff) | |
download | op-kernel-dev-bd97c4f035b47c1a3ae5cc5ceccdda028b25e9d5.zip op-kernel-dev-bd97c4f035b47c1a3ae5cc5ceccdda028b25e9d5.tar.gz |
[PATCH] USB: fix visor leaks
This patch fixes blatant leaks in visor driver and makes it report
mode sensible things in ->write_room (this is only needed if your visor
is a terminal though).
It is made to fit into 80 columns with a temporary variable.
Might even save a few instructions...
Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/visor.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 95a2936..cbc2146 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -435,13 +435,25 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf, static int visor_write_room (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); /* * We really can take anything the user throws at us * but let's pick a nice big number to tell the tty - * layer that we have lots of free space + * layer that we have lots of free space, unless we don't. */ + + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __FUNCTION__); + return 0; + } + spin_unlock_irqrestore(&priv->lock, flags); + return 2048; } @@ -758,15 +770,22 @@ static int visor_calc_num_ports (struct usb_serial *serial) static int generic_startup(struct usb_serial *serial) { + struct usb_serial_port **ports = serial->port; struct visor_private *priv; int i; for (i = 0; i < serial->num_ports; ++i) { priv = kzalloc (sizeof(*priv), GFP_KERNEL); - if (!priv) + if (!priv) { + while (i-- != 0) { + priv = usb_get_serial_port_data(ports[i]); + usb_set_serial_port_data(ports[i], NULL); + kfree(priv); + } return -ENOMEM; + } spin_lock_init(&priv->lock); - usb_set_serial_port_data(serial->port[i], priv); + usb_set_serial_port_data(ports[i], priv); } return 0; } @@ -876,7 +895,18 @@ static int clie_5_attach (struct usb_serial *serial) static void visor_shutdown (struct usb_serial *serial) { + struct visor_private *priv; + int i; + dbg("%s", __FUNCTION__); + + for (i = 0; i < serial->num_ports; i++) { + priv = usb_get_serial_port_data(serial->port[i]); + if (priv) { + usb_set_serial_port_data(serial->port[i], NULL); + kfree(priv); + } + } } static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) |