]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 28 Aug 2010 20:55:31 +0000 (13:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 28 Aug 2010 20:55:31 +0000 (13:55 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: pxa27x_keypad - remove input_free_device() in pxa27x_keypad_remove()
  Input: mousedev - fix regression of inverting axes
  Input: uinput - add devname alias to allow module on-demand load
  Input: hil_kbd - fix compile error
  USB: drop tty argument from usb_serial_handle_sysrq_char()
  Input: sysrq - drop tty argument form handle_sysrq()
  Input: sysrq - drop tty argument from sysrq ops handlers

1  2 
arch/sparc/kernel/process_64.c
drivers/gpu/drm/drm_fb_helper.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/generic.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/ssu100.c

index 485f547483847da14aebfaa0e327c6cbb75dce24,25b01b43b40d6f9ccb9aa4f9b797bc7726b8de14..c158a95ec664f1301d78ceb433d99a1c94098dbc
@@@ -303,7 -303,7 +303,7 @@@ void arch_trigger_all_cpu_backtrace(voi
  
  #ifdef CONFIG_MAGIC_SYSRQ
  
- static void sysrq_handle_globreg(int key, struct tty_struct *tty)
+ static void sysrq_handle_globreg(int key)
  {
        arch_trigger_all_cpu_backtrace();
  }
@@@ -739,9 -739,9 +739,9 @@@ asmlinkage int sparc_execve(struct pt_r
        if (IS_ERR(filename))
                goto out;
        error = do_execve(filename,
 -                        (char __user * __user *)
 +                        (const char __user *const __user *)
                          regs->u_regs[base + UREG_I1],
 -                        (char __user * __user *)
 +                        (const char __user *const __user *)
                          regs->u_regs[base + UREG_I2], regs);
        putname(filename);
        if (!error) {
index 8dd7e6f86bb3a40de79daf112bdcd0d6218187f7,5efd6d6742ec8e3a8e43729678eba7513cd33129..6a5e403f9aa160b54caad1bca22ba93dd27415e6
@@@ -94,11 -94,10 +94,11 @@@ static bool drm_fb_helper_connector_par
        int i;
        enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
        struct drm_fb_helper_cmdline_mode *cmdline_mode;
 -      struct drm_connector *connector = fb_helper_conn->connector;
 +      struct drm_connector *connector;
  
        if (!fb_helper_conn)
                return false;
 +      connector = fb_helper_conn->connector;
  
        cmdline_mode = &fb_helper_conn->cmdline_mode;
        if (!mode_option)
@@@ -370,7 -369,7 +370,7 @@@ static void drm_fb_helper_restore_work_
  }
  static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
  
- static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3)
+ static void drm_fb_helper_sysrq(int dummy1)
  {
        schedule_work(&drm_fb_helper_restore_work);
  }
index 63ddb2f65ceee774150090c8a42c9b83bc947dd3,5d47983b533cca2c21d800f6a44767c657c219de..c792c96f590e80918221c78caf7227e60ececaa1
@@@ -180,7 -180,6 +180,7 @@@ static struct usb_device_id id_table_co
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
 +      { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
        { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
 +      { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID),
 +              .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
  };
@@@ -1379,7 -1376,7 +1379,7 @@@ static void ftdi_set_max_packet_size(st
        }
  
        /* set max packet size based on descriptor */
 -      priv->max_packet_size = ep_desc->wMaxPacketSize;
 +      priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize);
  
        dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
  }
@@@ -1834,7 -1831,7 +1834,7 @@@ static int ftdi_process_packet(struct t
  
        if (port->port.console && port->sysrq) {
                for (i = 0; i < len; i++, ch++) {
-                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                       if (!usb_serial_handle_sysrq_char(port, *ch))
                                tty_insert_flip_char(tty, *ch, flag);
                }
        } else {
index 0b1a13384c6d96766b937b197d6fb55517282932,1abe34c38c08f3a4d5698e70ee9fb6ae683d4440..e6833e216fc9fa4e3628813d57f14891835caf6a
@@@ -343,7 -343,7 +343,7 @@@ void usb_serial_generic_process_read_ur
                tty_insert_flip_string(tty, ch, urb->actual_length);
        else {
                for (i = 0; i < urb->actual_length; i++, ch++) {
-                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                       if (!usb_serial_handle_sysrq_char(port, *ch))
                                tty_insert_flip_char(tty, *ch, TTY_NORMAL);
                }
        }
@@@ -448,12 -448,11 +448,11 @@@ void usb_serial_generic_unthrottle(stru
  EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
  
  #ifdef CONFIG_MAGIC_SYSRQ
- int usb_serial_handle_sysrq_char(struct tty_struct *tty,
-                       struct usb_serial_port *port, unsigned int ch)
+ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
  {
        if (port->sysrq && port->port.console) {
                if (ch && time_before(jiffies, port->sysrq)) {
-                       handle_sysrq(ch, tty);
+                       handle_sysrq(ch);
                        port->sysrq = 0;
                        return 1;
                }
        return 0;
  }
  #else
- int usb_serial_handle_sysrq_char(struct tty_struct *tty,
-                       struct usb_serial_port *port, unsigned int ch)
+ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
  {
        return 0;
  }
@@@ -518,7 -516,6 +516,7 @@@ void usb_serial_generic_disconnect(stru
        for (i = 0; i < serial->num_ports; ++i)
                generic_cleanup(serial->port[i]);
  }
 +EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
  
  void usb_serial_generic_release(struct usb_serial *serial)
  {
index c98f0fb675bac35d25f29c636b83e81af1d2a2af,34ad7b3d594880f0f494e3a0d0ccd4bb1980f2d9..8ae4c6cbc38a04ea250d43aad68aa43081098245
@@@ -86,7 -86,6 +86,7 @@@ static const struct usb_device_id id_ta
        { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
        { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
        { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
 +      { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
        { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
        { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
        { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
@@@ -789,7 -788,7 +789,7 @@@ static void pl2303_process_read_urb(str
  
        if (port->port.console && port->sysrq) {
                for (i = 0; i < urb->actual_length; ++i)
-                       if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
+                       if (!usb_serial_handle_sysrq_char(port, data[i]))
                                tty_insert_flip_char(tty, data[i], tty_flag);
        } else {
                tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
index 660c31f1499999e7def7e0644fc0b0f0a9859ddf,819de4740388a13e408068b4349a920f01771a79..68c18fdfc6da320978f9212325fd3f1ecf2ec64c
@@@ -15,7 -15,6 +15,7 @@@
  #include <linux/serial.h>
  #include <linux/usb.h>
  #include <linux/usb/serial.h>
 +#include <linux/serial_reg.h>
  #include <linux/uaccess.h>
  
  #define QT_OPEN_CLOSE_CHANNEL       0xca
  #define QT_HW_FLOW_CONTROL_MASK     0xc5
  #define QT_SW_FLOW_CONTROL_MASK     0xc6
  
 -#define MODEM_CTL_REGISTER         0x04
 -#define MODEM_STATUS_REGISTER      0x06
 -
 -
 -#define SERIAL_LSR_OE       0x02
 -#define SERIAL_LSR_PE       0x04
 -#define SERIAL_LSR_FE       0x08
 -#define SERIAL_LSR_BI       0x10
 -
 -#define SERIAL_LSR_TEMT     0x40
 -
 -#define  SERIAL_MCR_DTR             0x01
 -#define  SERIAL_MCR_RTS             0x02
 -#define  SERIAL_MCR_LOOP            0x10
 -
 -#define  SERIAL_MSR_CTS             0x10
 -#define  SERIAL_MSR_CD              0x80
 -#define  SERIAL_MSR_RI              0x40
 -#define  SERIAL_MSR_DSR             0x20
  #define  SERIAL_MSR_MASK            0xf0
  
 -#define  SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS)
 +#define  SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
  
 -#define  SERIAL_8_DATA              0x03
 -#define  SERIAL_7_DATA              0x02
 -#define  SERIAL_6_DATA              0x01
 -#define  SERIAL_5_DATA              0x00
 -
 -#define  SERIAL_ODD_PARITY          0X08
 -#define  SERIAL_EVEN_PARITY         0X18
 +#define  SERIAL_EVEN_PARITY         (UART_LCR_PARITY | UART_LCR_EPAR)
  
  #define  MAX_BAUD_RATE              460800
  
@@@ -75,12 -99,10 +75,12 @@@ static struct usb_driver ssu100_driver 
  };
  
  struct ssu100_port_private {
 +      spinlock_t status_lock;
        u8 shadowLSR;
        u8 shadowMSR;
        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
        unsigned short max_packet_size;
 +      struct async_icount icount;
  };
  
  static void ssu100_release(struct usb_serial *serial)
@@@ -128,10 -150,9 +128,10 @@@ static inline int ssu100_getregister(st
  
  static inline int ssu100_setregister(struct usb_device *dev,
                                     unsigned short uart,
 +                                   unsigned short reg,
                                     u16 data)
  {
 -      u16 value = (data << 8) | MODEM_CTL_REGISTER;
 +      u16 value = (data << 8) | reg;
  
        return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                               QT_SET_GET_REGISTER, 0x40, value, uart,
@@@ -157,11 -178,11 +157,11 @@@ static inline int update_mctrl(struct u
        clear &= ~set;  /* 'set' takes precedence over 'clear' */
        urb_value = 0;
        if (set & TIOCM_DTR)
 -              urb_value |= SERIAL_MCR_DTR;
 +              urb_value |= UART_MCR_DTR;
        if (set & TIOCM_RTS)
 -              urb_value |= SERIAL_MCR_RTS;
 +              urb_value |= UART_MCR_RTS;
  
 -      result = ssu100_setregister(dev, 0, urb_value);
 +      result = ssu100_setregister(dev, 0, UART_MCR, urb_value);
        if (result < 0)
                dbg("%s Error from MODEM_CTRL urb", __func__);
  
@@@ -243,24 -264,24 +243,24 @@@ static void ssu100_set_termios(struct t
  
        if (cflag & PARENB) {
                if (cflag & PARODD)
 -                      urb_value |= SERIAL_ODD_PARITY;
 +                      urb_value |= UART_LCR_PARITY;
                else
                        urb_value |= SERIAL_EVEN_PARITY;
        }
  
        switch (cflag & CSIZE) {
        case CS5:
 -              urb_value |= SERIAL_5_DATA;
 +              urb_value |= UART_LCR_WLEN5;
                break;
        case CS6:
 -              urb_value |= SERIAL_6_DATA;
 +              urb_value |= UART_LCR_WLEN6;
                break;
        case CS7:
 -              urb_value |= SERIAL_7_DATA;
 +              urb_value |= UART_LCR_WLEN7;
                break;
        default:
        case CS8:
 -              urb_value |= SERIAL_8_DATA;
 +              urb_value |= UART_LCR_WLEN8;
                break;
        }
  
@@@ -312,7 -333,6 +312,7 @@@ static int ssu100_open(struct tty_struc
        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
        u8 *data;
        int result;
 +      unsigned long flags;
  
        dbg("%s - port %d", __func__, port->number);
  
                return result;
        }
  
 -      priv->shadowLSR = data[0]  & (SERIAL_LSR_OE | SERIAL_LSR_PE |
 -                                    SERIAL_LSR_FE | SERIAL_LSR_BI);
 -
 -      priv->shadowMSR = data[1]  & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
 -                                    SERIAL_MSR_RI | SERIAL_MSR_CD);
 +      spin_lock_irqsave(&priv->status_lock, flags);
 +      priv->shadowLSR = data[0];
 +      priv->shadowMSR = data[1];
 +      spin_unlock_irqrestore(&priv->status_lock, flags);
  
        kfree(data);
  
@@@ -377,51 -398,11 +377,51 @@@ static int get_serial_info(struct usb_s
        return 0;
  }
  
 +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 +{
 +      struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 +      struct async_icount prev, cur;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&priv->status_lock, flags);
 +      prev = priv->icount;
 +      spin_unlock_irqrestore(&priv->status_lock, flags);
 +
 +      while (1) {
 +              wait_event_interruptible(priv->delta_msr_wait,
 +                                       ((priv->icount.rng != prev.rng) ||
 +                                        (priv->icount.dsr != prev.dsr) ||
 +                                        (priv->icount.dcd != prev.dcd) ||
 +                                        (priv->icount.cts != prev.cts)));
 +
 +              if (signal_pending(current))
 +                      return -ERESTARTSYS;
 +
 +              spin_lock_irqsave(&priv->status_lock, flags);
 +              cur = priv->icount;
 +              spin_unlock_irqrestore(&priv->status_lock, flags);
 +
 +              if ((prev.rng == cur.rng) &&
 +                  (prev.dsr == cur.dsr) &&
 +                  (prev.dcd == cur.dcd) &&
 +                  (prev.cts == cur.cts))
 +                      return -EIO;
 +
 +              if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
 +                  (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
 +                  (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) ||
 +                  (arg & TIOCM_CTS && (prev.cts != cur.cts)))
 +                      return 0;
 +      }
 +      return 0;
 +}
 +
  static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
                    unsigned int cmd, unsigned long arg)
  {
        struct usb_serial_port *port = tty->driver_data;
        struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 +      void __user *user_arg = (void __user *)arg;
  
        dbg("%s cmd 0x%04x", __func__, cmd);
  
                                       (struct serial_struct __user *) arg);
  
        case TIOCMIWAIT:
 -              while (priv != NULL) {
 -                      u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK;
 -                      interruptible_sleep_on(&priv->delta_msr_wait);
 -                      /* see if a signal did it */
 -                      if (signal_pending(current))
 -                              return -ERESTARTSYS;
 -                      else {
 -                              u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR;
 -                              if (!diff)
 -                                      return -EIO; /* no change => error */
 -
 -                              /* Return 0 if caller wanted to know about
 -                                 these bits */
 -
 -                              if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) ||
 -                                  ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) ||
 -                                  ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) ||
 -                                  ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS)))
 -                                      return 0;
 -                      }
 -              }
 +              return wait_modem_info(port, arg);
 +
 +      case TIOCGICOUNT:
 +      {
 +              struct serial_icounter_struct icount;
 +              struct async_icount cnow = priv->icount;
 +              memset(&icount, 0, sizeof(icount));
 +              icount.cts = cnow.cts;
 +              icount.dsr = cnow.dsr;
 +              icount.rng = cnow.rng;
 +              icount.dcd = cnow.dcd;
 +              icount.rx = cnow.rx;
 +              icount.tx = cnow.tx;
 +              icount.frame = cnow.frame;
 +              icount.overrun = cnow.overrun;
 +              icount.parity = cnow.parity;
 +              icount.brk = cnow.brk;
 +              icount.buf_overrun = cnow.buf_overrun;
 +              if (copy_to_user(user_arg, &icount, sizeof(icount)))
 +                      return -EFAULT;
                return 0;
 +      }
  
        default:
                break;
@@@ -474,7 -455,6 +474,7 @@@ static void ssu100_set_max_packet_size(
  
        unsigned num_endpoints;
        int i;
 +      unsigned long flags;
  
        num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
        dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
        }
  
        /* set max packet size based on descriptor */
 +      spin_lock_irqsave(&priv->status_lock, flags);
        priv->max_packet_size = ep_desc->wMaxPacketSize;
 +      spin_unlock_irqrestore(&priv->status_lock, flags);
  
        dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
  }
@@@ -507,9 -485,9 +507,9 @@@ static int ssu100_attach(struct usb_ser
                return -ENOMEM;
        }
  
 +      spin_lock_init(&priv->status_lock);
        init_waitqueue_head(&priv->delta_msr_wait);
        usb_set_serial_port_data(port, priv);
 -
        ssu100_set_max_packet_size(port);
  
        return ssu100_initdevice(serial->dev);
@@@ -528,20 -506,20 +528,20 @@@ static int ssu100_tiocmget(struct tty_s
        if (!d)
                return -ENOMEM;
  
 -      r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d);
 +      r = ssu100_getregister(dev, 0, UART_MCR, d);
        if (r < 0)
                goto mget_out;
  
 -      r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1);
 +      r = ssu100_getregister(dev, 0, UART_MSR, d+1);
        if (r < 0)
                goto mget_out;
  
 -      r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) |
 -              (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) |
 -              (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) |
 -              (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) |
 -              (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) |
 -              (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0);
 +      r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
 +              (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
 +              (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
 +              (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
 +              (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
 +              (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
  
  mget_out:
        kfree(d);
@@@ -568,7 -546,7 +568,7 @@@ static void ssu100_dtr_rts(struct usb_s
        if (!port->serial->disconnected) {
                /* Disable flow control */
                if (!on &&
 -                  ssu100_setregister(dev, 0, 0) < 0)
 +                  ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
                        dev_err(&port->dev, "error from flowcontrol urb\n");
                /* drop RTS and DTR */
                if (on)
        mutex_unlock(&port->serial->disc_mutex);
  }
  
 +static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
 +{
 +      struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&priv->status_lock, flags);
 +      priv->shadowMSR = msr;
 +      spin_unlock_irqrestore(&priv->status_lock, flags);
 +
 +      if (msr & UART_MSR_ANY_DELTA) {
 +              /* update input line counters */
 +              if (msr & UART_MSR_DCTS)
 +                      priv->icount.cts++;
 +              if (msr & UART_MSR_DDSR)
 +                      priv->icount.dsr++;
 +              if (msr & UART_MSR_DDCD)
 +                      priv->icount.dcd++;
 +              if (msr & UART_MSR_TERI)
 +                      priv->icount.rng++;
 +              wake_up_interruptible(&priv->delta_msr_wait);
 +      }
 +}
 +
 +static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
 +                            char *tty_flag)
 +{
 +      struct ssu100_port_private *priv = usb_get_serial_port_data(port);
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&priv->status_lock, flags);
 +      priv->shadowLSR = lsr;
 +      spin_unlock_irqrestore(&priv->status_lock, flags);
 +
 +      *tty_flag = TTY_NORMAL;
 +      if (lsr & UART_LSR_BRK_ERROR_BITS) {
 +              /* we always want to update icount, but we only want to
 +               * update tty_flag for one case */
 +              if (lsr & UART_LSR_BI) {
 +                      priv->icount.brk++;
 +                      *tty_flag = TTY_BREAK;
 +                      usb_serial_handle_break(port);
 +              }
 +              if (lsr & UART_LSR_PE) {
 +                      priv->icount.parity++;
 +                      if (*tty_flag == TTY_NORMAL)
 +                              *tty_flag = TTY_PARITY;
 +              }
 +              if (lsr & UART_LSR_FE) {
 +                      priv->icount.frame++;
 +                      if (*tty_flag == TTY_NORMAL)
 +                              *tty_flag = TTY_FRAME;
 +              }
 +              if (lsr & UART_LSR_OE){
 +                      priv->icount.overrun++;
 +                      if (*tty_flag == TTY_NORMAL)
 +                              *tty_flag = TTY_OVERRUN;
 +              }
 +      }
 +
 +}
 +
  static int ssu100_process_packet(struct tty_struct *tty,
                                 struct usb_serial_port *port,
                                 struct ssu100_port_private *priv,
                                 char *packet, int len)
  {
        int i;
 -      char flag;
 +      char flag = TTY_NORMAL;
        char *ch;
  
        dbg("%s - port %d", __func__, port->number);
  
 -      if (len < 4) {
 -              dbg("%s - malformed packet", __func__);
 -              return 0;
 -      }
 -
 -      if ((packet[0] == 0x1b) && (packet[1] == 0x1b) &&
 +      if ((len >= 4) &&
 +          (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
            ((packet[2] == 0x00) || (packet[2] == 0x01))) {
 -              if (packet[2] == 0x00)
 -                      priv->shadowLSR = packet[3] & (SERIAL_LSR_OE |
 -                                                     SERIAL_LSR_PE |
 -                                                     SERIAL_LSR_FE |
 -                                                     SERIAL_LSR_BI);
 -
 -              if (packet[2] == 0x01) {
 -                      priv->shadowMSR = packet[3];
 -                      wake_up_interruptible(&priv->delta_msr_wait);
 +              if (packet[2] == 0x00) {
 +                      ssu100_update_lsr(port, packet[3], &flag);
 +                      if (flag == TTY_OVERRUN)
 +                              tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                }
 +              if (packet[2] == 0x01)
 +                      ssu100_update_msr(port, packet[3]);
  
                len -= 4;
                ch = packet + 4;
  
        if (port->port.console && port->sysrq) {
                for (i = 0; i < len; i++, ch++) {
-                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                       if (!usb_serial_handle_sysrq_char(port, *ch))
                                tty_insert_flip_char(tty, *ch, flag);
                }
        } else
@@@ -707,6 -631,7 +707,6 @@@ static void ssu100_process_read_urb(str
        tty_kref_put(tty);
  }
  
 -
  static struct usb_serial_driver ssu100_device = {
        .driver = {
                .owner = THIS_MODULE,
        .tiocmset            = ssu100_tiocmset,
        .ioctl               = ssu100_ioctl,
        .set_termios         = ssu100_set_termios,
 +      .disconnect          = usb_serial_generic_disconnect,
  };
  
  static int __init ssu100_init(void)