]> Pileus Git - ~andy/linux/blobdiff - drivers/char/amiserial.c
Merge branch 'for-linus' of git://neil.brown.name/md
[~andy/linux] / drivers / char / amiserial.c
index 4f8d60c25a980f1dc73d648c235dcaf81fa165ec..a11c8c9ca3d4b858029205f9a265b6ee96b04fdb 100644 (file)
@@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info,
        if (!retinfo)
                return -EFAULT;
        memset(&tmp, 0, sizeof(tmp));
-       lock_kernel();
+       tty_lock();
        tmp.type = state->type;
        tmp.line = state->line;
        tmp.port = state->port;
@@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info,
        tmp.close_delay = state->close_delay;
        tmp.closing_wait = state->closing_wait;
        tmp.custom_divisor = state->custom_divisor;
-       unlock_kernel();
+       tty_unlock();
        if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
                return -EFAULT;
        return 0;
@@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info,
        if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
                return -EFAULT;
 
-       lock_kernel();
+       tty_lock();
        state = info->state;
        old_state = *state;
   
        change_irq = new_serial.irq != state->irq;
        change_port = (new_serial.port != state->port);
        if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
-         unlock_kernel();
+         tty_unlock();
          return -EINVAL;
        }
   
@@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info,
        }
 
        if (new_serial.baud_base < 9600) {
-               unlock_kernel();
+               tty_unlock();
                return -EINVAL;
        }
 
@@ -1163,7 +1163,7 @@ check_and_exit:
                }
        } else
                retval = startup(info);
-       unlock_kernel();
+       tty_unlock();
        return retval;
 }
 
@@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 {
        struct async_struct * info = tty->driver_data;
        unsigned long orig_jiffies, char_time;
+       int tty_was_locked = tty_locked();
        int lsr;
 
        if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
@@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 
        orig_jiffies = jiffies;
 
-       lock_kernel();
+       /*
+        * tty_wait_until_sent is called from lots of places,
+        * with or without the BTM.
+        */
+       if (!tty_was_locked)
+               tty_lock();
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
-       unlock_kernel();
+       if (!tty_was_locked)
+               tty_unlock();
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
@@ -1703,7 +1710,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                printk("block_til_ready blocking: ttys%d, count = %d\n",
                       info->line, state->count);
 #endif
+               tty_unlock();
                schedule();
+               tty_lock();
        }
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(&info->open_wait, &wait);