You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'tty-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here's the big tty/serial driver pull request for 3.14-rc1 There are a number of n_tty fixes and cleanups, and some serial driver bugfixes, and we got rid of one obsolete driver, making this series remove more lines than added, always a nice surprise. All of these have been in linux-next with no reports of issues" * tag 'tty-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (60 commits) tty/serial: at91: disable uart timer at start of shutdown serial: 8250: enable UART_BUG_NOMSR for Tegra tty/serial: at91: reset rx_ring when port is shutdown tty/serial: at91: fix race condition in atmel_serial_remove tty/serial: at91: Handle shutdown more safely serial: sirf: correct condition for fetching dma buffer into tty serial: sirf: provide pm entries of uart_ops serial: sirf: use PM macro initialize PM functions serial: clps711x: Enable driver compilation with COMPILE_TEST serial: clps711x: Add support for N_IRDA line discipline tty: synclink: avoid sleep_on race tty/amiserial: avoid interruptible_sleep_on tty: delete non-required instances of include <linux/init.h> tty: an overflow of multiplication in drivers/tty/cyclades.c serial: Remove old SC26XX driver serial: add support for 200 v3 series Titan card serial: 8250: Fix initialisation of Quatech cards with the AMCC PCI chip tty: Removing the deprecated function tty_vhangup_locked() TTY/n_gsm: Removing the wrong tty_unlock/lock() in gsm_dlci_release() tty/serial: at91: document clock properties ...
This commit is contained in:
@@ -6,6 +6,9 @@ Required properties:
|
||||
additional mode or an USART new feature.
|
||||
- reg: Should contain registers location and length
|
||||
- interrupts: Should contain interrupt
|
||||
- clock-names: tuple listing input clock names.
|
||||
Required elements: "usart"
|
||||
- clocks: phandles to input clocks.
|
||||
|
||||
Optional properties:
|
||||
- atmel,use-dma-rx: use of PDC or DMA for receiving data
|
||||
@@ -26,6 +29,8 @@ Example:
|
||||
compatible = "atmel,at91sam9260-usart";
|
||||
reg = <0xfff8c000 0x4000>;
|
||||
interrupts = <7>;
|
||||
clocks = <&usart0_clk>;
|
||||
clock-names = "usart";
|
||||
atmel,use-dma-rx;
|
||||
atmel,use-dma-tx;
|
||||
};
|
||||
@@ -35,6 +40,8 @@ Example:
|
||||
compatible = "atmel,at91sam9260-usart";
|
||||
reg = <0xf001c000 0x100>;
|
||||
interrupts = <12 4 5>;
|
||||
clocks = <&usart0_clk>;
|
||||
clock-names = "usart";
|
||||
atmel,use-dma-rx;
|
||||
atmel,use-dma-tx;
|
||||
dmas = <&dma0 2 0x3>,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
* Cirrus Logic CLPS711X Universal Asynchronous Receiver/Transmitter (UART)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "cirrus,clps711x-uart".
|
||||
- reg: Address and length of the register set for the device.
|
||||
- interrupts: Should contain UART TX and RX interrupt.
|
||||
- clocks: Should contain UART core clock number.
|
||||
- syscon: Phandle to SYSCON node, which contain UART control bits.
|
||||
|
||||
Optional properties:
|
||||
- uart-use-ms: Indicate the UART has modem signal (DCD, DSR, CTS).
|
||||
|
||||
Note: Each UART port should have an alias correctly numbered
|
||||
in "aliases" node.
|
||||
|
||||
Example:
|
||||
aliases {
|
||||
serial0 = &uart1;
|
||||
};
|
||||
|
||||
uart1: uart@80000480 {
|
||||
compatible = "cirrus,clps711x-uart";
|
||||
reg = <0x80000480 0x80>;
|
||||
interrupts = <12 13>;
|
||||
clocks = <&clks 11>;
|
||||
syscon = <&syscon1>;
|
||||
uart-use-ms;
|
||||
};
|
||||
@@ -61,8 +61,29 @@ static void __init clps711x_add_syscon(void)
|
||||
&clps711x_syscon_res[i], 1);
|
||||
}
|
||||
|
||||
static const struct resource clps711x_uart1_res[] __initconst = {
|
||||
DEFINE_RES_MEM(CLPS711X_PHYS_BASE + UARTDR1, SZ_128),
|
||||
DEFINE_RES_IRQ(IRQ_UTXINT1),
|
||||
DEFINE_RES_IRQ(IRQ_URXINT1),
|
||||
};
|
||||
|
||||
static const struct resource clps711x_uart2_res[] __initconst = {
|
||||
DEFINE_RES_MEM(CLPS711X_PHYS_BASE + UARTDR2, SZ_128),
|
||||
DEFINE_RES_IRQ(IRQ_UTXINT2),
|
||||
DEFINE_RES_IRQ(IRQ_URXINT2),
|
||||
};
|
||||
|
||||
static void __init clps711x_add_uart(void)
|
||||
{
|
||||
platform_device_register_simple("clps711x-uart", 0, clps711x_uart1_res,
|
||||
ARRAY_SIZE(clps711x_uart1_res));
|
||||
platform_device_register_simple("clps711x-uart", 1, clps711x_uart2_res,
|
||||
ARRAY_SIZE(clps711x_uart2_res));
|
||||
};
|
||||
|
||||
void __init clps711x_devices_init(void)
|
||||
{
|
||||
clps711x_add_gpio();
|
||||
clps711x_add_syscon();
|
||||
clps711x_add_uart();
|
||||
}
|
||||
|
||||
@@ -2511,8 +2511,8 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
|
||||
|
||||
/* If port is closing, signal caller to try again */
|
||||
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
|
||||
if (port->flags & ASYNC_CLOSING)
|
||||
interruptible_sleep_on(&port->close_wait);
|
||||
wait_event_interruptible_tty(tty, port->close_wait,
|
||||
!(port->flags & ASYNC_CLOSING));
|
||||
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
|
||||
-EAGAIN : -ERESTARTSYS);
|
||||
goto cleanup;
|
||||
|
||||
@@ -124,7 +124,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
|
||||
{
|
||||
struct serport *serport = (struct serport*) tty->disc_data;
|
||||
unsigned long flags;
|
||||
unsigned int ch_flags;
|
||||
unsigned int ch_flags = 0;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&serport->lock, flags);
|
||||
@@ -133,6 +133,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (fp) {
|
||||
switch (fp[i]) {
|
||||
case TTY_FRAME:
|
||||
ch_flags = SERIO_FRAME;
|
||||
@@ -146,6 +147,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
|
||||
ch_flags = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
serio_interrupt(serport->serio, cp[i], ch_flags);
|
||||
}
|
||||
|
||||
@@ -596,13 +596,11 @@ static int parport_serial_pci_probe(struct pci_dev *dev,
|
||||
|
||||
err = pci_enable_device (dev);
|
||||
if (err) {
|
||||
pci_set_drvdata (dev, NULL);
|
||||
kfree (priv);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (parport_register (dev, id)) {
|
||||
pci_set_drvdata (dev, NULL);
|
||||
kfree (priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -611,7 +609,6 @@ static int parport_serial_pci_probe(struct pci_dev *dev,
|
||||
int i;
|
||||
for (i = 0; i < priv->num_par; i++)
|
||||
parport_pc_unregister_port (priv->port[i]);
|
||||
pci_set_drvdata (dev, NULL);
|
||||
kfree (priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -624,8 +621,6 @@ static void parport_serial_pci_remove(struct pci_dev *dev)
|
||||
struct parport_serial_private *priv = pci_get_drvdata (dev);
|
||||
int i;
|
||||
|
||||
pci_set_drvdata(dev, NULL);
|
||||
|
||||
// Serial ports
|
||||
if (priv->serial)
|
||||
pciserial_remove_ports(priv->serial);
|
||||
|
||||
@@ -9,3 +9,23 @@ config FIREWIRE_SERIAL
|
||||
|
||||
To compile this driver as a module, say M here: the module will
|
||||
be called firewire-serial.
|
||||
|
||||
if FIREWIRE_SERIAL
|
||||
|
||||
config FWTTY_MAX_TOTAL_PORTS
|
||||
int "Maximum number of serial ports supported"
|
||||
default "64"
|
||||
help
|
||||
Set this to the maximum number of serial ports you want the
|
||||
firewire-serial driver to support.
|
||||
|
||||
config FWTTY_MAX_CARD_PORTS
|
||||
int "Maximum number of serial ports supported per adapter"
|
||||
range 0 FWTTY_MAX_TOTAL_PORTS
|
||||
default "32"
|
||||
help
|
||||
Set this to the maximum number of serial ports each firewire
|
||||
adapter supports. The actual number of serial ports registered
|
||||
is set with the module parameter "ttys".
|
||||
|
||||
endif
|
||||
|
||||
@@ -136,14 +136,14 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card,
|
||||
|
||||
#ifdef FWTTY_PROFILING
|
||||
|
||||
static void profile_fifo_avail(struct fwtty_port *port, unsigned *stat)
|
||||
static void fwtty_profile_fifo(struct fwtty_port *port, unsigned *stat)
|
||||
{
|
||||
spin_lock_bh(&port->lock);
|
||||
profile_size_distrib(stat, dma_fifo_avail(&port->tx_fifo));
|
||||
fwtty_profile_data(stat, dma_fifo_avail(&port->tx_fifo));
|
||||
spin_unlock_bh(&port->lock);
|
||||
}
|
||||
|
||||
static void dump_profile(struct seq_file *m, struct stats *stats)
|
||||
static void fwtty_dump_profile(struct seq_file *m, struct stats *stats)
|
||||
{
|
||||
/* for each stat, print sum of 0 to 2^k, then individually */
|
||||
int k = 4;
|
||||
@@ -183,8 +183,8 @@ static void dump_profile(struct seq_file *m, struct stats *stats)
|
||||
}
|
||||
|
||||
#else
|
||||
#define profile_fifo_avail(port, stat)
|
||||
#define dump_profile(m, stats)
|
||||
#define fwtty_profile_fifo(port, stat)
|
||||
#define fwtty_dump_profile(m, stats)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -456,16 +456,27 @@ static int fwtty_write_port_status(struct fwtty_port *port)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __fwtty_throttle(struct fwtty_port *port, struct tty_struct *tty)
|
||||
static void fwtty_throttle_port(struct fwtty_port *port)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
unsigned old;
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&port->lock);
|
||||
|
||||
old = port->mctrl;
|
||||
port->mctrl |= OOB_RX_THROTTLE;
|
||||
if (C_CRTSCTS(tty))
|
||||
port->mctrl &= ~TIOCM_RTS;
|
||||
if (~old & OOB_RX_THROTTLE)
|
||||
__fwtty_write_port_status(port);
|
||||
|
||||
spin_unlock_bh(&port->lock);
|
||||
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -532,80 +543,14 @@ static void fwtty_emit_breaks(struct work_struct *work)
|
||||
port->icount.brk += brk;
|
||||
}
|
||||
|
||||
static void fwtty_pushrx(struct work_struct *work)
|
||||
{
|
||||
struct fwtty_port *port = to_port(work, push);
|
||||
struct tty_struct *tty;
|
||||
struct buffered_rx *buf, *next;
|
||||
int n, c = 0;
|
||||
|
||||
spin_lock_bh(&port->lock);
|
||||
list_for_each_entry_safe(buf, next, &port->buf_list, list) {
|
||||
n = tty_insert_flip_string_fixed_flag(&port->port, buf->data,
|
||||
TTY_NORMAL, buf->n);
|
||||
c += n;
|
||||
port->buffered -= n;
|
||||
if (n < buf->n) {
|
||||
if (n > 0) {
|
||||
memmove(buf->data, buf->data + n, buf->n - n);
|
||||
buf->n -= n;
|
||||
}
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (tty) {
|
||||
__fwtty_throttle(port, tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
list_del(&buf->list);
|
||||
kfree(buf);
|
||||
}
|
||||
}
|
||||
if (c > 0)
|
||||
tty_flip_buffer_push(&port->port);
|
||||
|
||||
if (list_empty(&port->buf_list))
|
||||
clear_bit(BUFFERING_RX, &port->flags);
|
||||
spin_unlock_bh(&port->lock);
|
||||
}
|
||||
|
||||
static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n)
|
||||
{
|
||||
struct buffered_rx *buf;
|
||||
size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF;
|
||||
|
||||
if (port->buffered + n > HIGH_WATERMARK) {
|
||||
fwtty_err_ratelimited(port, "overflowed rx buffer: buffered: %d new: %zu wtrmk: %d\n",
|
||||
port->buffered, n, HIGH_WATERMARK);
|
||||
return 0;
|
||||
}
|
||||
buf = kmalloc(size, GFP_ATOMIC);
|
||||
if (!buf)
|
||||
return 0;
|
||||
INIT_LIST_HEAD(&buf->list);
|
||||
buf->n = n;
|
||||
memcpy(buf->data, d, n);
|
||||
|
||||
spin_lock_bh(&port->lock);
|
||||
list_add_tail(&buf->list, &port->buf_list);
|
||||
port->buffered += n;
|
||||
if (port->buffered > port->stats.watermark)
|
||||
port->stats.watermark = port->buffered;
|
||||
set_bit(BUFFERING_RX, &port->flags);
|
||||
spin_unlock_bh(&port->lock);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
int c, n = len;
|
||||
unsigned lsr;
|
||||
int err = 0;
|
||||
|
||||
fwtty_dbg(port, "%d\n", n);
|
||||
profile_size_distrib(port->stats.reads, n);
|
||||
fwtty_profile_data(port->stats.reads, n);
|
||||
|
||||
if (port->write_only) {
|
||||
n = 0;
|
||||
@@ -636,31 +581,24 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!test_bit(BUFFERING_RX, &port->flags)) {
|
||||
c = tty_insert_flip_string_fixed_flag(&port->port, data,
|
||||
TTY_NORMAL, n);
|
||||
c = tty_insert_flip_string_fixed_flag(&port->port, data, TTY_NORMAL, n);
|
||||
if (c > 0)
|
||||
tty_flip_buffer_push(&port->port);
|
||||
n -= c;
|
||||
|
||||
if (n) {
|
||||
/* start buffering and throttling */
|
||||
n -= fwtty_buffer_rx(port, &data[c], n);
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (tty) {
|
||||
spin_lock_bh(&port->lock);
|
||||
__fwtty_throttle(port, tty);
|
||||
spin_unlock_bh(&port->lock);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
} else
|
||||
n -= fwtty_buffer_rx(port, data, n);
|
||||
|
||||
if (n) {
|
||||
port->overrun = true;
|
||||
err = -EIO;
|
||||
fwtty_err_ratelimited(port, "flip buffer overrun\n");
|
||||
|
||||
} else {
|
||||
/* throttle the sender if remaining flip buffer space has
|
||||
* reached high watermark to avoid losing data which may be
|
||||
* in-flight. Since the AR request context is 32k, that much
|
||||
* data may have _already_ been acked.
|
||||
*/
|
||||
if (tty_buffer_space_avail(&port->port) < HIGH_WATERMARK)
|
||||
fwtty_throttle_port(port);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -821,7 +759,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain)
|
||||
if (n == -EAGAIN)
|
||||
++port->stats.tx_stall;
|
||||
else if (n == -ENODATA)
|
||||
profile_size_distrib(port->stats.txns, 0);
|
||||
fwtty_profile_data(port->stats.txns, 0);
|
||||
else {
|
||||
++port->stats.fifo_errs;
|
||||
fwtty_err_ratelimited(port, "fifo err: %d\n",
|
||||
@@ -830,7 +768,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain)
|
||||
break;
|
||||
}
|
||||
|
||||
profile_size_distrib(port->stats.txns, txn->dma_pended.len);
|
||||
fwtty_profile_data(port->stats.txns, txn->dma_pended.len);
|
||||
|
||||
fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST,
|
||||
peer->fifo_addr, txn->dma_pended.data,
|
||||
@@ -1101,20 +1039,13 @@ static int fwtty_port_activate(struct tty_port *tty_port,
|
||||
static void fwtty_port_shutdown(struct tty_port *tty_port)
|
||||
{
|
||||
struct fwtty_port *port = to_port(tty_port, port);
|
||||
struct buffered_rx *buf, *next;
|
||||
|
||||
/* TODO: cancel outstanding transactions */
|
||||
|
||||
cancel_delayed_work_sync(&port->emit_breaks);
|
||||
cancel_delayed_work_sync(&port->drain);
|
||||
cancel_work_sync(&port->push);
|
||||
|
||||
spin_lock_bh(&port->lock);
|
||||
list_for_each_entry_safe(buf, next, &port->buf_list, list) {
|
||||
list_del(&buf->list);
|
||||
kfree(buf);
|
||||
}
|
||||
port->buffered = 0;
|
||||
port->flags = 0;
|
||||
port->break_ctl = 0;
|
||||
port->overrun = 0;
|
||||
@@ -1184,7 +1115,7 @@ static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c)
|
||||
int n, len;
|
||||
|
||||
fwtty_dbg(port, "%d\n", c);
|
||||
profile_size_distrib(port->stats.writes, c);
|
||||
fwtty_profile_data(port->stats.writes, c);
|
||||
|
||||
spin_lock_bh(&port->lock);
|
||||
n = dma_fifo_in(&port->tx_fifo, buf, c);
|
||||
@@ -1262,9 +1193,7 @@ static void fwtty_unthrottle(struct tty_struct *tty)
|
||||
|
||||
fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0));
|
||||
|
||||
profile_fifo_avail(port, port->stats.unthrottle);
|
||||
|
||||
schedule_work(&port->push);
|
||||
fwtty_profile_fifo(port, port->stats.unthrottle);
|
||||
|
||||
spin_lock_bh(&port->lock);
|
||||
port->mctrl &= ~OOB_RX_THROTTLE;
|
||||
@@ -1523,15 +1452,14 @@ static void fwtty_debugfs_show_port(struct seq_file *m, struct fwtty_port *port)
|
||||
|
||||
seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped,
|
||||
stats.tx_stall, stats.fifo_errs, stats.lost);
|
||||
seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled,
|
||||
stats.watermark);
|
||||
seq_printf(m, " pkts:%d thr:%d", stats.sent, stats.throttled);
|
||||
|
||||
if (port->port.console) {
|
||||
seq_puts(m, "\n ");
|
||||
(*port->fwcon_ops->proc_show)(m, port->con_data);
|
||||
}
|
||||
|
||||
dump_profile(m, &port->stats);
|
||||
fwtty_dump_profile(m, &port->stats);
|
||||
}
|
||||
|
||||
static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer)
|
||||
@@ -2297,13 +2225,12 @@ static int fwserial_create(struct fw_unit *unit)
|
||||
port->index = FWTTY_INVALID_INDEX;
|
||||
port->port.ops = &fwtty_port_ops;
|
||||
port->serial = serial;
|
||||
tty_buffer_set_limit(&port->port, 128 * 1024);
|
||||
|
||||
spin_lock_init(&port->lock);
|
||||
INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx);
|
||||
INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks);
|
||||
INIT_WORK(&port->hangup, fwtty_do_hangup);
|
||||
INIT_WORK(&port->push, fwtty_pushrx);
|
||||
INIT_LIST_HEAD(&port->buf_list);
|
||||
init_waitqueue_head(&port->wait_tx);
|
||||
port->max_payload = link_speed_to_max_payload(SCODE_100);
|
||||
dma_fifo_init(&port->tx_fifo);
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
#ifdef FWTTY_PROFILING
|
||||
#define DISTRIBUTION_MAX_SIZE 8192
|
||||
#define DISTRIBUTION_MAX_INDEX (ilog2(DISTRIBUTION_MAX_SIZE) + 1)
|
||||
static inline void profile_size_distrib(unsigned stat[], unsigned val)
|
||||
static inline void fwtty_profile_data(unsigned stat[], unsigned val)
|
||||
{
|
||||
int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0;
|
||||
++stat[n];
|
||||
}
|
||||
#else
|
||||
#define DISTRIBUTION_MAX_INDEX 0
|
||||
#define profile_size_distrib(st, n)
|
||||
#define fwtty_profile_data(st, n)
|
||||
#endif
|
||||
|
||||
/* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */
|
||||
@@ -166,7 +166,6 @@ struct stats {
|
||||
unsigned sent;
|
||||
unsigned lost;
|
||||
unsigned throttled;
|
||||
unsigned watermark;
|
||||
unsigned reads[DISTRIBUTION_MAX_INDEX + 1];
|
||||
unsigned writes[DISTRIBUTION_MAX_INDEX + 1];
|
||||
unsigned txns[DISTRIBUTION_MAX_INDEX + 1];
|
||||
@@ -183,12 +182,6 @@ struct fwconsole_ops {
|
||||
#define FWCON_NOTIFY_ATTACH 1
|
||||
#define FWCON_NOTIFY_DETACH 2
|
||||
|
||||
struct buffered_rx {
|
||||
struct list_head list;
|
||||
size_t n;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* fwtty_port: structure used to track/represent underlying tty_port
|
||||
* @port: underlying tty_port
|
||||
@@ -223,11 +216,6 @@ struct buffered_rx {
|
||||
* The work can race with the writer but concurrent sending is
|
||||
* prevented with the IN_TX flag. Scheduled under lock to
|
||||
* limit scheduling when fifo has just been drained.
|
||||
* @push: work responsible for pushing buffered rx to the ldisc.
|
||||
* rx can become buffered if the tty buffer is filled before the
|
||||
* ldisc throttles the sender.
|
||||
* @buf_list: list of buffered rx yet to be sent to ldisc
|
||||
* @buffered: byte count of buffered rx
|
||||
* @tx_fifo: fifo used to store & block-up writes for dma to remote
|
||||
* @max_payload: max bytes transmissable per dma (based on peer's max_payload)
|
||||
* @status_mask: UART_LSR_* bitmask significant to rx (based on termios)
|
||||
@@ -267,9 +255,6 @@ struct fwtty_port {
|
||||
spinlock_t lock;
|
||||
unsigned mctrl;
|
||||
struct delayed_work drain;
|
||||
struct work_struct push;
|
||||
struct list_head buf_list;
|
||||
int buffered;
|
||||
struct dma_fifo tx_fifo;
|
||||
int max_payload;
|
||||
unsigned status_mask;
|
||||
@@ -291,7 +276,6 @@ struct fwtty_port {
|
||||
/* bit #s for flags field */
|
||||
#define IN_TX 0
|
||||
#define STOP_TX 1
|
||||
#define BUFFERING_RX 2
|
||||
|
||||
/* bitmasks for special mctrl/mstatus bits */
|
||||
#define OOB_RX_THROTTLE 0x00010000
|
||||
@@ -307,8 +291,8 @@ struct fwtty_port {
|
||||
#define FREQ_BREAKS (HZ / 50)
|
||||
|
||||
/* Ports are allocated in blocks of num_ports for each fw_card */
|
||||
#define MAX_CARD_PORTS 32 /* max # of ports per card */
|
||||
#define MAX_TOTAL_PORTS 64 /* max # of ports total */
|
||||
#define MAX_CARD_PORTS CONFIG_FWTTY_MAX_CARD_PORTS
|
||||
#define MAX_TOTAL_PORTS CONFIG_FWTTY_MAX_TOTAL_PORTS
|
||||
|
||||
/* tuning parameters */
|
||||
#define FWTTY_PORT_TXFIFO_LEN 4096
|
||||
|
||||
+18
-8
@@ -1248,6 +1248,8 @@ static int rs_ioctl(struct tty_struct *tty,
|
||||
struct async_icount cprev, cnow; /* kernel counter temps */
|
||||
void __user *argp = (void __user *)arg;
|
||||
unsigned long flags;
|
||||
DEFINE_WAIT(wait);
|
||||
int ret;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
||||
return -ENODEV;
|
||||
@@ -1288,25 +1290,33 @@ static int rs_ioctl(struct tty_struct *tty,
|
||||
cprev = info->icount;
|
||||
local_irq_restore(flags);
|
||||
while (1) {
|
||||
interruptible_sleep_on(&info->tport.delta_msr_wait);
|
||||
/* see if a signal did it */
|
||||
if (signal_pending(current))
|
||||
return -ERESTARTSYS;
|
||||
prepare_to_wait(&info->tport.delta_msr_wait,
|
||||
&wait, TASK_INTERRUPTIBLE);
|
||||
local_irq_save(flags);
|
||||
cnow = info->icount; /* atomic copy */
|
||||
local_irq_restore(flags);
|
||||
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
|
||||
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
|
||||
return -EIO; /* no change => error */
|
||||
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
|
||||
ret = -EIO; /* no change => error */
|
||||
break;
|
||||
}
|
||||
if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
|
||||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
|
||||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
|
||||
((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
|
||||
return 0;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
schedule();
|
||||
/* see if a signal did it */
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
cprev = cnow;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
finish_wait(&info->tport.delta_msr_wait, &wait);
|
||||
return ret;
|
||||
|
||||
case TIOCSERGWILD:
|
||||
case TIOCSERSWILD:
|
||||
|
||||
@@ -2709,6 +2709,8 @@ cy_ioctl(struct tty_struct *tty,
|
||||
break;
|
||||
#ifndef CONFIG_CYZ_INTR
|
||||
case CYZSETPOLLCYCLE:
|
||||
if (arg > LONG_MAX / HZ)
|
||||
return -ENODEV;
|
||||
cyz_polling_cycle = (arg * HZ) / 1000;
|
||||
break;
|
||||
case CYZGETPOLLCYCLE:
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/tty.h>
|
||||
|
||||
@@ -788,7 +788,7 @@ static int hvc_tiocmset(struct tty_struct *tty,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
int hvc_poll_init(struct tty_driver *driver, int line, char *options)
|
||||
static int hvc_poll_init(struct tty_driver *driver, int line, char *options)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/console.h>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
* Copyright (C) 2007 David Sterba
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
+37
-24
@@ -194,6 +194,7 @@ struct gsm_control {
|
||||
struct gsm_mux {
|
||||
struct tty_struct *tty; /* The tty our ldisc is bound to */
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
unsigned int num;
|
||||
struct kref ref;
|
||||
|
||||
@@ -1704,11 +1705,8 @@ static void gsm_dlci_release(struct gsm_dlci *dlci)
|
||||
gsm_destroy_network(dlci);
|
||||
mutex_unlock(&dlci->mutex);
|
||||
|
||||
/* tty_vhangup needs the tty_lock, so unlock and
|
||||
relock after doing the hangup. */
|
||||
tty_unlock(tty);
|
||||
tty_vhangup(tty);
|
||||
tty_lock(tty);
|
||||
|
||||
tty_port_tty_set(&dlci->port, NULL);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
@@ -2019,7 +2017,7 @@ static void gsm_error(struct gsm_mux *gsm,
|
||||
* and then shut down each device hanging up the channels as we go.
|
||||
*/
|
||||
|
||||
void gsm_cleanup_mux(struct gsm_mux *gsm)
|
||||
static void gsm_cleanup_mux(struct gsm_mux *gsm)
|
||||
{
|
||||
int i;
|
||||
struct gsm_dlci *dlci = gsm->dlci[0];
|
||||
@@ -2054,15 +2052,16 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
|
||||
dlci->state == DLCI_CLOSED);
|
||||
}
|
||||
/* Free up any link layer users */
|
||||
mutex_lock(&gsm->mutex);
|
||||
for (i = 0; i < NUM_DLCI; i++)
|
||||
if (gsm->dlci[i])
|
||||
gsm_dlci_release(gsm->dlci[i]);
|
||||
mutex_unlock(&gsm->mutex);
|
||||
/* Now wipe the queues */
|
||||
list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
|
||||
kfree(txq);
|
||||
INIT_LIST_HEAD(&gsm->tx_list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gsm_cleanup_mux);
|
||||
|
||||
/**
|
||||
* gsm_activate_mux - generic GSM setup
|
||||
@@ -2073,7 +2072,7 @@ EXPORT_SYMBOL_GPL(gsm_cleanup_mux);
|
||||
* finally kick off connecting to DLCI 0 on the modem.
|
||||
*/
|
||||
|
||||
int gsm_activate_mux(struct gsm_mux *gsm)
|
||||
static int gsm_activate_mux(struct gsm_mux *gsm)
|
||||
{
|
||||
struct gsm_dlci *dlci;
|
||||
int i = 0;
|
||||
@@ -2109,7 +2108,6 @@ int gsm_activate_mux(struct gsm_mux *gsm)
|
||||
gsm->dead = 0; /* Tty opens are now permissible */
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gsm_activate_mux);
|
||||
|
||||
/**
|
||||
* gsm_free_mux - free up a mux
|
||||
@@ -2117,13 +2115,12 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux);
|
||||
*
|
||||
* Dispose of allocated resources for a dead mux
|
||||
*/
|
||||
void gsm_free_mux(struct gsm_mux *gsm)
|
||||
static void gsm_free_mux(struct gsm_mux *gsm)
|
||||
{
|
||||
kfree(gsm->txframe);
|
||||
kfree(gsm->buf);
|
||||
kfree(gsm);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gsm_free_mux);
|
||||
|
||||
/**
|
||||
* gsm_free_muxr - free up a mux
|
||||
@@ -2153,7 +2150,7 @@ static inline void mux_put(struct gsm_mux *gsm)
|
||||
* Creates a new mux ready for activation.
|
||||
*/
|
||||
|
||||
struct gsm_mux *gsm_alloc_mux(void)
|
||||
static struct gsm_mux *gsm_alloc_mux(void)
|
||||
{
|
||||
struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL);
|
||||
if (gsm == NULL)
|
||||
@@ -2170,6 +2167,7 @@ struct gsm_mux *gsm_alloc_mux(void)
|
||||
return NULL;
|
||||
}
|
||||
spin_lock_init(&gsm->lock);
|
||||
mutex_init(&gsm->mutex);
|
||||
kref_init(&gsm->ref);
|
||||
INIT_LIST_HEAD(&gsm->tx_list);
|
||||
|
||||
@@ -2185,7 +2183,6 @@ struct gsm_mux *gsm_alloc_mux(void)
|
||||
|
||||
return gsm;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gsm_alloc_mux);
|
||||
|
||||
/**
|
||||
* gsmld_output - write to link
|
||||
@@ -2269,13 +2266,14 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *f;
|
||||
int i;
|
||||
char buf[64];
|
||||
char flags;
|
||||
char flags = TTY_NORMAL;
|
||||
|
||||
if (debug & 4)
|
||||
print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
|
||||
cp, count);
|
||||
|
||||
for (i = count, dp = cp, f = fp; i; i--, dp++) {
|
||||
if (f)
|
||||
flags = *f++;
|
||||
switch (flags) {
|
||||
case TTY_NORMAL:
|
||||
@@ -2711,7 +2709,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
|
||||
return;
|
||||
}
|
||||
|
||||
int gsm_change_mtu(struct net_device *net, int new_mtu)
|
||||
static int gsm_change_mtu(struct net_device *net, int new_mtu)
|
||||
{
|
||||
struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
|
||||
if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu))
|
||||
@@ -2909,23 +2907,33 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
This is ok from a locking
|
||||
perspective as we don't have to worry about this
|
||||
if DLCI0 is lost */
|
||||
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
|
||||
mutex_lock(&gsm->mutex);
|
||||
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) {
|
||||
mutex_unlock(&gsm->mutex);
|
||||
return -EL2NSYNC;
|
||||
}
|
||||
dlci = gsm->dlci[line];
|
||||
if (dlci == NULL) {
|
||||
alloc = true;
|
||||
dlci = gsm_dlci_alloc(gsm, line);
|
||||
}
|
||||
if (dlci == NULL)
|
||||
if (dlci == NULL) {
|
||||
mutex_unlock(&gsm->mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = tty_port_install(&dlci->port, driver, tty);
|
||||
if (ret) {
|
||||
if (alloc)
|
||||
dlci_put(dlci);
|
||||
mutex_unlock(&gsm->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dlci_get(dlci);
|
||||
dlci_get(gsm->dlci[0]);
|
||||
mux_get(gsm);
|
||||
tty->driver_data = dlci;
|
||||
mutex_unlock(&gsm->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2936,9 +2944,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
||||
struct tty_port *port = &dlci->port;
|
||||
|
||||
port->count++;
|
||||
dlci_get(dlci);
|
||||
dlci_get(dlci->gsm->dlci[0]);
|
||||
mux_get(dlci->gsm);
|
||||
tty_port_tty_set(port, tty);
|
||||
|
||||
dlci->modem_rx = 0;
|
||||
@@ -2965,7 +2970,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
|
||||
mutex_unlock(&dlci->mutex);
|
||||
gsm = dlci->gsm;
|
||||
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
|
||||
goto out;
|
||||
return;
|
||||
gsm_dlci_begin_close(dlci);
|
||||
if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
|
||||
if (C_HUPCL(tty))
|
||||
@@ -2973,10 +2978,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
|
||||
}
|
||||
tty_port_close_end(&dlci->port, tty);
|
||||
tty_port_tty_set(&dlci->port, NULL);
|
||||
out:
|
||||
dlci_put(dlci);
|
||||
dlci_put(gsm->dlci[0]);
|
||||
mux_put(gsm);
|
||||
return;
|
||||
}
|
||||
|
||||
static void gsmtty_hangup(struct tty_struct *tty)
|
||||
@@ -3153,6 +3155,16 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
|
||||
return gsmtty_modem_update(dlci, encode);
|
||||
}
|
||||
|
||||
static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
|
||||
{
|
||||
struct gsm_dlci *dlci = tty->driver_data;
|
||||
struct gsm_mux *gsm = dlci->gsm;
|
||||
|
||||
dlci_put(dlci);
|
||||
dlci_put(gsm->dlci[0]);
|
||||
mux_put(gsm);
|
||||
driver->ttys[tty->index] = NULL;
|
||||
}
|
||||
|
||||
/* Virtual ttys for the demux */
|
||||
static const struct tty_operations gsmtty_ops = {
|
||||
@@ -3172,6 +3184,7 @@ static const struct tty_operations gsmtty_ops = {
|
||||
.tiocmget = gsmtty_tiocmget,
|
||||
.tiocmset = gsmtty_tiocmset,
|
||||
.break_ctl = gsmtty_break_ctl,
|
||||
.remove = gsmtty_remove,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1244,7 +1244,7 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
{
|
||||
struct r3964_info *pInfo = tty->disc_data;
|
||||
const unsigned char *p;
|
||||
char *f, flags = 0;
|
||||
char *f, flags = TTY_NORMAL;
|
||||
int i;
|
||||
|
||||
for (i = count, p = cp, f = fp; i; i--, p++) {
|
||||
|
||||
+55
-44
@@ -105,6 +105,7 @@ struct n_tty_data {
|
||||
|
||||
/* must hold exclusive termios_rwsem to reset these */
|
||||
unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
|
||||
unsigned char push:1;
|
||||
|
||||
/* shared by producer and consumer */
|
||||
char read_buf[N_TTY_BUF_SIZE];
|
||||
@@ -275,6 +276,7 @@ static void n_tty_check_unthrottle(struct tty_struct *tty)
|
||||
return;
|
||||
n_tty_set_room(tty);
|
||||
n_tty_write_wakeup(tty->link);
|
||||
if (waitqueue_active(&tty->link->write_wait))
|
||||
wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
|
||||
return;
|
||||
}
|
||||
@@ -342,6 +344,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
|
||||
|
||||
ldata->erasing = 0;
|
||||
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
|
||||
ldata->push = 0;
|
||||
}
|
||||
|
||||
static void n_tty_packet_mode_flush(struct tty_struct *tty)
|
||||
@@ -351,6 +354,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
|
||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||
if (tty->link->packet) {
|
||||
tty->ctrl_status |= TIOCPKT_FLUSHREAD;
|
||||
if (waitqueue_active(&tty->link->read_wait))
|
||||
wake_up_interruptible(&tty->link->read_wait);
|
||||
}
|
||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||
@@ -1162,6 +1166,7 @@ static void n_tty_receive_break(struct tty_struct *tty)
|
||||
put_tty_queue('\0', ldata);
|
||||
}
|
||||
put_tty_queue('\0', ldata);
|
||||
if (waitqueue_active(&tty->read_wait))
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
}
|
||||
|
||||
@@ -1220,6 +1225,7 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
|
||||
put_tty_queue('\0', ldata);
|
||||
else
|
||||
put_tty_queue(c, ldata);
|
||||
if (waitqueue_active(&tty->read_wait))
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
}
|
||||
|
||||
@@ -1264,7 +1270,6 @@ static int
|
||||
n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
int parmrk;
|
||||
|
||||
if (I_IXON(tty)) {
|
||||
if (c == START_CHAR(tty)) {
|
||||
@@ -1349,8 +1354,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
|
||||
}
|
||||
if ((c == EOL_CHAR(tty)) ||
|
||||
(c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
|
||||
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
|
||||
? 1 : 0;
|
||||
/*
|
||||
* XXX are EOL_CHAR and EOL2_CHAR echoed?!?
|
||||
*/
|
||||
@@ -1365,7 +1368,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
|
||||
* XXX does PARMRK doubling happen for
|
||||
* EOL_CHAR and EOL2_CHAR?
|
||||
*/
|
||||
if (parmrk)
|
||||
if (c == (unsigned char) '\377' && I_PARMRK(tty))
|
||||
put_tty_queue(c, ldata);
|
||||
|
||||
handle_newline:
|
||||
@@ -1379,7 +1382,6 @@ handle_newline:
|
||||
}
|
||||
}
|
||||
|
||||
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
|
||||
if (L_ECHO(tty)) {
|
||||
finish_erasing(ldata);
|
||||
if (c == '\n')
|
||||
@@ -1393,7 +1395,8 @@ handle_newline:
|
||||
commit_echoes(tty);
|
||||
}
|
||||
|
||||
if (parmrk)
|
||||
/* PARMRK doubling check */
|
||||
if (c == (unsigned char) '\377' && I_PARMRK(tty))
|
||||
put_tty_queue(c, ldata);
|
||||
|
||||
put_tty_queue(c, ldata);
|
||||
@@ -1404,7 +1407,6 @@ static inline void
|
||||
n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
int parmrk;
|
||||
|
||||
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) {
|
||||
start_tty(tty);
|
||||
@@ -1418,13 +1420,13 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c)
|
||||
echo_char(c, tty);
|
||||
commit_echoes(tty);
|
||||
}
|
||||
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
|
||||
if (parmrk)
|
||||
/* PARMRK doubling check */
|
||||
if (c == (unsigned char) '\377' && I_PARMRK(tty))
|
||||
put_tty_queue(c, ldata);
|
||||
put_tty_queue(c, ldata);
|
||||
}
|
||||
|
||||
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
|
||||
static void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
n_tty_receive_char_inline(tty, c);
|
||||
}
|
||||
@@ -1449,8 +1451,7 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c)
|
||||
put_tty_queue(c, ldata);
|
||||
}
|
||||
|
||||
static inline void
|
||||
n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
|
||||
static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
if (I_ISTRIP(tty))
|
||||
c &= 0x7f;
|
||||
@@ -1681,32 +1682,9 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
}
|
||||
}
|
||||
|
||||
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *fp, int count)
|
||||
{
|
||||
int room, n;
|
||||
|
||||
down_read(&tty->termios_rwsem);
|
||||
|
||||
while (1) {
|
||||
room = receive_room(tty);
|
||||
n = min(count, room);
|
||||
if (!n)
|
||||
break;
|
||||
__receive_buf(tty, cp, fp, n);
|
||||
cp += n;
|
||||
if (fp)
|
||||
fp += n;
|
||||
count -= n;
|
||||
}
|
||||
|
||||
tty->receive_room = room;
|
||||
n_tty_check_throttle(tty);
|
||||
up_read(&tty->termios_rwsem);
|
||||
}
|
||||
|
||||
static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *fp, int count)
|
||||
static int
|
||||
n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *fp, int count, int flow)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
int room, n, rcvd = 0;
|
||||
@@ -1717,7 +1695,7 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
|
||||
room = receive_room(tty);
|
||||
n = min(count, room);
|
||||
if (!n) {
|
||||
if (!room)
|
||||
if (flow && !room)
|
||||
ldata->no_room = 1;
|
||||
break;
|
||||
}
|
||||
@@ -1736,6 +1714,18 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
|
||||
return rcvd;
|
||||
}
|
||||
|
||||
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *fp, int count)
|
||||
{
|
||||
n_tty_receive_buf_common(tty, cp, fp, count, 0);
|
||||
}
|
||||
|
||||
static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *fp, int count)
|
||||
{
|
||||
return n_tty_receive_buf_common(tty, cp, fp, count, 1);
|
||||
}
|
||||
|
||||
int is_ignored(int sig)
|
||||
{
|
||||
return (sigismember(¤t->blocked, sig) ||
|
||||
@@ -1762,7 +1752,16 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
|
||||
if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
|
||||
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
|
||||
ldata->line_start = ldata->canon_head = ldata->read_tail;
|
||||
ldata->line_start = ldata->read_tail;
|
||||
if (!L_ICANON(tty) || !read_cnt(ldata)) {
|
||||
ldata->canon_head = ldata->read_tail;
|
||||
ldata->push = 0;
|
||||
} else {
|
||||
set_bit((ldata->read_head - 1) & (N_TTY_BUF_SIZE - 1),
|
||||
ldata->read_flags);
|
||||
ldata->canon_head = ldata->read_head;
|
||||
ldata->push = 1;
|
||||
}
|
||||
ldata->erasing = 0;
|
||||
ldata->lnext = 0;
|
||||
}
|
||||
@@ -1825,7 +1824,9 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
start_tty(tty);
|
||||
|
||||
/* The termios change make the tty ready for I/O */
|
||||
if (waitqueue_active(&tty->write_wait))
|
||||
wake_up_interruptible(&tty->write_wait);
|
||||
if (waitqueue_active(&tty->read_wait))
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
}
|
||||
|
||||
@@ -1892,14 +1893,15 @@ err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static inline int input_available_p(struct tty_struct *tty, int amt)
|
||||
static inline int input_available_p(struct tty_struct *tty, int poll)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1;
|
||||
|
||||
if (ldata->icanon && !L_EXTPROC(tty)) {
|
||||
if (ldata->canon_head != ldata->read_tail)
|
||||
return 1;
|
||||
} else if (read_cnt(ldata) >= (amt ? amt : 1))
|
||||
} else if (read_cnt(ldata) >= amt)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -1965,6 +1967,12 @@ static int copy_from_read_buf(struct tty_struct *tty,
|
||||
* it copies one line of input up to and including the line-delimiting
|
||||
* character into the user-space buffer.
|
||||
*
|
||||
* NB: When termios is changed from non-canonical to canonical mode and
|
||||
* the read buffer contains data, n_tty_set_termios() simulates an EOF
|
||||
* push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer.
|
||||
* This causes data already processed as input to be immediately available
|
||||
* as input although a newline has not been received.
|
||||
*
|
||||
* Called under the atomic_read_lock mutex
|
||||
*
|
||||
* n_tty_read()/consumer path:
|
||||
@@ -2011,7 +2019,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
n += found;
|
||||
c = n;
|
||||
|
||||
if (found && read_buf(ldata, eol) == __DISABLED_CHAR) {
|
||||
if (found && !ldata->push && read_buf(ldata, eol) == __DISABLED_CHAR) {
|
||||
n--;
|
||||
eof_push = !n && ldata->read_tail != ldata->line_start;
|
||||
}
|
||||
@@ -2038,7 +2046,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
ldata->read_tail += c;
|
||||
|
||||
if (found) {
|
||||
if (!ldata->push)
|
||||
ldata->line_start = ldata->read_tail;
|
||||
else
|
||||
ldata->push = 0;
|
||||
tty_audit_push(tty);
|
||||
}
|
||||
return eof_push ? -EAGAIN : 0;
|
||||
@@ -2398,7 +2409,7 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
|
||||
|
||||
poll_wait(file, &tty->read_wait, wait);
|
||||
poll_wait(file, &tty->write_wait, wait);
|
||||
if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty)))
|
||||
if (input_available_p(tty, 1))
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
if (tty->packet && tty->link->ctrl_status)
|
||||
mask |= POLLPRI | POLLIN | POLLRDNORM;
|
||||
|
||||
@@ -1744,7 +1744,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = {
|
||||
static const struct pci_device_id rocket_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4QUAD) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8OCTA) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8OCTA) },
|
||||
|
||||
@@ -2670,6 +2670,10 @@ static void serial8250_config_port(struct uart_port *port, int flags)
|
||||
if (port->type == PORT_16550A && port->iotype == UPIO_AU)
|
||||
up->bugs |= UART_BUG_NOMSR;
|
||||
|
||||
/* HW bugs may trigger IRQ while IIR == NO_INT */
|
||||
if (port->type == PORT_TEGRA)
|
||||
up->bugs |= UART_BUG_NOMSR;
|
||||
|
||||
if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
|
||||
autoconfig_irq(up);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user