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

[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
...@@ -892,20 +892,20 @@ config SERIAL_VR41XX_CONSOLE ...@@ -892,20 +892,20 @@ config SERIAL_VR41XX_CONSOLE
a console on a serial port, say Y. Otherwise, say N. a console on a serial port, say Y. Otherwise, say N.
config SERIAL_JSM config SERIAL_JSM
tristate "Digi International NEO PCI Support" tristate "Digi International NEO PCI Support"
depends on PCI && BROKEN depends on PCI
select SERIAL_CORE select SERIAL_CORE
help help
This is a driver for Digi International's Neo series This is a driver for Digi International's Neo series
of cards which provide multiple serial ports. You would need of cards which provide multiple serial ports. You would need
something like this to connect more than two modems to your Linux something like this to connect more than two modems to your Linux
box, for instance in order to become a dial-in server. This driver box, for instance in order to become a dial-in server. This driver
supports PCI boards only. supports PCI boards only.
If you have a card like this, say Y here and read the file If you have a card like this, say Y here and read the file
<file:Documentation/jsm.txt>. <file:Documentation/jsm.txt>.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called jsm. module will be called jsm.
config SERIAL_SGI_IOC4 config SERIAL_SGI_IOC4
tristate "SGI IOC4 controller serial support" tristate "SGI IOC4 controller serial support"
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
* *
* Contact Information: * Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com> * 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.h>
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
...@@ -497,16 +499,16 @@ void jsm_input(struct jsm_channel *ch) ...@@ -497,16 +499,16 @@ void jsm_input(struct jsm_channel *ch)
{ {
struct jsm_board *bd; struct jsm_board *bd;
struct tty_struct *tp; struct tty_struct *tp;
struct tty_ldisc *ld;
u32 rmask; u32 rmask;
u16 head; u16 head;
u16 tail; u16 tail;
int data_len; int data_len;
unsigned long lock_flags; unsigned long lock_flags;
int flip_len; int flip_len = 0;
int len = 0; int len = 0;
int n = 0; int n = 0;
char *buf = NULL; char *buf = NULL;
char *buf2 = NULL;
int s = 0; int s = 0;
int i = 0; int i = 0;
...@@ -574,56 +576,50 @@ void jsm_input(struct jsm_channel *ch) ...@@ -574,56 +576,50 @@ void jsm_input(struct jsm_channel *ch)
/* /*
* If the rxbuf is empty and we are not throttled, put as much * If the rxbuf is empty and we are not throttled, put as much
* as we can directly into the linux TTY flip buffer. * as we can directly into the linux TTY 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.
* *
* 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) { flip_len = TTY_FLIPBUF_SIZE;
if (tp->real_raw)
flip_len = MYFLIPLEN;
else
flip_len = 2 * TTY_FLIPBUF_SIZE;
} else
flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;
len = min(data_len, flip_len); len = min(data_len, flip_len);
len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); 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); * If the DONT_FLIP flag is on, don't flush our buffer, and act
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); * like the ld doesn't have any space to put the data right now.
return; */
} if (test_bit(TTY_DONT_FLIP, &tp->flags))
len = 0;
/* /*
* If we're bypassing flip buffers on rx, we can blast it * If we were unable to get a reference to the ld,
* right into the beginning of the buffer. * 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 (!ld) {
if (tp->real_raw) { len = 0;
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;
} else {
buf = tp->flip.char_buf;
buf2 = tp->flip.flag_buf;
}
} else { } else {
buf = tp->flip.char_buf_ptr; /*
buf2 = tp->flip.flag_buf_ptr; * 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;
}
} }
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; n = len;
/* /*
...@@ -638,121 +634,47 @@ void jsm_input(struct jsm_channel *ch) ...@@ -638,121 +634,47 @@ void jsm_input(struct jsm_channel *ch)
if (s <= 0) if (s <= 0)
break; break;
memcpy(buf, ch->ch_rqueue + tail, s); /*
* If conditions are such that ld needs to see all
/* buf2 is only set when port isn't raw */ * UART errors, we will have to walk each character
if (buf2) * and error byte and send them to the buffer one at
memcpy(buf2, ch->ch_equeue + tail, s); * a time.
*/
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 (!jsm_rawreadok) {
if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { 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 * Give the Linux ld the flags in the
* format it likes. * format it likes.
*/ */
if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) if (*(ch->ch_equeue +tail +i) & UART_LSR_BI)
tp->flip.flag_buf_ptr[i] = TTY_BREAK; tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK);
else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
tp->flip.flag_buf_ptr[i] = TTY_PARITY; tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY);
else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
tp->flip.flag_buf_ptr[i] = TTY_FRAME; tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME);
else else
tp->flip.flag_buf_ptr[i] = TTY_NORMAL; tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
} }
} else { } else {
memset(tp->flip.flag_buf_ptr, 0, len); tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
} }
tail += s;
tp->flip.char_buf_ptr += len; n -= s;
tp->flip.flag_buf_ptr += len; /* Flip queue if needed */
tp->flip.count += len; tail &= rmask;
}
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;
}
} else
memset(tp->flip.flag_buf, 0, len);
} }
/* ch->ch_r_tail = tail & rmask;
* If we're doing raw reads, jam it right into the ch->ch_e_tail = tail & rmask;
* line disc bypassing the flip buffers. jsm_check_queue_flow_control(ch);
*/ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
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); /* Tell the tty layer its okay to "eat" the data now */
tty_flip_buffer_push(tp);
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, if (ld)
"jsm_input. %d real_raw len:%d calling receive_buf for board %d\n", tty_ldisc_deref(ld);
__LINE__, len, ch->ch_bd->boardnum);
tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
/* 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);
}
jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment