/*
- * 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;
.release = ipath_diag_release
};
-int ipath_diag_add(struct ipath_devdata *dd)
-{
- char name[16];
-
- snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit);
+static struct cdev *diag_cdev;
+static struct class_device *diag_class_dev;
- return ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
- &diag_file_ops, &dd->diag_cdev,
- &dd->diag_class_dev);
+int ipath_diag_init(void)
+{
+ return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag",
+ &diag_file_ops, &diag_cdev, &diag_class_dev);
}
-void ipath_diag_remove(struct ipath_devdata *dd)
+void ipath_diag_cleanup(void)
{
- ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
+ ipath_cdev_cleanup(&diag_cdev, &diag_class_dev);
}
/**
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;
}
goto bail;
}
reg_addr++;
- uaddr += sizeof(u64);
+ uaddr++;
}
ret = 0;
bail:
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;
}
writeq(data, reg_addr);
reg_addr++;
- uaddr += sizeof(u64);
+ uaddr++;
}
ret = 0;
bail:
}
reg_addr++;
- uaddr += sizeof(u32);
-
+ uaddr++;
}
ret = 0;
bail:
writel(data, reg_addr);
reg_addr++;
- uaddr += sizeof(u32);
+ uaddr++;
}
ret = 0;
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;
}
- dd = ipath_lookup(unit);
-
- if (dd == NULL || !(dd->ipath_flags & IPATH_PRESENT) ||
- !dd->ipath_kregbase) {
- ret = -ENODEV;
+ 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;
goto bail;
}
- fp->private_data = dd;
- ipath_diag_inuse = 1;
- diag_set_link = 0;
- ret = 0;
+ ret = -ENODEV;
+
+bail:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
/* Only expose a way to reset the device if we
make it into diag mode. */
- ipath_expose_reset(&dd->pcidev->dev);
+ if (ret == 0)
+ ipath_expose_reset(&dd->pcidev->dev);
-bail:
mutex_unlock(&ipath_mutex);
return ret;
}
-static int ipath_diag_release(struct inode *in, struct file *fp)
+static int ipath_diag_release(struct inode *i, struct file *f)
{
mutex_lock(&ipath_mutex);
ipath_diag_inuse = 0;
- fp->private_data = NULL;
mutex_unlock(&ipath_mutex);
return 0;
}
static ssize_t ipath_diag_read(struct file *fp, char __user *data,
size_t count, loff_t *off)
{
- struct ipath_devdata *dd = fp->private_data;
+ int unit = 0; /* XXX provide for reads on other units some day */
+ struct ipath_devdata *dd;
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)
ret = count;
}
+bail:
return ret;
}
static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
size_t count, loff_t *off)
{
- struct ipath_devdata *dd = fp->private_data;
+ int unit = 0; /* XXX this is bogus */
+ struct ipath_devdata *dd;
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)
ret = count;
}
+bail:
return ret;
}