linux-mtx 2.6.27: updates
authorMartin Dietze <di@fh-wedel.de>
Tue, 19 May 2009 13:54:14 +0000 (15:54 +0200)
committerKoen Kooi <koen@openembedded.org>
Tue, 19 May 2009 13:54:17 +0000 (15:54 +0200)
recipes/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch
recipes/linux/linux-mtx-1-2.4.27/32-usbserial-stalled-hack.diff
recipes/linux/linux-mtx-1-2.4.27/33-usbserial-bulk_in_size-4096.diff
recipes/linux/linux-mtx-1-2.4.27/43-usbserial-27-32-backport.diff [new file with mode: 0644]
recipes/linux/linux-mtx-1-2.4.27/45-acm-tty-and-sb2.patch [new file with mode: 0644]
recipes/linux/linux-mtx-1_2.4.27.bb
recipes/linux/linux-mtx-2-2.4.27/06-zboot-2.4.26.patch
recipes/linux/linux-mtx-2_2.4.27.bb

index 4e8a757..f4a8754 100644 (file)
@@ -1,6 +1,15 @@
 diff -Naru linux/arch/mips/Makefile linux.spi/arch/mips/Makefile
 --- linux/arch/mips/Makefile   2004-05-06 15:23:41.000000000 -0400
 +++ linux.spi/arch/mips/Makefile       2004-05-11 23:19:24.000000000 -0400
+@@ -17,7 +17,7 @@
+ # Select the object file format to substitute into the linker script.
+ #
+ ifdef CONFIG_CPU_LITTLE_ENDIAN
+-tool-prefix   = mipsel-linux-
++tool-prefix   = mipsel-nylon-linux-
+ ld-emul               = elf32ltsmip
+ else
+ tool-prefix   = mips-linux-
 @@ -29,6 +29,8 @@
  endif
  
index bfc1af9..1651bd5 100644 (file)
@@ -1,5 +1,5 @@
---- linux-2.4.27-mtx1/drivers/usb/serial/usbserial.c   2005-08-28 20:23:40.000000000 +0200
-+++ linux-2.4.27-mtx1/drivers/usb/serial/usbserial.c   2005-08-28 20:23:12.000000000 +0200
+--- linux-old/drivers/usb/serial/usbserial.c   2005-08-28 20:23:40.000000000 +0200
++++ linux/drivers/usb/serial/usbserial.c       2005-08-28 20:23:12.000000000 +0200
 @@ -499,6 +499,19 @@
                /* get_usb_serial checks port->tty, so cannot be used */
                serial = port->serial;
index e615a92..9169005 100644 (file)
@@ -1,5 +1,53 @@
---- linux/drivers/usb/serial/usbserial.c~33-usbserial-bulk_in_size-4096.diff   2006-03-31 15:05:46.674445000 +0200
-+++ linux/drivers/usb/serial/usbserial.c       2006-04-07 12:23:56.970400500 +0200
+--- linux/drivers/usb/acm.c.orig       2006-04-07 13:56:33.837683000 +0200
++++ linux/drivers/usb/acm.c    2006-04-07 12:14:37.995466750 +0200
+@@ -155,6 +155,11 @@
+       unsigned char clocal;                           /* termios CLOCAL */
+ };
++/* global params controlling max sizes for read, write, control */
++static int maxszr = 0;
++static int maxszw = 0;
++static int maxszc = 0;
++
+ static struct usb_driver acm_driver;
+ static struct tty_driver acm_tty_driver;
+ static struct acm *acm_table[ACM_TTY_MINORS];
+@@ -573,9 +578,13 @@
+                       }
+                       memset(acm, 0, sizeof(struct acm));
+-                      ctrlsize = epctrl->wMaxPacketSize;
+-                      readsize = epread->wMaxPacketSize;
+-                      acm->writesize = epwrite->wMaxPacketSize;
++                      ctrlsize = (epctrl->wMaxPacketSize > maxszc)?
++                              epctrl->wMaxPacketSize: maxszc;
++                      readsize = (epread->wMaxPacketSize > maxszr)?
++                              epread->wMaxPacketSize: maxszr;
++                      acm->writesize = (epwrite->wMaxPacketSize > maxszw)?
++                              epwrite->wMaxPacketSize: maxszw;
++
+                       acm->iface = cfacm->interface + j;
+                       acm->minor = minor;
+                       acm->dev = dev;
+@@ -740,6 +749,16 @@
+ module_init(acm_init);
+ module_exit(acm_exit);
++
++MODULE_PARM(maxszr, "i");
++MODULE_PARM_DESC(maxszr, "User specified USB endpoint read size");
++
++MODULE_PARM(maxszw, "i");
++MODULE_PARM_DESC(maxszw, "User specified USB endpoint write size");
++
++MODULE_PARM(maxszc, "i");
++MODULE_PARM_DESC(maxszc, "User specified USB endpoint control size");
++
+ MODULE_AUTHOR( DRIVER_AUTHOR );
+ MODULE_DESCRIPTION( DRIVER_DESC );
+ MODULE_LICENSE("GPL");
+--- linux/drivers/usb/serial/usbserial.c-orig  2009-02-27 23:34:48.000000000 +0100
++++ linux/drivers/usb/serial/usbserial.c       2009-02-27 23:34:54.000000000 +0100
 @@ -332,6 +332,9 @@
  static __u16  vendor  = 0x05f9;
  static __u16  product = 0xffff;
@@ -7,7 +55,7 @@
 +static int count_smaller64 = 0;
 +static int count_bigger64 = 0;
 +
- static struct usb_device_id generic_device_ids[5]; /* Initially all zeroes. */
+ static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
  
  /* All of the device info needed for the Generic Serial Converter */
 @@ -396,6 +399,10 @@
                port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
                port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
                if (!port->interrupt_in_buffer) {
-@@ -1807,6 +1825,7 @@
+@@ -1798,6 +1816,7 @@
  
  static void __exit usb_serial_exit(void)
  {
  
  #ifdef CONFIG_USB_SERIAL_GENERIC
        /* remove our generic driver */
-@@ -1874,6 +1893,15 @@
+@@ -1865,6 +1884,15 @@
  MODULE_PARM(debug, "i");
  MODULE_PARM_DESC(debug, "Debug enabled or not");
  
  #ifdef CONFIG_USB_SERIAL_GENERIC
  MODULE_PARM(vendor, "h");
  MODULE_PARM_DESC(vendor, "User specified USB idVendor");
---- linux/drivers/usb/acm.c.orig       2006-04-07 13:56:33.837683000 +0200
-+++ linux/drivers/usb/acm.c    2006-04-07 12:14:37.995466750 +0200
-@@ -155,6 +155,11 @@
-       unsigned char clocal;                           /* termios CLOCAL */
- };
-+/* global params controlling max sizes for read, write, control */
-+static int maxszr = 0;
-+static int maxszw = 0;
-+static int maxszc = 0;
-+
- static struct usb_driver acm_driver;
- static struct tty_driver acm_tty_driver;
- static struct acm *acm_table[ACM_TTY_MINORS];
-@@ -573,9 +578,13 @@
-                       }
-                       memset(acm, 0, sizeof(struct acm));
--                      ctrlsize = epctrl->wMaxPacketSize;
--                      readsize = epread->wMaxPacketSize;
--                      acm->writesize = epwrite->wMaxPacketSize;
-+                      ctrlsize = (epctrl->wMaxPacketSize > maxszc)?
-+                              epctrl->wMaxPacketSize: maxszc;
-+                      readsize = (epread->wMaxPacketSize > maxszr)?
-+                              epread->wMaxPacketSize: maxszr;
-+                      acm->writesize = (epwrite->wMaxPacketSize > maxszw)?
-+                              epwrite->wMaxPacketSize: maxszw;
-+
-                       acm->iface = cfacm->interface + j;
-                       acm->minor = minor;
-                       acm->dev = dev;
-@@ -740,6 +749,16 @@
- module_init(acm_init);
- module_exit(acm_exit);
-+
-+MODULE_PARM(maxszr, "i");
-+MODULE_PARM_DESC(maxszr, "User specified USB endpoint read size");
-+
-+MODULE_PARM(maxszw, "i");
-+MODULE_PARM_DESC(maxszw, "User specified USB endpoint write size");
-+
-+MODULE_PARM(maxszc, "i");
-+MODULE_PARM_DESC(maxszc, "User specified USB endpoint control size");
-+
- MODULE_AUTHOR( DRIVER_AUTHOR );
- MODULE_DESCRIPTION( DRIVER_DESC );
- MODULE_LICENSE("GPL");
diff --git a/recipes/linux/linux-mtx-1-2.4.27/43-usbserial-27-32-backport.diff b/recipes/linux/linux-mtx-1-2.4.27/43-usbserial-27-32-backport.diff
new file mode 100644 (file)
index 0000000..6a98f76
--- /dev/null
@@ -0,0 +1,33 @@
+--- linux/drivers/usb/serial/usbserial.c-27    2006-06-27 10:26:06.294476250 +0200
++++ linux/drivers/usb/serial/usbserial.c       2006-06-27 10:30:31.011020000 +0200
+@@ -528,8 +528,18 @@
+               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 (port->tty != NULL) {
++                      int rc;
++                      int sent = 0;
++                      while (sent < job->len) {
++                              rc = __serial_write(port, 0, job->buff + sent, job->len - sent);
++                              if ((rc < 0) || signal_pending(current))
++                                      break;
++                              sent += rc;
++                              if ((sent < job->len) && current->need_resched)
++                                      schedule();
++                      }
++              }
+               up(&port->sem);
+               spin_lock_irqsave(&post_lock, flags);
+@@ -725,6 +735,9 @@
+       struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+       int rc;
++      if (!port)
++              return -ENODEV;
++
+       if (!in_interrupt()) {
+               /*
+                * Run post_list to reduce a possiblity of reordered writes.
diff --git a/recipes/linux/linux-mtx-1-2.4.27/45-acm-tty-and-sb2.patch b/recipes/linux/linux-mtx-1-2.4.27/45-acm-tty-and-sb2.patch
new file mode 100644 (file)
index 0000000..4561fac
--- /dev/null
@@ -0,0 +1,721 @@
+--- linux/drivers/usb/acm.c-orig       2007-04-13 18:32:16.352672105 +0200
++++ linux/drivers/usb/acm.c    2007-04-13 18:33:21.063526545 +0200
+@@ -124,6 +124,9 @@
+ #define ACM_CTRL_PARITY               0x20
+ #define ACM_CTRL_OVERRUN      0x40
++// some devices don't have one comm and one data interface, but only one interface with endpoints for comm and data
++#define SINGLE_IF_ACM   0x01
++
+ /*
+  * Line speed and caracter encoding.
+  */
+@@ -139,6 +142,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,12 +158,23 @@
+       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;
++      unsigned char used_interfaces;
++      struct semaphore mutex;
+ };
++#define       mutex_lock(x)   down(x)
++#define       mutex_unlock(x) up(x)
++
+ /* global params controlling max sizes for read, write, control */
+ static int maxszr = 0;
+ static int maxszw = 0;
+ static int maxszc = 0;
++static int nonlegacy = 0;
+ static struct usb_driver acm_driver;
+ static struct tty_driver acm_tty_driver;
+@@ -167,6 +183,95 @@
+ #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.
+  */
+@@ -174,7 +279,10 @@
+ {
+       int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
+               request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
+-      dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
++      if (retval < 0)
++              err("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
++      else
++              dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
+       return retval < 0 ? retval : 0;
+ }
+@@ -191,10 +299,12 @@
+       struct acm *acm = urb->context;
+       struct usb_ctrlrequest *dr = urb->transfer_buffer;
+       unsigned char *data = (unsigned char *)(dr + 1);
+-      int newctrl;
++      int newctrl, s1, s2;
+       if (!ACM_READY(acm)) return;
++      //err("acm_ctrl_irq %p %i", urb, dr->bRequestType);
++
+       if (urb->status < 0) {
+               dbg("nonzero ctrl irq status received: %d", urb->status);
+               return;
+@@ -226,8 +336,15 @@
+                       return;
++              case 0x2a:
++                      s1 = le32_to_cpup((__u32 *) data);
++                      s2 = le32_to_cpup((__u32 *) (data+4));
++
++                      dbg("acm.c: ctrl 0x2a: idx %i len %i speed %i %i", dr->wIndex, dr->wLength, s1, s2);
++                      return;
++
+               default:
+-                      dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
++                      err("unknown control event received: request %d index %d len %d data0 %d data1 %d",
+                               dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
+                       return;
+       }
+@@ -238,36 +355,39 @@
+       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)
+-              dbg("nonzero read bulk status received: %d", urb->status);
++      if (urb->status) {
++              err("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);
++      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)) {
++                      dbg("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)
+@@ -283,6 +403,9 @@
+       mark_bh(IMMEDIATE_BH);
+ }
++static int unlinking_in_progress=0;
++static int closing=0;
++
+ static void acm_softint(void *private)
+ {
+       struct acm *acm = private;
+@@ -306,34 +429,57 @@
+       if (!acm || !acm->dev) return -EINVAL;
++      mutex_lock (&acm->mutex);
++
+       tty->driver_data = acm;
+       acm->tty = tty;
+       MOD_INC_USE_COUNT;
+-        lock_kernel();
++      if ( closing )
++              err("acm_tty_open: potential possibility of race condition detected");
++
++      if ( unlinking_in_progress ) {
++              err("acm_tty_open: cannot open because unlinking_in_progress %i", acm->used);
++              mutex_unlock (&acm->mutex);
++              return -1;
++      }
+-      if (acm->used++) {
+-                unlock_kernel();
+-                return 0;
+-        }
++      if (acm->used) {
++              acm->used++;
++              mutex_unlock (&acm->mutex);
++              return 0;
++      }
+-        unlock_kernel();
++      unlinking_in_progress=1;
++      err("acm_tty_open: %i %p !!", acm->used, tty);
++
++      acm->resubmit_to_unthrottle = 0;
++      acm->td_len = 0;
++      acm->td_busy = 0;
+       acm->ctrlurb.dev = acm->dev;
+       if (usb_submit_urb(&acm->ctrlurb))
+-              dbg("usb_submit_urb(ctrl irq) failed");
++              dbg("acm open: usb_submit_urb(ctrl irq) failed");
++      else
++              dbg("acm open: ctrlurb %p submitted", &acm->ctrlurb);
++
++      acm->used++;
++      acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
+       acm->readurb.dev = acm->dev;
+       if (usb_submit_urb(&acm->readurb))
+-              dbg("usb_submit_urb(read bulk) failed");
+-
+-      acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
++              dbg("acm open: usb_submit_urb(read bulk) failed");
++      else
++              dbg("acm open: readurb %p submitted", &acm->readurb);
+-      /* force low_latency on so that our tty_push actually forces the data through, 
++      /* 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;
++      unlinking_in_progress=0;
++      mutex_unlock (&acm->mutex);
++
+       return 0;
+ }
+@@ -343,19 +489,35 @@
+       if (!acm || !acm->used) return;
+-      if (!--acm->used) {
+-              if (acm->dev) {
+-                      acm_set_control(acm, acm->ctrlout = 0);
+-                      usb_unlink_urb(&acm->ctrlurb);
+-                      usb_unlink_urb(&acm->writeurb);
+-                      usb_unlink_urb(&acm->readurb);
+-              } else {
+-                      tty_unregister_devfs(&acm_tty_driver, acm->minor);
+-                      acm_table[acm->minor] = NULL;
+-                      kfree(acm);
+-              }
++      mutex_lock (&acm->mutex);
++
++      closing = 1;
++      if (--acm->used) {
++              closing=0;
++              MOD_DEC_USE_COUNT;
++              mutex_unlock (&acm->mutex);
++              return;
++      }
++      unlinking_in_progress = 1;
++
++      err("acm_tty_close: %i %p", acm->used, tty);
++
++      if (acm->dev) {
++              acm_set_control(acm, acm->ctrlout = 0);
++              usb_unlink_urb(&acm->ctrlurb);
++              usb_unlink_urb(&acm->writeurb);
++              usb_unlink_urb(&acm->readurb);
++      } else {
++              tty_unregister_devfs(&acm_tty_driver, acm->minor);
++              acm_table[acm->minor] = NULL;
++              kfree(acm->throttle_data);
++              kfree(acm);
+       }
++
++      closing=0;
++      unlinking_in_progress = 0;
+       MOD_DEC_USE_COUNT;
++      mutex_unlock (&acm->mutex);
+ }
+ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
+@@ -363,8 +525,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,22 +571,44 @@
+ {
+       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)
++
++      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)
+ {
+       struct acm *acm = tty->driver_data;
++
+       if (!ACM_READY(acm)) return;
++
++      if (nonlegacy) {
++              err("non-legacy port, skipping acm_tty_break_ctl");
++              return;
++      }
++
+       if (acm_send_break(acm, state ? 0xffff : 0))
+               dbg("send break failed");
+ }
+@@ -455,7 +647,19 @@
+                               case TIOCMBIC: newctrl &= ~mask; break;
+                       }
+-                      if (acm->ctrlout == newctrl) return 0;
++                      if (acm->ctrlout == newctrl) {
++                              dbg("acm_tty_ioctl: set old state %x", newctrl);
++                              return 0;
++                      }
++
++                      err("acm_tty_ioctl: %s%s%s -> dtr%s rts%s (%lx)",
++                                      cmd==TIOCMBIC?"Clear":(cmd==TIOCMBIS?"Set":"SET"),
++                                      mask & ACM_CTRL_DTR ? " DTR":"",
++                                      mask & ACM_CTRL_RTS ? " RTS":"",
++                                      newctrl & ACM_CTRL_DTR ? "+":"-",
++                                      newctrl & ACM_CTRL_RTS ? "+":"-",
++                                      arg);
++
+                       return acm_set_control(acm, acm->ctrlout = newctrl);
+       }
+@@ -483,6 +687,12 @@
+       if (!ACM_READY(acm)) return;
++      if (nonlegacy) {
++              acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
++              dbg("non-legacy port, skipping acm_tty_set_termios");
++              return;
++      }
++
+       newline.speed = cpu_to_le32p(acm_tty_speed +
+               (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
+       newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
+@@ -518,34 +727,64 @@
+       struct usb_config_descriptor *cfacm;
+       struct usb_interface_descriptor *ifcom, *ifdata;
+       struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
+-      int readsize, ctrlsize, minor, i, j;
++      int readsize, ctrlsize, minor, i;
+       unsigned char *buf;
++      unsigned char used_interfaces=2;
+       for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+               cfacm = dev->config + i;
+-              dbg("probing config %d", cfacm->bConfigurationValue);
++              ifcom = cfacm->interface[ifnum].altsetting + 0;
++
++              if (id->driver_info == SINGLE_IF_ACM) {
++                      printk("using single_if_acm\n");
++                      struct usb_endpoint_descriptor *ep=ifcom->endpoint;
++                      int k;
++
++                      if (ifcom->bNumEndpoints != 3) {
++                              continue;
++                      }
++
++                      epctrl = epread = epwrite = NULL;
++                      for (k=0; k<3; ++k, ++ep) {
++                              if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT &&
++                                              (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
++                                      epctrl = ep;
++                              } else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK &&
++                                              (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
++                                      epread = ep;
++                              } else if ( (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
++                                      epwrite = ep;
++                              }
++                      }
+-              for (j = 0; j < cfacm->bNumInterfaces - 1; j++) {
++                      if ( !epctrl || !epread || !epwrite ) {
++                              dbg("SINGLE_IF_ACM acm_probe inv eps epctrl %s epread %s epwrite %s", epctrl?"ok":"missing",
++                                              epread?"ok":"missing", epwrite?"ok":"missing");
++                              dbg("SINGLE_IF_ACM Invalid enpoint configuration");
++                              continue;
++                      }
+-                      if (usb_interface_claimed(cfacm->interface + j) ||
+-                          usb_interface_claimed(cfacm->interface + j + 1))
++                      used_interfaces = 1;
++              } else {
++                      if ((ifnum+1)>=cfacm->bNumInterfaces || usb_interface_claimed(cfacm->interface + ifnum + 1)) {
++                              // no data interface available
+                               continue;
++                      }
+-                      ifcom = cfacm->interface[j].altsetting + 0;
+-                      ifdata = cfacm->interface[j + 1].altsetting + 0;
++                      ifdata = cfacm->interface[ifnum + 1].altsetting + 0;
+                       if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) {
+-                              ifcom = cfacm->interface[j + 1].altsetting + 0;
+-                              ifdata = cfacm->interface[j].altsetting + 0;
++                              ifcom = cfacm->interface[ifnum + 1].altsetting + 0;
++                              ifdata = cfacm->interface[ifnum].altsetting + 0;
+                               if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2)
+                                       continue;
+                       }
+                       if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
+-                          ifcom->bInterfaceProtocol < 1 || ifcom->bInterfaceProtocol > 6 ||
+-                          ifcom->bNumEndpoints < 1)
++                                      ifcom->bInterfaceProtocol < 1 || ifcom->bInterfaceProtocol > 6 ||
++                                      ifcom->bNumEndpoints < 1)
+                               continue;
+                       epctrl = ifcom->endpoint + 0;
+@@ -553,76 +792,86 @@
+                       epwrite = ifdata->endpoint + 1;
+                       if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
+-                          (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
+-                          ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
++                                      (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
++                                      ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
+                               continue;
+-                      dbg("using interface %d\n", j);
+-
+                       if ((epread->bEndpointAddress & 0x80) != 0x80) {
+                               epread = ifdata->endpoint + 1;
+                               epwrite = ifdata->endpoint + 0;
+                       }
++              }
+-                      usb_set_configuration(dev, cfacm->bConfigurationValue);
++              usb_set_configuration(dev, cfacm->bConfigurationValue);
+-                      for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+-                      if (acm_table[minor]) {
+-                              err("no more free acm devices");
+-                              return NULL;
+-                      }
++              for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
++              if (acm_table[minor]) {
++                      err("no more free acm devices");
++                      return NULL;
++              }
+-                      if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+-                              err("out of memory");
+-                              return NULL;
+-                      }
+-                      memset(acm, 0, sizeof(struct acm));
++              if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
++                      err("out of memory");
++                      return NULL;
++              }
++              memset(acm, 0, sizeof(struct acm));
+-                      ctrlsize = (epctrl->wMaxPacketSize > maxszc)?
+-                              epctrl->wMaxPacketSize: maxszc;
+-                      readsize = (epread->wMaxPacketSize > maxszr)?
+-                              epread->wMaxPacketSize: maxszr;
+-                      acm->writesize = (epwrite->wMaxPacketSize > maxszw)?
+-                              epwrite->wMaxPacketSize: maxszw;
+-
+-                      acm->iface = cfacm->interface + j;
+-                      acm->minor = minor;
+-                      acm->dev = dev;
+-
+-                      acm->tqueue.routine = acm_softint;
+-                      acm->tqueue.data = acm;
+-
+-                      if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+-                              err("out of memory");
+-                              kfree(acm);
+-                              return NULL;
+-                      }
++              ctrlsize = (epctrl->wMaxPacketSize > maxszc)?
++                      epctrl->wMaxPacketSize: maxszc;
++              readsize = (epread->wMaxPacketSize > maxszr)?
++                      epread->wMaxPacketSize: maxszr;
++              acm->writesize = (epwrite->wMaxPacketSize > maxszw)?
++                      epwrite->wMaxPacketSize: maxszw;
++
++              init_MUTEX (&acm->mutex);
++              if (!(acm->throttle_data = kmalloc(TD_SIZE * sizeof (*acm->throttle_data), GFP_KERNEL))) {
++                      err("out of memory (throttle_data)");
++                      kfree(acm);
++                      return NULL;
++              }
++              acm->iface = cfacm->interface + ifnum;
++              acm->minor = minor;
++              acm->dev = dev;
+-                      FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
+-                                   buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
++              acm->used_interfaces = used_interfaces;
+-                      FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+-                                    buf += ctrlsize, readsize, acm_read_bulk, acm);
+-                      acm->readurb.transfer_flags |= USB_NO_FSBR;
++              acm->tqueue.routine = acm_softint;
++              acm->tqueue.data = acm;
+-                      FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+-                                    buf += readsize, acm->writesize, acm_write_bulk, acm);
+-                      acm->writeurb.transfer_flags |= USB_NO_FSBR;
++              if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
++                      err("out of memory (urb buf)");
++                      kfree(acm);
++                      return NULL;
++              }
+-                      printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
++              FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
++                              buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+-                      acm_set_control(acm, acm->ctrlout);
++              FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
++                              buf += ctrlsize, readsize, acm_read_bulk, acm);
++              acm->readurb.transfer_flags |= USB_NO_FSBR;
+-                      acm->line.speed = cpu_to_le32(9600);
+-                      acm->line.databits = 8;
+-                      acm_set_line(acm, &acm->line);
++              FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
++                              buf += readsize, acm->writesize, acm_write_bulk, acm);
++              acm->writeurb.transfer_flags |= USB_NO_FSBR;
+-                      usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
+-                      usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
++              printk(KERN_INFO "ttyACM%d: USB ACM device C %p W %p R %p %x\n", minor, &acm->ctrlurb,
++                              &acm->writeurb, &acm->readurb, acm->ctrlout);
++
++              acm_set_control(acm, acm->ctrlout);
+-                      tty_register_devfs(&acm_tty_driver, 0, minor);
+-                      return acm_table[minor] = acm;
++              acm->line.speed = cpu_to_le32(9600);
++              acm->line.databits = 8;
++              acm_set_line(acm, &acm->line);
++
++              if ( acm->used_interfaces == 2 ) {
++                      // only just checked interface is claimed automatically, so claim data interface too
++                      usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
+               }
++
++              tty_register_devfs(&acm_tty_driver, 0, minor);
++
++              return acm_table[minor] = acm;
+       }
+       return NULL;
+@@ -646,7 +895,9 @@
+       kfree(acm->ctrlurb.transfer_buffer);
+       usb_driver_release_interface(&acm_driver, acm->iface + 0);
+-      usb_driver_release_interface(&acm_driver, acm->iface + 1);
++      if ( acm->used_interfaces == 2 ) {
++              usb_driver_release_interface(&acm_driver, acm->iface + 1);
++      }
+       if (!acm->used) {
+               tty_unregister_devfs(&acm_tty_driver, acm->minor);
+@@ -665,6 +916,9 @@
+ static struct usb_device_id acm_ids[] = {
+       { USB_DEVICE(0x22B8, 0x1005) },         /* Motorola TimePort 280 */
++      { USB_DEVICE(0x05C6, 0x7001), driver_info: SINGLE_IF_ACM },             /* Siemens HC15/HC25 */
++      { USB_DEVICE(0x0681, 0x003e), driver_info: SINGLE_IF_ACM },             /* Siemens HC15/HC25 */
++      { USB_DEVICE(0x22B8, 0x1006) },
+       { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
+       { USB_DEVICE_INFO(USB_CLASS_COMM, 2, 0) },
+       { }
+@@ -735,7 +989,7 @@
+               return -1;
+       }
+-      info(DRIVER_VERSION ":" DRIVER_DESC);
++      info(DRIVER_VERSION ":" DRIVER_DESC "(non-legacy %d)", nonlegacy);
+       return 0;
+ }
+@@ -759,7 +1013,9 @@
+ MODULE_PARM(maxszc, "i");
+ MODULE_PARM_DESC(maxszc, "User specified USB endpoint control size");
++MODULE_PARM(nonlegacy, "i");
++MODULE_PARM_DESC(nonlegacy, "Set this to 1 to for use with non-legacy device");
++
+ MODULE_AUTHOR( DRIVER_AUTHOR );
+ MODULE_DESCRIPTION( DRIVER_DESC );
+ MODULE_LICENSE("GPL");
+-
index 5815a57..6dd7121 100644 (file)
@@ -35,7 +35,11 @@ SRC_URI = "cvs://cvs:cvs@ftp.linux-mips.org/home/cvs;module=linux;tag=linux_2_4_
        file://26-usbd-amd-pb1x00-kit-23may2003-update.diff;patch=1 \
        file://27-usbd-amd-pb1x00-kit-23may2003-usbd.diff;patch=1 \
        file://29-au1000-pci-config-clear-errors.diff;patch=1 \
+       file://32-usbserial-stalled-hack.diff;patch=1 \
+       file://33-usbserial-bulk_in_size-4096.diff;patch=1 \
        file://42-usb-ohci-fixes.patch;patch=1 \
+       file://43-usbserial-27-32-backport.diff;patch=1 \
+       file://45-acm-tty-and-sb2.patch;patch=1 \
        file://48-pptp.patch;patch=1 \
        file://defconfig-mtx-1"
 
@@ -74,8 +78,8 @@ fi
 FILES_kernel += " /tmp"
 
 do_deploy() {
-        install -d ${DEPLOY_DIR}/images
-       install -m 0644 arch/mips/zboot/images/mtx-1.flash.bin ${DEPLOY_DIR}/images/${KERNEL_IMAGE_NAME}.flash.bin
-        install -m 0644 arch/mips/zboot/images/mtx-1.flash.srec ${DEPLOY_DIR}/images/${KERNEL_IMAGE_NAME}.flash.srec
-       install -m 0644 arch/mips/zboot/images/mtx-1.srec ${DEPLOY_DIR}/images/${KERNEL_IMAGE_NAME}.ram.srec
+       install -d 0755 ${DEPLOY_DIR_IMAGE}
+       install -m 0644 arch/mips/zboot/images/mtx-1.flash.bin ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.flash.bin
+        install -m 0644 arch/mips/zboot/images/mtx-1.flash.srec ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.flash.srec
+       install -m 0644 arch/mips/zboot/images/mtx-1.srec ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.ram.srec
 }
index 48495b5..b4cb9fe 100644 (file)
@@ -1,6 +1,15 @@
 diff -Naru linux/arch/mips/Makefile linux.spi/arch/mips/Makefile
 --- linux/arch/mips/Makefile   2004-05-06 15:23:41.000000000 -0400
 +++ linux.spi/arch/mips/Makefile       2004-05-11 23:19:24.000000000 -0400
+@@ -17,7 +17,7 @@
+ # Select the object file format to substitute into the linker script.
+ #
+ ifdef CONFIG_CPU_LITTLE_ENDIAN
+-tool-prefix   = mipsel-linux-
++tool-prefix   = mipsel-nylon-linux-
+ ld-emul               = elf32ltsmip
+ else
+ tool-prefix   = mips-linux-
 @@ -29,6 +29,8 @@
  endif
  
index 66ce06c..5b26903 100644 (file)
@@ -86,8 +86,8 @@ fi
 FILES_kernel += " /tmp"
 
 do_deploy() {
-        install -d ${DEPLOY_DIR}/images
-       install -m 0644 arch/mips/zboot/images/mtx-2.flash.bin ${DEPLOY_DIR}/images/${KERNEL_IMAGE_NAME}.flash.bin
-        install -m 0644 arch/mips/zboot/images/mtx-2.flash.srec ${DEPLOY_DIR}/images/${KERNEL_IMAGE_NAME}.flash.srec
-       install -m 0644 arch/mips/zboot/images/mtx-2.srec ${DEPLOY_DIR}/images/${KERNEL_IMAGE_NAME}.ram.srec
+       install -d 0755 ${DEPLOY_DIR_IMAGE}
+       install -m 0644 arch/mips/zboot/images/mtx-2.flash.bin ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.flash.bin
+        install -m 0644 arch/mips/zboot/images/mtx-2.flash.srec ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.flash.srec
+       install -m 0644 arch/mips/zboot/images/mtx-2.srec ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.ram.srec
 }