Here is an updated patch that should work.  It is similar to the
previous patch except for a one line mistake correction from my
previous post.

--Sam

---------------------------------
Sam King
Ph.D. Student
Computer Science Department
University of Michigan, Ann Arbor

--- /usr/src/linux-2.4/drivers/usb/serial/usbserial.c   2004-08-18 20:30:12.000000000 
-0400
+++ usbserial.c 2004-09-14 14:16:51.000000000 -0400
@@ -351,13 +351,17 @@
 /*
  * The post kludge structures and variables.
  */
-#define POST_BSIZE     100     /* little below 128 in total */
+#define POST_JOB_WRITE    0
+#define POST_JOB_THROTTLE 1
+#define POST_BSIZE       100   /* little below 128 in total */
 struct usb_serial_post_job {
        struct list_head link;
+        int type;
        struct usb_serial_port *port;
        int len;
        char buff[POST_BSIZE];
 };
+
 static spinlock_t post_lock = SPIN_LOCK_UNLOCKED;      /* Also covers ->ref */
 static struct list_head post_list = LIST_HEAD_INIT(post_list);
 static struct tq_struct post_task;
@@ -368,11 +372,12 @@
 static int __serial_write (struct usb_serial_port *port, int from_user, const 
unsigned char *buf, int count);
 static int  serial_write (struct tty_struct * tty, int from_user, const unsigned char 
*buf, int count);
 static int  serial_post_job(struct usb_serial_port *port, int from_user,
-    int gfp, const unsigned char *buf, int count);
+    int gfp, const unsigned char *buf, int count,int type);
 static int  serial_post_one(struct usb_serial_port *port, int from_user,
-    int gfp, const unsigned char *buf, int count);
+    int gfp, const unsigned char *buf, int count, int type);
 static int  serial_write_room (struct tty_struct *tty);
 static int  serial_chars_in_buffer (struct tty_struct *tty);
+static void __serial_throttle (struct tty_struct * tty);
 static void serial_throttle (struct tty_struct * tty);
 static void serial_unthrottle (struct tty_struct * tty);
 static int  serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int 
cmd, unsigned long arg);
@@ -498,19 +503,26 @@
                port = job->port;
                /* get_usb_serial checks port->tty, so cannot be used */
                serial = port->serial;
-               if (port->write_busy) {
-                       dbg("%s - port %d busy", __FUNCTION__, port->number);
-                       pos = pos->next;
-                       continue;
-               }
+               if(job->type == POST_JOB_WRITE) {
+                       if (port->write_busy) {
+                               dbg("%s - port %d busy", __FUNCTION__, port->number);
+                               pos = pos->next;
+                               continue;
+                       }
+               }
                list_del(&job->link);
                spin_unlock_irqrestore(&post_lock, flags);

                down(&port->sem);
-               dbg("%s - port %d len %d backlog %d", __FUNCTION__,
-                   port->number, job->len, port->write_backlog);
-               if (port->tty != NULL)
-                       __serial_write(port, 0, job->buff, job->len);
+               if(job->type == POST_JOB_WRITE) {
+                       dbg("%s - port %d len %d backlog %d", __FUNCTION__,
+                           port->number, job->len, port->write_backlog);
+                       if (port->tty != NULL)
+                               __serial_write(port, 0, job->buff, job->len);
+               } else if(job->type == POST_JOB_THROTTLE) {
+                       if(port->tty != NULL)
+                               __serial_throttle(port->tty);
+               }
                up(&port->sem);

                spin_lock_irqsave(&post_lock, flags);
@@ -719,7 +731,7 @@
                if (port->write_busy) {
                        up(&port->sem);
                        return serial_post_job(port, from_user, GFP_KERNEL,
-                           buf, count);
+                           buf, count, POST_JOB_WRITE);
                }

                rc = __serial_write(port, from_user, buf, count);
@@ -737,11 +749,11 @@
                return -EINVAL;
        }

-       return serial_post_job(port, 0, GFP_ATOMIC, buf, count);
+       return serial_post_job(port, 0, GFP_ATOMIC, buf, count, POST_JOB_WRITE);
 }

 static int serial_post_job(struct usb_serial_port *port, int from_user,
-    int gfp, const unsigned char *buf, int count)
+    int gfp, const unsigned char *buf, int count, int type)
 {
        int done = 0, length;
        int rc;
@@ -764,27 +776,35 @@
                count = 512;
        }

-       while (done < count) {
-               length = count - done;
-               if (length > POST_BSIZE)
-                       length = POST_BSIZE;
-               if (length > port->bulk_out_size)
-                       length = port->bulk_out_size;
-
-               rc = serial_post_one(port, from_user, gfp, buf + done, length);
-               if (rc <= 0) {
-                       if (done != 0)
-                               return done;
-                       return rc;
+       if(type == POST_JOB_WRITE) {
+               while (done < count) {
+                       length = count - done;
+                       if (length > POST_BSIZE)
+                               length = POST_BSIZE;
+                       if (length > port->bulk_out_size)
+                               length = port->bulk_out_size;
+
+                       rc = serial_post_one(port, from_user, gfp,
+                                            buf + done, length,
+                                            type);
+                       if (rc <= 0) {
+                               if (done != 0)
+                                       return done;
+                               return rc;
+                       }
+                       done += rc;
                }
-               done += rc;
+       } else if(type == POST_JOB_THROTTLE) {
+               serial_post_one(port, from_user, gfp, buf, count, type);
+       } else {
+               BUG();
        }

        return done;
 }

 static int serial_post_one(struct usb_serial_port *port, int from_user,
-    int gfp, const unsigned char *buf, int count)
+    int gfp, const unsigned char *buf, int count, int type)
 {
        struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
        struct usb_serial_post_job *job;
@@ -800,14 +820,17 @@
        if (count >= POST_BSIZE)
                count = POST_BSIZE;
        job->len = count;
+       job->type = type;

-       if (from_user) {
-               if (copy_from_user(job->buff, buf, count)) {
-                       kfree(job);
-                       return -EFAULT;
+       if(type == POST_JOB_WRITE) {
+               if (from_user) {
+                       if (copy_from_user(job->buff, buf, count)) {
+                               kfree(job);
+                               return -EFAULT;
+                       }
+               } else {
+                       memcpy(job->buff, buf, count);
                }
-       } else {
-               memcpy(job->buff, buf, count);
        }

        spin_lock_irqsave(&post_lock, flags);
@@ -884,29 +907,49 @@
        return retval;
 }

-static void serial_throttle (struct tty_struct * tty)
+static void __serial_throttle (struct tty_struct * tty)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
        struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);

        if (!serial)
                return;
-
-       down (&port->sem);
-
+
        dbg("%s - port %d", __FUNCTION__, port->number);
-
+
        if (!port->open_count) {
                dbg ("%s - port not open", __FUNCTION__);
-               goto exit;
+               return;
        }
-
+
        /* pass on to the driver specific version of this function */
        if (serial->type->throttle)
                serial->type->throttle(port);

-exit:
-       up (&port->sem);
+}
+
+static void serial_throttle (struct tty_struct * tty)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+       struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+
+       if (!serial)
+               return;
+
+       if(!in_interrupt()) {
+
+               post_helper(NULL);
+
+               down(&port->sem);
+
+               __serial_throttle(tty);
+
+               up (&port->sem);
+
+               return;
+       }
+
+       serial_post_job(port, 0, GFP_ATOMIC, NULL, 0, POST_JOB_THROTTLE);
 }

 static void serial_unthrottle (struct tty_struct * tty)


-------------------------------------------------------
This SF.Net email is sponsored by: thawte's Crypto Challenge Vl
Crack the code and win a Sony DCRHC40 MiniDV Digital Handycam
Camcorder. More prizes in the weekly Lunch Hour Challenge.
Sign up NOW http://ad.doubleclick.net/clk;10740251;10262165;m
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to