aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-06-01 16:53:05 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 16:47:43 -0400
commitbe1bc2889a4db4961ef69f47fb471ecae9f23ade (patch)
treefd6d5e46e69efd9d66e6baa184988461f608f49a
parent4e608671674b62e97166f903830d5553e37970e8 (diff)
tty: introduce wait_event_interruptible_tty
Calling wait_event_interruptible implicitly releases the BKL when it sleeps, but we need to do this explcitly when we have converted it to a mutex. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/char/cyclades.c2
-rw-r--r--drivers/char/istallion.c12
-rw-r--r--drivers/char/n_r3964.c2
-rw-r--r--drivers/char/tty_port.c2
-rw-r--r--drivers/char/vt_ioctl.c5
-rw-r--r--drivers/serial/crisv10.c4
-rw-r--r--include/linux/tty.h42
7 files changed, 59 insertions, 10 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 51acfe39a438..27aad9422332 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1607,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
1607 * If the port is the middle of closing, bail out now 1607 * If the port is the middle of closing, bail out now
1608 */ 1608 */
1609 if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { 1609 if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
1610 wait_event_interruptible(info->port.close_wait, 1610 wait_event_interruptible_tty(info->port.close_wait,
1611 !(info->port.flags & ASYNC_CLOSING)); 1611 !(info->port.flags & ASYNC_CLOSING));
1612 return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; 1612 return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
1613 } 1613 }
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 5e9a81d8ebcf..be28391adb79 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l
954 * order of opens and closes may not be preserved across shared 954 * order of opens and closes may not be preserved across shared
955 * memory, so we must wait until it is complete. 955 * memory, so we must wait until it is complete.
956 */ 956 */
957 wait_event_interruptible(portp->raw_wait, 957 wait_event_interruptible_tty(portp->raw_wait,
958 !test_bit(ST_CLOSING, &portp->state)); 958 !test_bit(ST_CLOSING, &portp->state));
959 if (signal_pending(current)) { 959 if (signal_pending(current)) {
960 return -ERESTARTSYS; 960 return -ERESTARTSYS;
@@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l
989 set_bit(ST_OPENING, &portp->state); 989 set_bit(ST_OPENING, &portp->state);
990 spin_unlock_irqrestore(&brd_lock, flags); 990 spin_unlock_irqrestore(&brd_lock, flags);
991 991
992 wait_event_interruptible(portp->raw_wait, 992 wait_event_interruptible_tty(portp->raw_wait,
993 !test_bit(ST_OPENING, &portp->state)); 993 !test_bit(ST_OPENING, &portp->state));
994 if (signal_pending(current)) 994 if (signal_pending(current))
995 rc = -ERESTARTSYS; 995 rc = -ERESTARTSYS;
@@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
1020 * occurs on this port. 1020 * occurs on this port.
1021 */ 1021 */
1022 if (wait) { 1022 if (wait) {
1023 wait_event_interruptible(portp->raw_wait, 1023 wait_event_interruptible_tty(portp->raw_wait,
1024 !test_bit(ST_CLOSING, &portp->state)); 1024 !test_bit(ST_CLOSING, &portp->state));
1025 if (signal_pending(current)) { 1025 if (signal_pending(current)) {
1026 return -ERESTARTSYS; 1026 return -ERESTARTSYS;
@@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
1052 * to come back. 1052 * to come back.
1053 */ 1053 */
1054 rc = 0; 1054 rc = 0;
1055 wait_event_interruptible(portp->raw_wait, 1055 wait_event_interruptible_tty(portp->raw_wait,
1056 !test_bit(ST_CLOSING, &portp->state)); 1056 !test_bit(ST_CLOSING, &portp->state));
1057 if (signal_pending(current)) 1057 if (signal_pending(current))
1058 rc = -ERESTARTSYS; 1058 rc = -ERESTARTSYS;
@@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
1073 1073
1074static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) 1074static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
1075{ 1075{
1076 /*
1077 * no need for wait_event_tty because clearing ST_CMDING cannot block
1078 * on BTM
1079 */
1076 wait_event_interruptible(portp->raw_wait, 1080 wait_event_interruptible(portp->raw_wait,
1077 !test_bit(ST_CMDING, &portp->state)); 1081 !test_bit(ST_CMDING, &portp->state));
1078 if (signal_pending(current)) 1082 if (signal_pending(current))
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index f4bd2591e39f..a98290d7a2c5 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
1079 goto unlock; 1079 goto unlock;
1080 } 1080 }
1081 /* block until there is a message: */ 1081 /* block until there is a message: */
1082 wait_event_interruptible(pInfo->read_wait, 1082 wait_event_interruptible_tty(pInfo->read_wait,
1083 (pMsg = remove_msg(pInfo, pClient))); 1083 (pMsg = remove_msg(pInfo, pClient)));
1084 } 1084 }
1085 1085
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index a3bd1d0b66cf..35eb30402f18 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port,
231 231
232 /* block if port is in the process of being closed */ 232 /* block if port is in the process of being closed */
233 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { 233 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
234 wait_event_interruptible(port->close_wait, 234 wait_event_interruptible_tty(port->close_wait,
235 !(port->flags & ASYNC_CLOSING)); 235 !(port->flags & ASYNC_CLOSING));
236 if (port->flags & ASYNC_HUP_NOTIFY) 236 if (port->flags & ASYNC_HUP_NOTIFY)
237 return -EAGAIN; 237 return -EAGAIN;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index cf87c5336229..2bbeaaea46e9 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw)
133 list_add(&vw->list, &vt_events); 133 list_add(&vw->list, &vt_events);
134 spin_unlock_irqrestore(&vt_event_lock, flags); 134 spin_unlock_irqrestore(&vt_event_lock, flags);
135 /* Wait for it to pass */ 135 /* Wait for it to pass */
136 wait_event_interruptible(vt_event_waitqueue, vw->done); 136 wait_event_interruptible_tty(vt_event_waitqueue, vw->done);
137 /* Dequeue it */ 137 /* Dequeue it */
138 spin_lock_irqsave(&vt_event_lock, flags); 138 spin_lock_irqsave(&vt_event_lock, flags);
139 list_del(&vw->list); 139 list_del(&vw->list);
@@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc)
1761 return -EIO; 1761 return -EIO;
1762 } 1762 }
1763 release_console_sem(); 1763 release_console_sem();
1764 tty_lock();
1764 if (vt_waitactive(vt + 1)) { 1765 if (vt_waitactive(vt + 1)) {
1765 pr_debug("Suspend: Can't switch VCs."); 1766 pr_debug("Suspend: Can't switch VCs.");
1767 tty_unlock();
1766 return -EINTR; 1768 return -EINTR;
1767 } 1769 }
1770 tty_unlock();
1768 return prev; 1771 return prev;
1769} 1772}
1770 1773
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index f848e188deae..94bfb9f238e1 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -3992,7 +3992,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
3992 */ 3992 */
3993 if (tty_hung_up_p(filp) || 3993 if (tty_hung_up_p(filp) ||
3994 (info->flags & ASYNC_CLOSING)) { 3994 (info->flags & ASYNC_CLOSING)) {
3995 wait_event_interruptible(info->close_wait, 3995 wait_event_interruptible_tty(info->close_wait,
3996 !(info->flags & ASYNC_CLOSING)); 3996 !(info->flags & ASYNC_CLOSING));
3997#ifdef SERIAL_DO_RESTART 3997#ifdef SERIAL_DO_RESTART
3998 if (info->flags & ASYNC_HUP_NOTIFY) 3998 if (info->flags & ASYNC_HUP_NOTIFY)
@@ -4150,7 +4150,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
4150 */ 4150 */
4151 if (tty_hung_up_p(filp) || 4151 if (tty_hung_up_p(filp) ||
4152 (info->flags & ASYNC_CLOSING)) { 4152 (info->flags & ASYNC_CLOSING)) {
4153 wait_event_interruptible(info->close_wait, 4153 wait_event_interruptible_tty(info->close_wait,
4154 !(info->flags & ASYNC_CLOSING)); 4154 !(info->flags & ASYNC_CLOSING));
4155#ifdef SERIAL_DO_RESTART 4155#ifdef SERIAL_DO_RESTART
4156 return ((info->flags & ASYNC_HUP_NOTIFY) ? 4156 return ((info->flags & ASYNC_HUP_NOTIFY) ?
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6ead6b60c743..955d72ea71c0 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -607,5 +607,47 @@ static inline void tty_unlock(void) __releases(kernel_lock)
607} 607}
608#define tty_locked() (kernel_locked()) 608#define tty_locked() (kernel_locked())
609 609
610/*
611 * wait_event_interruptible_tty -- wait for a condition with the tty lock held
612 *
613 * The condition we are waiting for might take a long time to
614 * become true, or might depend on another thread taking the
615 * BTM. In either case, we need to drop the BTM to guarantee
616 * forward progress. This is a leftover from the conversion
617 * from the BKL and should eventually get removed as the BTM
618 * falls out of use.
619 *
620 * Do not use in new code.
621 */
622#define wait_event_interruptible_tty(wq, condition) \
623({ \
624 int __ret = 0; \
625 if (!(condition)) { \
626 __wait_event_interruptible_tty(wq, condition, __ret); \
627 } \
628 __ret; \
629})
630
631#define __wait_event_interruptible_tty(wq, condition, ret) \
632do { \
633 DEFINE_WAIT(__wait); \
634 \
635 for (;;) { \
636 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
637 if (condition) \
638 break; \
639 if (!signal_pending(current)) { \
640 tty_unlock(); \
641 schedule(); \
642 tty_lock(); \
643 continue; \
644 } \
645 ret = -ERESTARTSYS; \
646 break; \
647 } \
648 finish_wait(&wq, &__wait); \
649} while (0)
650
651
610#endif /* __KERNEL__ */ 652#endif /* __KERNEL__ */
611#endif 653#endif