fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / usb / serial / whiteheat.c
index b27741b..5483d85 100644 (file)
@@ -65,7 +65,6 @@
  * 
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -80,7 +79,7 @@
 #include <linux/usb.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
-#include "usb-serial.h"
+#include <linux/usb/serial.h>
 #include "whiteheat_fw.h"              /* firmware for the ConnectTech WhiteHEAT device */
 #include "whiteheat.h"                 /* WhiteHEAT specific commands */
 
@@ -127,11 +126,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver whiteheat_driver = {
-       .owner =        THIS_MODULE,
        .name =         "whiteheat",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table_combined,
+       .no_dynamic_id =        1,
 };
 
 /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
@@ -143,23 +142,25 @@ static int  whiteheat_attach              (struct usb_serial *serial);
 static void whiteheat_shutdown         (struct usb_serial *serial);
 static int  whiteheat_open             (struct usb_serial_port *port, struct file *filp);
 static void whiteheat_close            (struct usb_serial_port *port, struct file *filp);
-static int  whiteheat_write            (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int  whiteheat_write            (struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  whiteheat_write_room       (struct usb_serial_port *port);
 static int  whiteheat_ioctl            (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios      (struct usb_serial_port *port, struct termios * old);
+static void whiteheat_set_termios      (struct usb_serial_port *port, struct ktermios * old);
 static int  whiteheat_tiocmget         (struct usb_serial_port *port, struct file *file);
 static int  whiteheat_tiocmset         (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
 static void whiteheat_break_ctl                (struct usb_serial_port *port, int break_state);
 static int  whiteheat_chars_in_buffer  (struct usb_serial_port *port);
 static void whiteheat_throttle         (struct usb_serial_port *port);
 static void whiteheat_unthrottle       (struct usb_serial_port *port);
-static void whiteheat_read_callback    (struct urb *urb, struct pt_regs *regs);
-static void whiteheat_write_callback   (struct urb *urb, struct pt_regs *regs);
-
-static struct usb_serial_device_type whiteheat_fake_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Connect Tech - WhiteHEAT - (prerenumeration)",
-       .short_name =           "whiteheatnofirm",
+static void whiteheat_read_callback    (struct urb *urb);
+static void whiteheat_write_callback   (struct urb *urb);
+
+static struct usb_serial_driver whiteheat_fake_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "whiteheatnofirm",
+       },
+       .description =          "Connect Tech - WhiteHEAT - (prerenumeration)",
        .id_table =             id_table_prerenumeration,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
@@ -169,10 +170,12 @@ static struct usb_serial_device_type whiteheat_fake_device = {
        .attach =               whiteheat_firmware_attach,
 };
 
-static struct usb_serial_device_type whiteheat_device = {
-       .owner =                THIS_MODULE,
-       .name =                 "Connect Tech - WhiteHEAT",
-       .short_name =           "whiteheat",
+static struct usb_serial_driver whiteheat_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "whiteheat",
+       },
+       .description =          "Connect Tech - WhiteHEAT",
        .id_table =             id_table_std,
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
@@ -224,6 +227,7 @@ struct whiteheat_private {
        struct list_head        rx_urbs_submitted;
        struct list_head        rx_urb_q;
        struct work_struct      rx_work;
+       struct usb_serial_port  *port;
        struct list_head        tx_urbs_free;
        struct list_head        tx_urbs_submitted;
 };
@@ -232,13 +236,13 @@ struct whiteheat_private {
 /* local function prototypes */
 static int start_command_port(struct usb_serial *serial);
 static void stop_command_port(struct usb_serial *serial);
-static void command_port_write_callback(struct urb *urb, struct pt_regs *regs);
-static void command_port_read_callback(struct urb *urb, struct pt_regs *regs);
+static void command_port_write_callback(struct urb *urb);
+static void command_port_read_callback(struct urb *urb);
 
 static int start_port_read(struct usb_serial_port *port);
 static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
 static struct list_head *list_first(struct list_head *head);
-static void rx_data_softint(void *private);
+static void rx_data_softint(struct work_struct *work);
 
 static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
 static int firm_open(struct usb_serial_port *port);
@@ -254,6 +258,7 @@ static int firm_report_tx_done(struct usb_serial_port *port);
 
 #define COMMAND_PORT           4
 #define COMMAND_TIMEOUT                (2*HZ)  /* 2 second timeout for a command */
+#define        COMMAND_TIMEOUT_MS      2000
 #define CLOSING_DELAY          (30 * HZ)
 
 
@@ -379,48 +384,49 @@ static int whiteheat_attach (struct usb_serial *serial)
          * unlinking bug in disguise. Same for the call below.
          */
        usb_clear_halt(serial->dev, pipe);
-       ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT);
+       ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
        if (ret) {
-               err("%s: Couldn't send command [%d]", serial->type->name, ret);
+               err("%s: Couldn't send command [%d]", serial->type->description, ret);
                goto no_firmware;
-       } else if (alen != sizeof(command)) {
-               err("%s: Send command incomplete [%d]", serial->type->name, alen);
+       } else if (alen != 2) {
+               err("%s: Send command incomplete [%d]", serial->type->description, alen);
                goto no_firmware;
        }
 
        pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
        /* See the comment on the usb_clear_halt() above */
        usb_clear_halt(serial->dev, pipe);
-       ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT);
+       ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
        if (ret) {
-               err("%s: Couldn't get results [%d]", serial->type->name, ret);
+               err("%s: Couldn't get results [%d]", serial->type->description, ret);
                goto no_firmware;
-       } else if (alen != sizeof(result)) {
-               err("%s: Get results incomplete [%d]", serial->type->name, alen);
+       } else if (alen != sizeof(*hw_info) + 1) {
+               err("%s: Get results incomplete [%d]", serial->type->description, alen);
                goto no_firmware;
        } else if (result[0] != command[0]) {
-               err("%s: Command failed [%d]", serial->type->name, result[0]);
+               err("%s: Command failed [%d]", serial->type->description, result[0]);
                goto no_firmware;
        }
 
        hw_info = (struct whiteheat_hw_info *)&result[1];
 
-       info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
+       info("%s: Driver %s: Firmware v%d.%02d", serial->type->description,
             DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
        for (i = 0; i < serial->num_ports; i++) {
                port = serial->port[i];
 
-               info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
+               info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
                if (info == NULL) {
-                       err("%s: Out of memory for port structures\n", serial->type->name);
+                       err("%s: Out of memory for port structures\n", serial->type->description);
                        goto no_private;
                }
 
                spin_lock_init(&info->lock);
                info->flags = 0;
                info->mcr = 0;
-               INIT_WORK(&info->rx_work, rx_data_softint, port);
+               INIT_WORK(&info->rx_work, rx_data_softint);
+               info->port = port;
 
                INIT_LIST_HEAD(&info->rx_urbs_free);
                INIT_LIST_HEAD(&info->rx_urbs_submitted);
@@ -481,9 +487,9 @@ static int whiteheat_attach (struct usb_serial *serial)
                usb_set_serial_port_data(port, info);
        }
 
-       command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+       command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
        if (command_info == NULL) {
-               err("%s: Out of memory for port structures\n", serial->type->name);
+               err("%s: Out of memory for port structures\n", serial->type->description);
                goto no_command_private;
        }
 
@@ -500,9 +506,10 @@ static int whiteheat_attach (struct usb_serial *serial)
 
 no_firmware:
        /* Firmware likely not running */
-       err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
-       err("%s: If the firmware is not running (status led not blinking)\n", serial->type->name);
-       err("%s: please contact support@connecttech.com\n", serial->type->name);
+       err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
+       err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
+       err("%s: please contact support@connecttech.com\n", serial->type->description);
+       kfree(result);
        return -ENODEV;
 
 no_command_private:
@@ -590,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
 static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
 {
        int             retval = 0;
-       struct termios  old_term;
+       struct ktermios old_term;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -668,8 +675,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
 
        if (port->tty->driver->flush_buffer)
                port->tty->driver->flush_buffer(port->tty);
-       if (port->tty->ldisc.flush_buffer)
-               port->tty->ldisc.flush_buffer(port->tty);
+       tty_ldisc_flush(port->tty);
 
        firm_report_tx_done(port);
 
@@ -680,20 +686,17 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
        list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                urb = wrap->urb;
-               usb_unlink_urb(urb);
-               list_del(tmp);
-               list_add(tmp, &info->rx_urbs_free);
-       }
-       list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
-               list_del(tmp);
-               list_add(tmp, &info->rx_urbs_free);
+               usb_kill_urb(urb);
+               list_move(tmp, &info->rx_urbs_free);
        }
+       list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
+               list_move(tmp, &info->rx_urbs_free);
+
        list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                urb = wrap->urb;
-               usb_unlink_urb(urb);
-               list_del(tmp);
-               list_add(tmp, &info->tx_urbs_free);
+               usb_kill_urb(urb);
+               list_move(tmp, &info->tx_urbs_free);
        }
        spin_unlock_irqrestore(&info->lock, flags);
 
@@ -703,7 +706,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
 }
 
 
-static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count)
 {
        struct usb_serial *serial = port->serial;
        struct whiteheat_private *info = usb_get_serial_port_data(port);
@@ -735,12 +738,7 @@ static int whiteheat_write(struct usb_serial_port *port, int from_user, const un
                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                urb = wrap->urb;
                bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-               if (from_user) {
-                       if (copy_from_user(urb->transfer_buffer, buf + sent, bytes))
-                               return -EFAULT;
-               } else {
-                       memcpy (urb->transfer_buffer, buf + sent, bytes);
-               }
+               memcpy (urb->transfer_buffer, buf + sent, bytes);
 
                usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
 
@@ -872,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
 }
 
 
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
 {
        dbg("%s -port %d", __FUNCTION__, port->number);
 
@@ -953,7 +951,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
        spin_unlock_irqrestore(&info->lock, flags);
 
        if (actually_throttled)
-               rx_data_softint(port);
+               rx_data_softint(&info->rx_work);
 
        return;
 }
@@ -962,7 +960,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
 /*****************************************************************************
  * Connect Tech's White Heat callback routines
  *****************************************************************************/
-static void command_port_write_callback (struct urb *urb, struct pt_regs *regs)
+static void command_port_write_callback (struct urb *urb)
 {
        dbg("%s", __FUNCTION__);
 
@@ -973,7 +971,7 @@ static void command_port_write_callback (struct urb *urb, struct pt_regs *regs)
 }
 
 
-static void command_port_read_callback (struct urb *urb, struct pt_regs *regs)
+static void command_port_read_callback (struct urb *urb)
 {
        struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
        struct whiteheat_command_private *command_info;
@@ -1023,7 +1021,7 @@ static void command_port_read_callback (struct urb *urb, struct pt_regs *regs)
 }
 
 
-static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs)
+static void whiteheat_read_callback(struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct whiteheat_urb_wrap *wrap;
@@ -1065,7 +1063,7 @@ static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs)
 }
 
 
-static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs)
+static void whiteheat_write_callback(struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct whiteheat_private *info = usb_get_serial_port_data(port);
@@ -1080,8 +1078,7 @@ static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs)
                err("%s - Not my urb!", __FUNCTION__);
                return;
        }
-       list_del(&wrap->list);
-       list_add(&wrap->list, &info->tx_urbs_free);
+       list_move(&wrap->list, &info->tx_urbs_free);
        spin_unlock(&info->lock);
 
        if (urb->status) {
@@ -1089,9 +1086,7 @@ static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs)
                return;
        }
 
-       usb_serial_port_softint((void *)port);
-
-       schedule_work(&port->work);
+       usb_serial_port_softint(port);
 }
 
 
@@ -1120,11 +1115,11 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
        command_port->write_urb->transfer_buffer_length = datasize + 1;
        command_port->write_urb->dev = port->serial->dev;
        retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);
-       spin_unlock_irqrestore(&command_info->lock, flags);
        if (retval) {
                dbg("%s - submit urb failed", __FUNCTION__);
                goto exit;
        }
+       spin_unlock_irqrestore(&command_info->lock, flags);
 
        /* wait for the command to complete */
        wait_event_interruptible_timeout(command_info->wait_command, 
@@ -1344,7 +1339,7 @@ static void stop_command_port(struct usb_serial *serial)
        spin_lock_irqsave(&command_info->lock, flags);
        command_info->port_running--;
        if (!command_info->port_running)
-               usb_unlink_urb(command_port->read_urb);
+               usb_kill_urb(command_port->read_urb);
        spin_unlock_irqrestore(&command_info->lock, flags);
 }
 
@@ -1372,9 +1367,8 @@ static int start_port_read(struct usb_serial_port *port)
                        list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
                                wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
                                urb = wrap->urb;
-                               usb_unlink_urb(urb);
-                               list_del(tmp);
-                               list_add(tmp, &info->rx_urbs_free);
+                               usb_kill_urb(urb);
+                               list_move(tmp, &info->rx_urbs_free);
                        }
                        break;
                }
@@ -1408,10 +1402,11 @@ static struct list_head *list_first(struct list_head *head)
 }
 
 
-static void rx_data_softint(void *private)
+static void rx_data_softint(struct work_struct *work)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)private;
-       struct whiteheat_private *info = usb_get_serial_port_data(port);
+       struct whiteheat_private *info =
+               container_of(work, struct whiteheat_private, rx_work);
+       struct usb_serial_port *port = info->port;
        struct tty_struct *tty = port->tty;
        struct whiteheat_urb_wrap *wrap;
        struct urb *urb;
@@ -1435,7 +1430,9 @@ static void rx_data_softint(void *private)
                urb = wrap->urb;
 
                if (tty && urb->actual_length) {
-                       if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {
+                       int len = tty_buffer_request_room(tty, urb->actual_length);
+                       /* This stuff can go away now I suspect */
+                       if (unlikely(len < urb->actual_length)) {
                                spin_lock_irqsave(&info->lock, flags);
                                list_add(tmp, &info->rx_urb_q);
                                spin_unlock_irqrestore(&info->lock, flags);
@@ -1443,11 +1440,8 @@ static void rx_data_softint(void *private)
                                schedule_work(&info->rx_work);
                                return;
                        }
-
-                       memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);
-                       tty->flip.char_buf_ptr += urb->actual_length;
-                       tty->flip.count += urb->actual_length;
-                       sent += urb->actual_length;
+                       tty_insert_flip_string(tty, urb->transfer_buffer, len);
+                       sent += len;
                }
 
                urb->dev = port->serial->dev;