Greg KH <greg@...> writes: Dear Greg > > I moved the initialization and clean up code from the init_callback/release > > callback to the port_init/port_remove callback. I am referring to your last posting on Feb 25th: gkh> Release your port data in the port_remove callback, not the release gkh> callback. The release callback is for when your whole device is gkh> removed, not the individual ports. In addition, I initialized a spinlock as part of setting up the data structures in the port_init callback routine. Since then, the driver is no longer crashing, and also the load no longer slowly builds up causing the machine to eventually freeze. One problem solved. Next problem: When issuing a write command to the driver via echo "text" > /dev/ttyUSB0, there is a delay of about 30 seconds until echo completes (echo is blocking for 30 seconds). The timestamp in the syslog also show this: usbrsa_close is started only around 30 secs (see below below @ 7346.332061) after completion of the write completion handlers. The routine usbrsa_status_callback that was started first by usbrsa_open, and is then being continuously called by itself, does not block. (For the source code of the involved routines, please see below) With the ancient kernel version 3.17, this was working fine. I would not think that the 30 seconds blockng are not random but are related to a timeout of any kind. 1) I wonder what the kernel is doing between usbrsa_write and usbrsa_close. it seems not to be executing code within the driver. What can cause the 30 seconds of blocking/what is the kernel waiting for? 2) I have seen other drivers calling usb_serial_port_softint from various places. What exaclty does usb_serial_port_softint/schedule_word that is called by usb_serial_port_softint? Many thanks Tilman Syslog: ======= ... [ 7315.882626] usbrsa_open - port=0 [ 7315.882666] usbrsa ttyUSB0: usbrsa_write_room(): Pool=640;usbrsa.tx=4084 [ 7315.882673] usbrsa ttyUSB0: usbrsa_write - port 0 START [ 7315.882676] usbrsa_write; private struct =ffff8803ff468c00 [ 7315.882682] usbrsa ttyUSB0: usbrsa_write - port 0; bytes=10 := count=10 : nofTxBytesFree=4084 [ 7315.882688] usbrsa ttyUSB0: usbrsa_write - poolsize 10, urb_index 0 [ 7315.882694] usbrsa ttyUSB0: usbrsa_write - port 0;URB allocated=0 [ 7315.882699] usbrsa ttyUSB0: usbrsa_write - port 0;bytes in urb=10 [ 7315.882705] usbrsa ttyUSB0: usbrsa_write - length = 10, data = 31 32 33 34 35 36 37 38 39 30 [ 7315.882711] usbrsa ttyUSB0: usbrsa_write - port 0;sent=10;count=0; nof_bytes_to_be_sent=0;bytes=10 [ 7315.882714] usbrsa ttyUSB0: usbrsa_write() End - sent=10 [ 7315.882722] usbrsa ttyUSB0: usbrsa_write_room(): Pool=576;usbrsa.tx=4084 [ 7315.882726] usbrsa ttyUSB0: usbrsa_write - port 0 START [ 7315.882729] usbrsa_write; private struct =ffff8803ff468c00 [ 7315.882734] usbrsa ttyUSB0: usbrsa_write - port 0; bytes=2 := count=2 : nofTxBytesFree=4084 [ 7315.882738] usbrsa ttyUSB0: usbrsa_write - poolsize 10, urb_index 1 [ 7315.882742] usbrsa ttyUSB0: usbrsa_write - port 0;URB allocated=1 [ 7315.882745] usbrsa ttyUSB0: usbrsa_write - port 0;bytes in urb=2 [ 7315.882748] usbrsa ttyUSB0: usbrsa_write - length = 2, data = 0d 0a [ 7315.882753] usbrsa ttyUSB0: usbrsa_write - port 0;sent=2;count=0; nof_bytes_to_be_sent=0;bytes=2 [ 7315.882756] usbrsa ttyUSB0: usbrsa_write() End - sent=2 [ 7315.882769] usbrsa ttyUSB0: usbrsa_write_callback() - port = 0, ep =0xc0018380 [ 7315.882776] usbrsa ttyUSB0: usbrsa_write_callback - length = 10, data = 31 32 33 34 35 36 37 38 39 30 [ 7315.882781] usbrsa ttyUSB0: usbrsa_write_callback(): Returned URB 0 [ 7315.882918] usbrsa ttyUSB0: usbrsa_write_callback() - port = 0, ep =0xc0018380 [ 7315.882927] usbrsa ttyUSB0: usbrsa_write_callback - length = 2, data = 0d 0a [ 7315.882932] usbrsa ttyUSB0: usbrsa_write_callback(): Returned URB 1 [ 7315.882938] usbrsa_status_callback: nofTxBytesFree=4074,nofRxBytesReceived=0 [ 7315.883002] usbrsa_status_callback: nofTxBytesFree=4072,nofRxBytesReceived=0 [ 7346.332061] usbrsa_close - start [ 7346.332070] usbrsa ttyUSB0: usbrsa_close - port 0 start [ 7346.332076] usbrsa ttyUSB0: send_baudrate_lcr_register() CFLAG=3261 [ 7346.332080] usbrsa ttyUSB0: send_baudrate_lcr_register() ST16C550.DLL=50;ST16C550.DLM=0;ST16C550.LCR=3 [ 7346.332130] usbrsa ttyUSB0: usbrsa_baudrate_lcr_callback() - port = 0, ep=0xc0028300 [ 7346.332142] usbrsa ttyUSB0: send_baudrate_lcr_register() leaving [ 7346.332146] usbrsa ttyUSB0: usbrsa_close - #retries=3 [ 7346.332148] usbrsa_close - end [ 7346.332151] usbrsa ttyUSB0: usbrsa_close - end [ 7346.332163] usbrsa ttyUSB0: usbrsa_status_callback(): wake_up Source code Excerpt: ===================== static struct usb_serial_driver usbrsa_enumerated_device = { .driver = { .owner = THIS_MODULE, .name = "usbrsa", }, .description = "IO-DATA - USB-RSA", .id_table = id_table_std, .num_ports = 1, .attach = usbrsa_attach, .release = usbrsa_release, .port_probe = usbrsa_probe, .port_remove = usbrsa_remove, .open = usbrsa_open, .close = usbrsa_close, .write = usbrsa_write, .write_bulk_callback = usbrsa_write_callback, .read_bulk_callback = usbrsa_read_callback, .set_termios = usbrsa_set_termios, .tiocmset = usbrsa_tiocmset, .tiocmget = usbrsa_tiocmget, .init_termios = usbrsa_init_termios, .ioctl = usbrsa_ioctl, .write_room = usbrsa_write_room, .chars_in_buffer = usbrsa_chars_in_buffer, .throttle = usbrsa_throttle, .unthrottle = usbrsa_unthrottle }; static int usbrsa_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; int retval = 0; struct usbrsa_port_private* priv = usb_get_serial_port_data(port); unsigned long flags; printk("%s; priv=%p\n",__func__,priv); dev_dbg(&port->dev,"%s - port %d", __func__,port->port_number); // flush buffer of USB-RSA by sending reset //retval = send_reset(port); if (retval != 0) { dev_err(&port->dev, "%s(): usb_submit_urb() failed" " with error %d\n", __func__, retval); return ENODEV; } if (tty) { // usbrsa_set_termios will sent to endpoint 2 of the USB-RSA thereby // turning on the RX interrupt usbrsa_set_termios(tty, port, &tmp_termios); } // start reading from USB-RSA spin_lock_irqsave(&priv->lock, flags); if (!(test_bit(LOCK_STATUS,&priv->urb_lock))) { set_bit(LOCK_STATUS,&priv->urb_lock); // enable continuous reading priv->read_running = USBRSA_READ_RUNNING; spin_unlock_irqrestore(&priv->lock, flags); retval = usb_submit_urb(priv->status_urb,GFP_KERNEL); } else { spin_unlock_irqrestore(&priv->lock, flags); } dev_dbg(&port->dev,"%s - port %d: leaving", __func__, port->port_number); printk("%s - port=%d",__func__,port->port_number); return 0; } tatic void usbrsa_close(struct usb_serial_port *port) { struct usbrsa_port_private* priv = usb_get_serial_port_data(port); int retries = 3; unsigned long flags; int retval; printk("%s - start",__func__); dev_dbg(&port->dev,"%s - port %d start", __func__, port->port_number); // turn off RX interrupt of USB-RSA by sending to EP5) while(retries > 0) { // turn off RX interrupt of USB-RSA by sending to EP5. retval = send_baudrate_lcr_register(priv->c_flag, priv->baudrate, EP5OUT, port); if (retval != 0) { dev_err(&port->dev, "%s(): usb_submit_urb() failed" " with error %d\n", __func__, retval); } else { dev_dbg(&port->dev,"%s - #retries=%d", __func__,retries); break; } retries--; } // disable continuous reading spin_lock_irqsave(&priv->lock, flags); priv->read_running = USBRSA_READ_STOP; spin_unlock_irqrestore(&priv->lock, flags); printk("%s - end",__func__); dev_dbg(&port->dev,"%s - end ", __func__); return; } 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; dev_dbg(&port->dev,"%s - port %d START", __func__,port->port_number); printk("%s; private struct =%p\n",__func__,priv); while (count > 0) { // transfer only as many bytes as USB-RSA can take nof_bytes_to_be_sent = (count > priv->nofTxBytesFree) ? priv->nofTxBytesFree : count; dev_dbg(&port->dev,"%s - port %d; bytes=%d := count=%d : nofTxBytesFree=%d", __func__, port->port_number, nof_bytes_to_be_sent,count, priv->nofTxBytesFree); 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); dev_dbg(&port->dev,"%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; } dev_dbg(&port->dev,"%s - port %d;URB allocated=%d",__func__, port->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); dev_dbg(&port->dev,"%s - port %d;bytes in urb=%d",__func__, port->port_number, bytes); usb_serial_debug_data( &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; dev_dbg(&port->dev,"%s - port %d;sent=%d;count=%d; nof_bytes_to_be_sent=%d;bytes=%d", __func__, port->port_number, sent,count, nof_bytes_to_be_sent, bytes); } } } out_write_no_urbs: out_write_submit_failed: dev_dbg(&port->dev,"%s() End - sent=%d\n",__func__,sent); usb_serial_port_softint(port); 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; dev_dbg(&port->dev,"%s() - port = %d, ep =0x%x", __func__, port->port_number, priv->status_urb->pipe); usb_serial_debug_data( &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__); } dev_dbg(&port->dev,"%s(): Returned URB %d",__func__, urb_index); if (status) { dev_dbg(&port->dev,"%s(): nonzero urb status: 0x%d", __func__, status); } usb_serial_port_softint(port); } static void usbrsa_status_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; __u8* ep3in = urb->transfer_buffer; unsigned long flags; int retval; int read_urbs_needed = 0; int urb_index; unsigned int i; // dev_dbg(&port->dev,"%s() - port = %d, ep =0x%x", __func__, port->port_number, // priv->status_urb->pipe); spin_lock_irqsave(&priv->lock, flags); // read payload data of urb, i.e. bytes received and bytes // available in tx queue of USB-RSA priv->nofTxBytesFree = ep3in[0] + (256 * ep3in[1]); priv->nofRxBytesReceived= ep3in[2] + (256 * ep3in[3]); // unlock urb clear_bit(LOCK_STATUS,&priv->urb_lock); spin_unlock_irqrestore(&priv->lock, flags); if ((priv->DebugNofTxBytesFree != priv->nofTxBytesFree) || (priv->DebugRxBytesReceived != priv->nofRxBytesReceived)) { printk("%s: nofTxBytesFree=%d,nofRxBytesReceived=%d \n", __func__, priv->nofTxBytesFree, priv->nofRxBytesReceived); } priv->DebugNofTxBytesFree = priv->nofTxBytesFree; priv->DebugRxBytesReceived = priv->nofRxBytesReceived; // if coutinuous read enabled, either // -- issue next status request (USBRSA did not receive // anything) // -- issue a read urb (if rx queue is filled) if (priv->read_running == USBRSA_READ_RUNNING) { if(priv->nofRxBytesReceived != 0) { // USB-RSA received data // compute urbs needed read_urbs_needed = priv->nofRxBytesReceived/port->bulk_in_size; if (priv->nofRxBytesReceived%port->bulk_in_size) read_urbs_needed++; dev_dbg(&port->dev,"%s(): EP1IN: rx=%d, urbs_needed=%d,size_of_urb=%d", __func__, priv->nofRxBytesReceived, read_urbs_needed, port->bulk_in_size); // issue read urbs // todo: issue more than one read urb. Will this work ? if (read_urbs_needed > priv->urb_pool_size) read_urbs_needed = priv->urb_pool_size; for(i=0; i < read_urbs_needed;i++ ) { spin_lock_irqsave(&priv->lock, flags); urb_index = find_first_zero_bit(&priv->read_urb_pool_lock, priv->urb_pool_size); if (urb_index < priv->urb_pool_size) { set_bit(urb_index,&priv->read_urb_pool_lock); spin_unlock_irqrestore(&priv->lock, flags); // submit read dev_dbg(&port->dev,"%s(): submit read urb[%d]", __func__,urb_index ); retval = usb_submit_urb( priv->read_urb_pool[urb_index],GFP_KERNEL); if (retval) { // return urb to read pool spin_lock_irqsave(&priv->lock, flags); clear_bit(urb_index,&priv->read_urb_pool_lock); spin_unlock_irqrestore(&priv->lock, flags); dev_dbg(&port->dev,"%s(): nonzero urb status: 0x%d", __func__, status); return; } } else { spin_unlock_irqrestore(&priv->lock, flags); i = read_urbs_needed; } } } spin_lock_irqsave(&priv->lock, flags); set_bit(LOCK_STATUS,&priv->urb_lock); spin_unlock_irqrestore(&priv->lock, flags); retval = usb_submit_urb(priv->status_urb,GFP_KERNEL); if (retval != 0) { dev_err(&port->dev, "%s(): usb_submit_urb() failed" " with error %d\n", __func__, retval); spin_lock_irqsave(&priv->lock, flags); clear_bit(LOCK_STATUS,&priv->urb_lock); spin_unlock_irqrestore(&priv->lock, flags); } } else { // reading from device ceased -- do nothing //dev_dbg(&port->dev,"%s(): reading stopped: tx_free=%d;rx_recv=%d", // __func__, priv->nofTxBytesFree,priv->nofRxBytesReceived); } if (status) { dev_dbg(&port->dev,"%s(): nonzero urb status: 0x%d", __func__, status); } if (priv->read_running == USBRSA_READ_RUNNING) { //dev_dbg(&port->dev,"%s(): usb_serial_port_softint", __func__); usb_serial_port_softint(port); } else { dev_dbg(&port->dev,"%s(): wake_up", __func__); wake_up(&priv->wait_flag); } return; } -- 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