summaryrefslogtreecommitdiff
path: root/multitech
diff options
context:
space:
mode:
authorMike Fiore <mfiore@multitech.com>2013-03-27 11:13:38 -0500
committerMike Fiore <mfiore@multitech.com>2013-03-27 11:13:38 -0500
commit52478a46ad08fcc9706897ed497f61cbb238b49e (patch)
treeab6ea7b61fe7c6d71579a9020969ce80fe58041d /multitech
parent3d6759beb8d2bdb12a132ce1b98694a4ed70085a (diff)
vizzini: add flow control patch and bump
Diffstat (limited to 'multitech')
-rw-r--r--multitech/recipes/vizzini/vizzini-0.76/vizzini-0.76-flow-control.patch157
-rw-r--r--multitech/recipes/vizzini/vizzini_0.76.bb3
2 files changed, 159 insertions, 1 deletions
diff --git a/multitech/recipes/vizzini/vizzini-0.76/vizzini-0.76-flow-control.patch b/multitech/recipes/vizzini/vizzini-0.76/vizzini-0.76-flow-control.patch
new file mode 100644
index 0000000..77adf53
--- /dev/null
+++ b/multitech/recipes/vizzini/vizzini-0.76/vizzini-0.76-flow-control.patch
@@ -0,0 +1,157 @@
+--- a/vizzini.c 2013-03-26 11:34:39.362546946 -0500
++++ b/vizzini.c 2013-03-27 10:43:03.123460275 -0500
+@@ -92,6 +92,9 @@
+ #define N_OUT_URB 4
+ #define IN_BUFLEN 4096
+
++#define READ_URB_RUNNING 0
++#define READ_URB_STOPPED 1
++
+ static int debug;
+
+
+@@ -169,6 +172,7 @@
+
+ struct urb *in_urbs[N_IN_URB];
+ char *in_buffer[N_IN_URB];
++ int in_urb_flags[N_IN_URB];
+
+ int ctrlin;
+ int ctrlout;
+@@ -995,6 +999,8 @@
+ char *transfer_buffer = urb->transfer_buffer;
+ int length, room, have_extra_byte;
+ int err;
++ unsigned long flags;
++ int j;
+
+ if (debug) dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+
+@@ -1085,9 +1091,26 @@
+ portdata->extra_byte = transfer_buffer[urb->actual_length - 1];
+ }
+
+- err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (err)
+- dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err);
++ /* throttle device if requested */
++ spin_lock_irqsave(&port->lock, flags);
++ port->throttled = port->throttle_req;
++ if (! port->throttled) {
++ spin_unlock_irqrestore(&port->lock, flags);
++ err = usb_submit_urb(urb, GFP_ATOMIC);
++ if (err)
++ dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err);
++ } else {
++ spin_unlock_irqrestore(&port->lock, flags);
++ for (j = 0; j < N_IN_URB; j++) {
++ if (portdata->in_urbs[j] == urb) {
++ if (debug) dev_dbg(&port->dev, "throttling urb %d\n", j);
++ spin_lock_irqsave(&port->lock, flags);
++ portdata->in_urb_flags[j] = READ_URB_STOPPED;
++ spin_unlock_irqrestore(&port->lock, flags);
++ break;
++ }
++ }
++ }
+ }
+
+
+@@ -1172,6 +1195,7 @@
+ int i;
+ struct urb *urb;
+ int result;
++ unsigned long flags;
+
+ portdata = usb_get_serial_port_data(port);
+
+@@ -1179,10 +1203,19 @@
+
+ acm_set_control(port, portdata->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
+
++ /* unthrottle device in case TTY was closed while throttled */
++ spin_lock_irqsave(&port->lock, flags);
++ port->throttled = 0;
++ port->throttle_req = 0;
++ spin_unlock_irqrestore(&port->lock, flags);
++
+ /* Reset low level data toggle and start reading from endpoints */
+ for (i = 0; i < N_IN_URB; i++) {
+ if (debug) dev_dbg(&port->dev, "%s urb %d\n", __func__, i);
+
++ spin_lock_irqsave(&port->lock, flags);
++ portdata->in_urb_flags[i] = READ_URB_RUNNING;
++ spin_unlock_irqrestore(&port->lock, flags);
+ urb = portdata->in_urbs[i];
+ if (!urb)
+ continue;
+@@ -1207,8 +1240,6 @@
+ }
+ }
+
+- tty->low_latency = 1;
+-
+ /* start up the interrupt endpoint if we have one */
+ if (port->interrupt_in_urb) {
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+@@ -1592,6 +1623,51 @@
+ usb_serial_disconnect(interface);
+ }
+
++static void vizzini_throttle(struct tty_struct *tty)
++{
++ unsigned long flags;
++ struct usb_serial_port *port = tty->driver_data;
++
++ if (debug) dev_dbg(&port->dev, "TTY buffer approaching limit, stopping USB reads\n");
++
++ spin_lock_irqsave(&port->lock, flags);
++ port->throttle_req = 1;
++ spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static void vizzini_unthrottle(struct tty_struct *tty)
++{
++ unsigned long flags;
++ unsigned int was_throttled;
++ struct usb_serial_port *port = tty->driver_data;
++ struct vizzini_port_private *portdata = usb_get_serial_port_data(port);
++ int err;
++ int i;
++
++ if (debug) dev_dbg(&port->dev, "Resuming USB reads\n");
++
++ spin_lock_irqsave(&port->lock, flags);
++ was_throttled = port->throttled;
++ port->throttled = 0;
++ port->throttle_req = 0;
++ spin_unlock_irqrestore(&port->lock, flags);
++
++ if (was_throttled) {
++ for (i = 0; i < N_IN_URB; i++) {
++ spin_lock_irqsave(&port->lock, flags);
++ if (portdata->in_urb_flags[i] == READ_URB_STOPPED) {
++ if (debug) dev_dbg(&port->dev, "unthrottling urb %d\n", i);
++ portdata->in_urb_flags[i] = READ_URB_RUNNING;
++ spin_unlock_irqrestore(&port->lock, flags);
++ err = usb_submit_urb(portdata->in_urbs[i], GFP_ATOMIC);
++ if (err)
++ dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err);
++ } else {
++ spin_unlock_irqrestore(&port->lock, flags);
++ }
++ }
++ }
++}
+
+
+ static struct usb_serial_driver vizzini_device = {
+@@ -1606,6 +1682,8 @@
+ .probe = vizzini_probe,
+ .open = vizzini_open,
+ .close = vizzini_close,
++ .throttle = vizzini_throttle,
++ .unthrottle = vizzini_unthrottle,
+ .write = vizzini_write,
+ .write_room = vizzini_write_room,
+ .ioctl = vizzini_ioctl,
diff --git a/multitech/recipes/vizzini/vizzini_0.76.bb b/multitech/recipes/vizzini/vizzini_0.76.bb
index ff1f421..d1cc653 100644
--- a/multitech/recipes/vizzini/vizzini_0.76.bb
+++ b/multitech/recipes/vizzini/vizzini_0.76.bb
@@ -1,10 +1,11 @@
require vizzini.inc
-LOCAL_PR = "${INC_PR}.0"
+LOCAL_PR = "${INC_PR}.1"
MACHINE_KERNEL_PR_append = "${LOCAL_PR}"
SRC_URI += "file://xr21v141x-lnx-3.0-pak.tar.gz \
file://vizzini-0.76-rs485.patch \
+ file://vizzini-0.76-flow-control.patch \
"
S = "${WORKDIR}/xr21v141x-lnx-3.0-pak"