X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fwhiteheat.c;h=5483d8564c1b9b42015e39ffc264366fdac95d24;hb=a2f44b27303a5353859d77a3e96a1d3f33f56ab7;hp=cc9d849c163922d13ccc85d4958c40870432c7ff;hpb=daddc0d38b3571bed170afa273a49a0eba090c1e;p=linux-2.6.git diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index cc9d849c1..5483d8564 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -65,7 +65,6 @@ * */ -#include #include #include #include @@ -80,17 +79,12 @@ #include #include #include - -#ifdef CONFIG_USB_SERIAL_DEBUG - static int debug = 1; -#else - static int debug; -#endif - -#include "usb-serial.h" +#include #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 +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 */ @@ -148,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, @@ -174,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, @@ -229,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; }; @@ -237,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); @@ -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,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); @@ -486,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; } @@ -505,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: @@ -595,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); @@ -673,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); @@ -685,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); @@ -708,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); @@ -740,14 +738,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 +828,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 +845,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; /* @@ -876,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); @@ -957,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; } @@ -966,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__); @@ -974,17 +968,12 @@ 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; } -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 usb_serial *serial = get_usb_serial (command_port, __FUNCTION__); struct whiteheat_command_private *command_info; unsigned char *data = urb->transfer_buffer; int result; @@ -997,12 +986,7 @@ static void command_port_read_callback (struct urb *urb, struct pt_regs *regs) return; } - if (!serial) { - dbg("%s - bad serial pointer, exiting", __FUNCTION__); - 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) { @@ -1029,7 +1013,7 @@ static void command_port_read_callback (struct urb *urb, struct pt_regs *regs) } /* Continue trying to always read */ - command_port->read_urb->dev = serial->dev; + command_port->read_urb->dev = command_port->serial->dev; result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC); spin_unlock_irqrestore(&command_info->lock, flags); if (result) @@ -1037,10 +1021,9 @@ 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 usb_serial *serial = get_usb_serial (port, __FUNCTION__); struct whiteheat_urb_wrap *wrap; unsigned char *data = urb->transfer_buffer; struct whiteheat_private *info = usb_get_serial_port_data(port); @@ -1057,14 +1040,6 @@ static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs) list_del(&wrap->list); spin_unlock(&info->lock); - if (!serial) { - dbg("%s - bad serial pointer, exiting", __FUNCTION__); - spin_lock(&info->lock); - list_add(&wrap->list, &info->rx_urbs_free); - spin_unlock(&info->lock); - return; - } - if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); spin_lock(&info->lock); @@ -1073,7 +1048,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); @@ -1088,10 +1063,9 @@ 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 usb_serial *serial = get_usb_serial (port, __FUNCTION__); struct whiteheat_private *info = usb_get_serial_port_data(port); struct whiteheat_urb_wrap *wrap; @@ -1104,23 +1078,15 @@ 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 (!serial) { - dbg("%s - bad serial pointer, exiting", __FUNCTION__); - return; - } - if (urb->status) { dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); return; } - usb_serial_port_softint((void *)port); - - schedule_work(&port->work); + usb_serial_port_softint(port); } @@ -1149,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, @@ -1373,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); } @@ -1401,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; } @@ -1437,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; @@ -1464,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); @@ -1472,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; @@ -1539,8 +1504,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");