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 e79afad..3ced09c 100644 (file)
 #include <linux/usb.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
-
-#ifdef CONFIG_USB_SERIAL_DEBUG
-       static int debug = 1;
-#else
-       static int debug;
-#endif
-
 #include "usb-serial.h"
 #include "whiteheat_fw.h"              /* firmware for the ConnectTech WhiteHEAT device */
 #include "whiteheat.h"                 /* WhiteHEAT specific commands */
 
+static int debug;
+
 #ifndef CMSPAR
 #define CMSPAR 0
 #endif
@@ -132,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 */
@@ -148,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);
@@ -161,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,
@@ -174,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,
@@ -259,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)
 
 
@@ -384,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++) {
@@ -418,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;
                }
 
@@ -488,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;
        }
 
@@ -505,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:
@@ -673,8 +674,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);
 
@@ -685,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);
        }
@@ -696,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);
        }
@@ -708,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);
@@ -740,14 +740,9 @@ 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 (__FILE__, __FUNCTION__, bytes, urb->transfer_buffer);
+               usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
 
                urb->dev = serial->dev;
                urb->transfer_buffer_length = bytes;
@@ -835,6 +830,7 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
 static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
        struct serial_struct serstruct;
+       void __user *user_arg = (void __user *)arg;
 
        dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
@@ -851,13 +847,13 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
                        serstruct.close_delay = CLOSING_DELAY;
                        serstruct.closing_wait = CLOSING_DELAY;
 
-                       if (copy_to_user((void *)arg, &serstruct, sizeof(serstruct)))
+                       if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
                                return -EFAULT;
 
                        break;
 
                case TIOCSSERIAL:
-                       if (copy_from_user(&serstruct, (void *)arg, sizeof(serstruct)))
+                       if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
                                return -EFAULT;
 
                        /*
@@ -974,10 +970,6 @@ static void command_port_write_callback (struct urb *urb, struct pt_regs *regs)
                dbg ("nonzero urb status: %d", urb->status);
                return;
        }
-
-       usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
-
-       return;
 }
 
 
@@ -996,7 +988,7 @@ static void command_port_read_callback (struct urb *urb, struct pt_regs *regs)
                return;
        }
 
-       usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
 
        command_info = usb_get_serial_port_data(command_port);
        if (!command_info) {
@@ -1058,7 +1050,7 @@ static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs)
                return;
        }
 
-       usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
 
        spin_lock(&info->lock);
        list_add_tail(&wrap->list, &info->rx_urb_q);
@@ -1128,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, 
@@ -1352,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);
 }
 
@@ -1380,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);
                        }
@@ -1443,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);
@@ -1451,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;
@@ -1518,8 +1509,8 @@ MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(urb_pool_size, "i");
+module_param(urb_pool_size, int, 0);
 MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
 
-MODULE_PARM(debug, "i");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");