[ofa-general] [PATCH] IB/core/user_mad.c: Add support for issmdisabled

Hal Rosenstock halr at voltaire.com
Tue Mar 27 17:45:48 PDT 2007


IB/core/user_mad.c: Add support for issmdisabled

Signed-off-by: Hal Rosenstock <halr at voltaire.com>

diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index c069ebe..9ef2603 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Voltaire, Inc. All rights reserved. 
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -31,7 +31,6 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: user_mad.c 5596 2006-03-03 01:00:07Z sean.hefty $
  */
 
 #include <linux/module.h>
@@ -92,6 +91,8 @@ struct ib_umad_port {
 
 	struct cdev           *sm_dev;
 	struct class_device   *sm_class_dev;
+	struct cdev           *smdis_dev;
+	struct class_device   *smdis_class_dev;   
 	struct semaphore       sm_sem;
 
 	struct rw_semaphore    mutex;
@@ -135,7 +136,7 @@ static const dev_t base_dev = MKDEV(IB_U
 
 static DEFINE_SPINLOCK(port_lock);
 static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
-static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);
+static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 3);
 
 static void ib_umad_add_one(struct ib_device *device);
 static void ib_umad_remove_one(struct ib_device *device);
@@ -852,6 +853,77 @@ static const struct file_operations umad
 	.release = ib_umad_sm_close
 };
 
+static int ib_umad_smdis_open(struct inode *inode, struct file *filp)
+{
+	struct ib_umad_port *port;
+	struct ib_port_modify props = {
+		.set_port_cap_mask = IB_PORT_SM_DISABLED
+	};
+	int ret;
+
+	spin_lock(&port_lock);
+	port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - 2*IB_UMAD_MAX_PORTS];
+	if (port)
+		kref_get(&port->umad_dev->ref);
+	spin_unlock(&port_lock);
+
+	if (!port)
+		return -ENXIO;
+
+	if (filp->f_flags & O_NONBLOCK) {
+		if (down_trylock(&port->sm_sem)) {
+			ret = -EAGAIN;
+			goto fail;
+		}
+	} else {
+		if (down_interruptible(&port->sm_sem)) {
+			ret = -ERESTARTSYS;
+			goto fail;
+		}
+
+	}
+
+	ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
+	if (ret) {
+		up(&port->sm_sem);
+		goto fail;
+	}
+
+	filp->private_data = port;
+
+	return 0;
+
+fail:
+	kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+	return ret;
+}
+
+static int ib_umad_smdis_close(struct inode *inode, struct file *filp)
+{
+	struct ib_umad_port *port = filp->private_data;
+	struct ib_port_modify props = {
+		.clr_port_cap_mask = IB_PORT_SM_DISABLED
+	};
+	int ret = 0;
+
+	down_write(&port->mutex);
+	if (port->ib_dev)
+		ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
+	up_write(&port->mutex);
+
+	up(&port->sm_sem);
+
+	kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+
+	return ret;
+}
+
+static const struct file_operations umad_smdis_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = ib_umad_smdis_open,
+	.release = ib_umad_smdis_close
+};
+
 static struct ib_client umad_client = {
 	.name   = "umad",
 	.add    = ib_umad_add_one,
@@ -947,12 +1019,41 @@ static int ib_umad_init_port(struct ib_d
 	if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
 		goto err_sm_class;
 
+	port->smdis_dev = cdev_alloc();
+	if (!port->smdis_dev)
+		goto err_sm_class;
+	port->smdis_dev->owner = THIS_MODULE;
+	port->smdis_dev->ops   = &umad_smdis_fops;
+	kobject_set_name(&port->smdis_dev->kobj, "issmdisabled%d", port->dev_num);
+	if (cdev_add(port->smdis_dev, base_dev + port->dev_num + 2*IB_UMAD_MAX_PORTS, 1))
+		goto err_smdis_cdev;
+
+	port->smdis_class_dev = class_device_create(umad_class, NULL, port->smdis_dev->dev,
+						    device->dma_device,
+						    "issmdisabled%d",
+						    port->dev_num);
+	if (IS_ERR(port->smdis_class_dev))
+                goto err_smdis_cdev;
+
+	class_set_devdata(port->smdis_class_dev, port);
+
+	if (class_device_create_file(port->smdis_class_dev, &class_device_attr_ibdev))
+		goto err_smdis_class;
+	if (class_device_create_file(port->smdis_class_dev, &class_device_attr_port))
+		goto err_smdis_class;
+
 	spin_lock(&port_lock);
 	umad_port[port->dev_num] = port;
 	spin_unlock(&port_lock);
 
 	return 0;
 
+err_smdis_class:
+	class_device_destroy(umad_class, port->smdis_dev->dev);
+
+err_smdis_cdev:
+	cdev_del(port->smdis_dev);
+
 err_sm_class:
 	class_device_destroy(umad_class, port->sm_dev->dev);
 
@@ -979,9 +1080,11 @@ static void ib_umad_kill_port(struct ib_
 
 	class_device_destroy(umad_class, port->dev->dev);
 	class_device_destroy(umad_class, port->sm_dev->dev);
+	class_device_destroy(umad_class, port->smdis_dev->dev);
 
 	cdev_del(port->dev);
 	cdev_del(port->sm_dev);
+	cdev_del(port->smdis_dev);
 
 	spin_lock(&port_lock);
 	umad_port[port->dev_num] = NULL;






More information about the general mailing list