All of lore.kernel.org
 help / color / mirror / Atom feed
From: bart.hartgers@gmail.com
To: Greg Kroah-Hartman <gregkh@suse.de>, Mike McCormack <mikem@ring3k.org>
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	Bart Hartgers <bart.hartgers@gmail.com>
Subject: [PATCH 5/6] ark3116: (v2) Callbacks for interrupt and bulk read
Date: Wed, 28 Oct 2009 10:43:29 +0100	[thread overview]
Message-ID: <20091028095110.400791452@gmail.com> (raw)
In-Reply-To: 20091028094324.010816897@gmail.com

[-- Attachment #1: 0030_ark3116_callbacks.patch --]
[-- Type: text/plain, Size: 6228 bytes --]

Signed-off-by: Bart Hartgers <bart.hartgers@gmail.com>
---
Index: linux-2.6.32-rc4/drivers/usb/serial/ark3116.c
===================================================================
--- linux-2.6.32-rc4.orig/drivers/usb/serial/ark3116.c	2009-10-28 10:21:43.000000000 +0100
+++ linux-2.6.32-rc4/drivers/usb/serial/ark3116.c	2009-10-28 10:21:55.000000000 +0100
@@ -605,6 +605,198 @@ static void ark3116_break_ctl(struct tty
 	mutex_unlock(&priv->hw_lock);
 }
 
+static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
+{
+	struct ark3116_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->status_lock, flags);
+	priv->msr = msr;
+	spin_unlock_irqrestore(&priv->status_lock, flags);
+
+	if (msr & UART_MSR_ANY_DELTA) {
+		/* update input line counters */
+		if (msr & UART_MSR_DCTS)
+			priv->icount.cts++;
+		if (msr & UART_MSR_DDSR)
+			priv->icount.dsr++;
+		if (msr & UART_MSR_DDCD)
+			priv->icount.dcd++;
+		if (msr & UART_MSR_TERI)
+			priv->icount.rng++;
+		wake_up_interruptible(&priv->delta_msr_wait);
+	}
+}
+
+static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)
+{
+	struct ark3116_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->status_lock, flags);
+	/* combine bits */
+	priv->lsr |= lsr;
+	spin_unlock_irqrestore(&priv->status_lock, flags);
+
+	if (lsr&UART_LSR_BRK_ERROR_BITS) {
+		if (lsr & UART_LSR_BI)
+			priv->icount.brk++;
+		if (lsr & UART_LSR_FE)
+			priv->icount.frame++;
+		if (lsr & UART_LSR_PE)
+			priv->icount.parity++;
+		if (lsr & UART_LSR_OE)
+			priv->icount.overrun++;
+	}
+}
+
+static void ark3116_read_int_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	int status = urb->status;
+	const __u8 *data = urb->transfer_buffer;
+	int result;
+
+	switch (status) {
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+		    __func__, status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+		    __func__, status);
+		break;
+	case 0: /* success */
+		/* discovered this by trail and error... */
+		if ((urb->actual_length == 4) && (data[0] == 0xe8)) {
+			const __u8 id = data[1]&UART_IIR_ID;
+			dbg("%s: iir=%02x", __func__, data[1]);
+			if (id == UART_IIR_MSI) {
+				dbg("%s: msr=%02x", __func__, data[3]);
+				ark3116_update_msr(port, data[3]);
+				break;
+			} else if (id == UART_IIR_RLSI) {
+				dbg("%s: lsr=%02x", __func__, data[2]);
+				ark3116_update_lsr(port, data[2]);
+				break;
+			}
+		}
+		/*
+		 * Not sure what this data meant...
+		 */
+		usb_serial_debug_data(debug, &port->dev,
+				      __func__,
+				      urb->actual_length,
+				      urb->transfer_buffer);
+		break;
+	}
+
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting interrupt urb\n",
+			__func__, result);
+}
+
+
+/* Data comes in via the bulk (data) URB, erors/interrupts via the int URB.
+ * This means that we cannot be sure which data byte has an associated error
+ * condition, so we report an error for all data in the next bulk read.
+ *
+ * Actually, there might even be a window between the bulk data leaving the
+ * ark and reading/resetting the lsr in the read_bulk_callback where an
+ * interrupt for the next data block could come in.
+ * Without somekind of ordering on the ark, we would have to report the
+ * error for the next block of data as well...
+ * For now, let's pretend this can't happen.
+ */
+
+static void send_to_tty(struct tty_struct *tty,
+			const unsigned char *chars,
+			size_t size, char flag)
+{
+	if (size == 0)
+		return;
+	if (flag == TTY_NORMAL) {
+		tty_insert_flip_string(tty, chars, size);
+	} else {
+		int i;
+		for (i = 0; i < size; ++i)
+			tty_insert_flip_char(tty, chars[i], flag);
+	}
+}
+
+static void ark3116_read_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port =  urb->context;
+	struct ark3116_private *priv = usb_get_serial_port_data(port);
+	const __u8 *data = urb->transfer_buffer;
+	int status = urb->status;
+	struct tty_struct *tty;
+	unsigned long flags;
+	int result;
+	char flag;
+	__u32 lsr;
+
+	switch (status) {
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+		    __func__, status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+		    __func__, status);
+		break;
+	case 0: /* success */
+
+		spin_lock_irqsave(&priv->status_lock, flags);
+		lsr = priv->lsr;
+		/* clear error bits */
+		priv->lsr &= ~UART_LSR_BRK_ERROR_BITS;
+		spin_unlock_irqrestore(&priv->status_lock, flags);
+
+		if (unlikely(lsr & UART_LSR_BI))
+			flag = TTY_BREAK;
+		else if (unlikely(lsr & UART_LSR_PE))
+			flag = TTY_PARITY;
+		else if (unlikely(lsr & UART_LSR_FE))
+			flag = TTY_FRAME;
+		else
+			flag = TTY_NORMAL;
+
+		tty = tty_port_tty_get(&port->port);
+		if (tty) {
+			tty_buffer_request_room(tty, urb->actual_length + 1);
+			/* overrun is special, not associated with a char */
+			if (unlikely(lsr & UART_LSR_OE))
+				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+			send_to_tty(tty, data, urb->actual_length, flag);
+			tty_flip_buffer_push(tty);
+			tty_kref_put(tty);
+		}
+
+		/* Throttle the device if requested by tty */
+		spin_lock_irqsave(&port->lock, flags);
+		port->throttled = port->throttle_req;
+		if (port->throttled) {
+			spin_unlock_irqrestore(&port->lock, flags);
+			return;
+		} else
+			spin_unlock_irqrestore(&port->lock, flags);
+	}
+	/* Continue reading from device */
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&urb->dev->dev, "%s - failed resubmitting"
+			" read urb, error %d\n", __func__, result);
+}
+
 static struct usb_driver ark3116_driver = {
 	.name =		"ark3116",
 	.probe =	usb_serial_probe,
@@ -631,6 +823,8 @@ static struct usb_serial_driver ark3116_
 	.open =			ark3116_open,
 	.close =		ark3116_close,
 	.break_ctl = 		ark3116_break_ctl,
+	.read_int_callback = 	ark3116_read_int_callback,
+	.read_bulk_callback =	ark3116_read_bulk_callback,
 };
 
 static int __init ark3116_init(void)

-- 

  parent reply	other threads:[~2009-10-28  9:51 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-28  9:43 [PATCH 0/6] ark3116: (v2) driver rework after review bart.hartgers
2009-10-28  9:43 ` [PATCH 1/6] ark3116: (v2) Setup some basic infrastructure for new ark3116 driver bart.hartgers
2009-10-28  9:43 ` [PATCH 2/6] ark3116: (v2) Make existing functions 16450-aware and add close and release functions bart.hartgers
2009-10-28  9:43 ` [PATCH 3/6] ark3116: (v2) Replace cmget bart.hartgers
2009-10-28  9:43 ` [PATCH 4/6] ark3116: (v2) Add cmset and break bart.hartgers
2009-10-28  9:43 ` bart.hartgers [this message]
2009-10-28  9:43 ` [PATCH 6/6] ark3116: (v2) Cleanup of now unneeded functions bart.hartgers
2009-10-28 11:41 ` [PATCH 0/6] ark3116: (v2) driver rework after review Mike McCormack

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091028095110.400791452@gmail.com \
    --to=bart.hartgers@gmail.com \
    --cc=gregkh@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mikem@ring3k.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.