IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
[linux-2.6.git] / drivers / usb / serial / visor.c
index a473c1c..befe2e1 100644 (file)
@@ -13,7 +13,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -26,7 +25,7 @@
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
 #include "visor.h"
 
 /*
@@ -48,9 +47,9 @@ static int  visor_calc_num_ports(struct usb_serial *serial);
 static void visor_shutdown     (struct usb_serial *serial);
 static int  visor_ioctl                (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void visor_set_termios  (struct usb_serial_port *port, struct termios *old_termios);
-static void visor_write_bulk_callback  (struct urb *urb, struct pt_regs *regs);
-static void visor_read_bulk_callback   (struct urb *urb, struct pt_regs *regs);
-static void visor_read_int_callback    (struct urb *urb, struct pt_regs *regs);
+static void visor_write_bulk_callback  (struct urb *urb);
+static void visor_read_bulk_callback   (struct urb *urb);
+static void visor_read_int_callback    (struct urb *urb);
 static int  clie_3_5_startup   (struct usb_serial *serial);
 static int  treo_attach                (struct usb_serial *serial);
 static int clie_5_attach (struct usb_serial *serial);
@@ -69,6 +68,8 @@ static struct usb_device_id id_table [] = {
                .driver_info = (kernel_ulong_t)&palm_os_4_probe },
        { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID),
                .driver_info = (kernel_ulong_t)&palm_os_4_probe },
+       { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID),
+               .driver_info = (kernel_ulong_t)&palm_os_4_probe },
        { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID),
                .driver_info = (kernel_ulong_t)&palm_os_4_probe },
        { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID),
@@ -139,6 +140,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
        { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
        { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO600_ID) },
+       { USB_DEVICE(GSPDA_VENDOR_ID, GSPDA_XPLORE_M68_ID) },
        { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
        { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
        { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
@@ -173,11 +175,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver visor_driver = {
-       .owner =        THIS_MODULE,
        .name =         "visor",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table_combined,
+       .no_dynamic_id =        1,
 };
 
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
@@ -300,7 +302,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
        spin_lock_irqsave(&priv->lock, flags);
        priv->bytes_in = 0;
        priv->bytes_out = 0;
-       priv->outstanding_urbs = 0;
        priv->throttled = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -433,13 +434,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;
 }
 
@@ -458,7 +471,7 @@ static int visor_chars_in_buffer (struct usb_serial_port *port)
 }
 
 
-static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void visor_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct visor_private *priv = usb_get_serial_port_data(port);
@@ -477,18 +490,17 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        --priv->outstanding_urbs;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       schedule_work(&port->work);
+       usb_serial_port_softint(port);
 }
 
 
-static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void visor_read_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
        struct tty_struct *tty;
        unsigned long flags;
-       int i;
        int throttled;
        int result;
 
@@ -503,14 +515,8 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
        tty = port->tty;
        if (tty && urb->actual_length) {
-               for (i = 0; i < urb->actual_length ; ++i) {
-                       /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-                       if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                               tty_flip_buffer_push(tty);
-                       }
-                       /* this doesn't actually push the data through unless tty->low_latency is set */
-                       tty_insert_flip_char(tty, data[i], 0);
-               }
+               tty_buffer_request_room(tty, urb->actual_length);
+               tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
        spin_lock_irqsave(&priv->lock, flags);
@@ -533,7 +539,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
        return;
 }
 
-static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void visor_read_int_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        int result;
@@ -763,16 +769,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 = kmalloc (sizeof(*priv), GFP_KERNEL);
-               if (!priv)
+               priv = kzalloc (sizeof(*priv), GFP_KERNEL);
+               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;
-               memset (priv, 0x00, sizeof(*priv));
+               }
                spin_lock_init(&priv->lock);
-               usb_set_serial_port_data(serial->port[i], priv);
+               usb_set_serial_port_data(ports[i], priv);
        }
        return 0;
 }
@@ -882,7 +894,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)