Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / usb / serial / whiteheat.c
index 1b75901..3ced09c 100644 (file)
@@ -127,11 +127,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,7 +143,7 @@ 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);
@@ -156,10 +156,12 @@ 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 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 +171,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,
@@ -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,33 +384,33 @@ 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++) {
@@ -413,7 +418,7 @@ static int whiteheat_attach (struct usb_serial *serial)
 
                info = (struct whiteheat_private *)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;
                }
 
@@ -483,7 +488,7 @@ static int whiteheat_attach (struct usb_serial *serial)
 
        command_info = (struct whiteheat_command_private *)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 +505,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:
@@ -679,7 +685,7 @@ 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);
+               usb_kill_urb(urb);
                list_del(tmp);
                list_add(tmp, &info->rx_urbs_free);
        }
@@ -690,7 +696,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
        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);
+               usb_kill_urb(urb);
                list_del(tmp);
                list_add(tmp, &info->tx_urbs_free);
        }
@@ -702,7 +708,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);
@@ -734,12 +740,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);
 
@@ -1119,11 +1120,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, 
@@ -1343,7 +1344,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);
 }
 
@@ -1371,7 +1372,7 @@ 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);
+                               usb_kill_urb(urb);
                                list_del(tmp);
                                list_add(tmp, &info->rx_urbs_free);
                        }
@@ -1434,7 +1435,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);
@@ -1442,11 +1445,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;