diff options
Diffstat (limited to 'drivers/usb/serial/io_edgeport.c')
| -rw-r--r-- | drivers/usb/serial/io_edgeport.c | 256 |
1 files changed, 62 insertions, 194 deletions
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 5acc0d13864..c0866971db2 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -32,7 +32,6 @@ #include <linux/kernel.h> #include <linux/jiffies.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_driver.h> @@ -51,18 +50,12 @@ #include "io_ionsp.h" /* info for the iosp messages */ #include "io_16654.h" /* 16654 UART defines */ -/* - * Version Information - */ -#define DRIVER_VERSION "v2.7" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" #define DRIVER_DESC "Edgeport USB Serial Driver" #define MAX_NAME_LEN 64 -#define CHASE_TIMEOUT (5*HZ) /* 5 seconds */ #define OPEN_TIMEOUT (5*HZ) /* 5 seconds */ -#define COMMAND_TIMEOUT (5*HZ) /* 5 seconds */ /* receive port state */ enum RXSTATE { @@ -114,9 +107,7 @@ struct edgeport_port { wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */ wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ - wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ - struct async_icount icount; struct usb_serial_port *port; /* loop back to the owner of this object */ }; @@ -220,8 +211,6 @@ static void edge_break(struct tty_struct *tty, int break_state); static int edge_tiocmget(struct tty_struct *tty); static int edge_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int edge_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); static int edge_startup(struct usb_serial *serial); static void edge_disconnect(struct usb_serial *serial); static void edge_release(struct usb_serial *serial); @@ -236,8 +225,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); static void process_rcvd_status(struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3); -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length); +static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data, + int length); static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr); static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data); @@ -569,7 +558,6 @@ static void edge_interrupt_callback(struct urb *urb) struct device *dev; struct edgeport_port *edge_port; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; int bytes_avail; @@ -648,12 +636,7 @@ static void edge_interrupt_callback(struct urb *urb) /* tell the tty driver that something has changed */ - tty = tty_port_tty_get( - &edge_port->port->port); - if (tty) { - tty_wakeup(tty); - tty_kref_put(tty); - } + tty_port_tty_wakeup(&edge_port->port->port); /* Since we have more credit, check if more data can be sent */ send_more_port_data(edge_serial, @@ -742,7 +725,6 @@ static void edge_bulk_in_callback(struct urb *urb) static void edge_bulk_out_data_callback(struct urb *urb) { struct edgeport_port *edge_port = urb->context; - struct tty_struct *tty; int status = urb->status; if (status) { @@ -751,14 +733,8 @@ static void edge_bulk_out_data_callback(struct urb *urb) __func__, status); } - tty = tty_port_tty_get(&edge_port->port->port); - - if (tty && edge_port->open) { - /* let the tty driver wakeup if it has a special - write_wakeup function */ - tty_wakeup(tty); - } - tty_kref_put(tty); + if (edge_port->open) + tty_port_tty_wakeup(&edge_port->port->port); /* Release the Write URB */ edge_port->write_in_progress = false; @@ -777,7 +753,6 @@ static void edge_bulk_out_data_callback(struct urb *urb) static void edge_bulk_out_cmd_callback(struct urb *urb) { struct edgeport_port *edge_port = urb->context; - struct tty_struct *tty; int status = urb->status; atomic_dec(&CmdUrbs); @@ -798,13 +773,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb) return; } - /* Get pointer to tty */ - tty = tty_port_tty_get(&edge_port->port->port); - /* tell the tty driver that something has changed */ - if (tty && edge_port->open) - tty_wakeup(tty); - tty_kref_put(tty); + if (edge_port->open) + tty_port_tty_wakeup(&edge_port->port->port); /* we have completed the command */ edge_port->commandPending = false; @@ -888,12 +859,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) /* initialize our wait queues */ init_waitqueue_head(&edge_port->wait_open); init_waitqueue_head(&edge_port->wait_chase); - init_waitqueue_head(&edge_port->delta_msr_wait); init_waitqueue_head(&edge_port->wait_command); - /* initialize our icount structure */ - memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); - /* initialize our port settings */ edge_port->txCredits = 0; /* Can't send any data yet */ /* Must always set this bit to enable ints! */ @@ -930,7 +897,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) edge_port->txfifo.fifo = kmalloc(edge_port->maxTxCredits, GFP_KERNEL); if (!edge_port->txfifo.fifo) { - dev_dbg(dev, "%s - no memory\n", __func__); edge_close(port); return -ENOMEM; } @@ -940,13 +906,12 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) edge_port->write_in_progress = false; if (!edge_port->write_urb) { - dev_dbg(dev, "%s - no memory\n", __func__); edge_close(port); return -ENOMEM; } - dev_dbg(dev, "%s(%d) - Initialize TX fifo to %d bytes\n", - __func__, port->number, edge_port->maxTxCredits); + dev_dbg(dev, "%s - Initialize TX fifo to %d bytes\n", + __func__, edge_port->maxTxCredits); return 0; } @@ -1152,9 +1117,8 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, copySize = min((unsigned int)count, (edge_port->txCredits - fifo->count)); - dev_dbg(&port->dev, "%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes\n", - __func__, port->number, count, - edge_port->txCredits - fifo->count, copySize); + dev_dbg(&port->dev, "%s of %d byte(s) Fifo room %d -- will copy %d bytes\n", + __func__, count, edge_port->txCredits - fifo->count, copySize); /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */ @@ -1246,9 +1210,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, if (edge_port->write_in_progress || !edge_port->open || (fifo->count == 0)) { - dev_dbg(dev, "%s(%d) EXIT - fifo %d, PendingWrite = %d\n", - __func__, edge_port->port->number, - fifo->count, edge_port->write_in_progress); + dev_dbg(dev, "%s EXIT - fifo %d, PendingWrite = %d\n", + __func__, fifo->count, edge_port->write_in_progress); goto exit_send; } @@ -1260,9 +1223,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, * it's better to wait for more credits so we can do a larger write. */ if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) { - dev_dbg(dev, "%s(%d) Not enough credit - fifo %d TxCredit %d\n", - __func__, edge_port->port->number, fifo->count, - edge_port->txCredits); + dev_dbg(dev, "%s Not enough credit - fifo %d TxCredit %d\n", + __func__, fifo->count, edge_port->txCredits); goto exit_send; } @@ -1280,16 +1242,12 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, to send out */ count = fifo->count; buffer = kmalloc(count+2, GFP_ATOMIC); - if (buffer == NULL) { - dev_err_console(edge_port->port, - "%s - no more kernel memory...\n", __func__); + if (!buffer) { edge_port->write_in_progress = false; goto exit_send; } - buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number - - edge_port->port->serial->minor, count); - buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number - - edge_port->port->serial->minor, count); + buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->port_number, count); + buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->port_number, count); /* now copy our data */ bytesleft = fifo->size - fifo->tail; @@ -1320,7 +1278,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, /* decrement the number of credits we have by the number we just sent */ edge_port->txCredits -= count; - edge_port->icount.tx += count; + edge_port->port->icount.tx += count; status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { @@ -1332,7 +1290,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, /* revert the credits as something bad happened. */ edge_port->txCredits += count; - edge_port->icount.tx -= count; + edge_port->port->icount.tx -= count; } dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n", __func__, count, edge_port->txCredits, fifo->count); @@ -1407,8 +1365,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty) edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); if (num_chars) { - dev_dbg(&port->dev, "%s(port %d) - returns %d\n", __func__, - port->number, num_chars); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, num_chars); } return num_chars; @@ -1594,31 +1551,6 @@ static int edge_tiocmget(struct tty_struct *tty) return result; } -static int edge_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct async_icount cnow; - cnow = edge_port->icount; - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__, - port->number, icount->rx, icount->tx); - return 0; -} - static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { @@ -1630,8 +1562,8 @@ static int get_serial_info(struct edgeport_port *edge_port, memset(&tmp, 0, sizeof(tmp)); tmp.type = PORT_16550A; - tmp.line = edge_port->port->serial->minor; - tmp.port = edge_port->port->number; + tmp.line = edge_port->port->minor; + tmp.port = edge_port->port->port_number; tmp.irq = 0; tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; tmp.xmit_fifo_size = edge_port->maxTxCredits; @@ -1655,46 +1587,15 @@ static int edge_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; DEFINE_WAIT(wait); struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct async_icount cnow; - struct async_icount cprev; - - dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); switch (cmd) { case TIOCSERGETLSR: - dev_dbg(&port->dev, "%s (%d) TIOCSERGETLSR\n", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__); return get_lsr_info(edge_port, (unsigned int __user *) arg); case TIOCGSERIAL: - dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__); return get_serial_info(edge_port, (struct serial_struct __user *) arg); - - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); - cprev = edge_port->icount; - while (1) { - 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; - cnow = edge_port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - break; - } return -ENOIOCTLCMD; } @@ -1756,7 +1657,6 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, struct device *dev = &edge_serial->serial->dev->dev; struct usb_serial_port *port; struct edgeport_port *edge_port; - struct tty_struct *tty; __u16 lastBufferLength; __u16 rxLen; @@ -1864,15 +1764,12 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, edge_serial->rxPort]; edge_port = usb_get_serial_port_data(port); if (edge_port->open) { - tty = tty_port_tty_get( - &edge_port->port->port); - if (tty) { - dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n", - __func__, rxLen, edge_serial->rxPort); - edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); - tty_kref_put(tty); - } - edge_port->icount.rx += rxLen; + dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n", + __func__, rxLen, + edge_serial->rxPort); + edge_tty_recv(edge_port->port, buffer, + rxLen); + edge_port->port->icount.rx += rxLen; } buffer += rxLen; } @@ -2021,20 +1918,20 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, * edge_tty_recv * this function passes data on to the tty flip buffer *****************************************************************************/ -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length) +static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data, + int length) { int cnt; - cnt = tty_insert_flip_string(tty, data, length); + cnt = tty_insert_flip_string(&port->port, data, length); if (cnt < length) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", + dev_err(&port->dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt); } data += cnt; length -= cnt; - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } @@ -2048,7 +1945,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { - icount = &edge_port->icount; + icount = &edge_port->port->icount; /* update input line counters */ if (newMsr & EDGEPORT_MSR_DELTA_CTS) @@ -2059,7 +1956,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) icount->dcd++; if (newMsr & EDGEPORT_MSR_DELTA_RI) icount->rng++; - wake_up_interruptible(&edge_port->delta_msr_wait); + wake_up_interruptible(&edge_port->port->port.delta_msr_wait); } /* Save the new modem status */ @@ -2090,16 +1987,11 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, } /* Place LSR data byte into Rx buffer */ - if (lsrData) { - struct tty_struct *tty = - tty_port_tty_get(&edge_port->port->port); - if (tty) { - edge_tty_recv(&edge_port->port->dev, tty, &data, 1); - tty_kref_put(tty); - } - } + if (lsrData) + edge_tty_recv(edge_port->port, &data, 1); + /* update input line counters */ - icount = &edge_port->icount; + icount = &edge_port->port->icount; if (newLsr & LSR_BREAK) icount->brk++; if (newLsr & LSR_OVER_ERR) @@ -2128,11 +2020,8 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, dev_dbg(&serial->dev->dev, "%s - %x, %x, %d\n", __func__, extAddr, addr, length); transfer_buffer = kmalloc(64, GFP_KERNEL); - if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", - __func__, 64); + if (!transfer_buffer) return -ENOMEM; - } /* need to split these writes up into 64 byte chunks */ result = 0; @@ -2176,11 +2065,8 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, unsigned char *transfer_buffer; transfer_buffer = kmalloc(64, GFP_KERNEL); - if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", - __func__, 64); + if (!transfer_buffer) return -ENOMEM; - } /* need to split these writes up into 64 byte chunks */ result = 0; @@ -2222,11 +2108,8 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr, unsigned char *transfer_buffer; transfer_buffer = kmalloc(64, GFP_KERNEL); - if (!transfer_buffer) { - dev_err(&serial->dev->dev, - "%s - kmalloc(%d) failed.\n", __func__, 64); + if (!transfer_buffer) return -ENOMEM; - } /* need to split these reads up into 64 byte chunks */ result = 0; @@ -2266,17 +2149,13 @@ static int send_iosp_ext_cmd(struct edgeport_port *edge_port, int status = 0; buffer = kmalloc(10, GFP_ATOMIC); - if (!buffer) { - dev_err(&edge_port->port->dev, - "%s - kmalloc(%d) failed.\n", __func__, 10); + if (!buffer) return -ENOMEM; - } currentCommand = buffer; - MAKE_CMD_EXT_CMD(¤tCommand, &length, - edge_port->port->number - edge_port->port->serial->minor, - command, param); + MAKE_CMD_EXT_CMD(¤tCommand, &length, edge_port->port->port_number, + command, param); status = write_cmd_usb(edge_port, buffer, length); if (status) { @@ -2359,18 +2238,16 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, int cmdLen = 0; int divisor; int status; - unsigned char number = - edge_port->port->number - edge_port->port->serial->minor; + u32 number = edge_port->port->port_number; if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { - dev_dbg(dev, "SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d\n", - edge_port->port->number, baudRate); + dev_dbg(dev, "SendCmdWriteBaudRate - NOT Setting baud rate for port, baud = %d\n", + baudRate); return 0; } - dev_dbg(dev, "%s - port = %d, baud = %d\n", __func__, - edge_port->port->number, baudRate); + dev_dbg(dev, "%s - baud = %d\n", __func__, baudRate); status = calc_baud_rate_divisor(dev, baudRate, &divisor); if (status) { @@ -2380,10 +2257,9 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, /* Alloc memory for the string of commands. */ cmdBuffer = kmalloc(0x100, GFP_ATOMIC); - if (!cmdBuffer) { - dev_err(dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100); + if (!cmdBuffer) return -ENOMEM; - } + currCmd = cmdBuffer; /* Enable access to divisor latch */ @@ -2481,9 +2357,8 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port, currCmd = cmdBuffer; /* Build a cmd in the buffer to write the given register */ - MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, - edge_port->port->number - edge_port->port->serial->minor, - regNum, regValue); + MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->port_number, + regNum, regValue); status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); if (status) { @@ -2517,8 +2392,6 @@ static void change_port_settings(struct tty_struct *tty, __u8 txFlow; int status; - dev_dbg(dev, "%s - port %d\n", __func__, edge_port->port->number); - if (!edge_port->open && !edge_port->openPending) { dev_dbg(dev, "%s - port not opened\n", __func__); @@ -2892,10 +2765,9 @@ static int edge_startup(struct usb_serial *serial) /* create our private serial structure */ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); - if (edge_serial == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + if (!edge_serial) return -ENOMEM; - } + spin_lock_init(&edge_serial->es_lock); edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); @@ -2984,14 +2856,12 @@ static int edge_startup(struct usb_serial *serial) /* not set up yet, so do it now */ edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!edge_serial->interrupt_read_urb) { - dev_err(ddev, "out of memory\n"); + if (!edge_serial->interrupt_read_urb) return -ENOMEM; - } + edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->interrupt_in_buffer) { - dev_err(ddev, "out of memory\n"); usb_free_urb(edge_serial->interrupt_read_urb); return -ENOMEM; } @@ -3021,14 +2891,12 @@ static int edge_startup(struct usb_serial *serial) /* not set up yet, so do it now */ edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!edge_serial->read_urb) { - dev_err(ddev, "out of memory\n"); + if (!edge_serial->read_urb) return -ENOMEM; - } + edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->bulk_in_buffer) { - dev_err(&dev->dev, "out of memory\n"); usb_free_urb(edge_serial->read_urb); return -ENOMEM; } |
