Hi, Here's a patch against 2.4.15-pre7 that fixes a number of problems in the io_edgeport usb serial driver.
thanks, greg k-h diff --minimal -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c --- a/drivers/usb/serial/io_edgeport.c Mon Nov 19 20:55:21 2001 +++ b/drivers/usb/serial/io_edgeport.c Mon Nov 19 20:55:21 2001 @@ -25,6 +25,14 @@ * * Version history: * + * 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. * @@ -263,7 +271,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.1" +#define DRIVER_VERSION "v2.2" #define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]> and David Iacovelli" #define DRIVER_DESC "Edgeport USB Serial Driver" @@ -433,7 +441,7 @@ /* function prototypes for all URB callbacks */ static void edge_interrupt_callback (struct urb *urb); -static void edge_bulk_in_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); @@ -646,12 +654,6 @@ } #endif - - -/************************************************************************ - * * - * * - ************************************************************************/ static void get_product_info(struct edgeport_serial *edge_serial) { struct edgeport_product_info *product_info = &edge_serial->product_info; @@ -933,7 +935,7 @@ dbg(__FUNCTION__" - FREE URB %p (outstanding %d)", urb, CmdUrbs); - /* if this urb had a transfer buffer already (old transfer) free it */ + /* clean up the transfer buffer */ if (urb->transfer_buffer != NULL) { kfree(urb->transfer_buffer); } @@ -957,7 +959,6 @@ /* tell the tty driver that something has changed */ wake_up_interruptible(&tty->write_wait); - /* we have completed the command */ edge_port->commandPending = FALSE; wake_up_interruptible(&edge_port->wait_command); @@ -987,6 +988,9 @@ dbg(__FUNCTION__ " - port %d", port->number); + if (edge_port == NULL) + return -ENODEV; + ++port->open_count; MOD_INC_USE_COUNT; @@ -1002,6 +1006,12 @@ as the structures were not set up at that time.) */ serial = port->serial; edge_serial = (struct edgeport_serial *)serial->private; + if (edge_serial == NULL) { + port->active = 0; + port->open_count = 0; + MOD_DEC_USE_COUNT; + return -ENODEV; + } if (edge_serial->interrupt_in_buffer == NULL) { struct usb_serial_port *port0 = &serial->port[0]; @@ -1015,27 +1025,22 @@ edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress; /* set up our interrupt urb */ - /* Like to use FILL_INT_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */ - edge_serial->interrupt_read_urb->complete = edge_interrupt_callback; - edge_serial->interrupt_read_urb->context = edge_serial; - edge_serial->interrupt_read_urb->dev = serial->dev; - /* FILL_INT_URB(edge_serial->interrupt_read_urb, serial->dev, - usb_rcvintpipe (serial->dev, edge_serial->interrupt_in_endpoint), - edge_serial->interrupt_in_buffer, edge_serial->interrupt_in_endpoint.wMaxPacketSize, - edge_interrupt_callback, edge_serial, edge_serial->interrupt_in_endpoint.bInterval); - */ + FILL_INT_URB(edge_serial->interrupt_read_urb, + serial->dev, + usb_rcvintpipe(serial->dev, + +port0->interrupt_in_endpointAddress), + port0->interrupt_in_buffer, + +edge_serial->interrupt_read_urb->transfer_buffer_length, + edge_interrupt_callback, edge_serial, + edge_serial->interrupt_read_urb->interval); /* set up our bulk in urb */ - /* Like to use FILL_BULK_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */ - edge_serial->read_urb->complete = edge_bulk_in_callback; - edge_serial->read_urb->context = edge_serial; - edge_serial->read_urb->dev = serial->dev; - /* FILL_BULK_URB(edge_serial->read_urb, serial->dev, - usb_rcvbulkpipe (serial->dev, port->bulk_in_endpointAddress), - edge_serial->bulk_in_buffer, edge_serial->bulk_in_endpoint->wMaxPacketSize, + FILL_BULK_URB(edge_serial->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, +port0->bulk_in_endpointAddress), + port0->bulk_in_buffer, + edge_serial->read_urb->transfer_buffer_length, edge_bulk_in_callback, edge_serial); - */ - + /* start interrupt read for this edgeport * this interrupt will continue as long as the edgeport is connected */ response = usb_submit_urb (edge_serial->interrupt_read_urb); @@ -1239,7 +1244,9 @@ edge_serial = (struct edgeport_serial *)serial->private; edge_port = (struct edgeport_port *)port->private; - + if ((edge_serial == NULL) || (edge_port == NULL)) + return; + --port->open_count; if (port->open_count <= 0) { @@ -1285,15 +1292,14 @@ if (edge_port->txfifo.fifo) { kfree(edge_port->txfifo.fifo); } + port->active = 0; + port->open_count = 0; } MOD_DEC_USE_COUNT; dbg(__FUNCTION__" exited"); } - - - /***************************************************************************** * SerialWrite * this function is called by the tty driver when data should be written to @@ -1312,6 +1318,9 @@ dbg(__FUNCTION__ " - port %d", port->number); + if (edge_port == NULL) + return -ENODEV; + // get a pointer to the Tx fifo fifo = &edge_port->txfifo; @@ -1509,9 +1518,10 @@ dbg(__FUNCTION__); - if (edge_port->closePending == TRUE) { + if (edge_port == NULL) + return -ENODEV; + if (edge_port->closePending == TRUE) return -ENODEV; - } dbg(__FUNCTION__" - port %d", port->number); @@ -1544,6 +1554,11 @@ dbg(__FUNCTION__); + if (edge_port == NULL) + return -ENODEV; + if (edge_port->closePending == TRUE) + return -ENODEV; + if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return -EINVAL; @@ -1571,6 +1586,9 @@ dbg(__FUNCTION__" - port %d", port->number); + if (edge_port == NULL) + return; + if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return; @@ -1613,6 +1631,9 @@ dbg(__FUNCTION__" - port %d", port->number); + if (edge_port == NULL) + return; + if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return; @@ -1670,6 +1691,9 @@ dbg(__FUNCTION__" - port %d", port->number); + if (edge_port == NULL) + return; + if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return; @@ -2457,15 +2481,12 @@ /* Allocate our next urb */ urb = usb_alloc_urb (0); + if (!urb) + return -ENOMEM; CmdUrbs++; - dbg(__FUNCTION__" - ALLOCATE URB %p (outstanding %d)", urb, CmdUrbs); - if (!urb) { - return -ENOMEM; - } - FILL_BULK_URB (urb, edge_serial->serial->dev, usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint), buffer, length, edge_bulk_out_cmd_callback, edge_port); @@ -2474,17 +2495,11 @@ urb->transfer_flags |= USB_QUEUE_BULK; edge_port->commandPending = TRUE; - urb->dev = edge_serial->serial->dev; status = usb_submit_urb(urb); if (status) { /* something went wrong */ dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed"); - - /* if this urb had a transfer buffer already (old transfer) free it */ - if (urb->transfer_buffer != NULL) { - kfree(urb->transfer_buffer); - } usb_unlink_urb (urb); usb_free_urb (urb); return status; @@ -2548,6 +2563,10 @@ MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR); status = write_cmd_usb(edge_port, cmdBuffer, cmdLen ); + if (status) { + /* something bad happened, let's free up the memory */ + kfree (cmdBuffer); + } return status; } @@ -2623,6 +2642,10 @@ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->number, regNum, regValue); status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); + if (status) { + /* something bad happened, let's free up the memory */ + kfree (cmdBuffer); + } return status; } @@ -2707,10 +2730,8 @@ unsigned char stop_char = STOP_CHAR(tty); unsigned char start_char = START_CHAR(tty); - { - send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char); - send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); - } + send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char); + send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); /* if we are implementing INBOUND XON/XOFF */ if (I_IXOFF(tty)) { @@ -2962,10 +2983,11 @@ get_product_info(edge_serial); /* set the number of ports from the manufacturing description */ - // FIXME should we override this??? - //serial->num_ports = serial->product_info.NumPorts; + /* serial->num_ports = serial->product_info.NumPorts; */ if (edge_serial->product_info.NumPorts != serial->num_ports) { - warn(__FUNCTION__ " - Device Reported %d serial ports vs core thinking we have %d ports, email [EMAIL PROTECTED] this info.", edge_serial->product_info.NumPorts, serial->num_ports); + warn(__FUNCTION__ " - Device Reported %d serial ports vs core " + "thinking we have %d ports, email [EMAIL PROTECTED] this info.", + edge_serial->product_info.NumPorts, serial->num_ports); } dbg(__FUNCTION__ " - time 1 %ld", jiffies); @@ -3005,10 +3027,9 @@ /**************************************************************************** - * usb_edgeport_disconnect + * edge_shutdown * This function is called whenever the device is removed from the usb bus. ****************************************************************************/ -//static void usb_edgeport_disconnect (struct usb_device *dev, void *ptr) static void edge_shutdown (struct usb_serial *serial) { int i; @@ -3020,11 +3041,11 @@ while (serial->port[i].open_count > 0) { edge_close (&serial->port[i], NULL); } + kfree (serial->port[i].private); + serial->port[i].private = NULL; } - - /* free up any memory that we allocated */ - // FIXME - + kfree (serial->private); + serial->private = NULL; } _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel