diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-06-15 07:28:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-06-17 15:55:11 -0400 |
commit | f6c8dbe6e50c6e5121d7b6644718207daa008221 (patch) | |
tree | f7200d98ecaa899fb2c83d6b58b88a20b302f936 /drivers/tty | |
parent | a630fbfbb1beeffc5bbe542a7986bf2068874633 (diff) |
n_tty: Encapsulate minimum_to_wake within N_TTY
minimum_to_wake is unique to N_TTY processing, and belongs in
per-ldisc data.
Add the ldisc method, ldisc_ops::fasync(), to notify line disciplines
when signal-driven I/O is enabled or disabled. When enabled for N_TTY
(by fcntl(F_SETFL, O_ASYNC)), blocking reader/polls will be woken
for any readable input. When disabled, blocking reader/polls are not
woken until the read buffer is full.
Canonical mode (L_ICANON(tty), n_tty_data::icanon) is not affected by
the minimum_to_wake setting.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_tty.c | 39 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 17 |
2 files changed, 36 insertions, 20 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index cdcdb0ea061a..f1806de69b18 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -89,6 +89,7 @@ struct n_tty_data { | |||
89 | int read_head; | 89 | int read_head; |
90 | int read_tail; | 90 | int read_tail; |
91 | int read_cnt; | 91 | int read_cnt; |
92 | int minimum_to_wake; | ||
92 | 93 | ||
93 | unsigned char *echo_buf; | 94 | unsigned char *echo_buf; |
94 | unsigned int echo_pos; | 95 | unsigned int echo_pos; |
@@ -1455,7 +1456,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1455 | 1456 | ||
1456 | n_tty_set_room(tty); | 1457 | n_tty_set_room(tty); |
1457 | 1458 | ||
1458 | if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) || | 1459 | if ((!ldata->icanon && (ldata->read_cnt >= ldata->minimum_to_wake)) || |
1459 | L_EXTPROC(tty)) { | 1460 | L_EXTPROC(tty)) { |
1460 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1461 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
1461 | if (waitqueue_active(&tty->read_wait)) | 1462 | if (waitqueue_active(&tty->read_wait)) |
@@ -1636,7 +1637,7 @@ static int n_tty_open(struct tty_struct *tty) | |||
1636 | tty->disc_data = ldata; | 1637 | tty->disc_data = ldata; |
1637 | reset_buffer_flags(tty->disc_data); | 1638 | reset_buffer_flags(tty->disc_data); |
1638 | ldata->column = 0; | 1639 | ldata->column = 0; |
1639 | tty->minimum_to_wake = 1; | 1640 | ldata->minimum_to_wake = 1; |
1640 | tty->closing = 0; | 1641 | tty->closing = 0; |
1641 | /* indicate buffer work may resume */ | 1642 | /* indicate buffer work may resume */ |
1642 | clear_bit(TTY_LDISC_HALTED, &tty->flags); | 1643 | clear_bit(TTY_LDISC_HALTED, &tty->flags); |
@@ -1804,17 +1805,17 @@ do_it_again: | |||
1804 | minimum = MIN_CHAR(tty); | 1805 | minimum = MIN_CHAR(tty); |
1805 | if (minimum) { | 1806 | if (minimum) { |
1806 | if (time) | 1807 | if (time) |
1807 | tty->minimum_to_wake = 1; | 1808 | ldata->minimum_to_wake = 1; |
1808 | else if (!waitqueue_active(&tty->read_wait) || | 1809 | else if (!waitqueue_active(&tty->read_wait) || |
1809 | (tty->minimum_to_wake > minimum)) | 1810 | (ldata->minimum_to_wake > minimum)) |
1810 | tty->minimum_to_wake = minimum; | 1811 | ldata->minimum_to_wake = minimum; |
1811 | } else { | 1812 | } else { |
1812 | timeout = 0; | 1813 | timeout = 0; |
1813 | if (time) { | 1814 | if (time) { |
1814 | timeout = time; | 1815 | timeout = time; |
1815 | time = 0; | 1816 | time = 0; |
1816 | } | 1817 | } |
1817 | tty->minimum_to_wake = minimum = 1; | 1818 | ldata->minimum_to_wake = minimum = 1; |
1818 | } | 1819 | } |
1819 | } | 1820 | } |
1820 | 1821 | ||
@@ -1854,9 +1855,9 @@ do_it_again: | |||
1854 | TASK_RUNNING. */ | 1855 | TASK_RUNNING. */ |
1855 | set_current_state(TASK_INTERRUPTIBLE); | 1856 | set_current_state(TASK_INTERRUPTIBLE); |
1856 | 1857 | ||
1857 | if (((minimum - (b - buf)) < tty->minimum_to_wake) && | 1858 | if (((minimum - (b - buf)) < ldata->minimum_to_wake) && |
1858 | ((minimum - (b - buf)) >= 1)) | 1859 | ((minimum - (b - buf)) >= 1)) |
1859 | tty->minimum_to_wake = (minimum - (b - buf)); | 1860 | ldata->minimum_to_wake = (minimum - (b - buf)); |
1860 | 1861 | ||
1861 | if (!input_available_p(tty, 0)) { | 1862 | if (!input_available_p(tty, 0)) { |
1862 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 1863 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
@@ -1973,7 +1974,7 @@ do_it_again: | |||
1973 | remove_wait_queue(&tty->read_wait, &wait); | 1974 | remove_wait_queue(&tty->read_wait, &wait); |
1974 | 1975 | ||
1975 | if (!waitqueue_active(&tty->read_wait)) | 1976 | if (!waitqueue_active(&tty->read_wait)) |
1976 | tty->minimum_to_wake = minimum; | 1977 | ldata->minimum_to_wake = minimum; |
1977 | 1978 | ||
1978 | __set_current_state(TASK_RUNNING); | 1979 | __set_current_state(TASK_RUNNING); |
1979 | size = b - buf; | 1980 | size = b - buf; |
@@ -2105,6 +2106,7 @@ break_out: | |||
2105 | static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, | 2106 | static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, |
2106 | poll_table *wait) | 2107 | poll_table *wait) |
2107 | { | 2108 | { |
2109 | struct n_tty_data *ldata = tty->disc_data; | ||
2108 | unsigned int mask = 0; | 2110 | unsigned int mask = 0; |
2109 | 2111 | ||
2110 | poll_wait(file, &tty->read_wait, wait); | 2112 | poll_wait(file, &tty->read_wait, wait); |
@@ -2119,9 +2121,9 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, | |||
2119 | mask |= POLLHUP; | 2121 | mask |= POLLHUP; |
2120 | if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { | 2122 | if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { |
2121 | if (MIN_CHAR(tty) && !TIME_CHAR(tty)) | 2123 | if (MIN_CHAR(tty) && !TIME_CHAR(tty)) |
2122 | tty->minimum_to_wake = MIN_CHAR(tty); | 2124 | ldata->minimum_to_wake = MIN_CHAR(tty); |
2123 | else | 2125 | else |
2124 | tty->minimum_to_wake = 1; | 2126 | ldata->minimum_to_wake = 1; |
2125 | } | 2127 | } |
2126 | if (tty->ops->write && !tty_is_writelocked(tty) && | 2128 | if (tty->ops->write && !tty_is_writelocked(tty) && |
2127 | tty_chars_in_buffer(tty) < WAKEUP_CHARS && | 2129 | tty_chars_in_buffer(tty) < WAKEUP_CHARS && |
@@ -2169,6 +2171,18 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
2169 | } | 2171 | } |
2170 | } | 2172 | } |
2171 | 2173 | ||
2174 | static void n_tty_fasync(struct tty_struct *tty, int on) | ||
2175 | { | ||
2176 | struct n_tty_data *ldata = tty->disc_data; | ||
2177 | |||
2178 | if (!waitqueue_active(&tty->read_wait)) { | ||
2179 | if (on) | ||
2180 | ldata->minimum_to_wake = 1; | ||
2181 | else if (!tty->fasync) | ||
2182 | ldata->minimum_to_wake = N_TTY_BUF_SIZE; | ||
2183 | } | ||
2184 | } | ||
2185 | |||
2172 | struct tty_ldisc_ops tty_ldisc_N_TTY = { | 2186 | struct tty_ldisc_ops tty_ldisc_N_TTY = { |
2173 | .magic = TTY_LDISC_MAGIC, | 2187 | .magic = TTY_LDISC_MAGIC, |
2174 | .name = "n_tty", | 2188 | .name = "n_tty", |
@@ -2182,7 +2196,8 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { | |||
2182 | .set_termios = n_tty_set_termios, | 2196 | .set_termios = n_tty_set_termios, |
2183 | .poll = n_tty_poll, | 2197 | .poll = n_tty_poll, |
2184 | .receive_buf = n_tty_receive_buf, | 2198 | .receive_buf = n_tty_receive_buf, |
2185 | .write_wakeup = n_tty_write_wakeup | 2199 | .write_wakeup = n_tty_write_wakeup, |
2200 | .fasync = n_tty_fasync, | ||
2186 | }; | 2201 | }; |
2187 | 2202 | ||
2188 | /** | 2203 | /** |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6464029e4860..bd88007fa6ea 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -2138,6 +2138,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
2138 | static int __tty_fasync(int fd, struct file *filp, int on) | 2138 | static int __tty_fasync(int fd, struct file *filp, int on) |
2139 | { | 2139 | { |
2140 | struct tty_struct *tty = file_tty(filp); | 2140 | struct tty_struct *tty = file_tty(filp); |
2141 | struct tty_ldisc *ldisc; | ||
2141 | unsigned long flags; | 2142 | unsigned long flags; |
2142 | int retval = 0; | 2143 | int retval = 0; |
2143 | 2144 | ||
@@ -2148,11 +2149,17 @@ static int __tty_fasync(int fd, struct file *filp, int on) | |||
2148 | if (retval <= 0) | 2149 | if (retval <= 0) |
2149 | goto out; | 2150 | goto out; |
2150 | 2151 | ||
2152 | ldisc = tty_ldisc_ref(tty); | ||
2153 | if (ldisc) { | ||
2154 | if (ldisc->ops->fasync) | ||
2155 | ldisc->ops->fasync(tty, on); | ||
2156 | tty_ldisc_deref(ldisc); | ||
2157 | } | ||
2158 | |||
2151 | if (on) { | 2159 | if (on) { |
2152 | enum pid_type type; | 2160 | enum pid_type type; |
2153 | struct pid *pid; | 2161 | struct pid *pid; |
2154 | if (!waitqueue_active(&tty->read_wait)) | 2162 | |
2155 | tty->minimum_to_wake = 1; | ||
2156 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2163 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
2157 | if (tty->pgrp) { | 2164 | if (tty->pgrp) { |
2158 | pid = tty->pgrp; | 2165 | pid = tty->pgrp; |
@@ -2165,13 +2172,7 @@ static int __tty_fasync(int fd, struct file *filp, int on) | |||
2165 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 2172 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
2166 | retval = __f_setown(filp, pid, type, 0); | 2173 | retval = __f_setown(filp, pid, type, 0); |
2167 | put_pid(pid); | 2174 | put_pid(pid); |
2168 | if (retval) | ||
2169 | goto out; | ||
2170 | } else { | ||
2171 | if (!tty->fasync && !waitqueue_active(&tty->read_wait)) | ||
2172 | tty->minimum_to_wake = N_TTY_BUF_SIZE; | ||
2173 | } | 2175 | } |
2174 | retval = 0; | ||
2175 | out: | 2176 | out: |
2176 | return retval; | 2177 | return retval; |
2177 | } | 2178 | } |