Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / infiniband / hw / ipath / ipath_diag.c
index 28ddceb..147dd89 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2006 QLogic, Inc. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
 #include <linux/pci.h>
 #include <asm/uaccess.h>
 
-#include "ipath_common.h"
 #include "ipath_kernel.h"
-#include "ips_common.h"
 #include "ipath_layer.h"
+#include "ipath_common.h"
 
 int ipath_diag_inuse;
 static int diag_set_link;
@@ -66,18 +66,20 @@ static struct file_operations diag_file_ops = {
        .release = ipath_diag_release
 };
 
-static struct cdev *diag_cdev;
-static struct class_device *diag_class_dev;
-
-int ipath_diag_init(void)
+int ipath_diag_add(struct ipath_devdata *dd)
 {
-       return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag",
-                              &diag_file_ops, &diag_cdev, &diag_class_dev);
+       char name[16];
+
+       snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit);
+
+       return ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
+                              &diag_file_ops, &dd->diag_cdev,
+                              &dd->diag_class_dev);
 }
 
-void ipath_diag_cleanup(void)
+void ipath_diag_remove(struct ipath_devdata *dd)
 {
-       ipath_cdev_cleanup(&diag_cdev, &diag_class_dev);
+       ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
 }
 
 /**
@@ -101,8 +103,7 @@ static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
        int ret;
 
        /* not very efficient, but it works for now */
-       if (reg_addr < dd->ipath_kregbase ||
-           reg_end > dd->ipath_kregend) {
+       if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) {
                ret = -EINVAL;
                goto bail;
        }
@@ -113,7 +114,7 @@ static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
                        goto bail;
                }
                reg_addr++;
-               uaddr++;
+               uaddr += sizeof(u64);
        }
        ret = 0;
 bail:
@@ -139,8 +140,7 @@ static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
        int ret;
 
        /* not very efficient, but it works for now */
-       if (reg_addr < dd->ipath_kregbase ||
-           reg_end > dd->ipath_kregend) {
+       if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) {
                ret = -EINVAL;
                goto bail;
        }
@@ -153,7 +153,7 @@ static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
                writeq(data, reg_addr);
 
                reg_addr++;
-               uaddr++;
+               uaddr += sizeof(u64);
        }
        ret = 0;
 bail:
@@ -191,7 +191,8 @@ static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr,
                }
 
                reg_addr++;
-               uaddr++;
+               uaddr += sizeof(u32);
+
        }
        ret = 0;
 bail:
@@ -230,7 +231,7 @@ static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr,
                writel(data, reg_addr);
 
                reg_addr++;
-               uaddr++;
+               uaddr += sizeof(u32);
        }
        ret = 0;
 bail:
@@ -239,59 +240,45 @@ bail:
 
 static int ipath_diag_open(struct inode *in, struct file *fp)
 {
+       int unit = iminor(in) - IPATH_DIAG_MINOR_BASE;
        struct ipath_devdata *dd;
-       int unit = 0; /* XXX this is bogus */
-       unsigned long flags;
        int ret;
 
-       dd = ipath_lookup(unit);
-
        mutex_lock(&ipath_mutex);
-       spin_lock_irqsave(&ipath_devs_lock, flags);
 
        if (ipath_diag_inuse) {
                ret = -EBUSY;
                goto bail;
        }
 
-       list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
-               /*
-                * we need at least one infinipath device to be present
-                * (don't use INITTED, because we want to be able to open
-                * even if device is in freeze mode, which cleared INITTED).
-                * There is a small amount of risk to this, which is why we
-                * also verify kregbase is set.
-                */
-
-               if (!(dd->ipath_flags & IPATH_PRESENT) ||
-                   !dd->ipath_kregbase)
-                       continue;
-
-               ipath_diag_inuse = 1;
-               diag_set_link = 0;
-               ret = 0;
+       dd = ipath_lookup(unit);
+
+       if (dd == NULL || !(dd->ipath_flags & IPATH_PRESENT) ||
+           !dd->ipath_kregbase) {
+               ret = -ENODEV;
                goto bail;
        }
 
-       ret = -ENODEV;
-
-bail:
-       spin_unlock_irqrestore(&ipath_devs_lock, flags);
+       fp->private_data = dd;
+       ipath_diag_inuse = 1;
+       diag_set_link = 0;
+       ret = 0;
 
        /* Only expose a way to reset the device if we
           make it into diag mode. */
-       if (ret == 0)
-               ipath_expose_reset(&dd->pcidev->dev);
+       ipath_expose_reset(&dd->pcidev->dev);
 
+bail:
        mutex_unlock(&ipath_mutex);
 
        return ret;
 }
 
-static int ipath_diag_release(struct inode *i, struct file *f)
+static int ipath_diag_release(struct inode *in, struct file *fp)
 {
        mutex_lock(&ipath_mutex);
        ipath_diag_inuse = 0;
+       fp->private_data = NULL;
        mutex_unlock(&ipath_mutex);
        return 0;
 }
@@ -299,17 +286,10 @@ static int ipath_diag_release(struct inode *i, struct file *f)
 static ssize_t ipath_diag_read(struct file *fp, char __user *data,
                               size_t count, loff_t *off)
 {
-       int unit = 0; /* XXX provide for reads on other units some day */
-       struct ipath_devdata *dd;
+       struct ipath_devdata *dd = fp->private_data;
        void __iomem *kreg_base;
        ssize_t ret;
 
-       dd = ipath_lookup(unit);
-       if (!dd) {
-               ret = -ENODEV;
-               goto bail;
-       }
-
        kreg_base = dd->ipath_kregbase;
 
        if (count == 0)
@@ -328,23 +308,16 @@ static ssize_t ipath_diag_read(struct file *fp, char __user *data,
                ret = count;
        }
 
-bail:
        return ret;
 }
 
 static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
                                size_t count, loff_t *off)
 {
-       int unit = 0; /* XXX this is bogus */
-       struct ipath_devdata *dd;
+       struct ipath_devdata *dd = fp->private_data;
        void __iomem *kreg_base;
        ssize_t ret;
 
-       dd = ipath_lookup(unit);
-       if (!dd) {
-               ret = -ENODEV;
-               goto bail;
-       }
        kreg_base = dd->ipath_kregbase;
 
        if (count == 0)
@@ -363,6 +336,5 @@ static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
                ret = count;
        }
 
-bail:
        return ret;
 }