Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 May 2011 19:23:20 +0000 (12:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 May 2011 19:23:20 +0000 (12:23 -0700)
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (48 commits)
  serial: 8250_pci: add support for Cronyx Omega PCI multiserial board.
  tty/serial: Fix break handling for PORT_TEGRA
  tty/serial: Add explicit PORT_TEGRA type
  n_tracerouter and n_tracesink ldisc additions.
  Intel PTI implementaiton of MIPI 1149.7.
  Kernel documentation for the PTI feature.
  export kernel call get_task_comm().
  tty: Remove to support serial for S5P6442
  pch_phub: Support new device ML7223
  8250_pci: Add support for the Digi/IBM PCIe 2-port Adapter
  ASoC: Update cx20442 for TTY API change
  pch_uart: Support new device ML7223 IOH
  parport: Use request_muxed_region for IT87 probe and lock
  tty/serial: add support for Xilinx PS UART
  n_gsm: Use print_hex_dump_bytes
  drivers/tty/moxa.c: Put correct tty value
  TTY: tty_io, annotate locking functions
  TTY: serial_core, remove superfluous set_task_state
  TTY: serial_core, remove invalid test
  Char: moxa, fix locking in moxa_write
  ...

Fix up trivial conflicts in drivers/bluetooth/hci_ldisc.c and
drivers/tty/serial/Makefile.

I did the hci_ldisc thing as an evil merge, cleaning things up.

103 files changed:
Documentation/pti/pti_intel_mid.txt [new file with mode: 0644]
drivers/bluetooth/hci_ldisc.c
drivers/input/serio/serport.c
drivers/isdn/gigaset/ser-gigaset.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/pch_phub.c
drivers/misc/pti.c [new file with mode: 0644]
drivers/misc/ti-st/st_core.c
drivers/net/caif/caif_serial.c
drivers/net/can/slcan.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/irda/irtty-sir.c
drivers/net/ppp_async.c
drivers/net/ppp_synctty.c
drivers/net/slip.c
drivers/net/wan/x25_asy.c
drivers/parport/parport_pc.c
drivers/tty/Kconfig
drivers/tty/Makefile
drivers/tty/amiserial.c
drivers/tty/cyclades.c
drivers/tty/ipwireless/Makefile
drivers/tty/moxa.c
drivers/tty/n_gsm.c
drivers/tty/n_hdlc.c
drivers/tty/n_r3964.c
drivers/tty/n_tracerouter.c [new file with mode: 0644]
drivers/tty/n_tracesink.c [new file with mode: 0644]
drivers/tty/n_tracesink.h [new file with mode: 0644]
drivers/tty/n_tty.c
drivers/tty/nozomi.c
drivers/tty/pty.c
drivers/tty/rocket.c
drivers/tty/serial/21285.c
drivers/tty/serial/8250.c
drivers/tty/serial/8250.h
drivers/tty/serial/8250_accent.c
drivers/tty/serial/8250_boca.c
drivers/tty/serial/8250_exar_st16c554.c
drivers/tty/serial/8250_fourport.c
drivers/tty/serial/8250_hub6.c
drivers/tty/serial/8250_mca.c
drivers/tty/serial/8250_pci.c
drivers/tty/serial/8250_pnp.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/altera_uart.c
drivers/tty/serial/amba-pl010.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/clps711x.c
drivers/tty/serial/cpm_uart/cpm_uart.h
drivers/tty/serial/cpm_uart/cpm_uart_core.c
drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h
drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c
drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h
drivers/tty/serial/ifx6x60.c
drivers/tty/serial/imx.c
drivers/tty/serial/msm_serial.c
drivers/tty/serial/msm_serial.h
drivers/tty/serial/msm_smd_tty.c
drivers/tty/serial/netx-serial.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/pxa.c
drivers/tty/serial/s3c2400.c
drivers/tty/serial/s3c2410.c
drivers/tty/serial/s3c2412.c
drivers/tty/serial/s3c2440.c
drivers/tty/serial/s3c24a0.c
drivers/tty/serial/s3c6400.c
drivers/tty/serial/s5pv210.c
drivers/tty/serial/sa1100.c
drivers/tty/serial/samsung.c
drivers/tty/serial/samsung.h
drivers/tty/serial/sb1250-duart.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_ks8695.c
drivers/tty/serial/serial_txx9.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/vt8500_serial.c
drivers/tty/serial/xilinx_uartps.c [new file with mode: 0644]
drivers/tty/synclink.c
drivers/tty/tty_buffer.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/tty_ldisc.c
drivers/tty/tty_mutex.c
drivers/tty/vt/keyboard.c
drivers/tty/vt/selection.c
drivers/tty/vt/vc_screen.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
fs/exec.c
include/linux/pti.h [new file with mode: 0644]
include/linux/serial_core.h
include/linux/serial_reg.h
include/linux/tty.h
include/linux/tty_ldisc.h
sound/soc/codecs/cx20442.c

diff --git a/Documentation/pti/pti_intel_mid.txt b/Documentation/pti/pti_intel_mid.txt
new file mode 100644 (file)
index 0000000..e7a5b6d
--- /dev/null
@@ -0,0 +1,99 @@
+The Intel MID PTI project is HW implemented in Intel Atom
+system-on-a-chip designs based on the Parallel Trace
+Interface for MIPI P1149.7 cJTAG standard.  The kernel solution
+for this platform involves the following files:
+
+./include/linux/pti.h
+./drivers/.../n_tracesink.h
+./drivers/.../n_tracerouter.c
+./drivers/.../n_tracesink.c
+./drivers/.../pti.c
+
+pti.c is the driver that enables various debugging features
+popular on platforms from certain mobile manufacturers.
+n_tracerouter.c and n_tracesink.c allow extra system information to
+be collected and routed to the pti driver, such as trace
+debugging data from a modem.  Although n_tracerouter
+and n_tracesink are a part of the complete PTI solution,
+these two line disciplines can work separately from
+pti.c and route any data stream from one /dev/tty node
+to another /dev/tty node via kernel-space.  This provides
+a stable, reliable connection that will not break unless
+the user-space application shuts down (plus avoids
+kernel->user->kernel context switch overheads of routing
+data).
+
+An example debugging usage for this driver system:
+   *Hook /dev/ttyPTI0 to syslogd.  Opening this port will also start
+    a console device to further capture debugging messages to PTI.
+   *Hook /dev/ttyPTI1 to modem debugging data to write to PTI HW.
+    This is where n_tracerouter and n_tracesink are used.
+   *Hook /dev/pti to a user-level debugging application for writing
+    to PTI HW.
+   *Use mipi_* Kernel Driver API in other device drivers for
+    debugging to PTI by first requesting a PTI write address via
+    mipi_request_masterchannel(1).
+
+Below is example pseudo-code on how a 'privileged' application
+can hook up n_tracerouter and n_tracesink to any tty on
+a system.  'Privileged' means the application has enough
+privileges to successfully manipulate the ldisc drivers
+but is not just blindly executing as 'root'. Keep in mind
+the use of ioctl(,TIOCSETD,) is not specific to the n_tracerouter
+and n_tracesink line discpline drivers but is a generic
+operation for a program to use a line discpline driver
+on a tty port other than the default n_tty.
+
+/////////// To hook up n_tracerouter and n_tracesink /////////
+
+// Note that n_tracerouter depends on n_tracesink.
+#include <errno.h>
+#define ONE_TTY "/dev/ttyOne"
+#define TWO_TTY "/dev/ttyTwo"
+
+// needed global to hand onto ldisc connection
+static int g_fd_source = -1;
+static int g_fd_sink  = -1;
+
+// these two vars used to grab LDISC values from loaded ldisc drivers
+// in OS.  Look at /proc/tty/ldiscs to get the right numbers from
+// the ldiscs loaded in the system.
+int source_ldisc_num, sink_ldisc_num = -1;
+int retval;
+
+g_fd_source = open(ONE_TTY, O_RDWR); // must be R/W
+g_fd_sink   = open(TWO_TTY, O_RDWR); // must be R/W
+
+if (g_fd_source <= 0) || (g_fd_sink <= 0) {
+   // doubt you'll want to use these exact error lines of code
+   printf("Error on open(). errno: %d\n",errno);
+   return errno;
+}
+
+retval = ioctl(g_fd_sink, TIOCSETD, &sink_ldisc_num);
+if (retval < 0) {
+   printf("Error on ioctl().  errno: %d\n", errno);
+   return errno;
+}
+
+retval = ioctl(g_fd_source, TIOCSETD, &source_ldisc_num);
+if (retval < 0) {
+   printf("Error on ioctl().  errno: %d\n", errno);
+   return errno;
+}
+
+/////////// To disconnect n_tracerouter and n_tracesink ////////
+
+// First make sure data through the ldiscs has stopped.
+
+// Second, disconnect ldiscs.  This provides a
+// little cleaner shutdown on tty stack.
+sink_ldisc_num = 0;
+source_ldisc_num = 0;
+ioctl(g_fd_uart, TIOCSETD, &sink_ldisc_num);
+ioctl(g_fd_gadget, TIOCSETD, &source_ldisc_num);
+
+// Three, program closes connection, and cleanup:
+close(g_fd_uart);
+close(g_fd_gadget);
+g_fd_uart = g_fd_gadget = NULL;
index 320f71803a2b397f75c77a930dac1bd8de8f496d..b3f01996318f04c0f432a38112226dbbeba0efcf 100644 (file)
@@ -355,26 +355,29 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
  *             flags        pointer to flags for data
  *             count        count of received data in bytes
  *     
- * Return Value:    None
+ * Return Value:    Number of bytes received
  */
-static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
+static unsigned int hci_uart_tty_receive(struct tty_struct *tty,
+               const u8 *data, char *flags, int count)
 {
-       int ret;
        struct hci_uart *hu = (void *)tty->disc_data;
+       int received;
 
        if (!hu || tty != hu->tty)
-               return;
+               return -ENODEV;
 
        if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
-               return;
+               return -EINVAL;
 
        spin_lock(&hu->rx_lock);
-       ret = hu->proto->recv(hu, (void *) data, count);
-       if (ret > 0)
-               hu->hdev->stat.byte_rx += count;
+       received = hu->proto->recv(hu, (void *) data, count);
+       if (received > 0)
+               hu->hdev->stat.byte_rx += received;
        spin_unlock(&hu->rx_lock);
 
        tty_unthrottle(tty);
+
+       return received;
 }
 
 static int hci_uart_register_dev(struct hci_uart *hu)
index 8755f5f3ad37c2218de60b96782c0863615a705e..f3698967edf6bdd0e8b7f4b19abdb19e335a2c3d 100644 (file)
@@ -120,17 +120,21 @@ static void serport_ldisc_close(struct tty_struct *tty)
  * 'interrupt' routine.
  */
 
-static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+static unsigned int serport_ldisc_receive(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        struct serport *serport = (struct serport*) tty->disc_data;
        unsigned long flags;
        unsigned int ch_flags;
+       int ret = 0;
        int i;
 
        spin_lock_irqsave(&serport->lock, flags);
 
-       if (!test_bit(SERPORT_ACTIVE, &serport->flags))
+       if (!test_bit(SERPORT_ACTIVE, &serport->flags)) {
+               ret = -EINVAL;
                goto out;
+       }
 
        for (i = 0; i < count; i++) {
                switch (fp[i]) {
@@ -152,6 +156,8 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
 
 out:
        spin_unlock_irqrestore(&serport->lock, flags);
+
+       return ret == 0 ? count : ret;
 }
 
 /*
index 86a5c4f7775eb5c95a23a35b1bf05a77a8ba9681..1d44d470897ca4660b6e4f4e05218293f3e9c398 100644 (file)
@@ -674,7 +674,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
  *     cflags  buffer containing error flags for received characters (ignored)
  *     count   number of received characters
  */
-static void
+static unsigned int
 gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
                    char *cflags, int count)
 {
@@ -683,12 +683,12 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
        struct inbuf_t *inbuf;
 
        if (!cs)
-               return;
+               return -ENODEV;
        inbuf = cs->inbuf;
        if (!inbuf) {
                dev_err(cs->dev, "%s: no inbuf\n", __func__);
                cs_put(cs);
-               return;
+               return -EINVAL;
        }
 
        tail = inbuf->tail;
@@ -725,6 +725,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
        gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
        gigaset_schedule_event(cs);
        cs_put(cs);
+
+       return count;
 }
 
 /*
index d80dcdee88f3e588dbf2e0903719b22267794fa6..4e349cd98bcfd6e70a27fdcf08d6dafbec6aa181 100644 (file)
@@ -144,6 +144,19 @@ config PHANTOM
          If you choose to build module, its name will be phantom. If unsure,
          say N here.
 
+config INTEL_MID_PTI
+       tristate "Parallel Trace Interface for MIPI P1149.7 cJTAG standard"
+       default n
+       help
+         The PTI (Parallel Trace Interface) driver directs
+         trace data routed from various parts in the system out
+         through an Intel Penwell PTI port and out of the mobile
+         device for analysis with a debugging tool (Lauterbach or Fido).
+
+         You should select this driver if the target kernel is meant for
+         an Intel Atom (non-netbook) mobile device containing a MIPI
+         P1149.7 standard implementation.
+
 config SGI_IOC4
        tristate "SGI IOC4 Base IO support"
        depends on PCI
@@ -459,7 +472,7 @@ config BMP085
          module will be called bmp085.
 
 config PCH_PHUB
-       tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213"
+       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"
        depends on PCI
        help
          This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -467,10 +480,12 @@ config PCH_PHUB
          processor. The Topcliff has MAC address and Option ROM data in SROM.
          This driver can access MAC address and Option ROM data in SROM.
 
-         This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
-         for IVI(In-Vehicle Infotainment) use.
-         ML7213 is companion chip for Intel Atom E6xx series.
-         ML7213 is completely compatible for Intel EG20T PCH.
+         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+         Output Hub), ML7213 and ML7223.
+         ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
+         for MP(Media Phone) use.
+         ML7213/ML7223 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7223 is completely compatible for Intel EG20T PCH.
 
          To compile this driver as a module, choose M here: the module will
          be called pch_phub.
index 848e8464faab8fe9d691f076ef68a948c5958d9a..5f03172cc0b5a5cd852f91135a5690aba8df7b0d 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_IBM_ASM)           += ibmasm/
 obj-$(CONFIG_AD525X_DPOT)      += ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)  += ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)  += ad525x_dpot-spi.o
+0bj-$(CONFIG_INTEL_MID_PTI)    += pti.o
 obj-$(CONFIG_ATMEL_PWM)                += atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)                += atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)      += atmel_tclib.o
index a19cb710a2462a7dc2f72ca06cd5aab9f7609aa4..5fe79df448380a620ad88282df81eb1cab5a860c 100644 (file)
 #define PHUB_TIMEOUT 0x05              /* Time out value for Status Register */
 #define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */
 #define PCH_PHUB_ROM_WRITE_DISABLE 0x00        /* Disabling for writing ROM */
-#define PCH_PHUB_MAC_START_ADDR 0x20C  /* MAC data area start address offset */
-#define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset
+#define PCH_PHUB_MAC_START_ADDR_EG20T 0x14  /* MAC data area start address
+                                              offset */
+#define PCH_PHUB_MAC_START_ADDR_ML7223 0x20C  /* MAC data area start address
+                                                offset */
+#define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset
                                              (Intel EG20T PCH)*/
 #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address
                                                offset(OKI SEMICONDUCTOR ML7213)
                                              */
+#define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address
+                                               offset(OKI SEMICONDUCTOR ML7223)
+                                             */
 
 /* MAX number of INT_REDUCE_CONTROL registers */
 #define MAX_NUM_INT_REDUCE_CONTROL_REG 128
 #define PCI_VENDOR_ID_ROHM                     0x10db
 #define PCI_DEVICE_ID_ROHM_ML7213_PHUB         0x801A
 
+/* Macros for ML7223 */
+#define PCI_DEVICE_ID_ROHM_ML7223_mPHUB        0x8012 /* for Bus-m */
+#define PCI_DEVICE_ID_ROHM_ML7223_nPHUB        0x8002 /* for Bus-n */
+
 /* SROM ACCESS Macro */
 #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
 
  * @clkcfg_reg:                                CLK CFG register val
  * @pch_phub_base_address:             Register base address
  * @pch_phub_extrom_base_address:      external rom base address
+ * @pch_mac_start_address:             MAC address area start address
+ * @pch_opt_rom_start_address:         Option ROM start address
+ * @ioh_type:                          Save IOH type
  */
 struct pch_phub_reg {
        u32 phub_id_reg;
@@ -117,6 +130,9 @@ struct pch_phub_reg {
        u32 clkcfg_reg;
        void __iomem *pch_phub_base_address;
        void __iomem *pch_phub_extrom_base_address;
+       u32 pch_mac_start_address;
+       u32 pch_opt_rom_start_address;
+       int ioh_type;
 };
 
 /* SROM SPEC for MAC address assignment offset */
@@ -319,7 +335,7 @@ static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
 {
        unsigned int mem_addr;
 
-       mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T +
+       mem_addr = chip->pch_mac_start_address +
                        pch_phub_mac_offset[offset_address];
 
        pch_phub_read_serial_rom(chip, mem_addr, data);
@@ -336,7 +352,7 @@ static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
        int retval;
        unsigned int mem_addr;
 
-       mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T +
+       mem_addr = chip->pch_mac_start_address +
                        pch_phub_mac_offset[offset_address];
 
        retval = pch_phub_write_serial_rom(chip, mem_addr, data);
@@ -384,6 +400,48 @@ static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
        return retval;
 }
 
+/* pch_phub_gbe_serial_rom_conf_mp - makes SerialROM header format configuration
+ * for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf_mp(struct pch_phub_reg *chip)
+{
+       int retval;
+       u32 offset_addr;
+
+       offset_addr = 0x200;
+       retval = pch_phub_write_serial_rom(chip, 0x03 + offset_addr, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x02 + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x01 + offset_addr, 0x40);
+       retval |= pch_phub_write_serial_rom(chip, 0x00 + offset_addr, 0x02);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x07 + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x06 + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x05 + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x04 + offset_addr, 0x80);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x0b + offset_addr, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x0a + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x09 + offset_addr, 0x40);
+       retval |= pch_phub_write_serial_rom(chip, 0x08 + offset_addr, 0x18);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x13 + offset_addr, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x12 + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x11 + offset_addr, 0x40);
+       retval |= pch_phub_write_serial_rom(chip, 0x10 + offset_addr, 0x19);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x1b + offset_addr, 0xbc);
+       retval |= pch_phub_write_serial_rom(chip, 0x1a + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x19 + offset_addr, 0x40);
+       retval |= pch_phub_write_serial_rom(chip, 0x18 + offset_addr, 0x3a);
+
+       retval |= pch_phub_write_serial_rom(chip, 0x1f + offset_addr, 0x01);
+       retval |= pch_phub_write_serial_rom(chip, 0x1e + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x1d + offset_addr, 0x00);
+       retval |= pch_phub_write_serial_rom(chip, 0x1c + offset_addr, 0x00);
+
+       return retval;
+}
+
 /**
  * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
  * @offset_address:    Gigabit Ethernet MAC address offset value.
@@ -406,7 +464,10 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
        int retval;
        int i;
 
-       retval = pch_phub_gbe_serial_rom_conf(chip);
+       if (chip->ioh_type == 1) /* EG20T */
+               retval = pch_phub_gbe_serial_rom_conf(chip);
+       else    /* ML7223 */
+               retval = pch_phub_gbe_serial_rom_conf_mp(chip);
        if (retval)
                return retval;
 
@@ -441,12 +502,16 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
        }
 
        /* Get Rom signature */
-       pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature);
+       pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
+                               (unsigned char *)&rom_signature);
        rom_signature &= 0xff;
-       pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp);
+       pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address + 1,
+                               (unsigned char *)&tmp);
        rom_signature |= (tmp & 0xff) << 8;
        if (rom_signature == 0xAA55) {
-               pch_phub_read_serial_rom(chip, 0x82, &rom_length);
+               pch_phub_read_serial_rom(chip,
+                                        chip->pch_opt_rom_start_address + 2,
+                                        &rom_length);
                orom_size = rom_length * 512;
                if (orom_size < off) {
                        addr_offset = 0;
@@ -458,8 +523,9 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
                }
 
                for (addr_offset = 0; addr_offset < count; addr_offset++) {
-                       pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off,
-                                                        &buf[addr_offset]);
+                       pch_phub_read_serial_rom(chip,
+                           chip->pch_opt_rom_start_address + addr_offset + off,
+                           &buf[addr_offset]);
                }
        } else {
                err = -ENODATA;
@@ -502,8 +568,9 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
                if (PCH_PHUB_OROM_SIZE < off + addr_offset)
                        goto return_ok;
 
-               ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off,
-                                                      buf[addr_offset]);
+               ret = pch_phub_write_serial_rom(chip,
+                           chip->pch_opt_rom_start_address + addr_offset + off,
+                           buf[addr_offset]);
                if (ret) {
                        err = ret;
                        goto return_err;
@@ -603,19 +670,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
        dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
                "in pch_phub_base_address variable is %p\n", __func__,
                chip->pch_phub_base_address);
-       chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
 
-       if (chip->pch_phub_extrom_base_address == 0) {
-               dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
-               ret = -ENOMEM;
-               goto err_pci_map;
+       if (id->driver_data != 3) {
+               chip->pch_phub_extrom_base_address =\
+                                                  pci_map_rom(pdev, &rom_size);
+               if (chip->pch_phub_extrom_base_address == 0) {
+                       dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__);
+                       ret = -ENOMEM;
+                       goto err_pci_map;
+               }
+               dev_dbg(&pdev->dev, "%s : "
+                       "pci_map_rom SUCCESS and value in "
+                       "pch_phub_extrom_base_address variable is %p\n",
+                       __func__, chip->pch_phub_extrom_base_address);
        }
-       dev_dbg(&pdev->dev, "%s : "
-               "pci_map_rom SUCCESS and value in "
-               "pch_phub_extrom_base_address variable is %p\n", __func__,
-               chip->pch_phub_extrom_base_address);
 
-       if (id->driver_data == 1) {
+       if (id->driver_data == 1) { /* EG20T PCH */
                retval = sysfs_create_file(&pdev->dev.kobj,
                                           &dev_attr_pch_mac.attr);
                if (retval)
@@ -642,7 +712,9 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
                iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
                /* set the interrupt delay value */
                iowrite32(0x25, chip->pch_phub_base_address + 0x44);
-       } else if (id->driver_data == 2) {
+               chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T;
+               chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;
+       } else if (id->driver_data == 2) { /* ML7213 IOH */
                retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
                if (retval)
                        goto err_sysfs_create;
@@ -653,7 +725,38 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
                 * Device8(USB OHCI #0/ USB EHCI #0):a
                 */
                iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14);
+               chip->pch_opt_rom_start_address =\
+                                                PCH_PHUB_ROM_START_ADDR_ML7213;
+       } else if (id->driver_data == 3) { /* ML7223 IOH Bus-m*/
+               /* set the prefech value
+                * Device8(GbE)
+                */
+               iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14);
+               chip->pch_opt_rom_start_address =\
+                                                PCH_PHUB_ROM_START_ADDR_ML7223;
+               chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
+       } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/
+               retval = sysfs_create_file(&pdev->dev.kobj,
+                                          &dev_attr_pch_mac.attr);
+               if (retval)
+                       goto err_sysfs_create;
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+               if (retval)
+                       goto exit_bin_attr;
+               /* set the prefech value
+                * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a
+                * Device4(SDIO #0,1):f
+                * Device6(SATA 2):f
+                */
+               iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14);
+               /* set the interrupt delay value */
+               iowrite32(0x25, chip->pch_phub_base_address + 0x140);
+               chip->pch_opt_rom_start_address =\
+                                                PCH_PHUB_ROM_START_ADDR_ML7223;
+               chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
        }
+
+       chip->ioh_type = id->driver_data;
        pci_set_drvdata(pdev, chip);
 
        return 0;
@@ -733,6 +836,8 @@ static int pch_phub_resume(struct pci_dev *pdev)
 static struct pci_device_id pch_phub_pcidev_id[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB),       1,  },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3,  },
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4,  },
        { }
 };
 MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
@@ -759,5 +864,5 @@ static void __exit pch_phub_pci_exit(void)
 module_init(pch_phub_pci_init);
 module_exit(pch_phub_pci_exit);
 
-MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB");
 MODULE_LICENSE("GPL");
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
new file mode 100644 (file)
index 0000000..bb6f925
--- /dev/null
@@ -0,0 +1,980 @@
+/*
+ *  pti.c - PTI driver for cJTAG data extration
+ *
+ *  Copyright (C) Intel 2010
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The PTI (Parallel Trace Interface) driver directs trace data routed from
+ * various parts in the system out through the Intel Penwell PTI port and
+ * out of the mobile device for analysis with a debugging tool
+ * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7,
+ * compact JTAG, standard.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <linux/miscdevice.h>
+#include <linux/pti.h>
+
+#define DRIVERNAME             "pti"
+#define PCINAME                        "pciPTI"
+#define TTYNAME                        "ttyPTI"
+#define CHARNAME               "pti"
+#define PTITTY_MINOR_START     0
+#define PTITTY_MINOR_NUM       2
+#define MAX_APP_IDS            16   /* 128 channel ids / u8 bit size */
+#define MAX_OS_IDS             16   /* 128 channel ids / u8 bit size */
+#define MAX_MODEM_IDS          16   /* 128 channel ids / u8 bit size */
+#define MODEM_BASE_ID          71   /* modem master ID address    */
+#define CONTROL_ID             72   /* control master ID address  */
+#define CONSOLE_ID             73   /* console master ID address  */
+#define OS_BASE_ID             74   /* base OS master ID address  */
+#define APP_BASE_ID            80   /* base App master ID address */
+#define CONTROL_FRAME_LEN      32   /* PTI control frame maximum size */
+#define USER_COPY_SIZE         8192 /* 8Kb buffer for user space copy */
+#define APERTURE_14            0x3800000 /* offset to first OS write addr */
+#define APERTURE_LEN           0x400000  /* address length */
+
+struct pti_tty {
+       struct pti_masterchannel *mc;
+};
+
+struct pti_dev {
+       struct tty_port port;
+       unsigned long pti_addr;
+       unsigned long aperture_base;
+       void __iomem *pti_ioaddr;
+       u8 ia_app[MAX_APP_IDS];
+       u8 ia_os[MAX_OS_IDS];
+       u8 ia_modem[MAX_MODEM_IDS];
+};
+
+/*
+ * This protects access to ia_app, ia_os, and ia_modem,
+ * which keeps track of channels allocated in
+ * an aperture write id.
+ */
+static DEFINE_MUTEX(alloclock);
+
+static struct pci_device_id pci_ids[] __devinitconst = {
+               {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
+               {0}
+};
+
+static struct tty_driver *pti_tty_driver;
+static struct pti_dev *drv_data;
+
+static unsigned int pti_console_channel;
+static unsigned int pti_control_channel;
+
+/**
+ *  pti_write_to_aperture()- The private write function to PTI HW.
+ *
+ *  @mc: The 'aperture'. It's part of a write address that holds
+ *       a master and channel ID.
+ *  @buf: Data being written to the HW that will ultimately be seen
+ *        in a debugging tool (Fido, Lauterbach).
+ *  @len: Size of buffer.
+ *
+ *  Since each aperture is specified by a unique
+ *  master/channel ID, no two processes will be writing
+ *  to the same aperture at the same time so no lock is required. The
+ *  PTI-Output agent will send these out in the order that they arrived, and
+ *  thus, it will intermix these messages. The debug tool can then later
+ *  regroup the appropriate message segments together reconstituting each
+ *  message.
+ */
+static void pti_write_to_aperture(struct pti_masterchannel *mc,
+                                 u8 *buf,
+                                 int len)
+{
+       int dwordcnt;
+       int final;
+       int i;
+       u32 ptiword;
+       u32 __iomem *aperture;
+       u8 *p = buf;
+
+       /*
+        * calculate the aperture offset from the base using the master and
+        * channel id's.
+        */
+       aperture = drv_data->pti_ioaddr + (mc->master << 15)
+               + (mc->channel << 8);
+
+       dwordcnt = len >> 2;
+       final = len - (dwordcnt << 2);      /* final = trailing bytes    */
+       if (final == 0 && dwordcnt != 0) {  /* always need a final dword */
+               final += 4;
+               dwordcnt--;
+       }
+
+       for (i = 0; i < dwordcnt; i++) {
+               ptiword = be32_to_cpu(*(u32 *)p);
+               p += 4;
+               iowrite32(ptiword, aperture);
+       }
+
+       aperture += PTI_LASTDWORD_DTS;  /* adding DTS signals that is EOM */
+
+       ptiword = 0;
+       for (i = 0; i < final; i++)
+               ptiword |= *p++ << (24-(8*i));
+
+       iowrite32(ptiword, aperture);
+       return;
+}
+
+/**
+ *  pti_control_frame_built_and_sent()- control frame build and send function.
+ *
+ *  @mc: The master / channel structure on which the function
+ *       built a control frame.
+ *
+ *  To be able to post process the PTI contents on host side, a control frame
+ *  is added before sending any PTI content. So the host side knows on
+ *  each PTI frame the name of the thread using a dedicated master / channel.
+ *  The thread name is retrieved from the 'current' global variable.
+ *  This function builds this frame and sends it to a master ID CONTROL_ID.
+ *  The overhead is only 32 bytes since the driver only writes to HW
+ *  in 32 byte chunks.
+ */
+
+static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc)
+{
+       struct pti_masterchannel mccontrol = {.master = CONTROL_ID,
+                                             .channel = 0};
+       const char *control_format = "%3d %3d %s";
+       u8 control_frame[CONTROL_FRAME_LEN];
+
+       /*
+        * Since we access the comm member in current's task_struct,
+        * we only need to be as large as what 'comm' in that
+        * structure is.
+        */
+       char comm[TASK_COMM_LEN];
+
+       if (!in_interrupt())
+               get_task_comm(comm, current);
+       else
+               strncpy(comm, "Interrupt", TASK_COMM_LEN);
+
+       /* Absolutely ensure our buffer is zero terminated. */
+       comm[TASK_COMM_LEN-1] = 0;
+
+       mccontrol.channel = pti_control_channel;
+       pti_control_channel = (pti_control_channel + 1) & 0x7f;
+
+       snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
+               mc->channel, comm);
+       pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
+}
+
+/**
+ *  pti_write_full_frame_to_aperture()- high level function to
+ *                                     write to PTI.
+ *
+ *  @mc:  The 'aperture'. It's part of a write address that holds
+ *        a master and channel ID.
+ *  @buf: Data being written to the HW that will ultimately be seen
+ *        in a debugging tool (Fido, Lauterbach).
+ *  @len: Size of buffer.
+ *
+ *  All threads sending data (either console, user space application, ...)
+ *  are calling the high level function to write to PTI meaning that it is
+ *  possible to add a control frame before sending the content.
+ */
+static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
+                                               const unsigned char *buf,
+                                               int len)
+{
+       pti_control_frame_built_and_sent(mc);
+       pti_write_to_aperture(mc, (u8 *)buf, len);
+}
+
+/**
+ * get_id()- Allocate a master and channel ID.
+ *
+ * @id_array: an array of bits representing what channel
+ *            id's are allocated for writing.
+ * @max_ids:  The max amount of available write IDs to use.
+ * @base_id:  The starting SW channel ID, based on the Intel
+ *            PTI arch.
+ *
+ * Returns:
+ *     pti_masterchannel struct with master, channel ID address
+ *     0 for error
+ *
+ * Each bit in the arrays ia_app and ia_os correspond to a master and
+ * channel id. The bit is one if the id is taken and 0 if free. For
+ * every master there are 128 channel id's.
+ */
+static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
+{
+       struct pti_masterchannel *mc;
+       int i, j, mask;
+
+       mc = kmalloc(sizeof(struct pti_masterchannel), GFP_KERNEL);
+       if (mc == NULL)
+               return NULL;
+
+       /* look for a byte with a free bit */
+       for (i = 0; i < max_ids; i++)
+               if (id_array[i] != 0xff)
+                       break;
+       if (i == max_ids) {
+               kfree(mc);
+               return NULL;
+       }
+       /* find the bit in the 128 possible channel opportunities */
+       mask = 0x80;
+       for (j = 0; j < 8; j++) {
+               if ((id_array[i] & mask) == 0)
+                       break;
+               mask >>= 1;
+       }
+
+       /* grab it */
+       id_array[i] |= mask;
+       mc->master  = base_id;
+       mc->channel = ((i & 0xf)<<3) + j;
+       /* write new master Id / channel Id allocation to channel control */
+       pti_control_frame_built_and_sent(mc);
+       return mc;
+}
+
+/*
+ * The following three functions:
+ * pti_request_mastercahannel(), mipi_release_masterchannel()
+ * and pti_writedata() are an API for other kernel drivers to
+ * access PTI.
+ */
+
+/**
+ * pti_request_masterchannel()- Kernel API function used to allocate
+ *                             a master, channel ID address
+ *                             to write to PTI HW.
+ *
+ * @type: 0- request Application  master, channel aperture ID write address.
+ *        1- request OS master, channel aperture ID write
+ *           address.
+ *        2- request Modem master, channel aperture ID
+ *           write address.
+ *        Other values, error.
+ *
+ * Returns:
+ *     pti_masterchannel struct
+ *     0 for error
+ */
+struct pti_masterchannel *pti_request_masterchannel(u8 type)
+{
+       struct pti_masterchannel *mc;
+
+       mutex_lock(&alloclock);
+
+       switch (type) {
+
+       case 0:
+               mc = get_id(drv_data->ia_app, MAX_APP_IDS, APP_BASE_ID);
+               break;
+
+       case 1:
+               mc = get_id(drv_data->ia_os, MAX_OS_IDS, OS_BASE_ID);
+               break;
+
+       case 2:
+               mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS, MODEM_BASE_ID);
+               break;
+       default:
+               mc = NULL;
+       }
+
+       mutex_unlock(&alloclock);
+       return mc;
+}
+EXPORT_SYMBOL_GPL(pti_request_masterchannel);
+
+/**
+ * pti_release_masterchannel()- Kernel API function used to release
+ *                             a master, channel ID address
+ *                             used to write to PTI HW.
+ *
+ * @mc: master, channel apeture ID address to be released.
+ */
+void pti_release_masterchannel(struct pti_masterchannel *mc)
+{
+       u8 master, channel, i;
+
+       mutex_lock(&alloclock);
+
+       if (mc) {
+               master = mc->master;
+               channel = mc->channel;
+
+               if (master == APP_BASE_ID) {
+                       i = channel >> 3;
+                       drv_data->ia_app[i] &=  ~(0x80>>(channel & 0x7));
+               } else if (master == OS_BASE_ID) {
+                       i = channel >> 3;
+                       drv_data->ia_os[i] &= ~(0x80>>(channel & 0x7));
+               } else {
+                       i = channel >> 3;
+                       drv_data->ia_modem[i] &= ~(0x80>>(channel & 0x7));
+               }
+
+               kfree(mc);
+       }
+
+       mutex_unlock(&alloclock);
+}
+EXPORT_SYMBOL_GPL(pti_release_masterchannel);
+
+/**
+ * pti_writedata()- Kernel API function used to write trace
+ *                  debugging data to PTI HW.
+ *
+ * @mc:    Master, channel aperture ID address to write to.
+ *         Null value will return with no write occurring.
+ * @buf:   Trace debuging data to write to the PTI HW.
+ *         Null value will return with no write occurring.
+ * @count: Size of buf. Value of 0 or a negative number will
+ *         return with no write occuring.
+ */
+void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count)
+{
+       /*
+        * since this function is exported, this is treated like an
+        * API function, thus, all parameters should
+        * be checked for validity.
+        */
+       if ((mc != NULL) && (buf != NULL) && (count > 0))
+               pti_write_to_aperture(mc, buf, count);
+       return;
+}
+EXPORT_SYMBOL_GPL(pti_writedata);
+
+/**
+ * pti_pci_remove()- Driver exit method to remove PTI from
+ *                PCI bus.
+ * @pdev: variable containing pci info of PTI.
+ */
+static void __devexit pti_pci_remove(struct pci_dev *pdev)
+{
+       struct pti_dev *drv_data;
+
+       drv_data = pci_get_drvdata(pdev);
+       if (drv_data != NULL) {
+               pci_iounmap(pdev, drv_data->pti_ioaddr);
+               pci_set_drvdata(pdev, NULL);
+               kfree(drv_data);
+               pci_release_region(pdev, 1);
+               pci_disable_device(pdev);
+       }
+}
+
+/*
+ * for the tty_driver_*() basic function descriptions, see tty_driver.h.
+ * Specific header comments made for PTI-related specifics.
+ */
+
+/**
+ * pti_tty_driver_open()- Open an Application master, channel aperture
+ * ID to the PTI device via tty device.
+ *
+ * @tty: tty interface.
+ * @filp: filp interface pased to tty_port_open() call.
+ *
+ * Returns:
+ *     int, 0 for success
+ *     otherwise, fail value
+ *
+ * The main purpose of using the tty device interface is for
+ * each tty port to have a unique PTI write aperture.  In an
+ * example use case, ttyPTI0 gets syslogd and an APP aperture
+ * ID and ttyPTI1 is where the n_tracesink ldisc hooks to route
+ * modem messages into PTI.  Modem trace data does not have to
+ * go to ttyPTI1, but ttyPTI0 and ttyPTI1 do need to be distinct
+ * master IDs.  These messages go through the PTI HW and out of
+ * the handheld platform and to the Fido/Lauterbach device.
+ */
+static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp)
+{
+       /*
+        * we actually want to allocate a new channel per open, per
+        * system arch.  HW gives more than plenty channels for a single
+        * system task to have its own channel to write trace data. This
+        * also removes a locking requirement for the actual write
+        * procedure.
+        */
+       return tty_port_open(&drv_data->port, tty, filp);
+}
+
+/**
+ * pti_tty_driver_close()- close tty device and release Application
+ * master, channel aperture ID to the PTI device via tty device.
+ *
+ * @tty: tty interface.
+ * @filp: filp interface pased to tty_port_close() call.
+ *
+ * The main purpose of using the tty device interface is to route
+ * syslog daemon messages to the PTI HW and out of the handheld platform
+ * and to the Fido/Lauterbach device.
+ */
+static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
+{
+       tty_port_close(&drv_data->port, tty, filp);
+}
+
+/**
+ * pti_tty_intstall()- Used to set up specific master-channels
+ *                    to tty ports for organizational purposes when
+ *                    tracing viewed from debuging tools.
+ *
+ * @driver: tty driver information.
+ * @tty: tty struct containing pti information.
+ *
+ * Returns:
+ *     0 for success
+ *     otherwise, error
+ */
+static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+       int idx = tty->index;
+       struct pti_tty *pti_tty_data;
+       int ret = tty_init_termios(tty);
+
+       if (ret == 0) {
+               tty_driver_kref_get(driver);
+               tty->count++;
+               driver->ttys[idx] = tty;
+
+               pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL);
+               if (pti_tty_data == NULL)
+                       return -ENOMEM;
+
+               if (idx == PTITTY_MINOR_START)
+                       pti_tty_data->mc = pti_request_masterchannel(0);
+               else
+                       pti_tty_data->mc = pti_request_masterchannel(2);
+
+               if (pti_tty_data->mc == NULL)
+                       return -ENXIO;
+               tty->driver_data = pti_tty_data;
+       }
+
+       return ret;
+}
+
+/**
+ * pti_tty_cleanup()- Used to de-allocate master-channel resources
+ *                   tied to tty's of this driver.
+ *
+ * @tty: tty struct containing pti information.
+ */
+static void pti_tty_cleanup(struct tty_struct *tty)
+{
+       struct pti_tty *pti_tty_data = tty->driver_data;
+       if (pti_tty_data == NULL)
+               return;
+       pti_release_masterchannel(pti_tty_data->mc);
+       kfree(tty->driver_data);
+       tty->driver_data = NULL;
+}
+
+/**
+ * pti_tty_driver_write()-  Write trace debugging data through the char
+ * interface to the PTI HW.  Part of the misc device implementation.
+ *
+ * @filp: Contains private data which is used to obtain
+ *        master, channel write ID.
+ * @data: trace data to be written.
+ * @len:  # of byte to write.
+ *
+ * Returns:
+ *     int, # of bytes written
+ *     otherwise, error
+ */
+static int pti_tty_driver_write(struct tty_struct *tty,
+       const unsigned char *buf, int len)
+{
+       struct pti_tty *pti_tty_data = tty->driver_data;
+       if ((pti_tty_data != NULL) && (pti_tty_data->mc != NULL)) {
+               pti_write_to_aperture(pti_tty_data->mc, (u8 *)buf, len);
+               return len;
+       }
+       /*
+        * we can't write to the pti hardware if the private driver_data
+        * and the mc address is not there.
+        */
+       else
+               return -EFAULT;
+}
+
+/**
+ * pti_tty_write_room()- Always returns 2048.
+ *
+ * @tty: contains tty info of the pti driver.
+ */
+static int pti_tty_write_room(struct tty_struct *tty)
+{
+       return 2048;
+}
+
+/**
+ * pti_char_open()- Open an Application master, channel aperture
+ * ID to the PTI device. Part of the misc device implementation.
+ *
+ * @inode: not used.
+ * @filp:  Output- will have a masterchannel struct set containing
+ *                 the allocated application PTI aperture write address.
+ *
+ * Returns:
+ *     int, 0 for success
+ *     otherwise, a fail value
+ */
+static int pti_char_open(struct inode *inode, struct file *filp)
+{
+       struct pti_masterchannel *mc;
+
+       /*
+        * We really do want to fail immediately if
+        * pti_request_masterchannel() fails,
+        * before assigning the value to filp->private_data.
+        * Slightly easier to debug if this driver needs debugging.
+        */
+       mc = pti_request_masterchannel(0);
+       if (mc == NULL)
+               return -ENOMEM;
+       filp->private_data = mc;
+       return 0;
+}
+
+/**
+ * pti_char_release()-  Close a char channel to the PTI device. Part
+ * of the misc device implementation.
+ *
+ * @inode: Not used in this implementaiton.
+ * @filp:  Contains private_data that contains the master, channel
+ *         ID to be released by the PTI device.
+ *
+ * Returns:
+ *     always 0
+ */
+static int pti_char_release(struct inode *inode, struct file *filp)
+{
+       pti_release_masterchannel(filp->private_data);
+       kfree(filp->private_data);
+       return 0;
+}
+
+/**
+ * pti_char_write()-  Write trace debugging data through the char
+ * interface to the PTI HW.  Part of the misc device implementation.
+ *
+ * @filp:  Contains private data which is used to obtain
+ *         master, channel write ID.
+ * @data:  trace data to be written.
+ * @len:   # of byte to write.
+ * @ppose: Not used in this function implementation.
+ *
+ * Returns:
+ *     int, # of bytes written
+ *     otherwise, error value
+ *
+ * Notes: From side discussions with Alan Cox and experimenting
+ * with PTI debug HW like Nokia's Fido box and Lauterbach
+ * devices, 8192 byte write buffer used by USER_COPY_SIZE was
+ * deemed an appropriate size for this type of usage with
+ * debugging HW.
+ */
+static ssize_t pti_char_write(struct file *filp, const char __user *data,
+                             size_t len, loff_t *ppose)
+{
+       struct pti_masterchannel *mc;
+       void *kbuf;
+       const char __user *tmp;
+       size_t size = USER_COPY_SIZE;
+       size_t n = 0;
+
+       tmp = data;
+       mc = filp->private_data;
+
+       kbuf = kmalloc(size, GFP_KERNEL);
+       if (kbuf == NULL)  {
+               pr_err("%s(%d): buf allocation failed\n",
+                       __func__, __LINE__);
+               return -ENOMEM;
+       }
+
+       do {
+               if (len - n > USER_COPY_SIZE)
+                       size = USER_COPY_SIZE;
+               else
+                       size = len - n;
+
+               if (copy_from_user(kbuf, tmp, size)) {
+                       kfree(kbuf);
+                       return n ? n : -EFAULT;
+               }
+
+               pti_write_to_aperture(mc, kbuf, size);
+               n  += size;
+               tmp += size;
+
+       } while (len > n);
+
+       kfree(kbuf);
+       return len;
+}
+
+static const struct tty_operations pti_tty_driver_ops = {
+       .open           = pti_tty_driver_open,
+       .close          = pti_tty_driver_close,
+       .write          = pti_tty_driver_write,
+       .write_room     = pti_tty_write_room,
+       .install        = pti_tty_install,
+       .cleanup        = pti_tty_cleanup
+};
+
+static const struct file_operations pti_char_driver_ops = {
+       .owner          = THIS_MODULE,
+       .write          = pti_char_write,
+       .open           = pti_char_open,
+       .release        = pti_char_release,
+};
+
+static struct miscdevice pti_char_driver = {
+       .minor          = MISC_DYNAMIC_MINOR,
+       .name           = CHARNAME,
+       .fops           = &pti_char_driver_ops
+};
+
+/**
+ * pti_console_write()-  Write to the console that has been acquired.
+ *
+ * @c:   Not used in this implementaiton.
+ * @buf: Data to be written.
+ * @len: Length of buf.
+ */
+static void pti_console_write(struct console *c, const char *buf, unsigned len)
+{
+       static struct pti_masterchannel mc = {.master  = CONSOLE_ID,
+                                             .channel = 0};
+
+       mc.channel = pti_console_channel;
+       pti_console_channel = (pti_console_channel + 1) & 0x7f;
+
+       pti_write_full_frame_to_aperture(&mc, buf, len);
+}
+
+/**
+ * pti_console_device()-  Return the driver tty structure and set the
+ *                       associated index implementation.
+ *
+ * @c:     Console device of the driver.
+ * @index: index associated with c.
+ *
+ * Returns:
+ *     always value of pti_tty_driver structure when this function
+ *     is called.
+ */
+static struct tty_driver *pti_console_device(struct console *c, int *index)
+{
+       *index = c->index;
+       return pti_tty_driver;
+}
+
+/**
+ * pti_console_setup()-  Initialize console variables used by the driver.
+ *
+ * @c:     Not used.
+ * @opts:  Not used.
+ *
+ * Returns:
+ *     always 0.
+ */
+static int pti_console_setup(struct console *c, char *opts)
+{
+       pti_console_channel = 0;
+       pti_control_channel = 0;
+       return 0;
+}
+
+/*
+ * pti_console struct, used to capture OS printk()'s and shift
+ * out to the PTI device for debugging.  This cannot be
+ * enabled upon boot because of the possibility of eating
+ * any serial console printk's (race condition discovered).
+ * The console should be enabled upon when the tty port is
+ * used for the first time.  Since the primary purpose for
+ * the tty port is to hook up syslog to it, the tty port
+ * will be open for a really long time.
+ */
+static struct console pti_console = {
+       .name           = TTYNAME,
+       .write          = pti_console_write,
+       .device         = pti_console_device,
+       .setup          = pti_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = 0,
+};
+
+/**
+ * pti_port_activate()- Used to start/initialize any items upon
+ * first opening of tty_port().
+ *
+ * @port- The tty port number of the PTI device.
+ * @tty-  The tty struct associated with this device.
+ *
+ * Returns:
+ *     always returns 0
+ *
+ * Notes: The primary purpose of the PTI tty port 0 is to hook
+ * the syslog daemon to it; thus this port will be open for a
+ * very long time.
+ */
+static int pti_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+       if (port->tty->index == PTITTY_MINOR_START)
+               console_start(&pti_console);
+       return 0;
+}
+
+/**
+ * pti_port_shutdown()- Used to stop/shutdown any items upon the
+ * last tty port close.
+ *
+ * @port- The tty port number of the PTI device.
+ *
+ * Notes: The primary purpose of the PTI tty port 0 is to hook
+ * the syslog daemon to it; thus this port will be open for a
+ * very long time.
+ */
+static void pti_port_shutdown(struct tty_port *port)
+{
+       if (port->tty->index == PTITTY_MINOR_START)
+               console_stop(&pti_console);
+}
+
+static const struct tty_port_operations tty_port_ops = {
+       .activate = pti_port_activate,
+       .shutdown = pti_port_shutdown,
+};
+
+/*
+ * Note the _probe() call sets everything up and ties the char and tty
+ * to successfully detecting the PTI device on the pci bus.
+ */
+
+/**
+ * pti_pci_probe()- Used to detect pti on the pci bus and set
+ *                 things up in the driver.
+ *
+ * @pdev- pci_dev struct values for pti.
+ * @ent-  pci_device_id struct for pti driver.
+ *
+ * Returns:
+ *     0 for success
+ *     otherwise, error
+ */
+static int __devinit pti_pci_probe(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
+{
+       int retval = -EINVAL;
+       int pci_bar = 1;
+
+       dev_dbg(&pdev->dev, "%s %s(%d): PTI PCI ID %04x:%04x\n", __FILE__,
+                       __func__, __LINE__, pdev->vendor, pdev->device);
+
+       retval = misc_register(&pti_char_driver);
+       if (retval) {
+               pr_err("%s(%d): CHAR registration failed of pti driver\n",
+                       __func__, __LINE__);
+               pr_err("%s(%d): Error value returned: %d\n",
+                       __func__, __LINE__, retval);
+               return retval;
+       }
+
+       retval = pci_enable_device(pdev);
+       if (retval != 0) {
+               dev_err(&pdev->dev,
+                       "%s: pci_enable_device() returned error %d\n",
+                       __func__, retval);
+               return retval;
+       }
+
+       drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
+
+       if (drv_data == NULL) {
+               retval = -ENOMEM;
+               dev_err(&pdev->dev,
+                       "%s(%d): kmalloc() returned NULL memory.\n",
+                       __func__, __LINE__);
+               return retval;
+       }
+       drv_data->pti_addr = pci_resource_start(pdev, pci_bar);
+
+       retval = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
+       if (retval != 0) {
+               dev_err(&pdev->dev,
+                       "%s(%d): pci_request_region() returned error %d\n",
+                       __func__, __LINE__, retval);
+               kfree(drv_data);
+               return retval;
+       }
+       drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
+       drv_data->pti_ioaddr =
+               ioremap_nocache((u32)drv_data->aperture_base,
+               APERTURE_LEN);
+       if (!drv_data->pti_ioaddr) {
+               pci_release_region(pdev, pci_bar);
+               retval = -ENOMEM;
+               kfree(drv_data);
+               return retval;
+       }
+
+       pci_set_drvdata(pdev, drv_data);
+
+       tty_port_init(&drv_data->port);
+       drv_data->port.ops = &tty_port_ops;
+
+       tty_register_device(pti_tty_driver, 0, &pdev->dev);
+       tty_register_device(pti_tty_driver, 1, &pdev->dev);
+
+       register_console(&pti_console);
+
+       return retval;
+}
+
+static struct pci_driver pti_pci_driver = {
+       .name           = PCINAME,
+       .id_table       = pci_ids,
+       .probe          = pti_pci_probe,
+       .remove         = pti_pci_remove,
+};
+
+/**
+ *
+ * pti_init()- Overall entry/init call to the pti driver.
+ *             It starts the registration process with the kernel.
+ *
+ * Returns:
+ *     int __init, 0 for success
+ *     otherwise value is an error
+ *
+ */
+static int __init pti_init(void)
+{
+       int retval = -EINVAL;
+
+       /* First register module as tty device */
+
+       pti_tty_driver = alloc_tty_driver(1);
+       if (pti_tty_driver == NULL) {
+               pr_err("%s(%d): Memory allocation failed for ptiTTY driver\n",
+                       __func__, __LINE__);
+               return -ENOMEM;
+       }
+
+       pti_tty_driver->owner                   = THIS_MODULE;
+       pti_tty_driver->magic                   = TTY_DRIVER_MAGIC;
+       pti_tty_driver->driver_name             = DRIVERNAME;
+       pti_tty_driver->name                    = TTYNAME;
+       pti_tty_driver->major                   = 0;
+       pti_tty_driver->minor_start             = PTITTY_MINOR_START;
+       pti_tty_driver->minor_num               = PTITTY_MINOR_NUM;
+       pti_tty_driver->num                     = PTITTY_MINOR_NUM;
+       pti_tty_driver->type                    = TTY_DRIVER_TYPE_SYSTEM;
+       pti_tty_driver->subtype                 = SYSTEM_TYPE_SYSCONS;
+       pti_tty_driver->flags                   = TTY_DRIVER_REAL_RAW |
+                                                 TTY_DRIVER_DYNAMIC_DEV;
+       pti_tty_driver->init_termios            = tty_std_termios;
+
+       tty_set_operations(pti_tty_driver, &pti_tty_driver_ops);
+
+       retval = tty_register_driver(pti_tty_driver);
+       if (retval) {
+               pr_err("%s(%d): TTY registration failed of pti driver\n",
+                       __func__, __LINE__);
+               pr_err("%s(%d): Error value returned: %d\n",
+                       __func__, __LINE__, retval);
+
+               pti_tty_driver = NULL;
+               return retval;
+       }
+
+       retval = pci_register_driver(&pti_pci_driver);
+
+       if (retval) {
+               pr_err("%s(%d): PCI registration failed of pti driver\n",
+                       __func__, __LINE__);
+               pr_err("%s(%d): Error value returned: %d\n",
+                       __func__, __LINE__, retval);
+
+               tty_unregister_driver(pti_tty_driver);
+               pr_err("%s(%d): Unregistering TTY part of pti driver\n",
+                       __func__, __LINE__);
+               pti_tty_driver = NULL;
+               return retval;
+       }
+
+       return retval;
+}
+
+/**
+ * pti_exit()- Unregisters this module as a tty and pci driver.
+ */
+static void __exit pti_exit(void)
+{
+       int retval;
+
+       tty_unregister_device(pti_tty_driver, 0);
+       tty_unregister_device(pti_tty_driver, 1);
+
+       retval = tty_unregister_driver(pti_tty_driver);
+       if (retval) {
+               pr_err("%s(%d): TTY unregistration failed of pti driver\n",
+                       __func__, __LINE__);
+               pr_err("%s(%d): Error value returned: %d\n",
+                       __func__, __LINE__, retval);
+       }
+
+       pci_unregister_driver(&pti_pci_driver);
+
+       retval = misc_deregister(&pti_char_driver);
+       if (retval) {
+               pr_err("%s(%d): CHAR unregistration failed of pti driver\n",
+                       __func__, __LINE__);
+               pr_err("%s(%d): Error value returned: %d\n",
+                       __func__, __LINE__, retval);
+       }
+
+       unregister_console(&pti_console);
+       return;
+}
+
+module_init(pti_init);
+module_exit(pti_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ken Mills, Jay Freyensee");
+MODULE_DESCRIPTION("PTI Driver");
+
index f91f82eabda72a311602a8979ab835e0d938ffd6..1a05fe08e2cb7dc4462b76d360115e725321fc7e 100644 (file)
@@ -747,8 +747,8 @@ static void st_tty_close(struct tty_struct *tty)
        pr_debug("%s: done ", __func__);
 }
 
-static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,
-                          char *tty_flags, int count)
+static unsigned int st_tty_receive(struct tty_struct *tty,
+               const unsigned char *data, char *tty_flags, int count)
 {
 #ifdef VERBOSE
        print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
@@ -761,6 +761,8 @@ static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,
         */
        st_recv(tty->disc_data, data, count);
        pr_debug("done %s", __func__);
+
+       return count;
 }
 
 /* wake-up function called in from the TTY layer
index 3df0c0f8b8bf93ca98a8829e7c09162a70f384c4..73c7e03617ecc52313af4335f8b245d46b7eecb4 100644 (file)
@@ -167,8 +167,8 @@ static inline void debugfs_tx(struct ser_device *ser, const u8 *data, int size)
 
 #endif
 
-static void ldisc_receive(struct tty_struct *tty, const u8 *data,
-                       char *flags, int count)
+static unsigned int ldisc_receive(struct tty_struct *tty,
+               const u8 *data, char *flags, int count)
 {
        struct sk_buff *skb = NULL;
        struct ser_device *ser;
@@ -215,6 +215,8 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data,
        } else
                ++ser->dev->stats.rx_dropped;
        update_tty_status(ser);
+
+       return count;
 }
 
 static int handle_tx(struct ser_device *ser)
index 1b49df6b2470874b0cb76cf45214f247c6d3bf29..75622d54581f15f87ea3ca4b893e7f37cbf34e9e 100644 (file)
@@ -425,16 +425,17 @@ static void slc_setup(struct net_device *dev)
  * in parallel
  */
 
-static void slcan_receive_buf(struct tty_struct *tty,
+static unsigned int slcan_receive_buf(struct tty_struct *tty,
                              const unsigned char *cp, char *fp, int count)
 {
        struct slcan *sl = (struct slcan *) tty->disc_data;
+       int bytes = count;
 
        if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
-               return;
+               return -ENODEV;
 
        /* Read the characters out of the buffer */
-       while (count--) {
+       while (bytes--) {
                if (fp && *fp++) {
                        if (!test_and_set_bit(SLF_ERROR, &sl->flags))
                                sl->dev->stats.rx_errors++;
@@ -443,6 +444,8 @@ static void slcan_receive_buf(struct tty_struct *tty,
                }
                slcan_unesc(sl, *cp++);
        }
+
+       return count;
 }
 
 /************************************
index 3e5d0b6b6516133039192fa5dfd1fdf88660d81b..992089639ea4824404f42d53e5362eab2c2fb586 100644 (file)
@@ -456,7 +456,7 @@ out:
  * a block of 6pack data has been received, which can now be decapsulated
  * and sent on to some IP layer for further processing.
  */
-static void sixpack_receive_buf(struct tty_struct *tty,
+static unsigned int sixpack_receive_buf(struct tty_struct *tty,
        const unsigned char *cp, char *fp, int count)
 {
        struct sixpack *sp;
@@ -464,11 +464,11 @@ static void sixpack_receive_buf(struct tty_struct *tty,
        int count1;
 
        if (!count)
-               return;
+               return 0;
 
        sp = sp_get(tty);
        if (!sp)
-               return;
+               return -ENODEV;
 
        memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf));
 
@@ -487,6 +487,8 @@ static void sixpack_receive_buf(struct tty_struct *tty,
 
        sp_put(sp);
        tty_unthrottle(tty);
+
+       return count1;
 }
 
 /*
index 4c628393c8b157cbc09de52d902b5fa8c3d370a3..0e4f23531140c8ca6f938447f145351c39b93a37 100644 (file)
@@ -923,13 +923,14 @@ static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,
  * a block of data has been received, which can now be decapsulated
  * and sent on to the AX.25 layer for further processing.
  */
-static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-       char *fp, int count)
+static unsigned int mkiss_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        struct mkiss *ax = mkiss_get(tty);
+       int bytes = count;
 
        if (!ax)
-               return;
+               return -ENODEV;
 
        /*
         * Argh! mtu change time! - costs us the packet part received
@@ -939,7 +940,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                ax_changedmtu(ax);
 
        /* Read the characters out of the buffer */
-       while (count--) {
+       while (bytes--) {
                if (fp != NULL && *fp++) {
                        if (!test_and_set_bit(AXF_ERROR, &ax->flags))
                                ax->dev->stats.rx_errors++;
@@ -952,6 +953,8 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 
        mkiss_put(ax);
        tty_unthrottle(tty);
+
+       return count;
 }
 
 /*
index 3352b2443e58eb1ca0a45856c628850c08092be6..035861d8acb157f47d080b074c1de9a73a2988e1 100644 (file)
@@ -216,23 +216,23 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t
  * usbserial:  urb-complete-interrupt / softint
  */
 
-static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                             char *fp, int count) 
+static unsigned int irtty_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        struct sir_dev *dev;
        struct sirtty_cb *priv = tty->disc_data;
        int     i;
 
-       IRDA_ASSERT(priv != NULL, return;);
-       IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
+       IRDA_ASSERT(priv != NULL, return -ENODEV;);
+       IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EINVAL;);
 
        if (unlikely(count==0))         /* yes, this happens */
-               return;
+               return 0;
 
        dev = priv->dev;
        if (!dev) {
                IRDA_WARNING("%s(), not ready yet!\n", __func__);
-               return;
+               return -ENODEV;
        }
 
        for (i = 0; i < count; i++) {
@@ -242,11 +242,13 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                if (fp && *fp++) { 
                        IRDA_DEBUG(0, "Framing or parity error!\n");
                        sirdev_receive(dev, NULL, 0);   /* notify sir_dev (updating stats) */
-                       return;
+                       return -EINVAL;
                }
        }
 
        sirdev_receive(dev, cp, count);
+
+       return count;
 }
 
 /*
index a1b82c9c67d246c64f41ee1ec51f83b04fe0a6fa..53872d7d738219968a0f433beb0ac128bdb67d6d 100644 (file)
@@ -340,7 +340,7 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
 }
 
 /* May sleep, don't call from interrupt level or with interrupts disabled */
-static void
+static unsigned int
 ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
                  char *cflags, int count)
 {
@@ -348,7 +348,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
        unsigned long flags;
 
        if (!ap)
-               return;
+               return -ENODEV;
        spin_lock_irqsave(&ap->recv_lock, flags);
        ppp_async_input(ap, buf, cflags, count);
        spin_unlock_irqrestore(&ap->recv_lock, flags);
@@ -356,6 +356,8 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
                tasklet_schedule(&ap->tsk);
        ap_put(ap);
        tty_unthrottle(tty);
+
+       return count;
 }
 
 static void
index 2573f525f11c31ced737e750fefc66807bbbfc65..0815790a5cf9930c017f490ae5d52e1d3ea67ecb 100644 (file)
@@ -381,7 +381,7 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
 }
 
 /* May sleep, don't call from interrupt level or with interrupts disabled */
-static void
+static unsigned int
 ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
                  char *cflags, int count)
 {
@@ -389,7 +389,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
        unsigned long flags;
 
        if (!ap)
-               return;
+               return -ENODEV;
        spin_lock_irqsave(&ap->recv_lock, flags);
        ppp_sync_input(ap, buf, cflags, count);
        spin_unlock_irqrestore(&ap->recv_lock, flags);
@@ -397,6 +397,8 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
                tasklet_schedule(&ap->tsk);
        sp_put(ap);
        tty_unthrottle(tty);
+
+       return count;
 }
 
 static void
index 8ec1a9a0bb9ae007c69865b2599f07d3f23c99c8..584809c656d5aaecda43d638fcaba1f48c929c89 100644 (file)
@@ -670,16 +670,17 @@ static void sl_setup(struct net_device *dev)
  * in parallel
  */
 
-static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                                                       char *fp, int count)
+static unsigned int slip_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        struct slip *sl = tty->disc_data;
+       int bytes = count;
 
        if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
-               return;
+               return -ENODEV;
 
        /* Read the characters out of the buffer */
-       while (count--) {
+       while (bytes--) {
                if (fp && *fp++) {
                        if (!test_and_set_bit(SLF_ERROR, &sl->flags))
                                sl->dev->stats.rx_errors++;
@@ -693,6 +694,8 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 #endif
                        slip_unesc(sl, *cp++);
        }
+
+       return count;
 }
 
 /************************************
index 24297b274cd475ac855114394784c7eeaab2bcd0..40398bf7d036fca1d1b56047f638375fdfd6f796 100644 (file)
@@ -517,17 +517,18 @@ static int x25_asy_close(struct net_device *dev)
  * and sent on to some IP layer for further processing.
  */
 
-static void x25_asy_receive_buf(struct tty_struct *tty,
+static unsigned int x25_asy_receive_buf(struct tty_struct *tty,
                                const unsigned char *cp, char *fp, int count)
 {
        struct x25_asy *sl = tty->disc_data;
+       int bytes = count;
 
        if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
                return;
 
 
        /* Read the characters out of the buffer */
-       while (count--) {
+       while (bytes--) {
                if (fp && *fp++) {
                        if (!test_and_set_bit(SLF_ERROR, &sl->flags))
                                sl->dev->stats.rx_errors++;
@@ -536,6 +537,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty,
                }
                x25_asy_unesc(sl, *cp++);
        }
+
+       return count;
 }
 
 /*
index bc8ce48f07781f00dccc0c856194926562af9cc3..f330338c2f2231b0af7c603447428862ce8a4f8f 100644 (file)
@@ -1621,7 +1621,7 @@ static void __devinit detect_and_report_it87(void)
        u8 origval, r;
        if (verbose_probing)
                printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n");
-       if (!request_region(0x2e, 2, __func__))
+       if (!request_muxed_region(0x2e, 2, __func__))
                return;
        origval = inb(0x2e);            /* Save original value */
        outb(0x87, 0x2e);
index 3fd7199301b649797bb4f757b9f5040e68365811..bd7cc05279990a82a66e484607f55be3922312be 100644 (file)
@@ -319,3 +319,34 @@ config N_GSM
          This line discipline provides support for the GSM MUX protocol and
          presents the mux as a set of 61 individual tty devices.
 
+config TRACE_ROUTER
+       tristate "Trace data router for MIPI P1149.7 cJTAG standard"
+       depends on TRACE_SINK
+       default n
+       help
+         The trace router uses the Linux tty line discipline framework to
+         route trace data coming from a tty port (say UART for example) to
+         the trace sink line discipline driver and to another tty port (say
+         USB). This is part of a solution for the MIPI P1149.7, compact JTAG,
+         standard, which is for debugging mobile devices. The PTI driver in
+         drivers/misc/pti.c defines the majority of this MIPI solution.
+
+         You should select this driver if the target kernel is meant for
+         a mobile device containing a modem.  Then you will need to select
+         "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline
+         driver.
+
+config TRACE_SINK
+       tristate "Trace data sink for MIPI P1149.7 cJTAG standard"
+       default n
+       help
+         The trace sink uses the Linux line discipline framework to receive
+         trace data coming from the trace router line discipline driver
+         to a user-defined tty port target, like USB.
+         This is to provide a way to extract modem trace data on
+         devices that do not have a PTI HW module, or just need modem
+         trace data to come out of a different HW output port.
+         This is part of a solution for the P1149.7, compact JTAG, standard.
+
+         If you select this option, you need to select
+         "Trace data router for MIPI P1149.7 cJTAG standard".
index 690522fcb338f1b9fd7cd79a23e69eecfa26e030..ea89b0bd15fe66820f9b0445de08990af4e77aee 100644 (file)
@@ -6,6 +6,8 @@ obj-$(CONFIG_AUDIT)             += tty_audit.o
 obj-$(CONFIG_MAGIC_SYSRQ)      += sysrq.o
 obj-$(CONFIG_N_HDLC)           += n_hdlc.o
 obj-$(CONFIG_N_GSM)            += n_gsm.o
+obj-$(CONFIG_TRACE_ROUTER)     += n_tracerouter.o
+obj-$(CONFIG_TRACE_SINK)       += n_tracesink.o
 obj-$(CONFIG_R3964)            += n_r3964.o
 
 obj-y                          += vt/
index f214e5022472e6c02f8f6ff788b596c40238a3ee..220579592c203a47c4441c5562f2f4fece0edd8b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/amiserial.c
- *
  * Serial driver for the amiga builtin port.
  *
  * This code was created by taking serial.c version 4.30 from kernel
index c99728f0cd9f004d15e687b99b4db937ee870ed9..bfa05e8018237bede822973a2029c40caf57c014 100644 (file)
@@ -3,8 +3,6 @@
 #undef Z_EXT_CHARS_IN_BUFFER
 
 /*
- *  linux/drivers/char/cyclades.c
- *
  * This file contains the driver for the Cyclades async multiport
  * serial boards.
  *
@@ -1445,13 +1443,11 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
 {
        struct cyclades_card *card;
        unsigned long flags;
-       int channel;
 
        if (!(info->port.flags & ASYNC_INITIALIZED))
                return;
 
        card = info->card;
-       channel = info->line - card->first_line;
        if (!cy_is_Z(card)) {
                spin_lock_irqsave(&card->card_lock, flags);
 
@@ -1476,6 +1472,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
                spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
 #ifdef CY_DEBUG_OPEN
+               int channel = info->line - card->first_line;
                printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
                        "base_addr %p\n", card, channel, card->base_addr);
 #endif
index db80873d7f201a72438cb182a89992bc75b1cd8f..fe2e1730986bc38b3312b0a0c97905e5f4bc028d 100644 (file)
@@ -1,6 +1,4 @@
 #
-# drivers/char/pcmcia/ipwireless/Makefile
-#
 # Makefile for the IPWireless driver
 #
 
index 35b0c38590e6b641aabdb45383030bebce31c3bd..ba679ce0a77456b1ecbeb6e674b67fbbb4ab1dac 100644 (file)
@@ -371,7 +371,7 @@ static int moxa_ioctl(struct tty_struct *tty,
                                        tmp.cflag = p->cflag;
                                else
                                        tmp.cflag = ttyp->termios->c_cflag;
-                               tty_kref_put(tty);
+                               tty_kref_put(ttyp);
 copy:
                                if (copy_to_user(argm, &tmp, sizeof(tmp)))
                                        return -EFAULT;
@@ -1129,7 +1129,6 @@ static void moxa_shutdown(struct tty_port *port)
        struct moxa_port *ch = container_of(port, struct moxa_port, port);
         MoxaPortDisable(ch);
        MoxaPortFlushData(ch, 2);
-       clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
 }
 
 static int moxa_carrier_raised(struct tty_port *port)
@@ -1155,7 +1154,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
        struct moxa_board_conf *brd;
        struct moxa_port *ch;
        int port;
-       int retval;
 
        port = tty->index;
        if (port == MAX_PORTS) {
@@ -1190,10 +1188,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
        mutex_unlock(&ch->port.mutex);
        mutex_unlock(&moxa_openlock);
 
-       retval = tty_port_block_til_ready(&ch->port, tty, filp);
-       if (retval == 0)
-               set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags);
-       return retval;
+       return tty_port_block_til_ready(&ch->port, tty, filp);
 }
 
 static void moxa_close(struct tty_struct *tty, struct file *filp)
@@ -1207,14 +1202,15 @@ static int moxa_write(struct tty_struct *tty,
                      const unsigned char *buf, int count)
 {
        struct moxa_port *ch = tty->driver_data;
+       unsigned long flags;
        int len;
 
        if (ch == NULL)
                return 0;
 
-       spin_lock_bh(&moxa_lock);
+       spin_lock_irqsave(&moxa_lock, flags);
        len = MoxaPortWriteData(tty, buf, count);
-       spin_unlock_bh(&moxa_lock);
+       spin_unlock_irqrestore(&moxa_lock, flags);
 
        set_bit(LOWWAIT, &ch->statusflags);
        return len;
@@ -1281,10 +1277,8 @@ static int moxa_tiocmset(struct tty_struct *tty,
                         unsigned int set, unsigned int clear)
 {
        struct moxa_port *ch;
-       int port;
        int dtr, rts;
 
-       port = tty->index;
        mutex_lock(&moxa_openlock);
        ch = tty->driver_data;
        if (!ch) {
@@ -1756,11 +1750,9 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
                speed_t baud)
 {
        void __iomem *ofsAddr;
-       tcflag_t cflag;
        tcflag_t mode = 0;
 
        ofsAddr = port->tableAddr;
-       cflag = termio->c_cflag;        /* termio->c_cflag */
 
        mode = termio->c_cflag & CSIZE;
        if (mode == CS5)
index 77623b936538bca5d6af049dc649f3ee9e74a863..a4c42a75a3bfea0f0143e8dd70454fde5dddf524 100644 (file)
@@ -526,19 +526,6 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len)
        return olen;
 }
 
-static void hex_packet(const unsigned char *p, int len)
-{
-       int i;
-       for (i = 0; i < len; i++) {
-               if (i && (i % 16) == 0) {
-                       pr_cont("\n");
-                       pr_debug("");
-               }
-               pr_cont("%02X ", *p++);
-       }
-       pr_cont("\n");
-}
-
 /**
  *     gsm_send        -       send a control frame
  *     @gsm: our GSM mux
@@ -685,10 +672,10 @@ static void gsm_data_kick(struct gsm_mux *gsm)
                        len = msg->len + 2;
                }
 
-               if (debug & 4) {
-                       pr_debug("gsm_data_kick:\n");
-                       hex_packet(gsm->txframe, len);
-               }
+               if (debug & 4)
+                       print_hex_dump_bytes("gsm_data_kick: ",
+                                            DUMP_PREFIX_OFFSET,
+                                            gsm->txframe, len);
 
                if (gsm->output(gsm, gsm->txframe + skip_sof,
                                                len - skip_sof) < 0)
@@ -2095,10 +2082,9 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
                set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags);
                return -ENOSPC;
        }
-       if (debug & 4) {
-               pr_debug("-->%d bytes out\n", len);
-               hex_packet(data, len);
-       }
+       if (debug & 4)
+               print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET,
+                                    data, len);
        gsm->tty->ops->write(gsm->tty, data, len);
        return len;
 }
@@ -2142,8 +2128,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
        gsm->tty = NULL;
 }
 
-static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                             char *fp, int count)
+static unsigned int gsmld_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        struct gsm_mux *gsm = tty->disc_data;
        const unsigned char *dp;
@@ -2152,10 +2138,9 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        char buf[64];
        char flags;
 
-       if (debug & 4) {
-               pr_debug("Inbytes %dd\n", count);
-               hex_packet(cp, count);
-       }
+       if (debug & 4)
+               print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
+                                    cp, count);
 
        for (i = count, dp = cp, f = fp; i; i--, dp++) {
                flags = *f++;
@@ -2177,6 +2162,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        }
        /* FASYNC if needed ? */
        /* If clogged call tty_throttle(tty); */
+
+       return count;
 }
 
 /**
index cea56033b34c2b490e796ae75df0fbea4e550a3f..cac666314aef4a5f453c5031caaa5b8fac4f0508 100644 (file)
@@ -188,8 +188,8 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
                                    poll_table *wait);
 static int n_hdlc_tty_open(struct tty_struct *tty);
 static void n_hdlc_tty_close(struct tty_struct *tty);
-static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp,
-                              char *fp, int count);
+static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,
+               const __u8 *cp, char *fp, int count);
 static void n_hdlc_tty_wakeup(struct tty_struct *tty);
 
 #define bset(p,b)      ((p)[(b) >> 5] |= (1 << ((b) & 0x1f)))
@@ -509,8 +509,8 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)
  * Called by tty low level driver when receive data is available. Data is
  * interpreted as one HDLC frame.
  */
-static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
-                              char *flags, int count)
+static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,
+               const __u8 *data, char *flags, int count)
 {
        register struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
        register struct n_hdlc_buf *buf;
@@ -521,20 +521,20 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
                
        /* This can happen if stuff comes in on the backup tty */
        if (!n_hdlc || tty != n_hdlc->tty)
-               return;
+               return -ENODEV;
                
        /* verify line is using HDLC discipline */
        if (n_hdlc->magic != HDLC_MAGIC) {
                printk("%s(%d) line not using HDLC discipline\n",
                        __FILE__,__LINE__);
-               return;
+               return -EINVAL;
        }
        
        if ( count>maxframe ) {
                if (debuglevel >= DEBUG_LEVEL_INFO)     
                        printk("%s(%d) rx count>maxframesize, data discarded\n",
                               __FILE__,__LINE__);
-               return;
+               return -EINVAL;
        }
 
        /* get a free HDLC buffer */    
@@ -550,7 +550,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
                if (debuglevel >= DEBUG_LEVEL_INFO)     
                        printk("%s(%d) no more rx buffers, data discarded\n",
                               __FILE__,__LINE__);
-               return;
+               return -EINVAL;
        }
                
        /* copy received data to HDLC buffer */
@@ -565,6 +565,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
        if (n_hdlc->tty->fasync != NULL)
                kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN);
 
+       return count;
+
 }      /* end of n_hdlc_tty_receive() */
 
 /**
index 5c6c31459a2f6618cb7cf9d83c7100cf1a6d86ea..a4bc39c21a436476b7ea8363f6c4d892882a5520 100644 (file)
@@ -139,8 +139,8 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,
 static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
 static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
                struct poll_table_struct *wait);
-static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-               char *fp, int count);
+static unsigned int r3964_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count);
 
 static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
        .owner = THIS_MODULE,
@@ -1239,8 +1239,8 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
        return result;
 }
 
-static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                       char *fp, int count)
+static unsigned int r3964_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        struct r3964_info *pInfo = tty->disc_data;
        const unsigned char *p;
@@ -1257,6 +1257,8 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                }
 
        }
+
+       return count;
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/n_tracerouter.c b/drivers/tty/n_tracerouter.c
new file mode 100644 (file)
index 0000000..1f063d3
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  n_tracerouter.c - Trace data router through tty space
+ *
+ *  Copyright (C) Intel 2011
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This trace router uses the Linux line discipline framework to route
+ * trace data coming from a HW Modem to a PTI (Parallel Trace Module) port.
+ * The solution is not specific to a HW modem and this line disciple can
+ * be used to route any stream of data in kernel space.
+ * This is part of a solution for the P1149.7, compact JTAG, standard.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/tty.h>
+#include <linux/tty_ldisc.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm-generic/bug.h>
+#include "n_tracesink.h"
+
+/*
+ * Other ldisc drivers use 65536 which basically means,
+ * 'I can always accept 64k' and flow control is off.
+ * This number is deemed appropriate for this driver.
+ */
+#define RECEIVE_ROOM   65536
+#define DRIVERNAME     "n_tracerouter"
+
+/*
+ * struct to hold private configuration data for this ldisc.
+ * opencalled is used to hold if this ldisc has been opened.
+ * kref_tty holds the tty reference the ldisc sits on top of.
+ */
+struct tracerouter_data {
+       u8 opencalled;
+       struct tty_struct *kref_tty;
+};
+static struct tracerouter_data *tr_data;
+
+/* lock for when tty reference is being used */
+static DEFINE_MUTEX(routelock);
+
+/**
+ * n_tracerouter_open() - Called when a tty is opened by a SW entity.
+ * @tty: terminal device to the ldisc.
+ *
+ * Return:
+ *      0 for success.
+ *
+ * Caveats: This should only be opened one time per SW entity.
+ */
+static int n_tracerouter_open(struct tty_struct *tty)
+{
+       int retval = -EEXIST;
+
+       mutex_lock(&routelock);
+       if (tr_data->opencalled == 0) {
+
+               tr_data->kref_tty = tty_kref_get(tty);
+               if (tr_data->kref_tty == NULL) {
+                       retval = -EFAULT;
+               } else {
+                       tr_data->opencalled = 1;
+                       tty->disc_data      = tr_data;
+                       tty->receive_room   = RECEIVE_ROOM;
+                       tty_driver_flush_buffer(tty);
+                       retval = 0;
+               }
+       }
+       mutex_unlock(&routelock);
+       return retval;
+}
+
+/**
+ * n_tracerouter_close() - close connection
+ * @tty: terminal device to the ldisc.
+ *
+ * Called when a software entity wants to close a connection.
+ */
+static void n_tracerouter_close(struct tty_struct *tty)
+{
+       struct tracerouter_data *tptr = tty->disc_data;
+
+       mutex_lock(&routelock);
+       WARN_ON(tptr->kref_tty != tr_data->kref_tty);
+       tty_driver_flush_buffer(tty);
+       tty_kref_put(tr_data->kref_tty);
+       tr_data->kref_tty = NULL;
+       tr_data->opencalled = 0;
+       tty->disc_data = NULL;
+       mutex_unlock(&routelock);
+}
+
+/**
+ * n_tracerouter_read() - read request from user space
+ * @tty:  terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf:  pointer to the data buffer that gets eventually returned.
+ * @nr:   number of bytes of the data buffer that is returned.
+ *
+ * function that allows read() functionality in userspace. By default if this
+ * is not implemented it returns -EIO. This module is functioning like a
+ * router via n_tracerouter_receivebuf(), and there is no real requirement
+ * to implement this function. However, an error return value other than
+ * -EIO should be used just to show that there was an intent not to have
+ * this function implemented.  Return value based on read() man pages.
+ *
+ * Return:
+ *      -EINVAL
+ */
+static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file,
+                                 unsigned char __user *buf, size_t nr) {
+       return -EINVAL;
+}
+
+/**
+ * n_tracerouter_write() - Function that allows write() in userspace.
+ * @tty:  terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf:  pointer to the data buffer that gets eventually returned.
+ * @nr:   number of bytes of the data buffer that is returned.
+ *
+ * By default if this is not implemented, it returns -EIO.
+ * This should not be implemented, ever, because
+ * 1. this driver is functioning like a router via
+ *    n_tracerouter_receivebuf()
+ * 2. No writes to HW will ever go through this line discpline driver.
+ * However, an error return value other than -EIO should be used
+ * just to show that there was an intent not to have this function
+ * implemented.  Return value based on write() man pages.
+ *
+ * Return:
+ *     -EINVAL
+ */
+static ssize_t n_tracerouter_write(struct tty_struct *tty, struct file *file,
+                                  const unsigned char *buf, size_t nr) {
+       return -EINVAL;
+}
+
+/**
+ * n_tracerouter_receivebuf() - Routing function for driver.
+ * @tty: terminal device passed into the ldisc.  It's assumed
+ *       tty will never be NULL.
+ * @cp:  buffer, block of characters to be eventually read by
+ *       someone, somewhere (user read() call or some kernel function).
+ * @fp:  flag buffer.
+ * @count: number of characters (aka, bytes) in cp.
+ *
+ * This function takes the input buffer, cp, and passes it to
+ * an external API function for processing.
+ */
+static void n_tracerouter_receivebuf(struct tty_struct *tty,
+                                       const unsigned char *cp,
+                                       char *fp, int count)
+{
+       mutex_lock(&routelock);
+       n_tracesink_datadrain((u8 *) cp, count);
+       mutex_unlock(&routelock);
+}
+
+/*
+ * Flush buffer is not impelemented as the ldisc has no internal buffering
+ * so the tty_driver_flush_buffer() is sufficient for this driver's needs.
+ */
+
+static struct tty_ldisc_ops tty_ptirouter_ldisc = {
+       .owner          = THIS_MODULE,
+       .magic          = TTY_LDISC_MAGIC,
+       .name           = DRIVERNAME,
+       .open           = n_tracerouter_open,
+       .close          = n_tracerouter_close,
+       .read           = n_tracerouter_read,
+       .write          = n_tracerouter_write,
+       .receive_buf    = n_tracerouter_receivebuf
+};
+
+/**
+ * n_tracerouter_init -        module initialisation
+ *
+ * Registers this module as a line discipline driver.
+ *
+ * Return:
+ *     0 for success, any other value error.
+ */
+static int __init n_tracerouter_init(void)
+{
+       int retval;
+
+       tr_data = kzalloc(sizeof(struct tracerouter_data), GFP_KERNEL);
+       if (tr_data == NULL)
+               return -ENOMEM;
+
+
+       /* Note N_TRACEROUTER is defined in linux/tty.h */
+       retval = tty_register_ldisc(N_TRACEROUTER, &tty_ptirouter_ldisc);
+       if (retval < 0) {
+               pr_err("%s: Registration failed: %d\n", __func__, retval);
+               kfree(tr_data);
+       }
+       return retval;
+}
+
+/**
+ * n_tracerouter_exit -        module unload
+ *
+ * Removes this module as a line discipline driver.
+ */
+static void __exit n_tracerouter_exit(void)
+{
+       int retval = tty_unregister_ldisc(N_TRACEROUTER);
+
+       if (retval < 0)
+               pr_err("%s: Unregistration failed: %d\n", __func__,  retval);
+       else
+               kfree(tr_data);
+}
+
+module_init(n_tracerouter_init);
+module_exit(n_tracerouter_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jay Freyensee");
+MODULE_ALIAS_LDISC(N_TRACEROUTER);
+MODULE_DESCRIPTION("Trace router ldisc driver");
diff --git a/drivers/tty/n_tracesink.c b/drivers/tty/n_tracesink.c
new file mode 100644 (file)
index 0000000..ddce58b
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ *  n_tracesink.c - Trace data router and sink path through tty space.
+ *
+ *  Copyright (C) Intel 2011
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The trace sink uses the Linux line discipline framework to receive
+ * trace data coming from the PTI source line discipline driver
+ * to a user-desired tty port, like USB.
+ * This is to provide a way to extract modem trace data on
+ * devices that do not have a PTI HW module, or just need modem
+ * trace data to come out of a different HW output port.
+ * This is part of a solution for the P1149.7, compact JTAG, standard.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/tty.h>
+#include <linux/tty_ldisc.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <asm-generic/bug.h>
+#include "n_tracesink.h"
+
+/*
+ * Other ldisc drivers use 65536 which basically means,
+ * 'I can always accept 64k' and flow control is off.
+ * This number is deemed appropriate for this driver.
+ */
+#define RECEIVE_ROOM   65536
+#define DRIVERNAME     "n_tracesink"
+
+/*
+ * there is a quirk with this ldisc is he can write data
+ * to a tty from anyone calling his kernel API, which
+ * meets customer requirements in the drivers/misc/pti.c
+ * project.  So he needs to know when he can and cannot write when
+ * the API is called. In theory, the API can be called
+ * after an init() but before a successful open() which
+ * would crash the system if tty is not checked.
+ */
+static struct tty_struct *this_tty;
+static DEFINE_MUTEX(writelock);
+
+/**
+ * n_tracesink_open() - Called when a tty is opened by a SW entity.
+ * @tty: terminal device to the ldisc.
+ *
+ * Return:
+ *      0 for success,
+ *      -EFAULT = couldn't get a tty kref n_tracesink will sit
+ *       on top of
+ *      -EEXIST = open() called successfully once and it cannot
+ *      be called again.
+ *
+ * Caveats: open() should only be successful the first time a
+ * SW entity calls it.
+ */
+static int n_tracesink_open(struct tty_struct *tty)
+{
+       int retval = -EEXIST;
+
+       mutex_lock(&writelock);
+       if (this_tty == NULL) {
+               this_tty = tty_kref_get(tty);
+               if (this_tty == NULL) {
+                       retval = -EFAULT;
+               } else {
+                       tty->disc_data = this_tty;
+                       tty_driver_flush_buffer(tty);
+                       retval = 0;
+               }
+       }
+       mutex_unlock(&writelock);
+
+       return retval;
+}
+
+/**
+ * n_tracesink_close() - close connection
+ * @tty: terminal device to the ldisc.
+ *
+ * Called when a software entity wants to close a connection.
+ */
+static void n_tracesink_close(struct tty_struct *tty)
+{
+       mutex_lock(&writelock);
+       tty_driver_flush_buffer(tty);
+       tty_kref_put(this_tty);
+       this_tty = NULL;
+       tty->disc_data = NULL;
+       mutex_unlock(&writelock);
+}
+
+/**
+ * n_tracesink_read() - read request from user space
+ * @tty:  terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf:  pointer to the data buffer that gets eventually returned.
+ * @nr:   number of bytes of the data buffer that is returned.
+ *
+ * function that allows read() functionality in userspace. By default if this
+ * is not implemented it returns -EIO. This module is functioning like a
+ * router via n_tracesink_receivebuf(), and there is no real requirement
+ * to implement this function. However, an error return value other than
+ * -EIO should be used just to show that there was an intent not to have
+ * this function implemented.  Return value based on read() man pages.
+ *
+ * Return:
+ *      -EINVAL
+ */
+static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file,
+                               unsigned char __user *buf, size_t nr) {
+       return -EINVAL;
+}
+
+/**
+ * n_tracesink_write() - Function that allows write() in userspace.
+ * @tty:  terminal device passed into the ldisc.
+ * @file: pointer to open file object.
+ * @buf:  pointer to the data buffer that gets eventually returned.
+ * @nr:   number of bytes of the data buffer that is returned.
+ *
+ * By default if this is not implemented, it returns -EIO.
+ * This should not be implemented, ever, because
+ * 1. this driver is functioning like a router via
+ *    n_tracesink_receivebuf()
+ * 2. No writes to HW will ever go through this line discpline driver.
+ * However, an error return value other than -EIO should be used
+ * just to show that there was an intent not to have this function
+ * implemented.  Return value based on write() man pages.
+ *
+ * Return:
+ *     -EINVAL
+ */
+static ssize_t n_tracesink_write(struct tty_struct *tty, struct file *file,
+                                const unsigned char *buf, size_t nr) {
+       return -EINVAL;
+}
+
+/**
+ * n_tracesink_datadrain() - Kernel API function used to route
+ *                          trace debugging data to user-defined
+ *                          port like USB.
+ *
+ * @buf:   Trace debuging data buffer to write to tty target
+ *         port. Null value will return with no write occurring.
+ * @count: Size of buf. Value of 0 or a negative number will
+ *         return with no write occuring.
+ *
+ * Caveat: If this line discipline does not set the tty it sits
+ * on top of via an open() call, this API function will not
+ * call the tty's write() call because it will have no pointer
+ * to call the write().
+ */
+void n_tracesink_datadrain(u8 *buf, int count)
+{
+       mutex_lock(&writelock);
+
+       if ((buf != NULL) && (count > 0) && (this_tty != NULL))
+               this_tty->ops->write(this_tty, buf, count);
+
+       mutex_unlock(&writelock);
+}
+EXPORT_SYMBOL_GPL(n_tracesink_datadrain);
+
+/*
+ * Flush buffer is not impelemented as the ldisc has no internal buffering
+ * so the tty_driver_flush_buffer() is sufficient for this driver's needs.
+ */
+
+/*
+ * tty_ldisc function operations for this driver.
+ */
+static struct tty_ldisc_ops tty_n_tracesink = {
+       .owner          = THIS_MODULE,
+       .magic          = TTY_LDISC_MAGIC,
+       .name           = DRIVERNAME,
+       .open           = n_tracesink_open,
+       .close          = n_tracesink_close,
+       .read           = n_tracesink_read,
+       .write          = n_tracesink_write
+};
+
+/**
+ * n_tracesink_init-   module initialisation
+ *
+ * Registers this module as a line discipline driver.
+ *
+ * Return:
+ *     0 for success, any other value error.
+ */
+static int __init n_tracesink_init(void)
+{
+       /* Note N_TRACESINK is defined in linux/tty.h */
+       int retval = tty_register_ldisc(N_TRACESINK, &tty_n_tracesink);
+
+       if (retval < 0)
+               pr_err("%s: Registration failed: %d\n", __func__, retval);
+
+       return retval;
+}
+
+/**
+ * n_tracesink_exit -  module unload
+ *
+ * Removes this module as a line discipline driver.
+ */
+static void __exit n_tracesink_exit(void)
+{
+       int retval = tty_unregister_ldisc(N_TRACESINK);
+
+       if (retval < 0)
+               pr_err("%s: Unregistration failed: %d\n", __func__,  retval);
+}
+
+module_init(n_tracesink_init);
+module_exit(n_tracesink_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jay Freyensee");
+MODULE_ALIAS_LDISC(N_TRACESINK);
+MODULE_DESCRIPTION("Trace sink ldisc driver");
diff --git a/drivers/tty/n_tracesink.h b/drivers/tty/n_tracesink.h
new file mode 100644 (file)
index 0000000..a68bb44
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  n_tracesink.h - Kernel driver API to route trace data in kernel space.
+ *
+ *  Copyright (C) Intel 2011
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The PTI (Parallel Trace Interface) driver directs trace data routed from
+ * various parts in the system out through the Intel Penwell PTI port and
+ * out of the mobile device for analysis with a debugging tool
+ * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7,
+ * compact JTAG, standard.
+ *
+ * This header file is used by n_tracerouter to be able to send the
+ * data of it's tty port to the tty port this module sits.  This
+ * mechanism can also be used independent of the PTI module.
+ *
+ */
+
+#ifndef N_TRACESINK_H_
+#define N_TRACESINK_H_
+
+void n_tracesink_datadrain(u8 *buf, int count);
+
+#endif
index 0ad32888091c16c1c27de4c032517df583ea4c9f..95d0a9c2dd13e3e625d8b287d911d327cebe2ee4 100644 (file)
@@ -81,38 +81,6 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
        return put_user(x, ptr);
 }
 
-/**
- *     n_tty_set__room -       receive space
- *     @tty: terminal
- *
- *     Called by the driver to find out how much data it is
- *     permitted to feed to the line discipline without any being lost
- *     and thus to manage flow control. Not serialized. Answers for the
- *     "instant".
- */
-
-static void n_tty_set_room(struct tty_struct *tty)
-{
-       /* tty->read_cnt is not read locked ? */
-       int     left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
-       int old_left;
-
-       /*
-        * If we are doing input canonicalization, and there are no
-        * pending newlines, let characters through without limit, so
-        * that erase characters will be handled.  Other excess
-        * characters will be beeped.
-        */
-       if (left <= 0)
-               left = tty->icanon && !tty->canon_data;
-       old_left = tty->receive_room;
-       tty->receive_room = left;
-
-       /* Did this open up the receive buffer? We may need to flip */
-       if (left && !old_left)
-               schedule_work(&tty->buf.work);
-}
-
 static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
 {
        if (tty->read_cnt < N_TTY_BUF_SIZE) {
@@ -184,7 +152,6 @@ static void reset_buffer_flags(struct tty_struct *tty)
 
        tty->canon_head = tty->canon_data = tty->erasing = 0;
        memset(&tty->read_flags, 0, sizeof tty->read_flags);
-       n_tty_set_room(tty);
        check_unthrottle(tty);
 }
 
@@ -1360,17 +1327,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
  *     calls one at a time and in order (or using flush_to_ldisc)
  */
 
-static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                             char *fp, int count)
+static unsigned int n_tty_receive_buf(struct tty_struct *tty,
+               const unsigned char *cp, char *fp, int count)
 {
        const unsigned char *p;
        char *f, flags = TTY_NORMAL;
        int     i;
        char    buf[64];
        unsigned long cpuflags;
+       int left;
+       int ret = 0;
 
        if (!tty->read_buf)
-               return;
+               return 0;
 
        if (tty->real_raw) {
                spin_lock_irqsave(&tty->read_lock, cpuflags);
@@ -1380,6 +1349,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                memcpy(tty->read_buf + tty->read_head, cp, i);
                tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
                tty->read_cnt += i;
+               ret += i;
                cp += i;
                count -= i;
 
@@ -1389,8 +1359,10 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                memcpy(tty->read_buf + tty->read_head, cp, i);
                tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
                tty->read_cnt += i;
+               ret += i;
                spin_unlock_irqrestore(&tty->read_lock, cpuflags);
        } else {
+               ret = count;
                for (i = count, p = cp, f = fp; i; i--, p++) {
                        if (f)
                                flags = *f++;
@@ -1418,8 +1390,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                        tty->ops->flush_chars(tty);
        }
 
-       n_tty_set_room(tty);
-
        if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
                L_EXTPROC(tty)) {
                kill_fasync(&tty->fasync, SIGIO, POLL_IN);
@@ -1432,8 +1402,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
         * mode.  We don't want to throttle the driver if we're in
         * canonical mode and don't have a newline yet!
         */
-       if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
+       left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+       if (left < TTY_THRESHOLD_THROTTLE)
                tty_throttle(tty);
+
+       return ret;
 }
 
 int is_ignored(int sig)
@@ -1477,7 +1451,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
        if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
                tty->raw = 1;
                tty->real_raw = 1;
-               n_tty_set_room(tty);
                return;
        }
        if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1530,7 +1503,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
                else
                        tty->real_raw = 0;
        }
-       n_tty_set_room(tty);
        /* The termios change make the tty ready for I/O */
        wake_up_interruptible(&tty->write_wait);
        wake_up_interruptible(&tty->read_wait);
@@ -1812,8 +1784,6 @@ do_it_again:
                                retval = -ERESTARTSYS;
                                break;
                        }
-                       /* FIXME: does n_tty_set_room need locking ? */
-                       n_tty_set_room(tty);
                        timeout = schedule_timeout(timeout);
                        continue;
                }
@@ -1885,10 +1855,8 @@ do_it_again:
                 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
                 * we won't get any more characters.
                 */
-               if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
-                       n_tty_set_room(tty);
+               if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
                        check_unthrottle(tty);
-               }
 
                if (b - buf >= minimum)
                        break;
@@ -1910,7 +1878,6 @@ do_it_again:
        } else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
                 goto do_it_again;
 
-       n_tty_set_room(tty);
        return retval;
 }
 
index fd0a98524d513482807c30055b849726f953b590..b1aecc7bb32a263fbdc75035f65f156e1f4f2549 100644 (file)
@@ -364,8 +364,6 @@ struct port {
        u8 toggle_ul;
        u16 token_dl;
 
-       /* mutex to ensure one access patch to this port */
-       struct mutex tty_sem;
        wait_queue_head_t tty_wait;
        struct async_icount tty_icount;
 
@@ -1431,8 +1429,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
        }
 
        for (i = PORT_MDM; i < MAX_PORT; i++) {
-               if (kfifo_alloc(&dc->port[i].fifo_ul,
-                     FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) {
+               if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL,
+                                       GFP_KERNEL)) {
                        dev_err(&pdev->dev,
                                        "Could not allocate kfifo buffer\n");
                        ret = -ENOMEM;
@@ -1474,7 +1472,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
                struct device *tty_dev;
                struct port *port = &dc->port[i];
                port->dc = dc;
-               mutex_init(&port->tty_sem);
                tty_port_init(&port->port);
                port->port.ops = &noz_tty_port_ops;
                tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
@@ -1688,13 +1685,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
        if (!dc || !port)
                return -ENODEV;
 
-       mutex_lock(&port->tty_sem);
-
-       if (unlikely(!port->port.count)) {
-               DBG1(" ");
-               goto exit;
-       }
-
        rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
 
        /* notify card */
@@ -1719,7 +1709,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
        spin_unlock_irqrestore(&dc->spin_mutex, flags);
 
 exit:
-       mutex_unlock(&port->tty_sem);
        return rval;
 }
 
@@ -1738,12 +1727,9 @@ static int ntty_write_room(struct tty_struct *tty)
        int room = 4096;
        const struct nozomi *dc = get_dc_by_tty(tty);
 
-       if (dc) {
-               mutex_lock(&port->tty_sem);
-               if (port->port.count)
-                       room = kfifo_avail(&port->fifo_ul);
-               mutex_unlock(&port->tty_sem);
-       }
+       if (dc)
+               room = kfifo_avail(&port->fifo_ul);
+
        return room;
 }
 
@@ -1889,11 +1875,6 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
                goto exit_in_buffer;
        }
 
-       if (unlikely(!port->port.count)) {
-               dev_err(&dc->pdev->dev, "No tty open?\n");
-               goto exit_in_buffer;
-       }
-
        rval = kfifo_len(&port->fifo_ul);
 
 exit_in_buffer:
index 210774726add12f9de8ef0c280360201b6791331..98b6e3bdb000bda730a69a05680d76b8584f1715 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/pty.c
- *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  Added support for a Unix98-style ptmx device.
@@ -295,8 +293,8 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
                return -ENOMEM;
        if (!try_module_get(driver->other->owner)) {
                /* This cannot in fact currently happen */
-               free_tty_struct(o_tty);
-               return -ENOMEM;
+               retval = -ENOMEM;
+               goto err_free_tty;
        }
        initialize_tty_struct(o_tty, driver->other, idx);
 
@@ -304,13 +302,11 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
           the easy way .. */
        retval = tty_init_termios(tty);
        if (retval)
-               goto free_mem_out;
+               goto err_deinit_tty;
 
        retval = tty_init_termios(o_tty);
-       if (retval) {
-               tty_free_termios(tty);
-               goto free_mem_out;
-       }
+       if (retval)
+               goto err_free_termios;
 
        /*
         * Everything allocated ... set up the o_tty structure.
@@ -327,10 +323,14 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
        tty->count++;
        driver->ttys[idx] = tty;
        return 0;
-free_mem_out:
+err_free_termios:
+       tty_free_termios(tty);
+err_deinit_tty:
+       deinitialize_tty_struct(o_tty);
        module_put(o_tty->driver->owner);
+err_free_tty:
        free_tty_struct(o_tty);
-       return -ENOMEM;
+       return retval;
 }
 
 static int pty_bsd_ioctl(struct tty_struct *tty,
@@ -559,20 +559,19 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
                return -ENOMEM;
        if (!try_module_get(driver->other->owner)) {
                /* This cannot in fact currently happen */
-               free_tty_struct(o_tty);
-               return -ENOMEM;
+               goto err_free_tty;
        }
        initialize_tty_struct(o_tty, driver->other, idx);
 
        tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
        if (tty->termios == NULL)
-               goto free_mem_out;
+               goto err_free_mem;
        *tty->termios = driver->init_termios;
        tty->termios_locked = tty->termios + 1;
 
        o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
        if (o_tty->termios == NULL)
-               goto free_mem_out;
+               goto err_free_mem;
        *o_tty->termios = driver->other->init_termios;
        o_tty->termios_locked = o_tty->termios + 1;
 
@@ -591,11 +590,13 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
        tty->count++;
        pty_count++;
        return 0;
-free_mem_out:
+err_free_mem:
+       deinitialize_tty_struct(o_tty);
        kfree(o_tty->termios);
+       kfree(tty->termios);
        module_put(o_tty->driver->owner);
+err_free_tty:
        free_tty_struct(o_tty);
-       kfree(tty->termios);
        return -ENOMEM;
 }
 
index 036feeb5e3f6e9590c06852fefa95af977e3f8c9..13043e8d37fe8ffc4ffc6bb681c8f56009ebbe4b 100644 (file)
@@ -1380,7 +1380,6 @@ static void rp_send_xchar(struct tty_struct *tty, char ch)
 static void rp_throttle(struct tty_struct *tty)
 {
        struct r_port *info = tty->driver_data;
-       CHANNEL_t *cp;
 
 #ifdef ROCKET_DEBUG_THROTTLE
        printk(KERN_INFO "throttle %s: %d....\n", tty->name,
@@ -1390,7 +1389,6 @@ static void rp_throttle(struct tty_struct *tty)
        if (rocket_paranoia_check(info, "rp_throttle"))
                return;
 
-       cp = &info->channel;
        if (I_IXOFF(tty))
                rp_send_xchar(tty, STOP_CHAR(tty));
 
@@ -1400,7 +1398,6 @@ static void rp_throttle(struct tty_struct *tty)
 static void rp_unthrottle(struct tty_struct *tty)
 {
        struct r_port *info = tty->driver_data;
-       CHANNEL_t *cp;
 #ifdef ROCKET_DEBUG_THROTTLE
        printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
               tty->ldisc.chars_in_buffer(tty));
@@ -1409,7 +1406,6 @@ static void rp_unthrottle(struct tty_struct *tty)
        if (rocket_paranoia_check(info, "rp_throttle"))
                return;
 
-       cp = &info->channel;
        if (I_IXOFF(tty))
                rp_send_xchar(tty, START_CHAR(tty));
 
@@ -1722,13 +1718,10 @@ static int rp_write_room(struct tty_struct *tty)
 static int rp_chars_in_buffer(struct tty_struct *tty)
 {
        struct r_port *info = tty->driver_data;
-       CHANNEL_t *cp;
 
        if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
                return 0;
 
-       cp = &info->channel;
-
 #ifdef ROCKET_DEBUG_WRITE
        printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
 #endif
@@ -1779,7 +1772,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
 {
        int num_aiops, aiop, max_num_aiops, num_chan, chan;
        unsigned int aiopio[MAX_AIOPS_PER_BOARD];
-       char *str, *board_type;
        CONTROLLER_t *ctlp;
 
        int fast_clock = 0;
@@ -1800,7 +1792,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
        /*  Depending on the model, set up some config variables */
        switch (dev->device) {
        case PCI_DEVICE_ID_RP4QUAD:
-               str = "Quadcable";
                max_num_aiops = 1;
                ports_per_aiop = 4;
                rocketModel[i].model = MODEL_RP4QUAD;
@@ -1808,42 +1799,36 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rocketModel[i].numPorts = 4;
                break;
        case PCI_DEVICE_ID_RP8OCTA:
-               str = "Octacable";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_RP8OCTA;
                strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_URP8OCTA:
-               str = "Octacable";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_UPCI_RP8OCTA;
                strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_RP8INTF:
-               str = "8";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_RP8INTF;
                strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_URP8INTF:
-               str = "8";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_UPCI_RP8INTF;
                strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_RP8J:
-               str = "8J";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_RP8J;
                strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_RP4J:
-               str = "4J";
                max_num_aiops = 1;
                ports_per_aiop = 4;
                rocketModel[i].model = MODEL_RP4J;
@@ -1851,56 +1836,48 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rocketModel[i].numPorts = 4;
                break;
        case PCI_DEVICE_ID_RP8SNI:
-               str = "8 (DB78 Custom)";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_RP8SNI;
                strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_RP16SNI:
-               str = "16 (DB78 Custom)";
                max_num_aiops = 2;
                rocketModel[i].model = MODEL_RP16SNI;
                strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
                rocketModel[i].numPorts = 16;
                break;
        case PCI_DEVICE_ID_RP16INTF:
-               str = "16";
                max_num_aiops = 2;
                rocketModel[i].model = MODEL_RP16INTF;
                strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
                rocketModel[i].numPorts = 16;
                break;
        case PCI_DEVICE_ID_URP16INTF:
-               str = "16";
                max_num_aiops = 2;
                rocketModel[i].model = MODEL_UPCI_RP16INTF;
                strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
                rocketModel[i].numPorts = 16;
                break;
        case PCI_DEVICE_ID_CRP16INTF:
-               str = "16";
                max_num_aiops = 2;
                rocketModel[i].model = MODEL_CPCI_RP16INTF;
                strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
                rocketModel[i].numPorts = 16;
                break;
        case PCI_DEVICE_ID_RP32INTF:
-               str = "32";
                max_num_aiops = 4;
                rocketModel[i].model = MODEL_RP32INTF;
                strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
                rocketModel[i].numPorts = 32;
                break;
        case PCI_DEVICE_ID_URP32INTF:
-               str = "32";
                max_num_aiops = 4;
                rocketModel[i].model = MODEL_UPCI_RP32INTF;
                strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
                rocketModel[i].numPorts = 32;
                break;
        case PCI_DEVICE_ID_RPP4:
-               str = "Plus Quadcable";
                max_num_aiops = 1;
                ports_per_aiop = 4;
                altChanRingIndicator++;
@@ -1910,7 +1887,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rocketModel[i].numPorts = 4;
                break;
        case PCI_DEVICE_ID_RPP8:
-               str = "Plus Octacable";
                max_num_aiops = 2;
                ports_per_aiop = 4;
                altChanRingIndicator++;
@@ -1920,7 +1896,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rocketModel[i].numPorts = 8;
                break;
        case PCI_DEVICE_ID_RP2_232:
-               str = "Plus 2 (RS-232)";
                max_num_aiops = 1;
                ports_per_aiop = 2;
                altChanRingIndicator++;
@@ -1930,7 +1905,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rocketModel[i].numPorts = 2;
                break;
        case PCI_DEVICE_ID_RP2_422:
-               str = "Plus 2 (RS-422)";
                max_num_aiops = 1;
                ports_per_aiop = 2;
                altChanRingIndicator++;
@@ -1943,7 +1917,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
 
                max_num_aiops = 1;
                ports_per_aiop = 6;
-               str = "6-port";
 
                /*  If revision is 1, the rocketmodem flash must be loaded.
                 *  If it is 2 it is a "socketed" version. */
@@ -1961,7 +1934,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
        case PCI_DEVICE_ID_RP4M:
                max_num_aiops = 1;
                ports_per_aiop = 4;
-               str = "4-port";
                if (dev->revision == 1) {
                        rcktpt_type[i] = ROCKET_TYPE_MODEMII;
                        rocketModel[i].loadrm2 = 1;
@@ -1974,7 +1946,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rocketModel[i].numPorts = 4;
                break;
        default:
-               str = "(unknown/unsupported)";
                max_num_aiops = 0;
                break;
        }
@@ -2000,14 +1971,12 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                        if (!
                            (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
                             PCI_GPIO_CTRL_8PORT)) {
-                               str = "Quadcable";
                                ports_per_aiop = 4;
                                rocketModel[i].numPorts = 4;
                        }
                }
                break;
        case PCI_DEVICE_ID_UPCI_RM3_8PORT:
-               str = "8 ports";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
                strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
@@ -2018,7 +1987,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
                break;
        case PCI_DEVICE_ID_UPCI_RM3_4PORT:
-               str = "4 ports";
                max_num_aiops = 1;
                rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
                strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
@@ -2032,21 +2000,6 @@ static __init int register_PCI(int i, struct pci_dev *dev)
                break;
        }
 
-       switch (rcktpt_type[i]) {
-       case ROCKET_TYPE_MODEM:
-               board_type = "RocketModem";
-               break;
-       case ROCKET_TYPE_MODEMII:
-               board_type = "RocketModem II";
-               break;
-       case ROCKET_TYPE_MODEMIII:
-               board_type = "RocketModem III";
-               break;
-       default:
-               board_type = "RocketPort";
-               break;
-       }
-
        if (fast_clock) {
                sClockPrescale = 0x12;  /* mod 2 (divide by 3) */
                rp_baud_base[i] = 921600;
index d89aa38c5cf04a2c0adf7959da54fcd84eaa965c..1b37626e8f13130a35dd3b4f650177660a40ec85 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/serial/21285.c
- *
  * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
  *
  * Based on drivers/char/serial.c
index 6611535f444058e782ee96b054dd890c49039d54..b40f7b90c81da53925c420f7d8e37a18a739d4dd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/8250.c
- *
  *  Driver for 8250/16550-type serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -273,7 +271,7 @@ static const struct serial8250_config uart_config[] = {
                .fifo_size      = 32,
                .tx_loadsz      = 32,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_UUE,
+               .flags          = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
        },
        [PORT_RM9000] = {
                .name           = "RM9000",
@@ -303,6 +301,14 @@ static const struct serial8250_config uart_config[] = {
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
                .flags          = UART_CAP_FIFO | UART_CAP_AFE,
        },
+       [PORT_TEGRA] = {
+               .name           = "Tegra",
+               .fifo_size      = 32,
+               .tx_loadsz      = 8,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_01,
+               .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
+       },
 };
 
 #if defined(CONFIG_MIPS_ALCHEMY)
@@ -1427,6 +1433,27 @@ static void serial8250_enable_ms(struct uart_port *port)
        serial_out(up, UART_IER, up->ier);
 }
 
+/*
+ * Clear the Tegra rx fifo after a break
+ *
+ * FIXME: This needs to become a port specific callback once we have a
+ * framework for this
+ */
+static void clear_rx_fifo(struct uart_8250_port *up)
+{
+       unsigned int status, tmout = 10000;
+       do {
+               status = serial_in(up, UART_LSR);
+               if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+                       status = serial_in(up, UART_RX);
+               else
+                       break;
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       } while (1);
+}
+
 static void
 receive_chars(struct uart_8250_port *up, unsigned int *status)
 {
@@ -1461,6 +1488,13 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
                        if (lsr & UART_LSR_BI) {
                                lsr &= ~(UART_LSR_FE | UART_LSR_PE);
                                up->port.icount.brk++;
+                               /*
+                                * If tegra port then clear the rx fifo to
+                                * accept another break/character.
+                                */
+                               if (up->port.type == PORT_TEGRA)
+                                       clear_rx_fifo(up);
+
                                /*
                                 * We do the SysRQ and SAK checking
                                 * here because otherwise the break
@@ -2405,7 +2439,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                        UART_ENABLE_MS(&up->port, termios->c_cflag))
                up->ier |= UART_IER_MSI;
        if (up->capabilities & UART_CAP_UUE)
-               up->ier |= UART_IER_UUE | UART_IER_RTOIE;
+               up->ier |= UART_IER_UUE;
+       if (up->capabilities & UART_CAP_RTOIE)
+               up->ier |= UART_IER_RTOIE;
 
        serial_out(up, UART_IER, up->ier);
 
index 6e19ea3e48d5fd851f6a0ef822d9f0302d58d06b..6edf4a6a22d4b538e188d5e615634d4a0a7a6edc 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/8250.h
- *
  *  Driver for 8250/16550-type serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -44,6 +42,7 @@ struct serial8250_config {
 #define UART_CAP_SLEEP (1 << 10)       /* UART has IER sleep */
 #define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
 #define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
+#define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, Tegra) */
 
 #define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
 #define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
index 9c10262f2469ff821a5796e1772ebb4a379af5bb..34b51c651192e8d81a6c9c9453c4a206a3405a20 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/8250_accent.c
- *
  *  Copyright (C) 2005 Russell King.
  *  Data taken from include/asm-i386/serial.h
  *
index 3bfe0f7b26fbaaeda1e6430a659388d6275a61b5..d125dc107985b28f59bb302a636a3e3aa3cc2028 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/8250_boca.c
- *
  *  Copyright (C) 2005 Russell King.
  *  Data taken from include/asm-i386/serial.h
  *
index 567143ace1596f52b00eeb624724281e2e78f6fe..bf53aabf9b5e34919c9967f6d7e94106b04738b1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/8250_exar.c
- *
  *  Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com >
  *  Based on 8250_boca.
  *
index 6375d68b791318eba0d1de0c9791995e0e1d6df2..be1582609626b433739f15879c8697fe97e9b07d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/8250_fourport.c
- *
  *  Copyright (C) 2005 Russell King.
  *  Data taken from include/asm-i386/serial.h
  *
index 7609150e7d5eeec1da05fed57c97fac82d60ce9f..a5c778e83de054d7e35c57c65b0921319e905e75 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/8250_hub6.c
- *
  *  Copyright (C) 2005 Russell King.
  *  Data taken from include/asm-i386/serial.h
  *
index d10be944ad44478818eff256d3254a0c12404c77..d20abf04541e5f43c608ba4ec53d8ef9f9033a38 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/8250_mca.c
- *
  *  Copyright (C) 2005 Russell King.
  *  Data taken from include/asm-i386/serial.h
  *
index 738cec9807d35f4d968e50ea2a8db681ac3a8799..4b4968a294b293d0b17f43024487447b40bd450a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/8250_pci.c
- *
  *  Probe module for 8250/16550-type PCI serial ports.
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -973,6 +971,14 @@ ce4100_serial_setup(struct serial_private *priv,
        return ret;
 }
 
+static int
+pci_omegapci_setup(struct serial_private *priv,
+                     struct pciserial_board *board,
+                     struct uart_port *port, int idx)
+{
+       return setup_port(priv, port, 2, idx * 8, 0);
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
                        const struct pciserial_board *board,
                        struct uart_port *port, int idx)
@@ -1012,6 +1018,8 @@ static int skip_tx_en_setup(struct serial_private *priv,
 #define PCI_DEVICE_ID_TITAN_200EI      0xA016
 #define PCI_DEVICE_ID_TITAN_200EISI    0xA017
 #define PCI_DEVICE_ID_OXSEMI_16PCI958  0x9538
+#define PCIE_DEVICE_ID_NEO_2_OX_IBM    0x00F6
+#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
@@ -1412,7 +1420,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .setup          = pci_default_setup,
        },
        /*
-        * For Oxford Semiconductor and Mainpine
+        * For Oxford Semiconductor Tornado based devices
         */
        {
                .vendor         = PCI_VENDOR_ID_OXSEMI,
@@ -1430,6 +1438,24 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .init           = pci_oxsemi_tornado_init,
                .setup          = pci_default_setup,
        },
+       {
+               .vendor         = PCI_VENDOR_ID_DIGI,
+               .device         = PCIE_DEVICE_ID_NEO_2_OX_IBM,
+               .subvendor              = PCI_SUBVENDOR_ID_IBM,
+               .subdevice              = PCI_ANY_ID,
+               .init                   = pci_oxsemi_tornado_init,
+               .setup          = pci_default_setup,
+       },
+       /*
+        * Cronyx Omega PCI (PLX-chip based)
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_PLX,
+               .device         = PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_omegapci_setup,
+        },
        /*
         * Default "match everything" terminator entry
         */
@@ -1617,6 +1643,7 @@ enum pci_board_num_t {
        pbn_ADDIDATA_PCIe_4_3906250,
        pbn_ADDIDATA_PCIe_8_3906250,
        pbn_ce4100_1_115200,
+       pbn_omegapci,
 };
 
 /*
@@ -2312,6 +2339,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
                .base_baud      = 921600,
                .reg_shift      = 2,
        },
+       [pbn_omegapci] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 115200,
+               .uart_offset    = 0x200,
+       },
 };
 
 static const struct pci_device_id softmodem_blacklist[] = {
@@ -3075,6 +3108,14 @@ static struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
                PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
                pbn_oxsemi_8_4000000 },
+
+       /*
+        * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
+        */
+       {       PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+               PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+               pbn_oxsemi_2_4000000 },
+
        /*
         * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
         * from skokodyn@yahoo.com
@@ -3801,6 +3842,12 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
                pbn_ce4100_1_115200 },
 
+       /*
+        * Cronyx Omega PCI
+        */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_omegapci },
 
        /*
         * These entries match devices with class COMMUNICATION_SERIAL,
index 4822cb50cd0f0176f4bd1c1370297c67ef5591a3..fc301f6722e1bf4d2e9788f01e702cee6e711ddd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/8250_pnp.c
- *
  *  Probe module for 8250/16550-type ISAPNP serial ports.
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
index b1f0f83b870d43d186a125e709a5d6ac097e0760..636144cea932e40b21a43cb9ceb1ba714729b79e 100644 (file)
@@ -537,7 +537,7 @@ config SERIAL_S3C6400
 
 config SERIAL_S5PV210
        tristate "Samsung S5PV210 Serial port support"
-       depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_EXYNOS4210)
+       depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210)
        select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210)
        default y
        help
@@ -1585,7 +1585,7 @@ config SERIAL_IFX6X60
          Support for the IFX6x60 modem devices on Intel MID platforms.
 
 config SERIAL_PCH_UART
-       tristate "Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH"
+       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART"
        depends on PCI
        select SERIAL_CORE
        help
@@ -1593,10 +1593,12 @@ config SERIAL_PCH_UART
          which is an IOH(Input/Output Hub) for x86 embedded processor.
          Enabling PCH_DMA, this PCH UART works as DMA mode.
 
-         This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/
-         Output Hub) which is for IVI(In-Vehicle Infotainment) use.
-         ML7213 is companion chip for Intel Atom E6xx series.
-         ML7213 is completely compatible for Intel EG20T PCH.
+         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+         Output Hub), ML7213 and ML7223.
+         ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
+         for MP(Media Phone) use.
+         ML7213/ML7223 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7223 is completely compatible for Intel EG20T PCH.
 
 config SERIAL_MSM_SMD
        bool "Enable tty device interface for some SMD ports"
@@ -1620,4 +1622,17 @@ config SERIAL_MXS_AUART_CONSOLE
        help
          Enable a MXS AUART port to be the system console.
 
+config SERIAL_XILINX_PS_UART
+       tristate "Xilinx PS UART support"
+       select SERIAL_CORE
+       help
+         This driver supports the Xilinx PS UART port.
+
+config SERIAL_XILINX_PS_UART_CONSOLE
+       bool "Xilinx PS UART console support"
+       depends on SERIAL_XILINX_PS_UART=y
+       select SERIAL_CORE_CONSOLE
+       help
+         Enable a Xilinx PS UART port to be the system console.
+
 endmenu
index 35276043d9d12589a10346085246c8f6e39e75e0..cb2628fee4c7160e20f16eec800c76642ecfe9f8 100644 (file)
@@ -95,3 +95,4 @@ obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
 obj-$(CONFIG_SERIAL_MSM_SMD)   += msm_smd_tty.o
 obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
 obj-$(CONFIG_SERIAL_LANTIQ)    += lantiq.o
+obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
index 6d5b036ac7834883e8273dd32a378f27d340aeff..50bc5a5ac6533af4d9efceb1e21882eb489914ac 100644 (file)
@@ -540,11 +540,14 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
        int i = pdev->id;
        int ret;
 
-       /* -1 emphasizes that the platform must have one port, no .N suffix */
-       if (i == -1)
-               i = 0;
+       /* if id is -1 scan for a free id and use that one */
+       if (i == -1) {
+               for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++)
+                       if (altera_uart_ports[i].port.mapbase == 0)
+                               break;
+       }
 
-       if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
+       if (i < 0 || i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
                return -EINVAL;
 
        port = &altera_uart_ports[i].port;
@@ -587,6 +590,8 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
        port->ops = &altera_uart_ops;
        port->flags = UPF_BOOT_AUTOCONF;
 
+       dev_set_drvdata(&pdev->dev, port);
+
        uart_add_one_port(&altera_uart_driver, port);
 
        return 0;
@@ -594,14 +599,13 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 
 static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
-       struct uart_port *port;
-       int i = pdev->id;
+       struct uart_port *port = dev_get_drvdata(&pdev->dev);
 
-       if (i == -1)
-               i = 0;
-
-       port = &altera_uart_ports[i].port;
-       uart_remove_one_port(&altera_uart_driver, port);
+       if (port) {
+               uart_remove_one_port(&altera_uart_driver, port);
+               dev_set_drvdata(&pdev->dev, NULL);
+               port->mapbase = 0;
+       }
 
        return 0;
 }
index d742dd2c525c1191f96290ef8897c36ac932d4b9..c0d10c4ddb7355422f0bb426e296e167663fac0b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/amba.c
- *
  *  Driver for AMBA serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
index 6deee4e546be580d298c828ceea0b9c3b56f9e19..8dc0541feecc18c2c185cead4394f5357d25eee1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/amba.c
- *
  *  Driver for AMBA serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
index f119d1761106a6b56e9e9ae348d29f9ed9b6762a..652bdac8ce8ec4a56e9cb99506d0d61744c9661b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/atmel_serial.c
- *
  *  Driver for Atmel AT91 / AT32 Serial ports
  *  Copyright (C) 2003 Rick Bronson
  *
index b6acd19b458e91b08f973d438cf45506e5dc1270..e6c3dbd781d61fd21e9dcafd3d85c1a0799f1f66 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/clps711x.c
- *
  *  Driver for CLPS711x serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
index b754dcf0fda5317624da6804dee392fa3b487a9a..cf34d26ff6cdd642849fe61ae0f60af71ed04f94 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/cpm_uart.h
- *
  *  Driver for CPM (SCC/SMC) serial ports
  *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
index a9a6a5fd169ecfac48d6311be190ff6655a7b718..9488da74d4f717dc885ff928105aab467777e833 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/cpm_uart.c
- *
  *  Driver for CPM (SCC/SMC) serial ports; core driver
  *
  *  Based on arch/ppc/cpm2_io/uart.c by Dan Malek
index 3fc1d66e32c651cbcca46808a4aa1fac7ba9ca85..18f79575894a2c036f8eace28a8aa8d70924ee56 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/cpm_uart.c
- *
  *  Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
  *
  *  Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
index 10eecd6af6d4e913adb7563351131f68525744be..60c7e94cde1e2eee65afdf65e5c2f62448291a1d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/serial/cpm_uart/cpm_uart_cpm1.h
- *
  * Driver for CPM (SCC/SMC) serial ports
  *
  * definitions for cpm1
index 814ac006393fabac29f97d0f3cb129fe125f1ee3..a4927e66e7418de329f930bad1d50afe8fbf93d1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/cpm_uart_cpm2.c
- *
  *  Driver for CPM (SCC/SMC) serial ports; CPM2 definitions
  *
  *  Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
index 7194c63dcf5f0d436f834394829d8e62268ba682..51e651a699389b0d9dcc4b9be230f46cf986a18a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/serial/cpm_uart/cpm_uart_cpm2.h
- *
  * Driver for CPM (SCC/SMC) serial ports
  *
  * definitions for cpm2
index 8ee5a41d340d84a74908686bd5e55ab1633ec99f..5315525220fb24370399e785bf73ad1bf3f150bb 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/tty.h>
 #include <linux/device.h>
 #include <linux/spi/spi.h>
-#include <linux/tty.h>
 #include <linux/kfifo.h>
 #include <linux/tty_flip.h>
 #include <linux/timer.h>
@@ -56,7 +55,6 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/wait.h>
-#include <linux/tty.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/ifx_modem.h>
index 62df72d9f0aa32bef8a58a19f447dea922bdd18a..a54473123e0aad5c02e8e33177007b4b843cbb96 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/imx.c
- *
  *  Driver for Motorola IMX serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
index bfee9b4c66611045132893e1efcb6e8a8a925714..e6ba83876508e9318843757b15f3b3cba4e77f1c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/serial/msm_serial.c - driver for msm7k serial device and console
+ * Driver for msm7k serial device and console
  *
  * Copyright (C) 2007 Google, Inc.
  * Author: Robert Love <rlove@google.com>
index 9b8dc5d0d85546e70aa978dc4381fea752f07812..e4acef5de77ef82f01d45add56d8646d8ba2f50d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/serial/msm_serial.h
- *
  * Copyright (C) 2007 Google, Inc.
  * Author: Robert Love <rlove@google.com>
  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
index beeff1e86093b220c6d4712f5f97e62deefc179a..4f41dcdcb7719767a790f7bc98f654a3895ead38 100644 (file)
@@ -1,5 +1,4 @@
-/* drivers/tty/serial/msm_smd_tty.c
- *
+/*
  * Copyright (C) 2007 Google, Inc.
  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
index 7735c9f35fa09e6d9732f5ee4b84cee1c6b89ea9..d40da78e7c8513fb7fc8f1064ffda22e5827280e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/serial/netx-serial.c
- *
  * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  *
  * This program is free software; you can redistribute it and/or modify
index 26403b8e4b9b51ac7aaf941d49d40281401e00ed..c63d0d152af675fa15e78dee69844640309eabc8 100644 (file)
@@ -253,6 +253,8 @@ enum pch_uart_num_t {
        pch_ml7213_uart0,
        pch_ml7213_uart1,
        pch_ml7213_uart2,
+       pch_ml7223_uart0,
+       pch_ml7223_uart1,
 };
 
 static struct pch_uart_driver_data drv_dat[] = {
@@ -263,6 +265,8 @@ static struct pch_uart_driver_data drv_dat[] = {
        [pch_ml7213_uart0] = {PCH_UART_8LINE, 0},
        [pch_ml7213_uart1] = {PCH_UART_2LINE, 1},
        [pch_ml7213_uart2] = {PCH_UART_2LINE, 2},
+       [pch_ml7223_uart0] = {PCH_UART_8LINE, 0},
+       [pch_ml7223_uart1] = {PCH_UART_2LINE, 1},
 };
 
 static unsigned int default_baud = 9600;
@@ -1534,6 +1538,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
         .driver_data = pch_ml7213_uart1},
        {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029),
         .driver_data = pch_ml7213_uart2},
+       {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800C),
+        .driver_data = pch_ml7223_uart0},
+       {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),
+        .driver_data = pch_ml7223_uart1},
        {0,},
 };
 
index e1c8d4f1ce587dafe85febe3a70cd3b44f387545..5acd24a27d087fd510e84b514c19c35c6de40ab1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/serial/pmac_zilog.c
- * 
  * Driver for PowerMac Z85c30 based ESCC cell found in the
  * "macio" ASICs of various PowerMac models
  * 
index 1102a39b44f5497c4daf4512123ba49fbeb9cf54..4302e6e3768e504d76f63d2be40198195c303290 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/serial/pxa.c
- *
  *  Based on drivers/serial/8250.c by Russell King.
  *
  *  Author:    Nicolas Pitre
index fed1a9a1ffb4e7db9aedae7ff0b498ed933e27f7..d13051b3df87e1d0bcb11e36f5729354f52d0160 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c240.c
- *
+/*
  * Driver for Samsung SoC onboard UARTs.
  *
  * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics
index 73f089d3efd66225bef4af3fb94b56530de93c84..bffe6ff9b1589d5d7a35bb5726d2476f2a5dead5 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c2410.c
- *
+/*
  * Driver for Samsung S3C2410 SoC onboard UARTs.
  *
  * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
index 1700b1a2fb7e03cf6c6a2b9fa600a240f9e632f5..7e2b9504a68732c73c645f564b39bc77436b37b6 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c2412.c
- *
+/*
  * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs.
  *
  * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
index 094cc3904b1385b8265ceb05b81bdf241577ea48..9e10d415d5fd2c90e3cfe778fb2e64d598887fcc 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c2440.c
- *
+/*
  * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs.
  *
  * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
index fad6083ca42716af9e1ad615862928dc2d767e10..914eff22e499394f337936745a35239718d9f7c1 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c24a0.c
- *
+/*
  * Driver for Samsung S3C24A0 SoC onboard UARTs.
  *
  * Based on drivers/serial/s3c2410.c
index 4be92ab50058284f0cf823bf4ed4ab10b5c80be9..ded26c42ff37e4260c2911d72d66ff3477d2e016 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s3c6400.c
- *
+/*
  * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
  *
  * Copyright 2008 Openmoko,  Inc.
index 6ebccd70a7073d0e56e098b7598fa11e02a9bd10..fb2619f93d84e25424dc551def7a33ae56710041 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/s5pv210.c
- *
+/*
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
index 2199d819a9870b2d8d52d4ab8bb6ae6832d56c00..ef7a21a6a01b1997702c49a7559b13f03007c0d7 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/sa1100.c
- *
  *  Driver for SA11x0 serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
index 9e2fa8d784e2aff4f33f12264ddb408441e82fe0..f66f6482930363a9cbd2b69af11588021970cbfe 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/samsuing.c
- *
+/*
  * Driver core for Samsung SoC onboard UARTs.
  *
  * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
index 0ac06a07d25ffd4b41010bcba9448588d1fa6e19..5b098cd7604096af3dc3f9992b424d11055911f2 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/drivers/serial/samsung.h
- *
+/*
  * Driver for Samsung SoC onboard UARTs.
  *
  * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
index 602d9845c52ffa97c00951ad395e504af602cf83..ea2340b814e9392e2c5d1e693e1a14bbbd4b694f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     drivers/serial/sb1250-duart.c
- *
  *     Support for the asynchronous serial interface (DUART) included
  *     in the BCM1250 and derived System-On-a-Chip (SOC) devices.
  *
index 733fe8e73f0fcf4782f544d3c8205da88848a37b..db7912cb7ae041a71a901437d3c835ee242530a9 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/core.c
- *
  *  Driver core for serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
@@ -172,12 +170,16 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in
 
        retval = uport->ops->startup(uport);
        if (retval == 0) {
-               if (init_hw) {
-                       /*
-                        * Initialise the hardware port settings.
-                        */
-                       uart_change_speed(tty, state, NULL);
+               if (uart_console(uport) && uport->cons->cflag) {
+                       tty->termios->c_cflag = uport->cons->cflag;
+                       uport->cons->cflag = 0;
+               }
+               /*
+                * Initialise the hardware port settings.
+                */
+               uart_change_speed(tty, state, NULL);
 
+               if (init_hw) {
                        /*
                         * Setup the RTS and DTR signals once the
                         * port is open and ready to respond.
@@ -1240,17 +1242,6 @@ static void uart_set_termios(struct tty_struct *tty,
                }
                spin_unlock_irqrestore(&state->uart_port->lock, flags);
        }
-#if 0
-       /*
-        * No need to wake up processes in open wait, since they
-        * sample the CLOCAL flag once, and don't recheck it.
-        * XXX  It's not clear whether the current behavior is correct
-        * or not.  Hence, this may change.....
-        */
-       if (!(old_termios->c_cflag & CLOCAL) &&
-           (tty->termios->c_cflag & CLOCAL))
-               wake_up_interruptible(&state->uart_port.open_wait);
-#endif
 }
 
 /*
@@ -1423,7 +1414,6 @@ static void __uart_wait_until_sent(struct uart_port *port, int timeout)
                if (time_after(jiffies, expire))
                        break;
        }
-       set_current_state(TASK_RUNNING); /* might not be needed */
 }
 
 static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -1466,45 +1456,6 @@ static void uart_hangup(struct tty_struct *tty)
        mutex_unlock(&port->mutex);
 }
 
-/**
- *     uart_update_termios     -       update the terminal hw settings
- *     @tty: tty associated with UART
- *     @state: UART to update
- *
- *     Copy across the serial console cflag setting into the termios settings
- *     for the initial open of the port.  This allows continuity between the
- *     kernel settings, and the settings init adopts when it opens the port
- *     for the first time.
- */
-static void uart_update_termios(struct tty_struct *tty,
-                                               struct uart_state *state)
-{
-       struct uart_port *port = state->uart_port;
-
-       if (uart_console(port) && port->cons->cflag) {
-               tty->termios->c_cflag = port->cons->cflag;
-               port->cons->cflag = 0;
-       }
-
-       /*
-        * If the device failed to grab its irq resources,
-        * or some other error occurred, don't try to talk
-        * to the port hardware.
-        */
-       if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-               /*
-                * Make termios settings take effect.
-                */
-               uart_change_speed(tty, state, NULL);
-
-               /*
-                * And finally enable the RTS and DTR signals.
-                */
-               if (tty->termios->c_cflag & CBAUD)
-                       uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-       }
-}
-
 static int uart_carrier_raised(struct tty_port *port)
 {
        struct uart_state *state = container_of(port, struct uart_state, port);
@@ -1524,16 +1475,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)
        struct uart_state *state = container_of(port, struct uart_state, port);
        struct uart_port *uport = state->uart_port;
 
-       if (onoff) {
+       if (onoff)
                uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
-
-               /*
-                * If this is the first open to succeed,
-                * adjust things to suit.
-                */
-               if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
-                       uart_update_termios(port->tty, state);
-       }
        else
                uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 }
@@ -1585,15 +1528,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
        BUG_ON(!tty_locked());
        pr_debug("uart_open(%d) called\n", line);
 
-       /*
-        * tty->driver->num won't change, so we won't fail here with
-        * tty->driver_data set to something non-NULL (and therefore
-        * we won't get caught by uart_close()).
-        */
-       retval = -ENODEV;
-       if (line >= tty->driver->num)
-               goto fail;
-
        /*
         * We take the semaphore inside uart_get to guarantee that we won't
         * be re-entered while allocating the state structure, or while we
@@ -1972,13 +1906,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
        struct tty_port *port = &state->port;
        struct device *tty_dev;
        struct uart_match match = {uport, drv};
-       struct tty_struct *tty;
 
        mutex_lock(&port->mutex);
 
-       /* Must be inside the mutex lock until we convert to tty_port */
-       tty = port->tty;
-
        tty_dev = device_find_child(uport->dev, &match, serial_match_port);
        if (device_may_wakeup(tty_dev)) {
                if (!enable_irq_wake(uport->irq))
index b1962025b1aa7f79a381a58bd1d2ce56909ab180..2430319f2f52eb2301cbfc3991e310c1a9e0ecbd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/serial/serial_ks8695.c
- *
  *  Driver for KS8695 serial ports
  *
  *  Based on drivers/serial/serial_amba.c, by Kam Lee.
index c50e9fbbf743cbf5aa98f164afc759fd305e46d4..8e3fc1944e6d9fc671ccb3150532d74be3bc1f6d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/serial/serial_txx9.c
- *
  * Derived from many drivers using generic_serial interface,
  * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c
  * (was in Linux/VR tree) by Jim Pick.
index 920a6f929c8b62ec1dab5dff99f9b11bf044e39b..f35b8fb94b8383aceded2aaa983a75edee39126c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/serial/sh-sci.c
- *
  * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
  *
  *  Copyright (C) 2002 - 2011  Paul Mundt
index 322bf56c0d89ded465510a5a22a5f73b62b7a3e9..37fc4e3d487c5f0ce53da3df7e59781134ef875a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/serial/vt8500_serial.c
- *
  * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
  *
  * Based on msm_serial.c, which is:
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
new file mode 100644 (file)
index 0000000..19cc1e8
--- /dev/null
@@ -0,0 +1,1113 @@
+/*
+ * Xilinx PS UART driver
+ *
+ * 2011 (c) Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any
+ * later version.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#define XUARTPS_TTY_NAME       "ttyPS"
+#define XUARTPS_NAME           "xuartps"
+#define XUARTPS_MAJOR          0       /* use dynamic node allocation */
+#define XUARTPS_MINOR          0       /* works best with devtmpfs */
+#define XUARTPS_NR_PORTS       2
+#define XUARTPS_FIFO_SIZE      16      /* FIFO size */
+#define XUARTPS_REGISTER_SPACE 0xFFF
+
+#define xuartps_readl(offset)          ioread32(port->membase + offset)
+#define xuartps_writel(val, offset)    iowrite32(val, port->membase + offset)
+
+/********************************Register Map********************************/
+/** UART
+ *
+ * Register offsets for the UART.
+ *
+ */
+#define XUARTPS_CR_OFFSET      0x00  /* Control Register [8:0] */
+#define XUARTPS_MR_OFFSET      0x04  /* Mode Register [10:0] */
+#define XUARTPS_IER_OFFSET     0x08  /* Interrupt Enable [10:0] */
+#define XUARTPS_IDR_OFFSET     0x0C  /* Interrupt Disable [10:0] */
+#define XUARTPS_IMR_OFFSET     0x10  /* Interrupt Mask [10:0] */
+#define XUARTPS_ISR_OFFSET     0x14  /* Interrupt Status [10:0]*/
+#define XUARTPS_BAUDGEN_OFFSET 0x18  /* Baud Rate Generator [15:0] */
+#define XUARTPS_RXTOUT_OFFSET  0x1C  /* RX Timeout [7:0] */
+#define XUARTPS_RXWM_OFFSET    0x20  /* RX FIFO Trigger Level [5:0] */
+#define XUARTPS_MODEMCR_OFFSET 0x24  /* Modem Control [5:0] */
+#define XUARTPS_MODEMSR_OFFSET 0x28  /* Modem Status [8:0] */
+#define XUARTPS_SR_OFFSET      0x2C  /* Channel Status [11:0] */
+#define XUARTPS_FIFO_OFFSET    0x30  /* FIFO [15:0] or [7:0] */
+#define XUARTPS_BAUDDIV_OFFSET 0x34  /* Baud Rate Divider [7:0] */
+#define XUARTPS_FLOWDEL_OFFSET 0x38  /* Flow Delay [15:0] */
+#define XUARTPS_IRRX_PWIDTH_OFFSET 0x3C /* IR Minimum Received Pulse
+                                               Width [15:0] */
+#define XUARTPS_IRTX_PWIDTH_OFFSET 0x40 /* IR Transmitted pulse
+                                               Width [7:0] */
+#define XUARTPS_TXWM_OFFSET    0x44  /* TX FIFO Trigger Level [5:0] */
+
+/** Control Register
+ *
+ * The Control register (CR) controls the major functions of the device.
+ *
+ * Control Register Bit Definitions
+ */
+#define XUARTPS_CR_STOPBRK     0x00000100  /* Stop TX break */
+#define XUARTPS_CR_STARTBRK    0x00000080  /* Set TX break */
+#define XUARTPS_CR_TX_DIS      0x00000020  /* TX disabled. */
+#define XUARTPS_CR_TX_EN       0x00000010  /* TX enabled */
+#define XUARTPS_CR_RX_DIS      0x00000008  /* RX disabled. */
+#define XUARTPS_CR_RX_EN       0x00000004  /* RX enabled */
+#define XUARTPS_CR_TXRST       0x00000002  /* TX logic reset */
+#define XUARTPS_CR_RXRST       0x00000001  /* RX logic reset */
+#define XUARTPS_CR_RST_TO      0x00000040  /* Restart Timeout Counter */
+
+/** Mode Register
+ *
+ * The mode register (MR) defines the mode of transfer as well as the data
+ * format. If this register is modified during transmission or reception,
+ * data validity cannot be guaranteed.
+ *
+ * Mode Register Bit Definitions
+ *
+ */
+#define XUARTPS_MR_CLKSEL              0x00000001  /* Pre-scalar selection */
+#define XUARTPS_MR_CHMODE_L_LOOP       0x00000200  /* Local loop back mode */
+#define XUARTPS_MR_CHMODE_NORM         0x00000000  /* Normal mode */
+
+#define XUARTPS_MR_STOPMODE_2_BIT      0x00000080  /* 2 stop bits */
+#define XUARTPS_MR_STOPMODE_1_BIT      0x00000000  /* 1 stop bit */
+
+#define XUARTPS_MR_PARITY_NONE         0x00000020  /* No parity mode */
+#define XUARTPS_MR_PARITY_MARK         0x00000018  /* Mark parity mode */
+#define XUARTPS_MR_PARITY_SPACE                0x00000010  /* Space parity mode */
+#define XUARTPS_MR_PARITY_ODD          0x00000008  /* Odd parity mode */
+#define XUARTPS_MR_PARITY_EVEN         0x00000000  /* Even parity mode */
+
+#define XUARTPS_MR_CHARLEN_6_BIT       0x00000006  /* 6 bits data */
+#define XUARTPS_MR_CHARLEN_7_BIT       0x00000004  /* 7 bits data */
+#define XUARTPS_MR_CHARLEN_8_BIT       0x00000000  /* 8 bits data */
+
+/** Interrupt Registers
+ *
+ * Interrupt control logic uses the interrupt enable register (IER) and the
+ * interrupt disable register (IDR) to set the value of the bits in the
+ * interrupt mask register (IMR). The IMR determines whether to pass an
+ * interrupt to the interrupt status register (ISR).
+ * Writing a 1 to IER Enables an interrupt, writing a 1 to IDR disables an
+ * interrupt. IMR and ISR are read only, and IER and IDR are write only.
+ * Reading either IER or IDR returns 0x00.
+ *
+ * All four registers have the same bit definitions.
+ */
+#define XUARTPS_IXR_TOUT       0x00000100 /* RX Timeout error interrupt */
+#define XUARTPS_IXR_PARITY     0x00000080 /* Parity error interrupt */
+#define XUARTPS_IXR_FRAMING    0x00000040 /* Framing error interrupt */
+#define XUARTPS_IXR_OVERRUN    0x00000020 /* Overrun error interrupt */
+#define XUARTPS_IXR_TXFULL     0x00000010 /* TX FIFO Full interrupt */
+#define XUARTPS_IXR_TXEMPTY    0x00000008 /* TX FIFO empty interrupt */
+#define XUARTPS_ISR_RXEMPTY    0x00000002 /* RX FIFO empty interrupt */
+#define XUARTPS_IXR_RXTRIG     0x00000001 /* RX FIFO trigger interrupt */
+#define XUARTPS_IXR_RXFULL     0x00000004 /* RX FIFO full interrupt. */
+#define XUARTPS_IXR_RXEMPTY    0x00000002 /* RX FIFO empty interrupt. */
+#define XUARTPS_IXR_MASK       0x00001FFF /* Valid bit mask */
+
+/** Channel Status Register
+ *
+ * The channel status register (CSR) is provided to enable the control logic
+ * to monitor the status of bits in the channel interrupt status register,
+ * even if these are masked out by the interrupt mask register.
+ */
+#define XUARTPS_SR_RXEMPTY     0x00000002 /* RX FIFO empty */
+#define XUARTPS_SR_TXEMPTY     0x00000008 /* TX FIFO empty */
+#define XUARTPS_SR_TXFULL      0x00000010 /* TX FIFO full */
+#define XUARTPS_SR_RXTRIG      0x00000001 /* Rx Trigger */
+
+/**
+ * xuartps_isr - Interrupt handler
+ * @irq: Irq number
+ * @dev_id: Id of the port
+ *
+ * Returns IRQHANDLED
+ **/
+static irqreturn_t xuartps_isr(int irq, void *dev_id)
+{
+       struct uart_port *port = (struct uart_port *)dev_id;
+       struct tty_struct *tty;
+       unsigned long flags;
+       unsigned int isrstatus, numbytes;
+       unsigned int data;
+       char status = TTY_NORMAL;
+
+       /* Get the tty which could be NULL so don't assume it's valid */
+       tty = tty_port_tty_get(&port->state->port);
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       /* Read the interrupt status register to determine which
+        * interrupt(s) is/are active.
+        */
+       isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET);
+
+       /* drop byte with parity error if IGNPAR specified */
+       if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY)
+               isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT);
+
+       isrstatus &= port->read_status_mask;
+       isrstatus &= ~port->ignore_status_mask;
+
+       if ((isrstatus & XUARTPS_IXR_TOUT) ||
+               (isrstatus & XUARTPS_IXR_RXTRIG)) {
+               /* Receive Timeout Interrupt */
+               while ((xuartps_readl(XUARTPS_SR_OFFSET) &
+                       XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
+                       data = xuartps_readl(XUARTPS_FIFO_OFFSET);
+                       port->icount.rx++;
+
+                       if (isrstatus & XUARTPS_IXR_PARITY) {
+                               port->icount.parity++;
+                               status = TTY_PARITY;
+                       } else if (isrstatus & XUARTPS_IXR_FRAMING) {
+                               port->icount.frame++;
+                               status = TTY_FRAME;
+                       } else if (isrstatus & XUARTPS_IXR_OVERRUN)
+                               port->icount.overrun++;
+
+                       if (tty)
+                               uart_insert_char(port, isrstatus,
+                                               XUARTPS_IXR_OVERRUN, data,
+                                               status);
+               }
+               spin_unlock(&port->lock);
+               if (tty)
+                       tty_flip_buffer_push(tty);
+               spin_lock(&port->lock);
+       }
+
+       /* Dispatch an appropriate handler */
+       if ((isrstatus & XUARTPS_IXR_TXEMPTY) == XUARTPS_IXR_TXEMPTY) {
+               if (uart_circ_empty(&port->state->xmit)) {
+                       xuartps_writel(XUARTPS_IXR_TXEMPTY,
+                                               XUARTPS_IDR_OFFSET);
+               } else {
+                       numbytes = port->fifosize;
+                       /* Break if no more data available in the UART buffer */
+                       while (numbytes--) {
+                               if (uart_circ_empty(&port->state->xmit))
+                                       break;
+                               /* Get the data from the UART circular buffer
+                                * and write it to the xuartps's TX_FIFO
+                                * register.
+                                */
+                               xuartps_writel(
+                                       port->state->xmit.buf[port->state->xmit.
+                                       tail], XUARTPS_FIFO_OFFSET);
+
+                               port->icount.tx++;
+
+                               /* Adjust the tail of the UART buffer and wrap
+                                * the buffer if it reaches limit.
+                                */
+                               port->state->xmit.tail =
+                                       (port->state->xmit.tail + 1) & \
+                                               (UART_XMIT_SIZE - 1);
+                       }
+
+                       if (uart_circ_chars_pending(
+                                       &port->state->xmit) < WAKEUP_CHARS)
+                               uart_write_wakeup(port);
+               }
+       }
+
+       xuartps_writel(isrstatus, XUARTPS_ISR_OFFSET);
+
+       /* be sure to release the lock and tty before leaving */
+       spin_unlock_irqrestore(&port->lock, flags);
+       tty_kref_put(tty);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * xuartps_set_baud_rate - Calculate and set the baud rate
+ * @port: Handle to the uart port structure
+ * @baud: Baud rate to set
+ *
+ * Returns baud rate, requested baud when possible, or actual baud when there
+ *     was too much error
+ **/
+static unsigned int xuartps_set_baud_rate(struct uart_port *port,
+                                               unsigned int baud)
+{
+       unsigned int sel_clk;
+       unsigned int calc_baud = 0;
+       unsigned int brgr_val, brdiv_val;
+       unsigned int bauderror;
+
+       /* Formula to obtain baud rate is
+        *      baud_tx/rx rate = sel_clk/CD * (BDIV + 1)
+        *      input_clk = (Uart User Defined Clock or Apb Clock)
+        *              depends on UCLKEN in MR Reg
+        *      sel_clk = input_clk or input_clk/8;
+        *              depends on CLKS in MR reg
+        *      CD and BDIV depends on values in
+        *                      baud rate generate register
+        *                      baud rate clock divisor register
+        */
+       sel_clk = port->uartclk;
+       if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL)
+               sel_clk = sel_clk / 8;
+
+       /* Find the best values for baud generation */
+       for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) {
+
+               brgr_val = sel_clk / (baud * (brdiv_val + 1));
+               if (brgr_val < 2 || brgr_val > 65535)
+                       continue;
+
+               calc_baud = sel_clk / (brgr_val * (brdiv_val + 1));
+
+               if (baud > calc_baud)
+                       bauderror = baud - calc_baud;
+               else
+                       bauderror = calc_baud - baud;
+
+               /* use the values when percent error is acceptable */
+               if (((bauderror * 100) / baud) < 3) {
+                       calc_baud = baud;
+                       break;
+               }
+       }
+
+       /* Set the values for the new baud rate */
+       xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET);
+       xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET);
+
+       return calc_baud;
+}
+
+/*----------------------Uart Operations---------------------------*/
+
+/**
+ * xuartps_start_tx -  Start transmitting bytes
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_start_tx(struct uart_port *port)
+{
+       unsigned int status, numbytes = port->fifosize;
+
+       if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port))
+               return;
+
+       status = xuartps_readl(XUARTPS_CR_OFFSET);
+       /* Set the TX enable bit and clear the TX disable bit to enable the
+        * transmitter.
+        */
+       xuartps_writel((status & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN,
+               XUARTPS_CR_OFFSET);
+
+       while (numbytes-- && ((xuartps_readl(XUARTPS_SR_OFFSET)
+               & XUARTPS_SR_TXFULL)) != XUARTPS_SR_TXFULL) {
+
+               /* Break if no more data available in the UART buffer */
+               if (uart_circ_empty(&port->state->xmit))
+                       break;
+
+               /* Get the data from the UART circular buffer and
+                * write it to the xuartps's TX_FIFO register.
+                */
+               xuartps_writel(
+                       port->state->xmit.buf[port->state->xmit.tail],
+                       XUARTPS_FIFO_OFFSET);
+               port->icount.tx++;
+
+               /* Adjust the tail of the UART buffer and wrap
+                * the buffer if it reaches limit.
+                */
+               port->state->xmit.tail = (port->state->xmit.tail + 1) &
+                                       (UART_XMIT_SIZE - 1);
+       }
+
+       /* Enable the TX Empty interrupt */
+       xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET);
+
+       if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+}
+
+/**
+ * xuartps_stop_tx - Stop TX
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_stop_tx(struct uart_port *port)
+{
+       unsigned int regval;
+
+       regval = xuartps_readl(XUARTPS_CR_OFFSET);
+       regval |= XUARTPS_CR_TX_DIS;
+       /* Disable the transmitter */
+       xuartps_writel(regval, XUARTPS_CR_OFFSET);
+}
+
+/**
+ * xuartps_stop_rx - Stop RX
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_stop_rx(struct uart_port *port)
+{
+       unsigned int regval;
+
+       regval = xuartps_readl(XUARTPS_CR_OFFSET);
+       regval |= XUARTPS_CR_RX_DIS;
+       /* Disable the receiver */
+       xuartps_writel(regval, XUARTPS_CR_OFFSET);
+}
+
+/**
+ * xuartps_tx_empty -  Check whether TX is empty
+ * @port: Handle to the uart port structure
+ *
+ * Returns TIOCSER_TEMT on success, 0 otherwise
+ **/
+static unsigned int xuartps_tx_empty(struct uart_port *port)
+{
+       unsigned int status;
+
+       status = xuartps_readl(XUARTPS_ISR_OFFSET) & XUARTPS_IXR_TXEMPTY;
+       return status ? TIOCSER_TEMT : 0;
+}
+
+/**
+ * xuartps_break_ctl - Based on the input ctl we have to start or stop
+ *                     transmitting char breaks
+ * @port: Handle to the uart port structure
+ * @ctl: Value based on which start or stop decision is taken
+ *
+ **/
+static void xuartps_break_ctl(struct uart_port *port, int ctl)
+{
+       unsigned int status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       status = xuartps_readl(XUARTPS_CR_OFFSET);
+
+       if (ctl == -1)
+               xuartps_writel(XUARTPS_CR_STARTBRK | status,
+                                       XUARTPS_CR_OFFSET);
+       else {
+               if ((status & XUARTPS_CR_STOPBRK) == 0)
+                       xuartps_writel(XUARTPS_CR_STOPBRK | status,
+                                        XUARTPS_CR_OFFSET);
+       }
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/**
+ * xuartps_set_termios - termios operations, handling data length, parity,
+ *                             stop bits, flow control, baud rate
+ * @port: Handle to the uart port structure
+ * @termios: Handle to the input termios structure
+ * @old: Values of the previously saved termios structure
+ *
+ **/
+static void xuartps_set_termios(struct uart_port *port,
+                               struct ktermios *termios, struct ktermios *old)
+{
+       unsigned int cval = 0;
+       unsigned int baud;
+       unsigned long flags;
+       unsigned int ctrl_reg, mode_reg;
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       /* Empty the receive FIFO 1st before making changes */
+       while ((xuartps_readl(XUARTPS_SR_OFFSET) &
+                XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
+               xuartps_readl(XUARTPS_FIFO_OFFSET);
+       }
+
+       /* Disable the TX and RX to set baud rate */
+       xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+                       (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS),
+                       XUARTPS_CR_OFFSET);
+
+       /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */
+       baud = uart_get_baud_rate(port, termios, old, 0, 10000000);
+       baud = xuartps_set_baud_rate(port, baud);
+       if (tty_termios_baud_rate(termios))
+               tty_termios_encode_baud_rate(termios, baud, baud);
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       /* Set TX/RX Reset */
+       xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+                       (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
+                       XUARTPS_CR_OFFSET);
+
+       ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
+
+       /* Clear the RX disable and TX disable bits and then set the TX enable
+        * bit and RX enable bit to enable the transmitter and receiver.
+        */
+       xuartps_writel(
+               (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS))
+                       | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
+                       XUARTPS_CR_OFFSET);
+
+       xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
+
+       port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG |
+                       XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT;
+       port->ignore_status_mask = 0;
+
+       if (termios->c_iflag & INPCK)
+               port->read_status_mask |= XUARTPS_IXR_PARITY |
+               XUARTPS_IXR_FRAMING;
+
+       if (termios->c_iflag & IGNPAR)
+               port->ignore_status_mask |= XUARTPS_IXR_PARITY |
+                       XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN;
+
+       /* ignore all characters if CREAD is not set */
+       if ((termios->c_cflag & CREAD) == 0)
+               port->ignore_status_mask |= XUARTPS_IXR_RXTRIG |
+                       XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY |
+                       XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN;
+
+       mode_reg = xuartps_readl(XUARTPS_MR_OFFSET);
+
+       /* Handling Data Size */
+       switch (termios->c_cflag & CSIZE) {
+       case CS6:
+               cval |= XUARTPS_MR_CHARLEN_6_BIT;
+               break;
+       case CS7:
+               cval |= XUARTPS_MR_CHARLEN_7_BIT;
+               break;
+       default:
+       case CS8:
+               cval |= XUARTPS_MR_CHARLEN_8_BIT;
+               termios->c_cflag &= ~CSIZE;
+               termios->c_cflag |= CS8;
+               break;
+       }
+
+       /* Handling Parity and Stop Bits length */
+       if (termios->c_cflag & CSTOPB)
+               cval |= XUARTPS_MR_STOPMODE_2_BIT; /* 2 STOP bits */
+       else
+               cval |= XUARTPS_MR_STOPMODE_1_BIT; /* 1 STOP bit */
+
+       if (termios->c_cflag & PARENB) {
+               /* Mark or Space parity */
+               if (termios->c_cflag & CMSPAR) {
+                       if (termios->c_cflag & PARODD)
+                               cval |= XUARTPS_MR_PARITY_MARK;
+                       else
+                               cval |= XUARTPS_MR_PARITY_SPACE;
+               } else if (termios->c_cflag & PARODD)
+                               cval |= XUARTPS_MR_PARITY_ODD;
+                       else
+                               cval |= XUARTPS_MR_PARITY_EVEN;
+       } else
+               cval |= XUARTPS_MR_PARITY_NONE;
+       xuartps_writel(cval , XUARTPS_MR_OFFSET);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/**
+ * xuartps_startup - Called when an application opens a xuartps port
+ * @port: Handle to the uart port structure
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int xuartps_startup(struct uart_port *port)
+{
+       unsigned int retval = 0, status = 0;
+
+       retval = request_irq(port->irq, xuartps_isr, 0, XUARTPS_NAME,
+                                                               (void *)port);
+       if (retval)
+               return retval;
+
+       /* Disable the TX and RX */
+       xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS,
+                                               XUARTPS_CR_OFFSET);
+
+       /* Set the Control Register with TX/RX Enable, TX/RX Reset,
+        * no break chars.
+        */
+       xuartps_writel(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST,
+                               XUARTPS_CR_OFFSET);
+
+       status = xuartps_readl(XUARTPS_CR_OFFSET);
+
+       /* Clear the RX disable and TX disable bits and then set the TX enable
+        * bit and RX enable bit to enable the transmitter and receiver.
+        */
+       xuartps_writel((status & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS))
+                       | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN |
+                       XUARTPS_CR_STOPBRK), XUARTPS_CR_OFFSET);
+
+       /* Set the Mode Register with normal mode,8 data bits,1 stop bit,
+        * no parity.
+        */
+       xuartps_writel(XUARTPS_MR_CHMODE_NORM | XUARTPS_MR_STOPMODE_1_BIT
+               | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT,
+                XUARTPS_MR_OFFSET);
+
+       /* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */
+       xuartps_writel(14, XUARTPS_RXWM_OFFSET);
+
+       /* Receive Timeout register is enabled with value of 10 */
+       xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
+
+
+       /* Set the Interrupt Registers with desired interrupts */
+       xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
+               XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
+               XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
+       xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
+               XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
+               XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET);
+
+       return retval;
+}
+
+/**
+ * xuartps_shutdown - Called when an application closes a xuartps port
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_shutdown(struct uart_port *port)
+{
+       int status;
+
+       /* Disable interrupts */
+       status = xuartps_readl(XUARTPS_IMR_OFFSET);
+       xuartps_writel(status, XUARTPS_IDR_OFFSET);
+
+       /* Disable the TX and RX */
+       xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS,
+                                XUARTPS_CR_OFFSET);
+       free_irq(port->irq, port);
+}
+
+/**
+ * xuartps_type - Set UART type to xuartps port
+ * @port: Handle to the uart port structure
+ *
+ * Returns string on success, NULL otherwise
+ **/
+static const char *xuartps_type(struct uart_port *port)
+{
+       return port->type == PORT_XUARTPS ? XUARTPS_NAME : NULL;
+}
+
+/**
+ * xuartps_verify_port - Verify the port params
+ * @port: Handle to the uart port structure
+ * @ser: Handle to the structure whose members are compared
+ *
+ * Returns 0 if success otherwise -EINVAL
+ **/
+static int xuartps_verify_port(struct uart_port *port,
+                                       struct serial_struct *ser)
+{
+       if (ser->type != PORT_UNKNOWN && ser->type != PORT_XUARTPS)
+               return -EINVAL;
+       if (port->irq != ser->irq)
+               return -EINVAL;
+       if (ser->io_type != UPIO_MEM)
+               return -EINVAL;
+       if (port->iobase != ser->port)
+               return -EINVAL;
+       if (ser->hub6 != 0)
+               return -EINVAL;
+       return 0;
+}
+
+/**
+ * xuartps_request_port - Claim the memory region attached to xuartps port,
+ *                             called when the driver adds a xuartps port via
+ *                             uart_add_one_port()
+ * @port: Handle to the uart port structure
+ *
+ * Returns 0, -ENOMEM if request fails
+ **/
+static int xuartps_request_port(struct uart_port *port)
+{
+       if (!request_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE,
+                                        XUARTPS_NAME)) {
+               return -ENOMEM;
+       }
+
+       port->membase = ioremap(port->mapbase, XUARTPS_REGISTER_SPACE);
+       if (!port->membase) {
+               dev_err(port->dev, "Unable to map registers\n");
+               release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/**
+ * xuartps_release_port - Release the memory region attached to a xuartps
+ *                             port, called when the driver removes a xuartps
+ *                             port via uart_remove_one_port().
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_release_port(struct uart_port *port)
+{
+       release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE);
+       iounmap(port->membase);
+       port->membase = NULL;
+}
+
+/**
+ * xuartps_config_port - Configure xuartps, called when the driver adds a
+ *                             xuartps port
+ * @port: Handle to the uart port structure
+ * @flags: If any
+ *
+ **/
+static void xuartps_config_port(struct uart_port *port, int flags)
+{
+       if (flags & UART_CONFIG_TYPE && xuartps_request_port(port) == 0)
+               port->type = PORT_XUARTPS;
+}
+
+/**
+ * xuartps_get_mctrl - Get the modem control state
+ *
+ * @port: Handle to the uart port structure
+ *
+ * Returns the modem control state
+ *
+ **/
+static unsigned int xuartps_get_mctrl(struct uart_port *port)
+{
+       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void xuartps_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       /* N/A */
+}
+
+static void xuartps_enable_ms(struct uart_port *port)
+{
+       /* N/A */
+}
+
+/** The UART operations structure
+ */
+static struct uart_ops xuartps_ops = {
+       .set_mctrl      = xuartps_set_mctrl,
+       .get_mctrl      = xuartps_get_mctrl,
+       .enable_ms      = xuartps_enable_ms,
+
+       .start_tx       = xuartps_start_tx,     /* Start transmitting */
+       .stop_tx        = xuartps_stop_tx,      /* Stop transmission */
+       .stop_rx        = xuartps_stop_rx,      /* Stop reception */
+       .tx_empty       = xuartps_tx_empty,     /* Transmitter busy? */
+       .break_ctl      = xuartps_break_ctl,    /* Start/stop
+                                                * transmitting break
+                                                */
+       .set_termios    = xuartps_set_termios,  /* Set termios */
+       .startup        = xuartps_startup,      /* App opens xuartps */
+       .shutdown       = xuartps_shutdown,     /* App closes xuartps */
+       .type           = xuartps_type,         /* Set UART type */
+       .verify_port    = xuartps_verify_port,  /* Verification of port
+                                                * params
+                                                */
+       .request_port   = xuartps_request_port, /* Claim resources
+                                                * associated with a
+                                                * xuartps port
+                                                */
+       .release_port   = xuartps_release_port, /* Release resources
+                                                * associated with a
+                                                * xuartps port
+                                                */
+       .config_port    = xuartps_config_port,  /* Configure when driver
+                                                * adds a xuartps port
+                                                */
+};
+
+static struct uart_port xuartps_port[2];
+
+/**
+ * xuartps_get_port - Configure the port from the platform device resource
+ *                     info
+ *
+ * Returns a pointer to a uart_port or NULL for failure
+ **/
+static struct uart_port *xuartps_get_port(void)
+{
+       struct uart_port *port;
+       int id;
+
+       /* Find the next unused port */
+       for (id = 0; id < XUARTPS_NR_PORTS; id++)
+               if (xuartps_port[id].mapbase == 0)
+                       break;
+
+       if (id >= XUARTPS_NR_PORTS)
+               return NULL;
+
+       port = &xuartps_port[id];
+
+       /* At this point, we've got an empty uart_port struct, initialize it */
+       spin_lock_init(&port->lock);
+       port->membase   = NULL;
+       port->iobase    = 1; /* mark port in use */
+       port->irq       = 0;
+       port->type      = PORT_UNKNOWN;
+       port->iotype    = UPIO_MEM32;
+       port->flags     = UPF_BOOT_AUTOCONF;
+       port->ops       = &xuartps_ops;
+       port->fifosize  = XUARTPS_FIFO_SIZE;
+       port->line      = id;
+       port->dev       = NULL;
+       return port;
+}
+
+/*-----------------------Console driver operations--------------------------*/
+
+#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
+/**
+ * xuartps_console_wait_tx - Wait for the TX to be full
+ * @port: Handle to the uart port structure
+ *
+ **/
+static void xuartps_console_wait_tx(struct uart_port *port)
+{
+       while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY)
+                               != XUARTPS_SR_TXEMPTY)
+               barrier();
+}
+
+/**
+ * xuartps_console_putchar - write the character to the FIFO buffer
+ * @port: Handle to the uart port structure
+ * @ch: Character to be written
+ *
+ **/
+static void xuartps_console_putchar(struct uart_port *port, int ch)
+{
+       xuartps_console_wait_tx(port);
+       xuartps_writel(ch, XUARTPS_FIFO_OFFSET);
+}
+
+/**
+ * xuartps_console_write - perform write operation
+ * @port: Handle to the uart port structure
+ * @s: Pointer to character array
+ * @count: No of characters
+ **/
+static void xuartps_console_write(struct console *co, const char *s,
+                               unsigned int count)
+{
+       struct uart_port *port = &xuartps_port[co->index];
+       unsigned long flags;
+       unsigned int imr;
+       int locked = 1;
+
+       if (oops_in_progress)
+               locked = spin_trylock_irqsave(&port->lock, flags);
+       else
+               spin_lock_irqsave(&port->lock, flags);
+
+       /* save and disable interrupt */
+       imr = xuartps_readl(XUARTPS_IMR_OFFSET);
+       xuartps_writel(imr, XUARTPS_IDR_OFFSET);
+
+       uart_console_write(port, s, count, xuartps_console_putchar);
+       xuartps_console_wait_tx(port);
+
+       /* restore interrupt state, it seems like there may be a h/w bug
+        * in that the interrupt enable register should not need to be
+        * written based on the data sheet
+        */
+       xuartps_writel(~imr, XUARTPS_IDR_OFFSET);
+       xuartps_writel(imr, XUARTPS_IER_OFFSET);
+
+       if (locked)
+               spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/**
+ * xuartps_console_setup - Initialize the uart to default config
+ * @co: Console handle
+ * @options: Initial settings of uart
+ *
+ * Returns 0, -ENODEV if no device
+ **/
+static int __init xuartps_console_setup(struct console *co, char *options)
+{
+       struct uart_port *port = &xuartps_port[co->index];
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       if (co->index < 0 || co->index >= XUARTPS_NR_PORTS)
+               return -EINVAL;
+
+       if (!port->mapbase) {
+               pr_debug("console on ttyPS%i not present\n", co->index);
+               return -ENODEV;
+       }
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver xuartps_uart_driver;
+
+static struct console xuartps_console = {
+       .name   = XUARTPS_TTY_NAME,
+       .write  = xuartps_console_write,
+       .device = uart_console_device,
+       .setup  = xuartps_console_setup,
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */
+       .data   = &xuartps_uart_driver,
+};
+
+/**
+ * xuartps_console_init - Initialization call
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int __init xuartps_console_init(void)
+{
+       register_console(&xuartps_console);
+       return 0;
+}
+
+console_initcall(xuartps_console_init);
+
+#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */
+
+/** Structure Definitions
+ */
+static struct uart_driver xuartps_uart_driver = {
+       .owner          = THIS_MODULE,          /* Owner */
+       .driver_name    = XUARTPS_NAME,         /* Driver name */
+       .dev_name       = XUARTPS_TTY_NAME,     /* Node name */
+       .major          = XUARTPS_MAJOR,        /* Major number */
+       .minor          = XUARTPS_MINOR,        /* Minor number */
+       .nr             = XUARTPS_NR_PORTS,     /* Number of UART ports */
+#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
+       .cons           = &xuartps_console,     /* Console */
+#endif
+};
+
+/* ---------------------------------------------------------------------
+ * Platform bus binding
+ */
+/**
+ * xuartps_probe - Platform driver probe
+ * @pdev: Pointer to the platform device structure
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int __devinit xuartps_probe(struct platform_device *pdev)
+{
+       int rc;
+       struct uart_port *port;
+       struct resource *res, *res2;
+       int clk = 0;
+
+#ifdef CONFIG_OF
+       const unsigned int *prop;
+
+       prop = of_get_property(pdev->dev.of_node, "clock", NULL);
+       if (prop)
+               clk = be32_to_cpup(prop);
+#else
+       clk = *((unsigned int *)(pdev->dev.platform_data));
+#endif
+       if (!clk) {
+               dev_err(&pdev->dev, "no clock specified\n");
+               return -ENODEV;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res2)
+               return -ENODEV;
+
+       /* Initialize the port structure */
+       port = xuartps_get_port();
+
+       if (!port) {
+               dev_err(&pdev->dev, "Cannot get uart_port structure\n");
+               return -ENODEV;
+       } else {
+               /* Register the port.
+                * This function also registers this device with the tty layer
+                * and triggers invocation of the config_port() entry point.
+                */
+               port->mapbase = res->start;
+               port->irq = res2->start;
+               port->dev = &pdev->dev;
+               port->uartclk = clk;
+               dev_set_drvdata(&pdev->dev, port);
+               rc = uart_add_one_port(&xuartps_uart_driver, port);
+               if (rc) {
+                       dev_err(&pdev->dev,
+                               "uart_add_one_port() failed; err=%i\n", rc);
+                       dev_set_drvdata(&pdev->dev, NULL);
+                       return rc;
+               }
+               return 0;
+       }
+}
+
+/**
+ * xuartps_remove - called when the platform driver is unregistered
+ * @pdev: Pointer to the platform device structure
+ *
+ * Returns 0 on success, negative error otherwise
+ **/
+static int __devexit xuartps_remove(struct platform_device *pdev)
+{
+       struct uart_port *port = dev_get_drvdata(&pdev->dev);
+       int rc = 0;
+
+       /* Remove the xuartps port from the serial core */
+       if (port) {
+               rc = uart_remove_one_port(&xuartps_uart_driver, port);
+               dev_set_drvdata(&pdev->dev, NULL);
+               port->mapbase = 0;
+       }
+       return rc;
+}
+
+/**
+ * xuartps_suspend - suspend event
+ * @pdev: Pointer to the platform device structure
+ * @state: State of the device
+ *
+ * Returns 0
+ **/
+static int xuartps_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       /* Call the API provided in serial_core.c file which handles
+        * the suspend.
+        */
+       uart_suspend_port(&xuartps_uart_driver, &xuartps_port[pdev->id]);
+       return 0;
+}
+
+/**
+ * xuartps_resume - Resume after a previous suspend
+ * @pdev: Pointer to the platform device structure
+ *
+ * Returns 0
+ **/
+static int xuartps_resume(struct platform_device *pdev)
+{
+       uart_resume_port(&xuartps_uart_driver, &xuartps_port[pdev->id]);
+       return 0;
+}
+
+/* Match table for of_platform binding */
+
+#ifdef CONFIG_OF
+static struct of_device_id xuartps_of_match[] __devinitdata = {
+       { .compatible = "xlnx,xuartps", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, xuartps_of_match);
+#else
+#define xuartps_of_match NULL
+#endif
+
+static struct platform_driver xuartps_platform_driver = {
+       .probe   = xuartps_probe,               /* Probe method */
+       .remove  = __exit_p(xuartps_remove),    /* Detach method */
+       .suspend = xuartps_suspend,             /* Suspend */
+       .resume  = xuartps_resume,              /* Resume after a suspend */
+       .driver  = {
+               .owner = THIS_MODULE,
+               .name = XUARTPS_NAME,           /* Driver name */
+               .of_match_table = xuartps_of_match,
+               },
+};
+
+/* ---------------------------------------------------------------------
+ * Module Init and Exit
+ */
+/**
+ * xuartps_init - Initial driver registration call
+ *
+ * Returns whether the registration was successful or not
+ **/
+static int __init xuartps_init(void)
+{
+       int retval = 0;
+
+       /* Register the xuartps driver with the serial core */
+       retval = uart_register_driver(&xuartps_uart_driver);
+       if (retval)
+               return retval;
+
+       /* Register the platform driver */
+       retval = platform_driver_register(&xuartps_platform_driver);
+       if (retval)
+               uart_unregister_driver(&xuartps_uart_driver);
+
+       return retval;
+}
+
+/**
+ * xuartps_exit - Driver unregistration call
+ **/
+static void __exit xuartps_exit(void)
+{
+       /* The order of unregistration is important. Unregister the
+        * UART driver before the platform driver crashes the system.
+        */
+
+       /* Unregister the platform driver */
+       platform_driver_unregister(&xuartps_platform_driver);
+
+       /* Unregister the xuartps driver */
+       uart_unregister_driver(&xuartps_uart_driver);
+}
+
+module_init(xuartps_init);
+module_exit(xuartps_exit);
+
+MODULE_DESCRIPTION("Driver for PS UART");
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_LICENSE("GPL");
index 27da23d98e3f25f13b3a169ef78dbd20b79151d7..272e417a9b0d0620be9311307033ba607a48572f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/char/synclink.c
- *
  * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
index f1a7918d71aac192107af9b45f5e2dde1508383a..46de2e075dacda019589cc5462a0d60f6eea8d51 100644 (file)
@@ -416,6 +416,7 @@ static void flush_to_ldisc(struct work_struct *work)
                struct tty_buffer *head, *tail = tty->buf.tail;
                int seen_tail = 0;
                while ((head = tty->buf.head) != NULL) {
+                       int copied;
                        int count;
                        char *char_buf;
                        unsigned char *flag_buf;
@@ -442,17 +443,19 @@ static void flush_to_ldisc(struct work_struct *work)
                           line discipline as we want to empty the queue */
                        if (test_bit(TTY_FLUSHPENDING, &tty->flags))
                                break;
-                       if (!tty->receive_room || seen_tail)
-                               break;
-                       if (count > tty->receive_room)
-                               count = tty->receive_room;
                        char_buf = head->char_buf_ptr + head->read;
                        flag_buf = head->flag_buf_ptr + head->read;
-                       head->read += count;
                        spin_unlock_irqrestore(&tty->buf.lock, flags);
-                       disc->ops->receive_buf(tty, char_buf,
+                       copied = disc->ops->receive_buf(tty, char_buf,
                                                        flag_buf, count);
                        spin_lock_irqsave(&tty->buf.lock, flags);
+
+                       head->read += copied;
+
+                       if (copied == 0 || seen_tail) {
+                               schedule_work(&tty->buf.work);
+                               break;
+                       }
                }
                clear_bit(TTY_FLUSHING, &tty->flags);
        }
index d7d50b48287e8a7374e4d2e814527b4faa9dfaa9..6556f7452ba6f960a9f083068f1674164c93ff11 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/tty_io.c
- *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
@@ -964,12 +962,14 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
 }
 
 void tty_write_unlock(struct tty_struct *tty)
+       __releases(&tty->atomic_write_lock)
 {
        mutex_unlock(&tty->atomic_write_lock);
        wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
 }
 
 int tty_write_lock(struct tty_struct *tty, int ndelay)
+       __acquires(&tty->atomic_write_lock)
 {
        if (!mutex_trylock(&tty->atomic_write_lock)) {
                if (ndelay)
@@ -1391,16 +1391,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
                return ERR_PTR(-ENODEV);
 
        tty = alloc_tty_struct();
-       if (!tty)
-               goto fail_no_mem;
+       if (!tty) {
+               retval = -ENOMEM;
+               goto err_module_put;
+       }
        initialize_tty_struct(tty, driver, idx);
 
        retval = tty_driver_install_tty(driver, tty);
-       if (retval < 0) {
-               free_tty_struct(tty);
-               module_put(driver->owner);
-               return ERR_PTR(retval);
-       }
+       if (retval < 0)
+               goto err_deinit_tty;
 
        /*
         * Structures all installed ... call the ldisc open routines.
@@ -1409,15 +1408,18 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
         */
        retval = tty_ldisc_setup(tty, tty->link);
        if (retval)
-               goto release_mem_out;
+               goto err_release_tty;
        return tty;
 
-fail_no_mem:
+err_deinit_tty:
+       deinitialize_tty_struct(tty);
+       free_tty_struct(tty);
+err_module_put:
        module_put(driver->owner);
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(retval);
 
        /* call the tty release_tty routine to clean out this slot */
-release_mem_out:
+err_release_tty:
        if (printk_ratelimit())
                printk(KERN_INFO "tty_init_dev: ldisc open failed, "
                                 "clearing slot %d\n", idx);
@@ -1892,6 +1894,7 @@ got_driver:
        retval = tty_add_file(tty, filp);
        if (retval) {
                tty_unlock();
+               tty_release(inode, filp);
                return retval;
        }
 
@@ -1902,12 +1905,10 @@ got_driver:
 #ifdef TTY_DEBUG_HANGUP
        printk(KERN_DEBUG "opening %s...", tty->name);
 #endif
-       if (!retval) {
-               if (tty->ops->open)
-                       retval = tty->ops->open(tty, filp);
-               else
-                       retval = -ENODEV;
-       }
+       if (tty->ops->open)
+               retval = tty->ops->open(tty, filp);
+       else
+               retval = -ENODEV;
        filp->f_flags = saved_flags;
 
        if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) &&
@@ -2887,6 +2888,20 @@ void initialize_tty_struct(struct tty_struct *tty,
        tty->dev = tty_get_device(tty);
 }
 
+/**
+ *     deinitialize_tty_struct
+ *     @tty: tty to deinitialize
+ *
+ *     This subroutine deinitializes a tty structure that has been newly
+ *     allocated but tty_release cannot be called on that yet.
+ *
+ *     Locking: none - tty in question must not be exposed at this point
+ */
+void deinitialize_tty_struct(struct tty_struct *tty)
+{
+       tty_ldisc_deinit(tty);
+}
+
 /**
  *     tty_put_char    -       write one character to a tty
  *     @tty: tty
index 620c971422b66719c30d7e21b0c976741f3ebfdd..53f2442c609950ba27f84614c2efec51b6d4ad51 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/tty_ioctl.c
- *
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *
  * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
index e19e136471165dd163509750bddd6382ce70bcd2..5d01d32e2cf072fa26699fd7a7b19e77c7ff4f39 100644 (file)
@@ -956,6 +956,19 @@ void tty_ldisc_init(struct tty_struct *tty)
        tty_ldisc_assign(tty, ld);
 }
 
+/**
+ *     tty_ldisc_init          -       ldisc cleanup for new tty
+ *     @tty: tty that was allocated recently
+ *
+ *     The tty structure must not becompletely set up (tty_ldisc_setup) when
+ *      this call is made.
+ */
+void tty_ldisc_deinit(struct tty_struct *tty)
+{
+       put_ldisc(tty->ldisc);
+       tty_ldisc_assign(tty, NULL);
+}
+
 void tty_ldisc_begin(void)
 {
        /* Setup the default TTY line discipline. */
index 133697540c738441d6b92f6e2ebf72b0622baae6..3b2bb77194423fa3c3967f21916d64bd94513584 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * drivers/char/tty_lock.c
- */
 #include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
index d6b342b5b423ce69fc989cdf3593fa892d7f9167..3761ccf0f34081f889b32e49010ca8bdf310173c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/char/keyboard.c
- *
  * Written for linux by Johan Myreen as a translation from
  * the assembly version by Linus (with diacriticals added)
  *
index adf0ad2a8851a66b477538b7ac8d28df8956676a..67b1d0d7c8acb924fdc481cfc75b36fa6c925de8 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/char/selection.c
- *
  * This module exports the functions:
  *
  *     'int set_selection(struct tiocl_selection __user *, struct tty_struct *)'
@@ -334,8 +332,7 @@ int paste_selection(struct tty_struct *tty)
                        continue;
                }
                count = sel_buffer_lth - pasted;
-               count = min(count, tty->receive_room);
-               tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
+               count = tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
                                                                NULL, count);
                pasted += count;
        }
index 1564261e80c8d729f41f9b682504b521178e43ea..66825c9f516a2a871c5908d4d9da40aa48431270 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/char/vc_screen.c
- *
  * Provide access to virtual console memory.
  * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
  * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
index 4bea1efaec98edbff2dbc2e5db27ac807d70c7fb..b3915b7ad3e2facb654dbd50114623f01996f431 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/vt.c
- *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
@@ -858,7 +856,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
 {
        unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
        unsigned long end;
-       unsigned int old_cols, old_rows, old_row_size, old_screen_size;
+       unsigned int old_rows, old_row_size;
        unsigned int new_cols, new_rows, new_row_size, new_screen_size;
        unsigned int user;
        unsigned short *newscreen;
@@ -887,9 +885,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
                return -ENOMEM;
 
        old_rows = vc->vc_rows;
-       old_cols = vc->vc_cols;
        old_row_size = vc->vc_size_row;
-       old_screen_size = vc->vc_screenbuf_size;
 
        err = resize_screen(vc, new_cols, new_rows, user);
        if (err) {
@@ -1197,6 +1193,13 @@ static void csi_J(struct vc_data *vc, int vpar)
                                              vc->vc_x + 1);
                        }
                        break;
+               case 3: /* erase scroll-back buffer (and whole display) */
+                       scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
+                                   vc->vc_screenbuf_size >> 1);
+                       set_origin(vc);
+                       if (CON_IS_VISIBLE(vc))
+                               update_screen(vc);
+                       /* fall through */
                case 2: /* erase whole display */
                        count = vc->vc_cols * vc->vc_rows;
                        start = (unsigned short *)vc->vc_origin;
index 937d17219984508eaa2e26dff8278b6c79d6ca46..5e096f43bceaceb056098d69227d937501ef27bf 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/drivers/char/vt_ioctl.c
- *
  *  Copyright (C) 1992 obz under the linux copyright
  *
  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
@@ -698,10 +696,23 @@ int vt_ioctl(struct tty_struct *tty,
                break;
 
        case KDGKBMODE:
-               uival = ((kbd->kbdmode == VC_RAW) ? K_RAW :
-                                (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
-                                (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
-                                K_XLATE);
+               switch (kbd->kbdmode) {
+               case VC_RAW:
+                       uival = K_RAW;
+                       break;
+               case VC_MEDIUMRAW:
+                       uival = K_MEDIUMRAW;
+                       break;
+               case VC_UNICODE:
+                       uival = K_UNICODE;
+                       break;
+               case VC_OFF:
+                       uival = K_OFF;
+                       break;
+               default:
+                       uival = K_XLATE;
+                       break;
+               }
                goto setint;
 
        /* this could be folded into KDSKBMODE, but for compatibility
@@ -1499,7 +1510,6 @@ long vt_compat_ioctl(struct tty_struct *tty,
 {
        struct vc_data *vc = tty->driver_data;
        struct console_font_op op;      /* used in multiple places here */
-       struct kbd_struct *kbd;
        unsigned int console;
        void __user *up = (void __user *)arg;
        int perm;
@@ -1522,7 +1532,6 @@ long vt_compat_ioctl(struct tty_struct *tty,
        if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
                perm = 1;
 
-       kbd = kbd_table + console;
        switch (cmd) {
        /*
         * these need special handlers for incompatible data structures
index c016896dcbb2cb2e93016634d6c9b45709d5c833..c1cf372f17a7fdb5bb0d7dc89f1ae8ccf5964638 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1051,6 +1051,7 @@ char *get_task_comm(char *buf, struct task_struct *tsk)
        task_unlock(tsk);
        return buf;
 }
+EXPORT_SYMBOL_GPL(get_task_comm);
 
 void set_task_comm(struct task_struct *tsk, char *buf)
 {
diff --git a/include/linux/pti.h b/include/linux/pti.h
new file mode 100644 (file)
index 0000000..81af667
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (C) Intel 2011
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The PTI (Parallel Trace Interface) driver directs trace data routed from
+ * various parts in the system out through the Intel Penwell PTI port and
+ * out of the mobile device for analysis with a debugging tool
+ * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7,
+ * compact JTAG, standard.
+ *
+ * This header file will allow other parts of the OS to use the
+ * interface to write out it's contents for debugging a mobile system.
+ */
+
+#ifndef PTI_H_
+#define PTI_H_
+
+/* offset for last dword of any PTI message. Part of MIPI P1149.7 */
+#define PTI_LASTDWORD_DTS      0x30
+
+/* basic structure used as a write address to the PTI HW */
+struct pti_masterchannel {
+       u8 master;
+       u8 channel;
+};
+
+/* the following functions are defined in misc/pti.c */
+void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count);
+struct pti_masterchannel *pti_request_masterchannel(u8 type);
+void pti_release_masterchannel(struct pti_masterchannel *mc);
+
+#endif /*PTI_H_*/
index 758c5b0c6fd3cf4121fd2468dcaaf6f489bb0573..a5c31146a337dff33441ec6f61f3af92861f6a8e 100644 (file)
@@ -45,7 +45,8 @@
 #define PORT_OCTEON    17      /* Cavium OCTEON internal UART */
 #define PORT_AR7       18      /* Texas Instruments AR7 internal UART */
 #define PORT_U6_16550A 19      /* ST-Ericsson U6xxx internal UART */
-#define PORT_MAX_8250  19      /* max port ID */
+#define PORT_TEGRA     20      /* NVIDIA Tegra internal UART */
+#define PORT_MAX_8250  20      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
 /* VIA VT8500 SoC */
 #define PORT_VT8500    97
 
+/* Xilinx PSS UART */
+#define PORT_XUARTPS   98
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
index 3ecb71a9e505901c1a0ff3a3780ba29d3c4c3741..c75bda37c18e1a1861040ed42d15086d7bf97d5e 100644 (file)
@@ -57,6 +57,7 @@
  * ST16C654:    8  16  56  60           8  16  32  56  PORT_16654
  * TI16C750:    1  16  32  56          xx  xx  xx  xx  PORT_16750
  * TI16C752:    8  16  56  60           8  16  32  56
+ * Tegra:       1   4   8  14          16   8   4   1  PORT_TEGRA
  */
 #define UART_FCR_R_TRIG_00     0x00
 #define UART_FCR_R_TRIG_01     0x40
 #define UART_MCR_DTR           0x01 /* DTR complement */
 
 #define UART_LSR       5       /* In:  Line Status Register */
+#define UART_LSR_FIFOE         0x80 /* Fifo error */
 #define UART_LSR_TEMT          0x40 /* Transmitter empty */
 #define UART_LSR_THRE          0x20 /* Transmit-hold-register empty */
 #define UART_LSR_BI            0x10 /* Break interrupt indicator */
index 9f469c700550e79dc7fc3949e34c94096c2078ff..d6f05292e456e3ea7822627432285b859654ede0 100644 (file)
@@ -50,6 +50,8 @@
 #define N_CAIF         20      /* CAIF protocol for talking to modems */
 #define N_GSM0710      21      /* GSM 0710 Mux */
 #define N_TI_WL                22      /* for TI's WL BT, FM, GPS combo chips */
+#define N_TRACESINK    23      /* Trace data routing for MIPI P1149.7 */
+#define N_TRACEROUTER  24      /* Trace data routing for MIPI P1149.7 */
 
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
@@ -472,6 +474,7 @@ extern int tty_add_file(struct tty_struct *tty, struct file *file);
 extern void free_tty_struct(struct tty_struct *tty);
 extern void initialize_tty_struct(struct tty_struct *tty,
                struct tty_driver *driver, int idx);
+extern void deinitialize_tty_struct(struct tty_struct *tty);
 extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
                                                                int first_ok);
 extern int tty_release(struct inode *inode, struct file *filp);
@@ -525,6 +528,7 @@ extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
 extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
 extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty);
 extern void tty_ldisc_init(struct tty_struct *tty);
+extern void tty_ldisc_deinit(struct tty_struct *tty);
 extern void tty_ldisc_begin(void);
 /* This last one is just for the tty layer internals and shouldn't be used elsewhere */
 extern void tty_ldisc_enable(struct tty_struct *tty);
index ff7dc08696a8cc67c812ea516e9bcd9fee9c53c7..5b07792ccb46cb62280438159f3f6e3f00de573d 100644 (file)
@@ -76,7 +76,7 @@
  *     tty device.  It is solely the responsibility of the line
  *     discipline to handle poll requests.
  *
- * void        (*receive_buf)(struct tty_struct *, const unsigned char *cp,
+ * unsigned int (*receive_buf)(struct tty_struct *, const unsigned char *cp,
  *                    char *fp, int count);
  *
  *     This function is called by the low-level tty driver to send
@@ -84,7 +84,8 @@
  *     processing.  <cp> is a pointer to the buffer of input
  *     character received by the device.  <fp> is a pointer to a
  *     pointer of flag bytes which indicate whether a character was
- *     received with a parity error, etc.
+ *     received with a parity error, etc. Returns the amount of bytes
+ *     received.
  * 
  * void        (*write_wakeup)(struct tty_struct *);
  *
@@ -140,8 +141,8 @@ struct tty_ldisc_ops {
        /*
         * The following routines are called from below.
         */
-       void    (*receive_buf)(struct tty_struct *, const unsigned char *cp,
-                              char *fp, int count);
+       unsigned int (*receive_buf)(struct tty_struct *,
+                       const unsigned char *cp, char *fp, int count);
        void    (*write_wakeup)(struct tty_struct *);
        void    (*dcd_change)(struct tty_struct *, unsigned int,
                                struct pps_event_time *);
index d68ea532cc7f59a52e46be1a89ccf4d0c35ad518..f8c663dcff027d9d10083a41d0a6f5cd3b082e20 100644 (file)
@@ -262,14 +262,14 @@ static int v253_hangup(struct tty_struct *tty)
 }
 
 /* Line discipline .receive_buf() */
-static void v253_receive(struct tty_struct *tty,
-                               const unsigned char *cp, char *fp, int count)
+static unsigned int v253_receive(struct tty_struct *tty,
+                                const unsigned char *cp, char *fp, int count)
 {
        struct snd_soc_codec *codec = tty->disc_data;
        struct cx20442_priv *cx20442;
 
        if (!codec)
-               return;
+               return count;
 
        cx20442 = snd_soc_codec_get_drvdata(codec);
 
@@ -281,6 +281,8 @@ static void v253_receive(struct tty_struct *tty,
                codec->hw_write = (hw_write_t)tty->ops->write;
                codec->card->pop_time = 1;
        }
+
+       return count;
 }
 
 /* Line discipline .write_wakeup() */