*     the Free Software Foundation; either version 2 of the License, or
  *     (at your option) any later version.
  *
+ *     FIXME: brdp->state needs proper locking.
  */
 
 /*****************************************************************************/
                return -ENODEV;
 
        memset(&stli_brdstats, 0, sizeof(combrd_t));
+
        stli_brdstats.brd = brdp->brdnr;
        stli_brdstats.type = brdp->brdtype;
        stli_brdstats.hwid = 0;
        if (brdp == NULL)
                return -ENODEV;
 
+       mutex_lock(&portp->port.mutex);
        if (brdp->state & BST_STARTED) {
                if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
-                   &stli_cdkstats, sizeof(asystats_t), 1)) < 0)
+                   &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
+                       mutex_unlock(&portp->port.mutex);
                        return rc;
+               }
        } else {
                memset(&stli_cdkstats, 0, sizeof(asystats_t));
        }
        stli_comstats.modem = stli_cdkstats.dcdcnt;
        stli_comstats.hwid = stli_cdkstats.hwid;
        stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
+       mutex_unlock(&portp->port.mutex);
 
        return 0;
 }
        if (!brdp)
                return -ENODEV;
 
+       mutex_lock(&portp->port.mutex);
+
        if (brdp->state & BST_STARTED) {
-               if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0)
+               if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
+                       mutex_unlock(&portp->port.mutex);
                        return rc;
+               }
        }
 
        memset(&stli_comstats, 0, sizeof(comstats_t));
        stli_comstats.brd = portp->brdnr;
        stli_comstats.panel = portp->panelnr;
        stli_comstats.port = portp->portnr;
+       mutex_unlock(&portp->port.mutex);
 
        if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
                return -EFAULT;
        done = 0;
        rc = 0;
 
-       lock_kernel();
-
        switch (cmd) {
        case COM_GETPORTSTATS:
                rc = stli_getportstats(NULL, NULL, argp);
                done++;
                break;
        }
-       unlock_kernel();
-
        if (done)
                return rc;
 
        if (brdp->state == 0)
                return -ENODEV;
 
-       lock_kernel();
-
        switch (cmd) {
        case STL_BINTR:
                EBRDINTR(brdp);
                rc = -ENOIOCTLCMD;
                break;
        }
-       unlock_kernel();
        return rc;
 }
 
 
                timeout = HZ;
        tend = jiffies + timeout;
 
-       lock_kernel();
        while (stl_datastate(portp)) {
                if (signal_pending(current))
                        break;
                if (time_after_eq(jiffies, tend))
                        break;
        }
-       unlock_kernel();
 }
 
 /*****************************************************************************/
        pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
 
        memset(&sio, 0, sizeof(struct serial_struct));
+
+       mutex_lock(&portp->port.mutex);
        sio.line = portp->portnr;
        sio.port = portp->ioaddr;
        sio.flags = portp->port.flags;
        brdp = stl_brds[portp->brdnr];
        if (brdp != NULL)
                sio.irq = brdp->irq;
+       mutex_unlock(&portp->port.mutex);
 
        return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
 }
 
        if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
                return -EFAULT;
+       mutex_lock(&portp->port.mutex);
        if (!capable(CAP_SYS_ADMIN)) {
                if ((sio.baud_base != portp->baud_base) ||
                    (sio.close_delay != portp->close_delay) ||
                    ((sio.flags & ~ASYNC_USR_MASK) !=
-                   (portp->port.flags & ~ASYNC_USR_MASK)))
+                   (portp->port.flags & ~ASYNC_USR_MASK))) {
+                       mutex_unlock(&portp->port.mutex);
                        return -EPERM;
+               }
        } 
 
        portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
        portp->close_delay = sio.close_delay;
        portp->closing_wait = sio.closing_wait;
        portp->custom_divisor = sio.custom_divisor;
+       mutex_unlock(&portp->port.mutex);
        stl_setport(portp, tty->termios);
        return 0;
 }
 
        rc = 0;
 
-       lock_kernel();
-
        switch (cmd) {
        case TIOCGSERIAL:
                rc = stl_getserial(portp, argp);
                rc = -ENOIOCTLCMD;
                break;
        }
-       unlock_kernel();
        return rc;
 }
 
                        return -ENODEV;
        }
 
+       mutex_lock(&portp->port.mutex);
        portp->stats.state = portp->istate;
        portp->stats.flags = portp->port.flags;
        portp->stats.hwid = portp->hwid;
                (STL_TXBUFSIZE - (tail - head));
 
        portp->stats.signals = (unsigned long) stl_getsignals(portp);
+       mutex_unlock(&portp->port.mutex);
 
        return copy_to_user(cp, &portp->stats,
                            sizeof(comstats_t)) ? -EFAULT : 0;
                        return -ENODEV;
        }
 
+       mutex_lock(&portp->port.mutex);
        memset(&portp->stats, 0, sizeof(comstats_t));
        portp->stats.brd = portp->brdnr;
        portp->stats.panel = portp->panelnr;
        portp->stats.port = portp->portnr;
+       mutex_unlock(&portp->port.mutex);
        return copy_to_user(cp, &portp->stats,
                            sizeof(comstats_t)) ? -EFAULT : 0;
 }
                return -ENODEV;
        rc = 0;
 
-       lock_kernel();
        switch (cmd) {
        case COM_GETPORTSTATS:
                rc = stl_getportstats(NULL, NULL, argp);
                rc = -ENOIOCTLCMD;
                break;
        }
-       unlock_kernel();
        return rc;
 }