]> Pileus Git - ~andy/linux/blobdiff - drivers/tty/bfin_jtag_comm.c
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[~andy/linux] / drivers / tty / bfin_jtag_comm.c
index d81013c3d2293449d8606b3455f6ceef3533005f..61fc74fe17473d56e2f2fe18bca2dee83dd27bac 100644 (file)
@@ -62,8 +62,6 @@ static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d)
 
 static struct tty_driver *bfin_jc_driver;
 static struct task_struct *bfin_jc_kthread;
-static struct tty_struct * volatile bfin_jc_tty;
-static DEFINE_MUTEX(bfin_jc_tty_mutex);
 static struct tty_port port;
 static volatile struct circ_buf bfin_jc_write_buf;
 
@@ -73,18 +71,21 @@ bfin_jc_emudat_manager(void *arg)
        uint32_t inbound_len = 0, outbound_len = 0;
 
        while (!kthread_should_stop()) {
+               struct tty_struct *tty = tty_port_tty_get(&port);
                /* no one left to give data to, so sleep */
-               if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) {
+               if (tty == NULL && circ_empty(&bfin_jc_write_buf)) {
                        pr_debug("waiting for readers\n");
                        __set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule();
                        __set_current_state(TASK_RUNNING);
+                       continue;
                }
 
                /* no data available, so just chill */
                if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) {
                        pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n",
                                inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head);
+                       tty_kref_put(tty);
                        if (inbound_len)
                                schedule();
                        else
@@ -94,9 +95,6 @@ bfin_jc_emudat_manager(void *arg)
 
                /* if incoming data is ready, eat it */
                if (bfin_read_DBGSTAT() & EMUDIF) {
-                       struct tty_struct *tty;
-                       mutex_lock(&bfin_jc_tty_mutex);
-                       tty = (struct tty_struct *)bfin_jc_tty;
                        if (tty != NULL) {
                                uint32_t emudat = bfin_read_emudat();
                                if (inbound_len == 0) {
@@ -110,7 +108,6 @@ bfin_jc_emudat_manager(void *arg)
                                        tty_flip_buffer_push(tty);
                                }
                        }
-                       mutex_unlock(&bfin_jc_tty_mutex);
                }
 
                /* if outgoing data is ready, post it */
@@ -120,7 +117,6 @@ bfin_jc_emudat_manager(void *arg)
                                bfin_write_emudat(outbound_len);
                                pr_debug("outgoing length: 0x%08x\n", outbound_len);
                        } else {
-                               struct tty_struct *tty;
                                int tail = bfin_jc_write_buf.tail;
                                size_t ate = (4 <= outbound_len ? 4 : outbound_len);
                                uint32_t emudat =
@@ -132,14 +128,12 @@ bfin_jc_emudat_manager(void *arg)
                                );
                                bfin_jc_write_buf.tail += ate;
                                outbound_len -= ate;
-                               mutex_lock(&bfin_jc_tty_mutex);
-                               tty = (struct tty_struct *)bfin_jc_tty;
                                if (tty)
                                        tty_wakeup(tty);
-                               mutex_unlock(&bfin_jc_tty_mutex);
                                pr_debug("  outgoing data: 0x%08x (pushing %zu)\n", emudat, ate);
                        }
                }
+               tty_kref_put(tty);
        }
 
        __set_current_state(TASK_RUNNING);
@@ -149,22 +143,28 @@ bfin_jc_emudat_manager(void *arg)
 static int
 bfin_jc_open(struct tty_struct *tty, struct file *filp)
 {
-       mutex_lock(&bfin_jc_tty_mutex);
+       unsigned long flags;
+
+       spin_lock_irqsave(&port.lock, flags);
        port.count++;
-       bfin_jc_tty = tty;
+       spin_unlock_irqrestore(&port.lock, flags);
+       tty_port_tty_set(&port, tty);
        wake_up_process(bfin_jc_kthread);
-       mutex_unlock(&bfin_jc_tty_mutex);
        return 0;
 }
 
 static void
 bfin_jc_close(struct tty_struct *tty, struct file *filp)
 {
-       mutex_lock(&bfin_jc_tty_mutex);
-       if (--port.count == 0)
-               bfin_jc_tty = NULL;
+       unsigned long flags;
+       bool last;
+
+       spin_lock_irqsave(&port.lock, flags);
+       last = --port.count == 0;
+       spin_unlock_irqrestore(&port.lock, flags);
+       if (last)
+               tty_port_tty_set(&port, NULL);
        wake_up_process(bfin_jc_kthread);
-       mutex_unlock(&bfin_jc_tty_mutex);
 }
 
 /* XXX: we dont handle the put_char() case where we must handle count = 1 */