2012-06-04 11:40:27

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 00/25] TTY buffer in tty_port -- prep no. 3

Hi,

this is the third series of patches which allow tty buffers to be
moved from tty_struct (present from open to close/hangup) to tty_port
(present as long as the device). This will allow us to get rid of the
tty refcounting in the interrupt service routines and other hot paths
after we are done. This is because we won't need to handle races among
ISRs, timers, hangups and others, because tty_port lives as long as an
interrupt/timer tick may occur. Unlike tty_struct.

In this series, the third batch of drivers is converted to use
tty_port. Read: all drivers now have a tty_port. Second, we start
assigning tty_port to tty_struct->port in this series. So the TTY
layer now finally has an access to a tty_port in most of the drivers.
This means not every driver uses the new shiny interfaces creating
tty_struct => tty_port links automatically. I ran out of time (I had
to do other things) to convert them all... The rest is going to be
converted later.

Standard x86 stuff was runtime-tested. The rest is only checked to be
compilation-errors free.

Jiri Slaby (25):
TTY: ircomm, add tty_port
TTY: ircomm, use close times from tty_port
TTY: ircomm, use open counts from tty_port
TTY: ircomm, use flags from tty_port
TTY: ircomm, revamp locking
TTY: ircomm, use tty from tty_port
TTY: ircomm, define local tty_port
TTY: ircomm, define carrier routines
TTY: ircomm, use tty_port_close_end helper
TTY: ircomm, use tty_port_close_start helper
TTY: um/line, add tty_port
TTY: um/line, use tty from tty_port
PTY: remove one empty ops->remove
PTY: merge pty_install implementations
PTY: add tty_port
TTY: vt, remove con_schedule_flip
TTY: provide drivers with tty_port_install
TTY: serial_core, add ->install
TTY: vt, add ->install
TTY: usb-serial, use tty_port_install
TTY: centralize fail paths in tty_register_driver
TTY: add ports array to tty_driver
TTY: add tty_port_register_device helper
TTY: cyclades, add local pointer for card
TTY: use tty_port_register_device

arch/um/drivers/chan_kern.c | 4 +-
arch/um/drivers/line.c | 35 +++--
arch/um/drivers/line.h | 3 +-
drivers/isdn/capi/capi.c | 3 +-
drivers/isdn/gigaset/interface.c | 3 +-
drivers/mmc/card/sdio_uart.c | 4 +-
drivers/net/usb/hso.c | 7 +-
drivers/tty/cyclades.c | 79 +++++-----
drivers/tty/ehv_bytechan.c | 9 +-
drivers/tty/ipwireless/tty.c | 2 +-
drivers/tty/isicom.c | 3 +-
drivers/tty/mxser.c | 6 +-
drivers/tty/nozomi.c | 4 +-
drivers/tty/pty.c | 141 +++++++++---------
drivers/tty/rocket.c | 4 +-
drivers/tty/serial/ifx6x60.c | 4 +-
drivers/tty/serial/msm_smd_tty.c | 8 +-
drivers/tty/serial/serial_core.c | 28 ++--
drivers/tty/synclink_gt.c | 7 +-
drivers/tty/tty_io.c | 34 +++--
drivers/tty/tty_port.c | 17 +++
drivers/tty/vt/keyboard.c | 6 +-
drivers/tty/vt/vt.c | 62 ++++----
drivers/usb/class/cdc-acm.c | 3 +-
drivers/usb/gadget/u_serial.c | 3 +-
drivers/usb/serial/usb-serial.c | 2 +-
include/linux/kbd_kern.h | 12 --
include/linux/tty.h | 5 +
include/linux/tty_driver.h | 1 +
include/net/irda/ircomm_tty.h | 17 +--
net/bluetooth/rfcomm/tty.c | 4 +-
net/irda/ircomm/ircomm_param.c | 5 -
net/irda/ircomm/ircomm_tty.c | 271 ++++++++++++++++-------------------
net/irda/ircomm/ircomm_tty_attach.c | 40 ++++--
net/irda/ircomm/ircomm_tty_ioctl.c | 25 ++--
35 files changed, 450 insertions(+), 411 deletions(-)

--
1.7.10.3


2012-06-04 11:35:46

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 18/24] TTY: provide drivers with tty_port_install

This will be used in tty_ops->install to set tty->port (and to call
tty_standard_install).

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/tty_port.c | 8 ++++++++
include/linux/tty.h | 2 ++
2 files changed, 10 insertions(+)

diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index bf6e238..1ac8abf 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -413,6 +413,14 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
}
EXPORT_SYMBOL(tty_port_close);

+int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty)
+{
+ tty->port = port;
+ return tty_standard_install(driver, tty);
+}
+EXPORT_SYMBOL_GPL(tty_port_install);
+
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
{
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..45ef71d 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -521,6 +521,8 @@ extern int tty_port_close_start(struct tty_port *port,
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
extern void tty_port_close(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
+extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+ struct tty_struct *tty);
extern int tty_port_open(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
static inline int tty_port_users(struct tty_port *port)
--
1.7.10.3

2012-06-04 11:35:58

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 11/24] TTY: ircomm, use tty_port_close_start helper

Again, the code is identical, so leverage the helper code.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
net/irda/ircomm/ircomm_tty.c | 48 +-----------------------------------------
1 file changed, 1 insertion(+), 47 deletions(-)

diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index cfe352d..4e35b45 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -509,64 +509,18 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
struct tty_port *port = &self->port;
- unsigned long flags;

IRDA_DEBUG(0, "%s()\n", __func__ );

IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- spin_lock_irqsave(&port->lock, flags);
-
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&port->lock, flags);
-
- IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
- return;
- }
-
- if ((tty->count == 1) && (port->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- IRDA_DEBUG(0, "%s(), bad serial port count; "
- "tty->count is 1, state->count is %d\n", __func__ ,
- port->count);
- port->count = 1;
- }
-
- if (--port->count < 0) {
- IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
- __func__, self->line, port->count);
- port->count = 0;
- }
- if (port->count) {
- spin_unlock_irqrestore(&port->lock, flags);
-
- IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
+ if (tty_port_close_start(port, tty, filp) == 0)
return;
- }
-
- set_bit(ASYNCB_CLOSING, &port->flags);
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent_from_close(tty, port->closing_wait);

ircomm_tty_shutdown(self);

tty_driver_flush_buffer(tty);
- tty_ldisc_flush(tty);

tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);
--
1.7.10.3

2012-06-04 11:35:57

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 06/24] TTY: ircomm, revamp locking

Use self->spinlock only for ctrl_skb and tx_skb. TTY stuff is now
protected by tty_port->lock. This is needed for further cleanup (and
conversion to tty_port helpers).

This also closes the race in the end of close.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
include/net/irda/ircomm_tty.h | 1 -
net/irda/ircomm/ircomm_tty.c | 38 ++++++++++++++++++--------------------
2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index e4db3b5..a9027d8 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -96,7 +96,6 @@ struct ircomm_tty_cb {
struct work_struct tqueue;

/* Protect concurent access to :
- * o self->open_count
* o self->ctrl_skb
* o self->tx_skb
* Maybe other things may gain to be protected as well...
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 8e61026..7b2152c 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -283,13 +283,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
__FILE__, __LINE__, tty->driver->name, self->port.count);

- /* As far as I can see, we protect port.count - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&self->port.lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
self->port.count--;
}
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);
self->port.blocked_open++;

while (1) {
@@ -340,9 +339,9 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,

if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&self->port.lock, flags);
self->port.count++;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);
}
self->port.blocked_open--;

@@ -409,12 +408,12 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
}
/* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&self->port.lock, flags);
self->port.count++;

tty->driver_data = self;
self->tty = tty;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);

IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
self->line, self->port.count);
@@ -495,10 +494,10 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&self->port.lock, flags);

if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);

IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
return;
@@ -524,20 +523,15 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
self->port.count = 0;
}
if (self->port.count) {
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);

IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
return;
}

- /* Hum... Should be test_and_set_bit ??? - Jean II */
set_bit(ASYNCB_CLOSING, &self->port.flags);

- /* We need to unlock here (we were unlocking at the end of this
- * function), because tty_wait_until_sent() may schedule.
- * I don't know if the rest should be protected somehow,
- * so someone should check. - Jean II */
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);

/*
* Now we wait for the transmit buffer to clear; and we notify
@@ -552,16 +546,21 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
tty_driver_flush_buffer(tty);
tty_ldisc_flush(tty);

+ spin_lock_irqsave(&self->port.lock, flags);
tty->closing = 0;
self->tty = NULL;

if (self->port.blocked_open) {
- if (self->port.close_delay)
+ if (self->port.close_delay) {
+ spin_unlock_irqrestore(&self->port.lock, flags);
schedule_timeout_interruptible(self->port.close_delay);
+ spin_lock_irqsave(&self->port.lock, flags);
+ }
wake_up_interruptible(&self->port.open_wait);
}

self->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+ spin_unlock_irqrestore(&self->port.lock, flags);
wake_up_interruptible(&self->port.close_wait);
}

@@ -1003,12 +1002,11 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
/* ircomm_tty_flush_buffer(tty); */
ircomm_tty_shutdown(self);

- /* I guess we need to lock here - Jean II */
- spin_lock_irqsave(&self->spinlock, flags);
+ spin_lock_irqsave(&self->port.lock, flags);
self->port.flags &= ~ASYNC_NORMAL_ACTIVE;
self->tty = NULL;
self->port.count = 0;
- spin_unlock_irqrestore(&self->spinlock, flags);
+ spin_unlock_irqrestore(&self->port.lock, flags);

wake_up_interruptible(&self->port.open_wait);
}
--
1.7.10.3

2012-06-04 11:35:55

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 08/24] TTY: ircomm, define local tty_port

In some functions we use tty_port heavily. So let us have a local
pointer to that variable instead of having self->port all over the
code.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
net/irda/ircomm/ircomm_tty.c | 109 ++++++++++++++++++++++--------------------
1 file changed, 56 insertions(+), 53 deletions(-)

diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 03acc07..199d9cb 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -244,6 +244,7 @@ err:
static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
struct tty_struct *tty, struct file *filp)
{
+ struct tty_port *port = &self->port;
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0, extra_count = 0;
@@ -257,7 +258,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
*/
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
- self->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
return 0;
}
@@ -269,24 +270,24 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,

/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, self->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* mgsl_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/

retval = 0;
- add_wait_queue(&self->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);

IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
- __FILE__, __LINE__, tty->driver->name, self->port.count);
+ __FILE__, __LINE__, tty->driver->name, port->count);

- spin_lock_irqsave(&self->port.lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
- self->port.count--;
+ port->count--;
}
- spin_unlock_irqrestore(&self->port.lock, flags);
- self->port.blocked_open++;
+ spin_unlock_irqrestore(&port->lock, flags);
+ port->blocked_open++;

while (1) {
if (tty->termios->c_cflag & CBAUD) {
@@ -302,8 +303,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
current->state = TASK_INTERRUPTIBLE;

if (tty_hung_up_p(filp) ||
- !test_bit(ASYNCB_INITIALIZED, &self->port.flags)) {
- retval = (self->port.flags & ASYNC_HUP_NOTIFY) ?
+ !test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+ retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
@@ -313,7 +314,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
* specified, we cannot return before the IrCOMM link is
* ready
*/
- if (!test_bit(ASYNCB_CLOSING, &self->port.flags) &&
+ if (!test_bit(ASYNCB_CLOSING, &port->flags) &&
(do_clocal || (self->settings.dce & IRCOMM_CD)) &&
self->state == IRCOMM_TTY_READY)
{
@@ -326,27 +327,27 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
}

IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
- __FILE__, __LINE__, tty->driver->name, self->port.count);
+ __FILE__, __LINE__, tty->driver->name, port->count);

schedule();
}

__set_current_state(TASK_RUNNING);
- remove_wait_queue(&self->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);

if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
- spin_lock_irqsave(&self->port.lock, flags);
- self->port.count++;
- spin_unlock_irqrestore(&self->port.lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
+ port->count++;
+ spin_unlock_irqrestore(&port->lock, flags);
}
- self->port.blocked_open--;
+ port->blocked_open--;

IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
- __FILE__, __LINE__, tty->driver->name, self->port.count);
+ __FILE__, __LINE__, tty->driver->name, port->count);

if (!retval)
- self->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;

return retval;
}
@@ -484,6 +485,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ struct tty_port *port = &self->port;
unsigned long flags;

IRDA_DEBUG(0, "%s()\n", __func__ );
@@ -491,16 +493,16 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- spin_lock_irqsave(&self->port.lock, flags);
+ spin_lock_irqsave(&port->lock, flags);

if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&self->port.lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);

IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
return;
}

- if ((tty->count == 1) && (self->port.count != 1)) {
+ if ((tty->count == 1) && (port->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. state->count should always
@@ -510,55 +512,55 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
*/
IRDA_DEBUG(0, "%s(), bad serial port count; "
"tty->count is 1, state->count is %d\n", __func__ ,
- self->port.count);
- self->port.count = 1;
+ port->count);
+ port->count = 1;
}

- if (--self->port.count < 0) {
+ if (--port->count < 0) {
IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
- __func__, self->line, self->port.count);
- self->port.count = 0;
+ __func__, self->line, port->count);
+ port->count = 0;
}
- if (self->port.count) {
- spin_unlock_irqrestore(&self->port.lock, flags);
+ if (port->count) {
+ spin_unlock_irqrestore(&port->lock, flags);

IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
return;
}

- set_bit(ASYNCB_CLOSING, &self->port.flags);
+ set_bit(ASYNCB_CLOSING, &port->flags);

- spin_unlock_irqrestore(&self->port.lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);

/*
* Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
- if (self->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent_from_close(tty, self->port.closing_wait);
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent_from_close(tty, port->closing_wait);

ircomm_tty_shutdown(self);

tty_driver_flush_buffer(tty);
tty_ldisc_flush(tty);

- spin_lock_irqsave(&self->port.lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;

- if (self->port.blocked_open) {
- if (self->port.close_delay) {
- spin_unlock_irqrestore(&self->port.lock, flags);
- schedule_timeout_interruptible(self->port.close_delay);
- spin_lock_irqsave(&self->port.lock, flags);
+ if (port->blocked_open) {
+ if (port->close_delay) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ schedule_timeout_interruptible(port->close_delay);
+ spin_lock_irqsave(&port->lock, flags);
}
- wake_up_interruptible(&self->port.open_wait);
+ wake_up_interruptible(&port->open_wait);
}

- self->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- spin_unlock_irqrestore(&self->port.lock, flags);
- wake_up_interruptible(&self->port.close_wait);
- tty_port_tty_set(&self->port, NULL);
+ port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+ spin_unlock_irqrestore(&port->lock, flags);
+ wake_up_interruptible(&port->close_wait);
+ tty_port_tty_set(port, NULL);
}

/*
@@ -991,6 +993,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
static void ircomm_tty_hangup(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ struct tty_port *port = &self->port;
unsigned long flags;

IRDA_DEBUG(0, "%s()\n", __func__ );
@@ -1001,17 +1004,17 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
/* ircomm_tty_flush_buffer(tty); */
ircomm_tty_shutdown(self);

- spin_lock_irqsave(&self->port.lock, flags);
- self->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- if (self->port.tty) {
- set_bit(TTY_IO_ERROR, &self->port.tty->flags);
- tty_kref_put(self->port.tty);
+ spin_lock_irqsave(&port->lock, flags);
+ port->flags &= ~ASYNC_NORMAL_ACTIVE;
+ if (port->tty) {
+ set_bit(TTY_IO_ERROR, &port->tty->flags);
+ tty_kref_put(port->tty);
}
- self->port.tty = NULL;
- self->port.count = 0;
- spin_unlock_irqrestore(&self->port.lock, flags);
+ port->tty = NULL;
+ port->count = 0;
+ spin_unlock_irqrestore(&port->lock, flags);

- wake_up_interruptible(&self->port.open_wait);
+ wake_up_interruptible(&port->open_wait);
}

/*
--
1.7.10.3

2012-06-04 11:37:45

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 10/24] TTY: ircomm, use tty_port_close_end helper

Again, the code is identical, so leverage the helper code.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
net/irda/ircomm/ircomm_tty.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 3fdce18..cfe352d 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -568,21 +568,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
tty_driver_flush_buffer(tty);
tty_ldisc_flush(tty);

- spin_lock_irqsave(&port->lock, flags);
- tty->closing = 0;
-
- if (port->blocked_open) {
- if (port->close_delay) {
- spin_unlock_irqrestore(&port->lock, flags);
- schedule_timeout_interruptible(port->close_delay);
- spin_lock_irqsave(&port->lock, flags);
- }
- wake_up_interruptible(&port->open_wait);
- }
-
- port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- spin_unlock_irqrestore(&port->lock, flags);
- wake_up_interruptible(&port->close_wait);
+ tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);
}

--
1.7.10.3

2012-06-04 11:37:44

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 09/24] TTY: ircomm, define carrier routines

These will be used by the tty_port wait_til_ready later. (Now they are
used by our code.)

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
net/irda/ircomm/ircomm_tty.c | 43 ++++++++++++++++++++++++++++++++----------
1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 199d9cb..3fdce18 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -104,6 +104,35 @@ static const struct tty_operations ops = {
#endif /* CONFIG_PROC_FS */
};

+static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise)
+{
+ struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb,
+ port);
+ /*
+ * Here, we use to lock those two guys, but as ircomm_param_request()
+ * does it itself, I don't see the point (and I see the deadlock).
+ * Jean II
+ */
+ if (raise)
+ self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR;
+ else
+ self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR);
+
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+}
+
+static int ircomm_port_carrier_raised(struct tty_port *port)
+{
+ struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb,
+ port);
+ return self->settings.dce & IRCOMM_CD;
+}
+
+static const struct tty_port_operations ircomm_port_ops = {
+ .dtr_rts = ircomm_port_raise_dtr_rts,
+ .carrier_raised = ircomm_port_carrier_raised,
+};
+
/*
* Function ircomm_tty_init()
*
@@ -290,15 +319,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
port->blocked_open++;

while (1) {
- if (tty->termios->c_cflag & CBAUD) {
- /* Here, we use to lock those two guys, but
- * as ircomm_param_request() does it itself,
- * I don't see the point (and I see the deadlock).
- * Jean II */
- self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
-
- ircomm_param_request(self, IRCOMM_DTE, TRUE);
- }
+ if (tty->termios->c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);

current->state = TASK_INTERRUPTIBLE;

@@ -315,7 +337,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
* ready
*/
if (!test_bit(ASYNCB_CLOSING, &port->flags) &&
- (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
+ (do_clocal || tty_port_carrier_raised(port)) &&
self->state == IRCOMM_TTY_READY)
{
break;
@@ -379,6 +401,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
}

tty_port_init(&self->port);
+ self->port.ops = &ircomm_port_ops;
self->magic = IRCOMM_TTY_MAGIC;
self->flow = FLOW_STOP;

--
1.7.10.3

2012-06-04 11:37:42

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 15/24] PTY: merge pty_install implementations

There are currently two instances of code which handles PTY install.
One for the legacy BSD PTY's, one for unix98's PTY's. Both of them are
very similar and differ only in termios allocation and handling.

Since we will need to allocate a tty_port at that place, this would
require editing two places with the same pattern. Instead, let us move
the implementation to one common place and call it from both places.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/pty.c | 110 ++++++++++++++++++++++-------------------------------
1 file changed, 45 insertions(+), 65 deletions(-)

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 4bcaf89..881888f 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -282,39 +282,53 @@ done:
return 0;
}

-/* Traditional BSD devices */
-#ifdef CONFIG_LEGACY_PTYS
-
-static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
+ bool legacy)
{
struct tty_struct *o_tty;
int idx = tty->index;
- int retval;
+ int retval = -ENOMEM;

o_tty = alloc_tty_struct();
if (!o_tty)
- return -ENOMEM;
+ goto err;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
- retval = -ENOMEM;
goto err_free_tty;
}
initialize_tty_struct(o_tty, driver->other, idx);

- /* We always use new tty termios data so we can do this
- the easy way .. */
- retval = tty_init_termios(tty);
- if (retval)
- goto err_deinit_tty;
-
- retval = tty_init_termios(o_tty);
- if (retval)
- goto err_free_termios;
+ if (legacy) {
+ /* We always use new tty termios data so we can do this
+ the easy way .. */
+ retval = tty_init_termios(tty);
+ if (retval)
+ goto err_deinit_tty;
+
+ retval = tty_init_termios(o_tty);
+ if (retval)
+ goto err_free_termios;
+
+ driver->other->ttys[idx] = o_tty;
+ driver->ttys[idx] = tty;
+ } else {
+ tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+ if (tty->termios == NULL)
+ goto err_deinit_tty;
+ *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 err_free_termios;
+ *o_tty->termios = driver->other->init_termios;
+ o_tty->termios_locked = o_tty->termios + 1;
+ }

/*
* Everything allocated ... set up the o_tty structure.
*/
- driver->other->ttys[idx] = o_tty;
tty_driver_kref_get(driver->other);
if (driver->subtype == PTY_TYPE_MASTER)
o_tty->count++;
@@ -324,18 +338,29 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)

tty_driver_kref_get(driver);
tty->count++;
- driver->ttys[idx] = tty;
return 0;
err_free_termios:
- tty_free_termios(tty);
+ if (legacy)
+ tty_free_termios(tty);
+ else
+ kfree(tty->termios);
err_deinit_tty:
deinitialize_tty_struct(o_tty);
module_put(o_tty->driver->owner);
err_free_tty:
free_tty_struct(o_tty);
+err:
return retval;
}

+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+
+static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ return pty_common_install(driver, tty, true);
+}
+
static int pty_bsd_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -509,52 +534,7 @@ static void pty_unix98_shutdown(struct tty_struct *tty)

static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
{
- struct tty_struct *o_tty;
- int idx = tty->index;
-
- o_tty = alloc_tty_struct();
- if (!o_tty)
- return -ENOMEM;
- if (!try_module_get(driver->other->owner)) {
- /* This cannot in fact currently happen */
- 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 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 err_free_mem;
- *o_tty->termios = driver->other->init_termios;
- o_tty->termios_locked = o_tty->termios + 1;
-
- tty_driver_kref_get(driver->other);
- if (driver->subtype == PTY_TYPE_MASTER)
- o_tty->count++;
- /* Establish the links in both directions */
- tty->link = o_tty;
- o_tty->link = tty;
- /*
- * All structures have been allocated, so now we install them.
- * Failures after this point use release_tty to clean up, so
- * there's no need to null out the local pointers.
- */
- tty_driver_kref_get(driver);
- tty->count++;
- return 0;
-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);
- return -ENOMEM;
+ return pty_common_install(driver, tty, false);
}

static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
--
1.7.10.3

2012-06-04 11:37:39

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 03/24] TTY: ircomm, use close times from tty_port

Switch to tty_port->close_delay and closing_wait.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
include/net/irda/ircomm_tty.h | 3 ---
net/irda/ircomm/ircomm_tty.c | 10 ++++------
net/irda/ircomm/ircomm_tty_ioctl.c | 4 ++--
3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 365fa6e..b4184d0 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -101,9 +101,6 @@ struct ircomm_tty_cb {
struct timer_list watchdog_timer;
struct work_struct tqueue;

- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
-
int open_count;
int blocked_open; /* # of blocked opens */

diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 8eeaa8b..61e0adc 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -389,8 +389,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
INIT_WORK(&self->tqueue, ircomm_tty_do_softint);
self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED;
self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED;
- self->close_delay = 5*HZ/10;
- self->closing_wait = 30*HZ;

/* Init some important stuff */
init_timer(&self->watchdog_timer);
@@ -546,8 +544,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
- if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent_from_close(tty, self->closing_wait);
+ if (self->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent_from_close(tty, self->port.closing_wait);

ircomm_tty_shutdown(self);

@@ -558,8 +556,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
self->tty = NULL;

if (self->blocked_open) {
- if (self->close_delay)
- schedule_timeout_interruptible(self->close_delay);
+ if (self->port.close_delay)
+ schedule_timeout_interruptible(self->port.close_delay);
wake_up_interruptible(&self->port.open_wait);
}

diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index d0667d6..a6d25e3 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -272,8 +272,8 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
info.line = self->line;
info.flags = self->flags;
info.baud_base = self->settings.data_rate;
- info.close_delay = self->close_delay;
- info.closing_wait = self->closing_wait;
+ info.close_delay = self->port.close_delay;
+ info.closing_wait = self->port.closing_wait;

/* For compatibility */
info.type = PORT_16550A;
--
1.7.10.3

2012-06-04 11:37:37

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 02/24] TTY: ircomm, add tty_port

And use close/open_wait from there.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
include/net/irda/ircomm_tty.h | 3 +--
net/irda/ircomm/ircomm_tty.c | 21 +++++++++++----------
net/irda/ircomm/ircomm_tty_attach.c | 2 +-
3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 59ba38bc..365fa6e 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -62,6 +62,7 @@
*/
struct ircomm_tty_cb {
irda_queue_t queue; /* Must be first */
+ struct tty_port port;
magic_t magic;

int state; /* Connect state */
@@ -97,8 +98,6 @@ struct ircomm_tty_cb {
void *skey;
void *ckey;

- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
struct timer_list watchdog_timer;
struct work_struct tqueue;

diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 6b9d5a0..8eeaa8b 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -278,7 +278,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
*/

retval = 0;
- add_wait_queue(&self->open_wait, &wait);
+ add_wait_queue(&self->port.open_wait, &wait);

IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
__FILE__,__LINE__, tty->driver->name, self->open_count );
@@ -336,7 +336,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
}

__set_current_state(TASK_RUNNING);
- remove_wait_queue(&self->open_wait, &wait);
+ remove_wait_queue(&self->port.open_wait, &wait);

if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
@@ -381,6 +381,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
return -ENOMEM;
}

+ tty_port_init(&self->port);
self->magic = IRCOMM_TTY_MAGIC;
self->flow = FLOW_STOP;

@@ -393,8 +394,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)

/* Init some important stuff */
init_timer(&self->watchdog_timer);
- init_waitqueue_head(&self->open_wait);
- init_waitqueue_head(&self->close_wait);
spin_lock_init(&self->spinlock);

/*
@@ -408,6 +407,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
tty->termios->c_oflag = 0;

/* Insert into hash */
+ /* FIXME there is a window from find to here */
hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
}
/* ++ is not atomic, so this should be protected - Jean II */
@@ -438,7 +438,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
* probably better sleep uninterruptible?
*/

- if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) {
+ if (wait_event_interruptible(self->port.close_wait,
+ !test_bit(ASYNC_B_CLOSING, &self->flags))) {
IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
__func__);
return -ERESTARTSYS;
@@ -559,11 +560,11 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
if (self->blocked_open) {
if (self->close_delay)
schedule_timeout_interruptible(self->close_delay);
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
}

self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&self->close_wait);
+ wake_up_interruptible(&self->port.close_wait);
}

/*
@@ -1011,7 +1012,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
self->open_count = 0;
spin_unlock_irqrestore(&self->spinlock, flags);

- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
}

/*
@@ -1084,7 +1085,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
(status & IRCOMM_CD) ? "on" : "off");

if (status & IRCOMM_CD) {
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
} else {
IRDA_DEBUG(2,
"%s(), Doing serial hangup..\n", __func__ );
@@ -1103,7 +1104,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
tty->hw_stopped = 0;

/* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);

schedule_work(&self->tqueue);
return;
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index b65d66e..bb1e935 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -575,7 +575,7 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
self->tty->hw_stopped = 0;

/* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
+ wake_up_interruptible(&self->port.open_wait);
}

schedule_work(&self->tqueue);
--
1.7.10.3

2012-06-04 11:37:35

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 24/24] TTY: use tty_port_register_device

Currently we have no way to assign tty->port while performing tty
installataion. There are two ways to provide the link tty_struct =>
tty_port. Either by calling tty_port_install from tty->ops->install or
tty_port_register_device called instead of tty_register_device when
the device is being set up after connected.

In this patch we modify most of the drivers to do the latter. When the
drivers use tty_register_device and we have tty_port already, we
switch to tty_port_register_device. So we have the tty_struct =>
tty_port link for free for those.

The rest of the drivers will be changed in the next merge windows (I
ran out of time for this one).

Signed-off-by: Jiri Slaby <[email protected]>
---
arch/um/drivers/line.c | 3 ++-
drivers/isdn/capi/capi.c | 3 ++-
drivers/isdn/gigaset/interface.c | 3 ++-
drivers/mmc/card/sdio_uart.c | 4 ++--
drivers/net/usb/hso.c | 7 ++++---
drivers/tty/cyclades.c | 16 +++++++++-------
drivers/tty/ehv_bytechan.c | 9 +++++----
drivers/tty/ipwireless/tty.c | 2 +-
drivers/tty/isicom.c | 3 ++-
drivers/tty/mxser.c | 6 ++++--
drivers/tty/nozomi.c | 4 ++--
drivers/tty/rocket.c | 4 ++--
drivers/tty/serial/ifx6x60.c | 4 ++--
drivers/tty/serial/msm_smd_tty.c | 8 +++++---
drivers/tty/serial/serial_core.c | 3 ++-
drivers/tty/synclink_gt.c | 7 +++++--
drivers/usb/class/cdc-acm.c | 3 ++-
drivers/usb/gadget/u_serial.c | 3 ++-
net/bluetooth/rfcomm/tty.c | 4 ++--
19 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index fb6e4ea..46efa0f 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -510,7 +510,8 @@ int setup_one_line(struct line *lines, int n, char *init,
line->valid = 1;
err = parse_chan_pair(new, line, n, opts, error_out);
if (!err) {
- struct device *d = tty_register_device(driver, n, NULL);
+ struct device *d = tty_port_register_device(&line->port,
+ driver, n, NULL);
if (IS_ERR(d)) {
*error_out = "Failed to register device";
err = PTR_ERR(d);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 38c4bd8..c679867 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -234,7 +234,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)

mp->minor = minor;

- dev = tty_register_device(capinc_tty_driver, minor, NULL);
+ dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor,
+ NULL);
if (IS_ERR(dev))
goto err_out2;

diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index a6d9fd2..3e8c1e0 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -524,7 +524,8 @@ void gigaset_if_init(struct cardstate *cs)
tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs);

mutex_lock(&cs->mutex);
- cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
+ cs->tty_dev = tty_port_register_device(&cs->port, drv->tty,
+ cs->minor_index, NULL);

if (!IS_ERR(cs->tty_dev))
dev_set_drvdata(cs->tty_dev, cs);
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 5a2cbfa..4bba7b8 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -1132,8 +1132,8 @@ static int sdio_uart_probe(struct sdio_func *func,
kfree(port);
} else {
struct device *dev;
- dev = tty_register_device(sdio_uart_tty_driver,
- port->index, &func->dev);
+ dev = tty_port_register_device(&port->port,
+ sdio_uart_tty_driver, port->index, &func->dev);
if (IS_ERR(dev)) {
sdio_uart_port_remove(port);
ret = PTR_ERR(dev);
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 62f30b4..8e83860 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2289,9 +2289,11 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
if (minor < 0)
goto exit;

+ tty_port_init(&serial->port);
+
/* register our minor number */
- serial->parent->dev = tty_register_device(tty_drv, minor,
- &serial->parent->interface->dev);
+ serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
+ minor, &serial->parent->interface->dev);
dev = serial->parent->dev;
dev_set_drvdata(dev, serial->parent);
i = device_create_file(dev, &dev_attr_hsotype);
@@ -2300,7 +2302,6 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
serial->minor = minor;
serial->magic = HSO_SERIAL_MAGIC;
spin_lock_init(&serial->serial_lock);
- tty_port_init(&serial->port);
serial->num_rx_urbs = num_urbs;

/* RX, allocate urb and initialize */
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index cff5468..ef0a774 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -3292,7 +3292,7 @@ static int __init cy_detect_isa(void)
struct cyclades_card *card;
unsigned short cy_isa_irq, nboard;
void __iomem *cy_isa_address;
- unsigned short i, j, cy_isa_nchan;
+ unsigned short i, j, k, cy_isa_nchan;
int isparam = 0;

nboard = 0;
@@ -3395,9 +3395,10 @@ static int __init cy_detect_isa(void)
(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
cy_isa_irq, cy_isa_nchan, cy_next_channel);

- for (j = cy_next_channel;
- j < cy_next_channel + cy_isa_nchan; j++)
- tty_register_device(cy_serial_driver, j, NULL);
+ for (k = 0, j = cy_next_channel;
+ j < cy_next_channel + cy_isa_nchan; j++, k++)
+ tty_port_register_device(&card->ports[k].port,
+ cy_serial_driver, j, NULL);
cy_next_channel += cy_isa_nchan;
}
return nboard;
@@ -3701,7 +3702,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
void __iomem *addr0 = NULL, *addr2 = NULL;
char *card_name = NULL;
u32 uninitialized_var(mailbox);
- unsigned int device_id, nchan = 0, card_no, i;
+ unsigned int device_id, nchan = 0, card_no, i, j;
unsigned char plx_ver;
int retval, irq;

@@ -3912,8 +3913,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,

dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
- for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
- tty_register_device(cy_serial_driver, i, &pdev->dev);
+ for (j = 0, i = cy_next_channel; i < cy_next_channel + nchan; i++, j++)
+ tty_port_register_device(&card->ports[j].port,
+ cy_serial_driver, i, &pdev->dev);
cy_next_channel += nchan;

return 0;
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 4813684..4ab936b 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -738,16 +738,17 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
goto error;
}

- bc->dev = tty_register_device(ehv_bc_driver, i, &pdev->dev);
+ tty_port_init(&bc->port);
+ bc->port.ops = &ehv_bc_tty_port_ops;
+
+ bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i,
+ &pdev->dev);
if (IS_ERR(bc->dev)) {
ret = PTR_ERR(bc->dev);
dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret);
goto error;
}

- tty_port_init(&bc->port);
- bc->port.ops = &ehv_bc_tty_port_ops;
-
dev_set_drvdata(&pdev->dev, bc);

dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n",
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index f8b5fa0..160f0ad 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -476,7 +476,7 @@ static int add_tty(int j,
mutex_init(&ttys[j]->ipw_tty_mutex);
tty_port_init(&ttys[j]->port);

- tty_register_device(ipw_tty_driver, j, NULL);
+ tty_port_register_device(&ttys[j]->port, ipw_tty_driver, j, NULL);
ipwireless_associate_network_tty(network, channel_idx, ttys[j]);

if (secondary_channel_idx != -1)
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
index e1235ac..8060690 100644
--- a/drivers/tty/isicom.c
+++ b/drivers/tty/isicom.c
@@ -1611,7 +1611,8 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
goto errunri;

for (index = 0; index < board->port_count; index++)
- tty_register_device(isicom_normal, board->index * 16 + index,
+ tty_port_register_device(&board->ports[index].port,
+ isicom_normal, board->index * 16 + index,
&pdev->dev);

return 0;
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 90cc680..9ac15e7 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -2598,7 +2598,8 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
goto err_rel3;

for (i = 0; i < brd->info->nports; i++)
- tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
+ tty_port_register_device(&brd->ports[i].port, mxvar_sdriver,
+ brd->idx + i, &pdev->dev);

pci_set_drvdata(pdev, brd);

@@ -2695,7 +2696,8 @@ static int __init mxser_module_init(void)

brd->idx = m * MXSER_PORTS_PER_BOARD;
for (i = 0; i < brd->info->nports; i++)
- tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
+ tty_port_register_device(&brd->ports[i].port,
+ mxvar_sdriver, brd->idx + i, NULL);

m++;
}
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index e7592f9..b917c94 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -1473,8 +1473,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
port->dc = dc;
tty_port_init(&port->port);
port->port.ops = &noz_tty_port_ops;
- tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
- &pdev->dev);
+ tty_dev = tty_port_register_device(&port->port, ntty_driver,
+ dc->index_start + i, &pdev->dev);

if (IS_ERR(tty_dev)) {
ret = PTR_ERR(tty_dev);
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 777d5f9..f64b308 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -704,8 +704,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
spin_lock_init(&info->slock);
mutex_init(&info->write_mtx);
rp_table[line] = info;
- tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
- NULL);
+ tty_port_register_device(&info->port, rocket_driver, line,
+ pci_dev ? &pci_dev->dev : NULL);
}

/*
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 144cd39..3f0c256 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -800,8 +800,8 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
tty_port_init(pport);
pport->ops = &ifx_tty_port_ops;
ifx_dev->minor = IFX_SPI_TTY_ID;
- ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
- &ifx_dev->spi_dev->dev);
+ ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv,
+ ifx_dev->minor, &ifx_dev->spi_dev->dev);
if (IS_ERR(ifx_dev->tty_dev)) {
dev_dbg(&ifx_dev->spi_dev->dev,
"%s: registering tty device failed", __func__);
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
index b25e6ee..925d1fa 100644
--- a/drivers/tty/serial/msm_smd_tty.c
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -223,9 +223,11 @@ static int __init smd_tty_init(void)
return ret;

for (i = 0; i < smd_tty_channels_len; i++) {
- tty_port_init(&smd_tty[smd_tty_channels[i].id].port);
- smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops;
- tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0);
+ struct tty_port *port = &smd_tty[smd_tty_channels[i].id].port;
+ tty_port_init(port);
+ port->ops = &smd_tty_port_ops;
+ tty_port_register_device(port, smd_tty_driver,
+ smd_tty_channels[i].id, NULL);
}

return 0;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 246b823..dafd378 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2346,7 +2346,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters.
*/
- tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
+ tty_dev = tty_port_register_device(port, drv->tty_driver, uport->line,
+ uport->dev);
if (likely(!IS_ERR(tty_dev))) {
device_set_wakeup_capable(tty_dev, 1);
} else {
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index aa1debf..8a4addd 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -3689,8 +3689,11 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
}
}

- for (i=0; i < port_count; ++i)
- tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
+ for (i = 0; i < port_count; ++i) {
+ struct slgt_info *info = port_array[i];
+ tty_port_register_device(&info->port, serial_driver, info->line,
+ &info->pdev->dev);
+ }
}

static int __devinit init_one(struct pci_dev *dev,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index f2a120e..96f1a6a 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1290,7 +1290,8 @@ skip_countries:
usb_set_intfdata(data_interface, acm);

usb_get_intf(control_interface);
- tty_register_device(acm_tty_driver, minor, &control_interface->dev);
+ tty_port_register_device(&acm->port, acm_tty_driver, minor,
+ &control_interface->dev);

return 0;
alloc_fail7:
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 5b3f5ff..2b5534c 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1129,7 +1129,8 @@ int gserial_setup(struct usb_gadget *g, unsigned count)
for (i = 0; i < count; i++) {
struct device *tty_dev;

- tty_dev = tty_register_device(gs_tty_driver, i, &g->dev);
+ tty_dev = tty_port_register_device(&ports[i].port->port,
+ gs_tty_driver, i, &g->dev);
if (IS_ERR(tty_dev))
pr_warning("%s: no classdev for port %d, err %ld\n",
__func__, i, PTR_ERR(tty_dev));
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index cb96077..f89c568 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -278,8 +278,8 @@ out:
if (err < 0)
goto free;

- dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
-
+ dev->tty_dev = tty_port_register_device(&dev->port, rfcomm_tty_driver,
+ dev->id, NULL);
if (IS_ERR(dev->tty_dev)) {
err = PTR_ERR(dev->tty_dev);
list_del(&dev->list);
--
1.7.10.3

2012-06-04 11:37:33

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 04/24] TTY: ircomm, use open counts from tty_port

Switch to tty_port->count and blocked_open.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
include/net/irda/ircomm_tty.h | 3 ---
net/irda/ircomm/ircomm_tty.c | 42 ++++++++++++++++++++---------------------
2 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index b4184d0..5e94bad 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -101,9 +101,6 @@ struct ircomm_tty_cb {
struct timer_list watchdog_timer;
struct work_struct tqueue;

- int open_count;
- int blocked_open; /* # of blocked opens */
-
/* Protect concurent access to :
* o self->open_count
* o self->ctrl_skb
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 61e0adc..787578f 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -272,7 +272,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,

/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, self->open_count is dropped by one, so that
+ * this loop, self->port.count is dropped by one, so that
* mgsl_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
@@ -281,16 +281,16 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
add_wait_queue(&self->port.open_wait, &wait);

IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count );
+ __FILE__, __LINE__, tty->driver->name, self->port.count);

- /* As far as I can see, we protect open_count - Jean II */
+ /* As far as I can see, we protect port.count - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
- self->open_count--;
+ self->port.count--;
}
spin_unlock_irqrestore(&self->spinlock, flags);
- self->blocked_open++;
+ self->port.blocked_open++;

while (1) {
if (tty->termios->c_cflag & CBAUD) {
@@ -330,7 +330,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
}

IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count );
+ __FILE__, __LINE__, tty->driver->name, self->port.count);

schedule();
}
@@ -341,13 +341,13 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
- self->open_count++;
+ self->port.count++;
spin_unlock_irqrestore(&self->spinlock, flags);
}
- self->blocked_open--;
+ self->port.blocked_open--;

IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
- __FILE__,__LINE__, tty->driver->name, self->open_count);
+ __FILE__, __LINE__, tty->driver->name, self->port.count);

if (!retval)
self->flags |= ASYNC_NORMAL_ACTIVE;
@@ -410,14 +410,14 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
}
/* ++ is not atomic, so this should be protected - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
- self->open_count++;
+ self->port.count++;

tty->driver_data = self;
self->tty = tty;
spin_unlock_irqrestore(&self->spinlock, flags);

IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
- self->line, self->open_count);
+ self->line, self->port.count);

/* Not really used by us, but lets do it anyway */
self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
@@ -504,7 +504,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
return;
}

- if ((tty->count == 1) && (self->open_count != 1)) {
+ if ((tty->count == 1) && (self->port.count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. state->count should always
@@ -514,16 +514,16 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
*/
IRDA_DEBUG(0, "%s(), bad serial port count; "
"tty->count is 1, state->count is %d\n", __func__ ,
- self->open_count);
- self->open_count = 1;
+ self->port.count);
+ self->port.count = 1;
}

- if (--self->open_count < 0) {
+ if (--self->port.count < 0) {
IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
- __func__, self->line, self->open_count);
- self->open_count = 0;
+ __func__, self->line, self->port.count);
+ self->port.count = 0;
}
- if (self->open_count) {
+ if (self->port.count) {
spin_unlock_irqrestore(&self->spinlock, flags);

IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
@@ -555,7 +555,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
tty->closing = 0;
self->tty = NULL;

- if (self->blocked_open) {
+ if (self->port.blocked_open) {
if (self->port.close_delay)
schedule_timeout_interruptible(self->port.close_delay);
wake_up_interruptible(&self->port.open_wait);
@@ -1007,7 +1007,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
spin_lock_irqsave(&self->spinlock, flags);
self->flags &= ~ASYNC_NORMAL_ACTIVE;
self->tty = NULL;
- self->open_count = 0;
+ self->port.count = 0;
spin_unlock_irqrestore(&self->spinlock, flags);

wake_up_interruptible(&self->port.open_wait);
@@ -1354,7 +1354,7 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
seq_putc(m, '\n');

seq_printf(m, "Role: %s\n", self->client ? "client" : "server");
- seq_printf(m, "Open count: %d\n", self->open_count);
+ seq_printf(m, "Open count: %d\n", self->port.count);
seq_printf(m, "Max data size: %d\n", self->max_data_size);
seq_printf(m, "Max header size: %d\n", self->max_header_size);

--
1.7.10.3

2012-06-04 11:37:32

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 07/24] TTY: ircomm, use tty from tty_port

This also includes a switch to tty refcounting. It makes sure, the
code no longer can access a freed TTY struct.

Sometimes the only thing needed is to pass tty down to the callies.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
include/net/irda/ircomm_tty.h | 1 -
net/irda/ircomm/ircomm_param.c | 5 ---
net/irda/ircomm/ircomm_tty.c | 62 ++++++++++++++++++++++-------------
net/irda/ircomm/ircomm_tty_attach.c | 33 ++++++++++++++-----
net/irda/ircomm/ircomm_tty_ioctl.c | 11 ++++---
5 files changed, 70 insertions(+), 42 deletions(-)

diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index a9027d8..80ffde3 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -62,7 +62,6 @@ struct ircomm_tty_cb {

int state; /* Connect state */

- struct tty_struct *tty;
struct ircomm_cb *ircomm; /* IrCOMM layer instance */

struct sk_buff *tx_skb; /* Transmit buffer */
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index 8b915f3..3089391 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -99,7 +99,6 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };
*/
int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
{
- struct tty_struct *tty;
unsigned long flags;
struct sk_buff *skb;
int count;
@@ -109,10 +108,6 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
IRDA_ASSERT(self != NULL, return -1;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);

- tty = self->tty;
- if (!tty)
- return 0;
-
/* Make sure we don't send parameters for raw mode */
if (self->service_type == IRCOMM_3_WIRE_RAW)
return 0;
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 7b2152c..03acc07 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -242,18 +242,15 @@ err:
*
*/
static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
- struct file *filp)
+ struct tty_struct *tty, struct file *filp)
{
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0, extra_count = 0;
unsigned long flags;
- struct tty_struct *tty;

IRDA_DEBUG(2, "%s()\n", __func__ );

- tty = self->tty;
-
/*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
@@ -412,8 +409,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
self->port.count++;

tty->driver_data = self;
- self->tty = tty;
spin_unlock_irqrestore(&self->port.lock, flags);
+ tty_port_tty_set(&self->port, tty);

IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
self->line, self->port.count);
@@ -467,7 +464,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
if (ret)
return ret;

- ret = ircomm_tty_block_til_ready(self, filp);
+ ret = ircomm_tty_block_til_ready(self, tty, filp);
if (ret) {
IRDA_DEBUG(2,
"%s(), returning after block_til_ready with %d\n", __func__ ,
@@ -548,7 +545,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)

spin_lock_irqsave(&self->port.lock, flags);
tty->closing = 0;
- self->tty = NULL;

if (self->port.blocked_open) {
if (self->port.close_delay) {
@@ -562,6 +558,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
self->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
spin_unlock_irqrestore(&self->port.lock, flags);
wake_up_interruptible(&self->port.close_wait);
+ tty_port_tty_set(&self->port, NULL);
}

/*
@@ -604,7 +601,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
if (!self || self->magic != IRCOMM_TTY_MAGIC)
return;

- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);
if (!tty)
return;

@@ -625,7 +622,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
}

if (tty->hw_stopped)
- return;
+ goto put;

/* Unlink transmit buffer */
spin_lock_irqsave(&self->spinlock, flags);
@@ -644,6 +641,8 @@ static void ircomm_tty_do_softint(struct work_struct *work)

/* Check if user (still) wants to be waken up */
tty_wakeup(tty);
+put:
+ tty_kref_put(tty);
}

/*
@@ -1004,7 +1003,11 @@ static void ircomm_tty_hangup(struct tty_struct *tty)

spin_lock_irqsave(&self->port.lock, flags);
self->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- self->tty = NULL;
+ if (self->port.tty) {
+ set_bit(TTY_IO_ERROR, &self->port.tty->flags);
+ tty_kref_put(self->port.tty);
+ }
+ self->port.tty = NULL;
self->port.count = 0;
spin_unlock_irqrestore(&self->port.lock, flags);

@@ -1068,7 +1071,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);

status = self->settings.dce;

@@ -1089,10 +1092,10 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
tty_hangup(tty);

/* Hangup will remote the tty, so better break out */
- return;
+ goto put;
}
}
- if (self->port.flags & ASYNC_CTS_FLOW) {
+ if (tty && self->port.flags & ASYNC_CTS_FLOW) {
if (tty->hw_stopped) {
if (status & IRCOMM_CTS) {
IRDA_DEBUG(2,
@@ -1103,7 +1106,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
wake_up_interruptible(&self->port.open_wait);

schedule_work(&self->tqueue);
- return;
+ goto put;
}
} else {
if (!(status & IRCOMM_CTS)) {
@@ -1113,6 +1116,8 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
}
}
}
+put:
+ tty_kref_put(tty);
}

/*
@@ -1125,6 +1130,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
struct sk_buff *skb)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ struct tty_struct *tty;

IRDA_DEBUG(2, "%s()\n", __func__ );

@@ -1132,7 +1138,8 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
IRDA_ASSERT(skb != NULL, return -1;);

- if (!self->tty) {
+ tty = tty_port_tty_get(&self->port);
+ if (!tty) {
IRDA_DEBUG(0, "%s(), no tty!\n", __func__ );
return 0;
}
@@ -1143,7 +1150,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
* Devices like WinCE can do this, and since they don't send any
* params, we can just as well declare the hardware for running.
*/
- if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+ if (tty->hw_stopped && (self->flow == FLOW_START)) {
IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ );
ircomm_param_request(self, IRCOMM_POLL, TRUE);

@@ -1156,8 +1163,9 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
* Use flip buffer functions since the code may be called from interrupt
* context
*/
- tty_insert_flip_string(self->tty, skb->data, skb->len);
- tty_flip_buffer_push(self->tty);
+ tty_insert_flip_string(tty, skb->data, skb->len);
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);

/* No need to kfree_skb - see ircomm_ttp_data_indication() */

@@ -1208,12 +1216,13 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- tty = self->tty;
+ tty = tty_port_tty_get(&self->port);

switch (cmd) {
case FLOW_START:
IRDA_DEBUG(2, "%s(), hw start!\n", __func__ );
- tty->hw_stopped = 0;
+ if (tty)
+ tty->hw_stopped = 0;

/* ircomm_tty_do_softint will take care of the rest */
schedule_work(&self->tqueue);
@@ -1221,15 +1230,19 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
default: /* If we get here, something is very wrong, better stop */
case FLOW_STOP:
IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ );
- tty->hw_stopped = 1;
+ if (tty)
+ tty->hw_stopped = 1;
break;
}
+
+ tty_kref_put(tty);
self->flow = cmd;
}

#ifdef CONFIG_PROC_FS
static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
{
+ struct tty_struct *tty;
char sep;

seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]);
@@ -1356,9 +1369,12 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)
seq_printf(m, "Max data size: %d\n", self->max_data_size);
seq_printf(m, "Max header size: %d\n", self->max_header_size);

- if (self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (tty) {
seq_printf(m, "Hardware: %s\n",
- self->tty->hw_stopped ? "Stopped" : "Running");
+ tty->hw_stopped ? "Stopped" : "Running");
+ tty_kref_put(tty);
+ }
}

static int ircomm_tty_proc_show(struct seq_file *m, void *v)
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index bed311a..3ab70e7 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -130,6 +130,8 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
*/
int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
{
+ struct tty_struct *tty;
+
IRDA_DEBUG(0, "%s()\n", __func__ );

IRDA_ASSERT(self != NULL, return -1;);
@@ -142,7 +144,11 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
}

/* Make sure nobody tries to write before the link is up */
- self->tty->hw_stopped = 1;
+ tty = tty_port_tty_get(&self->port);
+ if (tty) {
+ tty->hw_stopped = 1;
+ tty_kref_put(tty);
+ }

ircomm_tty_ias_register(self);

@@ -398,23 +404,26 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap,
struct sk_buff *skb)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ struct tty_struct *tty;

IRDA_DEBUG(2, "%s()\n", __func__ );

IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- if (!self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (!tty)
return;

/* This will stop control data transfers */
self->flow = FLOW_STOP;

/* Stop data transfers */
- self->tty->hw_stopped = 1;
+ tty->hw_stopped = 1;

ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
NULL);
+ tty_kref_put(tty);
}

/*
@@ -550,12 +559,15 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
*/
void ircomm_tty_link_established(struct ircomm_tty_cb *self)
{
+ struct tty_struct *tty;
+
IRDA_DEBUG(2, "%s()\n", __func__ );

IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);

- if (!self->tty)
+ tty = tty_port_tty_get(&self->port);
+ if (!tty)
return;

del_timer(&self->watchdog_timer);
@@ -569,17 +581,19 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
if ((self->port.flags & ASYNC_CTS_FLOW) &&
((self->settings.dce & IRCOMM_CTS) == 0)) {
IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
- return;
+ goto put;
} else {
IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );

- self->tty->hw_stopped = 0;
+ tty->hw_stopped = 0;

/* Wake up processes blocked on open */
wake_up_interruptible(&self->port.open_wait);
}

schedule_work(&self->tqueue);
+put:
+ tty_kref_put(tty);
}

/*
@@ -983,9 +997,12 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
self->settings.dce = IRCOMM_DELTA_CD;
ircomm_tty_check_modem_status(self);
} else {
+ struct tty_struct *tty = tty_port_tty_get(&self->port);
IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
- if (self->tty)
- tty_hangup(self->tty);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
}
break;
default:
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index 31b917e..0eab650 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -52,17 +52,18 @@
* Change speed of the driver. If the remote device is a DCE, then this
* should make it change the speed of its serial port
*/
-static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+static void ircomm_tty_change_speed(struct ircomm_tty_cb *self,
+ struct tty_struct *tty)
{
unsigned int cflag, cval;
int baud;

IRDA_DEBUG(2, "%s()\n", __func__ );

- if (!self->tty || !self->tty->termios || !self->ircomm)
+ if (!self->ircomm)
return;

- cflag = self->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;

/* byte size and parity */
switch (cflag & CSIZE) {
@@ -81,7 +82,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
cval |= IRCOMM_PARITY_EVEN;

/* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(self->tty);
+ baud = tty_get_baud_rate(tty);
if (!baud)
baud = 9600; /* B0 transition handled in rs_set_termios */

@@ -159,7 +160,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty,
return;
}

- ircomm_tty_change_speed(self);
+ ircomm_tty_change_speed(self, tty);

/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) &&
--
1.7.10.3

2012-06-04 11:37:30

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 05/24] TTY: ircomm, use flags from tty_port

Switch to tty_port->flags. And while at it, remove redefined flags for
them.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: [email protected]
---
include/net/irda/ircomm_tty.h | 6 -----
net/irda/ircomm/ircomm_tty.c | 46 +++++++++++++++++------------------
net/irda/ircomm/ircomm_tty_attach.c | 5 ++--
net/irda/ircomm/ircomm_tty_ioctl.c | 10 ++++----
4 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 5e94bad..e4db3b5 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -52,11 +52,6 @@
/* Same for payload size. See qos.c for the smallest max data size */
#define IRCOMM_TTY_DATA_UNINITIALISED (64 - IRCOMM_TTY_HDR_UNINITIALISED)

-/* Those are really defined in include/linux/serial.h - Jean II */
-#define ASYNC_B_INITIALIZED 31 /* Serial port was initialized */
-#define ASYNC_B_NORMAL_ACTIVE 29 /* Normal device is active */
-#define ASYNC_B_CLOSING 27 /* Serial port is closing */
-
/*
* IrCOMM TTY driver state
*/
@@ -81,7 +76,6 @@ struct ircomm_tty_cb {
LOCAL_FLOW flow; /* IrTTP flow status */

int line;
- unsigned long flags;

__u8 dlsap_sel;
__u8 slsap_sel;
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 787578f..8e61026 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -194,7 +194,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);

/* Check if already open */
- if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) {
+ if (test_and_set_bit(ASYNCB_INITIALIZED, &self->port.flags)) {
IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ );
return 0;
}
@@ -231,7 +231,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)

return 0;
err:
- clear_bit(ASYNC_B_INITIALIZED, &self->flags);
+ clear_bit(ASYNCB_INITIALIZED, &self->port.flags);
return ret;
}

@@ -260,7 +260,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
*/
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
- self->flags |= ASYNC_NORMAL_ACTIVE;
+ self->port.flags |= ASYNC_NORMAL_ACTIVE;
IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
return 0;
}
@@ -306,8 +306,8 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
current->state = TASK_INTERRUPTIBLE;

if (tty_hung_up_p(filp) ||
- !test_bit(ASYNC_B_INITIALIZED, &self->flags)) {
- retval = (self->flags & ASYNC_HUP_NOTIFY) ?
+ !test_bit(ASYNCB_INITIALIZED, &self->port.flags)) {
+ retval = (self->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
@@ -317,7 +317,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
* specified, we cannot return before the IrCOMM link is
* ready
*/
- if (!test_bit(ASYNC_B_CLOSING, &self->flags) &&
+ if (!test_bit(ASYNCB_CLOSING, &self->port.flags) &&
(do_clocal || (self->settings.dce & IRCOMM_CD)) &&
self->state == IRCOMM_TTY_READY)
{
@@ -350,7 +350,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
__FILE__, __LINE__, tty->driver->name, self->port.count);

if (!retval)
- self->flags |= ASYNC_NORMAL_ACTIVE;
+ self->port.flags |= ASYNC_NORMAL_ACTIVE;

return retval;
}
@@ -420,13 +420,13 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
self->line, self->port.count);

/* Not really used by us, but lets do it anyway */
- self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;

/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
- test_bit(ASYNC_B_CLOSING, &self->flags)) {
+ test_bit(ASYNCB_CLOSING, &self->port.flags)) {

/* Hm, why are we blocking on ASYNC_CLOSING if we
* do return -EAGAIN/-ERESTARTSYS below anyway?
@@ -437,14 +437,14 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
*/

if (wait_event_interruptible(self->port.close_wait,
- !test_bit(ASYNC_B_CLOSING, &self->flags))) {
+ !test_bit(ASYNCB_CLOSING, &self->port.flags))) {
IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
__func__);
return -ERESTARTSYS;
}

#ifdef SERIAL_DO_RESTART
- return (self->flags & ASYNC_HUP_NOTIFY) ?
+ return (self->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
#else
return -EAGAIN;
@@ -531,7 +531,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
}

/* Hum... Should be test_and_set_bit ??? - Jean II */
- set_bit(ASYNC_B_CLOSING, &self->flags);
+ set_bit(ASYNCB_CLOSING, &self->port.flags);

/* We need to unlock here (we were unlocking at the end of this
* function), because tty_wait_until_sent() may schedule.
@@ -561,7 +561,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&self->port.open_wait);
}

- self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+ self->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&self->port.close_wait);
}

@@ -954,7 +954,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)

IRDA_DEBUG(0, "%s()\n", __func__ );

- if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags))
+ if (!test_and_clear_bit(ASYNCB_INITIALIZED, &self->port.flags))
return;

ircomm_tty_detach_cable(self);
@@ -1005,7 +1005,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)

/* I guess we need to lock here - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
- self->flags &= ~ASYNC_NORMAL_ACTIVE;
+ self->port.flags &= ~ASYNC_NORMAL_ACTIVE;
self->tty = NULL;
self->port.count = 0;
spin_unlock_irqrestore(&self->spinlock, flags);
@@ -1077,7 +1077,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
if (status & IRCOMM_DCE_DELTA_ANY) {
/*wake_up_interruptible(&self->delta_msr_wait);*/
}
- if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+ if ((self->port.flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
IRDA_DEBUG(2,
"%s(), ircomm%d CD now %s...\n", __func__ , self->line,
(status & IRCOMM_CD) ? "on" : "off");
@@ -1094,7 +1094,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
return;
}
}
- if (self->flags & ASYNC_CTS_FLOW) {
+ if (self->port.flags & ASYNC_CTS_FLOW) {
if (tty->hw_stopped) {
if (status & IRCOMM_CTS) {
IRDA_DEBUG(2,
@@ -1327,27 +1327,27 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m)

seq_puts(m, "Flags:");
sep = ' ';
- if (self->flags & ASYNC_CTS_FLOW) {
+ if (self->port.flags & ASYNC_CTS_FLOW) {
seq_printf(m, "%cASYNC_CTS_FLOW", sep);
sep = '|';
}
- if (self->flags & ASYNC_CHECK_CD) {
+ if (self->port.flags & ASYNC_CHECK_CD) {
seq_printf(m, "%cASYNC_CHECK_CD", sep);
sep = '|';
}
- if (self->flags & ASYNC_INITIALIZED) {
+ if (self->port.flags & ASYNC_INITIALIZED) {
seq_printf(m, "%cASYNC_INITIALIZED", sep);
sep = '|';
}
- if (self->flags & ASYNC_LOW_LATENCY) {
+ if (self->port.flags & ASYNC_LOW_LATENCY) {
seq_printf(m, "%cASYNC_LOW_LATENCY", sep);
sep = '|';
}
- if (self->flags & ASYNC_CLOSING) {
+ if (self->port.flags & ASYNC_CLOSING) {
seq_printf(m, "%cASYNC_CLOSING", sep);
sep = '|';
}
- if (self->flags & ASYNC_NORMAL_ACTIVE) {
+ if (self->port.flags & ASYNC_NORMAL_ACTIVE) {
seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep);
sep = '|';
}
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index bb1e935..bed311a 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -566,7 +566,8 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
* will have to wait for the peer device (DCE) to raise the CTS
* line.
*/
- if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
+ if ((self->port.flags & ASYNC_CTS_FLOW) &&
+ ((self->settings.dce & IRCOMM_CTS) == 0)) {
IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
return;
} else {
@@ -977,7 +978,7 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
ircomm_tty_start_watchdog_timer(self, 3*HZ);

- if (self->flags & ASYNC_CHECK_CD) {
+ if (self->port.flags & ASYNC_CHECK_CD) {
/* Drop carrier */
self->settings.dce = IRCOMM_DELTA_CD;
ircomm_tty_check_modem_status(self);
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index a6d25e3..31b917e 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -90,19 +90,19 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)

/* CTS flow control flag and modem status interrupts */
if (cflag & CRTSCTS) {
- self->flags |= ASYNC_CTS_FLOW;
+ self->port.flags |= ASYNC_CTS_FLOW;
self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
/* This got me. Bummer. Jean II */
if (self->service_type == IRCOMM_3_WIRE_RAW)
IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__);
} else {
- self->flags &= ~ASYNC_CTS_FLOW;
+ self->port.flags &= ~ASYNC_CTS_FLOW;
self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
}
if (cflag & CLOCAL)
- self->flags &= ~ASYNC_CHECK_CD;
+ self->port.flags &= ~ASYNC_CHECK_CD;
else
- self->flags |= ASYNC_CHECK_CD;
+ self->port.flags |= ASYNC_CHECK_CD;
#if 0
/*
* Set up parity check flag
@@ -270,7 +270,7 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,

memset(&info, 0, sizeof(info));
info.line = self->line;
- info.flags = self->flags;
+ info.flags = self->port.flags;
info.baud_base = self->settings.data_rate;
info.close_delay = self->port.close_delay;
info.closing_wait = self->port.closing_wait;
--
1.7.10.3

2012-06-04 11:40:35

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 21/24] TTY: centralize fail paths in tty_register_driver

Currently, some failures are handled in if's false branches, some at
the end of tty_register_driver via goto-labels. Let us handle the
failures at the end of the functions to have the failure handling at
a single place. The only thing needed is to label the lines properly
and jump there.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/tty_io.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79..d6e045b 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3144,10 +3144,8 @@ int tty_register_driver(struct tty_driver *driver)
dev = MKDEV(driver->major, driver->minor_start);
error = register_chrdev_region(dev, driver->num, driver->name);
}
- if (error < 0) {
- kfree(p);
- return error;
- }
+ if (error < 0)
+ goto err_free_p;

if (p) {
driver->ttys = (struct tty_struct **)p;
@@ -3160,13 +3158,8 @@ int tty_register_driver(struct tty_driver *driver)
cdev_init(&driver->cdev, &tty_fops);
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
- if (error) {
- unregister_chrdev_region(dev, driver->num);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
- return error;
- }
+ if (error)
+ goto err_unreg_char;

mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers);
@@ -3193,13 +3186,14 @@ err:
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);

+err_unreg_char:
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = NULL;
+err_free_p:
kfree(p);
return error;
}
-
EXPORT_SYMBOL(tty_register_driver);

/*
--
1.7.10.3

2012-06-04 11:40:40

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 23/24] TTY: add tty_port_register_device helper

This will automatically assign tty_port to tty_driver's port array for
later recall in tty_init_dev. This is intended to be called instead of
tty_register_device.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/tty_port.c | 9 +++++++++
include/linux/tty.h | 3 +++
2 files changed, 12 insertions(+)

diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 1ac8abf..4e9d2b2 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -33,6 +33,15 @@ void tty_port_init(struct tty_port *port)
}
EXPORT_SYMBOL(tty_port_init);

+struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device)
+{
+ driver->ports[index] = port;
+ return tty_register_device(driver, index, device);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device);
+
int tty_port_alloc_xmit_buf(struct tty_port *port)
{
/* We may sleep in get_zeroed_page() */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 45ef71d..40b18d7 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -497,6 +497,9 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);
#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))

extern void tty_port_init(struct tty_port *port);
+extern struct device *tty_port_register_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index,
+ struct device *device);
extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port);
extern void tty_port_put(struct tty_port *port);
--
1.7.10.3

2012-06-04 11:40:39

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 17/24] TTY: vt, remove con_schedule_flip

This is identical to tty_schedule_flip. So let us use that instead.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/vt/keyboard.c | 6 +++---
drivers/tty/vt/vt.c | 2 +-
include/linux/kbd_kern.h | 12 ------------
3 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 48cc6f2..0b6217c 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -310,7 +310,7 @@ static void put_queue(struct vc_data *vc, int ch)

if (tty) {
tty_insert_flip_char(tty, ch, 0);
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}
}

@@ -325,7 +325,7 @@ static void puts_queue(struct vc_data *vc, char *cp)
tty_insert_flip_char(tty, *cp, 0);
cp++;
}
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}

static void applkey(struct vc_data *vc, int key, char mode)
@@ -586,7 +586,7 @@ static void fn_send_intr(struct vc_data *vc)
if (!tty)
return;
tty_insert_flip_char(tty, 0, TTY_BREAK);
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}

static void fn_scroll_forw(struct vc_data *vc)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 84cbf29..88a4914 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1380,7 +1380,7 @@ static void respond_string(const char *p, struct tty_struct *tty)
tty_insert_flip_char(tty, *p, 0);
p++;
}
- con_schedule_flip(tty);
+ tty_schedule_flip(tty);
}

static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index daf4a3a..af9137d 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -145,16 +145,4 @@ void compute_shiftstate(void);

extern unsigned int keymap_count;

-/* console.c */
-
-static inline void con_schedule_flip(struct tty_struct *t)
-{
- unsigned long flags;
- spin_lock_irqsave(&t->buf.lock, flags);
- if (t->buf.tail != NULL)
- t->buf.tail->commit = t->buf.tail->used;
- spin_unlock_irqrestore(&t->buf.lock, flags);
- schedule_work(&t->buf.work);
-}
-
#endif
--
1.7.10.3

2012-06-04 11:40:37

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 12/24] TTY: um/line, add tty_port

And use count from there.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Jeff Dike <[email protected]>
Cc: Richard Weinberger <[email protected]>
Cc: [email protected]
---
arch/um/drivers/line.c | 7 ++++---
arch/um/drivers/line.h | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index acfd0e0..482a7bd 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -404,7 +404,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
goto out_unlock;

err = 0;
- if (line->count++)
+ if (line->port.count++)
goto out_unlock;

BUG_ON(tty->driver_data);
@@ -446,7 +446,7 @@ void line_close(struct tty_struct *tty, struct file * filp)
mutex_lock(&line->count_lock);
BUG_ON(!line->valid);

- if (--line->count)
+ if (--line->port.count)
goto out_unlock;

line->tty = NULL;
@@ -478,7 +478,7 @@ int setup_one_line(struct line *lines, int n, char *init,

mutex_lock(&line->count_lock);

- if (line->count) {
+ if (line->port.count) {
*error_out = "Device is already open";
goto out;
}
@@ -663,6 +663,7 @@ int register_lines(struct line_driver *line_driver,
driver->init_termios = tty_std_termios;

for (i = 0; i < nlines; i++) {
+ tty_port_init(&lines[i].port);
spin_lock_init(&lines[i].lock);
mutex_init(&lines[i].count_lock);
lines[i].driver = line_driver;
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 0a18347..0e06a1f 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -32,9 +32,9 @@ struct line_driver {
};

struct line {
+ struct tty_port port;
struct tty_struct *tty;
struct mutex count_lock;
- unsigned long count;
int valid;

char *init_str;
--
1.7.10.3

2012-06-04 11:40:33

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 14/24] PTY: remove one empty ops->remove

Currently, there are two as a left-over from previous patches.
Although we really need to provide an empty handler, we do not need
two. So remove one of them.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/pty.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 5505ffc..4bcaf89 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -557,18 +557,14 @@ err_free_tty:
return -ENOMEM;
}

-static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
-{
-}
-
-static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{
}

static const struct tty_operations ptm_unix98_ops = {
.lookup = ptm_unix98_lookup,
.install = pty_unix98_install,
- .remove = ptm_unix98_remove,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
@@ -585,7 +581,7 @@ static const struct tty_operations ptm_unix98_ops = {
static const struct tty_operations pty_unix98_ops = {
.lookup = pts_unix98_lookup,
.install = pty_unix98_install,
- .remove = pts_unix98_remove,
+ .remove = pty_unix98_remove,
.open = pty_open,
.close = pty_close,
.write = pty_write,
--
1.7.10.3

2012-06-04 11:40:32

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 20/24] TTY: usb-serial, use tty_port_install

To have tty->port set in ->install.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/usb/serial/usb-serial.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 6a1b609..2dc92d5 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -207,7 +207,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
if (retval)
goto error_get_interface;

- retval = tty_standard_install(driver, tty);
+ retval = tty_port_install(&port->port, driver, tty);
if (retval)
goto error_init_termios;

--
1.7.10.3

2012-06-04 11:40:30

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 16/24] PTY: add tty_port

This has *no* function in the PTY driver yet. However as the tty
buffers will move to the tty_port structure, we will need tty_port for
all TTYs in the system, PTY inclusive.

For PTYs this is ensured by allocating 2 tty_port's in pty_install,
i.e. where the tty->link is allocated. Both tty_port's are properly
assigned to each end of the tty.

Freeing is done at the same place where tty is freed, i.e. in
tty->ops->cleanup.

This means BTW that tty_port does not outlive TTY in PTY. This might
be a subject to change in the future if we see some problems.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/pty.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 881888f..b50fc1c 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -286,12 +286,15 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
bool legacy)
{
struct tty_struct *o_tty;
+ struct tty_port *ports[2];
int idx = tty->index;
int retval = -ENOMEM;

o_tty = alloc_tty_struct();
- if (!o_tty)
- goto err;
+ ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
+ ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
+ if (!o_tty || !ports[0] || !ports[1])
+ goto err_free_tty;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
goto err_free_tty;
@@ -335,6 +338,10 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
/* Establish the links in both directions */
tty->link = o_tty;
o_tty->link = tty;
+ tty_port_init(ports[0]);
+ tty_port_init(ports[1]);
+ o_tty->port = ports[0];
+ tty->port = ports[1];

tty_driver_kref_get(driver);
tty->count++;
@@ -348,11 +355,17 @@ err_deinit_tty:
deinitialize_tty_struct(o_tty);
module_put(o_tty->driver->owner);
err_free_tty:
+ kfree(ports[0]);
+ kfree(ports[1]);
free_tty_struct(o_tty);
-err:
return retval;
}

+static void pty_cleanup(struct tty_struct *tty)
+{
+ kfree(tty->port);
+}
+
/* Traditional BSD devices */
#ifdef CONFIG_LEGACY_PTYS

@@ -391,6 +404,7 @@ static const struct tty_operations master_pty_ops_bsd = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
+ .cleanup = pty_cleanup,
.resize = pty_resize
};

@@ -404,6 +418,7 @@ static const struct tty_operations slave_pty_ops_bsd = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
+ .cleanup = pty_cleanup,
.resize = pty_resize
};

@@ -555,6 +570,7 @@ static const struct tty_operations ptm_unix98_ops = {
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
.shutdown = pty_unix98_shutdown,
+ .cleanup = pty_cleanup,
.resize = pty_resize
};

@@ -570,7 +586,8 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
- .shutdown = pty_unix98_shutdown
+ .shutdown = pty_unix98_shutdown,
+ .cleanup = pty_cleanup,
};

/**
--
1.7.10.3

2012-06-04 11:40:29

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 13/24] TTY: um/line, use tty from tty_port

This means switching to the tty refcounted model so that we will not
race with interrupts.

Signed-off-by: Jiri Slaby <[email protected]>
Cc: Jeff Dike <[email protected]>
Cc: Richard Weinberger <[email protected]>
Cc: [email protected]
---
arch/um/drivers/chan_kern.c | 4 +++-
arch/um/drivers/line.c | 25 ++++++++++++++++++-------
arch/um/drivers/line.h | 1 -
3 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 45e248c..87eebfe 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
static void line_timer_cb(struct work_struct *work)
{
struct line *line = container_of(work, struct line, task.work);
+ struct tty_struct *tty = tty_port_tty_get(&line->port);

if (!line->throttled)
- chan_interrupt(line, line->tty, line->driver->read_irq);
+ chan_interrupt(line, tty, line->driver->read_irq);
+ tty_kref_put(tty);
}

int enable_chan(struct line *line)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 482a7bd..fb6e4ea 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
+ struct tty_struct *tty = tty_port_tty_get(&line->port);

if (line)
- chan_interrupt(line, line->tty, irq);
+ chan_interrupt(line, tty, irq);
+ tty_kref_put(tty);
return IRQ_HANDLED;
}

@@ -333,7 +335,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
- struct tty_struct *tty = line->tty;
+ struct tty_struct *tty;
int err;

/*
@@ -352,10 +354,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
}
spin_unlock(&line->lock);

+ tty = tty_port_tty_get(&line->port);
if (tty == NULL)
return IRQ_NONE;

tty_wakeup(tty);
+ tty_kref_put(tty);
+
return IRQ_HANDLED;
}

@@ -409,7 +414,7 @@ int line_open(struct line *lines, struct tty_struct *tty)

BUG_ON(tty->driver_data);
tty->driver_data = line;
- line->tty = tty;
+ tty_port_tty_set(&line->port, tty);

err = enable_chan(line);
if (err) /* line_close() will be called by our caller */
@@ -449,7 +454,7 @@ void line_close(struct tty_struct *tty, struct file * filp)
if (--line->port.count)
goto out_unlock;

- line->tty = NULL;
+ tty_port_tty_set(&line->port, NULL);
tty->driver_data = NULL;

if (line->sigio) {
@@ -610,9 +615,15 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
mutex_lock(&line->count_lock);
if (!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
- else if (line->tty == NULL)
- CONFIG_CHUNK(str, size, n, line->init_str, 1);
- else n = chan_config_string(line, str, size, error_out);
+ else {
+ struct tty_struct *tty = tty_port_tty_get(&line->port);
+ if (tty == NULL) {
+ CONFIG_CHUNK(str, size, n, line->init_str, 1);
+ } else {
+ n = chan_config_string(line, str, size, error_out);
+ tty_kref_put(tty);
+ }
+ }
mutex_unlock(&line->count_lock);

return n;
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 0e06a1f..5b3d4fb 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -33,7 +33,6 @@ struct line_driver {

struct line {
struct tty_port port;
- struct tty_struct *tty;
struct mutex count_lock;
int valid;

--
1.7.10.3

2012-06-04 11:40:25

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 19/24] TTY: vt, add ->install

We need to initialize the console only on the first open. This is
usually what is done in the ->install hook. vt used to do this in
->open. Now we move it to ->install and use newly added helper for
install: tty_port_install. It ensures tty->port to be set properly.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/vt/vt.c | 60 ++++++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 24 deletions(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 88a4914..7cb53c2 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2792,41 +2792,52 @@ static void con_flush_chars(struct tty_struct *tty)
/*
* Allocate the console screen memory.
*/
-static int con_open(struct tty_struct *tty, struct file *filp)
+static int con_install(struct tty_driver *driver, struct tty_struct *tty)
{
unsigned int currcons = tty->index;
- int ret = 0;
+ struct vc_data *vc;
+ int ret;

console_lock();
- if (tty->driver_data == NULL) {
- ret = vc_allocate(currcons);
- if (ret == 0) {
- struct vc_data *vc = vc_cons[currcons].d;
+ ret = vc_allocate(currcons);
+ if (ret)
+ goto unlock;

- /* Still being freed */
- if (vc->port.tty) {
- console_unlock();
- return -ERESTARTSYS;
- }
- tty->driver_data = vc;
- vc->port.tty = tty;
+ vc = vc_cons[currcons].d;

- if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
- tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
- tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
- }
- if (vc->vc_utf)
- tty->termios->c_iflag |= IUTF8;
- else
- tty->termios->c_iflag &= ~IUTF8;
- console_unlock();
- return ret;
- }
+ /* Still being freed */
+ if (vc->port.tty) {
+ ret = -ERESTARTSYS;
+ goto unlock;
}
+
+ ret = tty_port_install(&vc->port, driver, tty);
+ if (ret)
+ goto unlock;
+
+ tty->driver_data = vc;
+ vc->port.tty = tty;
+
+ if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
+ tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
+ tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
+ }
+ if (vc->vc_utf)
+ tty->termios->c_iflag |= IUTF8;
+ else
+ tty->termios->c_iflag &= ~IUTF8;
+unlock:
console_unlock();
return ret;
}

+static int con_open(struct tty_struct *tty, struct file *filp)
+{
+ /* everything done in install */
+ return 0;
+}
+
+
static void con_close(struct tty_struct *tty, struct file *filp)
{
/* Nothing to do - we defer to shutdown */
@@ -2947,6 +2958,7 @@ static int __init con_init(void)
console_initcall(con_init);

static const struct tty_operations con_ops = {
+ .install = con_install,
.open = con_open,
.close = con_close,
.write = con_write,
--
1.7.10.3

2012-06-04 11:40:24

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 01/24] TTY: cyclades, add local pointer for card

cy_pci_probe and cy_detect_isa reference cy_card[card_no] many times.
It makes the code hard to read. Let us add a local variable holding a
pointer to the card indexed by card_no and use that.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/cyclades.c | 63 +++++++++++++++++++++++++-----------------------
1 file changed, 33 insertions(+), 30 deletions(-)

diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index e61cabd..cff5468 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -3289,6 +3289,7 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
static int __init cy_detect_isa(void)
{
#ifdef CONFIG_ISA
+ struct cyclades_card *card;
unsigned short cy_isa_irq, nboard;
void __iomem *cy_isa_address;
unsigned short i, j, cy_isa_nchan;
@@ -3349,7 +3350,8 @@ static int __init cy_detect_isa(void)
}
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == NULL)
+ card = &cy_card[j];
+ if (card->base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
@@ -3363,7 +3365,7 @@ static int __init cy_detect_isa(void)

/* allocate IRQ */
if (request_irq(cy_isa_irq, cyy_interrupt,
- 0, "Cyclom-Y", &cy_card[j])) {
+ 0, "Cyclom-Y", card)) {
printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
"could not allocate IRQ#%d.\n",
(unsigned long)cy_isa_address, cy_isa_irq);
@@ -3372,16 +3374,16 @@ static int __init cy_detect_isa(void)
}

/* set cy_card */
- cy_card[j].base_addr = cy_isa_address;
- cy_card[j].ctl_addr.p9050 = NULL;
- cy_card[j].irq = (int)cy_isa_irq;
- cy_card[j].bus_index = 0;
- cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
- cy_card[j].nports = cy_isa_nchan;
- if (cy_init_card(&cy_card[j])) {
- cy_card[j].base_addr = NULL;
- free_irq(cy_isa_irq, &cy_card[j]);
+ card->base_addr = cy_isa_address;
+ card->ctl_addr.p9050 = NULL;
+ card->irq = (int)cy_isa_irq;
+ card->bus_index = 0;
+ card->first_line = cy_next_channel;
+ card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+ card->nports = cy_isa_nchan;
+ if (cy_init_card(card)) {
+ card->base_addr = NULL;
+ free_irq(cy_isa_irq, card);
iounmap(cy_isa_address);
continue;
}
@@ -3695,6 +3697,7 @@ err:
static int __devinit cy_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ struct cyclades_card *card;
void __iomem *addr0 = NULL, *addr2 = NULL;
char *card_name = NULL;
u32 uninitialized_var(mailbox);
@@ -3829,7 +3832,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
/* fill the next cy_card structure available */
for (card_no = 0; card_no < NR_CARDS; card_no++) {
- if (cy_card[card_no].base_addr == NULL)
+ card = &cy_card[card_no];
+ if (card->base_addr == NULL)
break;
}
if (card_no == NR_CARDS) { /* no more cy_cards available */
@@ -3843,27 +3847,26 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
/* allocate IRQ */
retval = request_irq(irq, cyy_interrupt,
- IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
+ IRQF_SHARED, "Cyclom-Y", card);
if (retval) {
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
}
- cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
+ card->num_chips = nchan / CyPORTS_PER_CHIP;
} else {
struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
struct ZFW_CTRL __iomem *zfw_ctrl;

zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);

- cy_card[card_no].hw_ver = mailbox;
- cy_card[card_no].num_chips = (unsigned int)-1;
- cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
+ card->hw_ver = mailbox;
+ card->num_chips = (unsigned int)-1;
+ card->board_ctrl = &zfw_ctrl->board_ctrl;
#ifdef CONFIG_CYZ_INTR
/* allocate IRQ only if board has an IRQ */
if (irq != 0 && irq != 255) {
retval = request_irq(irq, cyz_interrupt,
- IRQF_SHARED, "Cyclades-Z",
- &cy_card[card_no]);
+ IRQF_SHARED, "Cyclades-Z", card);
if (retval) {
dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap;
@@ -3873,17 +3876,17 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}

/* set cy_card */
- cy_card[card_no].base_addr = addr2;
- cy_card[card_no].ctl_addr.p9050 = addr0;
- cy_card[card_no].irq = irq;
- cy_card[card_no].bus_index = 1;
- cy_card[card_no].first_line = cy_next_channel;
- cy_card[card_no].nports = nchan;
- retval = cy_init_card(&cy_card[card_no]);
+ card->base_addr = addr2;
+ card->ctl_addr.p9050 = addr0;
+ card->irq = irq;
+ card->bus_index = 1;
+ card->first_line = cy_next_channel;
+ card->nports = nchan;
+ retval = cy_init_card(card);
if (retval)
goto err_null;

- pci_set_drvdata(pdev, &cy_card[card_no]);
+ pci_set_drvdata(pdev, card);

if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
@@ -3915,8 +3918,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,

return 0;
err_null:
- cy_card[card_no].base_addr = NULL;
- free_irq(irq, &cy_card[card_no]);
+ card->base_addr = NULL;
+ free_irq(irq, card);
err_unmap:
iounmap(addr0);
if (addr2)
--
1.7.10.3

2012-06-04 11:43:37

by Jiri Slaby

[permalink] [raw]
Subject: [PATCH 22/24] TTY: add ports array to tty_driver

It will hold tty_port structures for all drivers which do not want to
define tty->ops->install hook.

We ignore PTY here because it wants 1 million lines and it installs
tty_port in ->install anyway.

Signed-off-by: Jiri Slaby <[email protected]>
---
drivers/tty/tty_io.c | 18 +++++++++++++++++-
include/linux/tty_driver.h | 1 +
2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d6e045b..ac96f74 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1407,6 +1407,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
if (retval < 0)
goto err_deinit_tty;

+ if (!tty->port)
+ tty->port = driver->ports[idx];
+
/*
* Structures all installed ... call the ldisc open routines.
* If we fail here just call release_tty to clean up. No need
@@ -3094,6 +3097,7 @@ static void destruct_tty_driver(struct kref *kref)
kfree(p);
cdev_del(&driver->cdev);
}
+ kfree(driver->ports);
kfree(driver);
}

@@ -3132,6 +3136,18 @@ int tty_register_driver(struct tty_driver *driver)
if (!p)
return -ENOMEM;
}
+ /*
+ * There is too many lines in PTY and we won't need the array there
+ * since it has an ->install hook where it assigns ports properly.
+ */
+ if (driver->type != TTY_DRIVER_TYPE_PTY) {
+ driver->ports = kcalloc(driver->num, sizeof(struct tty_port *),
+ GFP_KERNEL);
+ if (!driver->ports) {
+ error = -ENOMEM;
+ goto err_free_p;
+ }
+ }

if (!driver->major) {
error = alloc_chrdev_region(&dev, driver->minor_start,
@@ -3190,7 +3206,7 @@ err_unreg_char:
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = NULL;
-err_free_p:
+err_free_p: /* destruct_tty_driver will free driver->ports */
kfree(p);
return error;
}
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 6e6dbb7..04419c1 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -313,6 +313,7 @@ struct tty_driver {
* Pointer to the tty data structures
*/
struct tty_struct **ttys;
+ struct tty_port **ports;
struct ktermios **termios;
void *driver_state;

--
1.7.10.3

2012-06-04 12:01:56

by Richard Weinberger

[permalink] [raw]
Subject: Re: [PATCH 13/24] TTY: um/line, use tty from tty_port

Jiri,

Thanks a lot for fixing this!

I have two questions:
1. Are these patches also usable on 3.4 and 3.3 or do they depend on 3.5's TTY changes?
2. Why didn't you use tty_port_open()/close()/etc. as Alan suggested my in [1]?

Thanks,
//richard

[1] http://lkml.indiana.edu/hypermail/linux/kernel/1201.3/01705.html

Am 04.06.2012 13:35, schrieb Jiri Slaby:
> This means switching to the tty refcounted model so that we will not
> race with interrupts.
>
> Signed-off-by: Jiri Slaby <[email protected]>
> Cc: Jeff Dike <[email protected]>
> Cc: Richard Weinberger <[email protected]>
> Cc: [email protected]
> ---
> arch/um/drivers/chan_kern.c | 4 +++-
> arch/um/drivers/line.c | 25 ++++++++++++++++++-------
> arch/um/drivers/line.h | 1 -
> 3 files changed, 21 insertions(+), 9 deletions(-)
>
> diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
> index 45e248c..87eebfe 100644
> --- a/arch/um/drivers/chan_kern.c
> +++ b/arch/um/drivers/chan_kern.c
> @@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
> static void line_timer_cb(struct work_struct *work)
> {
> struct line *line = container_of(work, struct line, task.work);
> + struct tty_struct *tty = tty_port_tty_get(&line->port);
>
> if (!line->throttled)
> - chan_interrupt(line, line->tty, line->driver->read_irq);
> + chan_interrupt(line, tty, line->driver->read_irq);
> + tty_kref_put(tty);
> }
>
> int enable_chan(struct line *line)
> diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
> index 482a7bd..fb6e4ea 100644
> --- a/arch/um/drivers/line.c
> +++ b/arch/um/drivers/line.c
> @@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data)
> {
> struct chan *chan = data;
> struct line *line = chan->line;
> + struct tty_struct *tty = tty_port_tty_get(&line->port);
>
> if (line)
> - chan_interrupt(line, line->tty, irq);
> + chan_interrupt(line, tty, irq);
> + tty_kref_put(tty);
> return IRQ_HANDLED;
> }
>
> @@ -333,7 +335,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
> {
> struct chan *chan = data;
> struct line *line = chan->line;
> - struct tty_struct *tty = line->tty;
> + struct tty_struct *tty;
> int err;
>
> /*
> @@ -352,10 +354,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
> }
> spin_unlock(&line->lock);
>
> + tty = tty_port_tty_get(&line->port);
> if (tty == NULL)
> return IRQ_NONE;
>
> tty_wakeup(tty);
> + tty_kref_put(tty);
> +
> return IRQ_HANDLED;
> }
>
> @@ -409,7 +414,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
>
> BUG_ON(tty->driver_data);
> tty->driver_data = line;
> - line->tty = tty;
> + tty_port_tty_set(&line->port, tty);
>
> err = enable_chan(line);
> if (err) /* line_close() will be called by our caller */
> @@ -449,7 +454,7 @@ void line_close(struct tty_struct *tty, struct file * filp)
> if (--line->port.count)
> goto out_unlock;
>
> - line->tty = NULL;
> + tty_port_tty_set(&line->port, NULL);
> tty->driver_data = NULL;
>
> if (line->sigio) {
> @@ -610,9 +615,15 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
> mutex_lock(&line->count_lock);
> if (!line->valid)
> CONFIG_CHUNK(str, size, n, "none", 1);
> - else if (line->tty == NULL)
> - CONFIG_CHUNK(str, size, n, line->init_str, 1);
> - else n = chan_config_string(line, str, size, error_out);
> + else {
> + struct tty_struct *tty = tty_port_tty_get(&line->port);
> + if (tty == NULL) {
> + CONFIG_CHUNK(str, size, n, line->init_str, 1);
> + } else {
> + n = chan_config_string(line, str, size, error_out);
> + tty_kref_put(tty);
> + }
> + }
> mutex_unlock(&line->count_lock);
>
> return n;
> diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
> index 0e06a1f..5b3d4fb 100644
> --- a/arch/um/drivers/line.h
> +++ b/arch/um/drivers/line.h
> @@ -33,7 +33,6 @@ struct line_driver {
>
> struct line {
> struct tty_port port;
> - struct tty_struct *tty;
> struct mutex count_lock;
> int valid;
>



Attachments:
signature.asc (490.00 B)
OpenPGP digital signature

2012-06-04 15:20:11

by Jiri Slaby

[permalink] [raw]
Subject: Re: [PATCH 13/24] TTY: um/line, use tty from tty_port

On 06/04/2012 02:01 PM, Richard Weinberger wrote:
> I have two questions: 1. Are these patches also usable on 3.4 and
> 3.3 or do they depend on 3.5's TTY changes?

Hi, I don't think they depend on any changes.

> 2. Why didn't you use tty_port_open()/close()/etc. as Alan
> suggested my in [1]?

This was not intended to fix anything particular. If it does, it is a
pure coincidence... These patches are a minimalistic subset to ensure
every driver has its own tty_port for each tty. We will need this
pairing later.

So the switch of the driver to the new tty port API, as suggested by
Alan, is still needed. I might do that later if I learn how to make
UML work. (The conversion is by definition invasive and needs runtime
testing.)

> [1]
> http://lkml.indiana.edu/hypermail/linux/kernel/1201.3/01705.html

thanks,
--
js
suse labs

2012-06-04 15:29:20

by Richard Weinberger

[permalink] [raw]
Subject: Re: [PATCH 13/24] TTY: um/line, use tty from tty_port

Hi!

Am 04.06.2012 17:20, schrieb Jiri Slaby:
> On 06/04/2012 02:01 PM, Richard Weinberger wrote:
>> I have two questions: 1. Are these patches also usable on 3.4 and
>> 3.3 or do they depend on 3.5's TTY changes?
>
> Hi, I don't think they depend on any changes.

Nice.

>> 2. Why didn't you use tty_port_open()/close()/etc. as Alan
>> suggested my in [1]?
>
> This was not intended to fix anything particular. If it does, it is a
> pure coincidence... These patches are a minimalistic subset to ensure
> every driver has its own tty_port for each tty. We will need this
> pairing later.

It looks like that it solves UML's TTY issues with systemd distros. :-)

> So the switch of the driver to the new tty port API, as suggested by
> Alan, is still needed. I might do that later if I learn how to make
> UML work. (The conversion is by definition invasive and needs runtime
> testing.)

Two days ago I did so but still faced the problems described here:
https://lkml.org/lkml/2012/3/10/163

Thanks,
//richard


Attachments:
signature.asc (490.00 B)
OpenPGP digital signature

2012-06-04 15:41:08

by Jiri Slaby

[permalink] [raw]
Subject: Re: [PATCH 13/24] TTY: um/line, use tty from tty_port

On 06/04/2012 05:29 PM, Richard Weinberger wrote:
> It looks like that it solves UML's TTY issues with systemd distros.
> :-)

Good.

>> So the switch of the driver to the new tty port API, as suggested
>> by Alan, is still needed. I might do that later if I learn how to
>> make UML work. (The conversion is by definition invasive and
>> needs runtime testing.)
>
> Two days ago I did so but still faced the problems described here:
> https://lkml.org/lkml/2012/3/10/163

Hmm, I remember. I suggest you to split the patch into several pieces.
For example moving the code from ->open into ->install can be done
separately. Otherwise it's hard to tell what's wrong with the patch as
a whole.

Also, it would be good to see the patch rebased on the top of my
patch, because tty_port_set/get pieces would be gone from your patch too.

regards,
--
js
suse labs

2012-06-04 15:42:50

by Richard Weinberger

[permalink] [raw]
Subject: Re: [PATCH 13/24] TTY: um/line, use tty from tty_port

Am 04.06.2012 17:41, schrieb Jiri Slaby:
> Hmm, I remember. I suggest you to split the patch into several pieces.
> For example moving the code from ->open into ->install can be done
> separately. Otherwise it's hard to tell what's wrong with the patch as
> a whole.
>
> Also, it would be good to see the patch rebased on the top of my
> patch, because tty_port_set/get pieces would be gone from your patch too.

Okay, I'll redo it!
I've a much cleaner version in my local queue.

Thanks,
//richard



Attachments:
signature.asc (490.00 B)
OpenPGP digital signature

2012-06-04 15:55:42

by Alan

[permalink] [raw]
Subject: Re: [PATCH 13/24] TTY: um/line, use tty from tty_port

> Two days ago I did so but still faced the problems described here:
> https://lkml.org/lkml/2012/3/10/163

If you are running a Fedora like distro it's because the user space is
broken. At some point we are going to have to make them fix the userspace
not to sit with ttys held open.


Alan

2012-06-04 16:29:17

by Richard Weinberger

[permalink] [raw]
Subject: Re: [uml-devel] [PATCH 13/24] TTY: um/line, use tty from tty_port

Am 04.06.2012 18:27, schrieb Boaz Harrosh:
> On 06/04/2012 06:42 PM, Richard Weinberger wrote:
>
>> Am 04.06.2012 17:41, schrieb Jiri Slaby:
>>> Hmm, I remember. I suggest you to split the patch into several pieces.
>>> For example moving the code from ->open into ->install can be done
>>> separately. Otherwise it's hard to tell what's wrong with the patch as
>>> a whole.
>>>
>>> Also, it would be good to see the patch rebased on the top of my
>>> patch, because tty_port_set/get pieces would be gone from your patch too.
>>
>> Okay, I'll redo it!
>> I've a much cleaner version in my local queue.
>>
>
>
> Can you send it my way, I'm still running broken, 3.4 Based ?
>

Can you please first give Jiri's patches a try?

[PATCH 12/24] TTY: um/line, add tty_port
[PATCH 13/24] TTY: um/line, use tty from tty_port

Thanks,
//richard


Attachments:
signature.asc (490.00 B)
OpenPGP digital signature

2012-06-04 16:32:57

by Alan

[permalink] [raw]
Subject: Re: [PATCH 04/24] TTY: ircomm, use open counts from tty_port

On Mon, 4 Jun 2012 13:35:18 +0200
Jiri Slaby <[email protected]> wrote:

> Switch to tty_port->count and blocked_open.

Only question here is tty_port->count should be under the port lock, so
code which plays with the count itself like this probably needs to be
using the port lock ?

Alan

2012-06-04 16:34:11

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [uml-devel] [PATCH 13/24] TTY: um/line, use tty from tty_port

On 06/04/2012 06:42 PM, Richard Weinberger wrote:

> Am 04.06.2012 17:41, schrieb Jiri Slaby:
>> Hmm, I remember. I suggest you to split the patch into several pieces.
>> For example moving the code from ->open into ->install can be done
>> separately. Otherwise it's hard to tell what's wrong with the patch as
>> a whole.
>>
>> Also, it would be good to see the patch rebased on the top of my
>> patch, because tty_port_set/get pieces would be gone from your patch too.
>
> Okay, I'll redo it!
> I've a much cleaner version in my local queue.
>


Can you send it my way, I'm still running broken, 3.4 Based ?

Thanks very much in advance
Boaz

> Thanks,
> //richard
>
>
>
>
>
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and
> threat landscape has changed and how IT managers can respond. Discussions
> will include endpoint security, mobile security and the latest in malware
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
>
>
>
> _______________________________________________
> User-mode-linux-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

2012-06-04 16:44:34

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [uml-devel] [PATCH 13/24] TTY: um/line, use tty from tty_port

On 06/04/2012 07:29 PM, Richard Weinberger wrote:

> Am 04.06.2012 18:27, schrieb Boaz Harrosh:
>> On 06/04/2012 06:42 PM, Richard Weinberger wrote:
>>
>>> Am 04.06.2012 17:41, schrieb Jiri Slaby:
>>>> Hmm, I remember. I suggest you to split the patch into several pieces.
>>>> For example moving the code from ->open into ->install can be done
>>>> separately. Otherwise it's hard to tell what's wrong with the patch as
>>>> a whole.
>>>>
>>>> Also, it would be good to see the patch rebased on the top of my
>>>> patch, because tty_port_set/get pieces would be gone from your patch too.
>>>
>>> Okay, I'll redo it!
>>> I've a much cleaner version in my local queue.
>>>
>>
>>
>> Can you send it my way, I'm still running broken, 3.4 Based ?
>>
>
> Can you please first give Jiri's patches a try?
>
> [PATCH 12/24] TTY: um/line, add tty_port
> [PATCH 13/24] TTY: um/line, use tty from tty_port
>


OK Will do

Boaz

> Thanks,
> //richard
>

2012-06-04 16:55:12

by Alan

[permalink] [raw]
Subject: Re: [PATCH 06/24] TTY: ircomm, revamp locking

On Mon, 4 Jun 2012 13:35:20 +0200
Jiri Slaby <[email protected]> wrote:

> Use self->spinlock only for ctrl_skb and tx_skb. TTY stuff is now
> protected by tty_port->lock. This is needed for further cleanup (and
> conversion to tty_port helpers).
>
> This also closes the race in the end of close.

Ah ok.. fixed here

2012-06-04 16:56:56

by Alan

[permalink] [raw]
Subject: Re: [PATCH 24/24] TTY: use tty_port_register_device

> In this patch we modify most of the drivers to do the latter. When the
> drivers use tty_register_device and we have tty_port already, we
> switch to tty_port_register_device. So we have the tty_struct =>
> tty_port link for free for those.

Nice solution

2012-06-04 17:02:38

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [uml-devel] [PATCH 13/24] TTY: um/line, use tty from tty_port

On 06/04/2012 07:29 PM, Richard Weinberger wrote:

> Am 04.06.2012 18:27, schrieb Boaz Harrosh:
>> On 06/04/2012 06:42 PM, Richard Weinberger wrote:
>>
>>> Am 04.06.2012 17:41, schrieb Jiri Slaby:
>>>> Hmm, I remember. I suggest you to split the patch into several pieces.
>>>> For example moving the code from ->open into ->install can be done
>>>> separately. Otherwise it's hard to tell what's wrong with the patch as
>>>> a whole.
>>>>
>>>> Also, it would be good to see the patch rebased on the top of my
>>>> patch, because tty_port_set/get pieces would be gone from your patch too.
>>>
>>> Okay, I'll redo it!
>>> I've a much cleaner version in my local queue.
>>>
>>
>>
>> Can you send it my way, I'm still running broken, 3.4 Based ?
>>
>
> Can you please first give Jiri's patches a try?
>
> [PATCH 12/24] TTY: um/line, add tty_port
> [PATCH 13/24] TTY: um/line, use tty from tty_port
>


No still crashing the same, way. BTW I do not have a systemd Distro. It's
plain old FC12. Though in the lab I have the same crash with FC15.

The crash is immediately after I login at the initial prompt. (every time)

Here is the crash print, what ever that is worth in UML.
(Can we make the crash dump stack trace a bit less terrible?)

----
Modules linked in: nfsd nfs lockd auth_rpcgss nfs_acl sunrpc osd libosd ipv6 binfmt_misc [last unloaded: scsi_wait_scan]
Pid: 1243, comm: login Not tainted 3.4.0-pnfs+
RIP: 0033:[<00000000601bbf7f>]
RSP: 0000000077ed7ad0 EFLAGS: 00010202
RAX: 00000000601bbf6b RBX: 00000000000001d8 RCX: 000000000000000b
RDX: 00000000600206dc RSI: 00000000601c4c14 RDI: 00000000000001d8
RBP: 0000000077ed7b20 R08: 0000000000000000 R09: 0000000077ed7c30
R10: 0000000000000000 R11: 0000003ea3882a83 R12: 0000000000000000
R13: 0000000000000fff R14: 0000000000000002 R15: 0000000077ed7c30
Call Trace:
603556c8: [<6001c6ac>] segv+0x2f6/0x31c
603556e0: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
60355708: [<6007d89f>] rcu_sched_qs+0xb8/0xbc
60355740: [<600191c8>] do_IRQ+0x0/0x54
60355748: [<6002bdf3>] os_waiting_for_events+0x0/0xb9
603557a8: [<60018d98>] to_irq_stack+0x0/0xa1
603557b8: [<6001c75e>] segv_handler+0x8c/0x96
603557d8: [<600194c9>] sigio_handler+0x88/0x93
60355808: [<6002d733>] sig_handler_common+0x9f/0xb3
60355860: [<601bbf6b>] do_raw_spin_lock+0x0/0x121
60355870: [<600206dc>] line_chars_in_buffer+0x0/0x82
60355878: [<601c4c14>] tty_chars_in_buffer+0x0/0x17
60355890: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
603558b0: [<601b331d>] radix_tree_lookup_slot+0x4d/0x5c
60355920: [<6001669c>] _einittext+0x18d1/0x2b55
60355930: [<600161a8>] _einittext+0x13dd/0x2b55
60355a08: [<6001669c>] _einittext+0x18d1/0x2b55
60355aa0: [<60017e28>] _init+0x508/0x870
60355aa8: [<60018d98>] to_irq_stack+0x0/0xa1
60355b28: [<60017e28>] _init+0x508/0x870
60355b38: [<6002d906>] sig_handler+0x4c/0x5e
60355b58: [<6002db99>] hard_handler+0x89/0xcb
60355c30: [<601c4c14>] tty_chars_in_buffer+0x0/0x17
60355c48: [<600206dc>] line_chars_in_buffer+0x0/0x82
60355c50: [<601bbf6b>] do_raw_spin_lock+0x0/0x121
60355c68: [<601bbf7f>] do_raw_spin_lock+0x14/0x121

Kernel panic - not syncing: Kernel mode fault at addr 0x1dc, ip 0x601bbf7f
Call Trace:
603555b8: [<60280af4>] panic+0x170/0x2e0
603555f0: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
603555f8: [<60280984>] panic+0x0/0x2e0
60355610: [<6006d5fd>] __module_text_address+0x14/0x5a
60355628: [<6006d653>] is_module_text_address+0x10/0x18
60355638: [<60050ced>] __kernel_text_address+0x97/0x9d
60355640: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
60355658: [<6001afc0>] show_trace+0xd4/0xdf
603556c8: [<6001c6d2>] segv_handler+0x0/0x96
603556e0: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
60355708: [<6007d89f>] rcu_sched_qs+0xb8/0xbc
60355740: [<600191c8>] do_IRQ+0x0/0x54
60355748: [<6002bdf3>] os_waiting_for_events+0x0/0xb9
603557a8: [<60018d98>] to_irq_stack+0x0/0xa1
603557b8: [<6001c75e>] segv_handler+0x8c/0x96
603557d8: [<600194c9>] sigio_handler+0x88/0x93
60355808: [<6002d733>] sig_handler_common+0x9f/0xb3
60355860: [<601bbf6b>] do_raw_spin_lock+0x0/0x121
60355870: [<600206dc>] line_chars_in_buffer+0x0/0x82
60355878: [<601c4c14>] tty_chars_in_buffer+0x0/0x17
60355890: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
603558b0: [<601b331d>] radix_tree_lookup_slot+0x4d/0x5c
60355920: [<6001669c>] _einittext+0x18d1/0x2b55
60355930: [<600161a8>] _einittext+0x13dd/0x2b55
60355a08: [<6001669c>] _einittext+0x18d1/0x2b55
60355aa0: [<60017e28>] _init+0x508/0x870
60355aa8: [<60018d98>] to_irq_stack+0x0/0xa1
60355b28: [<60017e28>] _init+0x508/0x870
60355b38: [<6002d906>] sig_handler+0x4c/0x5e
60355b58: [<6002db99>] hard_handler+0x89/0xcb
60355c30: [<601c4c14>] tty_chars_in_buffer+0x0/0x17
60355c48: [<600206dc>] line_chars_in_buffer+0x0/0x82
60355c50: [<601bbf6b>] do_raw_spin_lock+0x0/0x121
60355c68: [<601bbf7f>] do_raw_spin_lock+0x14/0x121


Modules linked in: nfsd nfs lockd auth_rpcgss nfs_acl sunrpc osd libosd ipv6 binfmt_misc [last unloaded: scsi_wait_scan]
Pid: 1243, comm: login Not tainted 3.4.0-pnfs+
RIP: 0033:[<00000030914d8318>]
RSP: 0000007fbfe72740 EFLAGS: 00000202
RAX: ffffffffffffffda RBX: 0000000000000010 RCX: ffffffffffffffff
RDX: 0000007fbfe72710 RSI: 0000000000005404 RDI: 0000000000000000
RBP: 0000000000000000 R08: 0000007fbfe74c40 R09: 0000000000000000
R10: 0000007fbfe72710 R11: 0000000000000202 R12: 0000007fbfe74c40
R13: 0000007fbfe72ac7 R14: 0000007fbfe72a50 R15: 0000000000000000
Call Trace:
60355538: [<6001c8c5>] panic_exit+0x3e/0x5c
60355540: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
60355568: [<60058a76>] notifier_call_chain+0x32/0x5e
603555a8: [<60058ad2>] atomic_notifier_call_chain+0x1a/0x1c
603555b8: [<60280b24>] panic+0x1a0/0x2e0
603555f0: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
603555f8: [<60280984>] panic+0x0/0x2e0
60355610: [<6006d5fd>] __module_text_address+0x14/0x5a
60355628: [<6006d653>] is_module_text_address+0x10/0x18
60355638: [<60050ced>] __kernel_text_address+0x97/0x9d
60355640: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
60355658: [<6001afc0>] show_trace+0xd4/0xdf
603556c8: [<6001c6d2>] segv_handler+0x0/0x96
603556e0: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
60355708: [<6007d89f>] rcu_sched_qs+0xb8/0xbc
60355740: [<600191c8>] do_IRQ+0x0/0x54
60355748: [<6002bdf3>] os_waiting_for_events+0x0/0xb9
603557a8: [<60018d98>] to_irq_stack+0x0/0xa1
603557b8: [<6001c75e>] segv_handler+0x8c/0x96
603557d8: [<600194c9>] sigio_handler+0x88/0x93
60355808: [<6002d733>] sig_handler_common+0x9f/0xb3
60355860: [<601bbf6b>] do_raw_spin_lock+0x0/0x121
60355870: [<600206dc>] line_chars_in_buffer+0x0/0x82
60355878: [<601c4c14>] tty_chars_in_buffer+0x0/0x17
60355890: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
603558b0: [<601b331d>] radix_tree_lookup_slot+0x4d/0x5c
60355920: [<6001669c>] _einittext+0x18d1/0x2b55
60355930: [<600161a8>] _einittext+0x13dd/0x2b55
60355a08: [<6001669c>] _einittext+0x18d1/0x2b55
60355aa0: [<60017e28>] _init+0x508/0x870
60355aa8: [<60018d98>] to_irq_stack+0x0/0xa1
60355b28: [<60017e28>] _init+0x508/0x870
60355b38: [<6002d906>] sig_handler+0x4c/0x5e
60355b58: [<6002db99>] hard_handler+0x89/0xcb
60355c30: [<601c4c14>] tty_chars_in_buffer+0x0/0x17
60355c48: [<600206dc>] line_chars_in_buffer+0x0/0x82
60355c50: [<601bbf6b>] do_raw_spin_lock+0x0/0x121
60355c68: [<601bbf7f>] do_raw_spin_lock+0x14/0x121
----

BTW I suspect that UML is unable to catch an invalid pointer execution
and just dumps core and exits. Let me explain.

A:
foo == ((foo_t *)NULL)->member_not_first
A NULL access backtrace will be generated before UML exit

but ..
B: a function call
((foo_op *)NULL)->function_member_not_first(...);

Will crap out without any kind of stack trace.

Is that possible?

Thanks
Boaz

2012-06-04 17:05:46

by Richard Weinberger

[permalink] [raw]
Subject: Re: [uml-devel] [PATCH 13/24] TTY: um/line, use tty from tty_port

Am 04.06.2012 18:55, schrieb Boaz Harrosh:
> No still crashing the same, way. BTW I do not have a systemd Distro. It's
> plain old FC12. Though in the lab I have the same crash with FC15.
>
> The crash is immediately after I login at the initial prompt. (every time)

Okay, I'll test my patches with FC12 too. :-\

> Here is the crash print, what ever that is worth in UML.
> (Can we make the crash dump stack trace a bit less terrible?)

-ENOPATCH. :-)
Feel free to send one.

Thanks,
//richard



Attachments:
signature.asc (490.00 B)
OpenPGP digital signature

2012-06-04 17:21:52

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [uml-devel] [PATCH 13/24] TTY: um/line, use tty from tty_port

On 06/04/2012 08:05 PM, Richard Weinberger wrote:

> Am 04.06.2012 18:55, schrieb Boaz Harrosh:
>> No still crashing the same, way. BTW I do not have a systemd Distro. It's
>> plain old FC12. Though in the lab I have the same crash with FC15.
>>
>> The crash is immediately after I login at the initial prompt. (every time)
>
> Okay, I'll test my patches with FC12 too. :-\
>


Thanks. Do you need help with an image?

>> Here is the crash print, what ever that is worth in UML.
>> (Can we make the crash dump stack trace a bit less terrible?)
>
> -ENOPATCH. :-)
> Feel free to send one.
>


:-) It's always the: "how much time I spend on saving time later?"

But I promise I'll do it one day.

> Thanks,
> //richard
>
>


Thanks
Boaz

2012-06-09 14:58:50

by Jiri Slaby

[permalink] [raw]
Subject: Re: [PATCH 24/24] TTY: use tty_port_register_device

On 06/04/2012 07:00 PM, Alan Cox wrote:
>> In this patch we modify most of the drivers to do the latter. When the
>> drivers use tty_register_device and we have tty_port already, we
>> switch to tty_port_register_device. So we have the tty_struct =>
>> tty_port link for free for those.
>
> Nice solution

Seems so on the first glance... But it is racy. There is a window since
tty_register_driver to tty_(port_)register_device where a node may be
opened already, but tty_port won't be set up yet.

The fix is to move cdev_add from tty_register_driver to
tty_register_device, which makes sense anyway. Any objections?

For the time being, Greg, please ignore 24/24 from these series (I see
you haven't applied any of the patches yet.)

thanks,
--
js
suse labs

2012-06-09 17:28:20

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 24/24] TTY: use tty_port_register_device

On Sat, Jun 09, 2012 at 04:58:43PM +0200, Jiri Slaby wrote:
> On 06/04/2012 07:00 PM, Alan Cox wrote:
> >> In this patch we modify most of the drivers to do the latter. When the
> >> drivers use tty_register_device and we have tty_port already, we
> >> switch to tty_port_register_device. So we have the tty_struct =>
> >> tty_port link for free for those.
> >
> > Nice solution
>
> Seems so on the first glance... But it is racy. There is a window since
> tty_register_driver to tty_(port_)register_device where a node may be
> opened already, but tty_port won't be set up yet.
>
> The fix is to move cdev_add from tty_register_driver to
> tty_register_device, which makes sense anyway. Any objections?
>
> For the time being, Greg, please ignore 24/24 from these series (I see
> you haven't applied any of the patches yet.)

Ok, I'll drop 24/24. I should get to these this upcoming week as I am
finally going to be home from all of my crazy traveling.

greg k-h

2012-06-12 22:55:50

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 16/24] PTY: add tty_port

On Mon, Jun 04, 2012 at 01:35:30PM +0200, Jiri Slaby wrote:
> This has *no* function in the PTY driver yet. However as the tty
> buffers will move to the tty_port structure, we will need tty_port for
> all TTYs in the system, PTY inclusive.
>
> For PTYs this is ensured by allocating 2 tty_port's in pty_install,
> i.e. where the tty->link is allocated. Both tty_port's are properly
> assigned to each end of the tty.
>
> Freeing is done at the same place where tty is freed, i.e. in
> tty->ops->cleanup.
>
> This means BTW that tty_port does not outlive TTY in PTY. This might
> be a subject to change in the future if we see some problems.
>
> Signed-off-by: Jiri Slaby <[email protected]>
> ---
> drivers/tty/pty.c | 25 +++++++++++++++++++++----
> 1 file changed, 21 insertions(+), 4 deletions(-)

As the locking rework got removed from Linus's tree, this patch doesn't
apply, so I've stopped at this point in the series.

Care to refresh it, and resend the rest of the patches, if you still
want me to apply them (I recall 24 wasn't ok, right?)

thanks,

greg k-h

2012-06-14 00:29:11

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 16/24] PTY: add tty_port

On Tue, Jun 12, 2012 at 03:55:44PM -0700, Greg KH wrote:
> On Mon, Jun 04, 2012 at 01:35:30PM +0200, Jiri Slaby wrote:
> > This has *no* function in the PTY driver yet. However as the tty
> > buffers will move to the tty_port structure, we will need tty_port for
> > all TTYs in the system, PTY inclusive.
> >
> > For PTYs this is ensured by allocating 2 tty_port's in pty_install,
> > i.e. where the tty->link is allocated. Both tty_port's are properly
> > assigned to each end of the tty.
> >
> > Freeing is done at the same place where tty is freed, i.e. in
> > tty->ops->cleanup.
> >
> > This means BTW that tty_port does not outlive TTY in PTY. This might
> > be a subject to change in the future if we see some problems.
> >
> > Signed-off-by: Jiri Slaby <[email protected]>
> > ---
> > drivers/tty/pty.c | 25 +++++++++++++++++++++----
> > 1 file changed, 21 insertions(+), 4 deletions(-)
>
> As the locking rework got removed from Linus's tree, this patch doesn't
> apply, so I've stopped at this point in the series.

Argh, this was my fault, sorry, let me try this again, I missed 14 and
15 for some reason...

greg k-h

2012-06-14 00:31:36

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 16/24] PTY: add tty_port

On Wed, Jun 13, 2012 at 05:29:05PM -0700, Greg KH wrote:
> On Tue, Jun 12, 2012 at 03:55:44PM -0700, Greg KH wrote:
> > On Mon, Jun 04, 2012 at 01:35:30PM +0200, Jiri Slaby wrote:
> > > This has *no* function in the PTY driver yet. However as the tty
> > > buffers will move to the tty_port structure, we will need tty_port for
> > > all TTYs in the system, PTY inclusive.
> > >
> > > For PTYs this is ensured by allocating 2 tty_port's in pty_install,
> > > i.e. where the tty->link is allocated. Both tty_port's are properly
> > > assigned to each end of the tty.
> > >
> > > Freeing is done at the same place where tty is freed, i.e. in
> > > tty->ops->cleanup.
> > >
> > > This means BTW that tty_port does not outlive TTY in PTY. This might
> > > be a subject to change in the future if we see some problems.
> > >
> > > Signed-off-by: Jiri Slaby <[email protected]>
> > > ---
> > > drivers/tty/pty.c | 25 +++++++++++++++++++++----
> > > 1 file changed, 21 insertions(+), 4 deletions(-)
> >
> > As the locking rework got removed from Linus's tree, this patch doesn't
> > apply, so I've stopped at this point in the series.
>
> Argh, this was my fault, sorry, let me try this again, I missed 14 and
> 15 for some reason...

Yup, that fixed it, ok, I've applied the rest now, let me know if I
messed anything up.

thanks,

greg k-h