]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/tty_io.c
tty: restore locked ioctl file op
[linux-2.6-omap-h63xx.git] / drivers / char / tty_io.c
index bc849957508d305a283dbf28d65d5d54fd2b2e41..a96f26a63fa2e6e54b98ed898dcda2488ac64d25 100644 (file)
@@ -368,6 +368,29 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
        }
 }
 
+/**
+ *     tty_buffer_flush                -       flush full tty buffers
+ *     @tty: tty to flush
+ *
+ *     flush all the buffers containing receive data
+ *
+ *     Locking: none
+ */
+
+static void tty_buffer_flush(struct tty_struct *tty)
+{
+       struct tty_buffer *thead;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tty->buf.lock, flags);
+       while((thead = tty->buf.head) != NULL) {
+               tty->buf.head = thead->next;
+               tty_buffer_free(tty, thead);
+       }
+       tty->buf.tail = NULL;
+       spin_unlock_irqrestore(&tty->buf.lock, flags);
+}
+
 /**
  *     tty_buffer_find         -       find a free tty buffer
  *     @tty: tty owning the buffer
@@ -1125,7 +1148,8 @@ int tty_check_change(struct tty_struct * tty)
                return 0;
        if (is_current_pgrp_orphaned())
                return -EIO;
-       (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+       kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+       set_thread_flag(TIF_SIGPENDING);
        return -ERESTARTSYS;
 }
 
@@ -1149,8 +1173,14 @@ static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait)
        return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
 }
 
-static long hung_up_tty_ioctl(struct file * file,
-                             unsigned int cmd, unsigned long arg)
+static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
+                            unsigned int cmd, unsigned long arg)
+{
+       return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
+}
+
+static long hung_up_tty_compat_ioctl(struct file * file,
+                                    unsigned int cmd, unsigned long arg)
 {
        return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
@@ -1198,8 +1228,8 @@ static const struct file_operations hung_up_tty_fops = {
        .read           = hung_up_tty_read,
        .write          = hung_up_tty_write,
        .poll           = hung_up_tty_poll,
-       .unlocked_ioctl = hung_up_tty_ioctl,
-       .compat_ioctl   = hung_up_tty_ioctl,
+       .ioctl          = hung_up_tty_ioctl,
+       .compat_ioctl   = hung_up_tty_compat_ioctl,
        .release        = tty_release,
 };
 
@@ -1248,6 +1278,7 @@ void tty_ldisc_flush(struct tty_struct *tty)
                        ld->flush_buffer(tty);
                tty_ldisc_deref(ld);
        }
+       tty_buffer_flush(tty);
 }
 
 EXPORT_SYMBOL_GPL(tty_ldisc_flush);
@@ -3350,6 +3381,15 @@ int tty_ioctl(struct inode * inode, struct file * file,
                case TIOCMBIC:
                case TIOCMBIS:
                        return tty_tiocmset(tty, file, cmd, p);
+               case TCFLSH:
+                       switch (arg) {
+                       case TCIFLUSH:
+                       case TCIOFLUSH:
+                               /* flush tty buffer and allow ldisc to process ioctl */
+                               tty_buffer_flush(tty);
+                               break;
+                       }
+                       break;
        }
        if (tty->driver->ioctl) {
                retval = (tty->driver->ioctl)(tty, file, cmd, arg);