Merge branch 'wr-cleanup' into k.o/for-4.4
authorDoug Ledford <dledford@redhat.com>
Thu, 29 Oct 2015 02:23:34 +0000 (22:23 -0400)
committerDoug Ledford <dledford@redhat.com>
Thu, 29 Oct 2015 02:23:34 +0000 (22:23 -0400)
17 files changed:
1  2 
drivers/infiniband/core/mad.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
include/rdma/ib_verbs.h

@@@ -752,7 -752,7 +752,7 @@@ static int handle_outgoing_dr_smp(struc
        struct ib_device *device = mad_agent_priv->agent.device;
        u8 port_num;
        struct ib_wc mad_wc;
-       struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
+       struct ib_ud_wr *send_wr = &mad_send_wr->send_wr;
        size_t mad_size = port_mad_size(mad_agent_priv->qp_info->port_priv);
        u16 out_mad_pkey_index = 0;
        u16 drslid;
  
        if (rdma_cap_ib_switch(device) &&
            smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
-               port_num = send_wr->wr.ud.port_num;
+               port_num = send_wr->port_num;
        else
                port_num = mad_agent_priv->agent.port_num;
  
        }
  
        build_smp_wc(mad_agent_priv->agent.qp,
-                    send_wr->wr_id, drslid,
-                    send_wr->wr.ud.pkey_index,
-                    send_wr->wr.ud.port_num, &mad_wc);
+                    send_wr->wr.wr_id, drslid,
+                    send_wr->pkey_index,
+                    send_wr->port_num, &mad_wc);
  
        if (opa && smp->base_version == OPA_MGMT_BASE_VERSION) {
                mad_wc.byte_len = mad_send_wr->send_buf.hdr_len
  
        local->mad_send_wr = mad_send_wr;
        if (opa) {
-               local->mad_send_wr->send_wr.wr.ud.pkey_index = out_mad_pkey_index;
+               local->mad_send_wr->send_wr.pkey_index = out_mad_pkey_index;
                local->return_wc_byte_len = mad_size;
        }
        /* Reference MAD agent until send side of local completion handled */
@@@ -1039,14 -1039,14 +1039,14 @@@ struct ib_mad_send_buf * ib_create_send
  
        mad_send_wr->sg_list[1].lkey = mad_agent->qp->pd->local_dma_lkey;
  
-       mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
-       mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
-       mad_send_wr->send_wr.num_sge = 2;
-       mad_send_wr->send_wr.opcode = IB_WR_SEND;
-       mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;
-       mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;
-       mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
-       mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
+       mad_send_wr->send_wr.wr.wr_id = (unsigned long) mad_send_wr;
+       mad_send_wr->send_wr.wr.sg_list = mad_send_wr->sg_list;
+       mad_send_wr->send_wr.wr.num_sge = 2;
+       mad_send_wr->send_wr.wr.opcode = IB_WR_SEND;
+       mad_send_wr->send_wr.wr.send_flags = IB_SEND_SIGNALED;
+       mad_send_wr->send_wr.remote_qpn = remote_qpn;
+       mad_send_wr->send_wr.remote_qkey = IB_QP_SET_QKEY;
+       mad_send_wr->send_wr.pkey_index = pkey_index;
  
        if (rmpp_active) {
                ret = alloc_send_rmpp_list(mad_send_wr, mad_size, gfp_mask);
@@@ -1151,7 -1151,7 +1151,7 @@@ int ib_send_mad(struct ib_mad_send_wr_p
  
        /* Set WR ID to find mad_send_wr upon completion */
        qp_info = mad_send_wr->mad_agent_priv->qp_info;
-       mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
+       mad_send_wr->send_wr.wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
        mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;
  
        mad_agent = mad_send_wr->send_buf.mad_agent;
  
        spin_lock_irqsave(&qp_info->send_queue.lock, flags);
        if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
-               ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
+               ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr.wr,
                                   &bad_send_wr);
                list = &qp_info->send_queue.list;
        } else {
@@@ -1244,7 -1244,7 +1244,7 @@@ int ib_post_send_mad(struct ib_mad_send
                 * request associated with the completion
                 */
                next_send_buf = send_buf->next;
-               mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;
+               mad_send_wr->send_wr.ah = send_buf->ah;
  
                if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==
                    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
@@@ -1877,7 -1877,7 +1877,7 @@@ static inline int rcv_has_same_gid(cons
                                          ((1 << lmc) - 1)));
                } else {
                        if (ib_get_cached_gid(device, port_num,
 -                                            attr.grh.sgid_index, &sgid))
 +                                            attr.grh.sgid_index, &sgid, NULL))
                                return 0;
                        return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
                                       16);
@@@ -2457,7 -2457,7 +2457,7 @@@ retry
        ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
  
        if (queued_send_wr) {
-               ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
+               ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr.wr,
                                   &bad_send_wr);
                if (ret) {
                        dev_err(&port_priv->device->dev,
@@@ -2515,7 -2515,7 +2515,7 @@@ static void mad_error_handler(struct ib
                        struct ib_send_wr *bad_send_wr;
  
                        mad_send_wr->retry = 0;
-                       ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr,
+                       ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr.wr,
                                        &bad_send_wr);
                        if (ret)
                                ib_mad_send_done_handler(port_priv, wc);
@@@ -2713,7 -2713,7 +2713,7 @@@ static void local_completions(struct wo
                        build_smp_wc(recv_mad_agent->agent.qp,
                                     (unsigned long) local->mad_send_wr,
                                     be16_to_cpu(IB_LID_PERMISSIVE),
-                                    local->mad_send_wr->send_wr.wr.ud.pkey_index,
+                                    local->mad_send_wr->send_wr.pkey_index,
                                     recv_mad_agent->agent.port_num, &wc);
  
                        local->mad_priv->header.recv_wc.wc = &wc;
@@@ -1478,7 -1478,7 +1478,7 @@@ ssize_t ib_uverbs_create_cq(struct ib_u
        if (copy_from_user(&cmd, buf, sizeof(cmd)))
                return -EFAULT;
  
 -      INIT_UDATA(&ucore, buf, cmd.response, sizeof(cmd), sizeof(resp));
 +      INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd), sizeof(resp));
  
        INIT_UDATA(&uhw, buf + sizeof(cmd),
                   (unsigned long)cmd.response + sizeof(resp),
@@@ -1741,65 -1741,66 +1741,65 @@@ ssize_t ib_uverbs_destroy_cq(struct ib_
        return in_len;
  }
  
 -ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 -                          struct ib_device *ib_dev,
 -                          const char __user *buf, int in_len,
 -                          int out_len)
 -{
 -      struct ib_uverbs_create_qp      cmd;
 -      struct ib_uverbs_create_qp_resp resp;
 -      struct ib_udata                 udata;
 -      struct ib_uqp_object           *obj;
 -      struct ib_device               *device;
 -      struct ib_pd                   *pd = NULL;
 -      struct ib_xrcd                 *xrcd = NULL;
 -      struct ib_uobject              *uninitialized_var(xrcd_uobj);
 -      struct ib_cq                   *scq = NULL, *rcq = NULL;
 -      struct ib_srq                  *srq = NULL;
 -      struct ib_qp                   *qp;
 -      struct ib_qp_init_attr          attr;
 -      int ret;
 -
 -      if (out_len < sizeof resp)
 -              return -ENOSPC;
 -
 -      if (copy_from_user(&cmd, buf, sizeof cmd))
 -              return -EFAULT;
 -
 -      if (cmd.qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
 +static int create_qp(struct ib_uverbs_file *file,
 +                   struct ib_udata *ucore,
 +                   struct ib_udata *uhw,
 +                   struct ib_uverbs_ex_create_qp *cmd,
 +                   size_t cmd_sz,
 +                   int (*cb)(struct ib_uverbs_file *file,
 +                             struct ib_uverbs_ex_create_qp_resp *resp,
 +                             struct ib_udata *udata),
 +                   void *context)
 +{
 +      struct ib_uqp_object            *obj;
 +      struct ib_device                *device;
 +      struct ib_pd                    *pd = NULL;
 +      struct ib_xrcd                  *xrcd = NULL;
 +      struct ib_uobject               *uninitialized_var(xrcd_uobj);
 +      struct ib_cq                    *scq = NULL, *rcq = NULL;
 +      struct ib_srq                   *srq = NULL;
 +      struct ib_qp                    *qp;
 +      char                            *buf;
 +      struct ib_qp_init_attr          attr;
 +      struct ib_uverbs_ex_create_qp_resp resp;
 +      int                             ret;
 +
 +      if (cmd->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
                return -EPERM;
  
 -      INIT_UDATA(&udata, buf + sizeof cmd,
 -                 (unsigned long) cmd.response + sizeof resp,
 -                 in_len - sizeof cmd, out_len - sizeof resp);
 -
        obj = kzalloc(sizeof *obj, GFP_KERNEL);
        if (!obj)
                return -ENOMEM;
  
 -      init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class);
 +      init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext,
 +                &qp_lock_class);
        down_write(&obj->uevent.uobject.mutex);
  
 -      if (cmd.qp_type == IB_QPT_XRC_TGT) {
 -              xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
 +      if (cmd->qp_type == IB_QPT_XRC_TGT) {
 +              xrcd = idr_read_xrcd(cmd->pd_handle, file->ucontext,
 +                                   &xrcd_uobj);
                if (!xrcd) {
                        ret = -EINVAL;
                        goto err_put;
                }
                device = xrcd->device;
        } else {
 -              if (cmd.qp_type == IB_QPT_XRC_INI) {
 -                      cmd.max_recv_wr = cmd.max_recv_sge = 0;
 +              if (cmd->qp_type == IB_QPT_XRC_INI) {
 +                      cmd->max_recv_wr = 0;
 +                      cmd->max_recv_sge = 0;
                } else {
 -                      if (cmd.is_srq) {
 -                              srq = idr_read_srq(cmd.srq_handle, file->ucontext);
 +                      if (cmd->is_srq) {
 +                              srq = idr_read_srq(cmd->srq_handle,
 +                                                 file->ucontext);
                                if (!srq || srq->srq_type != IB_SRQT_BASIC) {
                                        ret = -EINVAL;
                                        goto err_put;
                                }
                        }
  
 -                      if (cmd.recv_cq_handle != cmd.send_cq_handle) {
 -                              rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0);
 +                      if (cmd->recv_cq_handle != cmd->send_cq_handle) {
 +                              rcq = idr_read_cq(cmd->recv_cq_handle,
 +                                                file->ucontext, 0);
                                if (!rcq) {
                                        ret = -EINVAL;
                                        goto err_put;
                        }
                }
  
 -              scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq);
 +              scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq);
                rcq = rcq ?: scq;
 -              pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
 +              pd  = idr_read_pd(cmd->pd_handle, file->ucontext);
                if (!pd || !scq) {
                        ret = -EINVAL;
                        goto err_put;
        attr.recv_cq       = rcq;
        attr.srq           = srq;
        attr.xrcd          = xrcd;
 -      attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
 -      attr.qp_type       = cmd.qp_type;
 +      attr.sq_sig_type   = cmd->sq_sig_all ? IB_SIGNAL_ALL_WR :
 +                                            IB_SIGNAL_REQ_WR;
 +      attr.qp_type       = cmd->qp_type;
        attr.create_flags  = 0;
  
 -      attr.cap.max_send_wr     = cmd.max_send_wr;
 -      attr.cap.max_recv_wr     = cmd.max_recv_wr;
 -      attr.cap.max_send_sge    = cmd.max_send_sge;
 -      attr.cap.max_recv_sge    = cmd.max_recv_sge;
 -      attr.cap.max_inline_data = cmd.max_inline_data;
 +      attr.cap.max_send_wr     = cmd->max_send_wr;
 +      attr.cap.max_recv_wr     = cmd->max_recv_wr;
 +      attr.cap.max_send_sge    = cmd->max_send_sge;
 +      attr.cap.max_recv_sge    = cmd->max_recv_sge;
 +      attr.cap.max_inline_data = cmd->max_inline_data;
  
        obj->uevent.events_reported     = 0;
        INIT_LIST_HEAD(&obj->uevent.event_list);
        INIT_LIST_HEAD(&obj->mcast_list);
  
 -      if (cmd.qp_type == IB_QPT_XRC_TGT)
 +      if (cmd_sz >= offsetof(typeof(*cmd), create_flags) +
 +                    sizeof(cmd->create_flags))
 +              attr.create_flags = cmd->create_flags;
 +
 +      if (attr.create_flags & ~IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
 +              ret = -EINVAL;
 +              goto err_put;
 +      }
 +
 +      buf = (void *)cmd + sizeof(*cmd);
 +      if (cmd_sz > sizeof(*cmd))
 +              if (!(buf[0] == 0 && !memcmp(buf, buf + 1,
 +                                           cmd_sz - sizeof(*cmd) - 1))) {
 +                      ret = -EINVAL;
 +                      goto err_put;
 +              }
 +
 +      if (cmd->qp_type == IB_QPT_XRC_TGT)
                qp = ib_create_qp(pd, &attr);
        else
 -              qp = device->create_qp(pd, &attr, &udata);
 +              qp = device->create_qp(pd, &attr, uhw);
  
        if (IS_ERR(qp)) {
                ret = PTR_ERR(qp);
                goto err_put;
        }
  
 -      if (cmd.qp_type != IB_QPT_XRC_TGT) {
 +      if (cmd->qp_type != IB_QPT_XRC_TGT) {
                qp->real_qp       = qp;
                qp->device        = device;
                qp->pd            = pd;
                goto err_destroy;
  
        memset(&resp, 0, sizeof resp);
 -      resp.qpn             = qp->qp_num;
 -      resp.qp_handle       = obj->uevent.uobject.id;
 -      resp.max_recv_sge    = attr.cap.max_recv_sge;
 -      resp.max_send_sge    = attr.cap.max_send_sge;
 -      resp.max_recv_wr     = attr.cap.max_recv_wr;
 -      resp.max_send_wr     = attr.cap.max_send_wr;
 -      resp.max_inline_data = attr.cap.max_inline_data;
 +      resp.base.qpn             = qp->qp_num;
 +      resp.base.qp_handle       = obj->uevent.uobject.id;
 +      resp.base.max_recv_sge    = attr.cap.max_recv_sge;
 +      resp.base.max_send_sge    = attr.cap.max_send_sge;
 +      resp.base.max_recv_wr     = attr.cap.max_recv_wr;
 +      resp.base.max_send_wr     = attr.cap.max_send_wr;
 +      resp.base.max_inline_data = attr.cap.max_inline_data;
  
 -      if (copy_to_user((void __user *) (unsigned long) cmd.response,
 -                       &resp, sizeof resp)) {
 -              ret = -EFAULT;
 -              goto err_copy;
 -      }
 +      resp.response_length = offsetof(typeof(resp), response_length) +
 +                             sizeof(resp.response_length);
 +
 +      ret = cb(file, &resp, ucore);
 +      if (ret)
 +              goto err_cb;
  
        if (xrcd) {
                obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
  
        up_write(&obj->uevent.uobject.mutex);
  
 -      return in_len;
 -
 -err_copy:
 +      return 0;
 +err_cb:
        idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
  
  err_destroy:
@@@ -1954,113 -1937,6 +1954,113 @@@ err_put
        return ret;
  }
  
 +static int ib_uverbs_create_qp_cb(struct ib_uverbs_file *file,
 +                                struct ib_uverbs_ex_create_qp_resp *resp,
 +                                struct ib_udata *ucore)
 +{
 +      if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base)))
 +              return -EFAULT;
 +
 +      return 0;
 +}
 +
 +ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 +                          struct ib_device *ib_dev,
 +                          const char __user *buf, int in_len,
 +                          int out_len)
 +{
 +      struct ib_uverbs_create_qp      cmd;
 +      struct ib_uverbs_ex_create_qp   cmd_ex;
 +      struct ib_udata                 ucore;
 +      struct ib_udata                 uhw;
 +      ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp);
 +      int                             err;
 +
 +      if (out_len < resp_size)
 +              return -ENOSPC;
 +
 +      if (copy_from_user(&cmd, buf, sizeof(cmd)))
 +              return -EFAULT;
 +
 +      INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd),
 +                 resp_size);
 +      INIT_UDATA(&uhw, buf + sizeof(cmd),
 +                 (unsigned long)cmd.response + resp_size,
 +                 in_len - sizeof(cmd), out_len - resp_size);
 +
 +      memset(&cmd_ex, 0, sizeof(cmd_ex));
 +      cmd_ex.user_handle = cmd.user_handle;
 +      cmd_ex.pd_handle = cmd.pd_handle;
 +      cmd_ex.send_cq_handle = cmd.send_cq_handle;
 +      cmd_ex.recv_cq_handle = cmd.recv_cq_handle;
 +      cmd_ex.srq_handle = cmd.srq_handle;
 +      cmd_ex.max_send_wr = cmd.max_send_wr;
 +      cmd_ex.max_recv_wr = cmd.max_recv_wr;
 +      cmd_ex.max_send_sge = cmd.max_send_sge;
 +      cmd_ex.max_recv_sge = cmd.max_recv_sge;
 +      cmd_ex.max_inline_data = cmd.max_inline_data;
 +      cmd_ex.sq_sig_all = cmd.sq_sig_all;
 +      cmd_ex.qp_type = cmd.qp_type;
 +      cmd_ex.is_srq = cmd.is_srq;
 +
 +      err = create_qp(file, &ucore, &uhw, &cmd_ex,
 +                      offsetof(typeof(cmd_ex), is_srq) +
 +                      sizeof(cmd.is_srq), ib_uverbs_create_qp_cb,
 +                      NULL);
 +
 +      if (err)
 +              return err;
 +
 +      return in_len;
 +}
 +
 +static int ib_uverbs_ex_create_qp_cb(struct ib_uverbs_file *file,
 +                                   struct ib_uverbs_ex_create_qp_resp *resp,
 +                                   struct ib_udata *ucore)
 +{
 +      if (ib_copy_to_udata(ucore, resp, resp->response_length))
 +              return -EFAULT;
 +
 +      return 0;
 +}
 +
 +int ib_uverbs_ex_create_qp(struct ib_uverbs_file *file,
 +                         struct ib_device *ib_dev,
 +                         struct ib_udata *ucore,
 +                         struct ib_udata *uhw)
 +{
 +      struct ib_uverbs_ex_create_qp_resp resp;
 +      struct ib_uverbs_ex_create_qp cmd = {0};
 +      int err;
 +
 +      if (ucore->inlen < (offsetof(typeof(cmd), comp_mask) +
 +                          sizeof(cmd.comp_mask)))
 +              return -EINVAL;
 +
 +      err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
 +      if (err)
 +              return err;
 +
 +      if (cmd.comp_mask)
 +              return -EINVAL;
 +
 +      if (cmd.reserved)
 +              return -EINVAL;
 +
 +      if (ucore->outlen < (offsetof(typeof(resp), response_length) +
 +                           sizeof(resp.response_length)))
 +              return -ENOSPC;
 +
 +      err = create_qp(file, ucore, uhw, &cmd,
 +                      min(ucore->inlen, sizeof(cmd)),
 +                      ib_uverbs_ex_create_qp_cb, NULL);
 +
 +      if (err)
 +              return err;
 +
 +      return 0;
 +}
 +
  ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
                          struct ib_device *ib_dev,
                          const char __user *buf, int in_len, int out_len)
@@@ -2345,7 -2221,7 +2345,7 @@@ ssize_t ib_uverbs_modify_qp(struct ib_u
        attr->alt_ah_attr.port_num          = cmd.alt_dest.port_num;
  
        if (qp->real_qp == qp) {
 -              ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
 +              ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
                if (ret)
                        goto release_qp;
                ret = qp->device->modify_qp(qp, attr,
@@@ -2427,6 -2303,12 +2427,12 @@@ ssize_t ib_uverbs_destroy_qp(struct ib_
        return in_len;
  }
  
+ static void *alloc_wr(size_t wr_size, __u32 num_sge)
+ {
+       return kmalloc(ALIGN(wr_size, sizeof (struct ib_sge)) +
+                        num_sge * sizeof (struct ib_sge), GFP_KERNEL);
+ };
  ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                            struct ib_device *ib_dev,
                            const char __user *buf, int in_len,
                        goto out_put;
                }
  
-               next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
-                              user_wr->num_sge * sizeof (struct ib_sge),
-                              GFP_KERNEL);
-               if (!next) {
-                       ret = -ENOMEM;
+               if (is_ud) {
+                       struct ib_ud_wr *ud;
+                       if (user_wr->opcode != IB_WR_SEND &&
+                           user_wr->opcode != IB_WR_SEND_WITH_IMM) {
+                               ret = -EINVAL;
+                               goto out_put;
+                       }
+                       ud = alloc_wr(sizeof(*ud), user_wr->num_sge);
+                       if (!ud) {
+                               ret = -ENOMEM;
+                               goto out_put;
+                       }
+                       ud->ah = idr_read_ah(user_wr->wr.ud.ah, file->ucontext);
+                       if (!ud->ah) {
+                               kfree(ud);
+                               ret = -EINVAL;
+                               goto out_put;
+                       }
+                       ud->remote_qpn = user_wr->wr.ud.remote_qpn;
+                       ud->remote_qkey = user_wr->wr.ud.remote_qkey;
+                       next = &ud->wr;
+               } else if (user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+                          user_wr->opcode == IB_WR_RDMA_WRITE ||
+                          user_wr->opcode == IB_WR_RDMA_READ) {
+                       struct ib_rdma_wr *rdma;
+                       rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge);
+                       if (!rdma) {
+                               ret = -ENOMEM;
+                               goto out_put;
+                       }
+                       rdma->remote_addr = user_wr->wr.rdma.remote_addr;
+                       rdma->rkey = user_wr->wr.rdma.rkey;
+                       next = &rdma->wr;
+               } else if (user_wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+                          user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
+                       struct ib_atomic_wr *atomic;
+                       atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge);
+                       if (!atomic) {
+                               ret = -ENOMEM;
+                               goto out_put;
+                       }
+                       atomic->remote_addr = user_wr->wr.atomic.remote_addr;
+                       atomic->compare_add = user_wr->wr.atomic.compare_add;
+                       atomic->swap = user_wr->wr.atomic.swap;
+                       atomic->rkey = user_wr->wr.atomic.rkey;
+                       next = &atomic->wr;
+               } else if (user_wr->opcode == IB_WR_SEND ||
+                          user_wr->opcode == IB_WR_SEND_WITH_IMM ||
+                          user_wr->opcode == IB_WR_SEND_WITH_INV) {
+                       next = alloc_wr(sizeof(*next), user_wr->num_sge);
+                       if (!next) {
+                               ret = -ENOMEM;
+                               goto out_put;
+                       }
+               } else {
+                       ret = -EINVAL;
                        goto out_put;
                }
  
+               if (user_wr->opcode == IB_WR_SEND_WITH_IMM ||
+                   user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+                       next->ex.imm_data =
+                                       (__be32 __force) user_wr->ex.imm_data;
+               } else if (user_wr->opcode == IB_WR_SEND_WITH_INV) {
+                       next->ex.invalidate_rkey = user_wr->ex.invalidate_rkey;
+               }
                if (!last)
                        wr = next;
                else
                next->opcode     = user_wr->opcode;
                next->send_flags = user_wr->send_flags;
  
-               if (is_ud) {
-                       if (next->opcode != IB_WR_SEND &&
-                           next->opcode != IB_WR_SEND_WITH_IMM) {
-                               ret = -EINVAL;
-                               goto out_put;
-                       }
-                       next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
-                                                    file->ucontext);
-                       if (!next->wr.ud.ah) {
-                               ret = -EINVAL;
-                               goto out_put;
-                       }
-                       next->wr.ud.remote_qpn  = user_wr->wr.ud.remote_qpn;
-                       next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
-                       if (next->opcode == IB_WR_SEND_WITH_IMM)
-                               next->ex.imm_data =
-                                       (__be32 __force) user_wr->ex.imm_data;
-               } else {
-                       switch (next->opcode) {
-                       case IB_WR_RDMA_WRITE_WITH_IMM:
-                               next->ex.imm_data =
-                                       (__be32 __force) user_wr->ex.imm_data;
-                       case IB_WR_RDMA_WRITE:
-                       case IB_WR_RDMA_READ:
-                               next->wr.rdma.remote_addr =
-                                       user_wr->wr.rdma.remote_addr;
-                               next->wr.rdma.rkey        =
-                                       user_wr->wr.rdma.rkey;
-                               break;
-                       case IB_WR_SEND_WITH_IMM:
-                               next->ex.imm_data =
-                                       (__be32 __force) user_wr->ex.imm_data;
-                               break;
-                       case IB_WR_SEND_WITH_INV:
-                               next->ex.invalidate_rkey =
-                                       user_wr->ex.invalidate_rkey;
-                               break;
-                       case IB_WR_ATOMIC_CMP_AND_SWP:
-                       case IB_WR_ATOMIC_FETCH_AND_ADD:
-                               next->wr.atomic.remote_addr =
-                                       user_wr->wr.atomic.remote_addr;
-                               next->wr.atomic.compare_add =
-                                       user_wr->wr.atomic.compare_add;
-                               next->wr.atomic.swap = user_wr->wr.atomic.swap;
-                               next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
-                       case IB_WR_SEND:
-                               break;
-                       default:
-                               ret = -EINVAL;
-                               goto out_put;
-                       }
-               }
                if (next->num_sge) {
                        next->sg_list = (void *) next +
                                ALIGN(sizeof *next, sizeof (struct ib_sge));
@@@ -2582,8 -2479,8 +2603,8 @@@ out_put
        put_qp_read(qp);
  
        while (wr) {
-               if (is_ud && wr->wr.ud.ah)
-                       put_ah_read(wr->wr.ud.ah);
+               if (is_ud && ud_wr(wr)->ah)
+                       put_ah_read(ud_wr(wr)->ah);
                next = wr->next;
                kfree(wr);
                wr = next;
@@@ -2822,6 -2719,7 +2843,6 @@@ ssize_t ib_uverbs_create_ah(struct ib_u
        attr.grh.sgid_index    = cmd.attr.grh.sgid_index;
        attr.grh.hop_limit     = cmd.attr.grh.hop_limit;
        attr.grh.traffic_class = cmd.attr.grh.traffic_class;
 -      attr.vlan_id           = 0;
        memset(&attr.dmac, 0, sizeof(attr.dmac));
        memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
  
@@@ -528,8 -528,8 +528,8 @@@ static int build_rdma_write(struct t4_s
        if (wr->num_sge > T4_MAX_SEND_SGE)
                return -EINVAL;
        wqe->write.r2 = 0;
-       wqe->write.stag_sink = cpu_to_be32(wr->wr.rdma.rkey);
-       wqe->write.to_sink = cpu_to_be64(wr->wr.rdma.remote_addr);
+       wqe->write.stag_sink = cpu_to_be32(rdma_wr(wr)->rkey);
+       wqe->write.to_sink = cpu_to_be64(rdma_wr(wr)->remote_addr);
        if (wr->num_sge) {
                if (wr->send_flags & IB_SEND_INLINE) {
                        ret = build_immd(sq, wqe->write.u.immd_src, wr,
@@@ -566,10 -566,10 +566,10 @@@ static int build_rdma_read(union t4_wr 
        if (wr->num_sge > 1)
                return -EINVAL;
        if (wr->num_sge) {
-               wqe->read.stag_src = cpu_to_be32(wr->wr.rdma.rkey);
-               wqe->read.to_src_hi = cpu_to_be32((u32)(wr->wr.rdma.remote_addr
+               wqe->read.stag_src = cpu_to_be32(rdma_wr(wr)->rkey);
+               wqe->read.to_src_hi = cpu_to_be32((u32)(rdma_wr(wr)->remote_addr
                                                        >> 32));
-               wqe->read.to_src_lo = cpu_to_be32((u32)wr->wr.rdma.remote_addr);
+               wqe->read.to_src_lo = cpu_to_be32((u32)rdma_wr(wr)->remote_addr);
                wqe->read.stag_sink = cpu_to_be32(wr->sg_list[0].lkey);
                wqe->read.plen = cpu_to_be32(wr->sg_list[0].length);
                wqe->read.to_sink_hi = cpu_to_be32((u32)(wr->sg_list[0].addr
@@@ -606,39 -606,36 +606,36 @@@ static int build_rdma_recv(struct c4iw_
  }
  
  static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
-                        struct ib_send_wr *wr, u8 *len16, u8 t5dev)
+                        struct ib_send_wr *send_wr, u8 *len16, u8 t5dev)
  {
+       struct ib_fast_reg_wr *wr = fast_reg_wr(send_wr);
        struct fw_ri_immd *imdp;
        __be64 *p;
        int i;
-       int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32);
+       int pbllen = roundup(wr->page_list_len * sizeof(u64), 32);
        int rem;
  
-       if (wr->wr.fast_reg.page_list_len >
-           t4_max_fr_depth(use_dsgl))
+       if (wr->page_list_len > t4_max_fr_depth(use_dsgl))
                return -EINVAL;
  
        wqe->fr.qpbinde_to_dcacpu = 0;
-       wqe->fr.pgsz_shift = wr->wr.fast_reg.page_shift - 12;
+       wqe->fr.pgsz_shift = wr->page_shift - 12;
        wqe->fr.addr_type = FW_RI_VA_BASED_TO;
-       wqe->fr.mem_perms = c4iw_ib_to_tpt_access(wr->wr.fast_reg.access_flags);
+       wqe->fr.mem_perms = c4iw_ib_to_tpt_access(wr->access_flags);
        wqe->fr.len_hi = 0;
-       wqe->fr.len_lo = cpu_to_be32(wr->wr.fast_reg.length);
-       wqe->fr.stag = cpu_to_be32(wr->wr.fast_reg.rkey);
-       wqe->fr.va_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);
-       wqe->fr.va_lo_fbo = cpu_to_be32(wr->wr.fast_reg.iova_start &
-                                       0xffffffff);
+       wqe->fr.len_lo = cpu_to_be32(wr->length);
+       wqe->fr.stag = cpu_to_be32(wr->rkey);
+       wqe->fr.va_hi = cpu_to_be32(wr->iova_start >> 32);
+       wqe->fr.va_lo_fbo = cpu_to_be32(wr->iova_start & 0xffffffff);
  
        if (t5dev && use_dsgl && (pbllen > max_fr_immd)) {
                struct c4iw_fr_page_list *c4pl =
-                       to_c4iw_fr_page_list(wr->wr.fast_reg.page_list);
+                       to_c4iw_fr_page_list(wr->page_list);
                struct fw_ri_dsgl *sglp;
  
-               for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
-                       wr->wr.fast_reg.page_list->page_list[i] = (__force u64)
-                               cpu_to_be64((u64)
-                               wr->wr.fast_reg.page_list->page_list[i]);
+               for (i = 0; i < wr->page_list_len; i++) {
+                       wr->page_list->page_list[i] = (__force u64)
+                               cpu_to_be64((u64)wr->page_list->page_list[i]);
                }
  
                sglp = (struct fw_ri_dsgl *)(&wqe->fr + 1);
                imdp->immdlen = cpu_to_be32(pbllen);
                p = (__be64 *)(imdp + 1);
                rem = pbllen;
-               for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
-                       *p = cpu_to_be64(
-                               (u64)wr->wr.fast_reg.page_list->page_list[i]);
+               for (i = 0; i < wr->page_list_len; i++) {
+                       *p = cpu_to_be64((u64)wr->page_list->page_list[i]);
                        rem -= sizeof(*p);
                        if (++p == (__be64 *)&sq->queue[sq->size])
                                p = (__be64 *)sq->queue;
@@@ -712,7 -708,8 +708,7 @@@ static int ring_kernel_sq_db(struct c4i
        spin_lock_irqsave(&qhp->rhp->lock, flags);
        spin_lock(&qhp->lock);
        if (qhp->rhp->db_state == NORMAL)
 -              t4_ring_sq_db(&qhp->wq, inc,
 -                            is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
 +              t4_ring_sq_db(&qhp->wq, inc, NULL);
        else {
                add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
                qhp->wq.sq.wq_pidx_inc += inc;
@@@ -729,7 -726,8 +725,7 @@@ static int ring_kernel_rq_db(struct c4i
        spin_lock_irqsave(&qhp->rhp->lock, flags);
        spin_lock(&qhp->lock);
        if (qhp->rhp->db_state == NORMAL)
 -              t4_ring_rq_db(&qhp->wq, inc,
 -                            is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
 +              t4_ring_rq_db(&qhp->wq, inc, NULL);
        else {
                add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
                qhp->wq.rq.wq_pidx_inc += inc;
@@@ -815,7 -813,7 +811,7 @@@ int c4iw_post_send(struct ib_qp *ibqp, 
                        fw_opcode = FW_RI_FR_NSMR_WR;
                        swsqe->opcode = FW_RI_FAST_REGISTER;
                        err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16,
 -                                          is_t5(
 +                                          !is_t4(
                                            qhp->rhp->rdev.lldi.adapter_type) ?
                                            1 : 0);
                        break;
                idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
        }
        if (!qhp->rhp->rdev.status_page->db_off) {
 -              t4_ring_sq_db(&qhp->wq, idx,
 -                            is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
 +              t4_ring_sq_db(&qhp->wq, idx, wqe);
                spin_unlock_irqrestore(&qhp->lock, flag);
        } else {
                spin_unlock_irqrestore(&qhp->lock, flag);
@@@ -931,7 -930,8 +927,7 @@@ int c4iw_post_receive(struct ib_qp *ibq
                num_wrs--;
        }
        if (!qhp->rhp->rdev.status_page->db_off) {
 -              t4_ring_rq_db(&qhp->wq, idx,
 -                            is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
 +              t4_ring_rq_db(&qhp->wq, idx, wqe);
                spin_unlock_irqrestore(&qhp->lock, flag);
        } else {
                spin_unlock_irqrestore(&qhp->lock, flag);
@@@ -1871,7 -1871,7 +1867,7 @@@ int c4iw_ib_modify_qp(struct ib_qp *ibq
        attrs.rq_db_inc = attr->rq_psn;
        mask |= (attr_mask & IB_QP_SQ_PSN) ? C4IW_QP_ATTR_SQ_DB : 0;
        mask |= (attr_mask & IB_QP_RQ_PSN) ? C4IW_QP_ATTR_RQ_DB : 0;
 -      if (is_t5(to_c4iw_qp(ibqp)->rhp->rdev.lldi.adapter_type) &&
 +      if (!is_t4(to_c4iw_qp(ibqp)->rhp->rdev.lldi.adapter_type) &&
            (mask & (C4IW_QP_ATTR_SQ_DB|C4IW_QP_ATTR_RQ_DB)))
                return -EINVAL;
  
@@@ -457,7 -457,8 +457,8 @@@ int mlx4_ib_send_to_slave(struct mlx4_i
                          struct ib_grh *grh, struct ib_mad *mad)
  {
        struct ib_sge list;
-       struct ib_send_wr wr, *bad_wr;
+       struct ib_ud_wr wr;
+       struct ib_send_wr *bad_wr;
        struct mlx4_ib_demux_pv_ctx *tun_ctx;
        struct mlx4_ib_demux_pv_qp *tun_qp;
        struct mlx4_rcv_tunnel_mad *tun_mad;
        list.length = sizeof (struct mlx4_rcv_tunnel_mad);
        list.lkey = tun_ctx->pd->local_dma_lkey;
  
-       wr.wr.ud.ah = ah;
-       wr.wr.ud.port_num = port;
-       wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
-       wr.wr.ud.remote_qpn = dqpn;
-       wr.next = NULL;
-       wr.wr_id = ((u64) tun_tx_ix) | MLX4_TUN_SET_WRID_QPN(dest_qpt);
-       wr.sg_list = &list;
-       wr.num_sge = 1;
-       wr.opcode = IB_WR_SEND;
-       wr.send_flags = IB_SEND_SIGNALED;
-       ret = ib_post_send(src_qp, &wr, &bad_wr);
+       wr.ah = ah;
+       wr.port_num = port;
+       wr.remote_qkey = IB_QP_SET_QKEY;
+       wr.remote_qpn = dqpn;
+       wr.wr.next = NULL;
+       wr.wr.wr_id = ((u64) tun_tx_ix) | MLX4_TUN_SET_WRID_QPN(dest_qpt);
+       wr.wr.sg_list = &list;
+       wr.wr.num_sge = 1;
+       wr.wr.opcode = IB_WR_SEND;
+       wr.wr.send_flags = IB_SEND_SIGNALED;
+       ret = ib_post_send(src_qp, &wr.wr, &bad_wr);
  out:
        if (ret)
                ib_destroy_ah(ah);
@@@ -824,29 -825,18 +825,29 @@@ static int iboe_process_mad(struct ib_d
  {
        struct mlx4_counter counter_stats;
        struct mlx4_ib_dev *dev = to_mdev(ibdev);
 -      int err;
 +      struct counter_index *tmp_counter;
 +      int err = IB_MAD_RESULT_FAILURE, stats_avail = 0;
  
        if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
                return -EINVAL;
  
        memset(&counter_stats, 0, sizeof(counter_stats));
 -      err = mlx4_get_counter_stats(dev->dev,
 -                                   dev->counters[port_num - 1].index,
 -                                   &counter_stats, 0);
 -      if (err)
 -              err = IB_MAD_RESULT_FAILURE;
 -      else {
 +      mutex_lock(&dev->counters_table[port_num - 1].mutex);
 +      list_for_each_entry(tmp_counter,
 +                          &dev->counters_table[port_num - 1].counters_list,
 +                          list) {
 +              err = mlx4_get_counter_stats(dev->dev,
 +                                           tmp_counter->index,
 +                                           &counter_stats, 0);
 +              if (err) {
 +                      err = IB_MAD_RESULT_FAILURE;
 +                      stats_avail = 0;
 +                      break;
 +              }
 +              stats_avail = 1;
 +      }
 +      mutex_unlock(&dev->counters_table[port_num - 1].mutex);
 +      if (stats_avail) {
                memset(out_mad->data, 0, sizeof out_mad->data);
                switch (counter_stats.counter_mode & 0xf) {
                case 0:
@@@ -1183,10 -1173,11 +1184,11 @@@ static int is_proxy_qp0(struct mlx4_ib_
  int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
                         enum ib_qp_type dest_qpt, u16 pkey_index,
                         u32 remote_qpn, u32 qkey, struct ib_ah_attr *attr,
 -                       u8 *s_mac, struct ib_mad *mad)
 +                       u8 *s_mac, u16 vlan_id, struct ib_mad *mad)
  {
        struct ib_sge list;
-       struct ib_send_wr wr, *bad_wr;
+       struct ib_ud_wr wr;
+       struct ib_send_wr *bad_wr;
        struct mlx4_ib_demux_pv_ctx *sqp_ctx;
        struct mlx4_ib_demux_pv_qp *sqp;
        struct mlx4_mad_snd_buf *sqp_mad;
        list.length = sizeof (struct mlx4_mad_snd_buf);
        list.lkey = sqp_ctx->pd->local_dma_lkey;
  
-       wr.wr.ud.ah = ah;
-       wr.wr.ud.port_num = port;
-       wr.wr.ud.pkey_index = wire_pkey_ix;
-       wr.wr.ud.remote_qkey = qkey;
-       wr.wr.ud.remote_qpn = remote_qpn;
-       wr.next = NULL;
-       wr.wr_id = ((u64) wire_tx_ix) | MLX4_TUN_SET_WRID_QPN(src_qpnum);
-       wr.sg_list = &list;
-       wr.num_sge = 1;
-       wr.opcode = IB_WR_SEND;
-       wr.send_flags = IB_SEND_SIGNALED;
+       wr.ah = ah;
+       wr.port_num = port;
+       wr.pkey_index = wire_pkey_ix;
+       wr.remote_qkey = qkey;
+       wr.remote_qpn = remote_qpn;
+       wr.wr.next = NULL;
+       wr.wr.wr_id = ((u64) wire_tx_ix) | MLX4_TUN_SET_WRID_QPN(src_qpnum);
+       wr.wr.sg_list = &list;
+       wr.wr.num_sge = 1;
+       wr.wr.opcode = IB_WR_SEND;
+       wr.wr.send_flags = IB_SEND_SIGNALED;
        if (s_mac)
                memcpy(to_mah(ah)->av.eth.s_mac, s_mac, 6);
 +      if (vlan_id < 0x1000)
 +              vlan_id |= (attr->sl & 7) << 13;
 +      to_mah(ah)->av.eth.vlan = cpu_to_be16(vlan_id);
  
  
-       ret = ib_post_send(send_qp, &wr, &bad_wr);
+       ret = ib_post_send(send_qp, &wr.wr, &bad_wr);
  out:
        if (ret)
                ib_destroy_ah(ah);
@@@ -1309,7 -1297,6 +1311,7 @@@ static void mlx4_ib_multiplex_mad(struc
        u8 *slave_id;
        int slave;
        int port;
 +      u16 vlan_id;
  
        /* Get slave that sent this packet */
        if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
                fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);
  
        memcpy(ah_attr.dmac, tunnel->hdr.mac, 6);
 -      ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan);
 +      vlan_id = be16_to_cpu(tunnel->hdr.vlan);
        /* if slave have default vlan use it */
        mlx4_get_slave_default_vlan(dev->dev, ctx->port, slave,
 -                                  &ah_attr.vlan_id, &ah_attr.sl);
 +                                  &vlan_id, &ah_attr.sl);
  
        mlx4_ib_send_to_wire(dev, slave, ctx->port,
                             is_proxy_qp0(dev, wc->src_qp, slave) ?
                             be16_to_cpu(tunnel->hdr.pkey_index),
                             be32_to_cpu(tunnel->hdr.remote_qpn),
                             be32_to_cpu(tunnel->hdr.qkey),
 -                           &ah_attr, wc->smac, &tunnel->mad);
 +                           &ah_attr, wc->smac, vlan_id, &tunnel->mad);
  }
  
  static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
@@@ -617,18 -617,6 +617,18 @@@ static int qp0_enabled_vf(struct mlx4_d
        return 0;
  }
  
 +static void mlx4_ib_free_qp_counter(struct mlx4_ib_dev *dev,
 +                                  struct mlx4_ib_qp *qp)
 +{
 +      mutex_lock(&dev->counters_table[qp->port - 1].mutex);
 +      mlx4_counter_free(dev->dev, qp->counter_index->index);
 +      list_del(&qp->counter_index->list);
 +      mutex_unlock(&dev->counters_table[qp->port - 1].mutex);
 +
 +      kfree(qp->counter_index);
 +      qp->counter_index = NULL;
 +}
 +
  static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
                            struct ib_qp_init_attr *init_attr,
                            struct ib_udata *udata, int sqpn, struct mlx4_ib_qp **caller_qp,
        } else {
                qp->sq_no_prefetch = 0;
  
 -              if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
 -                      qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
 -
                if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
                        qp->flags |= MLX4_IB_QP_LSO;
  
                        goto err_proxy;
        }
  
 +      if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
 +              qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
 +
        err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp, gfp);
        if (err)
                goto err_qpn;
@@@ -1098,7 -1086,6 +1098,7 @@@ struct ib_qp *mlx4_ib_create_qp(struct 
  {
        struct mlx4_ib_qp *qp = NULL;
        int err;
 +      int sup_u_create_flags = MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
        u16 xrcdn = 0;
        gfp_t gfp;
  
        }
  
        if (init_attr->create_flags &&
 -          (udata ||
 -           ((init_attr->create_flags & ~(MLX4_IB_SRIOV_SQP | MLX4_IB_QP_CREATE_USE_GFP_NOIO)) &&
 +          ((udata && init_attr->create_flags & ~(sup_u_create_flags)) ||
 +           ((init_attr->create_flags & ~(MLX4_IB_SRIOV_SQP |
 +                                         MLX4_IB_QP_CREATE_USE_GFP_NOIO |
 +                                         MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK)) &&
              init_attr->qp_type != IB_QPT_UD) ||
             ((init_attr->create_flags & MLX4_IB_SRIOV_SQP) &&
              init_attr->qp_type > IB_QPT_GSI)))
@@@ -1204,9 -1189,6 +1204,9 @@@ int mlx4_ib_destroy_qp(struct ib_qp *qp
                mutex_unlock(&dev->qp1_proxy_lock[mqp->port - 1]);
        }
  
 +      if (mqp->counter_index)
 +              mlx4_ib_free_qp_counter(dev, mqp);
 +
        pd = get_pd(mqp);
        destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
  
@@@ -1409,12 -1391,11 +1409,12 @@@ static int _mlx4_set_path(struct mlx4_i
  static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_qp_attr *qp,
                         enum ib_qp_attr_mask qp_attr_mask,
                         struct mlx4_ib_qp *mqp,
 -                       struct mlx4_qp_path *path, u8 port)
 +                       struct mlx4_qp_path *path, u8 port,
 +                       u16 vlan_id, u8 *smac)
  {
        return _mlx4_set_path(dev, &qp->ah_attr,
 -                            mlx4_mac_to_u64((u8 *)qp->smac),
 -                            (qp_attr_mask & IB_QP_VID) ? qp->vlan_id : 0xffff,
 +                            mlx4_mac_to_u64(smac),
 +                            vlan_id,
                              path, &mqp->pri, port);
  }
  
@@@ -1425,8 -1406,9 +1425,8 @@@ static int mlx4_set_alt_path(struct mlx
                             struct mlx4_qp_path *path, u8 port)
  {
        return _mlx4_set_path(dev, &qp->alt_ah_attr,
 -                            mlx4_mac_to_u64((u8 *)qp->alt_smac),
 -                            (qp_attr_mask & IB_QP_ALT_VID) ?
 -                            qp->alt_vlan_id : 0xffff,
 +                            0,
 +                            0xffff,
                              path, &mqp->alt, port);
  }
  
@@@ -1442,8 -1424,7 +1442,8 @@@ static void update_mcg_macs(struct mlx4
        }
  }
  
 -static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac,
 +static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev,
 +                                  struct mlx4_ib_qp *qp,
                                    struct mlx4_qp_context *context)
  {
        u64 u64_mac;
        return 0;
  }
  
 +static int create_qp_lb_counter(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
 +{
 +      struct counter_index *new_counter_index;
 +      int err;
 +      u32 tmp_idx;
 +
 +      if (rdma_port_get_link_layer(&dev->ib_dev, qp->port) !=
 +          IB_LINK_LAYER_ETHERNET ||
 +          !(qp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK) ||
 +          !(dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK))
 +              return 0;
 +
 +      err = mlx4_counter_alloc(dev->dev, &tmp_idx);
 +      if (err)
 +              return err;
 +
 +      new_counter_index = kmalloc(sizeof(*new_counter_index), GFP_KERNEL);
 +      if (!new_counter_index) {
 +              mlx4_counter_free(dev->dev, tmp_idx);
 +              return -ENOMEM;
 +      }
 +
 +      new_counter_index->index = tmp_idx;
 +      new_counter_index->allocated = 1;
 +      qp->counter_index = new_counter_index;
 +
 +      mutex_lock(&dev->counters_table[qp->port - 1].mutex);
 +      list_add_tail(&new_counter_index->list,
 +                    &dev->counters_table[qp->port - 1].counters_list);
 +      mutex_unlock(&dev->counters_table[qp->port - 1].mutex);
 +
 +      return 0;
 +}
 +
  static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
                               const struct ib_qp_attr *attr, int attr_mask,
                               enum ib_qp_state cur_state, enum ib_qp_state new_state)
        int sqd_event;
        int steer_qp = 0;
        int err = -EINVAL;
 +      int counter_index;
  
        /* APM is not supported under RoCE */
        if (attr_mask & IB_QP_ALT_PATH &&
                context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
        context->sq_size_stride |= qp->sq.wqe_shift - 4;
  
 +      if (new_state == IB_QPS_RESET && qp->counter_index)
 +              mlx4_ib_free_qp_counter(dev, qp);
 +
        if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
                context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
                context->xrcd = cpu_to_be32((u32) qp->xrcdn);
        }
  
        if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
 -              if (dev->counters[qp->port - 1].index != -1) {
 -                      context->pri_path.counter_index =
 -                                      dev->counters[qp->port - 1].index;
 +              err = create_qp_lb_counter(dev, qp);
 +              if (err)
 +                      goto out;
 +
 +              counter_index =
 +                      dev->counters_table[qp->port - 1].default_counter;
 +              if (qp->counter_index)
 +                      counter_index = qp->counter_index->index;
 +
 +              if (counter_index != -1) {
 +                      context->pri_path.counter_index = counter_index;
                        optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX;
 +                      if (qp->counter_index) {
 +                              context->pri_path.fl |=
 +                                      MLX4_FL_ETH_SRC_CHECK_MC_LB;
 +                              context->pri_path.vlan_control |=
 +                                      MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
 +                      }
                } else
                        context->pri_path.counter_index =
                                MLX4_SINK_COUNTER_INDEX(dev->dev);
        }
  
        if (attr_mask & IB_QP_AV) {
 +              u8 port_num = mlx4_is_bonded(to_mdev(ibqp->device)->dev) ? 1 :
 +                      attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
 +              union ib_gid gid;
 +              struct ib_gid_attr gid_attr;
 +              u16 vlan = 0xffff;
 +              u8 smac[ETH_ALEN];
 +              int status = 0;
 +
 +              if (rdma_cap_eth_ah(&dev->ib_dev, port_num) &&
 +                  attr->ah_attr.ah_flags & IB_AH_GRH) {
 +                      int index = attr->ah_attr.grh.sgid_index;
 +
 +                      status = ib_get_cached_gid(ibqp->device, port_num,
 +                                                 index, &gid, &gid_attr);
 +                      if (!status && !memcmp(&gid, &zgid, sizeof(gid)))
 +                              status = -ENOENT;
 +                      if (!status && gid_attr.ndev) {
 +                              vlan = rdma_vlan_dev_vlan_id(gid_attr.ndev);
 +                              memcpy(smac, gid_attr.ndev->dev_addr, ETH_ALEN);
 +                              dev_put(gid_attr.ndev);
 +                      }
 +              }
 +              if (status)
 +                      goto out;
 +
                if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
 -                                attr_mask & IB_QP_PORT ?
 -                                attr->port_num : qp->port))
 +                                port_num, vlan, smac))
                        goto out;
  
                optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH |
                        if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_UD ||
                            qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI ||
                            qp->mlx4_ib_qp_type == MLX4_IB_QPT_TUN_GSI) {
 -                              err = handle_eth_ud_smac_index(dev, qp, (u8 *)attr->smac, context);
 +                              err = handle_eth_ud_smac_index(dev, qp, context);
                                if (err) {
                                        err = -EINVAL;
                                        goto out;
                }
        }
  out:
 +      if (err && qp->counter_index)
 +              mlx4_ib_free_qp_counter(dev, qp);
        if (err && steer_qp)
                mlx4_ib_steer_qp_reg(dev, qp, 0);
        kfree(context);
@@@ -2133,14 -2036,14 +2133,14 @@@ static int vf_get_qp0_qkey(struct mlx4_
  }
  
  static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
-                                 struct ib_send_wr *wr,
+                                 struct ib_ud_wr *wr,
                                  void *wqe, unsigned *mlx_seg_len)
  {
        struct mlx4_ib_dev *mdev = to_mdev(sqp->qp.ibqp.device);
        struct ib_device *ib_dev = &mdev->ib_dev;
        struct mlx4_wqe_mlx_seg *mlx = wqe;
        struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
-       struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+       struct mlx4_ib_ah *ah = to_mah(wr->ah);
        u16 pkey;
        u32 qkey;
        int send_size;
        int spc;
        int i;
  
-       if (wr->opcode != IB_WR_SEND)
+       if (wr->wr.opcode != IB_WR_SEND)
                return -EINVAL;
  
        send_size = 0;
  
-       for (i = 0; i < wr->num_sge; ++i)
-               send_size += wr->sg_list[i].length;
+       for (i = 0; i < wr->wr.num_sge; ++i)
+               send_size += wr->wr.sg_list[i].length;
  
        /* for proxy-qp0 sends, need to add in size of tunnel header */
        /* for tunnel-qp0 sends, tunnel header is already in s/g list */
        mlx->rlid = sqp->ud_header.lrh.destination_lid;
  
        sqp->ud_header.lrh.virtual_lane    = 0;
-       sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+       sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
        ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
        sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
        if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_TUN_SMI_OWNER)
-               sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+               sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
        else
                sqp->ud_header.bth.destination_qpn =
                        cpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]);
@@@ -2255,14 -2158,14 +2255,14 @@@ static void mlx4_u64_to_smac(u8 *dst_ma
        }
  }
  
- static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_ud_wr *wr,
                            void *wqe, unsigned *mlx_seg_len)
  {
        struct ib_device *ib_dev = sqp->qp.ibqp.device;
        struct mlx4_wqe_mlx_seg *mlx = wqe;
        struct mlx4_wqe_ctrl_seg *ctrl = wqe;
        struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
-       struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+       struct mlx4_ib_ah *ah = to_mah(wr->ah);
        union ib_gid sgid;
        u16 pkey;
        int send_size;
        bool is_grh;
  
        send_size = 0;
-       for (i = 0; i < wr->num_sge; ++i)
-               send_size += wr->sg_list[i].length;
+       for (i = 0; i < wr->wr.num_sge; ++i)
+               send_size += wr->wr.sg_list[i].length;
  
        is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET;
        is_grh = mlx4_ib_ah_grh_present(ah);
                } else  {
                        err = ib_get_cached_gid(ib_dev,
                                                be32_to_cpu(ah->av.ib.port_pd) >> 24,
 -                                              ah->av.ib.gid_index, &sgid);
 +                                              ah->av.ib.gid_index, &sgid,
 +                                              NULL);
 +                      if (!err && !memcmp(&sgid, &zgid, sizeof(sgid)))
 +                              err = -ENOENT;
                        if (err)
                                return err;
                }
                        ib_get_cached_gid(ib_dev,
                                          be32_to_cpu(ah->av.ib.port_pd) >> 24,
                                          ah->av.ib.gid_index,
 -                                        &sqp->ud_header.grh.source_gid);
 +                                        &sqp->ud_header.grh.source_gid, NULL);
                }
                memcpy(sqp->ud_header.grh.destination_gid.raw,
                       ah->av.ib.dgid, 16);
                mlx->rlid = sqp->ud_header.lrh.destination_lid;
        }
  
-       switch (wr->opcode) {
+       switch (wr->wr.opcode) {
        case IB_WR_SEND:
                sqp->ud_header.bth.opcode        = IB_OPCODE_UD_SEND_ONLY;
                sqp->ud_header.immediate_present = 0;
        case IB_WR_SEND_WITH_IMM:
                sqp->ud_header.bth.opcode        = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
                sqp->ud_header.immediate_present = 1;
-               sqp->ud_header.immediate_data    = wr->ex.imm_data;
+               sqp->ud_header.immediate_data    = wr->wr.ex.imm_data;
                break;
        default:
                return -EINVAL;
                if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
                        sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
        }
-       sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+       sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
        if (!sqp->qp.ibqp.qp_num)
                ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey);
        else
-               ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->wr.ud.pkey_index, &pkey);
+               ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->pkey_index, &pkey);
        sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
-       sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+       sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
        sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
-       sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ?
-                                              sqp->qkey : wr->wr.ud.remote_qkey);
+       sqp->ud_header.deth.qkey = cpu_to_be32(wr->remote_qkey & 0x80000000 ?
+                                              sqp->qkey : wr->remote_qkey);
        sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.ibqp.qp_num);
  
        header_size = ib_ud_header_pack(&sqp->ud_header, sqp->header_buf);
@@@ -2505,43 -2405,45 +2505,45 @@@ static __be32 convert_access(int acc
                cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
  }
  
- static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
+ static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg,
+               struct ib_fast_reg_wr *wr)
  {
-       struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
+       struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->page_list);
        int i;
  
-       for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i)
+       for (i = 0; i < wr->page_list_len; ++i)
                mfrpl->mapped_page_list[i] =
-                       cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] |
+                       cpu_to_be64(wr->page_list->page_list[i] |
                                    MLX4_MTT_FLAG_PRESENT);
  
-       fseg->flags             = convert_access(wr->wr.fast_reg.access_flags);
-       fseg->mem_key           = cpu_to_be32(wr->wr.fast_reg.rkey);
+       fseg->flags             = convert_access(wr->access_flags);
+       fseg->mem_key           = cpu_to_be32(wr->rkey);
        fseg->buf_list          = cpu_to_be64(mfrpl->map);
-       fseg->start_addr        = cpu_to_be64(wr->wr.fast_reg.iova_start);
-       fseg->reg_len           = cpu_to_be64(wr->wr.fast_reg.length);
+       fseg->start_addr        = cpu_to_be64(wr->iova_start);
+       fseg->reg_len           = cpu_to_be64(wr->length);
        fseg->offset            = 0; /* XXX -- is this just for ZBVA? */
-       fseg->page_size         = cpu_to_be32(wr->wr.fast_reg.page_shift);
+       fseg->page_size         = cpu_to_be32(wr->page_shift);
        fseg->reserved[0]       = 0;
        fseg->reserved[1]       = 0;
  }
  
- static void set_bind_seg(struct mlx4_wqe_bind_seg *bseg, struct ib_send_wr *wr)
+ static void set_bind_seg(struct mlx4_wqe_bind_seg *bseg,
+               struct ib_bind_mw_wr *wr)
  {
        bseg->flags1 =
-               convert_access(wr->wr.bind_mw.bind_info.mw_access_flags) &
+               convert_access(wr->bind_info.mw_access_flags) &
                cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ  |
                            MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE |
                            MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC);
        bseg->flags2 = 0;
-       if (wr->wr.bind_mw.mw->type == IB_MW_TYPE_2)
+       if (wr->mw->type == IB_MW_TYPE_2)
                bseg->flags2 |= cpu_to_be32(MLX4_WQE_BIND_TYPE_2);
-       if (wr->wr.bind_mw.bind_info.mw_access_flags & IB_ZERO_BASED)
+       if (wr->bind_info.mw_access_flags & IB_ZERO_BASED)
                bseg->flags2 |= cpu_to_be32(MLX4_WQE_BIND_ZERO_BASED);
-       bseg->new_rkey = cpu_to_be32(wr->wr.bind_mw.rkey);
-       bseg->lkey = cpu_to_be32(wr->wr.bind_mw.bind_info.mr->lkey);
-       bseg->addr = cpu_to_be64(wr->wr.bind_mw.bind_info.addr);
-       bseg->length = cpu_to_be64(wr->wr.bind_mw.bind_info.length);
+       bseg->new_rkey = cpu_to_be32(wr->rkey);
+       bseg->lkey = cpu_to_be32(wr->bind_info.mr->lkey);
+       bseg->addr = cpu_to_be64(wr->bind_info.addr);
+       bseg->length = cpu_to_be64(wr->bind_info.length);
  }
  
  static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
@@@ -2558,46 -2460,47 +2560,47 @@@ static __always_inline void set_raddr_s
        rseg->reserved = 0;
  }
  
- static void set_atomic_seg(struct mlx4_wqe_atomic_seg *aseg, struct ib_send_wr *wr)
+ static void set_atomic_seg(struct mlx4_wqe_atomic_seg *aseg,
+               struct ib_atomic_wr *wr)
  {
-       if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
-               aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add);
-       } else if (wr->opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-               aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add_mask);
+       if (wr->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
+               aseg->swap_add = cpu_to_be64(wr->swap);
+               aseg->compare  = cpu_to_be64(wr->compare_add);
+       } else if (wr->wr.opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
+               aseg->swap_add = cpu_to_be64(wr->compare_add);
+               aseg->compare  = cpu_to_be64(wr->compare_add_mask);
        } else {
-               aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
+               aseg->swap_add = cpu_to_be64(wr->compare_add);
                aseg->compare  = 0;
        }
  
  }
  
  static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
-                                 struct ib_send_wr *wr)
+                                 struct ib_atomic_wr *wr)
  {
-       aseg->swap_add          = cpu_to_be64(wr->wr.atomic.swap);
-       aseg->swap_add_mask     = cpu_to_be64(wr->wr.atomic.swap_mask);
-       aseg->compare           = cpu_to_be64(wr->wr.atomic.compare_add);
-       aseg->compare_mask      = cpu_to_be64(wr->wr.atomic.compare_add_mask);
+       aseg->swap_add          = cpu_to_be64(wr->swap);
+       aseg->swap_add_mask     = cpu_to_be64(wr->swap_mask);
+       aseg->compare           = cpu_to_be64(wr->compare_add);
+       aseg->compare_mask      = cpu_to_be64(wr->compare_add_mask);
  }
  
  static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
-                            struct ib_send_wr *wr)
+                            struct ib_ud_wr *wr)
  {
-       memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
-       dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
-       dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
-       dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
-       memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
+       memcpy(dseg->av, &to_mah(wr->ah)->av, sizeof (struct mlx4_av));
+       dseg->dqpn = cpu_to_be32(wr->remote_qpn);
+       dseg->qkey = cpu_to_be32(wr->remote_qkey);
+       dseg->vlan = to_mah(wr->ah)->av.eth.vlan;
+       memcpy(dseg->mac, to_mah(wr->ah)->av.eth.mac, 6);
  }
  
  static void set_tunnel_datagram_seg(struct mlx4_ib_dev *dev,
                                    struct mlx4_wqe_datagram_seg *dseg,
-                                   struct ib_send_wr *wr,
+                                   struct ib_ud_wr *wr,
                                    enum mlx4_ib_qp_type qpt)
  {
-       union mlx4_ext_av *av = &to_mah(wr->wr.ud.ah)->av;
+       union mlx4_ext_av *av = &to_mah(wr->ah)->av;
        struct mlx4_av sqp_av = {0};
        int port = *((u8 *) &av->ib.port_pd) & 0x3;
  
        dseg->qkey = cpu_to_be32(IB_QP_SET_QKEY);
  }
  
- static void build_tunnel_header(struct ib_send_wr *wr, void *wqe, unsigned *mlx_seg_len)
+ static void build_tunnel_header(struct ib_ud_wr *wr, void *wqe, unsigned *mlx_seg_len)
  {
        struct mlx4_wqe_inline_seg *inl = wqe;
        struct mlx4_ib_tunnel_header hdr;
-       struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+       struct mlx4_ib_ah *ah = to_mah(wr->ah);
        int spc;
        int i;
  
        memcpy(&hdr.av, &ah->av, sizeof hdr.av);
-       hdr.remote_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
-       hdr.pkey_index = cpu_to_be16(wr->wr.ud.pkey_index);
-       hdr.qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+       hdr.remote_qpn = cpu_to_be32(wr->remote_qpn);
+       hdr.pkey_index = cpu_to_be16(wr->pkey_index);
+       hdr.qkey = cpu_to_be32(wr->remote_qkey);
        memcpy(hdr.mac, ah->av.eth.mac, 6);
        hdr.vlan = ah->av.eth.vlan;
  
@@@ -2699,22 -2602,22 +2702,22 @@@ static void __set_data_seg(struct mlx4_
        dseg->addr       = cpu_to_be64(sg->addr);
  }
  
- static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
+ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_ud_wr *wr,
                         struct mlx4_ib_qp *qp, unsigned *lso_seg_len,
                         __be32 *lso_hdr_sz, __be32 *blh)
  {
-       unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
+       unsigned halign = ALIGN(sizeof *wqe + wr->hlen, 16);
  
        if (unlikely(halign > MLX4_IB_CACHE_LINE_SIZE))
                *blh = cpu_to_be32(1 << 6);
  
        if (unlikely(!(qp->flags & MLX4_IB_QP_LSO) &&
-                    wr->num_sge > qp->sq.max_gs - (halign >> 4)))
+                    wr->wr.num_sge > qp->sq.max_gs - (halign >> 4)))
                return -EINVAL;
  
-       memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
+       memcpy(wqe->header, wr->header, wr->hlen);
  
-       *lso_hdr_sz  = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
+       *lso_hdr_sz  = cpu_to_be32(wr->mss << 16 | wr->hlen);
        *lso_seg_len = halign;
        return 0;
  }
@@@ -2813,11 -2716,11 +2816,11 @@@ int mlx4_ib_post_send(struct ib_qp *ibq
                        case IB_WR_ATOMIC_CMP_AND_SWP:
                        case IB_WR_ATOMIC_FETCH_AND_ADD:
                        case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
-                               set_raddr_seg(wqe, wr->wr.atomic.remote_addr,
-                                             wr->wr.atomic.rkey);
+                               set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
+                                             atomic_wr(wr)->rkey);
                                wqe  += sizeof (struct mlx4_wqe_raddr_seg);
  
-                               set_atomic_seg(wqe, wr);
+                               set_atomic_seg(wqe, atomic_wr(wr));
                                wqe  += sizeof (struct mlx4_wqe_atomic_seg);
  
                                size += (sizeof (struct mlx4_wqe_raddr_seg) +
                                break;
  
                        case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
-                               set_raddr_seg(wqe, wr->wr.atomic.remote_addr,
-                                             wr->wr.atomic.rkey);
+                               set_raddr_seg(wqe, atomic_wr(wr)->remote_addr,
+                                             atomic_wr(wr)->rkey);
                                wqe  += sizeof (struct mlx4_wqe_raddr_seg);
  
-                               set_masked_atomic_seg(wqe, wr);
+                               set_masked_atomic_seg(wqe, atomic_wr(wr));
                                wqe  += sizeof (struct mlx4_wqe_masked_atomic_seg);
  
                                size += (sizeof (struct mlx4_wqe_raddr_seg) +
                        case IB_WR_RDMA_READ:
                        case IB_WR_RDMA_WRITE:
                        case IB_WR_RDMA_WRITE_WITH_IMM:
-                               set_raddr_seg(wqe, wr->wr.rdma.remote_addr,
-                                             wr->wr.rdma.rkey);
+                               set_raddr_seg(wqe, rdma_wr(wr)->remote_addr,
+                                             rdma_wr(wr)->rkey);
                                wqe  += sizeof (struct mlx4_wqe_raddr_seg);
                                size += sizeof (struct mlx4_wqe_raddr_seg) / 16;
                                break;
                        case IB_WR_FAST_REG_MR:
                                ctrl->srcrb_flags |=
                                        cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER);
-                               set_fmr_seg(wqe, wr);
+                               set_fmr_seg(wqe, fast_reg_wr(wr));
                                wqe  += sizeof (struct mlx4_wqe_fmr_seg);
                                size += sizeof (struct mlx4_wqe_fmr_seg) / 16;
                                break;
                        case IB_WR_BIND_MW:
                                ctrl->srcrb_flags |=
                                        cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER);
-                               set_bind_seg(wqe, wr);
+                               set_bind_seg(wqe, bind_mw_wr(wr));
                                wqe  += sizeof(struct mlx4_wqe_bind_seg);
                                size += sizeof(struct mlx4_wqe_bind_seg) / 16;
                                break;
                        break;
  
                case MLX4_IB_QPT_TUN_SMI_OWNER:
-                       err =  build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
+                       err =  build_sriov_qp0_header(to_msqp(qp), ud_wr(wr),
+                                       ctrl, &seglen);
                        if (unlikely(err)) {
                                *bad_wr = wr;
                                goto out;
                case MLX4_IB_QPT_TUN_SMI:
                case MLX4_IB_QPT_TUN_GSI:
                        /* this is a UD qp used in MAD responses to slaves. */
-                       set_datagram_seg(wqe, wr);
+                       set_datagram_seg(wqe, ud_wr(wr));
                        /* set the forced-loopback bit in the data seg av */
                        *(__be32 *) wqe |= cpu_to_be32(0x80000000);
                        wqe  += sizeof (struct mlx4_wqe_datagram_seg);
                        size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
                        break;
                case MLX4_IB_QPT_UD:
-                       set_datagram_seg(wqe, wr);
+                       set_datagram_seg(wqe, ud_wr(wr));
                        wqe  += sizeof (struct mlx4_wqe_datagram_seg);
                        size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
  
                        if (wr->opcode == IB_WR_LSO) {
-                               err = build_lso_seg(wqe, wr, qp, &seglen, &lso_hdr_sz, &blh);
+                               err = build_lso_seg(wqe, ud_wr(wr), qp, &seglen,
+                                               &lso_hdr_sz, &blh);
                                if (unlikely(err)) {
                                        *bad_wr = wr;
                                        goto out;
                        break;
  
                case MLX4_IB_QPT_PROXY_SMI_OWNER:
-                       err = build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
+                       err = build_sriov_qp0_header(to_msqp(qp), ud_wr(wr),
+                                       ctrl, &seglen);
                        if (unlikely(err)) {
                                *bad_wr = wr;
                                goto out;
                        add_zero_len_inline(wqe);
                        wqe += 16;
                        size++;
-                       build_tunnel_header(wr, wqe, &seglen);
+                       build_tunnel_header(ud_wr(wr), wqe, &seglen);
                        wqe  += seglen;
                        size += seglen / 16;
                        break;
                         * In this case we first add a UD segment targeting
                         * the tunnel qp, and then add a header with address
                         * information */
-                       set_tunnel_datagram_seg(to_mdev(ibqp->device), wqe, wr,
+                       set_tunnel_datagram_seg(to_mdev(ibqp->device), wqe,
+                                               ud_wr(wr),
                                                qp->mlx4_ib_qp_type);
                        wqe  += sizeof (struct mlx4_wqe_datagram_seg);
                        size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
-                       build_tunnel_header(wr, wqe, &seglen);
+                       build_tunnel_header(ud_wr(wr), wqe, &seglen);
                        wqe  += seglen;
                        size += seglen / 16;
                        break;
  
                case MLX4_IB_QPT_SMI:
                case MLX4_IB_QPT_GSI:
-                       err = build_mlx_header(to_msqp(qp), wr, ctrl, &seglen);
+                       err = build_mlx_header(to_msqp(qp), ud_wr(wr), ctrl,
+                                       &seglen);
                        if (unlikely(err)) {
                                *bad_wr = wr;
                                goto out;
@@@ -73,7 -73,7 +73,7 @@@ int ocrdma_query_gid(struct ib_device *
        if (index >= OCRDMA_MAX_SGID)
                return -EINVAL;
  
 -      ret = ib_get_cached_gid(ibdev, port, index, sgid);
 +      ret = ib_get_cached_gid(ibdev, port, index, sgid, NULL);
        if (ret == -EAGAIN) {
                memcpy(sgid, &zgid, sizeof(*sgid));
                return 0;
@@@ -1997,13 -1997,13 +1997,13 @@@ static void ocrdma_build_ud_hdr(struct 
  {
        struct ocrdma_ewqe_ud_hdr *ud_hdr =
                (struct ocrdma_ewqe_ud_hdr *)(hdr + 1);
-       struct ocrdma_ah *ah = get_ocrdma_ah(wr->wr.ud.ah);
+       struct ocrdma_ah *ah = get_ocrdma_ah(ud_wr(wr)->ah);
  
-       ud_hdr->rsvd_dest_qpn = wr->wr.ud.remote_qpn;
+       ud_hdr->rsvd_dest_qpn = ud_wr(wr)->remote_qpn;
        if (qp->qp_type == IB_QPT_GSI)
                ud_hdr->qkey = qp->qkey;
        else
-               ud_hdr->qkey = wr->wr.ud.remote_qkey;
+               ud_hdr->qkey = ud_wr(wr)->remote_qkey;
        ud_hdr->rsvd_ahid = ah->id;
        if (ah->av->valid & OCRDMA_AV_VLAN_VALID)
                hdr->cw |= (OCRDMA_FLAG_AH_VLAN_PR << OCRDMA_WQE_FLAGS_SHIFT);
@@@ -2106,9 -2106,9 +2106,9 @@@ static int ocrdma_build_write(struct oc
        status = ocrdma_build_inline_sges(qp, hdr, sge, wr, wqe_size);
        if (status)
                return status;
-       ext_rw->addr_lo = wr->wr.rdma.remote_addr;
-       ext_rw->addr_hi = upper_32_bits(wr->wr.rdma.remote_addr);
-       ext_rw->lrkey = wr->wr.rdma.rkey;
+       ext_rw->addr_lo = rdma_wr(wr)->remote_addr;
+       ext_rw->addr_hi = upper_32_bits(rdma_wr(wr)->remote_addr);
+       ext_rw->lrkey = rdma_wr(wr)->rkey;
        ext_rw->len = hdr->total_len;
        return 0;
  }
@@@ -2126,13 -2126,14 +2126,14 @@@ static void ocrdma_build_read(struct oc
        hdr->cw |= (OCRDMA_READ << OCRDMA_WQE_OPCODE_SHIFT);
        hdr->cw |= (OCRDMA_TYPE_LKEY << OCRDMA_WQE_TYPE_SHIFT);
  
-       ext_rw->addr_lo = wr->wr.rdma.remote_addr;
-       ext_rw->addr_hi = upper_32_bits(wr->wr.rdma.remote_addr);
-       ext_rw->lrkey = wr->wr.rdma.rkey;
+       ext_rw->addr_lo = rdma_wr(wr)->remote_addr;
+       ext_rw->addr_hi = upper_32_bits(rdma_wr(wr)->remote_addr);
+       ext_rw->lrkey = rdma_wr(wr)->rkey;
        ext_rw->len = hdr->total_len;
  }
  
- static void build_frmr_pbes(struct ib_send_wr *wr, struct ocrdma_pbl *pbl_tbl,
+ static void build_frmr_pbes(struct ib_fast_reg_wr *wr,
+                           struct ocrdma_pbl *pbl_tbl,
                            struct ocrdma_hw_mr *hwmr)
  {
        int i;
        num_pbes = 0;
  
        /* go through the OS phy regions & fill hw pbe entries into pbls. */
-       for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
+       for (i = 0; i < wr->page_list_len; i++) {
                /* number of pbes can be more for one OS buf, when
                 * buffers are of different sizes.
                 * split the ib_buf to one or more pbes.
                 */
-               buf_addr = wr->wr.fast_reg.page_list->page_list[i];
+               buf_addr = wr->page_list->page_list[i];
                pbe->pa_lo = cpu_to_le32((u32) (buf_addr & PAGE_MASK));
                pbe->pa_hi = cpu_to_le32((u32) upper_32_bits(buf_addr));
                num_pbes += 1;
@@@ -2178,9 -2179,10 +2179,10 @@@ static int get_encoded_page_size(int pg
  
  
  static int ocrdma_build_fr(struct ocrdma_qp *qp, struct ocrdma_hdr_wqe *hdr,
-                          struct ib_send_wr *wr)
+                          struct ib_send_wr *send_wr)
  {
        u64 fbo;
+       struct ib_fast_reg_wr *wr = fast_reg_wr(send_wr);
        struct ocrdma_ewqe_fr *fast_reg = (struct ocrdma_ewqe_fr *)(hdr + 1);
        struct ocrdma_mr *mr;
        struct ocrdma_dev *dev = get_ocrdma_dev(qp->ibqp.device);
  
        wqe_size = roundup(wqe_size, OCRDMA_WQE_ALIGN_BYTES);
  
-       if (wr->wr.fast_reg.page_list_len > dev->attr.max_pages_per_frmr)
+       if (wr->page_list_len > dev->attr.max_pages_per_frmr)
                return -EINVAL;
  
        hdr->cw |= (OCRDMA_FR_MR << OCRDMA_WQE_OPCODE_SHIFT);
        hdr->cw |= ((wqe_size / OCRDMA_WQE_STRIDE) << OCRDMA_WQE_SIZE_SHIFT);
  
-       if (wr->wr.fast_reg.page_list_len == 0)
+       if (wr->page_list_len == 0)
                BUG();
-       if (wr->wr.fast_reg.access_flags & IB_ACCESS_LOCAL_WRITE)
+       if (wr->access_flags & IB_ACCESS_LOCAL_WRITE)
                hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_LOCAL_WR;
-       if (wr->wr.fast_reg.access_flags & IB_ACCESS_REMOTE_WRITE)
+       if (wr->access_flags & IB_ACCESS_REMOTE_WRITE)
                hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_REMOTE_WR;
-       if (wr->wr.fast_reg.access_flags & IB_ACCESS_REMOTE_READ)
+       if (wr->access_flags & IB_ACCESS_REMOTE_READ)
                hdr->rsvd_lkey_flags |= OCRDMA_LKEY_FLAG_REMOTE_RD;
-       hdr->lkey = wr->wr.fast_reg.rkey;
-       hdr->total_len = wr->wr.fast_reg.length;
+       hdr->lkey = wr->rkey;
+       hdr->total_len = wr->length;
  
-       fbo = wr->wr.fast_reg.iova_start -
-           (wr->wr.fast_reg.page_list->page_list[0] & PAGE_MASK);
+       fbo = wr->iova_start - (wr->page_list->page_list[0] & PAGE_MASK);
  
-       fast_reg->va_hi = upper_32_bits(wr->wr.fast_reg.iova_start);
-       fast_reg->va_lo = (u32) (wr->wr.fast_reg.iova_start & 0xffffffff);
+       fast_reg->va_hi = upper_32_bits(wr->iova_start);
+       fast_reg->va_lo = (u32) (wr->iova_start & 0xffffffff);
        fast_reg->fbo_hi = upper_32_bits(fbo);
        fast_reg->fbo_lo = (u32) fbo & 0xffffffff;
-       fast_reg->num_sges = wr->wr.fast_reg.page_list_len;
+       fast_reg->num_sges = wr->page_list_len;
        fast_reg->size_sge =
-               get_encoded_page_size(1 << wr->wr.fast_reg.page_shift);
+               get_encoded_page_size(1 << wr->page_shift);
        mr = (struct ocrdma_mr *) (unsigned long)
                dev->stag_arr[(hdr->lkey >> 8) & (OCRDMA_MAX_STAG - 1)];
        build_frmr_pbes(wr, mr->hwmr.pbl_table, &mr->hwmr);
@@@ -2933,11 -2934,16 +2934,11 @@@ expand_cqe
        }
  stop_cqe:
        cq->getp = cur_getp;
 -      if (cq->deferred_arm) {
 -              ocrdma_ring_cq_db(dev, cq->id, true, cq->deferred_sol,
 -                                polled_hw_cqes);
 +      if (cq->deferred_arm || polled_hw_cqes) {
 +              ocrdma_ring_cq_db(dev, cq->id, cq->deferred_arm,
 +                                cq->deferred_sol, polled_hw_cqes);
                cq->deferred_arm = false;
                cq->deferred_sol = false;
 -      } else {
 -              /* We need to pop the CQE. No need to arm */
 -              ocrdma_ring_cq_db(dev, cq->id, false, cq->deferred_sol,
 -                                polled_hw_cqes);
 -              cq->deferred_sol = false;
        }
  
        return i;
@@@ -360,7 -360,7 +360,7 @@@ struct ipoib_dev_priv 
        unsigned             tx_head;
        unsigned             tx_tail;
        struct ib_sge        tx_sge[MAX_SKB_FRAGS + 1];
-       struct ib_send_wr    tx_wr;
+       struct ib_ud_wr      tx_wr;
        unsigned             tx_outstanding;
        struct ib_wc         send_wc[MAX_SEND_CQE];
  
@@@ -495,7 -495,6 +495,7 @@@ void ipoib_dev_cleanup(struct net_devic
  void ipoib_mcast_join_task(struct work_struct *work);
  void ipoib_mcast_carrier_on_task(struct work_struct *work);
  void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb);
 +void ipoib_mcast_free(struct ipoib_mcast *mc);
  
  void ipoib_mcast_restart_task(struct work_struct *work);
  int ipoib_mcast_start_thread(struct net_device *dev);
@@@ -528,7 -527,7 +528,7 @@@ static inline void ipoib_build_sge(stru
                priv->tx_sge[i + off].addr = mapping[i + off];
                priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
        }
-       priv->tx_wr.num_sge          = nr_frags + off;
+       priv->tx_wr.wr.num_sge       = nr_frags + off;
  }
  
  #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
@@@ -461,7 -461,7 +461,7 @@@ int ipoib_set_mode(struct net_device *d
                netdev_update_features(dev);
                dev_set_mtu(dev, ipoib_cm_max_mtu(dev));
                rtnl_unlock();
-               priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
+               priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
  
                ipoib_flush_paths(dev);
                rtnl_lock();
@@@ -1207,10 -1207,8 +1207,10 @@@ static void __ipoib_reap_neigh(struct i
  
  out_unlock:
        spin_unlock_irqrestore(&priv->lock, flags);
 -      list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
 +      list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
                ipoib_mcast_leave(dev, mcast);
 +              ipoib_mcast_free(mcast);
 +      }
  }
  
  static void ipoib_reap_neigh(struct work_struct *work)
@@@ -1860,7 -1858,7 +1860,7 @@@ static struct net_device *ipoib_add_por
        priv->dev->broadcast[8] = priv->pkey >> 8;
        priv->dev->broadcast[9] = priv->pkey & 0xff;
  
 -      result = ib_query_gid(hca, port, 0, &priv->local_gid);
 +      result = ib_query_gid(hca, port, 0, &priv->local_gid, NULL);
        if (result) {
                printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n",
                       hca->name, port, result);
@@@ -106,7 -106,7 +106,7 @@@ static void __ipoib_mcast_schedule_join
                queue_delayed_work(priv->wq, &priv->mcast_task, 0);
  }
  
 -static void ipoib_mcast_free(struct ipoib_mcast *mcast)
 +void ipoib_mcast_free(struct ipoib_mcast *mcast)
  {
        struct net_device *dev = mcast->dev;
        int tx_dropped = 0;
@@@ -245,7 -245,7 +245,7 @@@ static int ipoib_mcast_join_finish(stru
  
                priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
                spin_unlock_irq(&priv->lock);
-               priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
+               priv->tx_wr.remote_qkey = priv->qkey;
                set_qkey = 1;
        }
  
@@@ -561,7 -561,7 +561,7 @@@ void ipoib_mcast_join_task(struct work_
        }
        priv->local_lid = port_attr.lid;
  
 -      if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
 +      if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid, NULL))
                ipoib_warn(priv, "ib_query_gid() failed\n");
        else
                memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
@@@ -227,13 -227,18 +227,13 @@@ enum iser_data_dir 
   * @size:         num entries of this sg
   * @data_len:     total beffer byte len
   * @dma_nents:    returned by dma_map_sg
 - * @orig_sg:      pointer to the original sg list (in case
 - *                we used a copy)
 - * @orig_size:    num entris of orig sg list
   */
  struct iser_data_buf {
        struct scatterlist *sg;
        unsigned int       size;
        unsigned long      data_len;
        unsigned int       dma_nents;
 -      struct scatterlist *orig_sg;
 -      unsigned int       orig_size;
 -  };
 +};
  
  /* fwd declarations */
  struct iser_device;
@@@ -295,7 -300,11 +295,11 @@@ struct iser_tx_desc 
        int                          num_sge;
        bool                         mapped;
        u8                           wr_idx;
-       struct ib_send_wr            wrs[ISER_MAX_WRS];
+       union iser_wr {
+               struct ib_send_wr               send;
+               struct ib_fast_reg_wr           fast_reg;
+               struct ib_sig_handover_wr       sig;
+       } wrs[ISER_MAX_WRS];
        struct iser_mem_reg          data_reg;
        struct iser_mem_reg          prot_reg;
        struct ib_sig_attrs          sig_attrs;
@@@ -707,11 -716,11 +711,11 @@@ iser_reg_desc_put_fmr(struct ib_conn *i
  static inline struct ib_send_wr *
  iser_tx_next_wr(struct iser_tx_desc *tx_desc)
  {
-       struct ib_send_wr *cur_wr = &tx_desc->wrs[tx_desc->wr_idx];
+       struct ib_send_wr *cur_wr = &tx_desc->wrs[tx_desc->wr_idx].send;
        struct ib_send_wr *last_wr;
  
        if (tx_desc->wr_idx) {
-               last_wr = &tx_desc->wrs[tx_desc->wr_idx - 1];
+               last_wr = &tx_desc->wrs[tx_desc->wr_idx - 1].send;
                last_wr->next = cur_wr;
        }
        tx_desc->wr_idx++;
@@@ -88,6 -88,113 +88,6 @@@ int iser_assign_reg_ops(struct iser_dev
        return 0;
  }
  
 -static void
 -iser_free_bounce_sg(struct iser_data_buf *data)
 -{
 -      struct scatterlist *sg;
 -      int count;
 -
 -      for_each_sg(data->sg, sg, data->size, count)
 -              __free_page(sg_page(sg));
 -
 -      kfree(data->sg);
 -
 -      data->sg = data->orig_sg;
 -      data->size = data->orig_size;
 -      data->orig_sg = NULL;
 -      data->orig_size = 0;
 -}
 -
 -static int
 -iser_alloc_bounce_sg(struct iser_data_buf *data)
 -{
 -      struct scatterlist *sg;
 -      struct page *page;
 -      unsigned long length = data->data_len;
 -      int i = 0, nents = DIV_ROUND_UP(length, PAGE_SIZE);
 -
 -      sg = kcalloc(nents, sizeof(*sg), GFP_ATOMIC);
 -      if (!sg)
 -              goto err;
 -
 -      sg_init_table(sg, nents);
 -      while (length) {
 -              u32 page_len = min_t(u32, length, PAGE_SIZE);
 -
 -              page = alloc_page(GFP_ATOMIC);
 -              if (!page)
 -                      goto err;
 -
 -              sg_set_page(&sg[i], page, page_len, 0);
 -              length -= page_len;
 -              i++;
 -      }
 -
 -      data->orig_sg = data->sg;
 -      data->orig_size = data->size;
 -      data->sg = sg;
 -      data->size = nents;
 -
 -      return 0;
 -
 -err:
 -      for (; i > 0; i--)
 -              __free_page(sg_page(&sg[i - 1]));
 -      kfree(sg);
 -
 -      return -ENOMEM;
 -}
 -
 -static void
 -iser_copy_bounce(struct iser_data_buf *data, bool to_buffer)
 -{
 -      struct scatterlist *osg, *bsg = data->sg;
 -      void *oaddr, *baddr;
 -      unsigned int left = data->data_len;
 -      unsigned int bsg_off = 0;
 -      int i;
 -
 -      for_each_sg(data->orig_sg, osg, data->orig_size, i) {
 -              unsigned int copy_len, osg_off = 0;
 -
 -              oaddr = kmap_atomic(sg_page(osg)) + osg->offset;
 -              copy_len = min(left, osg->length);
 -              while (copy_len) {
 -                      unsigned int len = min(copy_len, bsg->length - bsg_off);
 -
 -                      baddr = kmap_atomic(sg_page(bsg)) + bsg->offset;
 -                      if (to_buffer)
 -                              memcpy(baddr + bsg_off, oaddr + osg_off, len);
 -                      else
 -                              memcpy(oaddr + osg_off, baddr + bsg_off, len);
 -
 -                      kunmap_atomic(baddr - bsg->offset);
 -                      osg_off += len;
 -                      bsg_off += len;
 -                      copy_len -= len;
 -
 -                      if (bsg_off >= bsg->length) {
 -                              bsg = sg_next(bsg);
 -                              bsg_off = 0;
 -                      }
 -              }
 -              kunmap_atomic(oaddr - osg->offset);
 -              left -= osg_off;
 -      }
 -}
 -
 -static inline void
 -iser_copy_from_bounce(struct iser_data_buf *data)
 -{
 -      iser_copy_bounce(data, false);
 -}
 -
 -static inline void
 -iser_copy_to_bounce(struct iser_data_buf *data)
 -{
 -      iser_copy_bounce(data, true);
 -}
 -
  struct iser_fr_desc *
  iser_reg_desc_get_fr(struct ib_conn *ib_conn)
  {
@@@ -131,6 -238,62 +131,6 @@@ iser_reg_desc_put_fmr(struct ib_conn *i
  {
  }
  
 -/**
 - * iser_start_rdma_unaligned_sg
 - */
 -static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
 -                                      struct iser_data_buf *data,
 -                                      enum iser_data_dir cmd_dir)
 -{
 -      struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
 -      int rc;
 -
 -      rc = iser_alloc_bounce_sg(data);
 -      if (rc) {
 -              iser_err("Failed to allocate bounce for data len %lu\n",
 -                       data->data_len);
 -              return rc;
 -      }
 -
 -      if (cmd_dir == ISER_DIR_OUT)
 -              iser_copy_to_bounce(data);
 -
 -      data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size,
 -                                      (cmd_dir == ISER_DIR_OUT) ?
 -                                      DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -      if (!data->dma_nents) {
 -              iser_err("Got dma_nents %d, something went wrong...\n",
 -                       data->dma_nents);
 -              rc = -ENOMEM;
 -              goto err;
 -      }
 -
 -      return 0;
 -err:
 -      iser_free_bounce_sg(data);
 -      return rc;
 -}
 -
 -/**
 - * iser_finalize_rdma_unaligned_sg
 - */
 -
 -void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
 -                                   struct iser_data_buf *data,
 -                                   enum iser_data_dir cmd_dir)
 -{
 -      struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
 -
 -      ib_dma_unmap_sg(dev, data->sg, data->size,
 -                      (cmd_dir == ISER_DIR_OUT) ?
 -                      DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -
 -      if (cmd_dir == ISER_DIR_IN)
 -              iser_copy_from_bounce(data);
 -
 -      iser_free_bounce_sg(data);
 -}
 -
  #define IS_4K_ALIGNED(addr)   ((((unsigned long)addr) & ~MASK_4K) == 0)
  
  /**
@@@ -192,6 -355,64 +192,6 @@@ static int iser_sg_to_page_vec(struct i
        return cur_page;
  }
  
 -
 -/**
 - * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
 - * for RDMA sub-list of a scatter-gather list of memory buffers, and  returns
 - * the number of entries which are aligned correctly. Supports the case where
 - * consecutive SG elements are actually fragments of the same physcial page.
 - */
 -static int iser_data_buf_aligned_len(struct iser_data_buf *data,
 -                                   struct ib_device *ibdev,
 -                                   unsigned sg_tablesize)
 -{
 -      struct scatterlist *sg, *sgl, *next_sg = NULL;
 -      u64 start_addr, end_addr;
 -      int i, ret_len, start_check = 0;
 -
 -      if (data->dma_nents == 1)
 -              return 1;
 -
 -      sgl = data->sg;
 -      start_addr  = ib_sg_dma_address(ibdev, sgl);
 -
 -      if (unlikely(sgl[0].offset &&
 -                   data->data_len >= sg_tablesize * PAGE_SIZE)) {
 -              iser_dbg("can't register length %lx with offset %x "
 -                       "fall to bounce buffer\n", data->data_len,
 -                       sgl[0].offset);
 -              return 0;
 -      }
 -
 -      for_each_sg(sgl, sg, data->dma_nents, i) {
 -              if (start_check && !IS_4K_ALIGNED(start_addr))
 -                      break;
 -
 -              next_sg = sg_next(sg);
 -              if (!next_sg)
 -                      break;
 -
 -              end_addr    = start_addr + ib_sg_dma_len(ibdev, sg);
 -              start_addr  = ib_sg_dma_address(ibdev, next_sg);
 -
 -              if (end_addr == start_addr) {
 -                      start_check = 0;
 -                      continue;
 -              } else
 -                      start_check = 1;
 -
 -              if (!IS_4K_ALIGNED(end_addr))
 -                      break;
 -      }
 -      ret_len = (next_sg) ? i : i+1;
 -
 -      if (unlikely(ret_len != data->dma_nents))
 -              iser_warn("rdma alignment violation (%d/%d aligned)\n",
 -                        ret_len, data->dma_nents);
 -
 -      return ret_len;
 -}
 -
  static void iser_data_buf_dump(struct iser_data_buf *data,
                               struct ib_device *ibdev)
  {
@@@ -262,6 -483,31 +262,6 @@@ iser_reg_dma(struct iser_device *device
        return 0;
  }
  
 -static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task,
 -                            struct iser_data_buf *mem,
 -                            enum iser_data_dir cmd_dir)
 -{
 -      struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn;
 -      struct iser_device *device = iser_task->iser_conn->ib_conn.device;
 -
 -      iscsi_conn->fmr_unalign_cnt++;
 -
 -      if (iser_debug_level > 0)
 -              iser_data_buf_dump(mem, device->ib_device);
 -
 -      /* unmap the command data before accessing it */
 -      iser_dma_unmap_task_data(iser_task, mem,
 -                               (cmd_dir == ISER_DIR_OUT) ?
 -                               DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -
 -      /* allocate copy buf, if we are writing, copy the */
 -      /* unaligned scatterlist, dma map the copy        */
 -      if (iser_start_rdma_unaligned_sg(iser_task, mem, cmd_dir) != 0)
 -              return -ENOMEM;
 -
 -      return 0;
 -}
 -
  /**
   * iser_reg_page_vec - Register physical memory
   *
@@@ -437,7 -683,7 +437,7 @@@ iser_reg_sig_mr(struct iscsi_iser_task 
  {
        struct iser_tx_desc *tx_desc = &iser_task->desc;
        struct ib_sig_attrs *sig_attrs = &tx_desc->sig_attrs;
-       struct ib_send_wr *wr;
+       struct ib_sig_handover_wr *wr;
        int ret;
  
        memset(sig_attrs, 0, sizeof(*sig_attrs));
  
        iser_set_prot_checks(iser_task->sc, &sig_attrs->check_mask);
  
-       if (!pi_ctx->sig_mr_valid) {
-               wr = iser_tx_next_wr(tx_desc);
-               iser_inv_rkey(wr, pi_ctx->sig_mr);
-       }
-       wr = iser_tx_next_wr(tx_desc);
-       wr->opcode = IB_WR_REG_SIG_MR;
-       wr->wr_id = ISER_FASTREG_LI_WRID;
-       wr->sg_list = &data_reg->sge;
-       wr->num_sge = 1;
-       wr->send_flags = 0;
-       wr->wr.sig_handover.sig_attrs = sig_attrs;
-       wr->wr.sig_handover.sig_mr = pi_ctx->sig_mr;
+       if (!pi_ctx->sig_mr_valid)
+               iser_inv_rkey(iser_tx_next_wr(tx_desc), pi_ctx->sig_mr);
+       wr = sig_handover_wr(iser_tx_next_wr(tx_desc));
+       wr->wr.opcode = IB_WR_REG_SIG_MR;
+       wr->wr.wr_id = ISER_FASTREG_LI_WRID;
+       wr->wr.sg_list = &data_reg->sge;
+       wr->wr.num_sge = 1;
+       wr->wr.send_flags = 0;
+       wr->sig_attrs = sig_attrs;
+       wr->sig_mr = pi_ctx->sig_mr;
        if (scsi_prot_sg_count(iser_task->sc))
-               wr->wr.sig_handover.prot = &prot_reg->sge;
+               wr->prot = &prot_reg->sge;
        else
-               wr->wr.sig_handover.prot = NULL;
-       wr->wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE |
-                                          IB_ACCESS_REMOTE_READ |
-                                          IB_ACCESS_REMOTE_WRITE;
+               wr->prot = NULL;
+       wr->access_flags = IB_ACCESS_LOCAL_WRITE |
+                          IB_ACCESS_REMOTE_READ |
+                          IB_ACCESS_REMOTE_WRITE;
        pi_ctx->sig_mr_valid = 0;
  
        sig_reg->sge.lkey = pi_ctx->sig_mr->lkey;
@@@ -491,7 -735,7 +489,7 @@@ static int iser_fast_reg_mr(struct iscs
        struct ib_mr *mr = rsc->mr;
        struct ib_fast_reg_page_list *frpl = rsc->frpl;
        struct iser_tx_desc *tx_desc = &iser_task->desc;
-       struct ib_send_wr *wr;
+       struct ib_fast_reg_wr *wr;
        int offset, size, plen;
  
        plen = iser_sg_to_page_vec(mem, device->ib_device, frpl->page_list,
                return -EINVAL;
        }
  
-       if (!rsc->mr_valid) {
-               wr = iser_tx_next_wr(tx_desc);
-               iser_inv_rkey(wr, mr);
-       }
-       wr = iser_tx_next_wr(tx_desc);
-       wr->opcode = IB_WR_FAST_REG_MR;
-       wr->wr_id = ISER_FASTREG_LI_WRID;
-       wr->send_flags = 0;
-       wr->wr.fast_reg.iova_start = frpl->page_list[0] + offset;
-       wr->wr.fast_reg.page_list = frpl;
-       wr->wr.fast_reg.page_list_len = plen;
-       wr->wr.fast_reg.page_shift = SHIFT_4K;
-       wr->wr.fast_reg.length = size;
-       wr->wr.fast_reg.rkey = mr->rkey;
-       wr->wr.fast_reg.access_flags = (IB_ACCESS_LOCAL_WRITE  |
-                                       IB_ACCESS_REMOTE_WRITE |
-                                       IB_ACCESS_REMOTE_READ);
+       if (!rsc->mr_valid)
+               iser_inv_rkey(iser_tx_next_wr(tx_desc), mr);
+       wr = fast_reg_wr(iser_tx_next_wr(tx_desc));
+       wr->wr.opcode = IB_WR_FAST_REG_MR;
+       wr->wr.wr_id = ISER_FASTREG_LI_WRID;
+       wr->wr.send_flags = 0;
+       wr->iova_start = frpl->page_list[0] + offset;
+       wr->page_list = frpl;
+       wr->page_list_len = plen;
+       wr->page_shift = SHIFT_4K;
+       wr->length = size;
+       wr->rkey = mr->rkey;
+       wr->access_flags = (IB_ACCESS_LOCAL_WRITE  |
+                           IB_ACCESS_REMOTE_WRITE |
+                           IB_ACCESS_REMOTE_READ);
        rsc->mr_valid = 0;
  
        reg->sge.lkey = mr->lkey;
        return 0;
  }
  
 -static int
 -iser_handle_unaligned_buf(struct iscsi_iser_task *task,
 -                        struct iser_data_buf *mem,
 -                        enum iser_data_dir dir)
 -{
 -      struct iser_conn *iser_conn = task->iser_conn;
 -      struct iser_device *device = iser_conn->ib_conn.device;
 -      int err, aligned_len;
 -
 -      aligned_len = iser_data_buf_aligned_len(mem, device->ib_device,
 -                                              iser_conn->scsi_sg_tablesize);
 -      if (aligned_len != mem->dma_nents) {
 -              err = fall_to_bounce_buf(task, mem, dir);
 -              if (err)
 -                      return err;
 -      }
 -
 -      return 0;
 -}
 -
  static int
  iser_reg_prot_sg(struct iscsi_iser_task *task,
                 struct iser_data_buf *mem,
@@@ -575,6 -837,10 +571,6 @@@ int iser_reg_rdma_mem(struct iscsi_iser
        bool use_dma_key;
        int err;
  
 -      err = iser_handle_unaligned_buf(task, mem, dir);
 -      if (unlikely(err))
 -              return err;
 -
        use_dma_key = (mem->dma_nents == 1 && !iser_always_reg &&
                       scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL);
  
  
                if (scsi_prot_sg_count(task->sc)) {
                        mem = &task->prot[dir];
 -                      err = iser_handle_unaligned_buf(task, mem, dir);
 -                      if (unlikely(err))
 -                              goto err_reg;
 -
                        err = iser_reg_prot_sg(task, mem, desc,
                                               use_dma_key, prot_reg);
                        if (unlikely(err))
@@@ -1017,7 -1017,7 +1017,7 @@@ int iser_connect(struct iser_conn   *is
        ib_conn->beacon.wr_id = ISER_BEACON_WRID;
        ib_conn->beacon.opcode = IB_WR_SEND;
  
 -      ib_conn->cma_id = rdma_create_id(iser_cma_handler,
 +      ib_conn->cma_id = rdma_create_id(&init_net, iser_cma_handler,
                                         (void *)iser_conn,
                                         RDMA_PS_TCP, IB_QPT_RC);
        if (IS_ERR(ib_conn->cma_id)) {
@@@ -1135,7 -1135,7 +1135,7 @@@ int iser_post_send(struct ib_conn *ib_c
        wr->opcode = IB_WR_SEND;
        wr->send_flags = signal ? IB_SEND_SIGNALED : 0;
  
-       ib_ret = ib_post_send(ib_conn->qp, &tx_desc->wrs[0], &bad_wr);
+       ib_ret = ib_post_send(ib_conn->qp, &tx_desc->wrs[0].send, &bad_wr);
        if (ib_ret)
                iser_err("ib_post_send failed, ret:%d opcode:%d\n",
                         ib_ret, bad_wr->opcode);
@@@ -1579,6 -1579,7 +1579,6 @@@ isert_rx_do_work(struct iser_rx_desc *r
        struct iser_hdr *iser_hdr = &rx_desc->iser_header;
        uint64_t read_va = 0, write_va = 0;
        uint32_t read_stag = 0, write_stag = 0;
 -      int rc;
  
        switch (iser_hdr->flags & 0xF0) {
        case ISCSI_CTRL:
                break;
        }
  
 -      rc = isert_rx_opcode(isert_conn, rx_desc,
 -                           read_stag, read_va, write_stag, write_va);
 +      isert_rx_opcode(isert_conn, rx_desc,
 +                      read_stag, read_va, write_stag, write_va);
  }
  
  static void
@@@ -1715,10 -1716,10 +1715,10 @@@ isert_unmap_cmd(struct isert_cmd *isert
                isert_unmap_data_buf(isert_conn, &wr->data);
        }
  
-       if (wr->send_wr) {
+       if (wr->rdma_wr) {
                isert_dbg("Cmd %p free send_wr\n", isert_cmd);
-               kfree(wr->send_wr);
-               wr->send_wr = NULL;
+               kfree(wr->rdma_wr);
+               wr->rdma_wr = NULL;
        }
  
        if (wr->ib_sge) {
@@@ -1753,7 -1754,7 +1753,7 @@@ isert_unreg_rdma(struct isert_cmd *iser
        }
  
        wr->ib_sge = NULL;
-       wr->send_wr = NULL;
+       wr->rdma_wr = NULL;
  }
  
  static void
@@@ -1922,7 -1923,7 +1922,7 @@@ isert_completion_rdma_write(struct iser
        }
  
        device->unreg_rdma_mem(isert_cmd, isert_conn);
-       wr->send_wr_num = 0;
+       wr->rdma_wr_num = 0;
        if (ret)
                transport_send_check_condition_and_sense(se_cmd,
                                                         se_cmd->pi_err, 0);
@@@ -1950,7 -1951,7 +1950,7 @@@ isert_completion_rdma_read(struct iser_
        iscsit_stop_dataout_timer(cmd);
        device->unreg_rdma_mem(isert_cmd, isert_conn);
        cmd->write_data_done = wr->data.len;
-       wr->send_wr_num = 0;
+       wr->rdma_wr_num = 0;
  
        isert_dbg("Cmd: %p RDMA_READ comp calling execute_cmd\n", isert_cmd);
        spin_lock_bh(&cmd->istate_lock);
@@@ -2402,7 -2403,7 +2402,7 @@@ isert_put_text_rsp(struct iscsi_cmd *cm
  
  static int
  isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
-                   struct ib_sge *ib_sge, struct ib_send_wr *send_wr,
+                   struct ib_sge *ib_sge, struct ib_rdma_wr *rdma_wr,
                    u32 data_left, u32 offset)
  {
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
        sg_nents = min(cmd->se_cmd.t_data_nents - sg_off, isert_conn->max_sge);
        page_off = offset % PAGE_SIZE;
  
-       send_wr->sg_list = ib_sge;
-       send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
+       rdma_wr->wr.sg_list = ib_sge;
+       rdma_wr->wr.wr_id = (uintptr_t)&isert_cmd->tx_desc;
        /*
         * Perform mapping of TCM scatterlist memory ib_sge dma_addr.
         */
                isert_dbg("Incrementing ib_sge pointer to %p\n", ib_sge);
        }
  
-       send_wr->num_sge = ++i;
+       rdma_wr->wr.num_sge = ++i;
        isert_dbg("Set outgoing sg_list: %p num_sg: %u from TCM SGLs\n",
-                 send_wr->sg_list, send_wr->num_sge);
+                 rdma_wr->wr.sg_list, rdma_wr->wr.num_sge);
  
-       return send_wr->num_sge;
+       return rdma_wr->wr.num_sge;
  }
  
  static int
@@@ -2458,7 -2459,7 +2458,7 @@@ isert_map_rdma(struct iscsi_conn *conn
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
        struct isert_conn *isert_conn = conn->context;
        struct isert_data_buf *data = &wr->data;
-       struct ib_send_wr *send_wr;
+       struct ib_rdma_wr *rdma_wr;
        struct ib_sge *ib_sge;
        u32 offset, data_len, data_left, rdma_write_max, va_offset = 0;
        int ret = 0, i, ib_sge_cnt;
        }
        wr->ib_sge = ib_sge;
  
-       wr->send_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge);
-       wr->send_wr = kzalloc(sizeof(struct ib_send_wr) * wr->send_wr_num,
+       wr->rdma_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge);
+       wr->rdma_wr = kzalloc(sizeof(struct ib_rdma_wr) * wr->rdma_wr_num,
                                GFP_KERNEL);
-       if (!wr->send_wr) {
-               isert_dbg("Unable to allocate wr->send_wr\n");
+       if (!wr->rdma_wr) {
+               isert_dbg("Unable to allocate wr->rdma_wr\n");
                ret = -ENOMEM;
                goto unmap_cmd;
        }
        wr->isert_cmd = isert_cmd;
        rdma_write_max = isert_conn->max_sge * PAGE_SIZE;
  
-       for (i = 0; i < wr->send_wr_num; i++) {
-               send_wr = &isert_cmd->rdma_wr.send_wr[i];
+       for (i = 0; i < wr->rdma_wr_num; i++) {
+               rdma_wr = &isert_cmd->rdma_wr.rdma_wr[i];
                data_len = min(data_left, rdma_write_max);
  
-               send_wr->send_flags = 0;
+               rdma_wr->wr.send_flags = 0;
                if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) {
-                       send_wr->opcode = IB_WR_RDMA_WRITE;
-                       send_wr->wr.rdma.remote_addr = isert_cmd->read_va + offset;
-                       send_wr->wr.rdma.rkey = isert_cmd->read_stag;
-                       if (i + 1 == wr->send_wr_num)
-                               send_wr->next = &isert_cmd->tx_desc.send_wr;
+                       rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+                       rdma_wr->remote_addr = isert_cmd->read_va + offset;
+                       rdma_wr->rkey = isert_cmd->read_stag;
+                       if (i + 1 == wr->rdma_wr_num)
+                               rdma_wr->wr.next = &isert_cmd->tx_desc.send_wr;
                        else
-                               send_wr->next = &wr->send_wr[i + 1];
+                               rdma_wr->wr.next = &wr->rdma_wr[i + 1].wr;
                } else {
-                       send_wr->opcode = IB_WR_RDMA_READ;
-                       send_wr->wr.rdma.remote_addr = isert_cmd->write_va + va_offset;
-                       send_wr->wr.rdma.rkey = isert_cmd->write_stag;
-                       if (i + 1 == wr->send_wr_num)
-                               send_wr->send_flags = IB_SEND_SIGNALED;
+                       rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+                       rdma_wr->remote_addr = isert_cmd->write_va + va_offset;
+                       rdma_wr->rkey = isert_cmd->write_stag;
+                       if (i + 1 == wr->rdma_wr_num)
+                               rdma_wr->wr.send_flags = IB_SEND_SIGNALED;
                        else
-                               send_wr->next = &wr->send_wr[i + 1];
+                               rdma_wr->wr.next = &wr->rdma_wr[i + 1].wr;
                }
  
                ib_sge_cnt = isert_build_rdma_wr(isert_conn, isert_cmd, ib_sge,
-                                       send_wr, data_len, offset);
+                                       rdma_wr, data_len, offset);
                ib_sge += ib_sge_cnt;
  
                offset += data_len;
@@@ -2599,8 -2600,8 +2599,8 @@@ isert_fast_reg_mr(struct isert_conn *is
        struct ib_device *ib_dev = device->ib_device;
        struct ib_mr *mr;
        struct ib_fast_reg_page_list *frpl;
-       struct ib_send_wr fr_wr, inv_wr;
-       struct ib_send_wr *bad_wr, *wr = NULL;
+       struct ib_fast_reg_wr fr_wr;
+       struct ib_send_wr inv_wr, *bad_wr, *wr = NULL;
        int ret, pagelist_len;
        u32 page_off;
  
  
        /* Prepare FASTREG WR */
        memset(&fr_wr, 0, sizeof(fr_wr));
-       fr_wr.wr_id = ISER_FASTREG_LI_WRID;
-       fr_wr.opcode = IB_WR_FAST_REG_MR;
-       fr_wr.wr.fast_reg.iova_start = frpl->page_list[0] + page_off;
-       fr_wr.wr.fast_reg.page_list = frpl;
-       fr_wr.wr.fast_reg.page_list_len = pagelist_len;
-       fr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
-       fr_wr.wr.fast_reg.length = mem->len;
-       fr_wr.wr.fast_reg.rkey = mr->rkey;
-       fr_wr.wr.fast_reg.access_flags = IB_ACCESS_LOCAL_WRITE;
+       fr_wr.wr.wr_id = ISER_FASTREG_LI_WRID;
+       fr_wr.wr.opcode = IB_WR_FAST_REG_MR;
+       fr_wr.iova_start = frpl->page_list[0] + page_off;
+       fr_wr.page_list = frpl;
+       fr_wr.page_list_len = pagelist_len;
+       fr_wr.page_shift = PAGE_SHIFT;
+       fr_wr.length = mem->len;
+       fr_wr.rkey = mr->rkey;
+       fr_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
  
        if (!wr)
-               wr = &fr_wr;
+               wr = &fr_wr.wr;
        else
-               wr->next = &fr_wr;
+               wr->next = &fr_wr.wr;
  
        ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
        if (ret) {
@@@ -2732,8 -2733,8 +2732,8 @@@ isert_reg_sig_mr(struct isert_conn *ise
                 struct isert_rdma_wr *rdma_wr,
                 struct fast_reg_descriptor *fr_desc)
  {
-       struct ib_send_wr sig_wr, inv_wr;
-       struct ib_send_wr *bad_wr, *wr = NULL;
+       struct ib_sig_handover_wr sig_wr;
+       struct ib_send_wr inv_wr, *bad_wr, *wr = NULL;
        struct pi_context *pi_ctx = fr_desc->pi_ctx;
        struct ib_sig_attrs sig_attrs;
        int ret;
        }
  
        memset(&sig_wr, 0, sizeof(sig_wr));
-       sig_wr.opcode = IB_WR_REG_SIG_MR;
-       sig_wr.wr_id = ISER_FASTREG_LI_WRID;
-       sig_wr.sg_list = &rdma_wr->ib_sg[DATA];
-       sig_wr.num_sge = 1;
-       sig_wr.wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE;
-       sig_wr.wr.sig_handover.sig_attrs = &sig_attrs;
-       sig_wr.wr.sig_handover.sig_mr = pi_ctx->sig_mr;
+       sig_wr.wr.opcode = IB_WR_REG_SIG_MR;
+       sig_wr.wr.wr_id = ISER_FASTREG_LI_WRID;
+       sig_wr.wr.sg_list = &rdma_wr->ib_sg[DATA];
+       sig_wr.wr.num_sge = 1;
+       sig_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
+       sig_wr.sig_attrs = &sig_attrs;
+       sig_wr.sig_mr = pi_ctx->sig_mr;
        if (se_cmd->t_prot_sg)
-               sig_wr.wr.sig_handover.prot = &rdma_wr->ib_sg[PROT];
+               sig_wr.prot = &rdma_wr->ib_sg[PROT];
  
        if (!wr)
-               wr = &sig_wr;
+               wr = &sig_wr.wr;
        else
-               wr->next = &sig_wr;
+               wr->next = &sig_wr.wr;
  
        ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
        if (ret) {
@@@ -2858,7 -2859,7 +2858,7 @@@ isert_reg_rdma(struct iscsi_conn *conn
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
        struct isert_conn *isert_conn = conn->context;
        struct fast_reg_descriptor *fr_desc = NULL;
-       struct ib_send_wr *send_wr;
+       struct ib_rdma_wr *rdma_wr;
        struct ib_sge *ib_sg;
        u32 offset;
        int ret = 0;
  
        memcpy(&wr->s_ib_sge, ib_sg, sizeof(*ib_sg));
        wr->ib_sge = &wr->s_ib_sge;
-       wr->send_wr_num = 1;
-       memset(&wr->s_send_wr, 0, sizeof(*send_wr));
-       wr->send_wr = &wr->s_send_wr;
+       wr->rdma_wr_num = 1;
+       memset(&wr->s_rdma_wr, 0, sizeof(wr->s_rdma_wr));
+       wr->rdma_wr = &wr->s_rdma_wr;
        wr->isert_cmd = isert_cmd;
  
-       send_wr = &isert_cmd->rdma_wr.s_send_wr;
-       send_wr->sg_list = &wr->s_ib_sge;
-       send_wr->num_sge = 1;
-       send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
+       rdma_wr = &isert_cmd->rdma_wr.s_rdma_wr;
+       rdma_wr->wr.sg_list = &wr->s_ib_sge;
+       rdma_wr->wr.num_sge = 1;
+       rdma_wr->wr.wr_id = (uintptr_t)&isert_cmd->tx_desc;
        if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) {
-               send_wr->opcode = IB_WR_RDMA_WRITE;
-               send_wr->wr.rdma.remote_addr = isert_cmd->read_va;
-               send_wr->wr.rdma.rkey = isert_cmd->read_stag;
-               send_wr->send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
+               rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+               rdma_wr->remote_addr = isert_cmd->read_va;
+               rdma_wr->rkey = isert_cmd->read_stag;
+               rdma_wr->wr.send_flags = !isert_prot_cmd(isert_conn, se_cmd) ?
                                      0 : IB_SEND_SIGNALED;
        } else {
-               send_wr->opcode = IB_WR_RDMA_READ;
-               send_wr->wr.rdma.remote_addr = isert_cmd->write_va;
-               send_wr->wr.rdma.rkey = isert_cmd->write_stag;
-               send_wr->send_flags = IB_SEND_SIGNALED;
+               rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+               rdma_wr->remote_addr = isert_cmd->write_va;
+               rdma_wr->rkey = isert_cmd->write_stag;
+               rdma_wr->wr.send_flags = IB_SEND_SIGNALED;
        }
  
        return 0;
@@@ -2966,8 -2967,8 +2966,8 @@@ isert_put_datain(struct iscsi_conn *con
                isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
                isert_init_send_wr(isert_conn, isert_cmd,
                                   &isert_cmd->tx_desc.send_wr);
-               isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
-               wr->send_wr_num += 1;
+               isert_cmd->rdma_wr.s_rdma_wr.wr.next = &isert_cmd->tx_desc.send_wr;
+               wr->rdma_wr_num += 1;
  
                rc = isert_post_recv(isert_conn, isert_cmd->rx_desc);
                if (rc) {
                }
        }
  
-       rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
+       rc = ib_post_send(isert_conn->qp, &wr->rdma_wr->wr, &wr_failed);
        if (rc)
                isert_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n");
  
@@@ -3010,7 -3011,7 +3010,7 @@@ isert_get_dataout(struct iscsi_conn *co
                return rc;
        }
  
-       rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
+       rc = ib_post_send(isert_conn->qp, &wr->rdma_wr->wr, &wr_failed);
        if (rc)
                isert_warn("ib_post_send() failed for IB_WR_RDMA_READ\n");
  
@@@ -3096,7 -3097,7 +3096,7 @@@ isert_setup_id(struct isert_np *isert_n
        sa = (struct sockaddr *)&np->np_sockaddr;
        isert_dbg("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa);
  
 -      id = rdma_create_id(isert_cma_handler, isert_np,
 +      id = rdma_create_id(&init_net, isert_cma_handler, isert_np,
                            RDMA_PS_TCP, IB_QPT_RC);
        if (IS_ERR(id)) {
                isert_err("rdma_create_id() failed: %ld\n", PTR_ERR(id));
@@@ -1306,7 -1306,7 +1306,7 @@@ static int srp_map_finish_fr(struct srp
        struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_send_wr *bad_wr;
-       struct ib_send_wr wr;
+       struct ib_fast_reg_wr wr;
        struct srp_fr_desc *desc;
        u32 rkey;
  
               sizeof(state->pages[0]) * state->npages);
  
        memset(&wr, 0, sizeof(wr));
-       wr.opcode = IB_WR_FAST_REG_MR;
-       wr.wr_id = FAST_REG_WR_ID_MASK;
-       wr.wr.fast_reg.iova_start = state->base_dma_addr;
-       wr.wr.fast_reg.page_list = desc->frpl;
-       wr.wr.fast_reg.page_list_len = state->npages;
-       wr.wr.fast_reg.page_shift = ilog2(dev->mr_page_size);
-       wr.wr.fast_reg.length = state->dma_len;
-       wr.wr.fast_reg.access_flags = (IB_ACCESS_LOCAL_WRITE |
-                                      IB_ACCESS_REMOTE_READ |
-                                      IB_ACCESS_REMOTE_WRITE);
-       wr.wr.fast_reg.rkey = desc->mr->lkey;
+       wr.wr.opcode = IB_WR_FAST_REG_MR;
+       wr.wr.wr_id = FAST_REG_WR_ID_MASK;
+       wr.iova_start = state->base_dma_addr;
+       wr.page_list = desc->frpl;
+       wr.page_list_len = state->npages;
+       wr.page_shift = ilog2(dev->mr_page_size);
+       wr.length = state->dma_len;
+       wr.access_flags = (IB_ACCESS_LOCAL_WRITE |
+                          IB_ACCESS_REMOTE_READ |
+                          IB_ACCESS_REMOTE_WRITE);
+       wr.rkey = desc->mr->lkey;
  
        *state->fr.next++ = desc;
        state->nmdesc++;
        srp_map_desc(state, state->base_dma_addr, state->dma_len,
                     desc->mr->rkey);
  
-       return ib_post_send(ch->qp, &wr, &bad_wr);
+       return ib_post_send(ch->qp, &wr.wr, &bad_wr);
  }
  
  static int srp_finish_mapping(struct srp_map_state *state,
@@@ -3213,7 -3213,7 +3213,7 @@@ static ssize_t srp_create_target(struc
        INIT_WORK(&target->tl_err_work, srp_tl_err_work);
        INIT_WORK(&target->remove_work, srp_remove_work);
        spin_lock_init(&target->lock);
 -      ret = ib_query_gid(ibdev, host->port, 0, &target->sgid);
 +      ret = ib_query_gid(ibdev, host->port, 0, &target->sgid, NULL);
        if (ret)
                goto out;
  
@@@ -546,8 -546,7 +546,8 @@@ static int srpt_refresh_port(struct srp
        sport->sm_lid = port_attr.sm_lid;
        sport->lid = port_attr.lid;
  
 -      ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);
 +      ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid,
 +                         NULL);
        if (ret)
                goto err_query_port;
  
@@@ -2823,7 -2822,7 +2823,7 @@@ static int srpt_cm_handler(struct ib_cm
  static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
                              struct srpt_send_ioctx *ioctx)
  {
-       struct ib_send_wr wr;
+       struct ib_rdma_wr wr;
        struct ib_send_wr *bad_wr;
        struct rdma_iu *riu;
        int i;
  
        for (i = 0; i < n_rdma; ++i, ++riu) {
                if (dir == DMA_FROM_DEVICE) {
-                       wr.opcode = IB_WR_RDMA_WRITE;
-                       wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+                       wr.wr.opcode = IB_WR_RDMA_WRITE;
+                       wr.wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
                                                SRPT_RDMA_WRITE_LAST :
                                                SRPT_RDMA_MID,
                                                ioctx->ioctx.index);
                } else {
-                       wr.opcode = IB_WR_RDMA_READ;
-                       wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+                       wr.wr.opcode = IB_WR_RDMA_READ;
+                       wr.wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
                                                SRPT_RDMA_READ_LAST :
                                                SRPT_RDMA_MID,
                                                ioctx->ioctx.index);
                }
-               wr.next = NULL;
-               wr.wr.rdma.remote_addr = riu->raddr;
-               wr.wr.rdma.rkey = riu->rkey;
-               wr.num_sge = riu->sge_cnt;
-               wr.sg_list = riu->sge;
+               wr.wr.next = NULL;
+               wr.remote_addr = riu->raddr;
+               wr.rkey = riu->rkey;
+               wr.wr.num_sge = riu->sge_cnt;
+               wr.wr.sg_list = riu->sge;
  
                /* only get completion event for the last rdma write */
                if (i == (n_rdma - 1) && dir == DMA_TO_DEVICE)
-                       wr.send_flags = IB_SEND_SIGNALED;
+                       wr.wr.send_flags = IB_SEND_SIGNALED;
  
-               ret = ib_post_send(ch->qp, &wr, &bad_wr);
+               ret = ib_post_send(ch->qp, &wr.wr, &bad_wr);
                if (ret)
                        break;
        }
                pr_err("%s[%d]: ib_post_send() returned %d for %d/%d\n",
                                 __func__, __LINE__, ret, i, n_rdma);
        if (ret && i > 0) {
-               wr.num_sge = 0;
-               wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
-               wr.send_flags = IB_SEND_SIGNALED;
+               wr.wr.num_sge = 0;
+               wr.wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
+               wr.wr.send_flags = IB_SEND_SIGNALED;
                while (ch->state == CH_LIVE &&
-                       ib_post_send(ch->qp, &wr, &bad_wr) != 0) {
+                       ib_post_send(ch->qp, &wr.wr, &bad_wr) != 0) {
                        pr_info("Trying to abort failed RDMA transfer [%d]\n",
                                ioctx->ioctx.index);
                        msleep(1000);
@@@ -128,9 -128,7 +128,9 @@@ extern kib_tunables_t  kiblnd_tunables
                                     IBLND_CREDIT_HIGHWATER_V1 : \
                                     *kiblnd_tunables.kib_peercredits_hiw) /* when eagerly to return credits */
  
 -#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(cb, dev, ps, qpt)
 +#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(&init_net, \
 +                                                             cb, dev, \
 +                                                             ps, qpt)
  
  static inline int
  kiblnd_concurrent_sends_v1(void)
@@@ -527,7 -525,7 +527,7 @@@ typedef struct kib_t
        __u64                  tx_msgaddr;    /* message buffer (I/O addr) */
        DECLARE_PCI_UNMAP_ADDR(tx_msgunmap);  /* for dma_unmap_single() */
        int                    tx_nwrq;       /* # send work items */
-       struct ib_send_wr      *tx_wrq;       /* send work items... */
+       struct ib_rdma_wr      *tx_wrq;       /* send work items... */
        struct ib_sge          *tx_sge;       /* ...and their memory */
        kib_rdma_desc_t        *tx_rd;        /* rdma descriptor */
        int                    tx_nfrags;     /* # entries in... */
diff --combined include/rdma/ib_verbs.h
@@@ -137,8 -137,6 +137,8 @@@ enum ib_device_cap_flags 
        IB_DEVICE_BLOCK_MULTICAST_LOOPBACK = (1<<22),
        IB_DEVICE_MEM_WINDOW_TYPE_2A    = (1<<23),
        IB_DEVICE_MEM_WINDOW_TYPE_2B    = (1<<24),
 +      IB_DEVICE_RC_IP_CSUM            = (1<<25),
 +      IB_DEVICE_RAW_IP_CSUM           = (1<<26),
        IB_DEVICE_MANAGED_FLOW_STEERING = (1<<29),
        IB_DEVICE_SIGNATURE_HANDOVER    = (1<<30),
        IB_DEVICE_ON_DEMAND_PAGING      = (1<<31),
@@@ -699,6 -697,7 +699,6 @@@ struct ib_ah_attr 
        u8                      ah_flags;
        u8                      port_num;
        u8                      dmac[ETH_ALEN];
 -      u16                     vlan_id;
  };
  
  enum ib_wc_status {
@@@ -874,6 -873,7 +874,6 @@@ enum ib_qp_create_flags 
        IB_QP_CREATE_RESERVED_END               = 1 << 31,
  };
  
 -
  /*
   * Note: users may not call ib_close_qp or ib_destroy_qp from the event_handler
   * callback to destroy the passed in QP.
@@@ -957,10 -957,10 +957,10 @@@ enum ib_qp_attr_mask 
        IB_QP_PATH_MIG_STATE            = (1<<18),
        IB_QP_CAP                       = (1<<19),
        IB_QP_DEST_QPN                  = (1<<20),
 -      IB_QP_SMAC                      = (1<<21),
 -      IB_QP_ALT_SMAC                  = (1<<22),
 -      IB_QP_VID                       = (1<<23),
 -      IB_QP_ALT_VID                   = (1<<24),
 +      IB_QP_RESERVED1                 = (1<<21),
 +      IB_QP_RESERVED2                 = (1<<22),
 +      IB_QP_RESERVED3                 = (1<<23),
 +      IB_QP_RESERVED4                 = (1<<24),
  };
  
  enum ib_qp_state {
@@@ -1010,6 -1010,10 +1010,6 @@@ struct ib_qp_attr 
        u8                      rnr_retry;
        u8                      alt_port_num;
        u8                      alt_timeout;
 -      u8                      smac[ETH_ALEN];
 -      u8                      alt_smac[ETH_ALEN];
 -      u16                     vlan_id;
 -      u16                     alt_vlan_id;
  };
  
  enum ib_wr_opcode {
@@@ -1096,54 -1100,93 +1096,93 @@@ struct ib_send_wr 
                __be32          imm_data;
                u32             invalidate_rkey;
        } ex;
-       union {
-               struct {
-                       u64     remote_addr;
-                       u32     rkey;
-               } rdma;
-               struct {
-                       u64     remote_addr;
-                       u64     compare_add;
-                       u64     swap;
-                       u64     compare_add_mask;
-                       u64     swap_mask;
-                       u32     rkey;
-               } atomic;
-               struct {
-                       struct ib_ah *ah;
-                       void   *header;
-                       int     hlen;
-                       int     mss;
-                       u32     remote_qpn;
-                       u32     remote_qkey;
-                       u16     pkey_index; /* valid for GSI only */
-                       u8      port_num;   /* valid for DR SMPs on switch only */
-               } ud;
-               struct {
-                       u64                             iova_start;
-                       struct ib_fast_reg_page_list   *page_list;
-                       unsigned int                    page_shift;
-                       unsigned int                    page_list_len;
-                       u32                             length;
-                       int                             access_flags;
-                       u32                             rkey;
-               } fast_reg;
-               struct {
-                       struct ib_mw            *mw;
-                       /* The new rkey for the memory window. */
-                       u32                      rkey;
-                       struct ib_mw_bind_info   bind_info;
-               } bind_mw;
-               struct {
-                       struct ib_sig_attrs    *sig_attrs;
-                       struct ib_mr           *sig_mr;
-                       int                     access_flags;
-                       struct ib_sge          *prot;
-               } sig_handover;
-       } wr;
-       u32                     xrc_remote_srq_num;     /* XRC TGT QPs only */
  };
  
+ struct ib_rdma_wr {
+       struct ib_send_wr       wr;
+       u64                     remote_addr;
+       u32                     rkey;
+ };
+ static inline struct ib_rdma_wr *rdma_wr(struct ib_send_wr *wr)
+ {
+       return container_of(wr, struct ib_rdma_wr, wr);
+ }
+ struct ib_atomic_wr {
+       struct ib_send_wr       wr;
+       u64                     remote_addr;
+       u64                     compare_add;
+       u64                     swap;
+       u64                     compare_add_mask;
+       u64                     swap_mask;
+       u32                     rkey;
+ };
+ static inline struct ib_atomic_wr *atomic_wr(struct ib_send_wr *wr)
+ {
+       return container_of(wr, struct ib_atomic_wr, wr);
+ }
+ struct ib_ud_wr {
+       struct ib_send_wr       wr;
+       struct ib_ah            *ah;
+       void                    *header;
+       int                     hlen;
+       int                     mss;
+       u32                     remote_qpn;
+       u32                     remote_qkey;
+       u16                     pkey_index; /* valid for GSI only */
+       u8                      port_num;   /* valid for DR SMPs on switch only */
+ };
+ static inline struct ib_ud_wr *ud_wr(struct ib_send_wr *wr)
+ {
+       return container_of(wr, struct ib_ud_wr, wr);
+ }
+ struct ib_fast_reg_wr {
+       struct ib_send_wr       wr;
+       u64                     iova_start;
+       struct ib_fast_reg_page_list *page_list;
+       unsigned int            page_shift;
+       unsigned int            page_list_len;
+       u32                     length;
+       int                     access_flags;
+       u32                     rkey;
+ };
+ static inline struct ib_fast_reg_wr *fast_reg_wr(struct ib_send_wr *wr)
+ {
+       return container_of(wr, struct ib_fast_reg_wr, wr);
+ }
+ struct ib_bind_mw_wr {
+       struct ib_send_wr       wr;
+       struct ib_mw            *mw;
+       /* The new rkey for the memory window. */
+       u32                     rkey;
+       struct ib_mw_bind_info  bind_info;
+ };
+ static inline struct ib_bind_mw_wr *bind_mw_wr(struct ib_send_wr *wr)
+ {
+       return container_of(wr, struct ib_bind_mw_wr, wr);
+ }
+ struct ib_sig_handover_wr {
+       struct ib_send_wr       wr;
+       struct ib_sig_attrs    *sig_attrs;
+       struct ib_mr           *sig_mr;
+       int                     access_flags;
+       struct ib_sge          *prot;
+ };
+ static inline struct ib_sig_handover_wr *sig_handover_wr(struct ib_send_wr *wr)
+ {
+       return container_of(wr, struct ib_sig_handover_wr, wr);
+ }
  struct ib_recv_wr {
        struct ib_recv_wr      *next;
        u64                     wr_id;
@@@ -2172,8 -2215,7 +2211,8 @@@ static inline bool rdma_cap_roce_gid_ta
  }
  
  int ib_query_gid(struct ib_device *device,
 -               u8 port_num, int index, union ib_gid *gid);
 +               u8 port_num, int index, union ib_gid *gid,
 +               struct ib_gid_attr *attr);
  
  int ib_query_pkey(struct ib_device *device,
                  u8 port_num, u16 index, u16 *pkey);
@@@ -2187,7 -2229,7 +2226,7 @@@ int ib_modify_port(struct ib_device *de
                   struct ib_port_modify *port_modify);
  
  int ib_find_gid(struct ib_device *device, union ib_gid *gid,
 -              u8 *port_num, u16 *index);
 +              struct net_device *ndev, u8 *port_num, u16 *index);
  
  int ib_find_pkey(struct ib_device *device,
                 u8 port_num, u16 pkey, u16 *index);