aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/n_tty.c')
-rw-r--r--drivers/tty/n_tty.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index cf6e0f2e1331..cc57a3a6b02b 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1949,6 +1949,18 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
1949 return ldata->commit_head - ldata->read_tail >= amt; 1949 return ldata->commit_head - ldata->read_tail >= amt;
1950} 1950}
1951 1951
1952static inline int check_other_done(struct tty_struct *tty)
1953{
1954 int done = test_bit(TTY_OTHER_DONE, &tty->flags);
1955 if (done) {
1956 /* paired with cmpxchg() in check_other_closed(); ensures
1957 * read buffer head index is not stale
1958 */
1959 smp_mb__after_atomic();
1960 }
1961 return done;
1962}
1963
1952/** 1964/**
1953 * copy_from_read_buf - copy read data directly 1965 * copy_from_read_buf - copy read data directly
1954 * @tty: terminal device 1966 * @tty: terminal device
@@ -2167,7 +2179,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
2167 struct n_tty_data *ldata = tty->disc_data; 2179 struct n_tty_data *ldata = tty->disc_data;
2168 unsigned char __user *b = buf; 2180 unsigned char __user *b = buf;
2169 DEFINE_WAIT_FUNC(wait, woken_wake_function); 2181 DEFINE_WAIT_FUNC(wait, woken_wake_function);
2170 int c; 2182 int c, done;
2171 int minimum, time; 2183 int minimum, time;
2172 ssize_t retval = 0; 2184 ssize_t retval = 0;
2173 long timeout; 2185 long timeout;
@@ -2235,8 +2247,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
2235 ((minimum - (b - buf)) >= 1)) 2247 ((minimum - (b - buf)) >= 1))
2236 ldata->minimum_to_wake = (minimum - (b - buf)); 2248 ldata->minimum_to_wake = (minimum - (b - buf));
2237 2249
2250 done = check_other_done(tty);
2251
2238 if (!input_available_p(tty, 0)) { 2252 if (!input_available_p(tty, 0)) {
2239 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { 2253 if (done) {
2240 retval = -EIO; 2254 retval = -EIO;
2241 break; 2255 break;
2242 } 2256 }
@@ -2443,12 +2457,12 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
2443 2457
2444 poll_wait(file, &tty->read_wait, wait); 2458 poll_wait(file, &tty->read_wait, wait);
2445 poll_wait(file, &tty->write_wait, wait); 2459 poll_wait(file, &tty->write_wait, wait);
2460 if (check_other_done(tty))
2461 mask |= POLLHUP;
2446 if (input_available_p(tty, 1)) 2462 if (input_available_p(tty, 1))
2447 mask |= POLLIN | POLLRDNORM; 2463 mask |= POLLIN | POLLRDNORM;
2448 if (tty->packet && tty->link->ctrl_status) 2464 if (tty->packet && tty->link->ctrl_status)
2449 mask |= POLLPRI | POLLIN | POLLRDNORM; 2465 mask |= POLLPRI | POLLIN | POLLRDNORM;
2450 if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
2451 mask |= POLLHUP;
2452 if (tty_hung_up_p(file)) 2466 if (tty_hung_up_p(file))
2453 mask |= POLLHUP; 2467 mask |= POLLHUP;
2454 if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { 2468 if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {