[PATCH] jsm: update for tty buffering revamp

Signed-off-by: V. Ananda Krishnan <mansarov@us.ibm.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
V. Ananda Krishnan 2006-02-03 03:04:30 -08:00 committed by Linus Torvalds
parent 7d95c8f27d
commit 0a577ce34f
2 changed files with 83 additions and 161 deletions

View File

@ -892,20 +892,20 @@ config SERIAL_VR41XX_CONSOLE
a console on a serial port, say Y. Otherwise, say N.
config SERIAL_JSM
tristate "Digi International NEO PCI Support"
depends on PCI && BROKEN
select SERIAL_CORE
help
This is a driver for Digi International's Neo series
of cards which provide multiple serial ports. You would need
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
supports PCI boards only.
If you have a card like this, say Y here and read the file
<file:Documentation/jsm.txt>.
tristate "Digi International NEO PCI Support"
depends on PCI
select SERIAL_CORE
help
This is a driver for Digi International's Neo series
of cards which provide multiple serial ports. You would need
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
supports PCI boards only.
If you have a card like this, say Y here and read the file
<file:Documentation/jsm.txt>.
To compile this driver as a module, choose M here: the
module will be called jsm.
To compile this driver as a module, choose M here: the
module will be called jsm.
config SERIAL_SGI_IOC4
tristate "SGI IOC4 controller serial support"

View File

@ -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 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 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 (!ld) {
len = 0;
} else {
/*
* 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;
}
/*
* If we're bypassing flip buffers on rx, we can blast it
* right into the beginning of the buffer.
*/
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;
} else {
buf = tp->flip.char_buf;
buf2 = tp->flip.flag_buf;
}
} else {
buf = tp->flip.char_buf_ptr;
buf2 = tp->flip.flag_buf_ptr;
}
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);
/*
* 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 (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
for (i = 0; i < s; i++) {
/*
* Give the Linux ld the flags in the
* format it likes.
*/
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
tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
}
} else {
tty_insert_flip_string(tp, ch->ch_rqueue + 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 (!jsm_rawreadok) {
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_ptr, 0, len);
}
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);
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;
}
} else
memset(tp->flip.flag_buf, 0, len);
}
/* Tell the tty layer its okay to "eat" the data now */
tty_flip_buffer_push(tp);
/*
* 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);
/* 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");
}