This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / serial / mcfserial.c
index d8875ae..7f1b9ee 100644 (file)
 #include <linux/serialP.h>
 #include <linux/console.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/semaphore.h>
+#include <asm/bitops.h>
 #include <asm/delay.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
@@ -736,7 +735,7 @@ static void mcfrs_flush_chars(struct tty_struct *tty)
        local_irq_restore(flags);
 }
 
-static int mcfrs_write(struct tty_struct * tty,
+static int mcfrs_write(struct tty_struct * tty, int from_user,
                    const unsigned char *buf, int count)
 {
        volatile unsigned char  *uartp;
@@ -745,8 +744,8 @@ static int mcfrs_write(struct tty_struct * tty,
        int                     c, total = 0;
 
 #if 0
-       printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n",
-               __FILE__, __LINE__, (int)tty, (int)buf, count);
+       printk("%s(%d): mcfrs_write(tty=%x,from_user=%d,buf=%x,count=%d)\n",
+               __FILE__, __LINE__, (int)tty, from_user, (int)buf, count);
 #endif
 
        if (serial_paranoia_check(info, tty->name, "mcfrs_write"))
@@ -765,7 +764,19 @@ static int mcfrs_write(struct tty_struct * tty,
                if (c <= 0)
                        break;
 
-               memcpy(info->xmit_buf + info->xmit_head, buf, c);
+               if (from_user) {
+                       down(&mcfrs_tmp_buf_sem);
+                       if (copy_from_user(mcfrs_tmp_buf, buf, c))
+                               return -EFAULT;
+
+                       local_irq_disable();
+                       c = min(c, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1,
+                                      ((int)SERIAL_XMIT_SIZE) - info->xmit_head));
+                       local_irq_restore(flags);
+                       memcpy(info->xmit_buf + info->xmit_head, mcfrs_tmp_buf, c);
+                       up(&mcfrs_tmp_buf_sem);
+               } else
+                       memcpy(info->xmit_buf + info->xmit_head, buf, c);
 
                local_irq_disable();
                info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
@@ -979,7 +990,7 @@ static void send_break(     struct mcf_serial * info, int duration)
 
        if (!info->addr)
                return;
-       set_current_state(TASK_INTERRUPTIBLE);
+       current->state = TASK_INTERRUPTIBLE;
        uartp = info->addr;
 
        local_irq_save(flags);
@@ -1231,7 +1242,8 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
 #endif 
        if (info->blocked_open) {
                if (info->close_delay) {
-                       msleep_interruptible(jiffies_to_msecs(info->close_delay));
+                       current->state = TASK_INTERRUPTIBLE;
+                       schedule_timeout(info->close_delay);
                }
                wake_up_interruptible(&info->open_wait);
        }
@@ -1296,7 +1308,8 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
                        fifo_cnt++;
                if (fifo_cnt == 0)
                        break;
-               msleep_interruptible(jiffies_to_msecs(char_time));
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(char_time);
                if (signal_pending(current))
                        break;
                if (timeout && time_after(jiffies, orig_jiffies + timeout))