Hello > But first, why are you reimplementing the write functionality -- why not > reuse the generic implementation? The USB-RSA has a TX buffer of 4 Kbytes. To be able to take advantage of it, I implemented a streaming mechanism using the whiteheat driver as role model. I have not fully finished it yet -- as of now, the inner loop is redundant. > You need to call usb_serial_port_softint from your completion handler. That did the trick -- no more stalling. Thanks. I however still observe the buffering effect, i.e. characters sent from the USBRSA to a serial port is not directly dumped but buffered, and eventually displayed by cat. Can I set the buffer size somehow or control flushing ? Thanks Tilman Here the source for the write routine and the write handler: static int usbrsa_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial* serial = port->serial; struct usbrsa_port_private* priv = usb_get_serial_port_data(port); unsigned long flags; int retval; int nof_bytes_to_be_sent; int bytes; int urb_index; int sent = 0; struct urb* urb; dbg("%s - port %d START", __func__, port->number); while (count > 0) { // transfer only as many bytes as USB-RSA can take nof_bytes_to_be_sent = (count > priv->nofTxBytesFree) ? priv->nofTxBytesFree : count; dbg("%s - port %d; bytes=%d := count=%d : nofTxBytesFree=%d", __func__, port->number, nof_bytes_to_be_sent,count, priv->nofTxBytesFree); // debug nof_bytes_to_be_sent = count; // end debug while (nof_bytes_to_be_sent > 0) { // check for empty urb in write pool spin_lock_irqsave(&priv->lock, flags); urb_index = find_first_zero_bit(&priv- >write_urb_pool_lock, priv->urb_pool_size); dbg("%s - poolsize %d, urb_index %d\n",__func__, priv- >urb_pool_size,urb_index); if (urb_index >= priv->urb_pool_size) { // no more urbs available spin_unlock_irqrestore(&priv->lock, flags); goto out_write_no_urbs; } dbg("%s - port %d;URB allocated=%d",__func__, port- >number,urb_index); // reserve urb set_bit(urb_index, &priv->write_urb_pool_lock); urb = priv->write_urb_pool[urb_index]; spin_unlock_irqrestore(&priv->lock, flags); // copy data from userspace into urb transfer buffer bytes = (nof_bytes_to_be_sent > port->bulk_out_size) ? port->bulk_out_size : nof_bytes_to_be_sent; memcpy(urb->transfer_buffer, buf + sent, bytes); dbg("%s - port %d;bytes in urb=%d",__func__, port- >number, bytes); usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer); urb->dev = serial->dev; urb->transfer_buffer_length = bytes; // sent urb to USB-RSA retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) { // return urb to pool spin_lock_irqsave(&priv->lock, flags); clear_bit(urb_index, &priv- >write_urb_pool_lock); spin_unlock_irqrestore(&priv->lock, flags); dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, retval); sent = retval; // bail out goto out_write_submit_failed; } else { sent += bytes; count -= bytes; nof_bytes_to_be_sent -= bytes; dbg("%s - port %d;sent=%d;count=%d; nof_bytes_to_be_sent=%d;bytes=%d", __func__, port->number, sent,count, nof_bytes_to_be_sent, bytes); } } } out_write_no_urbs: out_write_submit_failed: dbg("%s() End - sent=%d\n",__func__,sent); return sent; } static void usbrsa_write_callback(struct urb *urb) { struct usb_serial_port* port = urb->context; struct usbrsa_port_private* priv = usb_get_serial_port_data (port); int status = urb->status; unsigned long flags; int urb_index; dbg("%s() - port = %d, ep =0x%x", __func__, port->number, priv->status_urb->pipe); usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, urb->transfer_buffer); // find urb in write pool for (urb_index=0; urb_index < priv->urb_pool_size;urb_index++) { if (urb == priv->write_urb_pool[urb_index]) { // urb found; return urb to pool spin_lock_irqsave(&priv->lock, flags); clear_bit(urb_index, &priv->write_urb_pool_lock); spin_unlock_irqrestore(&priv->lock, flags); break; } } if (urb != priv->write_urb_pool[urb_index]) { // urb not found -- this points to a bug dev_err(&port->dev, "%s(): urb not in pool", __func__); } dbg("%s(): Returned URB %d",__func__, urb_index); if (status) { dbg("%s(): nonzero urb status: 0x%d", __func__, status); } usb_serial_port_softint(port); } -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html