Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a577ce3 authored by V. Ananda Krishnan's avatar V. Ananda Krishnan Committed by Linus Torvalds
Browse files

[PATCH] jsm: update for tty buffering revamp



Signed-off-by: default avatarV. Ananda Krishnan <mansarov@us.ibm.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7d95c8f2
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -893,7 +893,7 @@ config SERIAL_VR41XX_CONSOLE

config SERIAL_JSM
	tristate "Digi International NEO PCI Support"
	depends on PCI && BROKEN
	depends on PCI
	select SERIAL_CORE
	help
	  This is a driver for Digi International's Neo series
+65 −143
Original line number Diff line number Diff line
@@ -20,8 +20,10 @@
 *
 * Contact Information:
 * Scott H Kilau <Scott_Kilau@digi.com>
 * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
 *
 * Ananda Venkatarman <mansarov@us.ibm.com>
 * Modifications:
 * 01/19/06:	changed jsm_input routine to use the dynamically allocated
 *		tty_buffer changes. Contributors: Scott Kilau and Ananda V.
 ***********************************************************************/
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -497,16 +499,16 @@ void jsm_input(struct jsm_channel *ch)
{
	struct jsm_board *bd;
	struct tty_struct *tp;
	struct tty_ldisc *ld;
	u32 rmask;
	u16 head;
	u16 tail;
	int data_len;
	unsigned long lock_flags;
	int flip_len;
	int flip_len = 0;
	int len = 0;
	int n = 0;
	char *buf = NULL;
	char *buf2 = NULL;
	int s = 0;
	int i = 0;

@@ -574,56 +576,50 @@ void jsm_input(struct jsm_channel *ch)

	/*
	 * If the rxbuf is empty and we are not throttled, put as much
	 * as we can directly into the linux TTY flip buffer.
	 * The jsm_rawreadok case takes advantage of carnal knowledge that
	 * the char_buf and the flag_buf are next to each other and
	 * are each of (2 * TTY_FLIPBUF_SIZE) size.
	 * as we can directly into the linux TTY buffer.
	 *
	 * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf
	 *actually still uses the flag buffer, so you can't
	 *use it for input data
	 */
	if (jsm_rawreadok) {
		if (tp->real_raw)
			flip_len = MYFLIPLEN;
		else
			flip_len = 2 * TTY_FLIPBUF_SIZE;
	} else
		flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;
	flip_len = TTY_FLIPBUF_SIZE;

	len = min(data_len, flip_len);
	len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
	ld = tty_ldisc_ref(tp);

	if (len <= 0) {
		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
		return;
	}
	/*
	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
	 * like the ld doesn't have any space to put the data right now.
	 */
	if (test_bit(TTY_DONT_FLIP, &tp->flags))
		len = 0;

	/*
	 * If we're bypassing flip buffers on rx, we can blast it
	 * right into the beginning of the buffer.
	 * If we were unable to get a reference to the ld,
	 * don't flush our buffer, and act like the ld doesn't
	 * have any space to put the data right now.
	 */
	if (jsm_rawreadok) {
		if (tp->real_raw) {
			if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
					"JSM - FLIPBUF in use. delaying input\n");
				spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
				return;
			}
			ch->ch_flags |= CH_FLIPBUF_IN_USE;
			buf = ch->ch_bd->flipbuf;
			buf2 = NULL;
	if (!ld) {
		len = 0;
	} else {
			buf = tp->flip.char_buf;
			buf2 = tp->flip.flag_buf;
		/*
		 * If ld doesn't have a pointer to a receive_buf function,
		 * flush the data, then act like the ld doesn't have any
		 * space to put the data right now.
		 */
		if (!ld->receive_buf) {
				ch->ch_r_head = ch->ch_r_tail;
				len = 0;
		}
	} else {
		buf = tp->flip.char_buf_ptr;
		buf2 = tp->flip.flag_buf_ptr;
	}

	if (len <= 0) {
		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
		if (ld)
			tty_ldisc_deref(ld);
		return;
	}

	len = tty_buffer_request_room(tp, len);
	n = len;

	/*
@@ -638,121 +634,47 @@ void jsm_input(struct jsm_channel *ch)
		if (s <= 0)
			break;

		memcpy(buf, ch->ch_rqueue + tail, s);

		/* buf2 is only set when port isn't raw */
		if (buf2)
			memcpy(buf2, ch->ch_equeue + tail, s);

		tail += s;
		buf += s;
		if (buf2)
			buf2 += s;
		n -= s;
		/* Flip queue if needed */
		tail &= rmask;
	}

			/*
	 * In high performance mode, we don't have to update
	 * flag_buf or any of the counts or pointers into flip buf.
			 * If conditions are such that ld needs to see all
			 * UART errors, we will have to walk each character
			 * and error byte and send them to the buffer one at
			 * a time.
			 */
	if (!jsm_rawreadok) {

		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
			for (i = 0; i < len; i++) {
			for (i = 0; i < s; i++) {
				/*
				 * Give the Linux ld the flags in the
				 * format it likes.
				 */
				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
				if (*(ch->ch_equeue +tail +i) & UART_LSR_BI)
					tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i),  TTY_BREAK);
				else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
					tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY);
				else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
					tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME);
				else
					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
				tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
			}
		} else {
			memset(tp->flip.flag_buf_ptr, 0, len);
		}

		tp->flip.char_buf_ptr += len;
		tp->flip.flag_buf_ptr += len;
		tp->flip.count += len;
	}
	else if (!tp->real_raw) {
		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
			for (i = 0; i < len; i++) {
				/*
				 * Give the Linux ld the flags in the
				 * format it likes.
				 */
				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
				else
					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
			tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
		}
		} else
			memset(tp->flip.flag_buf, 0, len);
		tail += s;
		n -= s;
		/* Flip queue if needed */
		tail &= rmask;
	}

	/*
	 * If we're doing raw reads, jam it right into the
	 * line disc bypassing the flip buffers.
	 */
	if (jsm_rawreadok) {
		if (tp->real_raw) {
	ch->ch_r_tail = tail & rmask;
	ch->ch_e_tail = tail & rmask;

	jsm_check_queue_flow_control(ch);

			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */

	spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
				"jsm_input. %d real_raw len:%d calling receive_buf for board %d\n",
				__LINE__, len, ch->ch_bd->boardnum);
			tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
	/* Tell the tty layer its okay to "eat" the data now */
	tty_flip_buffer_push(tp);

			/* Allow use of channel flip buffer again */
			spin_lock_irqsave(&ch->ch_lock, lock_flags);
			ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

		} else {
			ch->ch_r_tail = tail & rmask;
			ch->ch_e_tail = tail & rmask;

			jsm_check_queue_flow_control(ch);

			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
				"jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n",
				__LINE__, len, ch->ch_bd->boardnum);

			tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len);
		}
	} else {
		ch->ch_r_tail = tail & rmask;
		ch->ch_e_tail = tail & rmask;

		jsm_check_queue_flow_control(ch);

		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);

		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
			"jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__);
		tty_schedule_flip(tp);
	}
	if (ld)
		tty_ldisc_deref(ld);

	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
}