]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'usb-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 19:19:23 +0000 (12:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 19:19:23 +0000 (12:19 -0700)
Pull USB patches from Greg Kroah-Hartman:
 "Here's the big USB pull request for 3.10-rc1.

  Lots of USB patches here, the majority being USB gadget changes and
  USB-serial driver cleanups, the rest being ARM build fixes / cleanups,
  and individual driver updates.  We also finally got some chipidea
  fixes, which have been delayed for a number of kernel releases, as the
  maintainer has now reappeared.

  All of these have been in linux-next for a while"

* tag 'usb-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (568 commits)
  USB: ehci-msm: USB_MSM_OTG needs USB_PHY
  USB: OHCI: avoid conflicting platform drivers
  USB: OMAP: ISP1301 needs USB_PHY
  USB: lpc32xx: ISP1301 needs USB_PHY
  USB: ftdi_sio: enable two UART ports on ST Microconnect Lite
  usb: phy: tegra: don't call into tegra-ehci directly
  usb: phy: phy core cannot yet be a module
  USB: Fix initconst in ehci driver
  usb-storage: CY7C68300A chips do not support Cypress ATACB
  USB: serial: option: Added support Olivetti Olicard 145
  USB: ftdi_sio: correct ST Micro Connect Lite PIDs
  ARM: mxs_defconfig: add CONFIG_USB_PHY
  ARM: imx_v6_v7_defconfig: add CONFIG_USB_PHY
  usb: phy: remove exported function from __init section
  usb: gadget: zero: put function instances on unbind
  usb: gadget: f_sourcesink.c: correct a copy-paste misnomer
  usb: gadget: cdc2: fix error return code in cdc_do_config()
  usb: gadget: multi: fix error return code in rndis_do_config()
  usb: gadget: f_obex: fix error return code in obex_bind()
  USB: storage: convert to use module_usb_driver()
  ...

16 files changed:
1  2 
drivers/Makefile
drivers/net/usb/cdc_mbim.c
drivers/net/usb/qmi_wwan.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/usb.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c

diff --combined drivers/Makefile
index 4865ed24708ab8a6717cee2c2083cb08451678f5,3c200a243af0db5b51aa72d7b05345a1b09f8156..33360de63650b99f1771bdfccbcd4e3eaf01aea3
@@@ -79,7 -79,7 +79,7 @@@ obj-$(CONFIG_ATA_OVER_ETH)    += block/aoe
  obj-$(CONFIG_PARIDE)          += block/paride/
  obj-$(CONFIG_TC)              += tc/
  obj-$(CONFIG_UWB)             += uwb/
- obj-$(CONFIG_USB_OTG_UTILS)   += usb/
+ obj-$(CONFIG_USB_PHY)         += usb/
  obj-$(CONFIG_USB)             += usb/
  obj-$(CONFIG_PCI)             += usb/
  obj-$(CONFIG_USB_GADGET)      += usb/
@@@ -114,7 -114,6 +114,7 @@@ obj-y                              += firmware
  obj-$(CONFIG_CRYPTO)          += crypto/
  obj-$(CONFIG_SUPERH)          += sh/
  obj-$(CONFIG_ARCH_SHMOBILE)   += sh/
 +obj-$(CONFIG_SSBI)            += ssbi/
  ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
  obj-y                         += clocksource/
  endif
index 6bd91676d2cbb9a46b43108ae1fa994d4fca84f9,673e3624713e926256348d31a3b96778f7106a20..32a76059e7dae84b8c32ea7f08a2595e84c663f8
@@@ -134,7 -134,7 +134,7 @@@ static struct sk_buff *cdc_mbim_tx_fixu
                goto error;
  
        if (skb) {
 -              if (skb->len <= sizeof(ETH_HLEN))
 +              if (skb->len <= ETH_HLEN)
                        goto error;
  
                /* mapping VLANs to MBIM sessions:
@@@ -323,6 -323,11 +323,11 @@@ static int cdc_mbim_suspend(struct usb_
                goto error;
        }
  
+       /*
+        * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+        * in system sleep context, otherwise, the resume callback has
+        * to recover device from previous suspend failure.
+        */
        ret = usbnet_suspend(intf, message);
        if (ret < 0)
                goto error;
index 2a3579f679103da7864260f114f98419852eaecd,bdceb7411de3b2fb45e3a2f937e158f412deea5e..5a88e72090ce7d0709d024a8c4b1f8fc173063a9
@@@ -13,7 -13,6 +13,7 @@@
  #include <linux/module.h>
  #include <linux/netdevice.h>
  #include <linux/ethtool.h>
 +#include <linux/etherdevice.h>
  #include <linux/mii.h>
  #include <linux/usb.h>
  #include <linux/usb/cdc.h>
@@@ -53,96 -52,6 +53,96 @@@ struct qmi_wwan_state 
        struct usb_interface *data;
  };
  
 +/* default ethernet address used by the modem */
 +static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
 +
 +/* Make up an ethernet header if the packet doesn't have one.
 + *
 + * A firmware bug common among several devices cause them to send raw
 + * IP packets under some circumstances.  There is no way for the
 + * driver/host to know when this will happen.  And even when the bug
 + * hits, some packets will still arrive with an intact header.
 + *
 + * The supported devices are only capably of sending IPv4, IPv6 and
 + * ARP packets on a point-to-point link. Any packet with an ethernet
 + * header will have either our address or a broadcast/multicast
 + * address as destination.  ARP packets will always have a header.
 + *
 + * This means that this function will reliably add the appropriate
 + * header iff necessary, provided our hardware address does not start
 + * with 4 or 6.
 + *
 + * Another common firmware bug results in all packets being addressed
 + * to 00:a0:c6:00:00:00 despite the host address being different.
 + * This function will also fixup such packets.
 + */
 +static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 +{
 +      __be16 proto;
 +
 +      /* usbnet rx_complete guarantees that skb->len is at least
 +       * hard_header_len, so we can inspect the dest address without
 +       * checking skb->len
 +       */
 +      switch (skb->data[0] & 0xf0) {
 +      case 0x40:
 +              proto = htons(ETH_P_IP);
 +              break;
 +      case 0x60:
 +              proto = htons(ETH_P_IPV6);
 +              break;
 +      case 0x00:
 +              if (is_multicast_ether_addr(skb->data))
 +                      return 1;
 +              /* possibly bogus destination - rewrite just in case */
 +              skb_reset_mac_header(skb);
 +              goto fix_dest;
 +      default:
 +              /* pass along other packets without modifications */
 +              return 1;
 +      }
 +      if (skb_headroom(skb) < ETH_HLEN)
 +              return 0;
 +      skb_push(skb, ETH_HLEN);
 +      skb_reset_mac_header(skb);
 +      eth_hdr(skb)->h_proto = proto;
 +      memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
 +fix_dest:
 +      memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
 +      return 1;
 +}
 +
 +/* very simplistic detection of IPv4 or IPv6 headers */
 +static bool possibly_iphdr(const char *data)
 +{
 +      return (data[0] & 0xd0) == 0x40;
 +}
 +
 +/* disallow addresses which may be confused with IP headers */
 +static int qmi_wwan_mac_addr(struct net_device *dev, void *p)
 +{
 +      int ret;
 +      struct sockaddr *addr = p;
 +
 +      ret = eth_prepare_mac_addr_change(dev, p);
 +      if (ret < 0)
 +              return ret;
 +      if (possibly_iphdr(addr->sa_data))
 +              return -EADDRNOTAVAIL;
 +      eth_commit_mac_addr_change(dev, p);
 +      return 0;
 +}
 +
 +static const struct net_device_ops qmi_wwan_netdev_ops = {
 +      .ndo_open               = usbnet_open,
 +      .ndo_stop               = usbnet_stop,
 +      .ndo_start_xmit         = usbnet_start_xmit,
 +      .ndo_tx_timeout         = usbnet_tx_timeout,
 +      .ndo_change_mtu         = usbnet_change_mtu,
 +      .ndo_set_mac_address    = qmi_wwan_mac_addr,
 +      .ndo_validate_addr      = eth_validate_addr,
 +};
 +
  /* using a counter to merge subdriver requests with our own into a combined state */
  static int qmi_wwan_manage_power(struct usbnet *dev, int on)
  {
@@@ -320,18 -229,6 +320,18 @@@ next_desc
                usb_driver_release_interface(driver, info->data);
        }
  
 +      /* Never use the same address on both ends of the link, even
 +       * if the buggy firmware told us to.
 +       */
 +      if (!compare_ether_addr(dev->net->dev_addr, default_modem_addr))
 +              eth_hw_addr_random(dev->net);
 +
 +      /* make MAC addr easily distinguishable from an IP header */
 +      if (possibly_iphdr(dev->net->dev_addr)) {
 +              dev->net->dev_addr[0] |= 0x02;  /* set local assignment bit */
 +              dev->net->dev_addr[0] &= 0xbf;  /* clear "IP" bit */
 +      }
 +      dev->net->netdev_ops = &qmi_wwan_netdev_ops;
  err:
        return status;
  }
@@@ -374,6 -271,11 +374,11 @@@ static int qmi_wwan_suspend(struct usb_
        struct qmi_wwan_state *info = (void *)&dev->data;
        int ret;
  
+       /*
+        * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+        * in system sleep context, otherwise, the resume callback has
+        * to recover device from previous suspend failure.
+        */
        ret = usbnet_suspend(intf, message);
        if (ret < 0)
                goto err;
@@@ -410,7 -312,6 +415,7 @@@ static const struct driver_info    qmi_wwa
        .bind           = qmi_wwan_bind,
        .unbind         = qmi_wwan_unbind,
        .manage_power   = qmi_wwan_manage_power,
 +      .rx_fixup       = qmi_wwan_rx_fixup,
  };
  
  #define HUAWEI_VENDOR_ID      0x12D1
index c77f7ae48f1c1ed93260bea354e6c6b148a235f5,6d4e0b96f89d57f9c020c7d510c42899e9772262..171d7a9df3aedd31fe660b4a7fec2cb5f9e1e6d8
@@@ -292,6 -292,7 +292,6 @@@ static void acm_ctrl_irq(struct urb *ur
  {
        struct acm *acm = urb->context;
        struct usb_cdc_notification *dr = urb->transfer_buffer;
 -      struct tty_struct *tty;
        unsigned char *data;
        int newctrl;
        int retval;
                break;
  
        case USB_CDC_NOTIFY_SERIAL_STATE:
 -              tty = tty_port_tty_get(&acm->port);
                newctrl = get_unaligned_le16(data);
  
 -              if (tty) {
 -                      if (!acm->clocal &&
 -                              (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
 -                              dev_dbg(&acm->control->dev,
 -                                      "%s - calling hangup\n", __func__);
 -                              tty_hangup(tty);
 -                      }
 -                      tty_kref_put(tty);
 +              if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
 +                      dev_dbg(&acm->control->dev, "%s - calling hangup\n",
 +                                      __func__);
 +                      tty_port_tty_hangup(&acm->port, false);
                }
  
                acm->ctrlin = newctrl;
@@@ -469,10 -475,15 +469,10 @@@ static void acm_write_bulk(struct urb *
  static void acm_softint(struct work_struct *work)
  {
        struct acm *acm = container_of(work, struct acm, work);
 -      struct tty_struct *tty;
  
        dev_vdbg(&acm->data->dev, "%s\n", __func__);
  
 -      tty = tty_port_tty_get(&acm->port);
 -      if (!tty)
 -              return;
 -      tty_wakeup(tty);
 -      tty_kref_put(tty);
 +      tty_port_tty_wakeup(&acm->port);
  }
  
  /*
@@@ -828,14 -839,6 +828,6 @@@ static int acm_tty_ioctl(struct tty_str
        return rv;
  }
  
- static const __u32 acm_tty_speed[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600,
-       1200, 1800, 2400, 4800, 9600, 19200, 38400,
-       57600, 115200, 230400, 460800, 500000, 576000,
-       921600, 1000000, 1152000, 1500000, 2000000,
-       2500000, 3000000, 3500000, 4000000
- };
  static void acm_tty_set_termios(struct tty_struct *tty,
                                                struct ktermios *termios_old)
  {
@@@ -1508,9 -1511,15 +1500,9 @@@ err_out
  static int acm_reset_resume(struct usb_interface *intf)
  {
        struct acm *acm = usb_get_intfdata(intf);
 -      struct tty_struct *tty;
  
 -      if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
 -              tty = tty_port_tty_get(&acm->port);
 -              if (tty) {
 -                      tty_hangup(tty);
 -                      tty_kref_put(tty);
 -              }
 -      }
 +      if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
 +              tty_port_tty_hangup(&acm->port, false);
  
        return acm_resume(intf);
  }
diff --combined drivers/usb/core/usb.c
index e092b414dc50c776c2e9fab2f8247fe99a390359,03eb7ae8fc1a3401e580d78af7a2fee1c4fe9a93..b10da720f2b4d612385e778578a86b2562eb11ed
@@@ -49,7 -49,7 +49,7 @@@ const char *usbcore_name = "usbcore"
  
  static bool nousb;    /* Disable USB when built into kernel image */
  
- #ifdef        CONFIG_USB_SUSPEND
+ #ifdef        CONFIG_PM_RUNTIME
  static int usb_autosuspend_delay = 2;         /* Default delay value,
                                                 * in seconds */
  module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
@@@ -307,7 -307,7 +307,7 @@@ static const struct dev_pm_ops usb_devi
        .thaw =         usb_dev_thaw,
        .poweroff =     usb_dev_poweroff,
        .restore =      usb_dev_restore,
- #ifdef CONFIG_USB_SUSPEND
+ #ifdef CONFIG_PM_RUNTIME
        .runtime_suspend =      usb_runtime_suspend,
        .runtime_resume =       usb_runtime_resume,
        .runtime_idle =         usb_runtime_idle,
  #endif        /* CONFIG_PM */
  
  
 -static char *usb_devnode(struct device *dev, umode_t *mode)
 +static char *usb_devnode(struct device *dev,
 +                       umode_t *mode, kuid_t *uid, kgid_t *gid)
  {
        struct usb_device *usb_dev;
  
index 31191581060c94762c7265eb031e224ccb227713,32873b4064025b124960e45b1309ef5a47d24346..7b807d38952783b43854370590e0cc9db628ae49
@@@ -196,7 -196,6 +196,6 @@@ struct digi_port 
        unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
        int dp_write_urb_in_use;
        unsigned int dp_modem_signals;
-       wait_queue_head_t dp_modem_change_wait;
        int dp_transmit_idle;
        wait_queue_head_t dp_transmit_idle_wait;
        int dp_throttled;
  
  /* Local Function Declarations */
  
 -static void digi_wakeup_write(struct usb_serial_port *port);
  static void digi_wakeup_write_lock(struct work_struct *work);
  static int digi_write_oob_command(struct usb_serial_port *port,
        unsigned char *buf, int count, int interruptible);
@@@ -373,10 -373,20 +372,10 @@@ static void digi_wakeup_write_lock(stru
        unsigned long flags;
  
        spin_lock_irqsave(&priv->dp_port_lock, flags);
 -      digi_wakeup_write(port);
 +      tty_port_tty_wakeup(&port->port);
        spin_unlock_irqrestore(&priv->dp_port_lock, flags);
  }
  
 -static void digi_wakeup_write(struct usb_serial_port *port)
 -{
 -      struct tty_struct *tty = tty_port_tty_get(&port->port);
 -      if (tty) {
 -              tty_wakeup(tty);
 -              tty_kref_put(tty);
 -      }
 -}
 -
 -
  /*
   *  Digi Write OOB Command
   *
@@@ -1033,7 -1043,7 +1032,7 @@@ static void digi_write_bulk_callback(st
                }
        }
        /* wake up processes sleeping on writes immediately */
 -      digi_wakeup_write(port);
 +      tty_port_tty_wakeup(&port->port);
        /* also queue up a wakeup at scheduler time, in case we */
        /* lost the race in write_chan(). */
        schedule_work(&priv->dp_wakeup_work);
@@@ -1138,53 -1148,51 +1137,51 @@@ static void digi_close(struct usb_seria
        if (port->serial->disconnected)
                goto exit;
  
-       if (port->serial->dev) {
-               /* FIXME: Transmit idle belongs in the wait_unti_sent path */
-               digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-               /* disable input flow control */
-               buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
-               buf[1] = priv->dp_port_num;
-               buf[2] = DIGI_DISABLE;
-               buf[3] = 0;
-               /* disable output flow control */
-               buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
-               buf[5] = priv->dp_port_num;
-               buf[6] = DIGI_DISABLE;
-               buf[7] = 0;
-               /* disable reading modem signals automatically */
-               buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
-               buf[9] = priv->dp_port_num;
-               buf[10] = DIGI_DISABLE;
-               buf[11] = 0;
-               /* disable receive */
-               buf[12] = DIGI_CMD_RECEIVE_ENABLE;
-               buf[13] = priv->dp_port_num;
-               buf[14] = DIGI_DISABLE;
-               buf[15] = 0;
-               /* flush fifos */
-               buf[16] = DIGI_CMD_IFLUSH_FIFO;
-               buf[17] = priv->dp_port_num;
-               buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
-               buf[19] = 0;
-               ret = digi_write_oob_command(port, buf, 20, 0);
-               if (ret != 0)
-                       dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret);
-               /* wait for final commands on oob port to complete */
-               prepare_to_wait(&priv->dp_flush_wait, &wait,
-                                                       TASK_INTERRUPTIBLE);
-               schedule_timeout(DIGI_CLOSE_TIMEOUT);
-               finish_wait(&priv->dp_flush_wait, &wait);
-               /* shutdown any outstanding bulk writes */
-               usb_kill_urb(port->write_urb);
-       }
+       /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+       digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
+       /* disable input flow control */
+       buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+       buf[1] = priv->dp_port_num;
+       buf[2] = DIGI_DISABLE;
+       buf[3] = 0;
+       /* disable output flow control */
+       buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+       buf[5] = priv->dp_port_num;
+       buf[6] = DIGI_DISABLE;
+       buf[7] = 0;
+       /* disable reading modem signals automatically */
+       buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
+       buf[9] = priv->dp_port_num;
+       buf[10] = DIGI_DISABLE;
+       buf[11] = 0;
+       /* disable receive */
+       buf[12] = DIGI_CMD_RECEIVE_ENABLE;
+       buf[13] = priv->dp_port_num;
+       buf[14] = DIGI_DISABLE;
+       buf[15] = 0;
+       /* flush fifos */
+       buf[16] = DIGI_CMD_IFLUSH_FIFO;
+       buf[17] = priv->dp_port_num;
+       buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+       buf[19] = 0;
+       ret = digi_write_oob_command(port, buf, 20, 0);
+       if (ret != 0)
+               dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n",
+                                                                       ret);
+       /* wait for final commands on oob port to complete */
+       prepare_to_wait(&priv->dp_flush_wait, &wait,
+                       TASK_INTERRUPTIBLE);
+       schedule_timeout(DIGI_CLOSE_TIMEOUT);
+       finish_wait(&priv->dp_flush_wait, &wait);
+       /* shutdown any outstanding bulk writes */
+       usb_kill_urb(port->write_urb);
  exit:
        spin_lock_irq(&priv->dp_port_lock);
        priv->dp_write_urb_in_use = 0;
@@@ -1241,7 -1249,6 +1238,6 @@@ static int digi_port_init(struct usb_se
  
        spin_lock_init(&priv->dp_port_lock);
        priv->dp_port_num = port_num;
-       init_waitqueue_head(&priv->dp_modem_change_wait);
        init_waitqueue_head(&priv->dp_transmit_idle_wait);
        init_waitqueue_head(&priv->dp_flush_wait);
        init_waitqueue_head(&priv->dp_close_wait);
@@@ -1511,7 -1518,7 +1507,7 @@@ static int digi_read_oob_callback(struc
                                /* port must be open to use tty struct */
                                if (rts) {
                                        tty->hw_stopped = 0;
 -                                      digi_wakeup_write(port);
 +                                      tty_port_tty_wakeup(&port->port);
                                }
                        } else {
                                priv->dp_modem_signals &= ~TIOCM_CTS;
                        else
                                priv->dp_modem_signals &= ~TIOCM_CD;
  
-                       wake_up_interruptible(&priv->dp_modem_change_wait);
                        spin_unlock(&priv->dp_port_lock);
                } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
                        spin_lock(&priv->dp_port_lock);
index cf0b0a2f7b564ee854fa95fd30ced39e8d1a3d60,ff9a6ef8477f26b8c65da0366664debc38dea0fd..1477e8593476deb54a831e3169c00c42e705c50a
@@@ -111,7 -111,6 +111,6 @@@ struct edgeport_port 
        wait_queue_head_t       wait_open;              /* for handling sleeping while waiting for open to finish */
        wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
  
-       struct async_icount     icount;
        struct usb_serial_port  *port;                  /* loop back to the owner of this object */
  };
  
@@@ -215,8 -214,6 +214,6 @@@ static void edge_break(struct tty_struc
  static int  edge_tiocmget(struct tty_struct *tty);
  static int  edge_tiocmset(struct tty_struct *tty,
                                        unsigned int set, unsigned int clear);
- static int  edge_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount);
  static int  edge_startup(struct usb_serial *serial);
  static void edge_disconnect(struct usb_serial *serial);
  static void edge_release(struct usb_serial *serial);
@@@ -564,6 -561,7 +561,6 @@@ static void edge_interrupt_callback(str
        struct device *dev;
        struct edgeport_port *edge_port;
        struct usb_serial_port *port;
 -      struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int length = urb->actual_length;
        int bytes_avail;
  
                                        /* tell the tty driver that something
                                           has changed */
 -                                      tty = tty_port_tty_get(
 -                                              &edge_port->port->port);
 -                                      if (tty) {
 -                                              tty_wakeup(tty);
 -                                              tty_kref_put(tty);
 -                                      }
 +                                      tty_port_tty_wakeup(&edge_port->port->port);
                                        /* Since we have more credit, check
                                           if more data can be sent */
                                        send_more_port_data(edge_serial,
@@@ -731,6 -734,7 +728,6 @@@ static void edge_bulk_in_callback(struc
  static void edge_bulk_out_data_callback(struct urb *urb)
  {
        struct edgeport_port *edge_port = urb->context;
 -      struct tty_struct *tty;
        int status = urb->status;
  
        if (status) {
                        __func__, status);
        }
  
 -      tty = tty_port_tty_get(&edge_port->port->port);
 -
 -      if (tty && edge_port->open) {
 -              /* let the tty driver wakeup if it has a special
 -                 write_wakeup function */
 -              tty_wakeup(tty);
 -      }
 -      tty_kref_put(tty);
 +      if (edge_port->open)
 +              tty_port_tty_wakeup(&edge_port->port->port);
  
        /* Release the Write URB */
        edge_port->write_in_progress = false;
  static void edge_bulk_out_cmd_callback(struct urb *urb)
  {
        struct edgeport_port *edge_port = urb->context;
 -      struct tty_struct *tty;
        int status = urb->status;
  
        atomic_dec(&CmdUrbs);
                return;
        }
  
 -      /* Get pointer to tty */
 -      tty = tty_port_tty_get(&edge_port->port->port);
 -
        /* tell the tty driver that something has changed */
 -      if (tty && edge_port->open)
 -              tty_wakeup(tty);
 -      tty_kref_put(tty);
 +      if (edge_port->open)
 +              tty_port_tty_wakeup(&edge_port->port->port);
  
        /* we have completed the command */
        edge_port->commandPending = false;
@@@ -867,9 -882,6 +864,6 @@@ static int edge_open(struct tty_struct 
        init_waitqueue_head(&edge_port->wait_chase);
        init_waitqueue_head(&edge_port->wait_command);
  
-       /* initialize our icount structure */
-       memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
        /* initialize our port settings */
        edge_port->txCredits = 0;       /* Can't send any data yet */
        /* Must always set this bit to enable ints! */
@@@ -1296,7 -1308,7 +1290,7 @@@ static void send_more_port_data(struct 
  
        /* decrement the number of credits we have by the number we just sent */
        edge_port->txCredits -= count;
-       edge_port->icount.tx += count;
+       edge_port->port->icount.tx += count;
  
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
  
                /* revert the credits as something bad happened. */
                edge_port->txCredits += count;
-               edge_port->icount.tx -= count;
+               edge_port->port->icount.tx -= count;
        }
        dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",
                __func__, count, edge_port->txCredits, fifo->count);
@@@ -1570,31 -1582,6 +1564,6 @@@ static int edge_tiocmget(struct tty_str
        return result;
  }
  
- static int edge_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount)
- {
-       struct usb_serial_port *port = tty->driver_data;
-       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       cnow = edge_port->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;
-       dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               port->number, icount->rx, icount->tx);
-       return 0;
- }
  static int get_serial_info(struct edgeport_port *edge_port,
                                struct serial_struct __user *retinfo)
  {
@@@ -1631,8 -1618,6 +1600,6 @@@ static int edge_ioctl(struct tty_struc
        struct usb_serial_port *port = tty->driver_data;
        DEFINE_WAIT(wait);
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       struct async_icount cprev;
  
        dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
  
        case TIOCGSERIAL:
                dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__,  port->number);
                return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
-               cprev = edge_port->icount;
-               while (1) {
-                       prepare_to_wait(&port->delta_msr_wait,
-                                               &wait, TASK_INTERRUPTIBLE);
-                       schedule();
-                       finish_wait(&port->delta_msr_wait, &wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       if (port->serial->disconnected)
-                               return -EIO;
-                       cnow = edge_port->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
        }
        return -ENOIOCTLCMD;
  }
@@@ -1848,7 -1802,7 +1784,7 @@@ static void process_rcvd_data(struct ed
                                                edge_serial->rxPort);
                                        edge_tty_recv(edge_port->port, buffer,
                                                        rxLen);
-                                       edge_port->icount.rx += rxLen;
+                                       edge_port->port->icount.rx += rxLen;
                                }
                                buffer += rxLen;
                        }
@@@ -2024,7 -1978,7 +1960,7 @@@ static void handle_new_msr(struct edgep
  
        if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
                        EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
-               icount = &edge_port->icount;
+               icount = &edge_port->port->icount;
  
                /* update input line counters */
                if (newMsr & EDGEPORT_MSR_DELTA_CTS)
                        icount->dcd++;
                if (newMsr & EDGEPORT_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&edge_port->port->delta_msr_wait);
+               wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
        }
  
        /* Save the new modem status */
@@@ -2070,7 -2024,7 +2006,7 @@@ static void handle_new_lsr(struct edgep
                edge_tty_recv(edge_port->port, &data, 1);
  
        /* update input line counters */
-       icount = &edge_port->icount;
+       icount = &edge_port->port->icount;
        if (newLsr & LSR_BREAK)
                icount->brk++;
        if (newLsr & LSR_OVER_ERR)
index b011478d2e5f43cffc8923f3264d69d9a4facceb,025310bc358a929d9a02ec7300a9c3609f1d025e..eb30d7b01f3681bd00c7fe73827533a613f162b6
@@@ -378,6 -378,7 +378,6 @@@ static void        usa26_instat_callback(struc
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
 -      struct tty_struct                       *tty;
        int old_dcd_state, err;
        int status = urb->status;
  
        p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
  
 -      if (old_dcd_state != p_priv->dcd_state) {
 -              tty = tty_port_tty_get(&port->port);
 -              if (tty && !C_CLOCAL(tty))
 -                      tty_hangup(tty);
 -              tty_kref_put(tty);
 -      }
 +      if (old_dcd_state != p_priv->dcd_state)
 +              tty_port_tty_hangup(&port->port, true);
  
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -505,6 -510,7 +505,6 @@@ static void        usa28_instat_callback(struc
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
 -      struct tty_struct                       *tty;
        int old_dcd_state;
        int status = urb->status;
  
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
  
 -      if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
 -              tty = tty_port_tty_get(&port->port);
 -              if (tty && !C_CLOCAL(tty))
 -                      tty_hangup(tty);
 -              tty_kref_put(tty);
 -      }
 +      if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
 +              tty_port_tty_hangup(&port->port, true);
  
                /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -632,8 -642,12 +632,8 @@@ static void       usa49_instat_callback(struc
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
  
 -      if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
 -              struct tty_struct *tty = tty_port_tty_get(&port->port);
 -              if (tty && !C_CLOCAL(tty))
 -                      tty_hangup(tty);
 -              tty_kref_put(tty);
 -      }
 +      if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
 +              tty_port_tty_hangup(&port->port, true);
  
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -712,45 -726,45 +712,45 @@@ static void usa49wg_indat_callback(stru
        i = 0;
        len = 0;
  
-       if (urb->actual_length) {
-               while (i < urb->actual_length) {
+       while (i < urb->actual_length) {
  
-                       /* Check port number from message*/
-                       if (data[i] >= serial->num_ports) {
-                               dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
-                                       __func__, data[i]);
-                               return;
-                       }
-                       port = serial->port[data[i++]];
-                       len = data[i++];
+               /* Check port number from message */
+               if (data[i] >= serial->num_ports) {
+                       dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
+                               __func__, data[i]);
+                       return;
+               }
+               port = serial->port[data[i++]];
+               len = data[i++];
  
-                       /* 0x80 bit is error flag */
-                       if ((data[i] & 0x80) == 0) {
-                               /* no error on any byte */
-                               i++;
-                               for (x = 1; x < len ; ++x)
-                                       tty_insert_flip_char(&port->port,
-                                                       data[i++], 0);
-                       } else {
-                               /*
-                                * some bytes had errors, every byte has status
-                                */
-                               for (x = 0; x + 1 < len; x += 2) {
-                                       int stat = data[i], flag = 0;
-                                       if (stat & RXERROR_OVERRUN)
-                                               flag |= TTY_OVERRUN;
-                                       if (stat & RXERROR_FRAMING)
-                                               flag |= TTY_FRAME;
-                                       if (stat & RXERROR_PARITY)
-                                               flag |= TTY_PARITY;
-                                       /* XXX should handle break (0x10) */
-                                       tty_insert_flip_char(&port->port,
-                                                       data[i+1], flag);
-                                       i += 2;
-                               }
+               /* 0x80 bit is error flag */
+               if ((data[i] & 0x80) == 0) {
+                       /* no error on any byte */
+                       i++;
+                       for (x = 1; x < len && i < urb->actual_length; ++x)
+                               tty_insert_flip_char(&port->port,
+                                               data[i++], 0);
+               } else {
+                       /*
+                        * some bytes had errors, every byte has status
+                        */
+                       for (x = 0; x + 1 < len &&
+                                   i + 1 < urb->actual_length; x += 2) {
+                               int stat = data[i], flag = 0;
+                               if (stat & RXERROR_OVERRUN)
+                                       flag |= TTY_OVERRUN;
+                               if (stat & RXERROR_FRAMING)
+                                       flag |= TTY_FRAME;
+                               if (stat & RXERROR_PARITY)
+                                       flag |= TTY_PARITY;
+                               /* XXX should handle break (0x10) */
+                               tty_insert_flip_char(&port->port, data[i+1],
+                                                    flag);
+                               i += 2;
                        }
-                       tty_flip_buffer_push(&port->port);
                }
+               tty_flip_buffer_push(&port->port);
        }
  
        /* Resubmit urb so we continue receiving */
@@@ -837,6 -851,7 +837,6 @@@ static void        usa90_instat_callback(struc
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
 -      struct tty_struct                       *tty;
        int old_dcd_state, err;
        int status = urb->status;
  
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
  
 -      if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
 -              tty = tty_port_tty_get(&port->port);
 -              if (tty && !C_CLOCAL(tty))
 -                      tty_hangup(tty);
 -              tty_kref_put(tty);
 -      }
 +      if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
 +              tty_port_tty_hangup(&port->port, true);
  
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -934,8 -953,12 +934,8 @@@ static void       usa67_instat_callback(struc
        p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
        p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
  
 -      if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
 -              struct tty_struct *tty = tty_port_tty_get(&port->port);
 -              if (tty && !C_CLOCAL(tty))
 -                      tty_hangup(tty);
 -              tty_kref_put(tty);
 -      }
 +      if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
 +              tty_port_tty_hangup(&port->port, true);
  
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -1092,7 -1115,6 +1092,6 @@@ static void keyspan_dtr_rts(struct usb_
  static void keyspan_close(struct usb_serial_port *port)
  {
        int                     i;
-       struct usb_serial       *serial = port->serial;
        struct keyspan_port_private     *p_priv;
  
        p_priv = usb_get_serial_port_data(port);
        p_priv->rts_state = 0;
        p_priv->dtr_state = 0;
  
-       if (serial->dev) {
-               keyspan_send_setup(port, 2);
-               /* pilot-xfer seems to work best with this delay */
-               mdelay(100);
-               /* keyspan_set_termios(port, NULL); */
-       }
-       /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
-               dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
-       }*/
+       keyspan_send_setup(port, 2);
+       /* pilot-xfer seems to work best with this delay */
+       mdelay(100);
  
        p_priv->out_flip = 0;
        p_priv->in_flip = 0;
  
-       if (serial->dev) {
-               /* Stop reading/writing urbs */
-               stop_urb(p_priv->inack_urb);
-               /* stop_urb(p_priv->outcont_urb); */
-               for (i = 0; i < 2; i++) {
-                       stop_urb(p_priv->in_urbs[i]);
-                       stop_urb(p_priv->out_urbs[i]);
-               }
+       stop_urb(p_priv->inack_urb);
+       for (i = 0; i < 2; i++) {
+               stop_urb(p_priv->in_urbs[i]);
+               stop_urb(p_priv->out_urbs[i]);
        }
  }
  
index 2230223978ca731bef98ffb09b121ad974ff649f,da3b29eb605ca2c8fc249b799b8e23d3d0473592..5f1d382e55cfbd3b673c4b26dbf7863fbf0d4be2
@@@ -104,8 -104,10 +104,8 @@@ static void keyspan_pda_wakeup_write(st
        struct keyspan_pda_private *priv =
                container_of(work, struct keyspan_pda_private, wakeup_work);
        struct usb_serial_port *port = priv->port;
 -      struct tty_struct *tty = tty_port_tty_get(&port->port);
 -      if (tty)
 -              tty_wakeup(tty);
 -      tty_kref_put(tty);
 +
 +      tty_port_tty_wakeup(&port->port);
  }
  
  static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@@ -593,12 -595,10 +593,10 @@@ static void keyspan_pda_dtr_rts(struct 
  {
        struct usb_serial *serial = port->serial;
  
-       if (serial->dev) {
-               if (on)
-                       keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
-               else
-                       keyspan_pda_set_modem_info(serial, 0);
-       }
+       if (on)
+               keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2));
+       else
+               keyspan_pda_set_modem_info(serial, 0);
  }
  
  
@@@ -649,13 -649,8 +647,8 @@@ error
  }
  static void keyspan_pda_close(struct usb_serial_port *port)
  {
-       struct usb_serial *serial = port->serial;
-       if (serial->dev) {
-               /* shutdown our bulk reads and writes */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->interrupt_in_urb);
  }
  
  
index e956eae198fd6cfbb014fc727912953dee22d892,fc506bb71315d97a2273c81324d48d57c549a629..cc0e54345df98c03621949fab2bdc91b7a90af3e
@@@ -62,7 -62,6 +62,6 @@@ struct moschip_port 
        __u8    shadowMCR;              /* last MCR value received */
        __u8    shadowMSR;              /* last MSR value received */
        char                    open;
-       struct async_icount     icount;
        struct usb_serial_port  *port;  /* loop back to the owner */
        struct urb              *write_urb_pool[NUM_URBS];
  };
@@@ -932,6 -931,7 +931,6 @@@ static void mos7720_bulk_in_callback(st
  static void mos7720_bulk_out_data_callback(struct urb *urb)
  {
        struct moschip_port *mos7720_port;
 -      struct tty_struct *tty;
        int status = urb->status;
  
        if (status) {
                return ;
        }
  
 -      tty = tty_port_tty_get(&mos7720_port->port->port);
 -
 -      if (tty && mos7720_port->open)
 -              tty_wakeup(tty);
 -      tty_kref_put(tty);
 +      if (mos7720_port->open)
 +              tty_port_tty_wakeup(&mos7720_port->port->port);
  }
  
  /*
@@@ -1071,9 -1074,6 +1070,6 @@@ static int mos7720_open(struct tty_stru
                dev_err(&port->dev, "%s - Error %d submitting read urb\n",
                                                        __func__, response);
  
-       /* initialize our icount structure */
-       memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
        /* initialize our port settings */
        mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
  
@@@ -1140,16 -1140,9 +1136,9 @@@ static void mos7720_close(struct usb_se
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
  
-       mutex_lock(&serial->disc_mutex);
-       /* these commands must not be issued if the device has
-        * been disconnected */
-       if (!serial->disconnected) {
-               write_mos_reg(serial, port->number - port->serial->minor,
-                             MCR, 0x00);
-               write_mos_reg(serial, port->number - port->serial->minor,
-                             IER, 0x00);
-       }
-       mutex_unlock(&serial->disc_mutex);
+       write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00);
+       write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00);
        mos7720_port->open = 0;
  }
  
@@@ -1799,33 -1792,6 +1788,6 @@@ static int mos7720_tiocmset(struct tty_
        return 0;
  }
  
- static int mos7720_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount)
- {
-       struct usb_serial_port *port = tty->driver_data;
-       struct moschip_port *mos7720_port;
-       struct async_icount cnow;
-       mos7720_port = usb_get_serial_port_data(port);
-       cnow = mos7720_port->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;
-       dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               icount->rx, icount->tx);
-       return 0;
- }
  static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
                          unsigned int __user *value)
  {
@@@ -1901,8 -1867,6 +1863,6 @@@ static int mos7720_ioctl(struct tty_str
  {
        struct usb_serial_port *port = tty->driver_data;
        struct moschip_port *mos7720_port;
-       struct async_icount cnow;
-       struct async_icount cprev;
  
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL)
                dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
                return get_serial_info(mos7720_port,
                                       (struct serial_struct __user *)arg);
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
-               cprev = mos7720_port->icount;
-               while (1) {
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       cnow = mos7720_port->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
        }
  
        return -ENOIOCTLCMD;
@@@ -2103,7 -2046,6 +2042,6 @@@ static struct usb_serial_driver moschip
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
-       .get_icount             = mos7720_get_icount,
        .set_termios            = mos7720_set_termios,
        .write                  = mos7720_write,
        .write_room             = mos7720_write_room,
index 2be376a2e0e3883dbb1c0bc5059580c8a7fe915a,f0b4e5c01e13ab4b1914499971266b6d0f110fed..a0d5ea5459823fbd528d83f5676120a8c456eca0
@@@ -219,8 -219,6 +219,6 @@@ struct moschip_port 
        char open;
        char open_ports;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
-       int delta_msr_cond;
-       struct async_icount icount;
        struct usb_serial_port *port;   /* loop back to the owner of this object */
  
        /* Offsets */
@@@ -399,32 -397,22 +397,22 @@@ static void mos7840_handle_new_msr(stru
        struct moschip_port *mos7840_port;
        struct async_icount *icount;
        mos7840_port = port;
-       icount = &mos7840_port->icount;
        if (new_msr &
            (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
             MOS_MSR_DELTA_CD)) {
-               icount = &mos7840_port->icount;
+               icount = &mos7840_port->port->icount;
  
                /* update input line counters */
-               if (new_msr & MOS_MSR_DELTA_CTS) {
+               if (new_msr & MOS_MSR_DELTA_CTS)
                        icount->cts++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_DSR) {
+               if (new_msr & MOS_MSR_DELTA_DSR)
                        icount->dsr++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_CD) {
+               if (new_msr & MOS_MSR_DELTA_CD)
                        icount->dcd++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_RI) {
+               if (new_msr & MOS_MSR_DELTA_RI)
                        icount->rng++;
-                       smp_wmb();
-               }
  
-               mos7840_port->delta_msr_cond = 1;
-               wake_up_interruptible(&port->port->delta_msr_wait);
+               wake_up_interruptible(&port->port->port.delta_msr_wait);
        }
  }
  
@@@ -442,23 -430,15 +430,15 @@@ static void mos7840_handle_new_lsr(stru
        }
  
        /* update input line counters */
-       icount = &port->icount;
-       if (new_lsr & SERIAL_LSR_BI) {
+       icount = &port->port->icount;
+       if (new_lsr & SERIAL_LSR_BI)
                icount->brk++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_OE) {
+       if (new_lsr & SERIAL_LSR_OE)
                icount->overrun++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_PE) {
+       if (new_lsr & SERIAL_LSR_PE)
                icount->parity++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_FE) {
+       if (new_lsr & SERIAL_LSR_FE)
                icount->frame++;
-               smp_wmb();
-       }
  }
  
  /************************************************************************/
@@@ -777,9 -757,8 +757,8 @@@ static void mos7840_bulk_in_callback(st
                struct tty_port *tport = &mos7840_port->port->port;
                tty_insert_flip_string(tport, data, urb->actual_length);
                tty_flip_buffer_push(tport);
-               mos7840_port->icount.rx += urb->actual_length;
-               smp_wmb();
-               dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx);
+               port->icount.rx += urb->actual_length;
+               dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);
        }
  
        if (!mos7840_port->read_urb) {
@@@ -816,6 -795,7 +795,6 @@@ static void mos7840_bulk_out_data_callb
  {
        struct moschip_port *mos7840_port;
        struct usb_serial_port *port;
 -      struct tty_struct *tty;
        int status = urb->status;
        int i;
  
        if (mos7840_port_paranoia_check(port, __func__))
                return;
  
 -      tty = tty_port_tty_get(&port->port);
 -      if (tty && mos7840_port->open)
 -              tty_wakeup(tty);
 -      tty_kref_put(tty);
 +      if (mos7840_port->open)
 +              tty_port_tty_wakeup(&port->port);
  
  }
  
@@@ -1127,17 -1109,12 +1106,12 @@@ static int mos7840_open(struct tty_stru
        /* initialize our wait queues */
        init_waitqueue_head(&mos7840_port->wait_chase);
  
-       /* initialize our icount structure */
-       memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
        /* initialize our port settings */
        /* Must set to enable ints! */
        mos7840_port->shadowMCR = MCR_MASTER_IE;
        /* send a open port command */
        mos7840_port->open = 1;
        /* mos7840_change_port_settings(mos7840_port,old_termios); */
-       mos7840_port->icount.tx = 0;
-       mos7840_port->icount.rx = 0;
  
        return 0;
  }
@@@ -1220,25 -1197,10 +1194,10 @@@ static void mos7840_close(struct usb_se
                }
        }
  
-       /* While closing port, shutdown all bulk read, write  *
-        * and interrupt read if they exists                  */
-       if (serial->dev) {
-               if (mos7840_port->write_urb) {
-                       dev_dbg(&port->dev, "%s", "Shutdown bulk write\n");
-                       usb_kill_urb(mos7840_port->write_urb);
-               }
-               if (mos7840_port->read_urb) {
-                       dev_dbg(&port->dev, "%s", "Shutdown bulk read\n");
-                       usb_kill_urb(mos7840_port->read_urb);
-                       mos7840_port->read_urb_busy = false;
-               }
-               if ((&mos7840_port->control_urb)) {
-                       dev_dbg(&port->dev, "%s", "Shutdown control read\n");
-                       /*/      usb_kill_urb (mos7840_port->control_urb); */
-               }
-       }
- /*      if(mos7840_port->ctrl_buf != NULL) */
- /*              kfree(mos7840_port->ctrl_buf); */
+       usb_kill_urb(mos7840_port->write_urb);
+       usb_kill_urb(mos7840_port->read_urb);
+       mos7840_port->read_urb_busy = false;
        port0->open_ports--;
        dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);
        if (port0->open_ports == 0) {
  
        if (mos7840_port->write_urb) {
                /* if this urb had a transfer buffer already (old tx) free it */
-               if (mos7840_port->write_urb->transfer_buffer != NULL)
-                       kfree(mos7840_port->write_urb->transfer_buffer);
+               kfree(mos7840_port->write_urb->transfer_buffer);
                usb_free_urb(mos7840_port->write_urb);
        }
  
@@@ -1328,9 -1289,8 +1286,8 @@@ static void mos7840_break(struct tty_st
        if (mos7840_port == NULL)
                return;
  
-       if (serial->dev)
-               /* flush and block until tx is empty */
-               mos7840_block_until_chase_response(tty, mos7840_port);
+       /* flush and block until tx is empty */
+       mos7840_block_until_chase_response(tty, mos7840_port);
  
        if (break_state == -1)
                data = mos7840_port->shadowLCR | LCR_SET_BREAK;
@@@ -1520,9 -1480,8 +1477,8 @@@ static int mos7840_write(struct tty_str
                goto exit;
        }
        bytes_sent = transfer_size;
-       mos7840_port->icount.tx += transfer_size;
-       smp_wmb();
-       dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+       port->icount.tx += transfer_size;
+       dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);
  exit:
        return bytes_sent;
  
@@@ -2141,34 -2100,6 +2097,6 @@@ static int mos7840_get_serial_info(stru
        return 0;
  }
  
- static int mos7840_get_icount(struct tty_struct *tty,
-                       struct serial_icounter_struct *icount)
- {
-       struct usb_serial_port *port = tty->driver_data;
-       struct moschip_port *mos7840_port;
-       struct async_icount cnow;
-       mos7840_port = mos7840_get_port_private(port);
-       cnow = mos7840_port->icount;
-       smp_rmb();
-       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;
-       dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               icount->rx, icount->tx);
-       return 0;
- }
  /*****************************************************************************
   * SerialIoctl
   *    this function handles any ioctl calls to the driver
@@@ -2181,9 -2112,6 +2109,6 @@@ static int mos7840_ioctl(struct tty_str
        void __user *argp = (void __user *)arg;
        struct moschip_port *mos7840_port;
  
-       struct async_icount cnow;
-       struct async_icount cprev;
        if (mos7840_port_paranoia_check(port, __func__))
                return -1;
  
        case TIOCSSERIAL:
                dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);
                break;
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s  TIOCMIWAIT\n", __func__);
-               cprev = mos7840_port->icount;
-               while (1) {
-                       /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
-                       mos7840_port->delta_msr_cond = 0;
-                       wait_event_interruptible(port->delta_msr_wait,
-                                                (port->serial->disconnected ||
-                                                 mos7840_port->
-                                                 delta_msr_cond == 1));
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       if (port->serial->disconnected)
-                               return -EIO;
-                       cnow = mos7840_port->icount;
-                       smp_rmb();
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO;    /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
        default:
                break;
        }
@@@ -2589,7 -2482,8 +2479,8 @@@ static struct usb_serial_driver moschip
        .break_ctl = mos7840_break,
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
-       .get_icount = mos7840_get_icount,
+       .tiocmiwait = usb_serial_generic_tiocmiwait,
+       .get_icount = usb_serial_generic_get_icount,
        .port_probe = mos7840_port_probe,
        .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
index 09cd3967b8df777237d09819966350716cc2f7d0,bff059a19e2fa9b07ad3636eeb2ec11b62b53f11..734372846abbb31b1381841f4f144a09a4f0b2a0
@@@ -347,6 -347,7 +347,7 @@@ static void option_instat_callback(stru
  /* Olivetti products */
  #define OLIVETTI_VENDOR_ID                    0x0b3c
  #define OLIVETTI_PRODUCT_OLICARD100           0xc000
+ #define OLIVETTI_PRODUCT_OLICARD145           0xc003
  
  /* Celot products */
  #define CELOT_VENDOR_ID                               0x211f
@@@ -1273,6 -1274,7 +1274,7 @@@ static const struct usb_device_id optio
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
  
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
        { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },    /* D-Link DWM-156 (variant) */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },    /* D-Link DWM-156 (variant) */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
        { } /* Terminating entry */
  };
  MODULE_DEVICE_TABLE(usb, option_ids);
@@@ -1537,8 -1545,13 +1545,8 @@@ static void option_instat_callback(stru
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
  
 -                      if (old_dcd_state && !portdata->dcd_state) {
 -                              struct tty_struct *tty =
 -                                              tty_port_tty_get(&port->port);
 -                              if (tty && !C_CLOCAL(tty))
 -                                      tty_hangup(tty);
 -                              tty_kref_put(tty);
 -                      }
 +                      if (old_dcd_state && !portdata->dcd_state)
 +                              tty_port_tty_hangup(&port->port, true);
                } else {
                        dev_dbg(dev, "%s: type %x req %x\n", __func__,
                                req_pkt->bRequestType, req_pkt->bRequest);
index ef3a7d5eaab4afa072daf8914b5db90040445fe6,3c278521f7e2179a7886537c7118da6e32490d2b..02b0803425c5d01d82f4b8d498a78c128bdfd268
@@@ -116,6 -116,7 +116,6 @@@ struct qt2_serial_private 
  };
  
  struct qt2_port_private {
 -      bool is_open;
        u8   device_port;
  
        spinlock_t urb_lock;
        u8          shadowLSR;
        u8          shadowMSR;
  
-       struct async_icount icount;
        struct usb_serial_port *port;
  };
  
@@@ -396,6 -395,7 +394,6 @@@ static int qt2_open(struct tty_struct *
                return status;
        }
  
 -      port_priv->is_open = true;
        port_priv->device_port = (u8) device_port;
  
        if (tty)
@@@ -415,17 -415,13 +413,11 @@@ static void qt2_close(struct usb_serial
        serial = port->serial;
        port_priv = usb_get_serial_port_data(port);
  
 -      port_priv->is_open = false;
 -
        spin_lock_irqsave(&port_priv->urb_lock, flags);
        usb_kill_urb(port_priv->write_urb);
        port_priv->urb_in_use = false;
        spin_unlock_irqrestore(&port_priv->urb_lock, flags);
  
-       mutex_lock(&port->serial->disc_mutex);
-       if (port->serial->disconnected) {
-               mutex_unlock(&port->serial->disc_mutex);
-               return;
-       }
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
                            usb_rcvctrlpipe(serial->dev, 0),
        if (i < 0)
                dev_err(&port->dev, "%s - close port failed %i\n",
                        __func__, i);
-       mutex_unlock(&port->serial->disc_mutex);
  }
  
  static void qt2_disconnect(struct usb_serial *serial)
@@@ -490,71 -484,6 +480,6 @@@ static int get_serial_info(struct usb_s
        return 0;
  }
  
- static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
- {
-       struct qt2_port_private *priv = usb_get_serial_port_data(port);
-       struct async_icount prev, cur;
-       unsigned long flags;
-       spin_lock_irqsave(&priv->lock, flags);
-       prev = priv->icount;
-       spin_unlock_irqrestore(&priv->lock, flags);
-       while (1) {
-               wait_event_interruptible(port->delta_msr_wait,
-                                        (port->serial->disconnected ||
-                                         (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;
-               if (port->serial->disconnected)
-                       return -EIO;
-               spin_lock_irqsave(&priv->lock, flags);
-               cur = priv->icount;
-               spin_unlock_irqrestore(&priv->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 qt2_get_icount(struct tty_struct *tty,
-                         struct serial_icounter_struct *icount)
- {
-       struct usb_serial_port *port = tty->driver_data;
-       struct qt2_port_private *priv = usb_get_serial_port_data(port);
-       struct async_icount cnow = priv->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;
-       return 0;
- }
  static int qt2_ioctl(struct tty_struct *tty,
                     unsigned int cmd, unsigned long arg)
  {
        case TIOCGSERIAL:
                return get_serial_info(port,
                                       (struct serial_struct __user *)arg);
-       case TIOCMIWAIT:
-               return wait_modem_info(port, arg);
        default:
                break;
        }
@@@ -903,6 -828,12 +824,6 @@@ static void qt2_break_ctl(struct tty_st
  
        port_priv = usb_get_serial_port_data(port);
  
 -      if (!port_priv->is_open) {
 -              dev_err(&port->dev,
 -                      "%s - port is not open\n", __func__);
 -              return;
 -      }
 -
        val = (break_state == -1) ? 1 : 0;
  
        status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
@@@ -948,18 -879,15 +869,15 @@@ static void qt2_update_msr(struct usb_s
        if (newMSR & UART_MSR_ANY_DELTA) {
                /* update input line counters */
                if (newMSR & UART_MSR_DCTS)
-                       port_priv->icount.cts++;
+                       port->icount.cts++;
                if (newMSR & UART_MSR_DDSR)
-                       port_priv->icount.dsr++;
+                       port->icount.dsr++;
                if (newMSR & UART_MSR_DDCD)
-                       port_priv->icount.dcd++;
+                       port->icount.dcd++;
                if (newMSR & UART_MSR_TERI)
-                       port_priv->icount.rng++;
+                       port->icount.rng++;
  
-               wake_up_interruptible(&port->delta_msr_wait);
+               wake_up_interruptible(&port->port.delta_msr_wait);
        }
  }
  
@@@ -979,7 -907,7 +897,7 @@@ static void qt2_update_lsr(struct usb_s
        port_priv->shadowLSR = newLSR;
        spin_unlock_irqrestore(&port_priv->lock, flags);
  
-       icount = &port_priv->icount;
+       icount = &port->icount;
  
        if (newLSR & UART_LSR_BRK_ERROR_BITS) {
  
@@@ -1089,7 -1017,8 +1007,8 @@@ static struct usb_serial_driver qt2_dev
        .break_ctl           = qt2_break_ctl,
        .tiocmget            = qt2_tiocmget,
        .tiocmset            = qt2_tiocmset,
-       .get_icount          = qt2_get_icount,
+       .tiocmiwait          = usb_serial_generic_tiocmiwait,
+       .get_icount          = usb_serial_generic_get_icount,
        .ioctl               = qt2_ioctl,
        .set_termios         = qt2_set_termios,
  };
index d66148a17fe36548e019c0b8b7b60aa563548a1a,2b06481dc85ceb2a5829d14cd24c01970fa3439e..8894665cd6102cfe756ea2a86f46176010483444
@@@ -628,6 -628,7 +628,6 @@@ static void sierra_instat_callback(stru
                        unsigned char signals = *((unsigned char *)
                                        urb->transfer_buffer +
                                        sizeof(struct usb_ctrlrequest));
 -                      struct tty_struct *tty;
  
                        dev_dbg(&port->dev, "%s: signal x%x\n", __func__,
                                signals);
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
  
 -                      tty = tty_port_tty_get(&port->port);
 -                      if (tty && !C_CLOCAL(tty) &&
 -                                      old_dcd_state && !portdata->dcd_state)
 -                              tty_hangup(tty);
 -                      tty_kref_put(tty);
 +                      if (old_dcd_state && !portdata->dcd_state)
 +                              tty_port_tty_hangup(&port->port, true);
                } else {
                        dev_dbg(&port->dev, "%s: type %x req %x\n",
                                __func__, req_pkt->bRequestType,
@@@ -774,30 -778,25 +774,25 @@@ static void sierra_close(struct usb_ser
        portdata->rts_state = 0;
        portdata->dtr_state = 0;
  
-       if (serial->dev) {
-               mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected) {
-                       serial->interface->needs_remote_wakeup = 0;
-                       /* odd error handling due to pm counters */
-                       if (!usb_autopm_get_interface(serial->interface))
-                               sierra_send_setup(port);
-                       else
-                               usb_autopm_get_interface_no_resume(serial->interface);
-                               
-               }
-               mutex_unlock(&serial->disc_mutex);
-               spin_lock_irq(&intfdata->susp_lock);
-               portdata->opened = 0;
-               spin_unlock_irq(&intfdata->susp_lock);
-               /* Stop reading urbs */
-               sierra_stop_rx_urbs(port);
-               /* .. and release them */
-               for (i = 0; i < portdata->num_in_urbs; i++) {
-                       sierra_release_urb(portdata->in_urbs[i]);
-                       portdata->in_urbs[i] = NULL;
-               }
+       mutex_lock(&serial->disc_mutex);
+       if (!serial->disconnected) {
+               serial->interface->needs_remote_wakeup = 0;
+               /* odd error handling due to pm counters */
+               if (!usb_autopm_get_interface(serial->interface))
+                       sierra_send_setup(port);
+               else
+                       usb_autopm_get_interface_no_resume(serial->interface);
+       }
+       mutex_unlock(&serial->disc_mutex);
+       spin_lock_irq(&intfdata->susp_lock);
+       portdata->opened = 0;
+       spin_unlock_irq(&intfdata->susp_lock);
+       sierra_stop_rx_urbs(port);
+       for (i = 0; i < portdata->num_in_urbs; i++) {
+               sierra_release_urb(portdata->in_urbs[i]);
+               portdata->in_urbs[i] = NULL;
        }
  }
  
index 19a71a9eecf09130d196dc8131e00733c9e09f4e,4b52132812c15908d2b00eb574e1676d4fd0a570..cac47aef2918972ead4aeb01a43bd9166daec0ca
  struct ti_port {
        int                     tp_is_open;
        __u8                    tp_msr;
-       __u8                    tp_lsr;
        __u8                    tp_shadow_mcr;
        __u8                    tp_uart_mode;   /* 232 or 485 modes */
        unsigned int            tp_uart_base_addr;
        int                     tp_flags;
-       int                     tp_closing_wait;/* in .01 secs */
-       struct async_icount     tp_icount;
        wait_queue_head_t       tp_write_wait;
        struct ti_device        *tp_tdev;
        struct usb_serial_port  *tp_port;
@@@ -108,8 -105,6 +105,6 @@@ static void ti_throttle(struct tty_stru
  static void ti_unthrottle(struct tty_struct *tty);
  static int ti_ioctl(struct tty_struct *tty,
                unsigned int cmd, unsigned long arg);
- static int ti_get_icount(struct tty_struct *tty,
-               struct serial_icounter_struct *icount);
  static void ti_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
  static int ti_tiocmget(struct tty_struct *tty);
@@@ -124,15 -119,13 +119,13 @@@ static void ti_recv(struct usb_serial_p
                int length);
  static void ti_send(struct ti_port *tport);
  static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
- static int ti_get_lsr(struct ti_port *tport);
+ static int ti_get_lsr(struct ti_port *tport, u8 *lsr);
  static int ti_get_serial_info(struct ti_port *tport,
        struct serial_struct __user *ret_arg);
  static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
        struct serial_struct __user *new_arg);
  static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
  
- static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush);
  static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);
  static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);
  
@@@ -235,7 -228,8 +228,8 @@@ static struct usb_serial_driver ti_1por
        .set_termios            = ti_set_termios,
        .tiocmget               = ti_tiocmget,
        .tiocmset               = ti_tiocmset,
-       .get_icount             = ti_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .break_ctl              = ti_break,
        .read_int_callback      = ti_interrupt_callback,
        .read_bulk_callback     = ti_bulk_in_callback,
@@@ -265,7 -259,8 +259,8 @@@ static struct usb_serial_driver ti_2por
        .set_termios            = ti_set_termios,
        .tiocmget               = ti_tiocmget,
        .tiocmset               = ti_tiocmset,
-       .get_icount             = ti_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .break_ctl              = ti_break,
        .read_int_callback      = ti_interrupt_callback,
        .read_bulk_callback     = ti_bulk_in_callback,
@@@ -430,7 -425,7 +425,7 @@@ static int ti_port_probe(struct usb_ser
                tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
        else
                tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
-       tport->tp_closing_wait = closing_wait;
+       port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
        init_waitqueue_head(&tport->tp_write_wait);
        if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
                kfree(tport);
@@@ -480,8 -475,6 +475,6 @@@ static int ti_open(struct tty_struct *t
  
        port_number = port->number - port->serial->minor;
  
-       memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
        tport->tp_msr = 0;
        tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
  
        tport->tp_is_open = 1;
        ++tdev->td_open_port_count;
  
+       port->port.drain_delay = 3;
        goto release_lock;
  
  unlink_int_urb:
@@@ -604,6 -599,7 +599,7 @@@ static void ti_close(struct usb_serial_
        int port_number;
        int status;
        int do_unlock;
+       unsigned long flags;
  
        tdev = usb_get_serial_data(port->serial);
        tport = usb_get_serial_port_data(port);
  
        tport->tp_is_open = 0;
  
-       ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->write_urb);
        tport->tp_write_urb_in_use = 0;
+       spin_lock_irqsave(&tport->tp_lock, flags);
+       kfifo_reset_out(&tport->write_fifo);
+       spin_unlock_irqrestore(&tport->tp_lock, flags);
  
        port_number = port->number - port->serial->minor;
  
@@@ -687,6 -684,8 +684,8 @@@ static int ti_chars_in_buffer(struct tt
        struct ti_port *tport = usb_get_serial_port_data(port);
        int chars = 0;
        unsigned long flags;
+       int ret;
+       u8 lsr;
  
        if (tport == NULL)
                return 0;
        chars = kfifo_len(&tport->write_fifo);
        spin_unlock_irqrestore(&tport->tp_lock, flags);
  
+       if (!chars) {
+               ret = ti_get_lsr(tport, &lsr);
+               if (!ret && !(lsr & TI_LSR_TX_EMPTY))
+                       chars = 1;
+       }
        dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
        return chars;
  }
@@@ -731,38 -736,11 +736,11 @@@ static void ti_unthrottle(struct tty_st
        }
  }
  
- static int ti_get_icount(struct tty_struct *tty,
-               struct serial_icounter_struct *icount)
- {
-       struct usb_serial_port *port = tty->driver_data;
-       struct ti_port *tport = usb_get_serial_port_data(port);
-       struct async_icount cnow = tport->tp_icount;
-       dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               cnow.rx, cnow.tx);
-       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;
-       return 0;
- }
  static int ti_ioctl(struct tty_struct *tty,
        unsigned int cmd, unsigned long arg)
  {
        struct usb_serial_port *port = tty->driver_data;
        struct ti_port *tport = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       struct async_icount cprev;
  
        dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd);
  
                dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);
                return ti_set_serial_info(tty, tport,
                                (struct serial_struct __user *)arg);
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
-               cprev = tport->tp_icount;
-               while (1) {
-                       interruptible_sleep_on(&port->delta_msr_wait);
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       if (port->serial->disconnected)
-                               return -EIO;
-                       cnow = tport->tp_icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
-                               return 0;
-                       cprev = cnow;
-               }
-               break;
        }
        return -ENOIOCTLCMD;
  }
@@@ -1018,8 -973,6 +973,6 @@@ static void ti_break(struct tty_struct 
        if (tport == NULL)
                return;
  
-       ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0);
        status = ti_write_byte(port, tport->tp_tdev,
                tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,
                TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
@@@ -1156,7 -1109,7 +1109,7 @@@ static void ti_bulk_in_callback(struct 
                else
                        ti_recv(port, urb->transfer_buffer, urb->actual_length);
                spin_lock(&tport->tp_lock);
-               tport->tp_icount.rx += urb->actual_length;
+               port->icount.rx += urb->actual_length;
                spin_unlock(&tport->tp_lock);
        }
  
@@@ -1229,6 -1182,7 +1182,6 @@@ static void ti_send(struct ti_port *tpo
  {
        int count, result;
        struct usb_serial_port *port = tport->tp_port;
 -      struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
        unsigned long flags;
  
        spin_lock_irqsave(&tport->tp_lock, flags);
                /* TODO: reschedule ti_send */
        } else {
                spin_lock_irqsave(&tport->tp_lock, flags);
-               tport->tp_icount.tx += count;
+               port->icount.tx += count;
                spin_unlock_irqrestore(&tport->tp_lock, flags);
        }
  
        /* more room in the buffer for new writes, wakeup */
 -      if (tty)
 -              tty_wakeup(tty);
 -      tty_kref_put(tty);
 +      tty_port_tty_wakeup(&port->port);
 +
        wake_up_interruptible(&tport->tp_write_wait);
        return;
  unlock:
        spin_unlock_irqrestore(&tport->tp_lock, flags);
 -      tty_kref_put(tty);
        return;
  }
  
@@@ -1297,7 -1253,7 +1250,7 @@@ static int ti_set_mcr(struct ti_port *t
  }
  
  
- static int ti_get_lsr(struct ti_port *tport)
+ static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
  {
        int size, status;
        struct ti_device *tdev = tport->tp_tdev;
  
        dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR);
  
-       tport->tp_lsr = data->bLSR;
+       *lsr = data->bLSR;
  
  free_data:
        kfree(data);
@@@ -1336,10 -1292,15 +1289,15 @@@ static int ti_get_serial_info(struct ti
  {
        struct usb_serial_port *port = tport->tp_port;
        struct serial_struct ret_serial;
+       unsigned cwait;
  
        if (!ret_arg)
                return -EFAULT;
  
+       cwait = port->port.closing_wait;
+       if (cwait != ASYNC_CLOSING_WAIT_NONE)
+               cwait = jiffies_to_msecs(cwait) / 10;
        memset(&ret_serial, 0, sizeof(ret_serial));
  
        ret_serial.type = PORT_16550A;
        ret_serial.flags = tport->tp_flags;
        ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
        ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
-       ret_serial.closing_wait = tport->tp_closing_wait;
+       ret_serial.closing_wait = cwait;
  
        if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
                return -EFAULT;
@@@ -1361,12 -1322,17 +1319,17 @@@ static int ti_set_serial_info(struct tt
        struct serial_struct __user *new_arg)
  {
        struct serial_struct new_serial;
+       unsigned cwait;
  
        if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
                return -EFAULT;
  
+       cwait = new_serial.closing_wait;
+       if (cwait != ASYNC_CLOSING_WAIT_NONE)
+               cwait = msecs_to_jiffies(10 * new_serial.closing_wait);
        tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
-       tport->tp_closing_wait = new_serial.closing_wait;
+       tport->tp_port->port.closing_wait = cwait;
  
        return 0;
  }
@@@ -1382,7 -1348,7 +1345,7 @@@ static void ti_handle_new_msr(struct ti
  
        if (msr & TI_MSR_DELTA_MASK) {
                spin_lock_irqsave(&tport->tp_lock, flags);
-               icount = &tport->tp_icount;
+               icount = &tport->tp_port->icount;
                if (msr & TI_MSR_DELTA_CTS)
                        icount->cts++;
                if (msr & TI_MSR_DELTA_DSR)
                        icount->dcd++;
                if (msr & TI_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&tport->tp_port->delta_msr_wait);
+               wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);
                spin_unlock_irqrestore(&tport->tp_lock, flags);
        }
  
  }
  
  
- static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
- {
-       struct ti_device *tdev = tport->tp_tdev;
-       struct usb_serial_port *port = tport->tp_port;
-       wait_queue_t wait;
-       spin_lock_irq(&tport->tp_lock);
-       /* wait for data to drain from the buffer */
-       tdev->td_urb_error = 0;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tport->tp_write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (kfifo_len(&tport->write_fifo) == 0
-               || timeout == 0 || signal_pending(current)
-               || tdev->td_urb_error
-               || port->serial->disconnected)  /* disconnect */
-                       break;
-               spin_unlock_irq(&tport->tp_lock);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irq(&tport->tp_lock);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tport->tp_write_wait, &wait);
-       /* flush any remaining data in the buffer */
-       if (flush)
-               kfifo_reset_out(&tport->write_fifo);
-       spin_unlock_irq(&tport->tp_lock);
-       mutex_lock(&port->serial->disc_mutex);
-       /* wait for data to drain from the device */
-       /* wait for empty tx register, plus 20 ms */
-       timeout += jiffies;
-       tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
-       while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
-       && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
-       && !port->serial->disconnected) {
-               if (ti_get_lsr(tport))
-                       break;
-               mutex_unlock(&port->serial->disc_mutex);
-               msleep_interruptible(20);
-               mutex_lock(&port->serial->disc_mutex);
-       }
-       mutex_unlock(&port->serial->disc_mutex);
- }
  static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)
  {
        unsigned long flags;
index 650be17a68f20993b4cf24489eafed109afa08a7,5eb96df8de05bdcd659974e587ca3121092f30fb..cf75beb1251bc85b3c709b989e1ddd5220094c7c
@@@ -1,6 -1,7 +1,7 @@@
  /*
   * USB Serial Converter driver
   *
+  * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)
   * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
   * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
   * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
@@@ -14,7 -15,6 +15,6 @@@
   *
   * See Documentation/usb/usb-serial.txt for more information on using this
   * driver
-  *
   */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@@ -49,7 -49,6 +49,6 @@@
     drivers depend on it.
  */
  
- /* initially all NULL */
  static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
  static DEFINE_MUTEX(table_lock);
  static LIST_HEAD(usb_serial_driver_list);
@@@ -139,7 -138,7 +138,7 @@@ static void destroy_serial(struct kref 
        if (serial->minor != SERIAL_TTY_NO_MINOR)
                return_serial(serial);
  
-       if (serial->attached)
+       if (serial->attached && serial->type->release)
                serial->type->release(serial);
  
        /* Now that nothing is using the ports, they can be freed */
@@@ -225,7 -224,7 +224,7 @@@ static int serial_install(struct tty_dr
        return retval;
  }
  
- static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+ static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)
  {
        struct usb_serial_port *port =
                container_of(tport, struct usb_serial_port, port);
@@@ -249,30 -248,27 +248,27 @@@ static int serial_open(struct tty_struc
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
        return tty_port_open(&port->port, tty, filp);
  }
  
  /**
-  * serial_down - shut down hardware
+  * serial_port_shutdown - shut down hardware
   * @tport: tty port to shut down
   *
-  * Shut down a USB serial port unless it is the console.  We never
-  * shut down the console hardware as it will always be in use. Serialized
-  * against activate by the tport mutex and kept to matching open/close pairs
+  * Shut down a USB serial port. Serialized against activate by the
+  * tport mutex and kept to matching open/close pairs
   * of calls by the ASYNCB_INITIALIZED flag.
+  *
+  * Not called if tty is console.
   */
- static void serial_down(struct tty_port *tport)
+ static void serial_port_shutdown(struct tty_port *tport)
  {
        struct usb_serial_port *port =
                container_of(tport, struct usb_serial_port, port);
        struct usb_serial_driver *drv = port->serial->type;
-       /*
-        * The console is magical.  Do not hang up the console hardware
-        * or there will be tears.
-        */
-       if (port->port.console)
-               return;
        if (drv->close)
                drv->close(port);
  }
@@@ -281,7 -277,8 +277,8 @@@ static void serial_hangup(struct tty_st
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
        tty_port_hangup(&port->port);
  }
  
@@@ -289,7 -286,8 +286,8 @@@ static void serial_close(struct tty_str
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
        tty_port_close(&port->port, tty, filp);
  }
  
@@@ -308,14 -306,14 +306,14 @@@ static void serial_cleanup(struct tty_s
        struct usb_serial *serial;
        struct module *owner;
  
+       dev_dbg(tty->dev, "%s\n", __func__);
        /* The console is magical.  Do not hang up the console hardware
         * or there will be tears.
         */
        if (port->port.console)
                return;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
        tty->driver_data = NULL;
  
        serial = port->serial;
@@@ -339,10 -337,8 +337,8 @@@ static int serial_write(struct tty_stru
        if (port->serial->dev->state == USB_STATE_NOTATTACHED)
                goto exit;
  
-       dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__,
-               port->number, count);
+       dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
  
-       /* pass on to the driver specific version of this function */
        retval = port->serial->type->write(tty, port, buf, count);
        if (retval < 0)
                retval = usb_translate_errors(retval);
@@@ -354,8 -350,8 +350,8 @@@ static int serial_write_room(struct tty
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-       /* pass on to the driver specific version of this function */
+       dev_dbg(tty->dev, "%s\n", __func__);
        return port->serial->type->write_room(tty);
  }
  
@@@ -365,7 -361,7 +361,7 @@@ static int serial_chars_in_buffer(struc
        struct usb_serial *serial = port->serial;
        int count = 0;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
        mutex_lock(&serial->disc_mutex);
        /* if the device was unplugged then any remaining characters
@@@ -383,9 -379,8 +379,8 @@@ static void serial_throttle(struct tty_
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
-       /* pass on to the driver specific version of this function */
        if (port->serial->type->throttle)
                port->serial->type->throttle(tty);
  }
@@@ -394,9 -389,8 +389,8 @@@ static void serial_unthrottle(struct tt
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
-       /* pass on to the driver specific version of this function */
        if (port->serial->type->unthrottle)
                port->serial->type->unthrottle(tty);
  }
@@@ -407,15 -401,20 +401,20 @@@ static int serial_ioctl(struct tty_stru
        struct usb_serial_port *port = tty->driver_data;
        int retval = -ENODEV;
  
-       dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__,
-               port->number, cmd);
+       dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd);
+       switch (cmd) {
+       case TIOCMIWAIT:
+               if (port->serial->type->tiocmiwait)
+                       retval = port->serial->type->tiocmiwait(tty, arg);
+               break;
+       default:
+               if (port->serial->type->ioctl)
+                       retval = port->serial->type->ioctl(tty, cmd, arg);
+               else
+                       retval = -ENOIOCTLCMD;
+       }
  
-       /* pass on to the driver specific version of this function
-          if it is available */
-       if (port->serial->type->ioctl) {
-               retval = port->serial->type->ioctl(tty, cmd, arg);
-       } else
-               retval = -ENOIOCTLCMD;
        return retval;
  }
  
@@@ -423,10 -422,8 +422,8 @@@ static void serial_set_termios(struct t
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
-       /* pass on to the driver specific version of this function
-          if it is available */
        if (port->serial->type->set_termios)
                port->serial->type->set_termios(tty, port, old);
        else
@@@ -437,12 -434,11 +434,11 @@@ static int serial_break(struct tty_stru
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
-       /* pass on to the driver specific version of this function
-          if it is available */
        if (port->serial->type->break_ctl)
                port->serial->type->break_ctl(tty, break_state);
        return 0;
  }
  
@@@ -496,7 -492,7 +492,7 @@@ static int serial_tiocmget(struct tty_s
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
        if (port->serial->type->tiocmget)
                return port->serial->type->tiocmget(tty);
@@@ -508,7 -504,7 +504,7 @@@ static int serial_tiocmset(struct tty_s
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
        if (port->serial->type->tiocmset)
                return port->serial->type->tiocmset(tty, set, clear);
@@@ -520,7 -516,7 +516,7 @@@ static int serial_get_icount(struct tty
  {
        struct usb_serial_port *port = tty->driver_data;
  
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
  
        if (port->serial->type->get_icount)
                return port->serial->type->get_icount(tty, icount);
@@@ -542,47 -538,51 +538,43 @@@ static void usb_serial_port_work(struc
  {
        struct usb_serial_port *port =
                container_of(work, struct usb_serial_port, work);
 -      struct tty_struct *tty;
  
 -      tty = tty_port_tty_get(&port->port);
 -      if (!tty)
 -              return;
 -
 -      dev_dbg(tty->dev, "%s\n", __func__);
 -
 -      tty_wakeup(tty);
 -      tty_kref_put(tty);
 +      tty_port_tty_wakeup(&port->port);
  }
  
- static void kill_traffic(struct usb_serial_port *port)
+ static void usb_serial_port_poison_urbs(struct usb_serial_port *port)
  {
        int i;
  
        for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
-               usb_kill_urb(port->read_urbs[i]);
+               usb_poison_urb(port->read_urbs[i]);
        for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-               usb_kill_urb(port->write_urbs[i]);
-       /*
-        * This is tricky.
-        * Some drivers submit the read_urb in the
-        * handler for the write_urb or vice versa
-        * this order determines the order in which
-        * usb_kill_urb() must be used to reliably
-        * kill the URBs. As it is unknown here,
-        * both orders must be used in turn.
-        * The call below is not redundant.
-        */
-       usb_kill_urb(port->read_urb);
-       usb_kill_urb(port->interrupt_in_urb);
-       usb_kill_urb(port->interrupt_out_urb);
+               usb_poison_urb(port->write_urbs[i]);
+       usb_poison_urb(port->interrupt_in_urb);
+       usb_poison_urb(port->interrupt_out_urb);
+ }
+ static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)
+ {
+       int i;
+       for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+               usb_unpoison_urb(port->read_urbs[i]);
+       for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+               usb_unpoison_urb(port->write_urbs[i]);
+       usb_unpoison_urb(port->interrupt_in_urb);
+       usb_unpoison_urb(port->interrupt_out_urb);
  }
  
- static void port_release(struct device *dev)
+ static void usb_serial_port_release(struct device *dev)
  {
        struct usb_serial_port *port = to_usb_serial_port(dev);
        int i;
  
        dev_dbg(dev, "%s\n", __func__);
  
-       /*
-        * Stop all the traffic before cancelling the work, so that
-        * nobody will restart it by calling usb_serial_port_softint.
-        */
-       kill_traffic(port);
-       cancel_work_sync(&port->work);
        usb_free_urb(port->interrupt_in_urb);
        usb_free_urb(port->interrupt_out_urb);
        for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
@@@ -607,10 -607,8 +599,8 @@@ static struct usb_serial *create_serial
        struct usb_serial *serial;
  
        serial = kzalloc(sizeof(*serial), GFP_KERNEL);
-       if (!serial) {
-               dev_err(&dev->dev, "%s - out of memory\n", __func__);
+       if (!serial)
                return NULL;
-       }
        serial->dev = usb_get_dev(dev);
        serial->type = driver;
        serial->interface = usb_get_intf(interface);
@@@ -673,7 -671,7 +663,7 @@@ static struct usb_serial_driver *search
        return NULL;
  }
  
- static int serial_carrier_raised(struct tty_port *port)
+ static int serial_port_carrier_raised(struct tty_port *port)
  {
        struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
        struct usb_serial_driver *drv = p->serial->type;
        return 1;
  }
  
- static void serial_dtr_rts(struct tty_port *port, int on)
+ static void serial_port_dtr_rts(struct tty_port *port, int on)
  {
        struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
        struct usb_serial *serial = p->serial;
  }
  
  static const struct tty_port_operations serial_port_ops = {
-       .carrier_raised = serial_carrier_raised,
-       .dtr_rts = serial_dtr_rts,
-       .activate = serial_activate,
-       .shutdown = serial_down,
+       .carrier_raised         = serial_port_carrier_raised,
+       .dtr_rts                = serial_port_dtr_rts,
+       .activate               = serial_port_activate,
+       .shutdown               = serial_port_shutdown,
  };
  
  static int usb_serial_probe(struct usb_interface *interface,
        serial = create_serial(dev, interface, type);
        if (!serial) {
                module_put(type->driver.owner);
-               dev_err(ddev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
  
                port->port.ops = &serial_port_ops;
                port->serial = serial;
                spin_lock_init(&port->lock);
-               init_waitqueue_head(&port->delta_msr_wait);
                /* Keep this for private driver use for the moment but
                   should probably go away */
                INIT_WORK(&port->work, usb_serial_port_work);
                port->dev.parent = &interface->dev;
                port->dev.driver = NULL;
                port->dev.bus = &usb_serial_bus_type;
-               port->dev.release = &port_release;
+               port->dev.release = &usb_serial_port_release;
                device_initialize(&port->dev);
        }
  
                for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
                        set_bit(j, &port->read_urbs_free);
                        port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->read_urbs[j]) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->read_urbs[j])
                                goto probe_error;
-                       }
                        port->bulk_in_buffers[j] = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->bulk_in_buffers[j]) {
-                               dev_err(ddev, "Couldn't allocate bulk_in_buffer\n");
+                       if (!port->bulk_in_buffers[j])
                                goto probe_error;
-                       }
                        usb_fill_bulk_urb(port->read_urbs[j], dev,
                                        usb_rcvbulkpipe(dev,
                                                endpoint->bEndpointAddress),
                for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
                        set_bit(j, &port->write_urbs_free);
                        port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->write_urbs[j]) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->write_urbs[j])
                                goto probe_error;
-                       }
                        port->bulk_out_buffers[j] = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->bulk_out_buffers[j]) {
-                               dev_err(ddev, "Couldn't allocate bulk_out_buffer\n");
+                       if (!port->bulk_out_buffers[j])
                                goto probe_error;
-                       }
                        usb_fill_bulk_urb(port->write_urbs[j], dev,
                                        usb_sndbulkpipe(dev,
                                                endpoint->bEndpointAddress),
                        endpoint = interrupt_in_endpoint[i];
                        port = serial->port[i];
                        port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->interrupt_in_urb) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->interrupt_in_urb)
                                goto probe_error;
-                       }
                        buffer_size = usb_endpoint_maxp(endpoint);
                        port->interrupt_in_endpointAddress =
                                                endpoint->bEndpointAddress;
                        port->interrupt_in_buffer = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->interrupt_in_buffer) {
-                               dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n");
+                       if (!port->interrupt_in_buffer)
                                goto probe_error;
-                       }
                        usb_fill_int_urb(port->interrupt_in_urb, dev,
                                usb_rcvintpipe(dev,
                                                endpoint->bEndpointAddress),
                        endpoint = interrupt_out_endpoint[i];
                        port = serial->port[i];
                        port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->interrupt_out_urb) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->interrupt_out_urb)
                                goto probe_error;
-                       }
                        buffer_size = usb_endpoint_maxp(endpoint);
                        port->interrupt_out_size = buffer_size;
                        port->interrupt_out_endpointAddress =
                                                endpoint->bEndpointAddress;
                        port->interrupt_out_buffer = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->interrupt_out_buffer) {
-                               dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n");
+                       if (!port->interrupt_out_buffer)
                                goto probe_error;
-                       }
                        usb_fill_int_urb(port->interrupt_out_urb, dev,
                                usb_sndintpipe(dev,
                                                  endpoint->bEndpointAddress),
@@@ -1113,13 -1093,15 +1085,15 @@@ static void usb_serial_disconnect(struc
                                tty_vhangup(tty);
                                tty_kref_put(tty);
                        }
-                       kill_traffic(port);
+                       usb_serial_port_poison_urbs(port);
+                       wake_up_interruptible(&port->port.delta_msr_wait);
                        cancel_work_sync(&port->work);
                        if (device_is_registered(&port->dev))
                                device_del(&port->dev);
                }
        }
-       serial->type->disconnect(serial);
+       if (serial->type->disconnect)
+               serial->type->disconnect(serial);
  
        /* let the last holder of this object cause it to be cleaned up */
        usb_serial_put(serial);
@@@ -1134,6 -1116,11 +1108,11 @@@ int usb_serial_suspend(struct usb_inter
  
        serial->suspending = 1;
  
+       /*
+        * serial->type->suspend() MUST return 0 in system sleep context,
+        * otherwise, the resume callback has to recover device from
+        * previous suspend failure.
+        */
        if (serial->type->suspend) {
                r = serial->type->suspend(serial, message);
                if (r < 0) {
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                if (port)
-                       kill_traffic(port);
+                       usb_serial_port_poison_urbs(port);
        }
  
  err_out:
  }
  EXPORT_SYMBOL(usb_serial_suspend);
  
+ static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
+ {
+       struct usb_serial_port *port;
+       int i;
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               if (port)
+                       usb_serial_port_unpoison_urbs(port);
+       }
+ }
  int usb_serial_resume(struct usb_interface *intf)
  {
        struct usb_serial *serial = usb_get_intfdata(intf);
        int rv;
  
+       usb_serial_unpoison_port_urbs(serial);
        serial->suspending = 0;
        if (serial->type->resume)
                rv = serial->type->resume(serial);
@@@ -1173,6 -1174,8 +1166,8 @@@ static int usb_serial_reset_resume(stru
        struct usb_serial *serial = usb_get_intfdata(intf);
        int rv;
  
+       usb_serial_unpoison_port_urbs(serial);
        serial->suspending = 0;
        if (serial->type->reset_resume)
                rv = serial->type->reset_resume(serial);
@@@ -1309,12 -1312,12 +1304,12 @@@ module_exit(usb_serial_exit)
        do {                                                            \
                if (!type->function) {                                  \
                        type->function = usb_serial_generic_##function; \
-                       pr_debug("Had to override the " #function       \
-                               " usb serial operation with the generic one.");\
-                       }                                               \
+                       pr_debug("%s: using generic " #function "\n",   \
+                                               type->driver.name);     \
+               }                                                       \
        } while (0)
  
- static void fixup_generic(struct usb_serial_driver *device)
+ static void usb_serial_operations_init(struct usb_serial_driver *device)
  {
        set_to_generic_if_null(device, open);
        set_to_generic_if_null(device, write);
        set_to_generic_if_null(device, chars_in_buffer);
        set_to_generic_if_null(device, read_bulk_callback);
        set_to_generic_if_null(device, write_bulk_callback);
-       set_to_generic_if_null(device, disconnect);
-       set_to_generic_if_null(device, release);
        set_to_generic_if_null(device, process_read_urb);
        set_to_generic_if_null(device, prepare_write_buffer);
  }
@@@ -1336,8 -1337,6 +1329,6 @@@ static int usb_serial_register(struct u
        if (usb_disabled())
                return -ENODEV;
  
-       fixup_generic(driver);
        if (!driver->description)
                driver->description = driver->driver.name;
        if (!driver->usb_driver) {
                return -EINVAL;
        }
  
+       usb_serial_operations_init(driver);
        /* Add this device to our list of devices */
        mutex_lock(&table_lock);
        list_add(&driver->driver_list, &usb_serial_driver_list);
@@@ -1463,7 -1464,6 +1456,6 @@@ void usb_serial_deregister_drivers(stru
  }
  EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
  
- /* Module information */
  MODULE_AUTHOR(DRIVER_AUTHOR);
  MODULE_DESCRIPTION(DRIVER_DESC);
  MODULE_LICENSE("GPL");