提交 0a577ce3 编写于 作者: V V. Ananda Krishnan 提交者: Linus Torvalds

[PATCH] jsm: update for tty buffering revamp

Signed-off-by: NV. Ananda Krishnan <mansarov@us.ibm.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 7d95c8f2
......@@ -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>.
To compile this driver as a module, choose M here: the
module will be called jsm.
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.
config SERIAL_SGI_IOC4
tristate "SGI IOC4 controller serial support"
......
......@@ -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;
} else {
buf = tp->flip.char_buf;
buf2 = tp->flip.flag_buf;
}
if (!ld) {
len = 0;
} 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;
/*
......@@ -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;
}
/*
* 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.
*/
/*
* 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++) {
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);
tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ;
}
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);
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 !!! */
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);
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,
"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");
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册