summaryrefslogtreecommitdiff
path: root/packages/linux/linux-mtx-2-2.4.27/45-acm-tty.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-mtx-2-2.4.27/45-acm-tty.patch')
-rw-r--r--packages/linux/linux-mtx-2-2.4.27/45-acm-tty.patch252
1 files changed, 0 insertions, 252 deletions
diff --git a/packages/linux/linux-mtx-2-2.4.27/45-acm-tty.patch b/packages/linux/linux-mtx-2-2.4.27/45-acm-tty.patch
deleted file mode 100644
index 028d10ad9a..0000000000
--- a/packages/linux/linux-mtx-2-2.4.27/45-acm-tty.patch
+++ /dev/null
@@ -1,252 +0,0 @@
---- linux/drivers/usb/acm.c~45-acm-tty.patch 2006-06-07 11:21:21.648422000 +0200
-+++ linux/drivers/usb/acm.c 2006-06-09 17:20:51.735793750 +0200
-@@ -139,6 +139,8 @@
- * Internal driver structures.
- */
-
-+#define TD_SIZE 16384
-+
- struct acm {
- struct usb_device *dev; /* the coresponding usb device */
- struct usb_interface *iface; /* the interfaces - +0 control +1 data */
-@@ -153,6 +155,11 @@
- unsigned int minor; /* acm minor number */
- unsigned char throttle; /* throttled by tty layer */
- unsigned char clocal; /* termios CLOCAL */
-+ unsigned long throttle_start;
-+ unsigned char resubmit_to_unthrottle; /* Leftover data from last operation */
-+ unsigned char *throttle_data;
-+ int td_len;
-+ int td_busy;
- };
-
- /* global params controlling max sizes for read, write, control */
-@@ -166,6 +173,96 @@
-
- #define ACM_READY(acm) (acm && acm->dev && acm->used)
-
-+
-+/*
-+ * Helper functions to optimize throttleing
-+ */
-+static int
-+acm_fill_tty(struct urb *urb, struct tty_struct *tty, unsigned char *data, int length)
-+{
-+ struct acm *acm = urb->context;
-+ int n = 0;
-+ /*printk("acm_fill_tty: %d bytes\n", length);*/
-+ if (!urb->status && !acm->throttle) {
-+ for (n = 0; n < length && !acm->throttle; n++) {
-+ /* if we insert more than TTY_FLIPBUF_SIZE characters,
-+ * we drop them. */
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ tty_flip_buffer_push(tty);
-+ }
-+ tty_insert_flip_char(tty, data[n], 0);
-+ }
-+ tty_flip_buffer_push(tty);
-+ }
-+ /*printk("copied %d bytes.\n", n);*/
-+ return n;
-+}
-+
-+static int
-+acm_shift_if_throttle(unsigned char *data, int *length, int shift_by)
-+{
-+ if (shift_by < *length) {
-+ dbg("need to shift uncopied %d bytes to front.", *length - shift_by);
-+ memmove(data, data + shift_by, *length - shift_by);
-+ *length -= shift_by;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int
-+acm_buffer_if_thottle(struct acm *acm, unsigned char *data, int start, int *length)
-+{
-+ int copied = *length;
-+ if (start < *length) {
-+ int space = TD_SIZE - acm->td_len;
-+ int needed = *length - start;
-+ copied = (space < needed)? space: needed;
-+ dbg("need to push %d to throttle buffer, can copy %d.",
-+ needed, copied);
-+ memcpy(acm->throttle_data + acm->td_len, data, copied);
-+ acm->td_len += copied;
-+ *length -= copied;
-+ }
-+ return copied;
-+}
-+
-+static int
-+acm_empty_throttle(struct urb *urb, struct tty_struct *tty)
-+{
-+ unsigned long flags;
-+ struct acm *acm = urb->context;
-+
-+ save_flags(flags);
-+ cli();
-+
-+ if (acm->td_busy) {
-+ restore_flags(flags);
-+ return 0;
-+ }
-+ acm->td_busy = 1;
-+ restore_flags(flags);
-+
-+ if (acm->td_len > 0) {
-+
-+ dbg("acm_empty_throttle: trying to empty throttle buffer: %d bytes.",
-+ acm->td_len);
-+
-+ /* if there has been something left from previous operations
-+ * we try to complete this before looking at the urb */
-+ int copied = acm_fill_tty(urb, tty, acm->throttle_data, acm->td_len);
-+ if (acm_shift_if_throttle(acm->throttle_data, &acm->td_len, copied)) {
-+ /* we were unable to empty the throttle data, so we can't
-+ * copy anything more now */
-+ acm->td_busy = 0;
-+ return 0;
-+ }
-+ acm->td_len = 0;
-+ }
-+ acm->td_busy = 0;
-+ return 1;
-+}
-+
- /*
- * Functions for ACM control messages.
- */
-@@ -238,36 +335,40 @@
- struct acm *acm = urb->context;
- struct tty_struct *tty = acm->tty;
- unsigned char *data = urb->transfer_buffer;
-- int i = 0;
-+ int copied = 0;
-+ int buffered = 0;
-
- if (!ACM_READY(acm)) return;
-
-- if (urb->status)
-+ if (urb->status) {
- dbg("nonzero read bulk status received: %d", urb->status);
-+ }
-
-- if (!urb->status && !acm->throttle) {
-- for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
-- /* if we insert more than TTY_FLIPBUF_SIZE characters,
-- * we drop them. */
-- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-- tty_flip_buffer_push(tty);
-- }
-- tty_insert_flip_char(tty, data[i], 0);
-- }
-- tty_flip_buffer_push(tty);
-+ dbg("acm_read_bulk, calling acm_empty_throttle()");
-+ if (!acm_empty_throttle(urb, tty)) {
-+ dbg("could not empty throttle buffer, entering throttle state, acm->td_busy: %d.", acm->td_busy);
- }
-
-+ /* got here, either there was nothing in the throttle data or it could
-+ * all be copied without throttleing again */
-+ copied = acm_fill_tty(urb, tty, data, urb->actual_length);
- if (acm->throttle) {
-- memmove(data, data + i, urb->actual_length - i);
-- urb->actual_length -= i;
-- return;
-+ int length = urb->actual_length;
-+ buffered = acm_buffer_if_thottle(acm, data, copied, &urb->actual_length);
-+ if (buffered < length - copied
-+ && acm_shift_if_throttle(data, &urb->actual_length, copied + buffered)) {
-+ printk("need to resubmit to unthrottle\n");
-+ acm->resubmit_to_unthrottle = 1;
-+ return;
-+ }
- }
-
- urb->actual_length = 0;
- urb->dev = acm->dev;
-
-- if (usb_submit_urb(urb))
-+ if (usb_submit_urb(urb)) {
- dbg("failed resubmitting read urb");
-+ }
- }
-
- static void acm_write_bulk(struct urb *urb)
-@@ -330,7 +431,12 @@
-
- acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
-
-- /* force low_latency on so that our tty_push actually forces the data through,
-+ acm->resubmit_to_unthrottle = 0;
-+ acm->td_len = 0;
-+ acm->td_busy = 0;
-+ acm->throttle_data = kmalloc(TD_SIZE * sizeof (*acm->throttle_data), GFP_KERNEL);
-+
-+ /* force low_latency on so that our tty_push actually forces the data through,
- otherwise it is scheduled, and with high data rates data can get lost. */
- tty->low_latency = 1;
-
-@@ -352,6 +458,7 @@
- } else {
- tty_unregister_devfs(&acm_tty_driver, acm->minor);
- acm_table[acm->minor] = NULL;
-+ kfree(acm->throttle_data);
- kfree(acm);
- }
- }
-@@ -363,8 +470,16 @@
- struct acm *acm = tty->driver_data;
-
- if (!ACM_READY(acm)) return -EINVAL;
-- if (acm->writeurb.status == -EINPROGRESS) return 0;
-- if (!count) return 0;
-+
-+ if (acm->writeurb.status == -EINPROGRESS) {
-+ dbg("tty_write in progress");
-+ return 0;
-+ }
-+
-+ if (!count) {
-+ dbg("tty_write: nothing to write");
-+ return 0;
-+ }
-
- count = (count > acm->writesize) ? acm->writesize : count;
-
-@@ -401,16 +516,32 @@
- {
- struct acm *acm = tty->driver_data;
- if (!ACM_READY(acm)) return;
-+ dbg("acm_tty_throttle ON %ld ---> %ld", jiffies-acm->throttle_start, jiffies);
- acm->throttle = 1;
-+ acm->throttle_start = jiffies;
- }
-
- static void acm_tty_unthrottle(struct tty_struct *tty)
- {
- struct acm *acm = tty->driver_data;
- if (!ACM_READY(acm)) return;
-+ dbg("acm_tty_throttle OFF %ld ---> %ld", jiffies, jiffies-acm->throttle_start);
- acm->throttle = 0;
-- if (acm->readurb.status != -EINPROGRESS)
-+
-+ dbg("acm_tty_unthrottle, calling acm_empty_throttle()");
-+ if (!acm_empty_throttle(&acm->readurb, tty)) {
-+ if (acm->td_busy) {
-+ printk("***** pending acm_empty_throttle!\n");
-+ } else {
-+ dbg("throttle not emptied.\n");
-+ }
-+ }
-+
-+ if (acm->resubmit_to_unthrottle != 0) {
-+ dbg("resubmit_to_unthrottle: acm_read_bulk");
-+ acm->resubmit_to_unthrottle = 0;
- acm_read_bulk(&acm->readurb);
-+ }
- }
-
- static void acm_tty_break_ctl(struct tty_struct *tty, int state)