[PATCH] jsm: update for tty buffering revamp
authorV. Ananda Krishnan <mansarov@us.ibm.com>
Fri, 3 Feb 2006 11:04:30 +0000 (03:04 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 3 Feb 2006 16:32:07 +0000 (08:32 -0800)
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>
drivers/serial/Kconfig
drivers/serial/jsm/jsm_tty.c

index 0d38f0f2ae2975d41f08fa059ab796385be2e71e..ee4265d7a8c9d9130b96293b980cb0dc21e3e17f 100644 (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>.
-
-          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"
index 6fa0d62d6f686269eadf52abacf56e516f7be3f8..07bf28ca330237db27d31b616d010e680fbc645b 100644 (file)
  *
  * 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");
 }