diff options
Diffstat (limited to 'drivers/usb/serial/keyspan_pda.c')
-rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 548 |
1 files changed, 237 insertions, 311 deletions
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index c1333919716b..e6f933e8d25f 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -5,12 +5,12 @@ * Copyright (C) 1999 - 2001 Greg Kroah-Hartman <greg@kroah.com> * Copyright (C) 1999, 2000 Brian Warner <warner@lothar.com> * Copyright (C) 2000 Al Borchers <borchers@steinerpoint.com> + * Copyright (C) 2020 Johan Hovold <johan@kernel.org> * * See Documentation/usb/usb-serial.rst for more information on using this * driver */ - #include <linux/kernel.h> #include <linux/errno.h> #include <linux/slab.h> @@ -25,30 +25,19 @@ #include <linux/usb/serial.h> #include <linux/usb/ezusb.h> -/* make a simple define to handle if we are compiling keyspan_pda or xircom support */ -#if IS_ENABLED(CONFIG_USB_SERIAL_KEYSPAN_PDA) - #define KEYSPAN -#else - #undef KEYSPAN -#endif -#if IS_ENABLED(CONFIG_USB_SERIAL_XIRCOM) - #define XIRCOM -#else - #undef XIRCOM -#endif - -#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>" +#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>, Johan Hovold <johan@kernel.org>" #define DRIVER_DESC "USB Keyspan PDA Converter driver" +#define KEYSPAN_TX_THRESHOLD 128 + struct keyspan_pda_private { int tx_room; - int tx_throttled; - struct work_struct wakeup_work; - struct work_struct unthrottle_work; + struct work_struct unthrottle_work; struct usb_serial *serial; struct usb_serial_port *port; }; +static int keyspan_pda_write_start(struct usb_serial_port *port); #define KEYSPAN_VENDOR_ID 0x06cd #define KEYSPAN_PDA_FAKE_ID 0x0103 @@ -62,18 +51,13 @@ struct keyspan_pda_private { #define ENTREGA_FAKE_ID 0x8093 static const struct usb_device_id id_table_combined[] = { -#ifdef KEYSPAN { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) }, -#endif -#ifdef XIRCOM { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID_2) }, { USB_DEVICE(ENTREGA_VENDOR_ID, ENTREGA_FAKE_ID) }, -#endif { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) }, { } /* Terminating entry */ }; - MODULE_DEVICE_TABLE(usb, id_table_combined); static const struct usb_device_id id_table_std[] = { @@ -81,46 +65,71 @@ static const struct usb_device_id id_table_std[] = { { } /* Terminating entry */ }; -#ifdef KEYSPAN static const struct usb_device_id id_table_fake[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) }, - { } /* Terminating entry */ -}; -#endif - -#ifdef XIRCOM -static const struct usb_device_id id_table_fake_xircom[] = { { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID_2) }, { USB_DEVICE(ENTREGA_VENDOR_ID, ENTREGA_FAKE_ID) }, - { } + { } /* Terminating entry */ }; -#endif -static void keyspan_pda_wakeup_write(struct work_struct *work) +static int keyspan_pda_get_write_room(struct keyspan_pda_private *priv) { - struct keyspan_pda_private *priv = - container_of(work, struct keyspan_pda_private, wakeup_work); struct usb_serial_port *port = priv->port; + struct usb_serial *serial = port->serial; + u8 *room; + int rc; + + room = kmalloc(1, GFP_KERNEL); + if (!room) + return -ENOMEM; - tty_port_tty_wakeup(&port->port); + rc = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + 6, /* write_room */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE + | USB_DIR_IN, + 0, /* value: 0 means "remaining room" */ + 0, /* index */ + room, + 1, + 2000); + if (rc != 1) { + if (rc >= 0) + rc = -EIO; + dev_dbg(&port->dev, "roomquery failed: %d\n", rc); + goto out_free; + } + + dev_dbg(&port->dev, "roomquery says %d\n", *room); + rc = *room; +out_free: + kfree(room); + + return rc; } static void keyspan_pda_request_unthrottle(struct work_struct *work) { struct keyspan_pda_private *priv = container_of(work, struct keyspan_pda_private, unthrottle_work); - struct usb_serial *serial = priv->serial; + struct usb_serial_port *port = priv->port; + struct usb_serial *serial = port->serial; + unsigned long flags; int result; - /* ask the device to tell us when the tx buffer becomes - sufficiently empty */ + dev_dbg(&port->dev, "%s\n", __func__); + + /* + * Ask the device to tell us when the tx buffer becomes + * sufficiently empty. + */ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 7, /* request_unthrottle */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - 16, /* value: threshold */ + KEYSPAN_TX_THRESHOLD, 0, /* index */ NULL, 0, @@ -128,9 +137,20 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) if (result < 0) dev_dbg(&serial->dev->dev, "%s - error %d from usb_control_msg\n", __func__, result); + /* + * Need to check available space after requesting notification in case + * buffer is already empty so that no notification is sent. + */ + result = keyspan_pda_get_write_room(priv); + if (result > KEYSPAN_TX_THRESHOLD) { + spin_lock_irqsave(&port->lock, flags); + priv->tx_room = max(priv->tx_room, result); + spin_unlock_irqrestore(&port->lock, flags); + + usb_serial_port_softint(port); + } } - static void keyspan_pda_rx_interrupt(struct urb *urb) { struct usb_serial_port *port = urb->context; @@ -139,6 +159,8 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) int retval; int status = urb->status; struct keyspan_pda_private *priv; + unsigned long flags; + priv = usb_get_serial_port_data(port); switch (status) { @@ -172,18 +194,22 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) break; case 1: /* status interrupt */ - if (len < 3) { + if (len < 2) { dev_warn(&port->dev, "short interrupt message received\n"); break; } - dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]); + dev_dbg(&port->dev, "rx int, d1=%d\n", data[1]); switch (data[1]) { case 1: /* modemline change */ break; case 2: /* tx unthrottle interrupt */ - priv->tx_throttled = 0; - /* queue up a wakeup at scheduler time */ - schedule_work(&priv->wakeup_work); + spin_lock_irqsave(&port->lock, flags); + priv->tx_room = max(priv->tx_room, KEYSPAN_TX_THRESHOLD); + spin_unlock_irqrestore(&port->lock, flags); + + keyspan_pda_write_start(port); + + usb_serial_port_softint(port); break; default: break; @@ -201,31 +227,30 @@ exit: __func__, retval); } - static void keyspan_pda_rx_throttle(struct tty_struct *tty) { - /* stop receiving characters. We just turn off the URB request, and - let chars pile up in the device. If we're doing hardware - flowcontrol, the device will signal the other end when its buffer - fills up. If we're doing XON/XOFF, this would be a good time to - send an XOFF, although it might make sense to foist that off - upon the device too. */ struct usb_serial_port *port = tty->driver_data; + /* + * Stop receiving characters. We just turn off the URB request, and + * let chars pile up in the device. If we're doing hardware + * flowcontrol, the device will signal the other end when its buffer + * fills up. If we're doing XON/XOFF, this would be a good time to + * send an XOFF, although it might make sense to foist that off upon + * the device too. + */ usb_kill_urb(port->interrupt_in_urb); } - static void keyspan_pda_rx_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - /* just restart the receive interrupt URB */ + /* just restart the receive interrupt URB */ if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL)) dev_dbg(&port->dev, "usb_submit_urb(read urb) failed\n"); } - static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud) { int rc; @@ -267,8 +292,6 @@ static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud) baud = 9600; } - /* rather than figure out how to sleep while waiting for this - to complete, I just use the "legacy" API. */ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0, /* set baud */ USB_TYPE_VENDOR @@ -281,10 +304,10 @@ static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud) 2000); /* timeout */ if (rc < 0) return 0; + return baud; } - static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; @@ -296,6 +319,7 @@ static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) value = 1; /* start break */ else value = 0; /* clear break */ + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 4, /* set break */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, @@ -303,39 +327,35 @@ static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) if (result < 0) dev_dbg(&port->dev, "%s - error %d from usb_control_msg\n", __func__, result); - /* there is something funky about this.. the TCSBRK that 'cu' performs - ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4 - seconds apart, but it feels like the break sent isn't as long as it - is on /dev/ttyS0 */ } - static void keyspan_pda_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; speed_t speed; - /* cflag specifies lots of stuff: number of stop bits, parity, number - of data bits, baud. What can the device actually handle?: - CSTOPB (1 stop bit or 2) - PARENB (parity) - CSIZE (5bit .. 8bit) - There is minimal hw support for parity (a PSW bit seems to hold the - parity of whatever is in the accumulator). The UART either deals - with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data, - 1 special, stop). So, with firmware changes, we could do: - 8N1: 10 bit - 8N2: 11 bit, extra bit always (mark?) - 8[EOMS]1: 11 bit, extra bit is parity - 7[EOMS]1: 10 bit, b0/b7 is parity - 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?) - - HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS - bit. - - For now, just do baud. */ - + /* + * cflag specifies lots of stuff: number of stop bits, parity, number + * of data bits, baud. What can the device actually handle?: + * CSTOPB (1 stop bit or 2) + * PARENB (parity) + * CSIZE (5bit .. 8bit) + * There is minimal hw support for parity (a PSW bit seems to hold the + * parity of whatever is in the accumulator). The UART either deals + * with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data, + * 1 special, stop). So, with firmware changes, we could do: + * 8N1: 10 bit + * 8N2: 11 bit, extra bit always (mark?) + * 8[EOMS]1: 11 bit, extra bit is parity + * 7[EOMS]1: 10 bit, b0/b7 is parity + * 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?) + * + * HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS + * bit. + * + * For now, just do baud. + */ speed = tty_get_baud_rate(tty); speed = keyspan_pda_setbaud(serial, speed); @@ -344,17 +364,19 @@ static void keyspan_pda_set_termios(struct tty_struct *tty, /* It hasn't changed so.. */ speed = tty_termios_baud_rate(old_termios); } - /* Only speed can change so copy the old h/w parameters - then encode the new speed */ + /* + * Only speed can change so copy the old h/w parameters then encode + * the new speed. + */ tty_termios_copy_hw(&tty->termios, old_termios); tty_encode_baud_rate(tty, speed, speed); } - -/* modem control pins: DTR and RTS are outputs and can be controlled. - DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be - read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused */ - +/* + * Modem control pins: DTR and RTS are outputs and can be controlled. + * DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be + * read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused. + */ static int keyspan_pda_get_modem_info(struct usb_serial *serial, unsigned char *value) { @@ -378,7 +400,6 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial, return rc; } - static int keyspan_pda_set_modem_info(struct usb_serial *serial, unsigned char value) { @@ -401,13 +422,14 @@ static int keyspan_pda_tiocmget(struct tty_struct *tty) rc = keyspan_pda_get_modem_info(serial, &status); if (rc < 0) return rc; - value = - ((status & (1<<7)) ? TIOCM_DTR : 0) | - ((status & (1<<6)) ? TIOCM_CAR : 0) | - ((status & (1<<5)) ? TIOCM_RNG : 0) | - ((status & (1<<4)) ? TIOCM_DSR : 0) | - ((status & (1<<3)) ? TIOCM_CTS : 0) | - ((status & (1<<2)) ? TIOCM_RTS : 0); + + value = ((status & BIT(7)) ? TIOCM_DTR : 0) | + ((status & BIT(6)) ? TIOCM_CAR : 0) | + ((status & BIT(5)) ? TIOCM_RNG : 0) | + ((status & BIT(4)) ? TIOCM_DSR : 0) | + ((status & BIT(3)) ? TIOCM_CTS : 0) | + ((status & BIT(2)) ? TIOCM_RTS : 0); + return value; } @@ -424,186 +446,127 @@ static int keyspan_pda_tiocmset(struct tty_struct *tty, return rc; if (set & TIOCM_RTS) - status |= (1<<2); + status |= BIT(2); if (set & TIOCM_DTR) - status |= (1<<7); + status |= BIT(7); if (clear & TIOCM_RTS) - status &= ~(1<<2); + status &= ~BIT(2); if (clear & TIOCM_DTR) - status &= ~(1<<7); + status &= ~BIT(7); rc = keyspan_pda_set_modem_info(serial, status); return rc; } -static int keyspan_pda_write(struct tty_struct *tty, - struct usb_serial_port *port, const unsigned char *buf, int count) +static int keyspan_pda_write_start(struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; - int request_unthrottle = 0; - int rc = 0; - struct keyspan_pda_private *priv; + struct keyspan_pda_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + struct urb *urb; + int count; + int room; + int rc; - priv = usb_get_serial_port_data(port); - /* guess how much room is left in the device's ring buffer, and if we - want to send more than that, check first, updating our notion of - what is left. If our write will result in no room left, ask the - device to give us an interrupt when the room available rises above - a threshold, and hold off all writers (eventually, those using - select() or poll() too) until we receive that unthrottle interrupt. - Block if we can't write anything at all, otherwise write as much as - we can. */ - if (count == 0) { - dev_dbg(&port->dev, "write request of 0 bytes\n"); - return 0; - } + /* + * Guess how much room is left in the device's ring buffer. If our + * write will result in no room left, ask the device to give us an + * interrupt when the room available rises above a threshold but also + * query how much room is currently available (in case our guess was + * too conservative and the buffer is already empty when the + * unthrottle work is scheduled). + */ + + /* + * We might block because of: + * the TX urb is in-flight (wait until it completes) + * the device is full (wait until it says there is room) + */ + spin_lock_irqsave(&port->lock, flags); + + room = priv->tx_room; + count = kfifo_len(&port->write_fifo); - /* we might block because of: - the TX urb is in-flight (wait until it completes) - the device is full (wait until it says there is room) - */ - spin_lock_bh(&port->lock); - if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) { - spin_unlock_bh(&port->lock); + if (!test_bit(0, &port->write_urbs_free) || count == 0 || room == 0) { + spin_unlock_irqrestore(&port->lock, flags); return 0; } - clear_bit(0, &port->write_urbs_free); - spin_unlock_bh(&port->lock); - - /* At this point the URB is in our control, nobody else can submit it - again (the only sudden transition was the one from EINPROGRESS to - finished). Also, the tx process is not throttled. So we are - ready to write. */ - - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - - /* Check if we might overrun the Tx buffer. If so, ask the - device how much room it really has. This is done only on - scheduler time, since usb_control_msg() sleeps. */ - if (count > priv->tx_room && !in_interrupt()) { - u8 *room; - - room = kmalloc(1, GFP_KERNEL); - if (!room) { - rc = -ENOMEM; - goto exit; - } + __clear_bit(0, &port->write_urbs_free); - rc = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 6, /* write_room */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_IN, - 0, /* value: 0 means "remaining room" */ - 0, /* index */ - room, - 1, - 2000); - if (rc > 0) { - dev_dbg(&port->dev, "roomquery says %d\n", *room); - priv->tx_room = *room; - } - kfree(room); - if (rc < 0) { - dev_dbg(&port->dev, "roomquery failed\n"); - goto exit; - } - if (rc == 0) { - dev_dbg(&port->dev, "roomquery returned 0 bytes\n"); - rc = -EIO; /* device didn't return any data */ - goto exit; - } - } - if (count > priv->tx_room) { - /* we're about to completely fill the Tx buffer, so - we'll be throttled afterwards. */ - count = priv->tx_room; - request_unthrottle = 1; - } + if (count > room) + count = room; + if (count > port->bulk_out_size) + count = port->bulk_out_size; - if (count) { - /* now transfer data */ - memcpy(port->write_urb->transfer_buffer, buf, count); - /* send the data out the bulk port */ - port->write_urb->transfer_buffer_length = count; + urb = port->write_urb; + count = kfifo_out(&port->write_fifo, urb->transfer_buffer, count); + urb->transfer_buffer_length = count; - priv->tx_room -= count; + port->tx_bytes += count; + priv->tx_room -= count; - rc = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (rc) { - dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n"); - goto exit; - } - } else { - /* There wasn't any room left, so we are throttled until - the buffer empties a bit */ - request_unthrottle = 1; + spin_unlock_irqrestore(&port->lock, flags); + + dev_dbg(&port->dev, "%s - count = %d, txroom = %d\n", __func__, count, room); + + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc) { + dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n"); + + spin_lock_irqsave(&port->lock, flags); + port->tx_bytes -= count; + priv->tx_room = max(priv->tx_room, room + count); + __set_bit(0, &port->write_urbs_free); + spin_unlock_irqrestore(&port->lock, flags); + + return rc; } - if (request_unthrottle) { - priv->tx_throttled = 1; /* block writers */ + if (count == room) schedule_work(&priv->unthrottle_work); - } - rc = count; -exit: - if (rc < 0) - set_bit(0, &port->write_urbs_free); - return rc; + return count; } - static void keyspan_pda_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct keyspan_pda_private *priv; + unsigned long flags; - set_bit(0, &port->write_urbs_free); - priv = usb_get_serial_port_data(port); + spin_lock_irqsave(&port->lock, flags); + port->tx_bytes -= urb->transfer_buffer_length; + __set_bit(0, &port->write_urbs_free); + spin_unlock_irqrestore(&port->lock, flags); - /* queue up a wakeup at scheduler time */ - schedule_work(&priv->wakeup_work); -} + keyspan_pda_write_start(port); + usb_serial_port_softint(port); +} -static int keyspan_pda_write_room(struct tty_struct *tty) +static int keyspan_pda_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { - struct usb_serial_port *port = tty->driver_data; - struct keyspan_pda_private *priv; - priv = usb_get_serial_port_data(port); - /* used by n_tty.c for processing of tabs and such. Giving it our - conservative guess is probably good enough, but needs testing by - running a console through the device. */ - return priv->tx_room; -} + int rc; + dev_dbg(&port->dev, "%s - count = %d\n", __func__, count); -static int keyspan_pda_chars_in_buffer(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct keyspan_pda_private *priv; - unsigned long flags; - int ret = 0; + if (!count) + return 0; - priv = usb_get_serial_port_data(port); + count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); - /* when throttled, return at least WAKEUP_CHARS to tell select() (via - n_tty.c:normal_poll() ) that we're not writeable. */ + rc = keyspan_pda_write_start(port); + if (rc) + return rc; - spin_lock_irqsave(&port->lock, flags); - if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) - ret = 256; - spin_unlock_irqrestore(&port->lock, flags); - return ret; + return count; } - static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) { struct usb_serial *serial = port->serial; if (on) - keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2)); + keyspan_pda_set_modem_info(serial, BIT(7) | BIT(2)); else keyspan_pda_set_modem_info(serial, 0); } @@ -612,74 +575,63 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) static int keyspan_pda_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; - u8 *room; - int rc = 0; - struct keyspan_pda_private *priv; + struct keyspan_pda_private *priv = usb_get_serial_port_data(port); + int rc; /* find out how much room is in the Tx ring */ - room = kmalloc(1, GFP_KERNEL); - if (!room) - return -ENOMEM; + rc = keyspan_pda_get_write_room(priv); + if (rc < 0) + return rc; - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - 6, /* write_room */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_IN, - 0, /* value */ - 0, /* index */ - room, - 1, - 2000); - if (rc < 0) { - dev_dbg(&port->dev, "%s - roomquery failed\n", __func__); - goto error; - } - if (rc == 0) { - dev_dbg(&port->dev, "%s - roomquery returned 0 bytes\n", __func__); - rc = -EIO; - goto error; - } - priv = usb_get_serial_port_data(port); - priv->tx_room = *room; - priv->tx_throttled = *room ? 0 : 1; + spin_lock_irq(&port->lock); + priv->tx_room = rc; + spin_unlock_irq(&port->lock); - /*Start reading from the device*/ rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (rc) { dev_dbg(&port->dev, "%s - usb_submit_urb(read int) failed\n", __func__); - goto error; + return rc; } -error: - kfree(room); - return rc; + + return 0; } + static void keyspan_pda_close(struct usb_serial_port *port) { - usb_kill_urb(port->write_urb); + struct keyspan_pda_private *priv = usb_get_serial_port_data(port); + + /* + * Stop the interrupt URB first as its completion handler may submit + * the write URB. + */ usb_kill_urb(port->interrupt_in_urb); -} + usb_kill_urb(port->write_urb); + + cancel_work_sync(&priv->unthrottle_work); + spin_lock_irq(&port->lock); + kfifo_reset(&port->write_fifo); + spin_unlock_irq(&port->lock); +} /* download the firmware to a "fake" device (pre-renumeration) */ static int keyspan_pda_fake_startup(struct usb_serial *serial) { + unsigned int vid = le16_to_cpu(serial->dev->descriptor.idVendor); const char *fw_name; /* download the firmware here ... */ ezusb_fx1_set_reset(serial->dev, 1); - if (0) { ; } -#ifdef KEYSPAN - else if (le16_to_cpu(serial->dev->descriptor.idVendor) == KEYSPAN_VENDOR_ID) + switch (vid) { + case KEYSPAN_VENDOR_ID: fw_name = "keyspan_pda/keyspan_pda.fw"; -#endif -#ifdef XIRCOM - else if ((le16_to_cpu(serial->dev->descriptor.idVendor) == XIRCOM_VENDOR_ID) || - (le16_to_cpu(serial->dev->descriptor.idVendor) == ENTREGA_VENDOR_ID)) + break; + case XIRCOM_VENDOR_ID: + case ENTREGA_VENDOR_ID: fw_name = "keyspan_pda/xircom_pgs.fw"; -#endif - else { + break; + default: dev_err(&serial->dev->dev, "%s: unknown vendor, aborting.\n", __func__); return -ENODEV; @@ -691,19 +643,17 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) return -ENOENT; } - /* after downloading firmware Renumeration will occur in a - moment and the new device will bind to the real driver */ + /* + * After downloading firmware renumeration will occur in a moment and + * the new device will bind to the real driver. + */ - /* we want this device to fail to have a driver assigned to it. */ + /* We want this device to fail to have a driver assigned to it. */ return 1; } -#ifdef KEYSPAN MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); -#endif -#ifdef XIRCOM MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); -#endif static int keyspan_pda_port_probe(struct usb_serial_port *port) { @@ -714,9 +664,7 @@ static int keyspan_pda_port_probe(struct usb_serial_port *port) if (!priv) return -ENOMEM; - INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); - priv->serial = port->serial; priv->port = port; usb_set_serial_port_data(port, priv); @@ -734,7 +682,6 @@ static int keyspan_pda_port_remove(struct usb_serial_port *port) return 0; } -#ifdef KEYSPAN static struct usb_serial_driver keyspan_pda_fake_device = { .driver = { .owner = THIS_MODULE, @@ -745,20 +692,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = { .num_ports = 1, .attach = keyspan_pda_fake_startup, }; -#endif - -#ifdef XIRCOM -static struct usb_serial_driver xircom_pgs_fake_device = { - .driver = { - .owner = THIS_MODULE, - .name = "xircom_no_firm", - }, - .description = "Xircom / Entrega PGS - (prerenumeration)", - .id_table = id_table_fake_xircom, - .num_ports = 1, - .attach = keyspan_pda_fake_startup, -}; -#endif static struct usb_serial_driver keyspan_pda_device = { .driver = { @@ -774,10 +707,8 @@ static struct usb_serial_driver keyspan_pda_device = { .open = keyspan_pda_open, .close = keyspan_pda_close, .write = keyspan_pda_write, - .write_room = keyspan_pda_write_room, - .write_bulk_callback = keyspan_pda_write_bulk_callback, + .write_bulk_callback = keyspan_pda_write_bulk_callback, .read_int_callback = keyspan_pda_rx_interrupt, - .chars_in_buffer = keyspan_pda_chars_in_buffer, .throttle = keyspan_pda_rx_throttle, .unthrottle = keyspan_pda_rx_unthrottle, .set_termios = keyspan_pda_set_termios, @@ -790,12 +721,7 @@ static struct usb_serial_driver keyspan_pda_device = { static struct usb_serial_driver * const serial_drivers[] = { &keyspan_pda_device, -#ifdef KEYSPAN &keyspan_pda_fake_device, -#endif -#ifdef XIRCOM - &xircom_pgs_fake_device, -#endif NULL }; |