}
 
        spin_lock_init(&pInfo->lock);
+       mutex_init(&pInfo->read_lock);
        pInfo->tty = tty;
        pInfo->priority = R3964_MASTER;
        pInfo->rx_first = pInfo->rx_last = NULL;
 
        TRACE_L("read()");
 
-       tty_lock(tty);
+       /*
+        *      Internal serialization of reads.
+        */
+       if (file->f_flags & O_NONBLOCK) {
+               if (!mutex_trylock(&pInfo->read_lock))
+                       return -EAGAIN;
+       } else {
+               if (mutex_lock_interruptible(&pInfo->read_lock))
+                       return -ERESTARTSYS;
+       }
 
        pClient = findClient(pInfo, task_pid(current));
        if (pClient) {
                                goto unlock;
                        }
                        /* block until there is a message: */
-                       wait_event_interruptible_tty(tty, tty->read_wait,
+                       wait_event_interruptible(tty->read_wait,
                                        (pMsg = remove_msg(pInfo, pClient)));
                }
 
        }
        ret = -EPERM;
 unlock:
-       tty_unlock(tty);
+       mutex_unlock(&pInfo->read_lock);
        return ret;
 }
 
        pHeader->locks = 0;
        pHeader->owner = NULL;
 
-       tty_lock(tty);
-
        pClient = findClient(pInfo, task_pid(current));
        if (pClient) {
                pHeader->owner = pClient;
        add_tx_queue(pInfo, pHeader);
        trigger_transmit(pInfo);
 
-       tty_unlock(tty);
-
        return 0;
 }
 
 
        unsigned char last_rx;
        unsigned char bcc;
         unsigned int  blocks_in_rx_queue;
-         
-       
+
+       struct mutex read_lock;         /* serialize r3964_read */
+
        struct r3964_client_info *firstClient;
        unsigned int state;
        unsigned int flags;