Same patch as before except Configure.help is repatched.

Could Greg/Johannes - whoever is the correct person please forward this
onto Linus/the powers that be :-)

Previous patch comment:

This is a patch against 2.4.14 which fixes the panic experienced by Tony
Battersby and includes updates to the web site location and some code
cleanups.



--
Bill Ryder
diff -rua orig/Documentation/Configure.help patched/Documentation/Configure.help
--- orig/Documentation/Configure.help   Sun Nov 11 15:25:16 2001
+++ patched/Documentation/Configure.help        Sun Nov 11 15:28:23 2001
@@ -12729,8 +12729,9 @@
 CONFIG_USB_SERIAL_FTDI_SIO
   Say Y here if you want to use a FTDI SIO single port USB to serial
   converter device. The implementation I have is called the USC-1000.
+  This driver has also be tested with the 245 and 232 devices.
 
-  See <http://reality.sgi.com/bryder_wellington/ftdi_sio> for more
+  See <http://ftdi-usb-sio.sourceforge.net> for more
   information on this driver and the device.
 
   This code is also available as a module ( = code which can be
diff -rua orig/drivers/usb/serial/ftdi_sio.c patched/drivers/usb/serial/ftdi_sio.c
--- orig/drivers/usb/serial/ftdi_sio.c  Sun Oct 21 15:13:11 2001
+++ patched/drivers/usb/serial/ftdi_sio.c       Sun Nov 11 15:26:54 2001
@@ -12,9 +12,18 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
+ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *     and extra documentation
  * 
+ * (04/Nov/2001) Bill Ryder
+ *     Fixed bug in read_bulk_callback where incorrect urb buffer was used.
+ *     cleaned up write offset calculation
+ *     added write_room since default values can be incorrect for sio
+ *     changed write_bulk_callback to use same queue_task as other drivers
+ *       (the previous version caused panics)
+ *     Removed port iteration code since the device only has one I/O port and it 
+ *       was wrong anyway.
+ * 
  * (31/May/2001) gkh
  *     switched from using spinlock to a semaphore, which fixes lots of problems.
  *
@@ -97,7 +106,6 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
-
 #ifdef CONFIG_USB_SERIAL_DEBUG
        static int debug = 1;
 #else
@@ -111,7 +119,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1.0"
+#define DRIVER_VERSION "v1.2.0"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]>, Bill Ryder 
<[EMAIL PROTECTED]>"
 #define DRIVER_DESC "USB FTDI RS232 Converters Driver"
 
@@ -146,6 +154,7 @@
 struct ftdi_private {
        ftdi_type_t ftdi_type;
        __u16 last_set_data_urb_value ; /* the last data state set - needed for doing 
a break */
+        int write_offset;
 };
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_startup           (struct usb_serial *serial);
@@ -154,6 +163,7 @@
 static int  ftdi_sio_open              (struct usb_serial_port *port, struct file 
*filp);
 static void ftdi_sio_close             (struct usb_serial_port *port, struct file 
*filp);
 static int  ftdi_sio_write             (struct usb_serial_port *port, int from_user, 
const unsigned char *buf, int count);
+static int  ftdi_sio_write_room                (struct usb_serial_port *port);
 static void ftdi_sio_write_bulk_callback (struct urb *urb);
 static void ftdi_sio_read_bulk_callback        (struct urb *urb);
 static void ftdi_sio_set_termios       (struct usb_serial_port *port, struct termios 
* old);
@@ -176,6 +186,7 @@
        open:                   ftdi_sio_open,
        close:                  ftdi_sio_close,
        write:                  ftdi_sio_write,
+       write_room:             ftdi_sio_write_room,
        read_bulk_callback:     ftdi_sio_read_bulk_callback,
        write_bulk_callback:    ftdi_sio_write_bulk_callback,
        ioctl:                  ftdi_sio_ioctl,
@@ -198,6 +209,7 @@
        open:                   ftdi_sio_open,
        close:                  ftdi_sio_close,
        write:                  ftdi_sio_write,
+       write_room:             ftdi_sio_write_room,
        read_bulk_callback:     ftdi_sio_read_bulk_callback,
        write_bulk_callback:    ftdi_sio_write_bulk_callback,
        ioctl:                  ftdi_sio_ioctl,
@@ -252,7 +264,6 @@
 {
        struct ftdi_private *priv;
        
-       init_waitqueue_head(&serial->port[0].write_wait);
        
        priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), 
GFP_KERNEL);
        if (!priv){
@@ -261,6 +272,7 @@
        }
 
        priv->ftdi_type = sio;
+       priv->write_offset = 1;
        
        return (0);
 }
@@ -270,7 +282,6 @@
 {
        struct ftdi_private *priv;
  
-       init_waitqueue_head(&serial->port[0].write_wait);
 
        priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), 
GFP_KERNEL);
        if (!priv){
@@ -279,6 +290,7 @@
        }
 
        priv->ftdi_type = F8U232AM;
+       priv->write_offset = 0;
        
        return (0);
 }
@@ -288,13 +300,14 @@
        
        dbg (__FUNCTION__);
 
-       /* Close ports if they are open */
+
+       /* stop reads and writes on all ports */
        while (serial->port[0].open_count > 0) {
-               ftdi_sio_close (&serial->port[0], NULL);
+               ftdi_sio_close (&serial->port[0], NULL);
        }
-       if (serial->port->private){
-               kfree(serial->port->private);
-               serial->port->private = NULL;
+       if (serial->port[0].private){
+               kfree(serial->port[0].private);
+               serial->port[0].private = NULL;
        }
 }
 
@@ -361,7 +374,7 @@
 
 static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_sio_close */
-       struct usb_serial *serial = port->serial;
+       struct usb_serial *serial = port->serial; /* Checked in usbserial.c */
        unsigned int c_cflag = port->tty->termios->c_cflag;
        char buf[1];
 
@@ -393,6 +406,7 @@
                        } /* Note change no line is hupcl is off */
 
                        /* shutdown our bulk reads and writes */
+                       /* ***CHECK*** behaviour when there is nothing queued */
                        usb_unlink_urb (port->write_urb);
                        usb_unlink_urb (port->read_urb);
                }
@@ -403,7 +417,6 @@
                if (!(port->tty->termios->c_cflag & CLOCAL)){
                        tty_hangup(port->tty);
                }
-               
        }
 
        up (&port->sem);
@@ -423,10 +436,10 @@
 { /* ftdi_sio_write */
        struct usb_serial *serial = port->serial;
        struct ftdi_private *priv = (struct ftdi_private *)port->private;
+       unsigned char *first_byte = port->write_urb->transfer_buffer;
+       unsigned char dbug_byte;
        int data_offset ;
-       int rc; 
        int result;
-       DECLARE_WAITQUEUE(wait, current);
        
        dbg(__FUNCTION__ " port %d, %d bytes", port->number, count);
 
@@ -435,95 +448,70 @@
                return 0;
        }
        
-       if (priv->ftdi_type == sio){
-               data_offset = 1;
-       } else {
-               data_offset = 0;
-       }
+       data_offset = priv->write_offset;
         dbg("data_offset set to %d",data_offset);
 
-       /* only do something if we have a bulk out endpoint */
-       if (serial->num_bulk_out) {
-               unsigned char *first_byte = port->write_urb->transfer_buffer;
-
-               /* Was seeing a race here, got a read callback, then write callback 
before
-                  hitting interuptible_sleep_on  - so wrapping in a wait_queue */
-
-               add_wait_queue(&port->write_wait, &wait);
-               set_current_state (TASK_INTERRUPTIBLE);
-               while (port->write_urb->status == -EINPROGRESS) {
-                       dbg(__FUNCTION__ " write in progress - retrying");
-                       if (signal_pending(current)) {
-                               set_current_state(TASK_RUNNING);
-                               remove_wait_queue(&port->write_wait, &wait);
-                               rc = -ERESTARTSYS;
-                               goto err;
-                       }
-                       schedule();
-               }               
-               remove_wait_queue(&port->write_wait, &wait);
-               set_current_state(TASK_RUNNING);
-
-               count += data_offset;
-               count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-               if (count == 0) {
-                       return 0;
-               }
+       if (port->write_urb->status == -EINPROGRESS) {
+               dbg (__FUNCTION__ " - already writing");
+               return (0);
+       }               
+
+       down(&port->sem);
+
+       count += data_offset;
+       count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
                /* Copy in the data to send */
-               if (from_user) {
-                       if (copy_from_user(port->write_urb->transfer_buffer + 
data_offset,
-                                          buf, count - data_offset ))
-                               return -EFAULT;
-               }
-               else {
-                       memcpy(port->write_urb->transfer_buffer + data_offset,
-                              buf, count - data_offset );
-               }  
-
-               first_byte = port->write_urb->transfer_buffer;
-               if (data_offset > 0){
-                       /* Write the control byte at the front of the packet*/
-                       *first_byte = 1 | ((count-data_offset) << 2) ; 
+       if (from_user) {
+               if (copy_from_user(port->write_urb->transfer_buffer + data_offset,
+                                  buf, count - data_offset )){
+                       up (&port->sem);
+                       return -EFAULT;
                }
+       } else {
+               memcpy(port->write_urb->transfer_buffer + data_offset,
+                      buf, count - data_offset );
+       }  
+
+       first_byte = port->write_urb->transfer_buffer;
+       if (data_offset > 0){
+               /* Write the control byte at the front of the packet*/
+               *first_byte = 1 | ((count-data_offset) << 2) ; 
+       }
 
-               dbg(__FUNCTION__ " Bytes: %d, First Byte: 0o%03o",count, 
first_byte[0]);
-               usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
+       dbg(__FUNCTION__ " Bytes: %d, First Byte: 0x%02x",count, first_byte[0]);
+       usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
                
-               /* send the data out the bulk port */
-               FILL_BULK_URB(port->write_urb, serial->dev, 
-                             usb_sndbulkpipe(serial->dev, 
port->bulk_out_endpointAddress),
-                             port->write_urb->transfer_buffer, count,
-                             ftdi_sio_write_bulk_callback, port);
+       /* send the data out the bulk port */
+       FILL_BULK_URB(port->write_urb, serial->dev, 
+                     usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+                     port->write_urb->transfer_buffer, count,
+                     ftdi_sio_write_bulk_callback, port);
                
-               result = usb_submit_urb(port->write_urb);
-               if (result) {
-                       err(__FUNCTION__ " - failed submitting write urb, error %d", 
result);
-                       return 0;
-               }
-
-               dbg(__FUNCTION__ " write returning: %d", count - data_offset);
-               return (count - data_offset);
+       result = usb_submit_urb(port->write_urb);
+       if (result) {
+               err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+               up (&port->sem);
+               return 0;
        }
-       
-       /* no bulk out, so return 0 bytes written */
-       return 0;
- err: /* error exit */
-       return(rc);
+       up (&port->sem);
+
+       dbg(__FUNCTION__ " write returning: %d", count - data_offset);
+       return (count - data_offset);
+
 } /* ftdi_sio_write */
 
 static void ftdi_sio_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial;
-               struct tty_struct *tty = port->tty;
 
        dbg("ftdi_sio_write_bulk_callback");
 
        if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) {
                return;
        }
-
+       
        serial = port->serial;
        if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) {
                return;
@@ -533,16 +521,29 @@
                dbg("nonzero write bulk status received: %d", urb->status);
                return;
        }
+       queue_task(&port->tqueue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
 
-       wake_up_interruptible(&port->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
-
-       wake_up_interruptible(&tty->write_wait);
-       
        return;
 } /* ftdi_sio_write_bulk_callback */
 
+
+static int ftdi_sio_write_room( struct usb_serial_port *port )
+{
+       struct ftdi_private *priv = (struct ftdi_private *)port->private;
+       int room;
+       if ( port->write_urb->status == -EINPROGRESS) {
+               /* There is a race here with the _write routines but it won't hurt */
+               room = 0;
+       } else { 
+               room = port->bulk_out_size - priv->write_offset;
+       }
+       return(room);
+
+
+} /* ftdi_sio_write_room */
+
+
 static void ftdi_sio_read_bulk_callback (struct urb *urb)
 { /* ftdi_sio_serial_buld_callback */
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -555,7 +556,7 @@
        int i;
        int result;
 
-       dbg(__FUNCTION__);
+       dbg(__FUNCTION__ " - port %d", port->number);
 
        if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
                return;
@@ -647,12 +648,12 @@
 #endif
 
        /* Continue trying to always read  */
-       FILL_BULK_URB(urb, serial->dev, 
+       FILL_BULK_URB(port->read_urb, serial->dev, 
                      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-                     urb->transfer_buffer, urb->transfer_buffer_length,
+                     port->read_urb->transfer_buffer, 
+port->read_urb->transfer_buffer_length,
                      ftdi_sio_read_bulk_callback, port);
 
-       result = usb_submit_urb(urb);
+       result = usb_submit_urb(port->read_urb);
        if (result)
                err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 

Reply via email to