This patch updates the io_edgeport driver.

diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c  Thu Jan  3 21:41:53 2002
+++ b/drivers/usb/serial/io_edgeport.c  Thu Jan  3 21:41:53 2002
@@ -25,6 +25,17 @@
  *
  * 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.
+ *
  *     (04/08/2001) gb
  *     - Identify version on module load.
  *
@@ -260,7 +271,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.0.0"
+#define DRIVER_VERSION "v2.2"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
@@ -307,11 +318,6 @@
 };
 
 
-/* the info for all of the devices that this driver supports */
-int EdgeportDevices[] = EDGEPORT_DEVICE_IDS;
-#define NUM_EDGEPORT_DEVICES (sizeof(EdgeportDevices) / sizeof(int))
-
-
 /* Transmit Fifo 
  * This Transmit queue is an extension of the edgeport Rx buffer. 
  * The maximum amount of data buffered in both the edgeport 
@@ -430,7 +436,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);
 
@@ -475,7 +481,6 @@
 
 static void unicode_to_ascii           (char *string, short *unicode, int 
unicode_size);
 
-static int  get_string_desc            (struct usb_device *dev, int Id, struct 
usb_string_descriptor **pRetDesc);
 
 
 
@@ -485,17 +490,15 @@
 // ************************************************************************
 // ************************************************************************
 
-// These functions should be in firmware.c
-
 /************************************************************************
  *                                                                     *
- *     update_edgeport_E2PROM()        Compare current versions of             *
+ * update_edgeport_E2PROM()    Compare current versions of             *
  *                             Boot ROM and Manufacture                *
  *                             Descriptors with versions               *
  *                             embedded in this driver                 *
  *                                                                     *
  ************************************************************************/
-void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
 {
        __u32 BootCurVer;
        __u32 BootNewVer;
@@ -611,6 +614,7 @@
 }
 
 
+#if 0
 /************************************************************************
  *
  *  Get string descriptor from device
@@ -641,14 +645,8 @@
        *pRetDesc = pStringDesc;
        return 0;
 }
+#endif
 
-
-
-
-/************************************************************************
- *                                                                                    
                                                         *
- *                                                                                    
                                                         *
- ************************************************************************/
 static void get_product_info(struct edgeport_serial *edge_serial)
 {
        struct edgeport_product_info *product_info = &edge_serial->product_info;
@@ -930,7 +928,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);
        }
@@ -944,7 +942,7 @@
        }
 
        if (status) {
-               dbg(__FUNCTION__" - nonzero write bulk status received: %d", 
urb->status);
+               dbg(__FUNCTION__" - nonzero write bulk status received: %d", status);
                return;
        }
 
@@ -954,7 +952,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);
@@ -984,6 +981,9 @@
        
        dbg(__FUNCTION__ " - port %d", port->number);
 
+       if (edge_port == NULL)
+               return -ENODEV;
+
        ++port->open_count;
        MOD_INC_USE_COUNT;
        
@@ -999,6 +999,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];
                        
@@ -1012,25 +1018,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;
-                       /* 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;
-                       /* FILL_BULK_URB(edge_serial->read_urb, serial->dev, 
-                                     usb_rcvbulkpipe (serial->dev, 
edge_serial->bulk_in_endpoint),
-                                     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);
@@ -1234,58 +1237,62 @@
        
        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) {
-               // block until tx is empty
-               block_until_tx_empty(edge_port);
-       
-               edge_port->closePending = TRUE;
-       
-               /* flush and chase */
-               edge_port->chaseResponsePending = TRUE;
-       
-               dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
-               status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
-               if (status == 0) {
-                       // block until chase finished
-                       block_until_chase_response(edge_port);
-               } else {
-                       edge_port->chaseResponsePending = FALSE;
+               if (serial->dev) {
+                       // block until tx is empty
+                       block_until_tx_empty(edge_port);
+
+                       edge_port->closePending = TRUE;
+
+                       /* flush and chase */
+                       edge_port->chaseResponsePending = TRUE;
+
+                       dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
+                       status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+                       if (status == 0) {
+                               // block until chase finished
+                               block_until_chase_response(edge_port);
+                       } else {
+                               edge_port->chaseResponsePending = FALSE;
+                       }
+
+                       /* close the port */
+                       dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
+                       send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+
+                       //port->close = TRUE;
+                       edge_port->closePending = FALSE;
+                       edge_port->open = FALSE;
+                       edge_port->openPending = FALSE;
+
+                       if (edge_port->write_urb) {
+                               usb_unlink_urb (edge_port->write_urb);
+                       }
                }
        
-               /* close the port */
-               dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
-               send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
-       
-               //port->close = TRUE;
-               edge_port->closePending = FALSE;
-               edge_port->open = FALSE;
-               edge_port->openPending = FALSE;
-       
                if (edge_port->write_urb) {
                        /* if this urb had a transfer buffer already (old transfer) 
free it */
                        if (edge_port->write_urb->transfer_buffer != NULL) {
                                kfree(edge_port->write_urb->transfer_buffer);
                        }
-       
-                       usb_unlink_urb (edge_port->write_urb);
                        usb_free_urb   (edge_port->write_urb);
                }
-       
                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
@@ -1304,6 +1311,9 @@
 
        dbg(__FUNCTION__ " - port %d", port->number);
 
+       if (edge_port == NULL)
+               return -ENODEV;
+
        // get a pointer to the Tx fifo
        fifo = &edge_port->txfifo;
 
@@ -1331,7 +1341,8 @@
 
        /* now copy our data */
        if (from_user) {
-               copy_from_user(&fifo->fifo[fifo->head], data, firsthalf);
+               if (copy_from_user(&fifo->fifo[fifo->head], data, firsthalf))
+                       return -EFAULT;
        } else {
                memcpy(&fifo->fifo[fifo->head], data, firsthalf);
        }  
@@ -1350,7 +1361,8 @@
        if (secondhalf) {
                dbg (__FUNCTION__" - copy rest of data %d", secondhalf);
                if (from_user) {
-                       copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], 
secondhalf);
+                       if (copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], 
+secondhalf))
+                               return -EFAULT;
                } else {
                        memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
                }
@@ -1391,7 +1403,6 @@
        struct urb      *urb;
        unsigned char   *buffer;
        int             status;
-       unsigned long   flags;
        int             count;
        int             bytesleft;
        int             firsthalf;
@@ -1399,13 +1410,9 @@
 
        dbg(__FUNCTION__"(%d)", edge_port->port->number);
 
-       /* find our next free urb */    // ICK!!! FIXME!!!
-       save_flags(flags); cli();
-
        if (edge_port->write_in_progress ||
            !edge_port->open             ||
            (fifo->count == 0)) {
-               restore_flags(flags);
                dbg(__FUNCTION__"(%d) EXIT - fifo %d, PendingWrite = %d", 
edge_port->port->number, fifo->count, edge_port->write_in_progress);
                return;
        }
@@ -1418,14 +1425,12 @@
        //      it's better to wait for more credits so we can do a larger
        //      write.
        if (edge_port->txCredits < 
EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) {
-               restore_flags(flags);
                dbg(__FUNCTION__"(%d) Not enough credit - fifo %d TxCredit %d", 
edge_port->port->number, fifo->count, edge_port->txCredits );
                return;
        }
 
        // lock this write
        edge_port->write_in_progress = TRUE;
-       restore_flags(flags);
 
        // get a pointer to the write_urb
        urb = edge_port->write_urb;
@@ -1506,9 +1511,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);
 
@@ -1541,6 +1547,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;
@@ -1568,6 +1579,9 @@
 
        dbg(__FUNCTION__" - port %d", port->number);
 
+       if (edge_port == NULL)
+               return;
+
        if (!edge_port->open) {
                dbg (__FUNCTION__" - port not opened");
                return;
@@ -1610,6 +1624,9 @@
 
        dbg(__FUNCTION__" - port %d", port->number);
 
+       if (edge_port == NULL)
+               return;
+
        if (!edge_port->open) {
                dbg (__FUNCTION__" - port not opened");
                return;
@@ -1667,6 +1684,9 @@
 
        dbg(__FUNCTION__" - port %d", port->number);
 
+       if (edge_port == NULL)
+               return;
+
        if (!edge_port->open) {
                dbg (__FUNCTION__" - port not opened");
                return;
@@ -1718,7 +1738,7 @@
        return -ENOIOCTLCMD;
 }
 
-static int set_modem_info(struct edgeport_port *edge_port, unsigned int *value)
+static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, unsigned 
+int *value)
 {
        unsigned int mcr = edge_port->shadowMCR;
        unsigned int arg;
@@ -1726,11 +1746,29 @@
        if (copy_from_user(&arg, value, sizeof(int)))
                return -EFAULT;
 
-       // turn off the RTS and DTR
-       mcr &=  ~(MCR_RTS | MCR_DTR);
+       switch (cmd) {
+               case TIOCMBIS:
+                       if (arg & TIOCM_RTS)
+                               mcr |= MCR_RTS;
+                       if (arg & TIOCM_DTR)
+                               mcr |= MCR_RTS;
+                       break;
 
-       mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
-       mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+               case TIOCMBIC:
+                       if (arg & TIOCM_RTS)
+                               mcr &= ~MCR_RTS;
+                       if (arg & TIOCM_DTR)
+                               mcr &= ~MCR_RTS;
+                       break;
+
+               case TIOCMSET:
+                       /* turn off the RTS and DTR and LOOPBACK 
+                        * and then only turn on what was asked to */
+                       mcr &=  ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
+                       mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+                       mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+                       break;
+       }
 
        edge_port->shadowMCR = mcr;
 
@@ -1802,7 +1840,6 @@
        struct async_icount cnow;
        struct async_icount cprev;
        struct serial_icounter_struct icount;
-       unsigned long flags;
 
 
        dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd);
@@ -1814,22 +1851,16 @@
                        return get_number_bytes_avail(edge_port, (unsigned int *) arg);
                        break;
 
-//             case TCGETS:            
-//                     dbg(__FUNCTION__" (%d) TCGETS",  port->number);
-//                     break;
-
-//             case TCSETS:            
-//                     dbg(__FUNCTION__" (%d) TCSETS",  port->number);
-//                     break;
-
                case TIOCSERGETLSR:
                        dbg(__FUNCTION__" (%d) TIOCSERGETLSR",  port->number);
                        return get_lsr_info(edge_port, (unsigned int *) arg);
                        return 0;
 
-               case TIOCMSET:  
-                       dbg(__FUNCTION__" (%d) TIOCMSET",  port->number);
-                       return set_modem_info(edge_port, (unsigned int *) arg);
+               case TIOCMBIS:
+               case TIOCMBIC:
+               case TIOCMSET:
+                       dbg(__FUNCTION__" (%d) TIOCMSET/TIOCMBIC/TIOCMSET",  
+port->number);
+                       return set_modem_info(edge_port, cmd, (unsigned int *) arg);
 
                case TIOCMGET:  
                        dbg(__FUNCTION__" (%d) TIOCMGET",  port->number);
@@ -1845,17 +1876,13 @@
 
                case TIOCMIWAIT:
                        dbg(__FUNCTION__" (%d) TIOCMIWAIT",  port->number);
-                       save_flags(flags); cli();
                        cprev = edge_port->icount;
-                       restore_flags(flags);
                        while (1) {
                                interruptible_sleep_on(&edge_port->delta_msr_wait);
                                /* see if a signal did it */
                                if (signal_pending(current))
                                        return -ERESTARTSYS;
-                               save_flags(flags); cli();
-                               cnow = edge_port->icount; /* atomic copy */
-                               restore_flags(flags);
+                               cnow = edge_port->icount;
                                if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                                    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
                                        return -EIO; /* no change => error */
@@ -1871,9 +1898,7 @@
                        break;
 
                case TIOCGICOUNT:
-                       save_flags(flags); cli();
                        cnow = edge_port->icount;
-                       restore_flags(flags);
                        icount.cts = cnow.cts;
                        icount.dsr = cnow.dsr;
                        icount.rng = cnow.rng;
@@ -2444,15 +2469,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);
@@ -2461,17 +2483,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;
@@ -2535,6 +2551,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;
 }
@@ -2610,6 +2630,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;
 }
@@ -2694,10 +2718,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)) {
@@ -2949,10 +2971,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);
@@ -2992,10 +3015,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;
@@ -3007,11 +3029,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;
 }
 
 
@@ -3037,7 +3059,7 @@
        usb_serial_register (&edgeport_16dual_device);
        usb_serial_register (&edgeport_compat_id_device);
        usb_serial_register (&edgeport_8i_device);
-       info(DRIVER_VERSION ":" DRIVER_DESC);
+       info(DRIVER_DESC " " DRIVER_VERSION);
        return 0;
 }
 


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to