]> Git Repo - linux.git/commitdiff
Merge tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
authorLinus Torvalds <[email protected]>
Thu, 21 Feb 2013 21:41:04 +0000 (13:41 -0800)
committerLinus Torvalds <[email protected]>
Thu, 21 Feb 2013 21:41:04 +0000 (13:41 -0800)
Pull tty/serial patches from Greg Kroah-Hartman:
 "Here's the big tty/serial driver patches for 3.9-rc1.

  More tty port rework and fixes from Jiri here, as well as lots of
  individual serial driver updates and fixes.

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

* tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (140 commits)
  tty: mxser: improve error handling in mxser_probe() and mxser_module_init()
  serial: imx: fix uninitialized variable warning
  serial: tegra: assume CONFIG_OF
  TTY: do not update atime/mtime on read/write
  lguest: select CONFIG_TTY to build properly.
  ARM defconfigs: add missing inclusions of linux/platform_device.h
  fb/exynos: include platform_device.h
  ARM: sa1100/assabet: include platform_device.h directly
  serial: imx: Fix recursive locking bug
  pps: Fix build breakage from decoupling pps from tty
  tty: Remove ancient hardpps()
  pps: Additional cleanups in uart_handle_dcd_change
  pps: Move timestamp read into PPS code proper
  pps: Don't crash the machine when exiting will do
  pps: Fix a use-after free bug when unregistering a source.
  pps: Use pps_lookup_dev to reduce ldisc coupling
  pps: Add pps_lookup_dev() function
  tty: serial: uartlite: Support uartlite on big and little endian systems
  tty: serial: uartlite: Fix sparse and checkpatch warnings
  serial/arc-uart: Miscll DT related updates (Grant's review comments)
  ...

Fix up trivial conflicts, mostly just due to the TTY config option
clashing with the EXPERIMENTAL removal.

34 files changed:
1  2 
arch/alpha/Kconfig
arch/parisc/Kconfig
arch/tile/Kconfig
drivers/i2c/busses/Kconfig
drivers/input/serio/Kconfig
drivers/isdn/gigaset/interface.c
drivers/lguest/Kconfig
drivers/misc/Kconfig
drivers/net/can/Kconfig
drivers/net/irda/Kconfig
drivers/net/ppp/Kconfig
drivers/net/usb/Kconfig
drivers/net/usb/hso.c
drivers/net/wan/Kconfig
drivers/staging/fwserial/fwserial.c
drivers/staging/speakup/selection.c
drivers/tty/serial/max3100.c
drivers/tty/serial/sccnxp.c
drivers/tty/tty_io.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/u_serial.c
drivers/usb/serial/Kconfig
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/usb_wwan.c
include/linux/pci_ids.h
include/linux/proc_fs.h
lib/Kconfig.kgdb
sound/soc/codecs/Kconfig

diff --combined arch/alpha/Kconfig
index 775361f67bfd38cd0d370a13e368bc8be1619185,1ef196ddadebf8fe2459a1ed27b434daba8edd2c..dabc93649495617d31d68e7a2635d184c09238c8
@@@ -5,6 -5,7 +5,6 @@@ config ALPH
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_SYSCALL_WRAPPERS
 -      select HAVE_IRQ_WORK
        select HAVE_PCSPKR_PLATFORM
        select HAVE_PERF_EVENTS
        select HAVE_DMA_ATTRS
@@@ -124,6 -125,7 +124,7 @@@ choic
  
  config ALPHA_GENERIC
        bool "Generic"
+       depends on TTY
        help
          A generic kernel will run on all supported Alpha hardware.
  
@@@ -490,6 -492,7 +491,7 @@@ config VGA_HOS
  
  config ALPHA_SRM
        bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
+       depends on TTY
        default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
        ---help---
          There are two different types of booting firmware on Alphas: SRM,
@@@ -555,7 -558,8 +557,7 @@@ config NR_CPU
            with working support have a maximum of 4 CPUs.
  
  config ARCH_DISCONTIGMEM_ENABLE
 -      bool "Discontiguous Memory Support (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL
 +      bool "Discontiguous Memory Support"
        help
          Say Y to support efficient handling of discontiguous physical memory,
          for architectures which are either NUMA (Non-Uniform Memory Access)
diff --combined arch/parisc/Kconfig
index 9f2820659da24486af7e9788eead197a499ee044,df5beb6397605c54d62e447a27026a541ae09632..c600f39aa453a9abb362d133fee91578a4ffd35c
@@@ -9,18 -9,21 +9,19 @@@ config PARIS
        select RTC_DRV_GENERIC
        select INIT_ALL_POSSIBLE
        select BUG
 -      select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_GENERIC_HARDIRQS
        select BROKEN_RODATA
        select GENERIC_IRQ_PROBE
        select GENERIC_PCI_IOMAP
 -      select IRQ_PER_CPU
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS
+       select TTY # Needed for pdc_cons.c
  
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
@@@ -192,12 -195,12 +193,12 @@@ config PARISC_PAGE_SIZE_4K
          If you don't know what to do, choose 4KB.
  
  config PARISC_PAGE_SIZE_16KB
 -      bool "16KB (EXPERIMENTAL)"
 -      depends on PA8X00 && EXPERIMENTAL
 +      bool "16KB"
 +      depends on PA8X00
  
  config PARISC_PAGE_SIZE_64KB
 -      bool "64KB (EXPERIMENTAL)"
 -      depends on PA8X00 && EXPERIMENTAL
 +      bool "64KB"
 +      depends on PA8X00
  
  endchoice
  
diff --combined arch/tile/Kconfig
index 1bb7ad4aeff4754937bdc09f667110d28348fc96,ae8a7ca67fa46de34463ba08bada58b9ad6ca3ab..36136e81f5d8eec9c60976b02fdc3445b8955ad8
@@@ -121,6 -121,7 +121,7 @@@ config DEBUG_COPY_FROM_USE
        def_bool n
  
  config HVC_TILE
+       depends on TTY
        select HVC_DRIVER
        def_bool y
  
@@@ -140,8 -141,6 +141,8 @@@ config ARCH_DEFCONFI
  
  source "init/Kconfig"
  
 +source "kernel/Kconfig.freezer"
 +
  menu "Tilera-specific configuration"
  
  config NR_CPUS
index 9b94a78ca776e946b5c8d26c2052e7300bfaed0f,cf474b2df4ae0941b67b26e046396a479be9b67d..8bb810e1900b6448b10364f30b433384b7b67284
@@@ -22,7 -22,7 +22,7 @@@ config I2C_ALI153
  
  config I2C_ALI1563
        tristate "ALI 1563"
 -      depends on PCI && EXPERIMENTAL
 +      depends on PCI
        help
          If you say yes to this option, support will be included for the SMB
          Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
@@@ -56,7 -56,7 +56,7 @@@ config I2C_AMD75
  
  config I2C_AMD756_S4882
        tristate "SMBus multiplexing on the Tyan S4882"
 -      depends on I2C_AMD756 && X86 && EXPERIMENTAL
 +      depends on I2C_AMD756 && X86
        help
          Enabling this option will add specific SMBus support for the Tyan
          S4882 motherboard.  On this 4-CPU board, the SMBus is multiplexed
@@@ -164,7 -164,7 +164,7 @@@ config I2C_NFORCE
  
  config I2C_NFORCE2_S4985
        tristate "SMBus multiplexing on the Tyan S4985"
 -      depends on I2C_NFORCE2 && X86 && EXPERIMENTAL
 +      depends on I2C_NFORCE2 && X86
        help
          Enabling this option will add specific SMBus support for the Tyan
          S4985 motherboard.  On this 4-CPU board, the SMBus is multiplexed
@@@ -215,7 -215,7 +215,7 @@@ config I2C_SIS96
  
  config I2C_VIA
        tristate "VIA VT82C586B"
 -      depends on PCI && EXPERIMENTAL
 +      depends on PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the VIA
@@@ -267,7 -267,7 +267,7 @@@ comment "Mac SMBus host controller driv
  
  config I2C_HYDRA
        tristate "CHRP Apple Hydra Mac I/O I2C interface"
 -      depends on PCI && PPC_CHRP && EXPERIMENTAL
 +      depends on PCI && PPC_CHRP
        select I2C_ALGOBIT
        help
          This supports the use of the I2C interface in the Apple Hydra Mac
@@@ -293,7 -293,7 +293,7 @@@ comment "I2C system bus drivers (mostl
  
  config I2C_AT91
        tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
 -      depends on ARCH_AT91 && EXPERIMENTAL
 +      depends on ARCH_AT91
        help
          This supports the use of the I2C interface on Atmel AT91
          processors.
@@@ -519,6 -519,7 +519,6 @@@ config I2C_NUC90
  
  config I2C_OCORES
        tristate "OpenCores I2C Controller"
 -      depends on EXPERIMENTAL
        help
          If you say yes to this option, support will be included for the
          OpenCores I2C controller. For details see
@@@ -711,7 -712,7 +711,7 @@@ config I2C_OCTEO
  
  config I2C_XILINX
        tristate "Xilinx I2C Controller"
 -      depends on EXPERIMENTAL && HAS_IOMEM
 +      depends on HAS_IOMEM
        help
          If you say yes to this option, support will be included for the
          Xilinx I2C controller.
@@@ -802,6 -803,7 +802,7 @@@ config I2C_PARPORT_LIGH
  
  config I2C_TAOS_EVM
        tristate "TAOS evaluation module"
 -      depends on EXPERIMENTAL && TTY
++      depends on TTY
        select SERIO
        select SERIO_SERPORT
        default n
index 560c243bfcaf41181e7cfbfc88e0a1cb266fce3d,fe4e4953d5f55f49913c798b1aed2369ac156834..6e9cc765e0dc036d0ea3d8d991aa4fe7d718a837
@@@ -36,6 -36,7 +36,7 @@@ config SERIO_I804
  config SERIO_SERPORT
        tristate "Serial port line discipline"
        default y
+       depends on TTY
        help
          Say Y here if you plan to use an input device (mouse, joystick,
          tablet, 6dof) that communicates over the RS232 serial (COM) port.
@@@ -236,7 -237,6 +237,7 @@@ config SERIO_PS2MUL
  
  config SERIO_ARC_PS2
        tristate "ARC PS/2 support"
 +      depends on GENERIC_HARDIRQS
        help
          Say Y here if you have an ARC FPGA platform with a PS/2
          controller in it.
index 20b7e7a1190f317bbf31d072c809ab70e919514b,0fbf4f215d865cbb8782110ff274fd04589e8a86..e2b539675b665d72aa1fe183cd9f0a61ad0262c2
@@@ -112,6 -112,36 +112,6 @@@ static int if_config(struct cardstate *
  }
  
  /*** the terminal driver ***/
 -/* stolen from usbserial and some other tty drivers */
 -
 -static int  if_open(struct tty_struct *tty, struct file *filp);
 -static void if_close(struct tty_struct *tty, struct file *filp);
 -static int  if_ioctl(struct tty_struct *tty,
 -                   unsigned int cmd, unsigned long arg);
 -static int  if_write_room(struct tty_struct *tty);
 -static int  if_chars_in_buffer(struct tty_struct *tty);
 -static void if_throttle(struct tty_struct *tty);
 -static void if_unthrottle(struct tty_struct *tty);
 -static void if_set_termios(struct tty_struct *tty, struct ktermios *old);
 -static int  if_tiocmget(struct tty_struct *tty);
 -static int  if_tiocmset(struct tty_struct *tty,
 -                      unsigned int set, unsigned int clear);
 -static int  if_write(struct tty_struct *tty,
 -                   const unsigned char *buf, int count);
 -
 -static const struct tty_operations if_ops = {
 -      .open =                 if_open,
 -      .close =                if_close,
 -      .ioctl =                if_ioctl,
 -      .write =                if_write,
 -      .write_room =           if_write_room,
 -      .chars_in_buffer =      if_chars_in_buffer,
 -      .set_termios =          if_set_termios,
 -      .throttle =             if_throttle,
 -      .unthrottle =           if_unthrottle,
 -      .tiocmget =             if_tiocmget,
 -      .tiocmset =             if_tiocmset,
 -};
  
  static int if_open(struct tty_struct *tty, struct file *filp)
  {
  
        if (cs->port.count == 1) {
                tty_port_tty_set(&cs->port, tty);
-               tty->low_latency = 1;
+               cs->port.low_latency = 1;
        }
  
        mutex_unlock(&cs->mutex);
@@@ -325,7 -355,7 +325,7 @@@ done
  static int if_write_room(struct tty_struct *tty)
  {
        struct cardstate *cs = tty->driver_data;
 -      int retval = -ENODEV;
 +      int retval;
  
        gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
  
@@@ -468,20 -498,6 +468,20 @@@ out
        mutex_unlock(&cs->mutex);
  }
  
 +static const struct tty_operations if_ops = {
 +      .open =                 if_open,
 +      .close =                if_close,
 +      .ioctl =                if_ioctl,
 +      .write =                if_write,
 +      .write_room =           if_write_room,
 +      .chars_in_buffer =      if_chars_in_buffer,
 +      .set_termios =          if_set_termios,
 +      .throttle =             if_throttle,
 +      .unthrottle =           if_unthrottle,
 +      .tiocmget =             if_tiocmget,
 +      .tiocmset =             if_tiocmset,
 +};
 +
  
  /* wakeup tasklet for the write operation */
  static void if_wake(unsigned long data)
@@@ -546,16 -562,8 +546,8 @@@ void gigaset_if_free(struct cardstate *
  void gigaset_if_receive(struct cardstate *cs,
                        unsigned char *buffer, size_t len)
  {
-       struct tty_struct *tty = tty_port_tty_get(&cs->port);
-       if (tty == NULL) {
-               gig_dbg(DEBUG_IF, "receive on closed device");
-               return;
-       }
-       tty_insert_flip_string(tty, buffer, len);
-       tty_flip_buffer_push(tty);
-       tty_kref_put(tty);
+       tty_insert_flip_string(&cs->port, buffer, len);
+       tty_flip_buffer_push(&cs->port);
  }
  EXPORT_SYMBOL_GPL(gigaset_if_receive);
  
diff --combined drivers/lguest/Kconfig
index 6cdcdb0d3d58119182bf77ca0106809fb81f72fd,f9c43145a611a6910b1fd67445c2d366645f966a..89875ea19ade465cf0f47573da5e9a054b21d683
@@@ -1,6 -1,6 +1,6 @@@
  config LGUEST
        tristate "Linux hypervisor example code"
-       depends on X86_32 && EVENTFD
 -      depends on X86_32 && EXPERIMENTAL && EVENTFD && TTY
++      depends on X86_32 && EVENTFD && TTY
        select HVC_DRIVER
        ---help---
          This is a very simple module which allows you to run
diff --combined drivers/misc/Kconfig
index 8f59d88897e7287354354b1c2f7cf807e97b18b3,4b2bb939dde16d8f3878dd98922fcd168fac14f3..668a5822ab4e8af1db7075dec09e3d005a62692c
@@@ -127,7 -127,7 +127,7 @@@ config PHANTO
  
  config INTEL_MID_PTI
        tristate "Parallel Trace Interface for MIPI P1149.7 cJTAG standard"
-       depends on PCI
+       depends on PCI && TTY
        default n
        help
          The PTI (Parallel Trace Interface) driver directs
@@@ -192,7 -192,7 +192,7 @@@ config ICS932S40
  
  config ATMEL_SSC
        tristate "Device driver for Atmel SSC peripheral"
 -      depends on AVR32 || ARCH_AT91
 +      depends on HAS_IOMEM
        ---help---
          This option enables device driver support for Atmel Synchronized
          Serial Communication peripheral (SSC).
diff --combined drivers/net/can/Kconfig
index 1cca19f1c490b5807f5862d6d75d90f7752b6c9e,72df3a306a08994b0a26242fdd8b5f49b1666a7e..9862b2e07644462b59fe81c137c7ad6d835bd2d8
@@@ -1,7 -1,9 +1,7 @@@
  menu "CAN Device Drivers"
 -      depends on CAN
  
  config CAN_VCAN
        tristate "Virtual Local CAN Interface (vcan)"
 -      depends on CAN
        ---help---
          Similar to the network loopback devices, vcan offers a
          virtual local CAN interface.
@@@ -11,6 -13,7 +11,7 @@@
  
  config CAN_SLCAN
        tristate "Serial / USB serial CAN Adaptors (slcan)"
 -      depends on CAN && TTY
++      depends on TTY
        ---help---
          CAN driver for several 'low cost' CAN interfaces that are attached
          via serial lines or via USB-to-serial adapters using the LAWICEL
  
  config CAN_DEV
        tristate "Platform CAN drivers with Netlink support"
 -      depends on CAN
        default y
        ---help---
          Enables the common framework for platform CAN drivers with Netlink
          support. This is the standard library for CAN drivers.
          If unsure, say Y.
  
 +if CAN_DEV
 +
  config CAN_CALC_BITTIMING
        bool "CAN bit-timing calculation"
 -      depends on CAN_DEV
        default y
        ---help---
          If enabled, CAN bit-timing parameters will be calculated for the
          arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
          If unsure, say Y.
  
 +config CAN_LEDS
 +      bool "Enable LED triggers for Netlink based drivers"
 +      depends on LEDS_CLASS
 +      select LEDS_TRIGGERS
 +      ---help---
 +        This option adds two LED triggers for packet receive and transmit
 +        events on each supported CAN device.
 +
 +        Say Y here if you are working on a system with led-class supported
 +        LEDs and you want to use them as canbus activity indicators.
 +
  config CAN_AT91
        tristate "Atmel AT91 onchip CAN controller"
 -      depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
 +      depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5
        ---help---
          This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
          and AT91SAM9X5 processors.
  
  config CAN_TI_HECC
 -      depends on CAN_DEV && ARCH_OMAP3
 +      depends on ARCH_OMAP3
        tristate "TI High End CAN Controller"
        ---help---
          Driver for TI HECC (High End CAN Controller) module found on many
  
  config CAN_MCP251X
        tristate "Microchip MCP251x SPI CAN controllers"
 -      depends on CAN_DEV && SPI && HAS_DMA
 +      depends on SPI && HAS_DMA
        ---help---
          Driver for the Microchip MCP251x SPI CAN controllers.
  
  config CAN_BFIN
 -      depends on CAN_DEV && (BF534 || BF536 || BF537 || BF538 || BF539 || BF54x)
 +      depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x
        tristate "Analog Devices Blackfin on-chip CAN"
        ---help---
          Driver for the Analog Devices Blackfin on-chip CAN controllers
@@@ -93,7 -85,7 +94,7 @@@
  
  config CAN_JANZ_ICAN3
        tristate "Janz VMOD-ICAN3 Intelligent CAN controller"
 -      depends on CAN_DEV && MFD_JANZ_CMODIO
 +      depends on MFD_JANZ_CMODIO
        ---help---
          Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which
          connects to a MODULbus carrier board.
@@@ -106,13 -98,13 +107,13 @@@ config HAVE_CAN_FLEXCA
  
  config CAN_FLEXCAN
        tristate "Support for Freescale FLEXCAN based chips"
 -      depends on CAN_DEV && HAVE_CAN_FLEXCAN
 +      depends on HAVE_CAN_FLEXCAN
        ---help---
          Say Y here if you want to support for Freescale FlexCAN.
  
  config PCH_CAN
        tristate "Intel EG20T PCH CAN controller"
 -      depends on CAN_DEV && PCI
 +      depends on PCI
        ---help---
          This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which
          is an IOH for x86 embedded processor (Intel Atom E6xx series).
  
  config CAN_GRCAN
        tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
 -      depends on CAN_DEV && OF
 +      depends on OF
        ---help---
          Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
          Note that the driver supports little endian, even though little
@@@ -139,10 -131,9 +140,10 @@@ source "drivers/net/can/usb/Kconfig
  
  source "drivers/net/can/softing/Kconfig"
  
 +endif
 +
  config CAN_DEBUG_DEVICES
        bool "CAN devices debugging messages"
 -      depends on CAN
        ---help---
          Say Y here if you want the CAN device drivers to produce a bunch of
          debug messages to the system log.  Select this if you are having
diff --combined drivers/net/irda/Kconfig
index 59e9d9e1fd0fa94877e3347dfad2036a2d95d435,e1454cdec14b2b968bb3282818597b45de4c0e31..2a30193d0d50b5f5a348bc21056ec0cfd2224098
@@@ -5,7 -5,7 +5,7 @@@ comment "SIR device drivers
  
  config IRTTY_SIR
        tristate "IrTTY (uses Linux serial driver)"
-       depends on IRDA
+       depends on IRDA && TTY
        help
          Say Y here if you want to build support for the IrTTY line
          discipline.  To compile it as a module, choose M here: the module
@@@ -140,7 -140,7 +140,7 @@@ config LITELINK_DONGL
  
  config MA600_DONGLE
        tristate "Mobile Action MA600 dongle"
 -      depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
 +      depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Mobile Action MA600
          dongle.  To compile it as a module, choose M here. The MA600 dongle
  
  config GIRBIL_DONGLE
        tristate "Greenwich GIrBIL dongle"
 -      depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
 +      depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Greenwich GIrBIL
          dongle.  If you want to compile it as a module, choose M here.
  
  config MCP2120_DONGLE
        tristate "Microchip MCP2120"
 -      depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
 +      depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Microchip MCP2120
          dongle.  If you want to compile it as a module, choose M here.
  
  config OLD_BELKIN_DONGLE
        tristate "Old Belkin dongle"
 -      depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
 +      depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Adaptec Airport 1000
          and 2000 dongles.  If you want to compile it as a module, choose
  
  config ACT200L_DONGLE
        tristate "ACTiSYS IR-200L dongle"
 -      depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
 +      depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the ACTiSYS IR-200L
          dongle. If you want to compile it as a module, choose M here.
  
  config KINGSUN_DONGLE
        tristate "KingSun/DonShine DS-620 IrDA-USB dongle"
 -      depends on IRDA && USB && EXPERIMENTAL
 +      depends on IRDA && USB
        help
          Say Y or M here if you want to build support for the KingSun/DonShine
          DS-620 IrDA-USB bridge device driver.
  
  config EP7211_DONGLE
        tristate "Cirrus Logic clps711x I/R support"
 -      depends on IRTTY_SIR && ARCH_CLPS711X && IRDA && EXPERIMENTAL
 +      depends on IRTTY_SIR && ARCH_CLPS711X && IRDA
        help
          Say Y here if you want to build support for the Cirrus logic
          EP7211 chipset's infrared module.
  
  config KSDAZZLE_DONGLE
 -      tristate "KingSun Dazzle IrDA-USB dongle (EXPERIMENTAL)"
 -      depends on IRDA && USB && EXPERIMENTAL
 +      tristate "KingSun Dazzle IrDA-USB dongle"
 +      depends on IRDA && USB
        help
          Say Y or M here if you want to build support for the KingSun Dazzle
          IrDA-USB bridge device driver.
          ksdazzle-sir.
  
  config KS959_DONGLE
 -      tristate "KingSun KS-959 IrDA-USB dongle (EXPERIMENTAL)"
 -      depends on IRDA && USB && EXPERIMENTAL
 +      tristate "KingSun KS-959 IrDA-USB dongle"
 +      depends on IRDA && USB
        help
          Say Y or M here if you want to build support for the KingSun KS-959
          IrDA-USB bridge device driver.
@@@ -264,8 -264,8 +264,8 @@@ config USB_IRD
          you will need both USB and IrDA support in your kernel...
  
  config SIGMATEL_FIR
 -      tristate "SigmaTel STIr4200 bridge (EXPERIMENTAL)"
 -      depends on IRDA && USB && EXPERIMENTAL
 +      tristate "SigmaTel STIr4200 bridge"
 +      depends on IRDA && USB
        select CRC32
        ---help---
          Say Y here if you want to build support for the SigmaTel STIr4200
@@@ -331,8 -331,8 +331,8 @@@ config SMC_IRCC_FI
          smsc-ircc2.o.
  
  config ALI_FIR
 -      tristate "ALi M5123 FIR (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && IRDA && ISA_DMA_API
 +      tristate "ALi M5123 FIR"
 +      depends on IRDA && ISA_DMA_API
        help
          Say Y here if you want to build support for the ALi M5123 FIR
          Controller.  The ALi M5123 FIR Controller is embedded in ALi M1543C,
          ali-ircc.
  
  config VLSI_FIR
 -      tristate "VLSI 82C147 SIR/MIR/FIR (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && IRDA && PCI
 +      tristate "VLSI 82C147 SIR/MIR/FIR"
 +      depends on IRDA && PCI
        help
          Say Y here if you want to build support for the VLSI 82C147
          PCI-IrDA Controller. This controller is used by the HP OmniBook 800
@@@ -387,7 -387,7 +387,7 @@@ config PXA_FIC
  
  config MCS_FIR
        tristate "MosChip MCS7780 IrDA-USB dongle"
 -      depends on IRDA && USB && EXPERIMENTAL
 +      depends on IRDA && USB
        select CRC32
        help
          Say Y or M here if you want to build support for the MosChip
diff --combined drivers/net/ppp/Kconfig
index 278dea0c4c983da461b6b748dff760e905f3556a,3d9ef4f1e6000dc534b4612ccc43c545cdafe060..1373c6d7278d84dbcfb84a936745e01d8273aa44
@@@ -82,8 -82,8 +82,8 @@@ config PPP_FILTE
          If unsure, say N.
  
  config PPP_MPPE
 -      tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
 -      depends on PPP && EXPERIMENTAL
 +      tristate "PPP MPPE compression (encryption)"
 +      depends on PPP
        select CRYPTO
        select CRYPTO_SHA1
        select CRYPTO_ARC4
@@@ -96,8 -96,8 +96,8 @@@
          configuring PPTP clients and servers to utilize this method.
  
  config PPP_MULTILINK
 -      bool "PPP multilink support (EXPERIMENTAL)"
 -      depends on PPP && EXPERIMENTAL
 +      bool "PPP multilink support"
 +      depends on PPP
        ---help---
          PPP multilink is a protocol (defined in RFC 1990) which allows you
          to combine several (logical or physical) lines into one logical PPP
@@@ -118,8 -118,8 +118,8 @@@ config PPPOAT
          changes its encapsulation unilaterally.
  
  config PPPOE
 -      tristate "PPP over Ethernet (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && PPP
 +      tristate "PPP over Ethernet"
 +      depends on PPP
        ---help---
          Support for PPP over Ethernet.
  
          the heading "Kernel mode PPPoE").
  
  config PPTP
 -      tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
 +      tristate "PPP over IPv4 (PPTP)"
 +      depends on PPP && NET_IPGRE_DEMUX
        ---help---
          Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
  
          utilize this module.
  
  config PPPOL2TP
 -      tristate "PPP over L2TP (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && L2TP && PPP
 +      tristate "PPP over L2TP"
 +      depends on L2TP && PPP
        ---help---
          Support for PPP-over-L2TP socket family. L2TP is a protocol
          used by ISPs and enterprises to tunnel PPP traffic over UDP
          tunnels. L2TP is replacing PPTP for VPN uses.
+ if TTY
  
  config PPP_ASYNC
        tristate "PPP support for async serial ports"
@@@ -172,4 -173,6 +173,6 @@@ config PPP_SYNC_TT
  
          To compile this driver as a module, choose M here.
  
+ endif # TTY
  endif # PPP
diff --combined drivers/net/usb/Kconfig
index 3a44a5d7bf9eb5419ec87ff43531a95f79ff4106,bd33153261ce506d86c4ecde6e29c97c29111e49..da92ed3797aa32e763c1496a5dce9cca4a273bd5
@@@ -8,7 -8,8 +8,7 @@@ menu "USB Network Adapters
        depends on USB && NET
  
  config USB_CATC
 -      tristate "USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL
 +      tristate "USB CATC NetMate-based Ethernet device support"
        select CRC32
        ---help---
          Say Y if you want to use one of the following 10Mbps USB Ethernet
@@@ -82,7 -83,8 +82,7 @@@ config USB_PEGASU
          module will be called pegasus.
  
  config USB_RTL8150
 -      tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL
 +      tristate "USB RTL8150 based ethernet device support"
        select NET_CORE
        select MII
        help
@@@ -186,7 -188,7 +186,7 @@@ config USB_NET_CDCETHE
  
  config USB_NET_CDC_EEM
        tristate "CDC EEM support"
 -      depends on USB_USBNET && EXPERIMENTAL
 +      depends on USB_USBNET
        help
          This option supports devices conforming to the Communication Device
          Class (CDC) Ethernet Emulation Model, a specification that's easy to
@@@ -285,7 -287,7 +285,7 @@@ config USB_NET_PLUS
        tristate "Prolific PL-2301/2302/25A1 based cables"
        # if the handshake/init/reset problems, from original 'plusb',
        # are ever resolved ... then remove "experimental"
 -      depends on USB_USBNET && EXPERIMENTAL
 +      depends on USB_USBNET
        help
          Choose this option if you're using a host-to-host cable
          with one of these chips.
@@@ -299,8 -301,8 +299,8 @@@ config USB_NET_MCS783
          adapters marketed under the DeLOCK brand.
  
  config USB_NET_RNDIS_HOST
 -      tristate "Host for RNDIS and ActiveSync devices (EXPERIMENTAL)"
 -      depends on USB_USBNET && EXPERIMENTAL
 +      tristate "Host for RNDIS and ActiveSync devices"
 +      depends on USB_USBNET
        select USB_NET_CDCETHER
        help
          This option enables hosting "Remote NDIS" USB networking links,
@@@ -378,7 -380,7 +378,7 @@@ config USB_EPSON288
  
  config USB_KC2190
        boolean "KT Technology KC2190 based cables (InstaNet)"
 -      depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
 +      depends on USB_NET_CDC_SUBSET
        help
          Choose this option if you're using a host-to-host cable
          with one of these chips.
@@@ -443,7 -445,7 +443,7 @@@ config USB_NET_QMI_WWA
  
  config USB_HSO
        tristate "Option USB High Speed Mobile Devices"
-       depends on USB && RFKILL
+       depends on USB && RFKILL && TTY
        default n
        help
          Choose this option if you have an Option HSDPA/HSUPA card.
@@@ -491,7 -493,7 +491,7 @@@ config USB_SIERRA_NE
  
  config USB_VL600
        tristate "LG VL600 modem dongle"
-       depends on USB_NET_CDCETHER
+       depends on USB_NET_CDCETHER && TTY
        select USB_ACM
        help
          Select this if you want to use an LG Electronics 4G/LTE usb modem
diff --combined drivers/net/usb/hso.c
index 41e5dfb5ee64eb0029d0c9a769759db58d5fbd52,f902a14da88cfc4987a2f30e964db8c075b0243d..e2dd3249b6bd3632d3d1750f2e992bea13f0178f
@@@ -2035,25 -2035,23 +2035,23 @@@ static int put_rxbuf_data(struct urb *u
        tty = tty_port_tty_get(&serial->port);
  
        /* Push data to tty */
-       if (tty) {
-               write_length_remaining = urb->actual_length -
-                       serial->curr_rx_urb_offset;
-               D1("data to push to tty");
-               while (write_length_remaining) {
-                       if (test_bit(TTY_THROTTLED, &tty->flags)) {
-                               tty_kref_put(tty);
-                               return -1;
-                       }
-                       curr_write_len =  tty_insert_flip_string
-                               (tty, urb->transfer_buffer +
-                                serial->curr_rx_urb_offset,
-                                write_length_remaining);
-                       serial->curr_rx_urb_offset += curr_write_len;
-                       write_length_remaining -= curr_write_len;
-                       tty_flip_buffer_push(tty);
+       write_length_remaining = urb->actual_length -
+               serial->curr_rx_urb_offset;
+       D1("data to push to tty");
+       while (write_length_remaining) {
+               if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
+                       tty_kref_put(tty);
+                       return -1;
                }
-               tty_kref_put(tty);
+               curr_write_len = tty_insert_flip_string(&serial->port,
+                       urb->transfer_buffer + serial->curr_rx_urb_offset,
+                       write_length_remaining);
+               serial->curr_rx_urb_offset += curr_write_len;
+               write_length_remaining -= curr_write_len;
+               tty_flip_buffer_push(&serial->port);
        }
+       tty_kref_put(tty);
        if (write_length_remaining == 0) {
                serial->curr_rx_urb_offset = 0;
                serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
@@@ -2317,8 -2315,10 +2315,8 @@@ static int hso_serial_common_create(str
                serial->rx_urb[i]->transfer_buffer_length = 0;
                serial->rx_data[i] = kzalloc(serial->rx_data_length,
                                             GFP_KERNEL);
 -              if (!serial->rx_data[i]) {
 -                      dev_err(dev, "%s - Out of memory\n", __func__);
 +              if (!serial->rx_data[i])
                        goto exit;
 -              }
        }
  
        /* TX, allocate urb and initialize */
        serial->tx_buffer_count = 0;
        serial->tx_data_length = tx_size;
        serial->tx_data = kzalloc(serial->tx_data_length, GFP_KERNEL);
 -      if (!serial->tx_data) {
 -              dev_err(dev, "%s - Out of memory\n", __func__);
 +      if (!serial->tx_data)
                goto exit;
 -      }
 +
        serial->tx_buffer = kzalloc(serial->tx_data_length, GFP_KERNEL);
 -      if (!serial->tx_buffer) {
 -              dev_err(dev, "%s - Out of memory\n", __func__);
 +      if (!serial->tx_buffer)
                goto exit;
 -      }
  
        return 0;
  exit:
@@@ -2575,8 -2578,10 +2573,8 @@@ static struct hso_device *hso_create_ne
                }
                hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE,
                                                           GFP_KERNEL);
 -              if (!hso_net->mux_bulk_rx_buf_pool[i]) {
 -                      dev_err(&interface->dev, "Could not allocate rx buf\n");
 +              if (!hso_net->mux_bulk_rx_buf_pool[i])
                        goto exit;
 -              }
        }
        hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!hso_net->mux_bulk_tx_urb) {
                goto exit;
        }
        hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL);
 -      if (!hso_net->mux_bulk_tx_buf) {
 -              dev_err(&interface->dev, "Could not allocate tx buf\n");
 +      if (!hso_net->mux_bulk_tx_buf)
                goto exit;
 -      }
  
        add_net_device(hso_dev);
  
@@@ -2809,8 -2816,10 +2807,8 @@@ struct hso_shared_int *hso_create_share
        mux->shared_intr_buf =
                kzalloc(le16_to_cpu(mux->intr_endp->wMaxPacketSize),
                        GFP_KERNEL);
 -      if (!mux->shared_intr_buf) {
 -              dev_err(&interface->dev, "Could not allocate intr buf?\n");
 +      if (!mux->shared_intr_buf)
                goto exit;
 -      }
  
        mutex_init(&mux->shared_int_lock);
  
diff --combined drivers/net/wan/Kconfig
index 13daec88d918ddd07ba7d317c2937db8cc87c63e,61eb8994b34f90fdce5fbf5b34894d2a158d1d4e..94e234975c6114d0e46fde4c71c34625596fe6f4
@@@ -356,9 -356,63 +356,9 @@@ config SDL
          To compile this driver as a module, choose M here: the
          module will be called sdla.
  
 -# Wan router core.
 -config WAN_ROUTER_DRIVERS
 -      tristate "WAN router drivers"
 -      depends on WAN_ROUTER
 -      ---help---
 -        Connect LAN to WAN via Linux box.
 -
 -        Select driver your card and remember to say Y to "Wan Router."
 -        You will need the wan-tools package which is available from
 -        <ftp://ftp.sangoma.com/>.
 -
 -        Note that the answer to this question won't directly affect the
 -        kernel except for how subordinate drivers may be built:
 -        saying N will just cause the configurator to skip all
 -        the questions about WAN router drivers.
 -
 -        If unsure, say N.
 -
 -config CYCLADES_SYNC
 -      tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
 -      depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
 -      ---help---
 -        Cyclom 2X from Cyclades Corporation <http://www.avocent.com/> is an
 -        intelligent multiprotocol WAN adapter with data transfer rates up to
 -        512 Kbps. These cards support the X.25 and SNA related protocols.
 -
 -        While no documentation is available at this time please grab the
 -        wanconfig tarball in
 -        <http://www.conectiva.com.br/~acme/cycsyn-devel/> (with minor changes
 -        to make it compile with the current wanrouter include files; efforts
 -        are being made to use the original package available at
 -        <ftp://ftp.sangoma.com/>).
 -
 -        Feel free to contact me or the cycsyn-devel mailing list at
 -        <[email protected]> and <[email protected]> for
 -        additional details, I hope to have documentation available as soon as
 -        possible. (Cyclades Brazil is writing the Documentation).
 -
 -        The next questions will ask you about the protocols you want the
 -        driver to support (for now only X.25 is supported).
 -
 -        If you have one or more of these cards, say Y to this option.
 -
 -        To compile this driver as a module, choose M here: the
 -        module will be called cyclomx.
 -
 -config CYCLOMX_X25
 -      bool "Cyclom 2X X.25 support (EXPERIMENTAL)"
 -      depends on CYCLADES_SYNC
 -      help
 -        Connect a Cyclom 2X card to an X.25 network.
 -
 -        Enabling X.25 support will enlarge your kernel by about 11 kB.
 -
  # X.25 network drivers
  config LAPBETHER
 -      tristate "LAPB over Ethernet driver (EXPERIMENTAL)"
 +      tristate "LAPB over Ethernet driver"
        depends on LAPB && X25
        ---help---
          Driver for a pseudo device (typically called /dev/lapb0) which allows
          If unsure, say N.
  
  config X25_ASY
 -      tristate "X.25 async driver (EXPERIMENTAL)"
 +      tristate "X.25 async driver"
-       depends on LAPB && X25
+       depends on LAPB && X25 && TTY
        ---help---
          Send and receive X.25 frames over regular asynchronous serial
          lines such as telephone lines equipped with ordinary modems.
index 8859c75f16fa555bfbbe0f80c1c883ff1396c431,e5e8f2f36e0ce72a530564d81d9970695999977d..5a6fb44f38a8ae22a2d6d8d8786b3788dc7f9f07
@@@ -40,10 -40,12 +40,10 @@@ static int num_ttys = 4;       /* # of st
                                    /* - doubles as loopback port index       */
  static bool auto_connect = true;    /* try to VIRT_CABLE to every peer        */
  static bool create_loop_dev = true; /* create a loopback device for each card */
 -bool limit_bw;                            /* limit async bandwidth to 20% of max    */
  
  module_param_named(ttys, num_ttys, int, S_IRUGO | S_IWUSR);
  module_param_named(auto, auto_connect, bool, S_IRUGO | S_IWUSR);
  module_param_named(loop, create_loop_dev, bool, S_IRUGO | S_IWUSR);
 -module_param(limit_bw, bool, S_IRUGO | S_IWUSR);
  
  /*
   * Threshold below which the tty is woken for writing
@@@ -72,20 -74,12 +72,20 @@@ static DEFINE_MUTEX(port_table_lock)
  static bool port_table_corrupt;
  #define FWTTY_INVALID_INDEX  MAX_TOTAL_PORTS
  
 +#define loop_idx(port)        (((port)->index) / num_ports)
 +#define table_idx(loop)       ((loop) * num_ports + num_ttys)
 +
  /* total # of tty ports created per fw_card */
  static int num_ports;
  
  /* slab used as pool for struct fwtty_transactions */
  static struct kmem_cache *fwtty_txn_cache;
  
 +struct tty_driver *fwtty_driver;
 +static struct tty_driver *fwloop_driver;
 +
 +static struct dentry *fwserial_debugfs;
 +
  struct fwtty_transaction;
  typedef void (*fwtty_transaction_cb)(struct fw_card *card, int rcode,
                                     void *data, size_t length,
@@@ -182,15 -176,10 +182,15 @@@ static void dump_profile(struct seq_fil
  #define dump_profile(m, stats)
  #endif
  
 -/* Returns the max receive packet size for the given card */
 +/*
 + * Returns the max receive packet size for the given node
 + * Devices which are OHCI v1.0/ v1.1/ v1.2-draft or RFC 2734 compliant
 + * are required by specification to support max_rec of 8 (512 bytes) or more.
 + */
  static inline int device_max_receive(struct fw_device *fw_device)
  {
 -      return 1 <<  (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1);
 +      /* see IEEE 1394-2008 table 8-8 */
 +      return min(2 << fw_device->max_rec, 4096);
  }
  
  static void fwtty_log_tx_error(struct fwtty_port *port, int rcode)
@@@ -500,16 -489,11 +500,11 @@@ static void fwtty_do_hangup(struct work
  static void fwtty_emit_breaks(struct work_struct *work)
  {
        struct fwtty_port *port = to_port(to_delayed_work(work), emit_breaks);
-       struct tty_struct *tty;
        static const char buf[16];
        unsigned long now = jiffies;
        unsigned long elapsed = now - port->break_last;
        int n, t, c, brk = 0;
  
-       tty = tty_port_tty_get(&port->port);
-       if (!tty)
-               return;
        /* generate breaks at the line rate (but at least 1) */
        n = (elapsed * port->cps) / HZ + 1;
        port->break_last = now;
  
        while (n) {
                t = min(n, 16);
-               c = tty_insert_flip_string_fixed_flag(tty, buf, TTY_BREAK, t);
+               c = tty_insert_flip_string_fixed_flag(&port->port, buf,
+                               TTY_BREAK, t);
                n -= c;
                brk += c;
                if (c < t)
                        break;
        }
-       tty_flip_buffer_push(tty);
-       tty_kref_put(tty);
+       tty_flip_buffer_push(&port->port);
  
        if (port->mstatus & (UART_LSR_BI << 24))
                schedule_delayed_work(&port->emit_breaks, FREQ_BREAKS);
@@@ -540,13 -523,9 +534,9 @@@ static void fwtty_pushrx(struct work_st
        struct buffered_rx *buf, *next;
        int n, c = 0;
  
-       tty = tty_port_tty_get(&port->port);
-       if (!tty)
-               return;
        spin_lock_bh(&port->lock);
        list_for_each_entry_safe(buf, next, &port->buf_list, list) {
-               n = tty_insert_flip_string_fixed_flag(tty, buf->data,
+               n = tty_insert_flip_string_fixed_flag(&port->port, buf->data,
                                                      TTY_NORMAL, buf->n);
                c += n;
                port->buffered -= n;
                                memmove(buf->data, buf->data + n, buf->n - n);
                                buf->n -= n;
                        }
-                       __fwtty_throttle(port, tty);
+                       tty = tty_port_tty_get(&port->port);
+                       if (tty) {
+                               __fwtty_throttle(port, tty);
+                               tty_kref_put(tty);
+                       }
                        break;
                } else {
                        list_del(&buf->list);
                }
        }
        if (c > 0)
-               tty_flip_buffer_push(tty);
+               tty_flip_buffer_push(&port->port);
  
        if (list_empty(&port->buf_list))
                clear_bit(BUFFERING_RX, &port->flags);
        spin_unlock_bh(&port->lock);
-       tty_kref_put(tty);
  }
  
  static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n)
        struct buffered_rx *buf;
        size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF;
  
 -      if (port->buffered + n > HIGH_WATERMARK)
 +      if (port->buffered + n > HIGH_WATERMARK) {
 +              fwtty_err_ratelimited(port, "overflowed rx buffer: buffered: %d new: %zu wtrmk: %d",
 +                                    port->buffered, n, HIGH_WATERMARK);
                return 0;
 +      }
        buf = kmalloc(size, GFP_ATOMIC);
        if (!buf)
                return 0;
@@@ -607,10 -585,6 +599,6 @@@ static int fwtty_rx(struct fwtty_port *
        unsigned lsr;
        int err = 0;
  
-       tty = tty_port_tty_get(&port->port);
-       if (!tty)
-               return -ENOENT;
        fwtty_dbg(port, "%d", n);
        profile_size_distrib(port->stats.reads, n);
  
  
        lsr &= port->status_mask;
        if (lsr & ~port->ignore_mask & UART_LSR_OE) {
-               if (!tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
+               if (!tty_insert_flip_char(&port->port, 0, TTY_OVERRUN)) {
                        err = -EIO;
                        goto out;
                }
        }
  
        if (!test_bit(BUFFERING_RX, &port->flags)) {
-               c = tty_insert_flip_string_fixed_flag(tty, data, TTY_NORMAL, n);
+               c = tty_insert_flip_string_fixed_flag(&port->port, data,
+                               TTY_NORMAL, n);
                if (c > 0)
-                       tty_flip_buffer_push(tty);
+                       tty_flip_buffer_push(&port->port);
                n -= c;
  
                if (n) {
                        /* start buffering and throttling */
                        n -= fwtty_buffer_rx(port, &data[c], n);
  
-                       spin_lock_bh(&port->lock);
-                       __fwtty_throttle(port, tty);
-                       spin_unlock_bh(&port->lock);
+                       tty = tty_port_tty_get(&port->port);
+                       if (tty) {
+                               spin_lock_bh(&port->lock);
+                               __fwtty_throttle(port, tty);
+                               spin_unlock_bh(&port->lock);
+                               tty_kref_put(tty);
+                       }
                }
        } else
                n -= fwtty_buffer_rx(port, data, n);
        }
  
  out:
-       tty_kref_put(tty);
        port->icount.rx += len;
        port->stats.lost += n;
        return err;
@@@ -1174,19 -1151,6 +1165,19 @@@ static int fwtty_install(struct tty_dri
        return err;
  }
  
 +static int fwloop_install(struct tty_driver *driver, struct tty_struct *tty)
 +{
 +      struct fwtty_port *port = fwtty_port_get(table_idx(tty->index));
 +      int err;
 +
 +      err = tty_standard_install(driver, tty);
 +      if (!err)
 +              tty->driver_data = port;
 +      else
 +              fwtty_port_put(port);
 +      return err;
 +}
 +
  static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c)
  {
        struct fwtty_port *port = tty->driver_data;
@@@ -1514,26 -1478,17 +1505,26 @@@ static void fwtty_proc_show_port(struc
        if (port->port.console)
                (*port->fwcon_ops->stats)(&stats, port->con_data);
  
 -      seq_printf(m, " tx:%d rx:%d", port->icount.tx + stats.xchars,
 -                 port->icount.rx);
 +      seq_printf(m, " addr:%012llx tx:%d rx:%d", port->rx_handler.offset,
 +                 port->icount.tx + stats.xchars, port->icount.rx);
        seq_printf(m, " cts:%d dsr:%d rng:%d dcd:%d", port->icount.cts,
                   port->icount.dsr, port->icount.rng, port->icount.dcd);
        seq_printf(m, " fe:%d oe:%d pe:%d brk:%d", port->icount.frame,
                   port->icount.overrun, port->icount.parity, port->icount.brk);
 +}
 +
 +static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port)
 +{
 +      struct stats stats;
 +
 +      memcpy(&stats, &port->stats, sizeof(stats));
 +      if (port->port.console)
 +              (*port->fwcon_ops->stats)(&stats, port->con_data);
 +
        seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped,
                   stats.tx_stall, stats.fifo_errs, stats.lost);
        seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled,
                   stats.watermark);
 -      seq_printf(m, " addr:%012llx", port->rx_handler.offset);
  
        if (port->port.console) {
                seq_printf(m, "\n    ");
        dump_profile(m, &port->stats);
  }
  
 -static void fwtty_proc_show_peer(struct seq_file *m, struct fwtty_peer *peer)
 +static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer)
  {
        int generation = peer->generation;
  
        seq_printf(m, " node:%04x gen:%d", peer->node_id, generation);
        seq_printf(m, " sp:%d max:%d guid:%016llx", peer->speed,
                   peer->max_payload, (unsigned long long) peer->guid);
 -
 -      if (capable(CAP_SYS_ADMIN)) {
 -              seq_printf(m, " mgmt:%012llx",
 -                         (unsigned long long) peer->mgmt_addr);
 -              seq_printf(m, " addr:%012llx",
 -                         (unsigned long long) peer->status_addr);
 -      }
 +      seq_printf(m, " mgmt:%012llx", (unsigned long long) peer->mgmt_addr);
 +      seq_printf(m, " addr:%012llx", (unsigned long long) peer->status_addr);
        seq_putc(m, '\n');
  }
  
  static int fwtty_proc_show(struct seq_file *m, void *v)
  {
        struct fwtty_port *port;
 -      struct fw_serial *serial;
 -      struct fwtty_peer *peer;
        int i;
  
        seq_puts(m, "fwserinfo: 1.0 driver: 1.0\n");
                fwtty_port_put(port);
                seq_printf(m, "\n");
        }
 -      seq_putc(m, '\n');
 +      return 0;
 +}
  
 -      rcu_read_lock();
 -      list_for_each_entry_rcu(serial, &fwserial_list, list) {
 -              seq_printf(m, "card: %s  guid: %016llx\n",
 -                         dev_name(serial->card->device),
 -                         (unsigned long long) serial->card->guid);
 -              list_for_each_entry_rcu(peer, &serial->peer_list, list)
 -                      fwtty_proc_show_peer(m, peer);
 +static int fwtty_debugfs_stats_show(struct seq_file *m, void *v)
 +{
 +      struct fw_serial *serial = m->private;
 +      struct fwtty_port *port;
 +      int i;
 +
 +      for (i = 0; i < num_ports; ++i) {
 +              port = fwtty_port_get(serial->ports[i]->index);
 +              if (port) {
 +                      seq_printf(m, "%2d:", port->index);
 +                      fwtty_proc_show_port(m, port);
 +                      fwtty_debugfs_show_port(m, port);
 +                      fwtty_port_put(port);
 +                      seq_printf(m, "\n");
 +              }
        }
 +      return 0;
 +}
 +
 +static int fwtty_debugfs_peers_show(struct seq_file *m, void *v)
 +{
 +      struct fw_serial *serial = m->private;
 +      struct fwtty_peer *peer;
 +
 +      rcu_read_lock();
 +      seq_printf(m, "card: %s  guid: %016llx\n",
 +                 dev_name(serial->card->device),
 +                 (unsigned long long) serial->card->guid);
 +      list_for_each_entry_rcu(peer, &serial->peer_list, list)
 +              fwtty_debugfs_show_peer(m, peer);
        rcu_read_unlock();
        return 0;
  }
@@@ -1612,32 -1551,6 +1603,32 @@@ static int fwtty_proc_open(struct inod
        return single_open(fp, fwtty_proc_show, NULL);
  }
  
 +static int fwtty_stats_open(struct inode *inode, struct file *fp)
 +{
 +      return single_open(fp, fwtty_debugfs_stats_show, inode->i_private);
 +}
 +
 +static int fwtty_peers_open(struct inode *inode, struct file *fp)
 +{
 +      return single_open(fp, fwtty_debugfs_peers_show, inode->i_private);
 +}
 +
 +static const struct file_operations fwtty_stats_fops = {
 +      .owner =        THIS_MODULE,
 +      .open =         fwtty_stats_open,
 +      .read =         seq_read,
 +      .llseek =       seq_lseek,
 +      .release =      single_release,
 +};
 +
 +static const struct file_operations fwtty_peers_fops = {
 +      .owner =        THIS_MODULE,
 +      .open =         fwtty_peers_open,
 +      .read =         seq_read,
 +      .llseek =       seq_lseek,
 +      .release =      single_release,
 +};
 +
  static const struct file_operations fwtty_proc_fops = {
        .owner =        THIS_MODULE,
        .open =         fwtty_proc_open,
@@@ -1674,26 -1587,6 +1665,26 @@@ static const struct tty_operations fwtt
        .proc_fops =            &fwtty_proc_fops,
  };
  
 +static const struct tty_operations fwloop_ops = {
 +      .open =                 fwtty_open,
 +      .close =                fwtty_close,
 +      .hangup =               fwtty_hangup,
 +      .cleanup =              fwtty_cleanup,
 +      .install =              fwloop_install,
 +      .write =                fwtty_write,
 +      .write_room =           fwtty_write_room,
 +      .chars_in_buffer =      fwtty_chars_in_buffer,
 +      .send_xchar =           fwtty_send_xchar,
 +      .throttle =             fwtty_throttle,
 +      .unthrottle =           fwtty_unthrottle,
 +      .ioctl =                fwtty_ioctl,
 +      .set_termios =          fwtty_set_termios,
 +      .break_ctl =            fwtty_break_ctl,
 +      .tiocmget =             fwtty_tiocmget,
 +      .tiocmset =             fwtty_tiocmset,
 +      .get_icount =           fwtty_get_icount,
 +};
 +
  static inline int mgmt_pkt_expected_len(__be16 code)
  {
        static const struct fwserial_mgmt_pkt pkt;
@@@ -1783,7 -1676,8 +1774,7 @@@ static void fwserial_virt_plug_complete
  
        /* reconfigure tx_fifo optimally for this peer */
        spin_lock_bh(&port->lock);
 -      port->max_payload = min3(peer->max_payload, peer->fifo_len,
 -                               MAX_ASYNC_PAYLOAD);
 +      port->max_payload = min(peer->max_payload, peer->fifo_len);
        dma_fifo_change_tx_limit(&port->tx_fifo, port->max_payload);
        spin_unlock_bh(&peer->port->lock);
  
@@@ -1878,11 -1772,10 +1869,11 @@@ static struct fwtty_port *fwserial_find
        return NULL;
  }
  
 -static void fwserial_release_port(struct fwtty_port *port)
 +static void fwserial_release_port(struct fwtty_port *port, bool reset)
  {
        /* drop carrier (and all other line status) */
 -      fwtty_update_port_status(port, 0);
 +      if (reset)
 +              fwtty_update_port_status(port, 0);
  
        spin_lock_bh(&port->lock);
  
@@@ -1912,7 -1805,7 +1903,7 @@@ static void fwserial_plug_timeout(unsig
        spin_unlock_bh(&peer->lock);
  
        if (port)
 -              fwserial_release_port(port);
 +              fwserial_release_port(port, false);
  }
  
  /**
@@@ -1975,7 -1868,7 +1966,7 @@@ cancel_timer
        peer_revert_state(peer);
  release_port:
        spin_unlock_bh(&peer->lock);
 -      fwserial_release_port(port);
 +      fwserial_release_port(port, false);
  free_pkt:
        kfree(pkt);
        return err;
   * The port reference is put by fwtty_cleanup (if a reference was
   * ever taken).
   */
 -static void fwserial_close_port(struct fwtty_port *port)
 +static void fwserial_close_port(struct tty_driver *driver,
 +                              struct fwtty_port *port)
  {
        struct tty_struct *tty;
  
        }
        mutex_unlock(&port->port.mutex);
  
 -      tty_unregister_device(fwtty_driver, port->index);
 +      if (driver == fwloop_driver)
 +              tty_unregister_device(driver, loop_idx(port));
 +      else
 +              tty_unregister_device(driver, port->index);
  }
  
  /**
@@@ -2257,12 -2146,84 +2248,12 @@@ static void fwserial_remove_peer(struc
        spin_unlock_bh(&peer->lock);
  
        if (port)
 -              fwserial_release_port(port);
 +              fwserial_release_port(port, true);
  
        synchronize_rcu();
        kfree(peer);
  }
  
 -/**
 - * create_loop_device - create a loopback tty device
 - * @tty_driver: tty_driver to own loopback device
 - * @prototype: ptr to already-assigned 'prototype' tty port
 - * @index: index to associate this device with the tty port
 - * @parent: device to child to
 - *
 - * HACK - this is basically tty_port_register_device() with an
 - * alternate naming scheme. Suggest tty_port_register_named_device()
 - * helper api.
 - *
 - * Creates a loopback tty device named 'fwloop<n>' which is attached to
 - * the local unit in fwserial_add_peer(). Note that <n> in the device
 - * name advances in increments of port allocation blocks, ie., for port
 - * indices 0..3, the device name will be 'fwloop0'; for 4..7, 'fwloop1',
 - * and so on.
 - *
 - * Only one loopback device should be created per fw_card.
 - */
 -static void release_loop_device(struct device *dev)
 -{
 -      kfree(dev);
 -}
 -
 -static struct device *create_loop_device(struct tty_driver *driver,
 -                                       struct fwtty_port *prototype,
 -                                       struct fwtty_port *port,
 -                                       struct device *parent)
 -{
 -      char name[64];
 -      int index = port->index;
 -      dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
 -      struct device *dev = NULL;
 -      int err;
 -
 -      if (index >= fwtty_driver->num)
 -              return ERR_PTR(-EINVAL);
 -
 -      snprintf(name, 64, "%s%d", loop_dev_name, index / num_ports);
 -
 -      tty_port_link_device(&port->port, driver, index);
 -
 -      cdev_init(&driver->cdevs[index], driver->cdevs[prototype->index].ops);
 -      driver->cdevs[index].owner = driver->owner;
 -      err = cdev_add(&driver->cdevs[index], devt, 1);
 -      if (err)
 -              return ERR_PTR(err);
 -
 -      dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 -      if (!dev) {
 -              cdev_del(&driver->cdevs[index]);
 -              return ERR_PTR(-ENOMEM);
 -      }
 -
 -      dev->devt = devt;
 -      dev->class = prototype->device->class;
 -      dev->parent = parent;
 -      dev->release = release_loop_device;
 -      dev_set_name(dev, "%s", name);
 -      dev->groups = NULL;
 -      dev_set_drvdata(dev, NULL);
 -
 -      err = device_register(dev);
 -      if (err) {
 -              put_device(dev);
 -              cdev_del(&driver->cdevs[index]);
 -              return ERR_PTR(err);
 -      }
 -
 -      return dev;
 -}
 -
  /**
   * fwserial_create - init everything to create TTYs for a specific fw_card
   * @unit: fw_unit for first 'serial' unit device probed for this fw_card
@@@ -2361,28 -2322,17 +2352,28 @@@ static int fwserial_create(struct fw_un
        if (create_loop_dev) {
                struct device *loop_dev;
  
 -              loop_dev = create_loop_device(fwtty_driver,
 -                                            serial->ports[0],
 -                                            serial->ports[num_ttys],
 -                                            card->device);
 +              loop_dev = tty_port_register_device(&serial->ports[j]->port,
 +                                                  fwloop_driver,
 +                                                  loop_idx(serial->ports[j]),
 +                                                  card->device);
                if (IS_ERR(loop_dev)) {
                        err = PTR_ERR(loop_dev);
                        fwtty_err(&unit, "create loop device failed (%d)", err);
                        goto unregister_ttys;
                }
 -              serial->ports[num_ttys]->device = loop_dev;
 -              serial->ports[num_ttys]->loopback = true;
 +              serial->ports[j]->device = loop_dev;
 +              serial->ports[j]->loopback = true;
 +      }
 +
 +      if (!IS_ERR_OR_NULL(fwserial_debugfs)) {
 +              serial->debugfs = debugfs_create_dir(dev_name(&unit->device),
 +                                                   fwserial_debugfs);
 +              if (!IS_ERR_OR_NULL(serial->debugfs)) {
 +                      debugfs_create_file("peers", 0444, serial->debugfs,
 +                                          serial, &fwtty_peers_fops);
 +                      debugfs_create_file("stats", 0444, serial->debugfs,
 +                                          serial, &fwtty_stats_fops);
 +              }
        }
  
        list_add_rcu(&serial->list, &fwserial_list);
        fwtty_err(&unit, "unable to add peer unit device (%d)", err);
  
        /* fall-through to error processing */
 +      debugfs_remove_recursive(serial->debugfs);
 +
        list_del_rcu(&serial->list);
 +      if (create_loop_dev)
 +              tty_unregister_device(fwloop_driver, loop_idx(serial->ports[j]));
  unregister_ttys:
        for (--j; j >= 0; --j)
                tty_unregister_device(fwtty_driver, serial->ports[j]->index);
@@@ -2490,12 -2436,8 +2481,12 @@@ static int fwserial_remove(struct devic
                /* unlink from the fwserial_list here */
                list_del_rcu(&serial->list);
  
 -              for (i = 0; i < num_ports; ++i)
 -                      fwserial_close_port(serial->ports[i]);
 +              debugfs_remove_recursive(serial->debugfs);
 +
 +              for (i = 0; i < num_ttys; ++i)
 +                      fwserial_close_port(fwtty_driver, serial->ports[i]);
 +              if (create_loop_dev)
 +                      fwserial_close_port(fwloop_driver, serial->ports[i]);
                kref_put(&serial->kref, fwserial_destroy);
        }
        mutex_unlock(&fwserial_list_mutex);
@@@ -2559,25 -2501,26 +2550,25 @@@ static struct fw_driver fwserial_drive
  /* XXX: config ROM definitons could be improved with semi-automated offset
   * and length calculation
   */
 +#define FW_ROM_LEN(quads)     ((quads) << 16)
  #define FW_ROM_DESCRIPTOR(ofs)        (((CSR_LEAF | CSR_DESCRIPTOR) << 24) | (ofs))
  
  struct fwserial_unit_directory_data {
 -      u16     crc;
 -      u16     len;
 +      u32     len_crc;
        u32     unit_specifier;
        u32     unit_sw_version;
        u32     unit_addr_offset;
        u32     desc1_ofs;
 -      u16     desc1_crc;
 -      u16     desc1_len;
 +      u32     desc1_len_crc;
        u32     desc1_data[5];
  } __packed;
  
  static struct fwserial_unit_directory_data fwserial_unit_directory_data = {
 -      .len = 4,
 +      .len_crc = FW_ROM_LEN(4),
        .unit_specifier = FW_UNIT_SPECIFIER(LINUX_VENDOR_ID),
        .unit_sw_version = FW_UNIT_VERSION(FWSERIAL_VERSION),
        .desc1_ofs = FW_ROM_DESCRIPTOR(1),
 -      .desc1_len = 5,
 +      .desc1_len_crc = FW_ROM_LEN(5),
        .desc1_data = {
                0x00000000,                     /*   type = text            */
                0x00000000,                     /*   enc = ASCII, lang EN   */
@@@ -2597,7 -2540,7 +2588,7 @@@ static struct fw_descriptor fwserial_un
   * The management address is in the unit space region but above other known
   * address users (to keep wild writes from causing havoc)
   */
 -const struct fw_address_region fwserial_mgmt_addr_region = {
 +static const struct fw_address_region fwserial_mgmt_addr_region = {
        .start = CSR_REGISTER_BASE + 0x1e0000ULL,
        .end = 0x1000000000000ULL,
  };
@@@ -2663,7 -2606,7 +2654,7 @@@ static void fwserial_handle_plug_req(st
  
        spin_unlock_bh(&peer->lock);
        if (port)
 -              fwserial_release_port(port);
 +              fwserial_release_port(port, false);
  
        rcode = fwserial_send_mgmt_sync(peer, pkt);
  
  cleanup:
        spin_unlock_bh(&peer->lock);
        if (port)
 -              fwserial_release_port(port);
 +              fwserial_release_port(port, false);
        kfree(pkt);
        return;
  }
@@@ -2729,14 -2672,15 +2720,14 @@@ static void fwserial_handle_unplug_req(
  
        spin_lock_bh(&peer->lock);
        if (peer->state == FWPS_UNPLUG_RESPONDING) {
 -              if (rcode == RCODE_COMPLETE)
 -                      port = peer_revert_state(peer);
 -              else
 +              if (rcode != RCODE_COMPLETE)
                        fwtty_err(&peer->unit, "UNPLUG_RSP error (%d)", rcode);
 +              port = peer_revert_state(peer);
        }
  cleanup:
        spin_unlock_bh(&peer->lock);
        if (port)
 -              fwserial_release_port(port);
 +              fwserial_release_port(port, true);
        kfree(pkt);
        return;
  }
@@@ -2747,7 -2691,6 +2738,7 @@@ static int fwserial_parse_mgmt_write(st
                                     size_t len)
  {
        struct fwtty_port *port = NULL;
 +      bool reset = false;
        int rcode;
  
        if (addr != fwserial_mgmt_addr_handler.offset || len < sizeof(pkt->hdr))
                        if (be16_to_cpu(pkt->hdr.code) & FWSC_RSP_NACK)
                                fwtty_notice(&peer->unit, "NACK unplug?");
                        port = peer_revert_state(peer);
 +                      reset = true;
                }
                break;
  
        spin_unlock_bh(&peer->lock);
  
        if (port)
 -              fwserial_release_port(port);
 +              fwserial_release_port(port, reset);
  
        return rcode;
  }
@@@ -2885,18 -2827,14 +2876,18 @@@ static int __init fwserial_init(void
  {
        int err, num_loops = !!(create_loop_dev);
  
 +      /* XXX: placeholder for a "firewire" debugfs node */
 +      fwserial_debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
 +
        /* num_ttys/num_ports must not be set above the static alloc avail */
        if (num_ttys + num_loops > MAX_CARD_PORTS)
                num_ttys = MAX_CARD_PORTS - num_loops;
        num_ports = num_ttys + num_loops;
  
 -      fwtty_driver = alloc_tty_driver(MAX_TOTAL_PORTS);
 -      if (!fwtty_driver) {
 -              err = -ENOMEM;
 +      fwtty_driver = tty_alloc_driver(MAX_TOTAL_PORTS, TTY_DRIVER_REAL_RAW
 +                                      | TTY_DRIVER_DYNAMIC_DEV);
 +      if (IS_ERR(fwtty_driver)) {
 +              err = PTR_ERR(fwtty_driver);
                return err;
        }
  
        fwtty_driver->minor_start       = 0;
        fwtty_driver->type              = TTY_DRIVER_TYPE_SERIAL;
        fwtty_driver->subtype           = SERIAL_TYPE_NORMAL;
 -      fwtty_driver->flags             = TTY_DRIVER_REAL_RAW |
 -                                              TTY_DRIVER_DYNAMIC_DEV;
 -
        fwtty_driver->init_termios          = tty_std_termios;
        fwtty_driver->init_termios.c_cflag  |= CLOCAL;
        tty_set_operations(fwtty_driver, &fwtty_ops);
                goto put_tty;
        }
  
 +      if (create_loop_dev) {
 +              fwloop_driver = tty_alloc_driver(MAX_TOTAL_PORTS / num_ports,
 +                                               TTY_DRIVER_REAL_RAW
 +                                               | TTY_DRIVER_DYNAMIC_DEV);
 +              if (IS_ERR(fwloop_driver)) {
 +                      err = PTR_ERR(fwloop_driver);
 +                      goto unregister_driver;
 +              }
 +
 +              fwloop_driver->driver_name      = KBUILD_MODNAME "_loop";
 +              fwloop_driver->name             = loop_dev_name;
 +              fwloop_driver->major            = 0;
 +              fwloop_driver->minor_start      = 0;
 +              fwloop_driver->type             = TTY_DRIVER_TYPE_SERIAL;
 +              fwloop_driver->subtype          = SERIAL_TYPE_NORMAL;
 +              fwloop_driver->init_termios         = tty_std_termios;
 +              fwloop_driver->init_termios.c_cflag  |= CLOCAL;
 +              tty_set_operations(fwloop_driver, &fwloop_ops);
 +
 +              err = tty_register_driver(fwloop_driver);
 +              if (err) {
 +                      driver_err("register loop driver failed (%d)", err);
 +                      goto put_loop;
 +              }
 +      }
 +
        fwtty_txn_cache = kmem_cache_create("fwtty_txn_cache",
                                            sizeof(struct fwtty_transaction),
                                            0, 0, fwtty_txn_constructor);
        if (!fwtty_txn_cache) {
                err = -ENOMEM;
 -              goto unregister_driver;
 +              goto unregister_loop;
        }
  
        /*
@@@ -2989,17 -2904,10 +2980,17 @@@ remove_handler
        fw_core_remove_address_handler(&fwserial_mgmt_addr_handler);
  destroy_cache:
        kmem_cache_destroy(fwtty_txn_cache);
 +unregister_loop:
 +      if (create_loop_dev)
 +              tty_unregister_driver(fwloop_driver);
 +put_loop:
 +      if (create_loop_dev)
 +              put_tty_driver(fwloop_driver);
  unregister_driver:
        tty_unregister_driver(fwtty_driver);
  put_tty:
        put_tty_driver(fwtty_driver);
 +      debugfs_remove_recursive(fwserial_debugfs);
        return err;
  }
  
@@@ -3009,13 -2917,8 +3000,13 @@@ static void __exit fwserial_exit(void
        fw_core_remove_descriptor(&fwserial_unit_directory);
        fw_core_remove_address_handler(&fwserial_mgmt_addr_handler);
        kmem_cache_destroy(fwtty_txn_cache);
 +      if (create_loop_dev) {
 +              tty_unregister_driver(fwloop_driver);
 +              put_tty_driver(fwloop_driver);
 +      }
        tty_unregister_driver(fwtty_driver);
        put_tty_driver(fwtty_driver);
 +      debugfs_remove_recursive(fwserial_debugfs);
  }
  
  module_init(fwserial_init);
@@@ -3028,3 -2931,4 +3019,3 @@@ MODULE_DEVICE_TABLE(ieee1394, fwserial_
  MODULE_PARM_DESC(ttys, "Number of ttys to create for each local firewire node");
  MODULE_PARM_DESC(auto, "Auto-connect a tty to each firewire node discovered");
  MODULE_PARM_DESC(loop, "Create a loopback device, fwloop<n>, with ttys");
 -MODULE_PARM_DESC(limit_bw, "Limit bandwidth utilization to 20%.");
index 822ac3d24788f19f9c47b2d3bf6b8397960abf1e,2aa22379fda001721e3fd5f57e755b08e5b34771..775af26b99140ea8d45422c143db884fc2405ed7
@@@ -2,6 -2,7 +2,7 @@@
  #include <linux/consolemap.h>
  #include <linux/interrupt.h>
  #include <linux/sched.h>
+ #include <linux/device.h> /* for dev_warn */
  #include <linux/selection.h>
  
  #include "speakup.h"
@@@ -10,7 -11,7 +11,7 @@@
  /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
  #define ishardspace(c)      ((c) == ' ')
  
 -unsigned short xs, ys, xe, ye; /* our region points */
 +unsigned short spk_xs, spk_ys, spk_xe, spk_ye; /* our region points */
  
  /* Variables for selection control. */
  /* must not be disallocated */
@@@ -51,12 -52,12 +52,12 @@@ int speakup_set_selection(struct tty_st
        int i, ps, pe;
        struct vc_data *vc = vc_cons[fg_console].d;
  
 -      xs = limit(xs, vc->vc_cols - 1);
 -      ys = limit(ys, vc->vc_rows - 1);
 -      xe = limit(xe, vc->vc_cols - 1);
 -      ye = limit(ye, vc->vc_rows - 1);
 -      ps = ys * vc->vc_size_row + (xs << 1);
 -      pe = ye * vc->vc_size_row + (xe << 1);
 +      spk_xs = limit(spk_xs, vc->vc_cols - 1);
 +      spk_ys = limit(spk_ys, vc->vc_rows - 1);
 +      spk_xe = limit(spk_xe, vc->vc_cols - 1);
 +      spk_ye = limit(spk_ye, vc->vc_rows - 1);
 +      ps = spk_ys * vc->vc_size_row + (spk_xs << 1);
 +      pe = spk_ye * vc->vc_size_row + (spk_xe << 1);
  
        if (ps > pe) {
                /* make sel_start <= sel_end */
@@@ -95,6 -96,7 +96,6 @@@
        /* Allocate a new buffer before freeing the old one ... */
        bp = kmalloc((sel_end-sel_start)/2+1, GFP_ATOMIC);
        if (!bp) {
 -              dev_warn(tty->dev, "selection: kmalloc() failed\n");
                speakup_clear_selection();
                return -ENOMEM;
        }
index dd6277eb5a3820408e946c63abe26cf072b88fdf,791e1dfb8b110bb6482c245679d7c4dd3a13d682..32517d4bceab2b5cbecd1861b36ecd32b770e500
@@@ -179,7 -179,8 +179,7 @@@ static void max3100_work(struct work_st
  
  static void max3100_dowork(struct max3100_port *s)
  {
 -      if (!s->force_end_work && !work_pending(&s->work) &&
 -          !freezing(current) && !s->suspending)
 +      if (!s->force_end_work && !freezing(current) && !s->suspending)
                queue_work(s->workqueue, &s->work);
  }
  
@@@ -310,8 -311,8 +310,8 @@@ static void max3100_work(struct work_st
                        }
                }
  
-               if (rxchars > 16 && s->port.state->port.tty != NULL) {
-                       tty_flip_buffer_push(s->port.state->port.tty);
+               if (rxchars > 16) {
+                       tty_flip_buffer_push(&s->port.state->port);
                        rxchars = 0;
                }
                if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                  (!uart_circ_empty(xmit) &&
                   !uart_tx_stopped(&s->port))));
  
-       if (rxchars > 0 && s->port.state->port.tty != NULL)
-               tty_flip_buffer_push(s->port.state->port.tty);
+       if (rxchars > 0)
+               tty_flip_buffer_push(&s->port.state->port);
  }
  
  static irqreturn_t max3100_irq(int irqno, void *dev_id)
@@@ -529,7 -530,7 +529,7 @@@ max3100_set_termios(struct uart_port *p
                        MAX3100_STATUS_OE;
  
        /* we are sending char from a workqueue so enable */
-       s->port.state->port.tty->low_latency = 1;
+       s->port.state->port.low_latency = 1;
  
        if (s->poll_time > 0)
                del_timer_sync(&s->timer);
index e869eab180bec04edb920de8077f42fde3344603,caccbe8fc1befcd52977681b140389935f6af21c..08dbfb88d42c00e4df140532432c0076928328c1
@@@ -15,7 -15,6 +15,7 @@@
  #define SUPPORT_SYSRQ
  #endif
  
 +#include <linux/err.h>
  #include <linux/module.h>
  #include <linux/device.h>
  #include <linux/console.h>
@@@ -24,8 -23,9 +24,9 @@@
  #include <linux/io.h>
  #include <linux/tty.h>
  #include <linux/tty_flip.h>
+ #include <linux/spinlock.h>
  #include <linux/platform_device.h>
- #include <linux/platform_data/sccnxp.h>
+ #include <linux/platform_data/serial-sccnxp.h>
  
  #define SCCNXP_NAME                   "uart-sccnxp"
  #define SCCNXP_MAJOR                  204
@@@ -107,6 -107,7 +108,7 @@@ enum 
  struct sccnxp_port {
        struct uart_driver      uart;
        struct uart_port        port[SCCNXP_MAX_UARTS];
+       bool                    opened[SCCNXP_MAX_UARTS];
  
        const char              *name;
        int                     irq;
        struct console          console;
  #endif
  
-       struct mutex            sccnxp_mutex;
+       spinlock_t              lock;
+       bool                    poll;
+       struct timer_list       timer;
  
        struct sccnxp_pdata     pdata;
  };
@@@ -175,14 -179,12 +180,12 @@@ static int sccnxp_update_best_err(int a
        return 1;
  }
  
- struct baud_table {
+ static const struct {
        u8      csr;
        u8      acr;
        u8      mr0;
        int     baud;
- };
- const struct baud_table baud_std[] = {
+ } baud_std[] = {
        { 0,    ACR_BAUD0,      MR0_BAUD_NORMAL,        50, },
        { 0,    ACR_BAUD1,      MR0_BAUD_NORMAL,        75, },
        { 1,    ACR_BAUD0,      MR0_BAUD_NORMAL,        110, },
@@@ -286,10 -288,6 +289,6 @@@ static void sccnxp_handle_rx(struct uar
  {
        u8 sr;
        unsigned int ch, flag;
-       struct tty_struct *tty = tty_port_tty_get(&port->state->port);
-       if (!tty)
-               return;
  
        for (;;) {
                sr = sccnxp_port_read(port, SCCNXP_SR_REG);
                if (unlikely(sr)) {
                        if (sr & SR_BRK) {
                                port->icount.brk++;
+                               sccnxp_port_write(port, SCCNXP_CR_REG,
+                                                 CR_CMD_BREAK_RESET);
                                if (uart_handle_break(port))
                                        continue;
                        } else if (sr & SR_PE)
                                port->icount.parity++;
                        else if (sr & SR_FE)
                                port->icount.frame++;
-                       else if (sr & SR_OVR)
+                       else if (sr & SR_OVR) {
                                port->icount.overrun++;
+                               sccnxp_port_write(port, SCCNXP_CR_REG,
+                                                 CR_CMD_STATUS_RESET);
+                       }
  
                        sr &= port->read_status_mask;
                        if (sr & SR_BRK)
                uart_insert_char(port, sr, SR_OVR, ch, flag);
        }
  
-       tty_flip_buffer_push(tty);
-       tty_kref_put(tty);
+       tty_flip_buffer_push(&port->state->port);
  }
  
  static void sccnxp_handle_tx(struct uart_port *port)
                uart_write_wakeup(port);
  }
  
- static irqreturn_t sccnxp_ist(int irq, void *dev_id)
+ static void sccnxp_handle_events(struct sccnxp_port *s)
  {
        int i;
        u8 isr;
-       struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
-       mutex_lock(&s->sccnxp_mutex);
  
-       for (;;) {
+       do {
                isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG);
                isr &= s->imr;
                if (!isr)
                        break;
  
-               dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr);
                for (i = 0; i < s->uart.nr; i++) {
-                       if (isr & ISR_RXRDY(i))
+                       if (s->opened[i] && (isr & ISR_RXRDY(i)))
                                sccnxp_handle_rx(&s->port[i]);
-                       if (isr & ISR_TXRDY(i))
+                       if (s->opened[i] && (isr & ISR_TXRDY(i)))
                                sccnxp_handle_tx(&s->port[i]);
                }
-       }
+       } while (1);
+ }
+ static void sccnxp_timer(unsigned long data)
+ {
+       struct sccnxp_port *s = (struct sccnxp_port *)data;
+       unsigned long flags;
  
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
+       sccnxp_handle_events(s);
+       spin_unlock_irqrestore(&s->lock, flags);
+       if (!timer_pending(&s->timer))
+               mod_timer(&s->timer, jiffies +
+                         usecs_to_jiffies(s->pdata.poll_time_us));
+ }
+ static irqreturn_t sccnxp_ist(int irq, void *dev_id)
+ {
+       struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
+       unsigned long flags;
+       spin_lock_irqsave(&s->lock, flags);
+       sccnxp_handle_events(s);
+       spin_unlock_irqrestore(&s->lock, flags);
  
        return IRQ_HANDLED;
  }
  static void sccnxp_start_tx(struct uart_port *port)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
  
        /* Set direction to output */
        if (s->flags & SCCNXP_HAVE_IO)
  
        sccnxp_enable_irq(port, IMR_TXRDY);
  
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static void sccnxp_stop_tx(struct uart_port *port)
  static void sccnxp_stop_rx(struct uart_port *port)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
        sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE);
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static unsigned int sccnxp_tx_empty(struct uart_port *port)
  {
        u8 val;
+       unsigned long flags;
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
        val = sccnxp_port_read(port, SCCNXP_SR_REG);
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  
        return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
  }
@@@ -456,28 -477,30 +478,30 @@@ static void sccnxp_enable_ms(struct uar
  static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
  
        if (!(s->flags & SCCNXP_HAVE_IO))
                return;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
  
        sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR);
        sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS);
  
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static unsigned int sccnxp_get_mctrl(struct uart_port *port)
  {
        u8 bitmask, ipr;
+       unsigned long flags;
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
        unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
  
        if (!(s->flags & SCCNXP_HAVE_IO))
                return mctrl;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
  
        ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG);
  
                mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0;
        }
  
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  
        return mctrl;
  }
  static void sccnxp_break_ctl(struct uart_port *port, int break_state)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
        sccnxp_port_write(port, SCCNXP_CR_REG, break_state ?
                          CR_CMD_START_BREAK : CR_CMD_STOP_BREAK);
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static void sccnxp_set_termios(struct uart_port *port,
                               struct ktermios *termios, struct ktermios *old)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
        u8 mr1, mr2;
        int baud;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
  
        /* Mask termios capabilities we don't support */
        termios->c_cflag &= ~CMSPAR;
        /* Update timeout according to new baud rate */
        uart_update_timeout(port, termios->c_cflag, baud);
  
+       /* Report actual baudrate back to core */
        if (tty_termios_baud_rate(termios))
                tty_termios_encode_baud_rate(termios, baud, baud);
  
        /* Enable RX & TX */
        sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
  
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static int sccnxp_startup(struct uart_port *port)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
  
        if (s->flags & SCCNXP_HAVE_IO) {
                /* Outputs are controlled manually */
        /* Enable RX interrupt */
        sccnxp_enable_irq(port, IMR_RXRDY);
  
-       mutex_unlock(&s->sccnxp_mutex);
+       s->opened[port->line] = 1;
+       spin_unlock_irqrestore(&s->lock, flags);
  
        return 0;
  }
  static void sccnxp_shutdown(struct uart_port *port)
  {
        struct sccnxp_port *s = dev_get_drvdata(port->dev);
+       unsigned long flags;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
+       s->opened[port->line] = 0;
  
        /* Disable interrupts */
        sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
        if (s->flags & SCCNXP_HAVE_IO)
                sccnxp_set_bit(port, DIR_OP, 0);
  
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static const char *sccnxp_type(struct uart_port *port)
@@@ -722,10 -754,11 +755,11 @@@ static void sccnxp_console_write(struc
  {
        struct sccnxp_port *s = (struct sccnxp_port *)co->data;
        struct uart_port *port = &s->port[co->index];
+       unsigned long flags;
  
-       mutex_lock(&s->sccnxp_mutex);
+       spin_lock_irqsave(&s->lock, flags);
        uart_console_write(port, c, n, sccnxp_console_putchar);
-       mutex_unlock(&s->sccnxp_mutex);
+       spin_unlock_irqrestore(&s->lock, flags);
  }
  
  static int sccnxp_console_setup(struct console *co, char *options)
@@@ -764,7 -797,7 +798,7 @@@ static int sccnxp_probe(struct platform
        }
        platform_set_drvdata(pdev, s);
  
-       mutex_init(&s->sccnxp_mutex);
+       spin_lock_init(&s->lock);
  
        /* Individual chip settings */
        switch (chiptype) {
        } else
                memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
  
-       s->irq = platform_get_irq(pdev, 0);
-       if (s->irq <= 0) {
-               dev_err(&pdev->dev, "Missing irq resource data\n");
-               ret = -ENXIO;
-               goto err_out;
+       if (s->pdata.poll_time_us) {
+               dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n",
+                        s->pdata.poll_time_us);
+               s->poll = 1;
+       }
+       if (!s->poll) {
+               s->irq = platform_get_irq(pdev, 0);
+               if (s->irq < 0) {
+                       dev_err(&pdev->dev, "Missing irq resource data\n");
+                       ret = -ENXIO;
+                       goto err_out;
+               }
        }
  
        /* Check input frequency */
                goto err_out;
        }
  
 -      membase = devm_request_and_ioremap(&pdev->dev, res);
 -      if (!membase) {
 -              dev_err(&pdev->dev, "Failed to ioremap\n");
 -              ret = -EIO;
 +      membase = devm_ioremap_resource(&pdev->dev, res);
 +      if (IS_ERR(membase)) {
 +              ret = PTR_ERR(membase);
                goto err_out;
        }
  
        if (s->pdata.init)
                s->pdata.init();
  
-       ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist,
-                                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                       dev_name(&pdev->dev), s);
-       if (!ret)
+       if (!s->poll) {
+               ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL,
+                                               sccnxp_ist,
+                                               IRQF_TRIGGER_FALLING |
+                                               IRQF_ONESHOT,
+                                               dev_name(&pdev->dev), s);
+               if (!ret)
+                       return 0;
+               dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
+       } else {
+               init_timer(&s->timer);
+               setup_timer(&s->timer, sccnxp_timer, (unsigned long)s);
+               mod_timer(&s->timer, jiffies +
+                         usecs_to_jiffies(s->pdata.poll_time_us));
                return 0;
-       dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
+       }
  
  err_out:
        platform_set_drvdata(pdev, NULL);
@@@ -948,7 -1000,10 +1000,10 @@@ static int sccnxp_remove(struct platfor
        int i;
        struct sccnxp_port *s = platform_get_drvdata(pdev);
  
-       devm_free_irq(&pdev->dev, s->irq, s);
+       if (!s->poll)
+               devm_free_irq(&pdev->dev, s->irq, s);
+       else
+               del_timer_sync(&s->timer);
  
        for (i = 0; i < s->uart.nr; i++)
                uart_remove_one_port(&s->uart, &s->port[i]);
diff --combined drivers/tty/tty_io.c
index 6b20fd66d4add86380b10617fee25a9466a2a3c0,8f44d627cceab85268ec037eec799d8c0494c7bc..60e48a11b66c81c416f0734d9ea6bd610cbf79a9
@@@ -536,7 -536,7 +536,7 @@@ EXPORT_SYMBOL_GPL(tty_wakeup)
   *    __tty_hangup            -       actual handler for hangup events
   *    @work: tty device
   *
-  *    This can be called by the "eventd" kernel thread.  That is process
+  *    This can be called by a "kworker" kernel thread.  That is process
   *    synchronous but doesn't hold any locks, so we need to make sure we
   *    have the appropriate locks for what we're doing.
   *
@@@ -977,8 -977,7 +977,7 @@@ static ssize_t tty_read(struct file *fi
        else
                i = -EIO;
        tty_ldisc_deref(ld);
-       if (i > 0)
-               inode->i_atime = current_fs_time(inode->i_sb);
        return i;
  }
  
@@@ -1079,11 -1078,8 +1078,8 @@@ static inline ssize_t do_tty_write
                        break;
                cond_resched();
        }
-       if (written) {
-               struct inode *inode = file->f_path.dentry->d_inode;
-               inode->i_mtime = current_fs_time(inode->i_sb);
+       if (written)
                ret = written;
-       }
  out:
        tty_write_unlock(tty);
        return ret;
@@@ -2906,9 -2902,9 +2902,9 @@@ void do_SAK(struct tty_struct *tty
  
  EXPORT_SYMBOL(do_SAK);
  
 -static int dev_match_devt(struct device *dev, void *data)
 +static int dev_match_devt(struct device *dev, const void *data)
  {
 -      dev_t *devt = data;
 +      const dev_t *devt = data;
        return dev->devt == *devt;
  }
  
index c5c6fa60910d3fe309cde04c45f13c46054cc2b0,a1bd951f9cb7f7287a0be8d6d45d4165ab44cd69..5a0c541daf893a33a428bedb8d68ec1fa72d4234
@@@ -281,7 -281,6 +281,7 @@@ config USB_S3C_HSOT
  config USB_IMX
        tristate "Freescale i.MX1 USB Peripheral Controller"
        depends on ARCH_MXC
 +      depends on BROKEN
        help
           Freescale's i.MX1 includes an integrated full speed
           USB 1.1 device controller.
@@@ -320,7 -319,6 +320,7 @@@ config USB_S3C_HSUD
  
  config USB_MV_UDC
        tristate "Marvell USB2.0 Device Controller"
 +      depends on GENERIC_HARDIRQS
        help
          Marvell Socs (including PXA and MMP series) include a high speed
          USB2.0 OTG controller, which can be configured as high speed or
@@@ -442,7 -440,7 +442,7 @@@ config USB_GOK
  
  config USB_EG20T
        tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
 -      depends on PCI
 +      depends on PCI && GENERIC_HARDIRQS
        help
          This is a USB device driver for EG20T PCH.
          EG20T PCH is the platform controller hub that is used in Intel's
@@@ -502,15 -500,6 +502,15 @@@ config USB_LIBCOMPOSIT
        tristate
        depends on USB_GADGET
  
 +config USB_F_ACM
 +      tristate
 +
 +config USB_F_SS_LB
 +      tristate
 +
 +config USB_U_SERIAL
 +      tristate
 +
  choice
        tristate "USB Gadget Drivers"
        default USB_ETH
  config USB_ZERO
        tristate "Gadget Zero (DEVELOPMENT)"
        select USB_LIBCOMPOSITE
 +      select USB_F_SS_LB
        help
          Gadget Zero is a two-configuration device.  It either sinks and
          sources bulk data; or it loops back a configurable number of
@@@ -762,8 -750,7 +762,9 @@@ config USB_GADGET_TARGE
  
  config USB_G_SERIAL
        tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+       depends on TTY
 +      select USB_U_SERIAL
 +      select USB_F_ACM
        select USB_LIBCOMPOSITE
        help
          The Serial Gadget talks to the Linux-USB generic serial driver.
@@@ -813,12 -800,12 +814,14 @@@ config USB_G_PRINTE
          For more information, see Documentation/usb/gadget_printer.txt
          which includes sample code for accessing the device file.
  
+ if TTY
  config USB_CDC_COMPOSITE
        tristate "CDC Composite Device (Ethernet and ACM)"
        depends on NET
        select USB_LIBCOMPOSITE
 +      select USB_U_SERIAL
 +      select USB_F_ACM
        help
          This driver provides two functions in one configuration:
          a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
@@@ -834,7 -821,6 +837,7 @@@ config USB_G_NOKI
        tristate "Nokia composite gadget"
        depends on PHONET
        select USB_LIBCOMPOSITE
 +      select USB_U_SERIAL
        help
          The Nokia composite gadget provides support for acm, obex
          and phonet in only one composite gadget driver.
@@@ -846,8 -832,6 +849,8 @@@ config USB_G_ACM_M
        tristate "CDC Composite Device (ACM and mass storage)"
        depends on BLOCK
        select USB_LIBCOMPOSITE
 +      select USB_U_SERIAL
 +      select USB_F_ACM
        help
          This driver provides two functions in one configuration:
          a mass storage, and a CDC ACM (serial port) link.
@@@ -860,8 -844,6 +863,8 @@@ config USB_G_MULT
        depends on BLOCK && NET
        select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
        select USB_LIBCOMPOSITE
 +      select USB_U_SERIAL
 +      select USB_F_ACM
        help
          The Multifunction Composite Gadget provides Ethernet (RNDIS
          and/or CDC Ethernet), mass storage and ACM serial link
@@@ -900,6 -882,8 +903,8 @@@ config USB_G_MULTI_CD
  
          If unsure, say "y".
  
+ endif # TTY
  config USB_G_HID
        tristate "HID Gadget"
        select USB_LIBCOMPOSITE
  # Standalone / single function gadgets
  config USB_G_DBGP
        tristate "EHCI Debug Device Gadget"
+       depends on TTY
        select USB_LIBCOMPOSITE
        help
          This gadget emulates an EHCI Debug device. This is useful when you want
@@@ -937,7 -922,6 +943,7 @@@ config USB_G_DBGP_PRINT
  
  config USB_G_DBGP_SERIAL
        depends on USB_G_DBGP
 +      select USB_U_SERIAL
        bool "serial"
        help
          Userland can interact using /dev/ttyGSxxx.
index 588a9be18ef81c77c8cdbf1a06e547c67350c14d,46b1cc773ab866d96ec123d18bb7d46d98f69a0c..c5034d9c946b479b52e7e06cba68729392727d07
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/tty_flip.h>
  #include <linux/slab.h>
  #include <linux/export.h>
 +#include <linux/module.h>
  
  #include "u_serial.h"
  
   * "serial port" functionality through the USB gadget stack.  Each such
   * port is exposed through a /dev/ttyGS* node.
   *
 - * After initialization (gserial_setup), these TTY port devices stay
 - * available until they are removed (gserial_cleanup).  Each one may be
 - * connected to a USB function (gserial_connect), or disconnected (with
 - * gserial_disconnect) when the USB host issues a config change event.
 - * Data can only flow when the port is connected to the host.
 + * After this module has been loaded, the individual TTY port can be requested
 + * (gserial_alloc_line()) and it will stay available until they are removed
 + * (gserial_free_line()). Each one may be connected to a USB function
 + * (gserial_connect), or disconnected (with gserial_disconnect) when the USB
 + * host issues a config change event. Data can only flow when the port is
 + * connected to the host.
   *
   * A given TTY port can be made available in multiple configurations.
   * For example, each one might expose a ttyGS0 node which provides a
@@@ -121,10 -119,13 +121,10 @@@ struct gs_port 
        struct usb_cdc_line_coding port_line_coding;    /* 8-N-1 etc */
  };
  
 -/* increase N_PORTS if you need more */
 -#define N_PORTS               4
  static struct portmaster {
        struct mutex    lock;                   /* protect open/close */
        struct gs_port  *port;
 -} ports[N_PORTS];
 -static unsigned       n_ports;
 +} ports[MAX_U_SERIAL_PORTS];
  
  #define GS_CLOSE_TIMEOUT              15              /* seconds */
  
@@@ -308,7 -309,6 +308,7 @@@ gs_alloc_req(struct usb_ep *ep, unsigne
  
        return req;
  }
 +EXPORT_SYMBOL_GPL(gs_alloc_req);
  
  /*
   * gs_free_req
@@@ -320,7 -320,6 +320,7 @@@ void gs_free_req(struct usb_ep *ep, str
        kfree(req->buf);
        usb_ep_free_request(ep, req);
  }
 +EXPORT_SYMBOL_GPL(gs_free_req);
  
  /*
   * gs_send_packet
@@@ -496,12 -495,8 +496,8 @@@ static void gs_rx_push(unsigned long _p
  
                req = list_first_entry(queue, struct usb_request, list);
  
-               /* discard data if tty was closed */
-               if (!tty)
-                       goto recycle;
                /* leave data queued if tty was rx throttled */
-               if (test_bit(TTY_THROTTLED, &tty->flags))
+               if (tty && test_bit(TTY_THROTTLED, &tty->flags))
                        break;
  
                switch (req->status) {
                                size -= n;
                        }
  
-                       count = tty_insert_flip_string(tty, packet, size);
+                       count = tty_insert_flip_string(&port->port, packet,
+                                       size);
                        if (count)
                                do_push = true;
                        if (count != size) {
                        }
                        port->n_read = 0;
                }
- recycle:
                list_move(&req->list, &port->read_pool);
                port->read_started--;
        }
        /* Push from tty to ldisc; without low_latency set this is handled by
         * a workqueue, so we won't get callbacks and can hold port_lock
         */
-       if (tty && do_push)
-               tty_flip_buffer_push(tty);
+       if (do_push)
+               tty_flip_buffer_push(&port->port);
  
  
        /* We want our data queue to become empty ASAP, keeping data
@@@ -1031,19 -1027,10 +1028,19 @@@ static in
  gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
  {
        struct gs_port  *port;
 +      int             ret = 0;
 +
 +      mutex_lock(&ports[port_num].lock);
 +      if (ports[port_num].port) {
 +              ret = -EBUSY;
 +              goto out;
 +      }
  
        port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
 -      if (port == NULL)
 -              return -ENOMEM;
 +      if (port == NULL) {
 +              ret = -ENOMEM;
 +              goto out;
 +      }
  
        tty_port_init(&port->port);
        spin_lock_init(&port->port_lock);
        port->port_line_coding = *coding;
  
        ports[port_num].port = port;
 -
 -      return 0;
 -}
 -
 -/**
 - * gserial_setup - initialize TTY driver for one or more ports
 - * @g: gadget to associate with these ports
 - * @count: how many ports to support
 - * Context: may sleep
 - *
 - * The TTY stack needs to know in advance how many devices it should
 - * plan to manage.  Use this call to set up the ports you will be
 - * exporting through USB.  Later, connect them to functions based
 - * on what configuration is activated by the USB host; and disconnect
 - * them as appropriate.
 - *
 - * An example would be a two-configuration device in which both
 - * configurations expose port 0, but through different functions.
 - * One configuration could even expose port 1 while the other
 - * one doesn't.
 - *
 - * Returns negative errno or zero.
 - */
 -int gserial_setup(struct usb_gadget *g, unsigned count)
 -{
 -      unsigned                        i;
 -      struct usb_cdc_line_coding      coding;
 -      int                             status;
 -
 -      if (count == 0 || count > N_PORTS)
 -              return -EINVAL;
 -
 -      gs_tty_driver = alloc_tty_driver(count);
 -      if (!gs_tty_driver)
 -              return -ENOMEM;
 -
 -      gs_tty_driver->driver_name = "g_serial";
 -      gs_tty_driver->name = PREFIX;
 -      /* uses dynamically assigned dev_t values */
 -
 -      gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
 -      gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
 -      gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 -      gs_tty_driver->init_termios = tty_std_termios;
 -
 -      /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
 -       * MS-Windows.  Otherwise, most of these flags shouldn't affect
 -       * anything unless we were to actually hook up to a serial line.
 -       */
 -      gs_tty_driver->init_termios.c_cflag =
 -                      B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 -      gs_tty_driver->init_termios.c_ispeed = 9600;
 -      gs_tty_driver->init_termios.c_ospeed = 9600;
 -
 -      coding.dwDTERate = cpu_to_le32(9600);
 -      coding.bCharFormat = 8;
 -      coding.bParityType = USB_CDC_NO_PARITY;
 -      coding.bDataBits = USB_CDC_1_STOP_BITS;
 -
 -      tty_set_operations(gs_tty_driver, &gs_tty_ops);
 -
 -      /* make devices be openable */
 -      for (i = 0; i < count; i++) {
 -              mutex_init(&ports[i].lock);
 -              status = gs_port_alloc(i, &coding);
 -              if (status) {
 -                      count = i;
 -                      goto fail;
 -              }
 -      }
 -      n_ports = count;
 -
 -      /* export the driver ... */
 -      status = tty_register_driver(gs_tty_driver);
 -      if (status) {
 -              pr_err("%s: cannot register, err %d\n",
 -                              __func__, status);
 -              goto fail;
 -      }
 -
 -      /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
 -      for (i = 0; i < count; i++) {
 -              struct device   *tty_dev;
 -
 -              tty_dev = tty_port_register_device(&ports[i].port->port,
 -                              gs_tty_driver, i, &g->dev);
 -              if (IS_ERR(tty_dev))
 -                      pr_warning("%s: no classdev for port %d, err %ld\n",
 -                              __func__, i, PTR_ERR(tty_dev));
 -      }
 -
 -      pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
 -                      count, (count == 1) ? "" : "s");
 -
 -      return status;
 -fail:
 -      while (count--) {
 -              tty_port_destroy(&ports[count].port->port);
 -              kfree(ports[count].port);
 -      }
 -      put_tty_driver(gs_tty_driver);
 -      gs_tty_driver = NULL;
 -      return status;
 +out:
 +      mutex_unlock(&ports[port_num].lock);
 +      return ret;
  }
  
  static int gs_closed(struct gs_port *port)
        return cond;
  }
  
 -/**
 - * gserial_cleanup - remove TTY-over-USB driver and devices
 - * Context: may sleep
 - *
 - * This is called to free all resources allocated by @gserial_setup().
 - * Accordingly, it may need to wait until some open /dev/ files have
 - * closed.
 - *
 - * The caller must have issued @gserial_disconnect() for any ports
 - * that had previously been connected, so that there is never any
 - * I/O pending when it's called.
 - */
 -void gserial_cleanup(void)
 +static void gserial_free_port(struct gs_port *port)
 +{
 +      tasklet_kill(&port->push);
 +      /* wait for old opens to finish */
 +      wait_event(port->port.close_wait, gs_closed(port));
 +      WARN_ON(port->port_usb != NULL);
 +      tty_port_destroy(&port->port);
 +      kfree(port);
 +}
 +
 +void gserial_free_line(unsigned char port_num)
  {
 -      unsigned        i;
        struct gs_port  *port;
  
 -      if (!gs_tty_driver)
 +      mutex_lock(&ports[port_num].lock);
 +      if (WARN_ON(!ports[port_num].port)) {
 +              mutex_unlock(&ports[port_num].lock);
                return;
 +      }
 +      port = ports[port_num].port;
 +      ports[port_num].port = NULL;
 +      mutex_unlock(&ports[port_num].lock);
  
 -      /* start sysfs and /dev/ttyGS* node removal */
 -      for (i = 0; i < n_ports; i++)
 -              tty_unregister_device(gs_tty_driver, i);
 -
 -      for (i = 0; i < n_ports; i++) {
 -              /* prevent new opens */
 -              mutex_lock(&ports[i].lock);
 -              port = ports[i].port;
 -              ports[i].port = NULL;
 -              mutex_unlock(&ports[i].lock);
 -
 -              tasklet_kill(&port->push);
 +      gserial_free_port(port);
 +      tty_unregister_device(gs_tty_driver, port_num);
 +}
 +EXPORT_SYMBOL_GPL(gserial_free_line);
  
 -              /* wait for old opens to finish */
 -              wait_event(port->port.close_wait, gs_closed(port));
 +int gserial_alloc_line(unsigned char *line_num)
 +{
 +      struct usb_cdc_line_coding      coding;
 +      struct device                   *tty_dev;
 +      int                             ret;
 +      int                             port_num;
  
 -              WARN_ON(port->port_usb != NULL);
 +      coding.dwDTERate = cpu_to_le32(9600);
 +      coding.bCharFormat = 8;
 +      coding.bParityType = USB_CDC_NO_PARITY;
 +      coding.bDataBits = USB_CDC_1_STOP_BITS;
  
 -              tty_port_destroy(&port->port);
 -              kfree(port);
 +      for (port_num = 0; port_num < MAX_U_SERIAL_PORTS; port_num++) {
 +              ret = gs_port_alloc(port_num, &coding);
 +              if (ret == -EBUSY)
 +                      continue;
 +              if (ret)
 +                      return ret;
 +              break;
        }
 -      n_ports = 0;
 +      if (ret)
 +              return ret;
  
 -      tty_unregister_driver(gs_tty_driver);
 -      put_tty_driver(gs_tty_driver);
 -      gs_tty_driver = NULL;
 +      /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
 +
 +      tty_dev = tty_port_register_device(&ports[port_num].port->port,
 +                      gs_tty_driver, port_num, NULL);
 +      if (IS_ERR(tty_dev)) {
 +              struct gs_port  *port;
 +              pr_err("%s: failed to register tty for port %d, err %ld\n",
 +                              __func__, port_num, PTR_ERR(tty_dev));
  
 -      pr_debug("%s: cleaned up ttyGS* support\n", __func__);
 +              ret = PTR_ERR(tty_dev);
 +              port = ports[port_num].port;
 +              ports[port_num].port = NULL;
 +              gserial_free_port(port);
 +              goto err;
 +      }
 +      *line_num = port_num;
 +err:
 +      return ret;
  }
 +EXPORT_SYMBOL_GPL(gserial_alloc_line);
  
  /**
   * gserial_connect - notify TTY I/O glue that USB link is active
   *
   * Caller needs to have set up the endpoints and USB function in @dev
   * before calling this, as well as the appropriate (speed-specific)
 - * endpoint descriptors, and also have set up the TTY driver by calling
 - * @gserial_setup().
 + * endpoint descriptors, and also have allocate @port_num by calling
 + * @gserial_alloc_line().
   *
   * Returns negative errno or zero.
   * On success, ep->driver_data will be overwritten.
@@@ -1173,18 -1238,11 +1170,18 @@@ int gserial_connect(struct gserial *gse
        unsigned long   flags;
        int             status;
  
 -      if (!gs_tty_driver || port_num >= n_ports)
 +      if (port_num >= MAX_U_SERIAL_PORTS)
                return -ENXIO;
  
 -      /* we "know" gserial_cleanup() hasn't been called */
        port = ports[port_num].port;
 +      if (!port) {
 +              pr_err("serial line %d not allocated.\n", port_num);
 +              return -EINVAL;
 +      }
 +      if (port->port_usb) {
 +              pr_err("serial line %d is in use.\n", port_num);
 +              return -EBUSY;
 +      }
  
        /* activate the endpoints */
        status = usb_ep_enable(gser->in);
@@@ -1231,7 -1289,7 +1228,7 @@@ fail_out
        gser->in->driver_data = NULL;
        return status;
  }
 -
 +EXPORT_SYMBOL_GPL(gserial_connect);
  /**
   * gserial_disconnect - notify TTY I/O glue that USB link is inactive
   * @gser: the function, on which gserial_connect() was called
@@@ -1286,65 -1344,3 +1283,65 @@@ void gserial_disconnect(struct gserial 
  
        spin_unlock_irqrestore(&port->port_lock, flags);
  }
 +EXPORT_SYMBOL_GPL(gserial_disconnect);
 +
 +static int userial_init(void)
 +{
 +      unsigned                        i;
 +      int                             status;
 +
 +      gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
 +      if (!gs_tty_driver)
 +              return -ENOMEM;
 +
 +      gs_tty_driver->driver_name = "g_serial";
 +      gs_tty_driver->name = PREFIX;
 +      /* uses dynamically assigned dev_t values */
 +
 +      gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
 +      gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
 +      gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 +      gs_tty_driver->init_termios = tty_std_termios;
 +
 +      /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
 +       * MS-Windows.  Otherwise, most of these flags shouldn't affect
 +       * anything unless we were to actually hook up to a serial line.
 +       */
 +      gs_tty_driver->init_termios.c_cflag =
 +                      B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 +      gs_tty_driver->init_termios.c_ispeed = 9600;
 +      gs_tty_driver->init_termios.c_ospeed = 9600;
 +
 +      tty_set_operations(gs_tty_driver, &gs_tty_ops);
 +      for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
 +              mutex_init(&ports[i].lock);
 +
 +      /* export the driver ... */
 +      status = tty_register_driver(gs_tty_driver);
 +      if (status) {
 +              pr_err("%s: cannot register, err %d\n",
 +                              __func__, status);
 +              goto fail;
 +      }
 +
 +      pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
 +                      MAX_U_SERIAL_PORTS,
 +                      (MAX_U_SERIAL_PORTS == 1) ? "" : "s");
 +
 +      return status;
 +fail:
 +      put_tty_driver(gs_tty_driver);
 +      gs_tty_driver = NULL;
 +      return status;
 +}
 +module_init(userial_init);
 +
 +static void userial_cleanup(void)
 +{
 +      tty_unregister_driver(gs_tty_driver);
 +      put_tty_driver(gs_tty_driver);
 +      gs_tty_driver = NULL;
 +}
 +module_exit(userial_cleanup);
 +
 +MODULE_LICENSE("GPL");
index dad8363e5b2a33571ca56c618189a4b810e9a45b,d8e35fe30b0c8c5a0d0fd87fbabf3230737c944d..17b7f9ae36ad16eb183b3eb2cf7ec187ccadf7b5
@@@ -4,7 -4,7 +4,7 @@@
  
  menuconfig USB_SERIAL
        tristate "USB Serial Converter support"
-       depends on USB
+       depends on USB && TTY
        ---help---
          Say Y here if you have a USB device that provides normal serial
          ports, or acts like a serial device, and you want to connect it to
@@@ -647,18 -647,6 +647,18 @@@ config USB_SERIAL_VIVOPAY_SERIA
            To compile this driver as a module, choose M here: the
            module will be called vivopay-serial.
  
 +config USB_SERIAL_XSENS_MT
 +      tristate "Xsens motion tracker serial interface driver"
 +      help
 +        Say Y here if you want to use Xsens motion trackers.
 +
 +        This driver supports the new generation of motion trackers
 +        by Xsens. Older devices can be accessed using the FTDI_SIO
 +        driver.
 +
 +        To compile this driver as a module, choose M here: the
 +        module will be called xsens_mt.
 +
  config USB_SERIAL_ZIO
        tristate "ZIO Motherboard USB serial interface driver"
        help
index d07fccf3bab5caa431dd5d77d3d552913a89ac9c,eaa038d032b85b427f635791168e770a58795916..edd162df49caed8b02a1c0823a497c6c5d9d180e
@@@ -584,7 -584,6 +584,7 @@@ static struct usb_device_id id_table_co
        /*
         * ELV devices:
         */
 +      { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
 +      { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
@@@ -1886,22 -1884,24 +1886,22 @@@ static void ftdi_dtr_rts(struct usb_ser
  {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
  
 -      mutex_lock(&port->serial->disc_mutex);
 -      if (!port->serial->disconnected) {
 -              /* Disable flow control */
 -              if (!on && usb_control_msg(port->serial->dev,
 +      /* Disable flow control */
 +      if (!on) {
 +              if (usb_control_msg(port->serial->dev,
                            usb_sndctrlpipe(port->serial->dev, 0),
                            FTDI_SIO_SET_FLOW_CTRL_REQUEST,
                            FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
                            0, priv->interface, NULL, 0,
                            WDR_TIMEOUT) < 0) {
 -                          dev_err(&port->dev, "error from flowcontrol urb\n");
 +                      dev_err(&port->dev, "error from flowcontrol urb\n");
                }
 -              /* drop RTS and DTR */
 -              if (on)
 -                      set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 -              else
 -                      clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
        }
 -      mutex_unlock(&port->serial->disc_mutex);
 +      /* drop RTS and DTR */
 +      if (on)
 +              set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 +      else
 +              clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
  }
  
  /*
@@@ -1960,9 -1960,8 +1960,8 @@@ static int ftdi_prepare_write_buffer(st
  
  #define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE)
  
- static int ftdi_process_packet(struct tty_struct *tty,
-               struct usb_serial_port *port, struct ftdi_private *priv,
-               char *packet, int len)
+ static int ftdi_process_packet(struct usb_serial_port *port,
+               struct ftdi_private *priv, char *packet, int len)
  {
        int i;
        char status;
                /* Overrun is special, not associated with a char */
                if (packet[1] & FTDI_RS_OE) {
                        priv->icount.overrun++;
-                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+                       tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
                }
        }
  
        if (port->port.console && port->sysrq) {
                for (i = 0; i < len; i++, ch++) {
                        if (!usb_serial_handle_sysrq_char(port, *ch))
-                               tty_insert_flip_char(tty, *ch, flag);
+                               tty_insert_flip_char(&port->port, *ch, flag);
                }
        } else {
-               tty_insert_flip_string_fixed_flag(tty, ch, flag, len);
+               tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
        }
  
        return len;
  static void ftdi_process_read_urb(struct urb *urb)
  {
        struct usb_serial_port *port = urb->context;
-       struct tty_struct *tty;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        char *data = (char *)urb->transfer_buffer;
        int i;
        int len;
        int count = 0;
  
-       tty = tty_port_tty_get(&port->port);
-       if (!tty)
-               return;
        for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
                len = min_t(int, urb->actual_length - i, priv->max_packet_size);
-               count += ftdi_process_packet(tty, port, priv, &data[i], len);
+               count += ftdi_process_packet(port, priv, &data[i], len);
        }
  
        if (count)
-               tty_flip_buffer_push(tty);
-       tty_kref_put(tty);
+               tty_flip_buffer_push(&port->port);
  }
  
  static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
index 641ab3da2d83191bc13785a6f631379009e43e52,b5ab0a54b6b6624195419de00a6054f075c682bd..c23776679f7029a37598e5cea826060670be7e64
@@@ -201,8 -201,8 +201,8 @@@ static int closing_wait = EDGE_CLOSING_
  static bool ignore_cpu_rev;
  static int default_uart_mode;         /* RS232 */
  
- static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
-                         unsigned char *data, int length);
+ static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
+               int length);
  
  static void stop_read(struct edgeport_port *edge_port);
  static int restart_read(struct edgeport_port *edge_port);
@@@ -521,6 -521,65 +521,6 @@@ exit_is_tx_active
        return bytes_left;
  }
  
 -static void chase_port(struct edgeport_port *port, unsigned long timeout,
 -                                                              int flush)
 -{
 -      int baud_rate;
 -      struct tty_struct *tty = tty_port_tty_get(&port->port->port);
 -      struct usb_serial *serial = port->port->serial;
 -      wait_queue_t wait;
 -      unsigned long flags;
 -
 -      if (!tty)
 -              return;
 -
 -      if (!timeout)
 -              timeout = (HZ * EDGE_CLOSING_WAIT)/100;
 -
 -      /* wait for data to drain from the buffer */
 -      spin_lock_irqsave(&port->ep_lock, flags);
 -      init_waitqueue_entry(&wait, current);
 -      add_wait_queue(&tty->write_wait, &wait);
 -      for (;;) {
 -              set_current_state(TASK_INTERRUPTIBLE);
 -              if (kfifo_len(&port->write_fifo) == 0
 -              || timeout == 0 || signal_pending(current)
 -              || serial->disconnected)
 -                      /* disconnect */
 -                      break;
 -              spin_unlock_irqrestore(&port->ep_lock, flags);
 -              timeout = schedule_timeout(timeout);
 -              spin_lock_irqsave(&port->ep_lock, flags);
 -      }
 -      set_current_state(TASK_RUNNING);
 -      remove_wait_queue(&tty->write_wait, &wait);
 -      if (flush)
 -              kfifo_reset_out(&port->write_fifo);
 -      spin_unlock_irqrestore(&port->ep_lock, flags);
 -      tty_kref_put(tty);
 -
 -      /* wait for data to drain from the device */
 -      timeout += jiffies;
 -      while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
 -                                              && !serial->disconnected) {
 -              /* not disconnected */
 -              if (!tx_active(port))
 -                      break;
 -              msleep(10);
 -      }
 -
 -      /* disconnected */
 -      if (serial->disconnected)
 -              return;
 -
 -      /* wait one more character time, based on baud rate */
 -      /* (tx_active doesn't seem to wait for the last byte) */
 -      baud_rate = port->baud_rate;
 -      if (baud_rate == 0)
 -              baud_rate = 50;
 -      msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
 -}
 -
  static int choose_config(struct usb_device *dev)
  {
        /*
@@@ -1484,7 -1543,6 +1484,6 @@@ static void handle_new_lsr(struct edgep
        struct async_icount *icount;
        __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
                                                LSR_FRM_ERR | LSR_BREAK));
-       struct tty_struct *tty;
  
        dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, new_lsr);
  
                new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
  
        /* Place LSR data byte into Rx buffer */
-       if (lsr_data) {
-               tty = tty_port_tty_get(&edge_port->port->port);
-               if (tty) {
-                       edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
-                       tty_kref_put(tty);
-               }
-       }
+       if (lsr_data)
+               edge_tty_recv(edge_port->port, &data, 1);
  
        /* update input line counters */
        icount = &edge_port->icount;
@@@ -1620,7 -1673,6 +1614,6 @@@ static void edge_bulk_in_callback(struc
        struct edgeport_port *edge_port = urb->context;
        struct device *dev = &edge_port->port->dev;
        unsigned char *data = urb->transfer_buffer;
-       struct tty_struct *tty;
        int retval = 0;
        int port_number;
        int status = urb->status;
                ++data;
        }
  
-       tty = tty_port_tty_get(&edge_port->port->port);
-       if (tty && urb->actual_length) {
+       if (urb->actual_length) {
                usb_serial_debug_data(dev, __func__, urb->actual_length, data);
                if (edge_port->close_pending)
                        dev_dbg(dev, "%s - close pending, dropping data on the floor\n",
                                                                __func__);
                else
-                       edge_tty_recv(dev, tty, data, urb->actual_length);
+                       edge_tty_recv(edge_port->port, data,
+                                       urb->actual_length);
                edge_port->icount.rx += urb->actual_length;
        }
-       tty_kref_put(tty);
  
  exit:
        /* continue read unless stopped */
                dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval);
  }
  
- static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
-                                       unsigned char *data, int length)
+ static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
+               int length)
  {
        int queued;
  
-       queued = tty_insert_flip_string(tty, data, length);
+       queued = tty_insert_flip_string(&port->port, data, length);
        if (queued < length)
-               dev_err(dev, "%s - dropping data, %d bytes lost\n",
+               dev_err(&port->dev, "%s - dropping data, %d bytes lost\n",
                        __func__, length - queued);
-       tty_flip_buffer_push(tty);
+       tty_flip_buffer_push(&port->port);
  }
  
  static void edge_bulk_out_callback(struct urb *urb)
@@@ -1885,8 -1936,6 +1877,8 @@@ static int edge_open(struct tty_struct 
  
        ++edge_serial->num_ports_open;
  
 +      port->port.drain_delay = 1;
 +
        goto release_es_lock;
  
  unlink_int_urb:
@@@ -1902,7 -1951,6 +1894,7 @@@ static void edge_close(struct usb_seria
        struct edgeport_serial *edge_serial;
        struct edgeport_port *edge_port;
        struct usb_serial *serial = port->serial;
 +      unsigned long flags;
        int port_number;
  
        edge_serial = usb_get_serial_data(port->serial);
         * this flag and dump add read data */
        edge_port->close_pending = 1;
  
 -      /* chase the port close and flush */
 -      chase_port(edge_port, (HZ * closing_wait) / 100, 1);
 -
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->write_urb);
        edge_port->ep_write_urb_in_use = 0;
 +      spin_lock_irqsave(&edge_port->ep_lock, flags);
 +      kfifo_reset_out(&edge_port->write_fifo);
 +      spin_unlock_irqrestore(&edge_port->ep_lock, flags);
  
        /* assuming we can still talk to the device,
         * send a close port command to it */
@@@ -2045,21 -2093,16 +2037,21 @@@ static int edge_chars_in_buffer(struct 
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        int chars = 0;
        unsigned long flags;
 +      int ret;
  
        if (edge_port == NULL)
                return 0;
 -      if (edge_port->close_pending == 1)
 -              return 0;
  
        spin_lock_irqsave(&edge_port->ep_lock, flags);
        chars = kfifo_len(&edge_port->write_fifo);
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
  
 +      if (!chars) {
 +              ret = tx_active(edge_port);
 +              if (ret > 0)
 +                      chars = ret;
 +      }
 +
        dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
        return chars;
  }
@@@ -2397,15 -2440,10 +2389,15 @@@ static int get_serial_info(struct edgep
                                struct serial_struct __user *retinfo)
  {
        struct serial_struct tmp;
 +      unsigned cwait;
  
        if (!retinfo)
                return -EFAULT;
  
 +      cwait = edge_port->port->port.closing_wait;
 +      if (cwait != ASYNC_CLOSING_WAIT_NONE)
 +              cwait = jiffies_to_msecs(closing_wait) / 10;
 +
        memset(&tmp, 0, sizeof(tmp));
  
        tmp.type                = PORT_16550A;
        tmp.xmit_fifo_size      = edge_port->port->bulk_out_size;
        tmp.baud_base           = 9600;
        tmp.close_delay         = 5*HZ;
 -      tmp.closing_wait        = closing_wait;
 +      tmp.closing_wait        = cwait;
  
        if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
                return -EFAULT;
@@@ -2471,7 -2509,8 +2463,7 @@@ static void edge_break(struct tty_struc
        int status;
        int bv = 0;     /* Off */
  
 -      /* chase the port close */
 -      chase_port(edge_port, 0, 0);
 +      tty_wait_until_sent(tty, 0);
  
        if (break_state == -1)
                bv = 1; /* On */
@@@ -2544,8 -2583,6 +2536,8 @@@ static int edge_port_probe(struct usb_s
                return ret;
        }
  
 +      port->port.closing_wait = msecs_to_jiffies(closing_wait * 10);
 +
        return 0;
  }
  
index 3d95637f3d68d93d65257496587b2849ea8d0a60,f6d7f68fa43cbff922dae8c9dedc6726577f5649..1fd1935c8316f525e5795c22fa0dada0093b6be9
@@@ -291,21 -291,19 +291,19 @@@ static void     usa26_indat_callback(struc
        int                     i, err;
        int                     endpoint;
        struct usb_serial_port  *port;
-       struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
  
        endpoint = usb_pipeendpoint(urb->pipe);
  
        if (status) {
 -              dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n",
 +              dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
                        __func__, status, endpoint);
                return;
        }
  
        port =  urb->context;
-       tty = tty_port_tty_get(&port->port);
-       if (tty && urb->actual_length) {
+       if (urb->actual_length) {
                /* 0x80 bit is error flag */
                if ((data[0] & 0x80) == 0) {
                        /* no errors on individual bytes, only
                        else
                                err = 0;
                        for (i = 1; i < urb->actual_length ; ++i)
-                               tty_insert_flip_char(tty, data[i], err);
+                               tty_insert_flip_char(&port->port, data[i], err);
                } else {
                        /* some bytes had errors, every byte has status */
                        dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
                                if (stat & RXERROR_PARITY)
                                        flag |= TTY_PARITY;
                                /* XXX should handle break (0x10) */
-                               tty_insert_flip_char(tty, data[i+1], flag);
+                               tty_insert_flip_char(&port->port, data[i+1],
+                                               flag);
                        }
                }
-               tty_flip_buffer_push(tty);
+               tty_flip_buffer_push(&port->port);
        }
-       tty_kref_put(tty);
  
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -446,7 -444,6 +444,6 @@@ static void usa28_indat_callback(struc
  {
        int                     err;
        struct usb_serial_port  *port;
-       struct tty_struct       *tty;
        unsigned char           *data;
        struct keyspan_port_private             *p_priv;
        int status = urb->status;
                p_priv = usb_get_serial_port_data(port);
                data = urb->transfer_buffer;
  
-               tty = tty_port_tty_get(&port->port);
-               if (tty && urb->actual_length) {
-                       tty_insert_flip_string(tty, data, urb->actual_length);
-                       tty_flip_buffer_push(tty);
+               if (urb->actual_length) {
+                       tty_insert_flip_string(&port->port, data,
+                                       urb->actual_length);
+                       tty_flip_buffer_push(&port->port);
                }
-               tty_kref_put(tty);
  
                /* Resubmit urb so we continue receiving */
                err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -532,7 -528,7 +528,7 @@@ static void        usa28_instat_callback(struc
  
        /*
        dev_dbg(&urb->dev->dev,
 -              "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
 +              "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
                data[0], data[1], data[2], data[3], data[4], data[5],
                data[6], data[7], data[8], data[9], data[10], data[11]);
        */
@@@ -669,7 -665,6 +665,6 @@@ static void        usa49_indat_callback(struc
        int                     i, err;
        int                     endpoint;
        struct usb_serial_port  *port;
-       struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
  
        }
  
        port =  urb->context;
-       tty = tty_port_tty_get(&port->port);
-       if (tty && urb->actual_length) {
+       if (urb->actual_length) {
                /* 0x80 bit is error flag */
                if ((data[0] & 0x80) == 0) {
                        /* no error on any byte */
-                       tty_insert_flip_string(tty, data + 1,
+                       tty_insert_flip_string(&port->port, data + 1,
                                                urb->actual_length - 1);
                } else {
                        /* some bytes had errors, every byte has status */
                                if (stat & RXERROR_PARITY)
                                        flag |= TTY_PARITY;
                                /* XXX should handle break (0x10) */
-                               tty_insert_flip_char(tty, data[i+1], flag);
+                               tty_insert_flip_char(&port->port, data[i+1],
+                                               flag);
                        }
                }
-               tty_flip_buffer_push(tty);
+               tty_flip_buffer_push(&port->port);
        }
-       tty_kref_put(tty);
  
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@@ -718,7 -712,6 +712,6 @@@ static void usa49wg_indat_callback(stru
        int                     i, len, x, err;
        struct usb_serial       *serial;
        struct usb_serial_port  *port;
-       struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
  
                                return;
                        }
                        port = serial->port[data[i++]];
-                       tty = tty_port_tty_get(&port->port);
                        len = data[i++];
  
                        /* 0x80 bit is error flag */
                                /* no error on any byte */
                                i++;
                                for (x = 1; x < len ; ++x)
-                                       tty_insert_flip_char(tty, data[i++], 0);
+                                       tty_insert_flip_char(&port->port,
+                                                       data[i++], 0);
                        } else {
                                /*
                                 * some bytes had errors, every byte has status
                                        if (stat & RXERROR_PARITY)
                                                flag |= TTY_PARITY;
                                        /* XXX should handle break (0x10) */
-                                       tty_insert_flip_char(tty,
+                                       tty_insert_flip_char(&port->port,
                                                        data[i+1], flag);
                                        i += 2;
                                }
                        }
-                       tty_flip_buffer_push(tty);
-                       tty_kref_put(tty);
+                       tty_flip_buffer_push(&port->port);
                }
        }
  
@@@ -792,7 -784,6 +784,6 @@@ static void usa90_indat_callback(struc
        int                     endpoint;
        struct usb_serial_port  *port;
        struct keyspan_port_private             *p_priv;
-       struct tty_struct       *tty;
        unsigned char           *data = urb->transfer_buffer;
        int status = urb->status;
  
        p_priv = usb_get_serial_port_data(port);
  
        if (urb->actual_length) {
-               tty = tty_port_tty_get(&port->port);
                /* if current mode is DMA, looks like usa28 format
                   otherwise looks like usa26 data format */
  
                if (p_priv->baud > 57600)
-                       tty_insert_flip_string(tty, data, urb->actual_length);
+                       tty_insert_flip_string(&port->port, data,
+                                       urb->actual_length);
                else {
                        /* 0x80 bit is error flag */
                        if ((data[0] & 0x80) == 0) {
                                else
                                        err = 0;
                                for (i = 1; i < urb->actual_length ; ++i)
-                                       tty_insert_flip_char(tty, data[i],
-                                                                       err);
+                                       tty_insert_flip_char(&port->port,
+                                                       data[i], err);
                        }  else {
                        /* some bytes had errors, every byte has status */
                                dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
                                        if (stat & RXERROR_PARITY)
                                                flag |= TTY_PARITY;
                                        /* XXX should handle break (0x10) */
-                                       tty_insert_flip_char(tty, data[i+1],
-                                                                       flag);
+                                       tty_insert_flip_char(&port->port,
+                                                       data[i+1], flag);
                                }
                        }
                }
-               tty_flip_buffer_push(tty);
-               tty_kref_put(tty);
+               tty_flip_buffer_push(&port->port);
        }
  
        /* Resubmit urb so we continue receiving */
index d9c86516fed434fb80cc4a40613f9fc3f5a80eb5,f42528e05d7b639f90905e9d3496d36e7a111cc2..a64d420f687b0a198ded7bac0cd38a17b89494c0
@@@ -499,15 -499,19 +499,15 @@@ static void mct_u232_dtr_rts(struct usb
        unsigned int control_state;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
  
 -      mutex_lock(&port->serial->disc_mutex);
 -      if (!port->serial->disconnected) {
 -              /* drop DTR and RTS */
 -              spin_lock_irq(&priv->lock);
 -              if (on)
 -                      priv->control_state |= TIOCM_DTR | TIOCM_RTS;
 -              else
 -                      priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
 -              control_state = priv->control_state;
 -              spin_unlock_irq(&priv->lock);
 -              mct_u232_set_modem_ctrl(port, control_state);
 -      }
 -      mutex_unlock(&port->serial->disc_mutex);
 +      spin_lock_irq(&priv->lock);
 +      if (on)
 +              priv->control_state |= TIOCM_DTR | TIOCM_RTS;
 +      else
 +              priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
 +      control_state = priv->control_state;
 +      spin_unlock_irq(&priv->lock);
 +
 +      mct_u232_set_modem_ctrl(port, control_state);
  }
  
  static void mct_u232_close(struct usb_serial_port *port)
@@@ -527,7 -531,6 +527,6 @@@ static void mct_u232_read_int_callback(
  {
        struct usb_serial_port *port = urb->context;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int retval;
        int status = urb->status;
         */
        if (urb->transfer_buffer_length > 2) {
                if (urb->actual_length) {
-                       tty = tty_port_tty_get(&port->port);
-                       if (tty) {
-                               tty_insert_flip_string(tty, data,
-                                               urb->actual_length);
-                               tty_flip_buffer_push(tty);
-                       }
-                       tty_kref_put(tty);
+                       tty_insert_flip_string(&port->port, data,
+                                       urb->actual_length);
+                       tty_flip_buffer_push(&port->port);
                }
                goto exit;
        }
index a8d5110d4cc566369ebc6f47a2d99c023ef5e5a2,6850745808c3932e3167f2d85c76636465eecec4..00e6c9bac8a309b0df675903654ce0521f991cad
@@@ -609,7 -609,6 +609,6 @@@ void qt2_process_read_urb(struct urb *u
        struct qt2_serial_private *serial_priv;
        struct usb_serial_port *port;
        struct qt2_port_private *port_priv;
-       struct tty_struct *tty;
        bool escapeflag;
        unsigned char *ch;
        int i;
                return;
  
        ch = urb->transfer_buffer;
-       tty = NULL;
        serial = urb->context;
        serial_priv = usb_get_serial_data(serial);
        port = serial->port[serial_priv->current_port];
        port_priv = usb_get_serial_port_data(port);
  
-       if (port_priv->is_open)
-               tty = tty_port_tty_get(&port->port);
        for (i = 0; i < urb->actual_length; i++) {
                ch = (unsigned char *)urb->transfer_buffer + i;
                if ((i <= (len - 3)) &&
                                                 __func__);
                                        break;
                                }
-                               if (tty) {
-                                       tty_flip_buffer_push(tty);
-                                       tty_kref_put(tty);
-                               }
+                               tty_flip_buffer_push(&port->port);
  
                                newport = *(ch + 3);
  
                                serial_priv->current_port = newport;
                                port = serial->port[serial_priv->current_port];
                                port_priv = usb_get_serial_port_data(port);
-                               if (port_priv->is_open)
-                                       tty = tty_port_tty_get(&port->port);
-                               else
-                                       tty = NULL;
                                i += 3;
                                escapeflag = true;
                                break;
                                escapeflag = true;
                                break;
                        case QT2_CONTROL_ESCAPE:
-                               tty_buffer_request_room(tty, 2);
-                               tty_insert_flip_string(tty, ch, 2);
+                               tty_buffer_request_room(&port->port, 2);
+                               tty_insert_flip_string(&port->port, ch, 2);
                                i += 2;
                                escapeflag = true;
                                break;
                                continue;
                }
  
-               if (tty) {
-                       tty_buffer_request_room(tty, 1);
-                       tty_insert_flip_string(tty, ch, 1);
-               }
+               tty_buffer_request_room(&port->port, 1);
+               tty_insert_flip_string(&port->port, ch, 1);
        }
  
-       if (tty) {
-               tty_flip_buffer_push(tty);
-               tty_kref_put(tty);
-       }
+       tty_flip_buffer_push(&port->port);
  }
  
  static void qt2_write_bulk_callback(struct urb *urb)
@@@ -945,17 -928,19 +928,17 @@@ static void qt2_dtr_rts(struct usb_seri
        struct usb_device *dev = port->serial->dev;
        struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
  
 -      mutex_lock(&port->serial->disc_mutex);
 -      if (!port->serial->disconnected) {
 -              /* Disable flow control */
 -              if (!on && qt2_setregister(dev, port_priv->device_port,
 +      /* Disable flow control */
 +      if (!on) {
 +              if (qt2_setregister(dev, port_priv->device_port,
                                           UART_MCR, 0) < 0)
                        dev_warn(&port->dev, "error from flowcontrol urb\n");
 -              /* drop RTS and DTR */
 -              if (on)
 -                      update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
 -              else
 -                      update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
        }
 -      mutex_unlock(&port->serial->disc_mutex);
 +      /* drop RTS and DTR */
 +      if (on)
 +              update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
 +      else
 +              update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
  }
  
  static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
index d4426c038c325933d8f26afeed550f0918e3892f,70aee8d59f232278d7a33be77822d5535d26cdcb..c13f6e747748b31d16c0d087fa4f8b1953826285
@@@ -569,7 -569,6 +569,6 @@@ static void sierra_indat_callback(struc
        int err;
        int endpoint;
        struct usb_serial_port *port;
-       struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
  
                        " endpoint %02x\n", __func__, status, endpoint);
        } else {
                if (urb->actual_length) {
-                       tty = tty_port_tty_get(&port->port);
-                       if (tty) {
-                               tty_insert_flip_string(tty, data,
-                                       urb->actual_length);
-                               tty_flip_buffer_push(tty);
-                               tty_kref_put(tty);
-                               usb_serial_debug_data(&port->dev, __func__,
-                                                     urb->actual_length, data);
-                       }
+                       tty_insert_flip_string(&port->port, data,
+                               urb->actual_length);
+                       tty_flip_buffer_push(&port->port);
+                       usb_serial_debug_data(&port->dev, __func__,
+                                             urb->actual_length, data);
                } else {
                        dev_dbg(&port->dev, "%s: empty read urb"
                                " received\n", __func__);
@@@ -861,13 -856,19 +856,13 @@@ static int sierra_open(struct tty_struc
  
  static void sierra_dtr_rts(struct usb_serial_port *port, int on)
  {
 -      struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
  
        portdata = usb_get_serial_port_data(port);
        portdata->rts_state = on;
        portdata->dtr_state = on;
  
 -      if (serial->dev) {
 -              mutex_lock(&serial->disc_mutex);
 -              if (!serial->disconnected)
 -                      sierra_send_setup(port);
 -              mutex_unlock(&serial->disc_mutex);
 -      }
 +      sierra_send_setup(port);
  }
  
  static int sierra_startup(struct usb_serial *serial)
index d938396171e87f22dd4f1f685dc3d33cccf751a9,58bc7e793524180a5dea4c602c479ede32d7aec6..b57cf841c5b6aa2ab1c21e13c12e063d51a2a9e7
@@@ -506,16 -506,19 +506,16 @@@ static void ssu100_dtr_rts(struct usb_s
  {
        struct usb_device *dev = port->serial->dev;
  
 -      mutex_lock(&port->serial->disc_mutex);
 -      if (!port->serial->disconnected) {
 -              /* Disable flow control */
 -              if (!on &&
 -                  ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
 +      /* Disable flow control */
 +      if (!on) {
 +              if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
                        dev_err(&port->dev, "error from flowcontrol urb\n");
 -              /* drop RTS and DTR */
 -              if (on)
 -                      set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
 -              else
 -                      clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
        }
 -      mutex_unlock(&port->serial->disc_mutex);
 +      /* drop RTS and DTR */
 +      if (on)
 +              set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
 +      else
 +              clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
  }
  
  static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
@@@ -579,8 -582,7 +579,7 @@@ static void ssu100_update_lsr(struct us
  
  }
  
- static int ssu100_process_packet(struct urb *urb,
-                                struct tty_struct *tty)
+ static void ssu100_process_read_urb(struct urb *urb)
  {
        struct usb_serial_port *port = urb->context;
        char *packet = (char *)urb->transfer_buffer;
                if (packet[2] == 0x00) {
                        ssu100_update_lsr(port, packet[3], &flag);
                        if (flag == TTY_OVERRUN)
-                               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+                               tty_insert_flip_char(&port->port, 0,
+                                               TTY_OVERRUN);
                }
                if (packet[2] == 0x01)
                        ssu100_update_msr(port, packet[3]);
                ch = packet;
  
        if (!len)
-               return 0;       /* status only */
+               return; /* status only */
  
        if (port->port.console && port->sysrq) {
                for (i = 0; i < len; i++, ch++) {
                        if (!usb_serial_handle_sysrq_char(port, *ch))
-                               tty_insert_flip_char(tty, *ch, flag);
+                               tty_insert_flip_char(&port->port, *ch, flag);
                }
        } else
-               tty_insert_flip_string_fixed_flag(tty, ch, flag, len);
-       return len;
- }
- static void ssu100_process_read_urb(struct urb *urb)
- {
-       struct usb_serial_port *port = urb->context;
-       struct tty_struct *tty;
-       int count;
-       tty = tty_port_tty_get(&port->port);
-       if (!tty)
-               return;
-       count = ssu100_process_packet(urb, tty);
+               tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
  
-       if (count)
-               tty_flip_buffer_push(tty);
-       tty_kref_put(tty);
+       tty_flip_buffer_push(&port->port);
  }
  
  static struct usb_serial_driver ssu100_device = {
index 1355a6cd45089832ee73520e9e9b1c6343bf7a23,a547c91e3c0557c609d2b52712699af9ada6c7d4..571965aa1cc015257eaf4bde8316ce10045a82a0
@@@ -38,6 -38,7 +38,6 @@@
  
  void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
  {
 -      struct usb_serial *serial = port->serial;
        struct usb_wwan_port_private *portdata;
        struct usb_wwan_intf_private *intfdata;
  
                return;
  
        portdata = usb_get_serial_port_data(port);
 -      mutex_lock(&serial->disc_mutex);
 +      /* FIXME: locking */
        portdata->rts_state = on;
        portdata->dtr_state = on;
 -      if (serial->dev)
 -              intfdata->send_setup(port);
 -      mutex_unlock(&serial->disc_mutex);
 +
 +      intfdata->send_setup(port);
  }
  EXPORT_SYMBOL(usb_wwan_dtr_rts);
  
@@@ -273,7 -275,6 +273,6 @@@ static void usb_wwan_indat_callback(str
        int err;
        int endpoint;
        struct usb_serial_port *port;
-       struct tty_struct *tty;
        struct device *dev;
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
                dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n",
                        __func__, status, endpoint);
        } else {
-               tty = tty_port_tty_get(&port->port);
-               if (tty) {
-                       if (urb->actual_length) {
-                               tty_insert_flip_string(tty, data,
-                                               urb->actual_length);
-                               tty_flip_buffer_push(tty);
-                       } else
-                               dev_dbg(dev, "%s: empty read urb received\n", __func__);
-                       tty_kref_put(tty);
-               }
+               if (urb->actual_length) {
+                       tty_insert_flip_string(&port->port, data,
+                                       urb->actual_length);
+                       tty_flip_buffer_push(&port->port);
+               } else
+                       dev_dbg(dev, "%s: empty read urb received\n", __func__);
  
                /* Resubmit urb so we continue receiving */
                err = usb_submit_urb(urb, GFP_ATOMIC);
diff --combined include/linux/pci_ids.h
index 6938ccfa42d59f5d795d6b4f0ed0e62c25fb32fe,19e8d7a42b3465d373cf681a3de273ab12fe5a9c..31717bd287fd9f8f1e2515d8947aa5c5896b21f1
  #define PCI_VENDOR_ID_ESDGMBH         0x12fe
  #define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
  
 +#define PCI_VENDOR_ID_CB              0x1307  /* Measurement Computing */
 +
  #define PCI_VENDOR_ID_SIIG            0x131f
  #define PCI_SUBVENDOR_ID_SIIG         0x131f
  #define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000
  #define PCI_VENDOR_ID_QUATECH         0x135C
  #define PCI_DEVICE_ID_QUATECH_QSC100  0x0010
  #define PCI_DEVICE_ID_QUATECH_DSC100  0x0020
+ #define PCI_DEVICE_ID_QUATECH_DSC200  0x0030
+ #define PCI_DEVICE_ID_QUATECH_QSC200  0x0040
  #define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050
  #define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060
+ #define PCI_DEVICE_ID_QUATECH_QSCP100 0x0120
+ #define PCI_DEVICE_ID_QUATECH_DSCP100 0x0130
+ #define PCI_DEVICE_ID_QUATECH_QSCP200 0x0140
+ #define PCI_DEVICE_ID_QUATECH_DSCP200 0x0150
+ #define PCI_DEVICE_ID_QUATECH_QSCLP100        0x0170
+ #define PCI_DEVICE_ID_QUATECH_DSCLP100        0x0180
+ #define PCI_DEVICE_ID_QUATECH_DSC100E 0x0181
+ #define PCI_DEVICE_ID_QUATECH_SSCLP100        0x0190
+ #define PCI_DEVICE_ID_QUATECH_QSCLP200        0x01A0
+ #define PCI_DEVICE_ID_QUATECH_DSCLP200        0x01B0
+ #define PCI_DEVICE_ID_QUATECH_DSC200E 0x01B1
+ #define PCI_DEVICE_ID_QUATECH_SSCLP200        0x01C0
+ #define PCI_DEVICE_ID_QUATECH_ESCLP100        0x01E0
  #define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
  
  #define PCI_VENDOR_ID_SEALEVEL                0x135e
  #define PCI_DEVICE_ID_CMEDIA_CM8738   0x0111
  #define PCI_DEVICE_ID_CMEDIA_CM8738B  0x0112
  
 +#define PCI_VENDOR_ID_ADVANTECH               0x13fe
 +
 +#define PCI_VENDOR_ID_MEILHAUS                0x1402
 +
  #define PCI_VENDOR_ID_LAVA            0x1407
  #define PCI_DEVICE_ID_LAVA_DSERIAL    0x0100 /* 2x 16550 */
  #define PCI_DEVICE_ID_LAVA_QUATRO_A   0x0101 /* 2x 16550, half of 4 port */
  
  #define PCI_VENDOR_ID_CHELSIO         0x1425
  
 +#define PCI_VENDOR_ID_ADLINK          0x144a
 +
  #define PCI_VENDOR_ID_SAMSUNG         0x144d
  
  #define PCI_VENDOR_ID_GIGABYTE                0x1458
  #define PCI_DEVICE_ID_AFAVLAB_P030    0x2182
  #define PCI_SUBDEVICE_ID_AFAVLAB_P061         0x2150
  
 +#define PCI_VENDOR_ID_AMPLICON                0x14dc
 +
  #define PCI_VENDOR_ID_BCM_GVC          0x14a4
  #define PCI_VENDOR_ID_BROADCOM                0x14e4
  #define PCI_DEVICE_ID_TIGON3_5752     0x1600
  #define PCI_DEVICE_ID_TIGON3_5754M    0x1672
  #define PCI_DEVICE_ID_TIGON3_5755M    0x1673
  #define PCI_DEVICE_ID_TIGON3_5756     0x1674
 +#define PCI_DEVICE_ID_TIGON3_5750     0x1676
  #define PCI_DEVICE_ID_TIGON3_5751     0x1677
  #define PCI_DEVICE_ID_TIGON3_5715     0x1678
  #define PCI_DEVICE_ID_TIGON3_5715S    0x1679
diff --combined include/linux/proc_fs.h
index d0a1f2ca1c3fe06194a4774c14777afc06fae3f7,3c22538aab667c1f843b9c4a8d0ef7b613b773c6..8307f2f94d860f46139b6a20d6795a9186704c19
@@@ -127,7 -127,12 +127,12 @@@ extern void pid_ns_release_proc(struct 
   * proc_tty.c
   */
  struct tty_driver;
+ #ifdef CONFIG_TTY
  extern void proc_tty_init(void);
+ #else
+ static inline void proc_tty_init(void)
+ { }
+ #endif
  extern void proc_tty_register_driver(struct tty_driver *driver);
  extern void proc_tty_unregister_driver(struct tty_driver *driver);
  
@@@ -171,6 -176,9 +176,6 @@@ static inline struct proc_dir_entry *cr
        return res;
  }
   
 -extern struct proc_dir_entry *proc_net_fops_create(struct net *net,
 -      const char *name, umode_t mode, const struct file_operations *fops);
 -extern void proc_net_remove(struct net *net, const char *name);
  extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
        struct proc_dir_entry *parent);
  
@@@ -181,15 -189,21 +186,15 @@@ extern int proc_alloc_inum(unsigned in
  extern void proc_free_inum(unsigned int inum);
  #else
  
 -#define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
 -static inline void proc_net_remove(struct net *net, const char *name) {}
 -
  static inline void proc_flush_task(struct task_struct *task)
  {
  }
  
  static inline struct proc_dir_entry *create_proc_entry(const char *name,
        umode_t mode, struct proc_dir_entry *parent) { return NULL; }
 -static inline struct proc_dir_entry *proc_create(const char *name,
 -      umode_t mode, struct proc_dir_entry *parent,
 -      const struct file_operations *proc_fops)
 -{
 -      return NULL;
 -}
 +
 +#define proc_create(name, mode, parent, fops)  ({ (void)(mode), NULL; })
 +
  static inline struct proc_dir_entry *proc_create_data(const char *name,
        umode_t mode, struct proc_dir_entry *parent,
        const struct file_operations *proc_fops, void *data)
diff --combined lib/Kconfig.kgdb
index 77439eb8528df2f4e28e6ffac830d469fca2b9f8,30894fab84d6791ffb5cfb3e40b9ce8dcb77b3d3..dbb58ae1b8e0c91060b3d8089bd5912d23a4c078
@@@ -5,7 -5,7 +5,7 @@@ config HAVE_ARCH_KGD
  menuconfig KGDB
        bool "KGDB: kernel debugger"
        depends on HAVE_ARCH_KGDB
 -      depends on DEBUG_KERNEL && EXPERIMENTAL
 +      depends on DEBUG_KERNEL
        help
          If you say Y here, it will be possible to remotely debug the
          kernel using gdb.  It is recommended but not required, that
@@@ -22,6 -22,7 +22,7 @@@ config KGDB_SERIAL_CONSOL
        tristate "KGDB: use kgdb over the serial console"
        select CONSOLE_POLL
        select MAGIC_SYSRQ
+       depends on TTY
        default y
        help
          Share a serial console with kgdb. Sysrq-g must be used
diff --combined sound/soc/codecs/Kconfig
index 133025fbb6d40e7ed3be462b1a7505975d978346,298822c0ad65d8b422b379769c2eb1d640a898f1..45b72561c61588f672b524471d9c5dd96cdeb73f
@@@ -34,9 -34,8 +34,9 @@@ config SND_SOC_ALL_CODEC
        select SND_SOC_CS42L73 if I2C
        select SND_SOC_CS4270 if I2C
        select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
-       select SND_SOC_CX20442
+       select SND_SOC_CX20442 if TTY
        select SND_SOC_DA7210 if I2C
 +      select SND_SOC_DA7213 if I2C
        select SND_SOC_DA732X if I2C
        select SND_SOC_DA9055 if I2C
        select SND_SOC_DFBMCS320
@@@ -99,7 -98,7 +99,7 @@@
        select SND_SOC_WM8782
        select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8900 if I2C
 -      select SND_SOC_WM8903 if I2C
 +      select SND_SOC_WM8903 if I2C && GENERIC_HARDIRQS
        select SND_SOC_WM8904 if I2C
        select SND_SOC_WM8940 if I2C
        select SND_SOC_WM8955 if I2C
@@@ -237,6 -236,7 +237,7 @@@ config SND_SOC_CS427
  
  config SND_SOC_CX20442
        tristate
+       depends on TTY
  
  config SND_SOC_JZ4740_CODEC
        select REGMAP_MMIO
@@@ -248,9 -248,6 +249,9 @@@ config SND_SOC_L
  config SND_SOC_DA7210
          tristate
  
 +config SND_SOC_DA7213
 +        tristate
 +
  config SND_SOC_DA732X
          tristate
  
This page took 0.378406 seconds and 4 git commands to generate.