IB/mad: add new ioctl to ABI to support new registration options
authorIra Weiny <ira.weiny@intel.com>
Fri, 8 Aug 2014 23:00:55 +0000 (19:00 -0400)
committerRoland Dreier <roland@purestorage.com>
Mon, 11 Aug 2014 03:36:00 +0000 (20:36 -0700)
Registrations options are specified through flags.  Definitions of flags will
be in subsequent patches.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
12 files changed:
Documentation/infiniband/user_mad.txt
drivers/infiniband/core/agent.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mthca/mthca_mad.c
drivers/infiniband/hw/qib/qib_mad.c
drivers/infiniband/ulp/srpt/ib_srpt.c
include/rdma/ib_mad.h
include/uapi/rdma/ib_user_mad.h

index 8a36695..7aca13a 100644 (file)
@@ -26,6 +26,11 @@ Creating MAD agents
   ioctl.  Also, all agents registered through a file descriptor will
   be unregistered when the descriptor is closed.
 
+  2014 -- a new registration ioctl is now provided which allows additional
+       fields to be provided during registration.
+       Users of this registration call are implicitly setting the use of
+       pkey_index (see below).
+
 Receiving MADs
 
   MADs are received using read().  The receive side now supports
@@ -104,10 +109,10 @@ P_Key Index Handling
   The old ib_umad interface did not allow setting the P_Key index for
   MADs that are sent and did not provide a way for obtaining the P_Key
   index of received MADs.  A new layout for struct ib_user_mad_hdr
-  with a pkey_index member has been defined; however, to preserve
-  binary compatibility with older applications, this new layout will
-  not be used unless the IB_USER_MAD_ENABLE_PKEY ioctl is called
-  before a file descriptor is used for anything else.
+  with a pkey_index member has been defined; however, to preserve binary
+  compatibility with older applications, this new layout will not be used
+  unless one of IB_USER_MAD_ENABLE_PKEY or IB_USER_MAD_REGISTER_AGENT2 ioctl's
+  are called before a file descriptor is used for anything else.
 
   In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented
   to 6, the new layout of struct ib_user_mad_hdr will be used by
index 8e32c5a..f6d2961 100644 (file)
@@ -161,7 +161,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
                port_priv->agent[0] = ib_register_mad_agent(device, port_num,
                                                            IB_QPT_SMI, NULL, 0,
                                                            &agent_send_handler,
-                                                           NULL, NULL);
+                                                           NULL, NULL, 0);
                if (IS_ERR(port_priv->agent[0])) {
                        ret = PTR_ERR(port_priv->agent[0]);
                        goto error2;
@@ -172,7 +172,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
        port_priv->agent[1] = ib_register_mad_agent(device, port_num,
                                                    IB_QPT_GSI, NULL, 0,
                                                    &agent_send_handler,
-                                                   NULL, NULL);
+                                                   NULL, NULL, 0);
        if (IS_ERR(port_priv->agent[1])) {
                ret = PTR_ERR(port_priv->agent[1]);
                goto error3;
index c323917..e28a494 100644 (file)
@@ -3753,7 +3753,7 @@ static void cm_add_one(struct ib_device *ib_device)
        struct cm_port *port;
        struct ib_mad_reg_req reg_req = {
                .mgmt_class = IB_MGMT_CLASS_CM,
-               .mgmt_class_version = IB_CM_CLASS_VERSION
+               .mgmt_class_version = IB_CM_CLASS_VERSION,
        };
        struct ib_port_modify port_modify = {
                .set_port_cap_mask = IB_PORT_CM_SUP
@@ -3801,7 +3801,8 @@ static void cm_add_one(struct ib_device *ib_device)
                                                        0,
                                                        cm_send_handler,
                                                        cm_recv_handler,
-                                                       port);
+                                                       port,
+                                                       0);
                if (IS_ERR(port->mad_agent))
                        goto error2;
 
index f46995d..988bbda 100644 (file)
@@ -198,7 +198,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
                                           u8 rmpp_version,
                                           ib_mad_send_handler send_handler,
                                           ib_mad_recv_handler recv_handler,
-                                          void *context)
+                                          void *context,
+                                          u32 registration_flags)
 {
        struct ib_mad_port_private *port_priv;
        struct ib_mad_agent *ret = ERR_PTR(-EINVAL);
@@ -359,6 +360,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
        mad_agent_priv->agent.context = context;
        mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp;
        mad_agent_priv->agent.port_num = port_num;
+       mad_agent_priv->agent.flags = registration_flags;
        spin_lock_init(&mad_agent_priv->lock);
        INIT_LIST_HEAD(&mad_agent_priv->send_list);
        INIT_LIST_HEAD(&mad_agent_priv->wait_list);
index 233eaf5..c38f030 100644 (file)
@@ -1184,7 +1184,7 @@ static void ib_sa_add_one(struct ib_device *device)
                sa_dev->port[i].agent =
                        ib_register_mad_agent(device, i + s, IB_QPT_GSI,
                                              NULL, 0, send_handler,
-                                             recv_handler, sa_dev);
+                                             recv_handler, sa_dev, 0);
                if (IS_ERR(sa_dev->port[i].agent))
                        goto err;
 
index ea90a3e..11af1c6 100644 (file)
@@ -647,6 +647,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
 
 found:
        if (ureq.mgmt_class) {
+               memset(&req, 0, sizeof(req));
                req.mgmt_class         = ureq.mgmt_class;
                req.mgmt_class_version = ureq.mgmt_class_version;
                memcpy(req.oui, ureq.oui, sizeof req.oui);
@@ -667,7 +668,7 @@ found:
                                      ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
                                      ureq.mgmt_class ? &req : NULL,
                                      ureq.rmpp_version,
-                                     send_handler, recv_handler, file);
+                                     send_handler, recv_handler, file, 0);
        if (IS_ERR(agent)) {
                ret = PTR_ERR(agent);
                agent = NULL;
@@ -705,6 +706,119 @@ out:
        return ret;
 }
 
+static int ib_umad_reg_agent2(struct ib_umad_file *file, void __user *arg)
+{
+       struct ib_user_mad_reg_req2 ureq;
+       struct ib_mad_reg_req req;
+       struct ib_mad_agent *agent = NULL;
+       int agent_id;
+       int ret;
+
+       mutex_lock(&file->port->file_mutex);
+       mutex_lock(&file->mutex);
+
+       if (!file->port->ib_dev) {
+               dev_notice(file->port->dev,
+                          "ib_umad_reg_agent2: invalid device\n");
+               ret = -EPIPE;
+               goto out;
+       }
+
+       if (copy_from_user(&ureq, arg, sizeof(ureq))) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       if (ureq.qpn != 0 && ureq.qpn != 1) {
+               dev_notice(file->port->dev,
+                          "ib_umad_reg_agent2: invalid QPN %d specified\n",
+                          ureq.qpn);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (ureq.flags & ~IB_USER_MAD_REG_FLAGS_CAP) {
+               dev_notice(file->port->dev,
+                          "ib_umad_reg_agent2 failed: invalid registration flags specified 0x%x; supported 0x%x\n",
+                          ureq.flags, IB_USER_MAD_REG_FLAGS_CAP);
+               ret = -EINVAL;
+
+               if (put_user((u32)IB_USER_MAD_REG_FLAGS_CAP,
+                               (u32 __user *) (arg + offsetof(struct
+                               ib_user_mad_reg_req2, flags))))
+                       ret = -EFAULT;
+
+               goto out;
+       }
+
+       for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id)
+               if (!__get_agent(file, agent_id))
+                       goto found;
+
+       dev_notice(file->port->dev,
+                  "ib_umad_reg_agent2: Max Agents (%u) reached\n",
+                  IB_UMAD_MAX_AGENTS);
+       ret = -ENOMEM;
+       goto out;
+
+found:
+       if (ureq.mgmt_class) {
+               memset(&req, 0, sizeof(req));
+               req.mgmt_class         = ureq.mgmt_class;
+               req.mgmt_class_version = ureq.mgmt_class_version;
+               if (ureq.oui & 0xff000000) {
+                       dev_notice(file->port->dev,
+                                  "ib_umad_reg_agent2 failed: oui invalid 0x%08x\n",
+                                  ureq.oui);
+                       ret = -EINVAL;
+                       goto out;
+               }
+               req.oui[2] =  ureq.oui & 0x0000ff;
+               req.oui[1] = (ureq.oui & 0x00ff00) >> 8;
+               req.oui[0] = (ureq.oui & 0xff0000) >> 16;
+               memcpy(req.method_mask, ureq.method_mask,
+                       sizeof(req.method_mask));
+       }
+
+       agent = ib_register_mad_agent(file->port->ib_dev, file->port->port_num,
+                                     ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
+                                     ureq.mgmt_class ? &req : NULL,
+                                     ureq.rmpp_version,
+                                     send_handler, recv_handler, file,
+                                     ureq.flags);
+       if (IS_ERR(agent)) {
+               ret = PTR_ERR(agent);
+               agent = NULL;
+               goto out;
+       }
+
+       if (put_user(agent_id,
+                    (u32 __user *)(arg +
+                               offsetof(struct ib_user_mad_reg_req2, id)))) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       if (!file->already_used) {
+               file->already_used = 1;
+               file->use_pkey_index = 1;
+       }
+
+       file->agent[agent_id] = agent;
+       ret = 0;
+
+out:
+       mutex_unlock(&file->mutex);
+
+       if (ret && agent)
+               ib_unregister_mad_agent(agent);
+
+       mutex_unlock(&file->port->file_mutex);
+
+       return ret;
+}
+
+
 static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
 {
        struct ib_mad_agent *agent = NULL;
@@ -760,6 +874,8 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
                return ib_umad_unreg_agent(filp->private_data, (__u32 __user *) arg);
        case IB_USER_MAD_ENABLE_PKEY:
                return ib_umad_enable_pkey(filp->private_data);
+       case IB_USER_MAD_REGISTER_AGENT2:
+               return ib_umad_reg_agent2(filp->private_data, (void __user *) arg);
        default:
                return -ENOIOCTLCMD;
        }
@@ -776,6 +892,8 @@ static long ib_umad_compat_ioctl(struct file *filp, unsigned int cmd,
                return ib_umad_unreg_agent(filp->private_data, compat_ptr(arg));
        case IB_USER_MAD_ENABLE_PKEY:
                return ib_umad_enable_pkey(filp->private_data);
+       case IB_USER_MAD_REGISTER_AGENT2:
+               return ib_umad_reg_agent2(filp->private_data, compat_ptr(arg));
        default:
                return -ENOIOCTLCMD;
        }
index 287ad05..82a7dd8 100644 (file)
@@ -891,7 +891,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
                                agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
                                                              q ? IB_QPT_GSI : IB_QPT_SMI,
                                                              NULL, 0, send_handler,
-                                                             NULL, NULL);
+                                                             NULL, NULL, 0);
                                if (IS_ERR(agent)) {
                                        ret = PTR_ERR(agent);
                                        goto err;
index b6f7f45..8881fa3 100644 (file)
@@ -294,7 +294,7 @@ int mthca_create_agents(struct mthca_dev *dev)
                        agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
                                                      q ? IB_QPT_GSI : IB_QPT_SMI,
                                                      NULL, 0, send_handler,
-                                                     NULL, NULL);
+                                                     NULL, NULL, 0);
                        if (IS_ERR(agent)) {
                                ret = PTR_ERR(agent);
                                goto err;
index 22c720e..636be11 100644 (file)
@@ -2476,7 +2476,7 @@ int qib_create_agents(struct qib_ibdev *dev)
                ibp = &dd->pport[p].ibport_data;
                agent = ib_register_mad_agent(&dev->ibdev, p + 1, IB_QPT_SMI,
                                              NULL, 0, send_handler,
-                                             NULL, NULL);
+                                             NULL, NULL, 0);
                if (IS_ERR(agent)) {
                        ret = PTR_ERR(agent);
                        goto err;
index fe09f27..8a8311e 100644 (file)
@@ -563,7 +563,7 @@ static int srpt_refresh_port(struct srpt_port *sport)
                                                         &reg_req, 0,
                                                         srpt_mad_send_handler,
                                                         srpt_mad_recv_handler,
-                                                        sport);
+                                                        sport, 0);
                if (IS_ERR(sport->mad_agent)) {
                        ret = PTR_ERR(sport->mad_agent);
                        sport->mad_agent = NULL;
index 3d81b90..876f497 100644 (file)
@@ -355,6 +355,7 @@ typedef void (*ib_mad_recv_handler)(struct ib_mad_agent *mad_agent,
  * @hi_tid: Access layer assigned transaction ID for this client.
  *   Unsolicited MADs sent by this client will have the upper 32-bits
  *   of their TID set to this value.
+ * @flags: registration flags
  * @port_num: Port number on which QP is registered
  * @rmpp_version: If set, indicates the RMPP version used by this agent.
  */
@@ -367,6 +368,7 @@ struct ib_mad_agent {
        ib_mad_snoop_handler    snoop_handler;
        void                    *context;
        u32                     hi_tid;
+       u32                     flags;
        u8                      port_num;
        u8                      rmpp_version;
 };
@@ -426,6 +428,7 @@ struct ib_mad_recv_wc {
  *   in the range from 0x30 to 0x4f. Otherwise not used.
  * @method_mask: The caller will receive unsolicited MADs for any method
  *   where @method_mask = 1.
+ *
  */
 struct ib_mad_reg_req {
        u8      mgmt_class;
@@ -451,6 +454,7 @@ struct ib_mad_reg_req {
  * @recv_handler: The completion callback routine invoked for a received
  *   MAD.
  * @context: User specified context associated with the registration.
+ * @registration_flags: Registration flags to set for this agent
  */
 struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
                                           u8 port_num,
@@ -459,7 +463,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
                                           u8 rmpp_version,
                                           ib_mad_send_handler send_handler,
                                           ib_mad_recv_handler recv_handler,
-                                          void *context);
+                                          void *context,
+                                          u32 registration_flags);
 
 enum ib_mad_snoop_flags {
        /*IB_MAD_SNOOP_POSTED_SENDS        = 1,*/
index d6fce1c..c00b081 100644 (file)
@@ -191,6 +191,42 @@ struct ib_user_mad_reg_req {
        __u8    rmpp_version;
 };
 
+/**
+ * ib_user_mad_reg_req2 - MAD registration request
+ *
+ * @id                 - Set by the _kernel_; used by userspace to identify the
+ *                       registered agent in future requests.
+ * @qpn                - Queue pair number; must be 0 or 1.
+ * @mgmt_class         - Indicates which management class of MADs should be
+ *                       receive by the caller.  This field is only required if
+ *                       the user wishes to receive unsolicited MADs, otherwise
+ *                       it should be 0.
+ * @mgmt_class_version - Indicates which version of MADs for the given
+ *                       management class to receive.
+ * @res                - Ignored.
+ * @flags              - additional registration flags; Must be in the set of
+ *                       flags defined in IB_USER_MAD_REG_FLAGS_CAP
+ * @method_mask        - The caller wishes to receive unsolicited MADs for the
+ *                       methods whose bit(s) is(are) set.
+ * @oui                - Indicates IEEE OUI to use when mgmt_class is a vendor
+ *                       class in the range from 0x30 to 0x4f. Otherwise not
+ *                       used.
+ * @rmpp_version       - If set, indicates the RMPP version to use.
+ */
+#define IB_USER_MAD_REG_FLAGS_CAP (0)
+struct ib_user_mad_reg_req2 {
+       __u32   id;
+       __u32   qpn;
+       __u8    mgmt_class;
+       __u8    mgmt_class_version;
+       __u16   res;
+       __u32   flags;
+       __u64   method_mask[2];
+       __u32   oui;
+       __u8    rmpp_version;
+       __u8    reserved[3];
+};
+
 #define IB_IOCTL_MAGIC         0x1b
 
 #define IB_USER_MAD_REGISTER_AGENT     _IOWR(IB_IOCTL_MAGIC, 1, \
@@ -200,4 +236,7 @@ struct ib_user_mad_reg_req {
 
 #define IB_USER_MAD_ENABLE_PKEY                _IO(IB_IOCTL_MAGIC, 3)
 
+#define IB_USER_MAD_REGISTER_AGENT2     _IOWR(IB_IOCTL_MAGIC, 4, \
+                                             struct ib_user_mad_reg_req2)
+
 #endif /* IB_USER_MAD_H */