This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / char / hvcs.c
index c605280..15b1d8c 100644 (file)
@@ -315,7 +315,7 @@ static void hvcs_throttle(struct tty_struct *tty);
 static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
                struct pt_regs *regs);
 
-static int hvcs_write(struct tty_struct *tty,
+static int hvcs_write(struct tty_struct *tty, int from_user,
                const unsigned char *buf, int count);
 static int hvcs_write_room(struct tty_struct *tty);
 static int hvcs_chars_in_buffer(struct tty_struct *tty);
@@ -527,7 +527,7 @@ static int khvcsd(void *unused)
 
 static struct vio_device_id hvcs_driver_table[] __devinitdata= {
        {"serial-server", "hvterm2"},
-       { NULL, }
+       { 0, }
 };
 MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
 
@@ -1183,12 +1183,12 @@ static void hvcs_hangup(struct tty_struct * tty)
  * tty_hangup will allow hvcs_write time to complete execution before it
  * terminates our device.
  */
-static int hvcs_write(struct tty_struct *tty,
+static int hvcs_write(struct tty_struct *tty, int from_user,
                const unsigned char *buf, int count)
 {
        struct hvcs_struct *hvcsd = tty->driver_data;
        unsigned int unit_address;
-       const unsigned char *charbuf;
+       unsigned char *charbuf;
        unsigned long flags;
        int total_sent = 0;
        int tosend = 0;
@@ -1208,7 +1208,21 @@ static int hvcs_write(struct tty_struct *tty,
                count = HVCS_MAX_FROM_USER;
        }
 
-       charbuf = buf;
+       if (!from_user)
+               charbuf = (unsigned char *)buf;
+       else {
+               charbuf = kmalloc(count, GFP_KERNEL);
+               if (!charbuf) {
+                       printk(KERN_WARNING "HVCS: write -ENOMEM.\n");
+                       return -ENOMEM;
+               }
+
+               if (copy_from_user(charbuf, buf, count)) {
+                       kfree(charbuf);
+                       printk(KERN_WARNING "HVCS: write -EFAULT.\n");
+                       return -EFAULT;
+               }
+       }
 
        spin_lock_irqsave(&hvcsd->lock, flags);
 
@@ -1220,6 +1234,8 @@ static int hvcs_write(struct tty_struct *tty,
         */
        if (hvcsd->open_count <= 0) {
                spin_unlock_irqrestore(&hvcsd->lock, flags);
+               if (from_user)
+                       kfree(charbuf);
                return -ENODEV;
        }
 
@@ -1276,6 +1292,8 @@ static int hvcs_write(struct tty_struct *tty,
        }
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
+       if (from_user)
+               kfree(charbuf);
 
        if (result == -1)
                return -EIO;