Allow multiple open() calls to tty devices.
authorFlorian Pose <fp@igh-essen.com>
Tue, 02 Feb 2010 14:10:52 +0100
changeset 1797 5bf740cd1599
parent 1796 3bb9ca8b58f2
child 1803 5b04770444df
Allow multiple open() calls to tty devices.
tty/module.c
--- a/tty/module.c	Tue Jan 26 16:43:08 2010 +0100
+++ b/tty/module.c	Tue Feb 02 14:10:52 2010 +0100
@@ -109,6 +109,8 @@
 
     struct timer_list timer;
     struct tty_struct *tty;
+    unsigned int open_count;
+    struct semaphore sem;
 
     ec_tty_operations_t ops;
     void *cb_data;
@@ -198,6 +200,8 @@
     t->rx_write_idx = 0;
     init_timer(&t->timer);
     t->tty = NULL;
+    t->open_count = 0;
+    init_MUTEX(&t->sem);
     t->ops = *ops;
     t->cb_data = cb_data;
 
@@ -366,24 +370,29 @@
     int line = tty->index;
 
 #if EC_TTY_DEBUG >= 1
-    printk(KERN_INFO PFX "Opening line %i.\n", line);
+    printk(KERN_INFO PFX "%s(tty=%p, file=%p): Opening line %i.\n",
+            __func__, tty, file, line);
 #endif
 
     if (line < 0 || line >= EC_TTY_MAX_DEVICES) {
+        tty->driver_data = NULL;
         return -ENXIO;
     }
 
     t = ttys[line];
     if (!t) {
+        tty->driver_data = NULL;
         return -ENXIO;
     }
 
-    if (t->tty) {
-        return -EBUSY;
-    }
-
-    t->tty = tty;
-    tty->driver_data = t;
+    if (!t->tty) {
+        t->tty = tty;
+        tty->driver_data = t;
+    }
+
+    down(&t->sem);
+    t->open_count++;
+    up(&t->sem);
     return 0;
 }
 
@@ -394,11 +403,16 @@
     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
 
 #if EC_TTY_DEBUG >= 1
-    printk(KERN_INFO PFX "Closing line %i.\n", tty->index);
-#endif
-
-    if (t->tty == tty) {
-        t->tty = NULL;
+    printk(KERN_INFO PFX "%s(tty=%p, file=%p): Closing line %i.\n",
+            __func__, tty, file, tty->index);
+#endif
+
+    if (t) {
+        down(&t->sem);
+        if (--t->open_count == 0) {
+            t->tty = NULL;
+        }
+        up(&t->sem);
     }
 }