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);
static struct vio_device_id hvcs_driver_table[] __devinitdata= {
{"serial-server", "hvterm2"},
- { NULL, }
+ { 0, }
};
MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
* 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;
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);
*/
if (hvcsd->open_count <= 0) {
spin_unlock_irqrestore(&hvcsd->lock, flags);
+ if (from_user)
+ kfree(charbuf);
return -ENODEV;
}
}
spin_unlock_irqrestore(&hvcsd->lock, flags);
+ if (from_user)
+ kfree(charbuf);
if (result == -1)
return -EIO;