X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fio_edgeport.c;h=f623d58370a4c2561a5be318a4d9f01a90f5b063;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=14c1dd64cb3626004f40cb31218eba5918c5c32a;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 14c1dd64c..f623d5837 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -27,228 +27,8 @@ * Networks technical support, or Peter Berger , * or Al Borchers . * - * Version history: - * - * 2003_04_03 al borchers - * - fixed a bug (that shows up with dosemu) where the tty struct is - * used in a callback after it has been freed - * - * 2.3 2002_03_08 greg kroah-hartman - * - fixed bug when multiple devices were attached at the same time. - * - * 2.2 2001_11_14 greg kroah-hartman - * - fixed bug in edge_close that kept the port from being used more - * than once. - * - fixed memory leak on device removal. - * - fixed potential double free of memory when command urb submitting - * failed. - * - other small cleanups when the device is removed - * - * 2.1 2001_07_09 greg kroah-hartman - * - added support for TIOCMBIS and TIOCMBIC. - * - * (04/08/2001) gb - * - Identify version on module load. - * - * 2.0 2001_03_05 greg kroah-hartman - * - reworked entire driver to fit properly in with the other usb-serial - * drivers. Occasional oopses still happen, but it's a good start. - * - * 1.2.3 (02/23/2001) greg kroah-hartman - * - changed device table to work properly for 2.4.x final format. - * - fixed problem with dropping data at high data rates. - * - * 1.2.2 (11/27/2000) greg kroah-hartman - * - cleaned up more NTisms. - * - Added device table for 2.4.0-test11 - * - * 1.2.1 (11/08/2000) greg kroah-hartman - * - Started to clean up NTisms. - * - Fixed problem with dev field of urb for kernels >= 2.4.0-test9 - * - * 1.2 (10/17/2000) David Iacovelli - * Remove all EPIC code and GPL source - * Fix RELEVANT_IFLAG macro to include flow control - * changes port configuration changes. - * Fix redefinition of SERIAL_MAGIC - * Change all timeout values to 5 seconds - * Tried to fix the UHCI multiple urb submission, but failed miserably. - * it seems to work fine with OHCI. - * ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must - * find a way to work arount this UHCI bug ) - * - * 1.1 (10/11/2000) David Iacovelli - * Fix XON/XOFF flow control to support both IXON and IXOFF - * - * 0.9.27 (06/30/2000) David Iacovelli - * Added transmit queue and now allocate urb for command writes. - * - * 0.9.26 (06/29/2000) David Iacovelli - * Add support for 80251 based edgeport - * - * 0.9.25 (06/27/2000) David Iacovelli - * Do not close the port if it has multiple opens. - * - * 0.9.24 (05/26/2000) David Iacovelli - * Add IOCTLs to support RXTX and JAVA POS - * and first cut at running BlackBox Demo - * - * 0.9.23 (05/24/2000) David Iacovelli - * Add IOCTLs to support RXTX and JAVA POS - * - * 0.9.22 (05/23/2000) David Iacovelli - * fixed bug in enumeration. If epconfig turns on mapping by - * path after a device is already plugged in, we now update - * the mapping correctly - * - * 0.9.21 (05/16/2000) David Iacovelli - * Added BlockUntilChaseResp() to also wait for txcredits - * Updated the way we allocate and handle write URBs - * Add debug code to dump buffers - * - * 0.9.20 (05/01/2000) David Iacovelli - * change driver to use usb/tts/ - * - * 0.9.19 (05/01/2000) David Iacovelli - * Update code to compile if DEBUG is off - * - * 0.9.18 (04/28/2000) David Iacovelli - * cleanup and test tty_register with devfs - * - * 0.9.17 (04/27/2000) greg kroah-hartman - * changed tty_register around to be like the way it - * was before, but now it works properly with devfs. - * - * 0.9.16 (04/26/2000) david iacovelli - * Fixed bug in GetProductInfo() - * - * 0.9.15 (04/25/2000) david iacovelli - * Updated enumeration - * - * 0.9.14 (04/24/2000) david iacovelli - * Removed all config/status IOCTLS and - * converted to using /proc/edgeport - * still playing with devfs - * - * 0.9.13 (04/24/2000) david iacovelli - * Removed configuration based on ttyUSB0 - * Added support for configuration using /prod/edgeport - * first attempt at using devfs (not working yet!) - * Added IOCTL to GetProductInfo() - * Added support for custom baud rates - * Add support for random port numbers - * - * 0.9.12 (04/18/2000) david iacovelli - * added additional configuration IOCTLs - * use ttyUSB0 for configuration - * - * 0.9.11 (04/17/2000) greg kroah-hartman - * fixed module initialization race conditions. - * made all urbs dynamically allocated. - * made driver devfs compatible. now it only registers the tty device - * when the device is actually plugged in. - * - * 0.9.10 (04/13/2000) greg kroah-hartman - * added proc interface framework. - * - * 0.9.9 (04/13/2000) david iacovelli - * added enumeration code and ioctls to configure the device - * - * 0.9.8 (04/12/2000) david iacovelli - * Change interrupt read start when device is plugged in - * and stop when device is removed - * process interrupt reads when all ports are closed - * (keep value of rxBytesAvail consistent with the edgeport) - * set the USB_BULK_QUEUE flag so that we can shove a bunch - * of urbs at once down the pipe - * - * 0.9.7 (04/10/2000) david iacovelli - * start to add enumeration code. - * generate serial number for epic devices - * add support for kdb - * - * 0.9.6 (03/30/2000) david iacovelli - * add IOCTL to get string, manufacture, and boot descriptors - * - * 0.9.5 (03/14/2000) greg kroah-hartman - * more error checking added to SerialOpen to try to fix UHCI open problem - * - * 0.9.4 (03/09/2000) greg kroah-hartman - * added more error checking to handle oops when data is hanging - * around and tty is abruptly closed. - * - * 0.9.3 (03/09/2000) david iacovelli - * Add epic support for xon/xoff chars - * play with performance - * - * 0.9.2 (03/08/2000) greg kroah-hartman - * changed most "info" calls to "dbg" - * implemented flow control properly in the termios call - * - * 0.9.1 (03/08/2000) david iacovelli - * added EPIC support - * enabled bootloader update - * - * 0.9 (03/08/2000) greg kroah-hartman - * Release to IO networks. - * Integrated changes that David made - * made getting urbs for writing SMP safe - * - * 0.8 (03/07/2000) greg kroah-hartman - * Release to IO networks. - * Fixed problems that were seen in code by David. - * Now both Edgeport/4 and Edgeport/2 works properly. - * Changed most of the functions to use port instead of serial. - * - * 0.7 (02/27/2000) greg kroah-hartman - * Milestone 3 release. - * Release to IO Networks - * ioctl for waiting on line change implemented. - * ioctl for getting statistics implemented. - * multiport support working. - * lsr and msr registers are now handled properly. - * change break now hooked up and working. - * support for all known Edgeport devices. - * - * 0.6 (02/22/2000) greg kroah-hartman - * Release to IO networks. - * CHASE is implemented correctly when port is closed. - * SerialOpen now blocks correctly until port is fully opened. - * - * 0.5 (02/20/2000) greg kroah-hartman - * Release to IO networks. - * Known problems: - * modem status register changes are not sent on to the user - * CHASE is not implemented when the port is closed. - * - * 0.4 (02/16/2000) greg kroah-hartman - * Second cut at the CeBit demo. - * Doesn't leak memory on every write to the port - * Still small leaks on startup. - * Added support for Edgeport/2 and Edgeport/8 - * - * 0.3 (02/15/2000) greg kroah-hartman - * CeBit demo release. - * Force the line settings to 4800, 8, 1, e for the demo. - * Warning! This version leaks memory like crazy! - * - * 0.2 (01/30/2000) greg kroah-hartman - * Milestone 1 release. - * Device is found by USB subsystem, enumerated, fimware is downloaded - * and the descriptors are printed to the debug log, config is set, and - * green light starts to blink. Open port works, and data can be sent - * and received at the default settings of the UART. Loopback connector - * and debug log confirms this. - * - * 0.1 (01/23/2000) greg kroah-hartman - * Initial release to help IO Networks try to set up their test system. - * Edgeport4 is recognized, firmware is downloaded, config is set so - * device blinks green light every 3 sec. Port is bound, but opening, - * closing, and sending data do not work properly. - * */ -#include #include #include #include @@ -261,9 +41,10 @@ #include #include #include +#include #include #include -#include "usb-serial.h" +#include #include "io_edgeport.h" #include "io_ionsp.h" /* info for the iosp messages */ #include "io_16654.h" /* 16654 UART defines */ @@ -360,7 +141,7 @@ struct edgeport_port { /* This structure holds all of the individual device information */ struct edgeport_serial { - char name[MAX_NAME_LEN+1]; /* string name of this device */ + char name[MAX_NAME_LEN+2]; /* string name of this device */ struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ @@ -402,7 +183,7 @@ struct divisor_table_entry { // These assume a 3.6864MHz crystal, the standard /16, and // MCR.7 = 0. // -static struct divisor_table_entry divisor_table[] = { +static const struct divisor_table_entry divisor_table[] = { { 50, 4608}, { 75, 3072}, { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ @@ -435,10 +216,10 @@ static int CmdUrbs = 0; /* Number of outstanding Command Write Urbs */ /* local function prototypes */ /* function prototypes for all URB callbacks */ -static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs); -static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs); -static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs); -static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs); +static void edge_interrupt_callback (struct urb *urb); +static void edge_bulk_in_callback (struct urb *urb); +static void edge_bulk_out_data_callback (struct urb *urb); +static void edge_bulk_out_cmd_callback (struct urb *urb); /* function prototypes for the usbserial callbacks */ static int edge_open (struct usb_serial_port *port, struct file *filp); @@ -448,7 +229,7 @@ static int edge_write_room (struct usb_serial_port *port); static int edge_chars_in_buffer (struct usb_serial_port *port); static void edge_throttle (struct usb_serial_port *port); static void edge_unthrottle (struct usb_serial_port *port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void edge_break (struct usb_serial_port *port, int break_state); static int edge_tiocmget (struct usb_serial_port *port, struct file *file); @@ -460,11 +241,11 @@ static void edge_shutdown (struct usb_serial *serial); #include "io_tables.h" /* all of the devices that this driver supports */ static struct usb_driver io_driver = { - .owner = THIS_MODULE, .name = "io_edgeport", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, + .no_dynamic_id = 1, }; /* function prototypes for all of our local functions */ @@ -476,7 +257,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); static int calc_baud_rate_divisor (int baud_rate, int *divisor); static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate); -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios); +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios); static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue); static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength); static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port); @@ -488,7 +269,7 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial); static void get_boot_desc (struct edgeport_serial *edge_serial); static void load_application_firmware (struct edgeport_serial *edge_serial); -static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); +static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size); // ************************************************************************ @@ -591,7 +372,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) * Get string descriptor from device * * * ************************************************************************/ -static int get_string (struct usb_device *dev, int Id, char *string) +static int get_string (struct usb_device *dev, int Id, char *string, int buflen) { struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; @@ -613,7 +394,7 @@ static int get_string (struct usb_device *dev, int Id, char *string) return 0; } - unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); + unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); kfree(pStringDesc); return strlen(string); @@ -753,7 +534,7 @@ static void get_product_info(struct edgeport_serial *edge_serial) * this is the callback function for when we have received data on the * interrupt endpoint. *****************************************************************************/ -static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs) +static void edge_interrupt_callback (struct urb *urb) { struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; struct edgeport_port *edge_port; @@ -850,7 +631,7 @@ exit: * this is the callback function for when we have received data on the * bulk in endpoint. *****************************************************************************/ -static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) +static void edge_bulk_in_callback (struct urb *urb) { struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; unsigned char *data = urb->transfer_buffer; @@ -906,7 +687,7 @@ static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) * this is the callback function for when we have finished sending serial data * on the bulk out endpoint. *****************************************************************************/ -static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs) +static void edge_bulk_out_data_callback (struct urb *urb) { struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; struct tty_struct *tty; @@ -937,7 +718,7 @@ static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs) * this is the callback function for when we have finished sending a command * on the bulk out endpoint. *****************************************************************************/ -static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs) +static void edge_bulk_out_cmd_callback (struct urb *urb) { struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; struct tty_struct *tty; @@ -950,9 +731,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs) /* clean up the transfer buffer */ - if (urb->transfer_buffer != NULL) { - kfree(urb->transfer_buffer); - } + kfree(urb->transfer_buffer); /* Free the command urb */ usb_free_urb (urb); @@ -971,7 +750,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs) /* we have completed the command */ edge_port->commandPending = FALSE; - wake_up_interruptible(&edge_port->wait_command); + wake_up(&edge_port->wait_command); } @@ -991,7 +770,6 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) struct usb_serial *serial; struct edgeport_serial *edge_serial; int response; - int timeout; dbg("%s - port %d", __FUNCTION__, port->number); @@ -1073,10 +851,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) } /* now wait for the port to be completely opened */ - timeout = OPEN_TIMEOUT; - while (timeout && edge_port->openPending == TRUE) { - timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout); - } + wait_event_timeout(edge_port->wait_open, (edge_port->openPending != TRUE), OPEN_TIMEOUT); if (edge_port->open == FALSE) { /* open timed out */ @@ -1128,9 +903,10 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) ************************************************************************/ static void block_until_chase_response(struct edgeport_port *edge_port) { + DEFINE_WAIT(wait); __u16 lastCredits; int timeout = 1*HZ; - int wait = 10; + int loop = 10; while (1) { // Save Last credits @@ -1148,12 +924,14 @@ static void block_until_chase_response(struct edgeport_port *edge_port) } // Block the thread for a while - interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout); + prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE); + schedule_timeout(timeout); + finish_wait(&edge_port->wait_chase, &wait); if (lastCredits == edge_port->txCredits) { // No activity.. count down. - wait--; - if (wait == 0) { + loop--; + if (loop == 0) { edge_port->chaseResponsePending = FALSE; dbg("%s - Chase TIMEOUT", __FUNCTION__); return; @@ -1161,7 +939,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port) } else { // Reset timout value back to 10 seconds dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits); - wait = 10; + loop = 10; } } } @@ -1179,10 +957,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port) ************************************************************************/ static void block_until_tx_empty (struct edgeport_port *edge_port) { + DEFINE_WAIT(wait); struct TxFifo *fifo = &edge_port->txfifo; __u32 lastCount; int timeout = HZ/10; - int wait = 30; + int loop = 30; while (1) { // Save Last count @@ -1195,20 +974,22 @@ static void block_until_tx_empty (struct edgeport_port *edge_port) } // Block the thread for a while - interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout); + prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE); + schedule_timeout(timeout); + finish_wait(&edge_port->wait_chase, &wait); dbg("%s wait", __FUNCTION__); if (lastCount == fifo->count) { // No activity.. count down. - wait--; - if (wait == 0) { + loop--; + if (loop == 0) { dbg("%s - TIMEOUT", __FUNCTION__); return; } } else { // Reset timout value back to seconds - wait = 30; + loop = 30; } } } @@ -1257,22 +1038,16 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) edge_port->open = FALSE; edge_port->openPending = FALSE; - if (edge_port->write_urb) { - usb_kill_urb(edge_port->write_urb); - } + usb_kill_urb(edge_port->write_urb); if (edge_port->write_urb) { /* if this urb had a transfer buffer already (old transfer) free it */ - if (edge_port->write_urb->transfer_buffer != NULL) { - kfree(edge_port->write_urb->transfer_buffer); - } - usb_free_urb (edge_port->write_urb); + kfree(edge_port->write_urb->transfer_buffer); + usb_free_urb(edge_port->write_urb); edge_port->write_urb = NULL; } - if (edge_port->txfifo.fifo) { - kfree(edge_port->txfifo.fifo); - edge_port->txfifo.fifo = NULL; - } + kfree(edge_port->txfifo.fifo); + edge_port->txfifo.fifo = NULL; dbg("%s exited", __FUNCTION__); } @@ -1416,11 +1191,9 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge // get a pointer to the write_urb urb = edge_port->write_urb; - /* if this urb had a transfer buffer already (old transfer) free it */ - if (urb->transfer_buffer != NULL) { - kfree(urb->transfer_buffer); - urb->transfer_buffer = NULL; - } + /* make sure transfer buffer is freed */ + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; /* build the data header for the buffer and port that we are about to send out */ count = fifo->count; @@ -1658,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port) * SerialSetTermios * this function is called by the tty driver when it wants to change the termios structure *****************************************************************************/ -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; @@ -1817,13 +1590,8 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; tmp.xmit_fifo_size = edge_port->maxTxCredits; tmp.baud_base = 9600; - #if HZ < 2185 tmp.close_delay = 5*HZ; tmp.closing_wait = 30*HZ; - #else - tmp.close_delay = 2*HZ; - tmp.closing_wait = 65534; - #endif // tmp.custom_divisor = state->custom_divisor; // tmp.hub6 = state->hub6; // tmp.io_type = state->io_type; @@ -1841,12 +1609,12 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct *****************************************************************************/ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) { + DEFINE_WAIT(wait); struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct async_icount cnow; struct async_icount cprev; struct serial_icounter_struct icount; - dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd); switch (cmd) { @@ -1873,7 +1641,9 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); cprev = edge_port->icount; while (1) { - interruptible_sleep_on(&edge_port->delta_msr_wait); + prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE); + schedule(); + finish_wait(&edge_port->delta_msr_wait, &wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; @@ -2113,7 +1883,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 // We could choose to do something else when Byte3 says Timeout on Chase from Edgeport, // like wait longer in block_until_chase_response, but for now we don't. edge_port->chaseResponsePending = FALSE; - wake_up_interruptible (&edge_port->wait_chase); + wake_up (&edge_port->wait_chase); return; case IOSP_EXT_STATUS_RX_CHECK_RSP: @@ -2136,7 +1906,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 /* we have completed the open */ edge_port->openPending = FALSE; edge_port->open = TRUE; - wake_up_interruptible(&edge_port->wait_open); + wake_up(&edge_port->wait_open); return; } @@ -2192,20 +1962,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c int cnt; do { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", - __FUNCTION__, length); - return; - } + cnt = tty_buffer_request_room(tty, length); + if (cnt < length) { + dev_err(dev, "%s - dropping data, %d bytes lost\n", + __FUNCTION__, length - cnt); + if(cnt == 0) + break; } - cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); - memcpy(tty->flip.char_buf_ptr, data, cnt); - memset(tty->flip.flag_buf_ptr, 0, cnt); - tty->flip.char_buf_ptr += cnt; - tty->flip.flag_buf_ptr += cnt; - tty->flip.count += cnt; + tty_insert_flip_string(tty, data, cnt); data += cnt; length -= cnt; } while (length > 0); @@ -2505,9 +2269,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer // wait for command to finish timeout = COMMAND_TIMEOUT; #if 0 - while (timeout && edge_port->commandPending == TRUE) { - timeout = interruptible_sleep_on_timeout (&edge_port->wait_command, timeout); - } + wait_event (&edge_port->wait_command, (edge_port->commandPending == FALSE)); if (edge_port->commandPending == TRUE) { /* command timed out */ @@ -2582,7 +2344,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) dbg("%s - %d", __FUNCTION__, baudrate); - for (i = 0; i < NUM_ENTRIES(divisor_table); i++) { + for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { if ( divisor_table[i].BaudRate == baudrate ) { *divisor = divisor_table[i].Divisor; return 0; @@ -2650,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r #ifndef CMSPAR #define CMSPAR 0 #endif -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct tty_struct *tty; int baud; @@ -2799,16 +2561,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio * ASCII range, but it's only for debugging... * NOTE: expects the unicode in LE format ****************************************************************************/ -static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) +static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size) { int i; - if (unicode_size <= 0) + if (buflen <= 0) /* never happens, but... */ return; + --buflen; /* space for nul */ - for (i = 0; i < unicode_size; ++i) + for (i = 0; i < unicode_size; i++) { + if (i >= buflen) + break; string[i] = (char)(le16_to_cpu(unicode[i])); - string[unicode_size] = 0x00; + } + string[i] = 0x00; } @@ -2838,11 +2604,17 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial) dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); - unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1); + unicode_to_ascii(string, sizeof(string), + edge_serial->manuf_descriptor.SerialNumber, + edge_serial->manuf_descriptor.SerNumLength/2); dbg(" SerialNumber: %s", string); - unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1); + unicode_to_ascii(string, sizeof(string), + edge_serial->manuf_descriptor.AssemblyNumber, + edge_serial->manuf_descriptor.AssemblyNumLength/2); dbg(" AssemblyNumber: %s", string); - unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1); + unicode_to_ascii(string, sizeof(string), + edge_serial->manuf_descriptor.OemAssyNumber, + edge_serial->manuf_descriptor.OemAssyNumLength/2); dbg(" OemAssyNumber: %s", string); dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); @@ -2955,27 +2727,26 @@ static int edge_startup (struct usb_serial *serial) struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_device *dev; - int i; + int i, j; dev = serial->dev; /* create our private serial structure */ - edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); + edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); if (edge_serial == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } - memset (edge_serial, 0, sizeof(struct edgeport_serial)); spin_lock_init(&edge_serial->es_lock); edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); /* get the name for the device from the device */ - if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) { - edge_serial->name[i-1] = ' '; - } - - get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]); + i = get_string(dev, dev->descriptor.iManufacturer, + &edge_serial->name[0], MAX_NAME_LEN+1); + edge_serial->name[i++] = ' '; + get_string(dev, dev->descriptor.iProduct, + &edge_serial->name[i], MAX_NAME_LEN+2 - i); dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); @@ -3020,6 +2791,10 @@ static int edge_startup (struct usb_serial *serial) edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); + for (j = 0; j < i; ++j) { + kfree (usb_get_serial_port_data(serial->port[j])); + usb_set_serial_port_data(serial->port[j], NULL); + } usb_set_serial_data(serial, NULL); kfree(edge_serial); return -ENOMEM; @@ -3112,4 +2887,4 @@ module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(low_latency, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Low latency enabled or not"); +MODULE_PARM_DESC(low_latency, "Low latency enabled or not");