IB/ipath - initialize diagpkt file on device init only

Don't attempt to set up the diagpkt device in the module init code.
Instead, wait until a piece of hardware is initted.  Fixes a problem
when loading the ib_ipath module when no InfiniPath hardware is present:
modprobe would go into the D state and stay there.

Signed-off-by: Robert Walsh <robert.walsh@qlogic.com>

diff -r c68975ef442a drivers/infiniband/hw/ipath/ipath_diag.c
--- a/drivers/infiniband/hw/ipath/ipath_diag.c	Tue Oct 10 14:10:34 2006 -0700
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c	Tue Oct 10 14:26:07 2006 -0700
@@ -66,19 +66,54 @@ static struct file_operations diag_file_
 	.release = ipath_diag_release
 };
 
+static ssize_t ipath_diagpkt_write(struct file *fp,
+				   const char __user *data,
+				   size_t count, loff_t *off);
+
+static struct file_operations diagpkt_file_ops = {
+	.owner = THIS_MODULE,
+	.write = ipath_diagpkt_write,
+};
+
+static atomic_t diagpkt_count = ATOMIC_INIT(0);
+static struct cdev *diagpkt_cdev;
+static struct class_device *diagpkt_class_dev;
+
 int ipath_diag_add(struct ipath_devdata *dd)
 {
 	char name[16];
+	int ret = 0;
+
+	if (atomic_inc_return(&diagpkt_count) == 1) {
+		ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR,
+				      "ipath_diagpkt", &diagpkt_file_ops,
+				      &diagpkt_cdev, &diagpkt_class_dev);
+
+		if (ret) {
+                        ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
+				      "device: %d", ret);
+			goto done;
+		}
+	}
 
 	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);
+	ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
+			      &diag_file_ops, &dd->diag_cdev,
+			      &dd->diag_class_dev);
+	if (ret)
+		ipath_dev_err(dd, "Couldn't create %s device: %d",
+			      name, ret);
+
+done:
+	return ret;
 }
 
 void ipath_diag_remove(struct ipath_devdata *dd)
 {
+	if (atomic_dec_and_test(&diagpkt_count))
+		ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev);
+
 	ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
 }
 
@@ -272,30 +307,6 @@ bail:
 	mutex_unlock(&ipath_mutex);
 
 	return ret;
-}
-
-static ssize_t ipath_diagpkt_write(struct file *fp,
-				   const char __user *data,
-				   size_t count, loff_t *off);
-
-static struct file_operations diagpkt_file_ops = {
-	.owner = THIS_MODULE,
-	.write = ipath_diagpkt_write,
-};
-
-static struct cdev *diagpkt_cdev;
-static struct class_device *diagpkt_class_dev;
-
-int __init ipath_diagpkt_add(void)
-{
-	return ipath_cdev_init(IPATH_DIAGPKT_MINOR,
-			       "ipath_diagpkt", &diagpkt_file_ops,
-			       &diagpkt_cdev, &diagpkt_class_dev);
-}
-
-void __exit ipath_diagpkt_remove(void)
-{
-	ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev);
 }
 
 /**
diff -r c68975ef442a drivers/infiniband/hw/ipath/ipath_driver.c
--- a/drivers/infiniband/hw/ipath/ipath_driver.c	Tue Oct 10 14:10:34 2006 -0700
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c	Tue Oct 10 14:25:44 2006 -0700
@@ -2021,17 +2021,7 @@ static int __init infinipath_init(void)
 		goto bail_group;
 	}
 
-	ret = ipath_diagpkt_add();
-	if (ret < 0) {
-		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
-		       "diag data device: error %d\n", -ret);
-		goto bail_ipathfs;
-	}
- 
 	goto bail;
-
-bail_ipathfs:
-	ipath_exit_ipathfs();
 
 bail_group:
 	ipath_driver_remove_group(&ipath_driver.driver);
diff -r c68975ef442a drivers/infiniband/hw/ipath/ipath_kernel.h
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h	Tue Oct 10 14:10:34 2006 -0700
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h	Tue Oct 10 14:25:45 2006 -0700
@@ -869,9 +869,6 @@ void ipath_device_remove_group(struct de
 void ipath_device_remove_group(struct device *, struct ipath_devdata *);
 int ipath_expose_reset(struct device *);
 
-int ipath_diagpkt_add(void);
-void ipath_diagpkt_remove(void);
-
 int ipath_init_ipathfs(void);
 void ipath_exit_ipathfs(void);
 int ipathfs_add_device(struct ipath_devdata *);
