[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