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