Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / char / hvcs.c
index 15b1d8c..8d97b39 100644 (file)
  * the hvcs_final_close() function in order to get it out of the spinlock.
  * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping
  * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from
- * arch/ppc64/hvcserver.h.
+ * include/asm-powerpc/hvcserver.h 
  *
  * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to
  * prevent possible lockup with realtime scheduling as similarily pointed out by
@@ -168,9 +168,10 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
 
 /*
  * The hcall interface involves putting 8 chars into each of two registers.
- * We load up those 2 registers (in arch/ppc64/hvconsole.c) by casting char[16]
- * to long[2].  It would work without __ALIGNED__, but a little (tiny) bit
- * slower because an unaligned load is slower than aligned load.
+ * We load up those 2 registers (in arch/powerpc/platforms/pseries/hvconsole.c)
+ * by casting char[16] to long[2].  It would work without __ALIGNED__, but a 
+ * little (tiny) bit slower because an unaligned load is slower than aligned 
+ * load.
  */
 #define __ALIGNED__    __attribute__((__aligned__(8)))
 
@@ -257,7 +258,7 @@ static struct task_struct *hvcs_task;
 static unsigned long *hvcs_pi_buff;
 
 /* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */
-static spinlock_t hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(hvcs_pi_lock);
 
 /* One vty-server per hvcs_struct */
 struct hvcs_struct {
@@ -308,14 +309,14 @@ struct hvcs_struct {
 #define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
 
 static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
-static spinlock_t hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(hvcs_structs_lock);
 
 static void hvcs_unthrottle(struct tty_struct *tty);
 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, int from_user,
+static int hvcs_write(struct tty_struct *tty,
                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);
@@ -438,7 +439,6 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
        char buf[HVCS_BUFF_LEN] __ALIGNED__;
        unsigned long flags;
        int got = 0;
-       int i;
 
        spin_lock_irqsave(&hvcsd->lock, flags);
 
@@ -456,12 +456,11 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
        /* remove the read masks */
        hvcsd->todo_mask &= ~(HVCS_READ_MASK);
 
-       if ((tty->flip.count + HVCS_BUFF_LEN) < TTY_FLIPBUF_SIZE) {
+       if (tty_buffer_request_room(tty, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
                got = hvc_get_chars(unit_address,
                                &buf[0],
                                HVCS_BUFF_LEN);
-               for (i=0;got && i<got;i++)
-                       tty_insert_flip_char(tty, buf[i], TTY_NORMAL);
+               tty_insert_flip_string(tty, buf, got);
        }
 
        /* Give the TTY time to process the data we just sent. */
@@ -469,10 +468,9 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
                hvcsd->todo_mask |= HVCS_QUICK_READ;
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
-       if (tty->flip.count) {
-               /* This is synch because tty->low_latency == 1 */
+       /* This is synch because tty->low_latency == 1 */
+       if(got)
                tty_flip_buffer_push(tty);
-       }
 
        if (!got) {
                /* Do this _after_ the flip_buffer_push */
@@ -527,7 +525,7 @@ static int khvcsd(void *unused)
 
 static struct vio_device_id hvcs_driver_table[] __devinitdata= {
        {"serial-server", "hvterm2"},
-       { 0, }
+       { "", "" }
 };
 MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
 
@@ -631,7 +629,7 @@ static int __devinit hvcs_probe(
        /* hvcsd->tty is zeroed out with the memset */
        memset(hvcsd, 0x00, sizeof(*hvcsd));
 
-       hvcsd->lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&hvcsd->lock);
        /* Automatically incs the refcount the first time */
        kobject_init(&hvcsd->kobj);
        /* Set up the callback for terminating the hvcs_struct's life */
@@ -720,10 +718,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
 };
 
 static struct vio_driver hvcs_vio_driver = {
-       .name           = hvcs_driver_name,
        .id_table       = hvcs_driver_table,
        .probe          = hvcs_probe,
        .remove         = hvcs_remove,
+       .driver         = {
+               .name   = hvcs_driver_name,
+               .owner  = THIS_MODULE,
+       }
 };
 
 /* Only called from hvcs_get_pi please */
@@ -903,7 +904,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
                 * It is possible the vty-server was removed after the irq was
                 * requested but before we have time to enable interrupts.
                 */
-               if (vio_enable_interrupts(vdev) == H_Success)
+               if (vio_enable_interrupts(vdev) == H_SUCCESS)
                        return 0;
                else {
                        printk(KERN_ERR "HVCS: int enable failed for"
@@ -1183,12 +1184,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, int from_user,
+static int hvcs_write(struct tty_struct *tty,
                const unsigned char *buf, int count)
 {
        struct hvcs_struct *hvcsd = tty->driver_data;
        unsigned int unit_address;
-       unsigned char *charbuf;
+       const unsigned char *charbuf;
        unsigned long flags;
        int total_sent = 0;
        int tosend = 0;
@@ -1208,21 +1209,7 @@ static int hvcs_write(struct tty_struct *tty, int from_user,
                count = HVCS_MAX_FROM_USER;
        }
 
-       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;
-               }
-       }
+       charbuf = buf;
 
        spin_lock_irqsave(&hvcsd->lock, flags);
 
@@ -1234,8 +1221,6 @@ static int hvcs_write(struct tty_struct *tty, int from_user,
         */
        if (hvcsd->open_count <= 0) {
                spin_unlock_irqrestore(&hvcsd->lock, flags);
-               if (from_user)
-                       kfree(charbuf);
                return -ENODEV;
        }
 
@@ -1292,8 +1277,6 @@ static int hvcs_write(struct tty_struct *tty, int from_user,
        }
 
        spin_unlock_irqrestore(&hvcsd->lock, flags);
-       if (from_user)
-               kfree(charbuf);
 
        if (result == -1)
                return -EIO;
@@ -1381,6 +1364,7 @@ static int __init hvcs_module_init(void)
 
        hvcs_tty_driver->driver_name = hvcs_driver_name;
        hvcs_tty_driver->name = hvcs_device_node;
+       hvcs_tty_driver->devfs_name = hvcs_device_node;
 
        /*
         * We'll let the system assign us a major number, indicated by leaving
@@ -1483,7 +1467,7 @@ static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
 }
 /* The sysfs interface for the driver and devices */
 
-static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct vio_dev *viod = to_vio_dev(dev);
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1497,7 +1481,7 @@ static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
 }
 static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
 
-static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct vio_dev *viod = to_vio_dev(dev);
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1511,7 +1495,7 @@ static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
 }
 static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
 
-static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
+static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
                size_t count)
 {
        /*
@@ -1522,7 +1506,7 @@ static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
        return -EPERM;
 }
 
-static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
+static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct vio_dev *viod = to_vio_dev(dev);
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1538,7 +1522,7 @@ static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
 static DEVICE_ATTR(current_vty,
        S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
 
-static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
+static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
                size_t count)
 {
        struct vio_dev *viod = to_vio_dev(dev);
@@ -1576,7 +1560,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
        return count;
 }
 
-static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
+static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct vio_dev *viod = to_vio_dev(dev);
        struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1591,7 +1575,7 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
 static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
                hvcs_vterm_state_show, hvcs_vterm_state_store);
 
-static ssize_t hvcs_index_show(struct device *dev, char *buf)
+static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct vio_dev *viod = to_vio_dev(dev);
        struct hvcs_struct *hvcsd = from_vio_dev(viod);