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