Hi,

Here's a patch against 2.4.15-pre5 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  Fri Nov 16 14:47:16 2001
+++ b/drivers/usb/serial/io_edgeport.c  Fri Nov 16 14:47:16 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

Reply via email to