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 <[EMAIL PROTECTED]>

diff -urp -X dontdiff linux-2.6.17-git2-gregkh/drivers/usb/serial/visor.c 
linux-2.6.17-git2-gregkh-v/drivers/usb/serial/visor.c
--- linux-2.6.17-git2-gregkh/drivers/usb/serial/visor.c 2006-06-21 
14:23:43.000000000 -0700
+++ linux-2.6.17-git2-gregkh-v/drivers/usb/serial/visor.c       2006-06-21 
14:37:37.000000000 -0700
@@ -436,13 +436,25 @@ static int visor_write (struct usb_seria
 
 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;
 }
 
@@ -759,15 +771,22 @@ static int visor_calc_num_ports (struct 
 
 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;
 }
@@ -877,7 +896,18 @@ static int clie_5_attach (struct usb_ser
 
 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)

All the advantages of Linux Managed Hosting--Without the Cost and Risk!
Fully trained technicians. The highest number of Red Hat certifications in
the hosting industry. Fanatical Support. Click to learn more
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to