Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 23 Jun 2015 22:53:26 +0000 (15:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 23 Jun 2015 22:53:26 +0000 (15:53 -0700)
Pull rdma updates from Doug Ledford:

 - a large cleanup of how device capabilities are checked for various
   features

 - additional cleanups in the MAD processing

 - update to the srp driver

 - creation and use of centralized log message helpers

 - add const to a number of args to calls and clean up call chain

 - add support for extended cq create verb

 - add support for timestamps on cq completion

 - add support for processing OPA MAD packets

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma: (92 commits)
  IB/mad: Add final OPA MAD processing
  IB/mad: Add partial Intel OPA MAD support
  IB/mad: Add partial Intel OPA MAD support
  IB/core: Add OPA MAD core capability flag
  IB/mad: Add support for additional MAD info to/from drivers
  IB/mad: Convert allocations from kmem_cache to kzalloc
  IB/core: Add ability for drivers to report an alternate MAD size.
  IB/mad: Support alternate Base Versions when creating MADs
  IB/mad: Create a generic helper for DR forwarding checks
  IB/mad: Create a generic helper for DR SMP Recv processing
  IB/mad: Create a generic helper for DR SMP Send processing
  IB/mad: Split IB SMI handling from MAD Recv handler
  IB/mad cleanup: Generalize processing of MAD data
  IB/mad cleanup: Clean up function params -- find_mad_agent
  IB/mlx4: Add support for CQ time-stamping
  IB/mlx4: Add mmap call to map the hardware clock
  IB/core: Pass hardware specific data in query_device
  IB/core: Add timestamp_mask and hca_core_clock to query_device
  IB/core: Extend ib_uverbs_create_cq
  IB/core: Add CQ creation time-stamping flag
  ...

1  2 
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/hw/ocrdma/ocrdma_ah.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c

index 0271608a51c40ff2ade721f94b710997ffbe5c2d,32063add9280d15348d98bfe14046f04709d6823..dbddddd6fb5d111e94e44e2800282c84312131a0
@@@ -267,7 -267,8 +267,8 @@@ static int cm_alloc_msg(struct cm_id_pr
        m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
                               cm_id_priv->av.pkey_index,
                               0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
-                              GFP_ATOMIC);
+                              GFP_ATOMIC,
+                              IB_MGMT_BASE_VERSION);
        if (IS_ERR(m)) {
                ib_destroy_ah(ah);
                return PTR_ERR(m);
@@@ -297,7 -298,8 +298,8 @@@ static int cm_alloc_response_msg(struc
  
        m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
                               0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
-                              GFP_ATOMIC);
+                              GFP_ATOMIC,
+                              IB_MGMT_BASE_VERSION);
        if (IS_ERR(m)) {
                ib_destroy_ah(ah);
                return PTR_ERR(m);
@@@ -861,7 -863,6 +863,7 @@@ retest
                cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
                break;
        case IB_CM_REQ_SENT:
 +      case IB_CM_MRA_REQ_RCVD:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                spin_unlock_irq(&cm_id_priv->lock);
                ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
                                       NULL, 0, NULL, 0);
                }
                break;
 -      case IB_CM_MRA_REQ_RCVD:
        case IB_CM_REP_SENT:
        case IB_CM_MRA_REP_RCVD:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
@@@ -3759,11 -3761,9 +3761,9 @@@ static void cm_add_one(struct ib_devic
        };
        unsigned long flags;
        int ret;
+       int count = 0;
        u8 i;
  
-       if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
-               return;
        cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
                         ib_device->phys_port_cnt, GFP_KERNEL);
        if (!cm_dev)
  
        set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
        for (i = 1; i <= ib_device->phys_port_cnt; i++) {
+               if (!rdma_cap_ib_cm(ib_device, i))
+                       continue;
                port = kzalloc(sizeof *port, GFP_KERNEL);
                if (!port)
                        goto error1;
                ret = ib_modify_port(ib_device, i, 0, &port_modify);
                if (ret)
                        goto error3;
+               count++;
        }
+       if (!count)
+               goto free;
        ib_set_client_data(ib_device, &cm_client, cm_dev);
  
        write_lock_irqsave(&cm.device_lock, flags);
@@@ -3824,11 -3833,15 +3833,15 @@@ error1
        port_modify.set_port_cap_mask = 0;
        port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
        while (--i) {
+               if (!rdma_cap_ib_cm(ib_device, i))
+                       continue;
                port = cm_dev->port[i-1];
                ib_modify_port(ib_device, port->port_num, 0, &port_modify);
                ib_unregister_mad_agent(port->mad_agent);
                cm_remove_port_fs(port);
        }
+ free:
        device_unregister(cm_dev->device);
        kfree(cm_dev);
  }
@@@ -3852,6 -3865,9 +3865,9 @@@ static void cm_remove_one(struct ib_dev
        write_unlock_irqrestore(&cm.device_lock, flags);
  
        for (i = 1; i <= ib_device->phys_port_cnt; i++) {
+               if (!rdma_cap_ib_cm(ib_device, i))
+                       continue;
                port = cm_dev->port[i-1];
                ib_modify_port(ib_device, port->port_num, 0, &port_modify);
                ib_unregister_mad_agent(port->mad_agent);
index 38ffe098150351aef9ff2ac650726ae7926f6856,3b943b700a639a89fc0b8f84c5a74b5ed74aa49c..143ded2bbe7c7fbd8d51a6d952aab1f7cf101b35
@@@ -65,6 -65,34 +65,34 @@@ MODULE_LICENSE("Dual BSD/GPL")
  #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
  #define CMA_IBOE_PACKET_LIFETIME 18
  
+ static const char * const cma_events[] = {
+       [RDMA_CM_EVENT_ADDR_RESOLVED]    = "address resolved",
+       [RDMA_CM_EVENT_ADDR_ERROR]       = "address error",
+       [RDMA_CM_EVENT_ROUTE_RESOLVED]   = "route resolved ",
+       [RDMA_CM_EVENT_ROUTE_ERROR]      = "route error",
+       [RDMA_CM_EVENT_CONNECT_REQUEST]  = "connect request",
+       [RDMA_CM_EVENT_CONNECT_RESPONSE] = "connect response",
+       [RDMA_CM_EVENT_CONNECT_ERROR]    = "connect error",
+       [RDMA_CM_EVENT_UNREACHABLE]      = "unreachable",
+       [RDMA_CM_EVENT_REJECTED]         = "rejected",
+       [RDMA_CM_EVENT_ESTABLISHED]      = "established",
+       [RDMA_CM_EVENT_DISCONNECTED]     = "disconnected",
+       [RDMA_CM_EVENT_DEVICE_REMOVAL]   = "device removal",
+       [RDMA_CM_EVENT_MULTICAST_JOIN]   = "multicast join",
+       [RDMA_CM_EVENT_MULTICAST_ERROR]  = "multicast error",
+       [RDMA_CM_EVENT_ADDR_CHANGE]      = "address change",
+       [RDMA_CM_EVENT_TIMEWAIT_EXIT]    = "timewait exit",
+ };
+ const char *rdma_event_msg(enum rdma_cm_event_type event)
+ {
+       size_t index = event;
+       return (index < ARRAY_SIZE(cma_events) && cma_events[index]) ?
+                       cma_events[index] : "unrecognized event";
+ }
+ EXPORT_SYMBOL(rdma_event_msg);
  static void cma_add_one(struct ib_device *device);
  static void cma_remove_one(struct ib_device *device);
  
@@@ -349,18 -377,35 +377,35 @@@ static int cma_translate_addr(struct so
        return ret;
  }
  
+ static inline int cma_validate_port(struct ib_device *device, u8 port,
+                                     union ib_gid *gid, int dev_type)
+ {
+       u8 found_port;
+       int ret = -ENODEV;
+       if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port))
+               return ret;
+       if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port))
+               return ret;
+       ret = ib_find_cached_gid(device, gid, &found_port, NULL);
+       if (port != found_port)
+               return -ENODEV;
+       return ret;
+ }
  static int cma_acquire_dev(struct rdma_id_private *id_priv,
                           struct rdma_id_private *listen_id_priv)
  {
        struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
        struct cma_device *cma_dev;
-       union ib_gid gid, iboe_gid;
+       union ib_gid gid, iboe_gid, *gidp;
        int ret = -ENODEV;
-       u8 port, found_port;
-       enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
-               IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
+       u8 port;
  
-       if (dev_ll != IB_LINK_LAYER_INFINIBAND &&
+       if (dev_addr->dev_type != ARPHRD_INFINIBAND &&
            id_priv->id.ps == RDMA_PS_IPOIB)
                return -EINVAL;
  
  
        memcpy(&gid, dev_addr->src_dev_addr +
               rdma_addr_gid_offset(dev_addr), sizeof gid);
-       if (listen_id_priv &&
-           rdma_port_get_link_layer(listen_id_priv->id.device,
-                                    listen_id_priv->id.port_num) == dev_ll) {
+       if (listen_id_priv) {
                cma_dev = listen_id_priv->cma_dev;
                port = listen_id_priv->id.port_num;
-               if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB &&
-                   rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET)
-                       ret = ib_find_cached_gid(cma_dev->device, &iboe_gid,
-                                                &found_port, NULL);
-               else
-                       ret = ib_find_cached_gid(cma_dev->device, &gid,
-                                                &found_port, NULL);
+               gidp = rdma_protocol_roce(cma_dev->device, port) ?
+                      &iboe_gid : &gid;
  
-               if (!ret && (port  == found_port)) {
-                       id_priv->id.port_num = found_port;
+               ret = cma_validate_port(cma_dev->device, port, gidp,
+                                       dev_addr->dev_type);
+               if (!ret) {
+                       id_priv->id.port_num = port;
                        goto out;
                }
        }
        list_for_each_entry(cma_dev, &dev_list, list) {
                for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) {
                        if (listen_id_priv &&
                            listen_id_priv->cma_dev == cma_dev &&
                            listen_id_priv->id.port_num == port)
                                continue;
-                       if (rdma_port_get_link_layer(cma_dev->device, port) == dev_ll) {
-                               if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB &&
-                                   rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET)
-                                       ret = ib_find_cached_gid(cma_dev->device, &iboe_gid, &found_port, NULL);
-                               else
-                                       ret = ib_find_cached_gid(cma_dev->device, &gid, &found_port, NULL);
-                               if (!ret && (port == found_port)) {
-                                       id_priv->id.port_num = found_port;
-                                       goto out;
-                               }
+                       gidp = rdma_protocol_roce(cma_dev->device, port) ?
+                              &iboe_gid : &gid;
+                       ret = cma_validate_port(cma_dev->device, port, gidp,
+                                               dev_addr->dev_type);
+                       if (!ret) {
+                               id_priv->id.port_num = port;
+                               goto out;
                        }
                }
        }
@@@ -435,10 -475,10 +475,10 @@@ static int cma_resolve_ib_dev(struct rd
        pkey = ntohs(addr->sib_pkey);
  
        list_for_each_entry(cur_dev, &dev_list, list) {
-               if (rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB)
-                       continue;
                for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) {
+                       if (!rdma_cap_af_ib(cur_dev->device, p))
+                               continue;
                        if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index))
                                continue;
  
@@@ -633,10 -673,9 +673,9 @@@ static int cma_modify_qp_rtr(struct rdm
        if (ret)
                goto out;
  
-       if (rdma_node_get_transport(id_priv->cma_dev->device->node_type)
-           == RDMA_TRANSPORT_IB &&
-           rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)
-           == IB_LINK_LAYER_ETHERNET) {
+       BUG_ON(id_priv->cma_dev->device != id_priv->id.device);
+       if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
                ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL);
  
                if (ret)
@@@ -700,11 -739,10 +739,10 @@@ static int cma_ib_init_qp_attr(struct r
        int ret;
        u16 pkey;
  
-       if (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) ==
-           IB_LINK_LAYER_INFINIBAND)
-               pkey = ib_addr_get_pkey(dev_addr);
-       else
+       if (rdma_cap_eth_ah(id_priv->id.device, id_priv->id.port_num))
                pkey = 0xffff;
+       else
+               pkey = ib_addr_get_pkey(dev_addr);
  
        ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
                                  pkey, &qp_attr->pkey_index);
@@@ -735,8 -773,7 +773,7 @@@ int rdma_init_qp_attr(struct rdma_cm_i
        int ret = 0;
  
        id_priv = container_of(id, struct rdma_id_private, id);
-       switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
-       case RDMA_TRANSPORT_IB:
+       if (rdma_cap_ib_cm(id->device, id->port_num)) {
                if (!id_priv->cm_id.ib || (id_priv->id.qp_type == IB_QPT_UD))
                        ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
                else
  
                if (qp_attr->qp_state == IB_QPS_RTR)
                        qp_attr->rq_psn = id_priv->seq_num;
-               break;
-       case RDMA_TRANSPORT_IWARP:
+       } else if (rdma_cap_iw_cm(id->device, id->port_num)) {
                if (!id_priv->cm_id.iw) {
                        qp_attr->qp_access_flags = 0;
                        *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
                } else
                        ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
                                                 qp_attr_mask);
-               break;
-       default:
+       } else
                ret = -ENOSYS;
-               break;
-       }
  
        return ret;
  }
@@@ -845,26 -878,18 +878,26 @@@ static void cma_save_ib_info(struct rdm
        listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr;
        ib = (struct sockaddr_ib *) &id->route.addr.src_addr;
        ib->sib_family = listen_ib->sib_family;
 -      ib->sib_pkey = path->pkey;
 -      ib->sib_flowinfo = path->flow_label;
 -      memcpy(&ib->sib_addr, &path->sgid, 16);
 +      if (path) {
 +              ib->sib_pkey = path->pkey;
 +              ib->sib_flowinfo = path->flow_label;
 +              memcpy(&ib->sib_addr, &path->sgid, 16);
 +      } else {
 +              ib->sib_pkey = listen_ib->sib_pkey;
 +              ib->sib_flowinfo = listen_ib->sib_flowinfo;
 +              ib->sib_addr = listen_ib->sib_addr;
 +      }
        ib->sib_sid = listen_ib->sib_sid;
        ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL);
        ib->sib_scope_id = listen_ib->sib_scope_id;
  
 -      ib = (struct sockaddr_ib *) &id->route.addr.dst_addr;
 -      ib->sib_family = listen_ib->sib_family;
 -      ib->sib_pkey = path->pkey;
 -      ib->sib_flowinfo = path->flow_label;
 -      memcpy(&ib->sib_addr, &path->dgid, 16);
 +      if (path) {
 +              ib = (struct sockaddr_ib *) &id->route.addr.dst_addr;
 +              ib->sib_family = listen_ib->sib_family;
 +              ib->sib_pkey = path->pkey;
 +              ib->sib_flowinfo = path->flow_label;
 +              memcpy(&ib->sib_addr, &path->dgid, 16);
 +      }
  }
  
  static __be16 ss_get_port(const struct sockaddr_storage *ss)
@@@ -913,11 -938,9 +946,11 @@@ static int cma_save_net_info(struct rdm
  {
        struct cma_hdr *hdr;
  
 -      if ((listen_id->route.addr.src_addr.ss_family == AF_IB) &&
 -          (ib_event->event == IB_CM_REQ_RECEIVED)) {
 -              cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path);
 +      if (listen_id->route.addr.src_addr.ss_family == AF_IB) {
 +              if (ib_event->event == IB_CM_REQ_RECEIVED)
 +                      cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path);
 +              else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED)
 +                      cma_save_ib_info(id, listen_id, NULL);
                return 0;
        }
  
@@@ -945,13 -968,9 +978,9 @@@ static inline int cma_user_data_offset(
  
  static void cma_cancel_route(struct rdma_id_private *id_priv)
  {
-       switch (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)) {
-       case IB_LINK_LAYER_INFINIBAND:
+       if (rdma_cap_ib_sa(id_priv->id.device, id_priv->id.port_num)) {
                if (id_priv->query)
                        ib_sa_cancel_query(id_priv->query_id, id_priv->query);
-               break;
-       default:
-               break;
        }
  }
  
@@@ -1023,17 -1042,12 +1052,12 @@@ static void cma_leave_mc_groups(struct 
                mc = container_of(id_priv->mc_list.next,
                                  struct cma_multicast, list);
                list_del(&mc->list);
-               switch (rdma_port_get_link_layer(id_priv->cma_dev->device, id_priv->id.port_num)) {
-               case IB_LINK_LAYER_INFINIBAND:
+               if (rdma_cap_ib_mcast(id_priv->cma_dev->device,
+                                     id_priv->id.port_num)) {
                        ib_sa_free_multicast(mc->multicast.ib);
                        kfree(mc);
-                       break;
-               case IB_LINK_LAYER_ETHERNET:
+               } else
                        kref_put(&mc->mcref, release_mc);
-                       break;
-               default:
-                       break;
-               }
        }
  }
  
@@@ -1054,17 -1068,12 +1078,12 @@@ void rdma_destroy_id(struct rdma_cm_id 
        mutex_unlock(&id_priv->handler_mutex);
  
        if (id_priv->cma_dev) {
-               switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
-               case RDMA_TRANSPORT_IB:
+               if (rdma_cap_ib_cm(id_priv->id.device, 1)) {
                        if (id_priv->cm_id.ib)
                                ib_destroy_cm_id(id_priv->cm_id.ib);
-                       break;
-               case RDMA_TRANSPORT_IWARP:
+               } else if (rdma_cap_iw_cm(id_priv->id.device, 1)) {
                        if (id_priv->cm_id.iw)
                                iw_destroy_cm_id(id_priv->cm_id.iw);
-                       break;
-               default:
-                       break;
                }
                cma_leave_mc_groups(id_priv);
                cma_release_dev(id_priv);
@@@ -1610,6 -1619,7 +1629,7 @@@ static int cma_iw_listen(struct rdma_id
        if (IS_ERR(id))
                return PTR_ERR(id);
  
+       id->tos = id_priv->tos;
        id_priv->cm_id.iw = id;
  
        memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv),
@@@ -1642,8 -1652,7 +1662,7 @@@ static void cma_listen_on_dev(struct rd
        struct rdma_cm_id *id;
        int ret;
  
-       if (cma_family(id_priv) == AF_IB &&
-           rdma_node_get_transport(cma_dev->device->node_type) != RDMA_TRANSPORT_IB)
+       if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
                return;
  
        id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps,
@@@ -1984,26 -1993,15 +2003,15 @@@ int rdma_resolve_route(struct rdma_cm_i
                return -EINVAL;
  
        atomic_inc(&id_priv->refcount);
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
-               switch (rdma_port_get_link_layer(id->device, id->port_num)) {
-               case IB_LINK_LAYER_INFINIBAND:
-                       ret = cma_resolve_ib_route(id_priv, timeout_ms);
-                       break;
-               case IB_LINK_LAYER_ETHERNET:
-                       ret = cma_resolve_iboe_route(id_priv);
-                       break;
-               default:
-                       ret = -ENOSYS;
-               }
-               break;
-       case RDMA_TRANSPORT_IWARP:
+       if (rdma_cap_ib_sa(id->device, id->port_num))
+               ret = cma_resolve_ib_route(id_priv, timeout_ms);
+       else if (rdma_protocol_roce(id->device, id->port_num))
+               ret = cma_resolve_iboe_route(id_priv);
+       else if (rdma_protocol_iwarp(id->device, id->port_num))
                ret = cma_resolve_iw_route(id_priv, timeout_ms);
-               break;
-       default:
+       else
                ret = -ENOSYS;
-               break;
-       }
        if (ret)
                goto err;
  
@@@ -2045,7 -2043,7 +2053,7 @@@ static int cma_bind_loopback(struct rdm
        mutex_lock(&lock);
        list_for_each_entry(cur_dev, &dev_list, list) {
                if (cma_family(id_priv) == AF_IB &&
-                   rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB)
+                   !rdma_cap_ib_cm(cur_dev->device, 1))
                        continue;
  
                if (!cma_dev)
@@@ -2077,7 -2075,7 +2085,7 @@@ port_found
                goto out;
  
        id_priv->id.route.addr.dev_addr.dev_type =
-               (rdma_port_get_link_layer(cma_dev->device, p) == IB_LINK_LAYER_INFINIBAND) ?
+               (rdma_protocol_ib(cma_dev->device, p)) ?
                ARPHRD_INFINIBAND : ARPHRD_ETHER;
  
        rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
@@@ -2554,18 -2552,15 +2562,15 @@@ int rdma_listen(struct rdma_cm_id *id, 
  
        id_priv->backlog = backlog;
        if (id->device) {
-               switch (rdma_node_get_transport(id->device->node_type)) {
-               case RDMA_TRANSPORT_IB:
+               if (rdma_cap_ib_cm(id->device, 1)) {
                        ret = cma_ib_listen(id_priv);
                        if (ret)
                                goto err;
-                       break;
-               case RDMA_TRANSPORT_IWARP:
+               } else if (rdma_cap_iw_cm(id->device, 1)) {
                        ret = cma_iw_listen(id_priv, backlog);
                        if (ret)
                                goto err;
-                       break;
-               default:
+               } else {
                        ret = -ENOSYS;
                        goto err;
                }
@@@ -2857,6 -2852,7 +2862,7 @@@ static int cma_connect_iw(struct rdma_i
        if (IS_ERR(cm_id))
                return PTR_ERR(cm_id);
  
+       cm_id->tos = id_priv->tos;
        id_priv->cm_id.iw = cm_id;
  
        memcpy(&cm_id->local_addr, cma_src_addr(id_priv),
@@@ -2901,20 -2897,15 +2907,15 @@@ int rdma_connect(struct rdma_cm_id *id
                id_priv->srq = conn_param->srq;
        }
  
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
+       if (rdma_cap_ib_cm(id->device, id->port_num)) {
                if (id->qp_type == IB_QPT_UD)
                        ret = cma_resolve_ib_udp(id_priv, conn_param);
                else
                        ret = cma_connect_ib(id_priv, conn_param);
-               break;
-       case RDMA_TRANSPORT_IWARP:
+       } else if (rdma_cap_iw_cm(id->device, id->port_num))
                ret = cma_connect_iw(id_priv, conn_param);
-               break;
-       default:
+       else
                ret = -ENOSYS;
-               break;
-       }
        if (ret)
                goto err;
  
@@@ -3017,8 -3008,7 +3018,7 @@@ int rdma_accept(struct rdma_cm_id *id, 
                id_priv->srq = conn_param->srq;
        }
  
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
+       if (rdma_cap_ib_cm(id->device, id->port_num)) {
                if (id->qp_type == IB_QPT_UD) {
                        if (conn_param)
                                ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
                        else
                                ret = cma_rep_recv(id_priv);
                }
-               break;
-       case RDMA_TRANSPORT_IWARP:
+       } else if (rdma_cap_iw_cm(id->device, id->port_num))
                ret = cma_accept_iw(id_priv, conn_param);
-               break;
-       default:
+       else
                ret = -ENOSYS;
-               break;
-       }
  
        if (ret)
                goto reject;
@@@ -3085,8 -3071,7 +3081,7 @@@ int rdma_reject(struct rdma_cm_id *id, 
        if (!id_priv->cm_id.ib)
                return -EINVAL;
  
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
+       if (rdma_cap_ib_cm(id->device, id->port_num)) {
                if (id->qp_type == IB_QPT_UD)
                        ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, 0,
                                                private_data, private_data_len);
                        ret = ib_send_cm_rej(id_priv->cm_id.ib,
                                             IB_CM_REJ_CONSUMER_DEFINED, NULL,
                                             0, private_data, private_data_len);
-               break;
-       case RDMA_TRANSPORT_IWARP:
+       } else if (rdma_cap_iw_cm(id->device, id->port_num)) {
                ret = iw_cm_reject(id_priv->cm_id.iw,
                                   private_data, private_data_len);
-               break;
-       default:
+       } else
                ret = -ENOSYS;
-               break;
-       }
        return ret;
  }
  EXPORT_SYMBOL(rdma_reject);
@@@ -3116,22 -3098,18 +3108,18 @@@ int rdma_disconnect(struct rdma_cm_id *
        if (!id_priv->cm_id.ib)
                return -EINVAL;
  
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
+       if (rdma_cap_ib_cm(id->device, id->port_num)) {
                ret = cma_modify_qp_err(id_priv);
                if (ret)
                        goto out;
                /* Initiate or respond to a disconnect. */
                if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
                        ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
-               break;
-       case RDMA_TRANSPORT_IWARP:
+       } else if (rdma_cap_iw_cm(id->device, id->port_num)) {
                ret = iw_cm_disconnect(id_priv->cm_id.iw, 0);
-               break;
-       default:
+       } else
                ret = -EINVAL;
-               break;
-       }
  out:
        return ret;
  }
@@@ -3377,24 -3355,13 +3365,13 @@@ int rdma_join_multicast(struct rdma_cm_
        list_add(&mc->list, &id_priv->mc_list);
        spin_unlock(&id_priv->lock);
  
-       switch (rdma_node_get_transport(id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
-               switch (rdma_port_get_link_layer(id->device, id->port_num)) {
-               case IB_LINK_LAYER_INFINIBAND:
-                       ret = cma_join_ib_multicast(id_priv, mc);
-                       break;
-               case IB_LINK_LAYER_ETHERNET:
-                       kref_init(&mc->mcref);
-                       ret = cma_iboe_join_multicast(id_priv, mc);
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-               break;
-       default:
+       if (rdma_protocol_roce(id->device, id->port_num)) {
+               kref_init(&mc->mcref);
+               ret = cma_iboe_join_multicast(id_priv, mc);
+       } else if (rdma_cap_ib_mcast(id->device, id->port_num))
+               ret = cma_join_ib_multicast(id_priv, mc);
+       else
                ret = -ENOSYS;
-               break;
-       }
  
        if (ret) {
                spin_lock_irq(&id_priv->lock);
@@@ -3422,19 -3389,15 +3399,15 @@@ void rdma_leave_multicast(struct rdma_c
                                ib_detach_mcast(id->qp,
                                                &mc->multicast.ib->rec.mgid,
                                                be16_to_cpu(mc->multicast.ib->rec.mlid));
-                       if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) {
-                               switch (rdma_port_get_link_layer(id->device, id->port_num)) {
-                               case IB_LINK_LAYER_INFINIBAND:
-                                       ib_sa_free_multicast(mc->multicast.ib);
-                                       kfree(mc);
-                                       break;
-                               case IB_LINK_LAYER_ETHERNET:
-                                       kref_put(&mc->mcref, release_mc);
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
+                       BUG_ON(id_priv->cma_dev->device != id->device);
+                       if (rdma_cap_ib_mcast(id->device, id->port_num)) {
+                               ib_sa_free_multicast(mc->multicast.ib);
+                               kfree(mc);
+                       } else if (rdma_protocol_roce(id->device, id->port_num))
+                               kref_put(&mc->mcref, release_mc);
                        return;
                }
        }
index f5a5ea836dbdc9fe4f12e6f26e1acca5dac3c6d1,5f8a8dd423fc6eac921cb02d400e249629a917bf..4bafa15708d0fc4212587cb4dfd6fce7d3f3211b
@@@ -56,13 -56,7 +56,13 @@@ static inline int set_av_attr(struct oc
        vlan_tag = attr->vlan_id;
        if (!vlan_tag || (vlan_tag > 0xFFF))
                vlan_tag = dev->pvid;
 -      if (vlan_tag && (vlan_tag < 0x1000)) {
 +      if (vlan_tag || dev->pfc_state) {
 +              if (!vlan_tag) {
 +                      pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
 +                              dev->id);
 +                      pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
 +                              dev->id);
 +              }
                eth.eth_type = cpu_to_be16(0x8100);
                eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
                vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
@@@ -127,9 -121,7 +127,9 @@@ struct ib_ah *ocrdma_create_ah(struct i
                goto av_conf_err;
        }
  
 -      if (pd->uctx) {
 +      if ((pd->uctx) &&
 +          (!rdma_is_multicast_addr((struct in6_addr *)attr->grh.dgid.raw)) &&
 +          (!rdma_link_local_addr((struct in6_addr *)attr->grh.dgid.raw))) {
                status = rdma_addr_find_dmac_by_grh(&sgid, &attr->grh.dgid,
                                          attr->dmac, &attr->vlan_id);
                if (status) {
@@@ -204,12 -196,19 +204,19 @@@ int ocrdma_modify_ah(struct ib_ah *ibah
  int ocrdma_process_mad(struct ib_device *ibdev,
                       int process_mad_flags,
                       u8 port_num,
-                      struct ib_wc *in_wc,
-                      struct ib_grh *in_grh,
-                      struct ib_mad *in_mad, struct ib_mad *out_mad)
+                      const struct ib_wc *in_wc,
+                      const struct ib_grh *in_grh,
+                      const struct ib_mad_hdr *in, size_t in_mad_size,
+                      struct ib_mad_hdr *out, size_t *out_mad_size,
+                      u16 *out_mad_pkey_index)
  {
        int status;
        struct ocrdma_dev *dev;
+       const struct ib_mad *in_mad = (const struct ib_mad *)in;
+       struct ib_mad *out_mad = (struct ib_mad *)out;
+       BUG_ON(in_mad_size != sizeof(*in_mad) ||
+              *out_mad_size != sizeof(*out_mad));
  
        switch (in_mad->mad_hdr.mgmt_class) {
        case IB_MGMT_CLASS_PERF_MGMT:
index 9dcb66077d6cbf9cd37bdaaa594414aadee4c96f,aab120280907964dd1c26c51d5d116a9e503e616..5bb61eb58f2c71859969d73ac6e326d4dafc51fd
@@@ -61,10 -61,14 +61,14 @@@ int ocrdma_query_gid(struct ib_device *
        return 0;
  }
  
- int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr)
+ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
+                       struct ib_udata *uhw)
  {
        struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
  
+       if (uhw->inlen || uhw->outlen)
+               return -EINVAL;
        memset(attr, 0, sizeof *attr);
        memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
               min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver)));
@@@ -365,7 -369,7 +369,7 @@@ static struct ocrdma_pd *_ocrdma_alloc_
        if (!pd)
                return ERR_PTR(-ENOMEM);
  
 -      if (udata && uctx) {
 +      if (udata && uctx && dev->attr.max_dpp_pds) {
                pd->dpp_enabled =
                        ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R;
                pd->num_dpp_qp =
  
        if (dev->pd_mgr->pd_prealloc_valid) {
                status = ocrdma_get_pd_num(dev, pd);
-               return (status == 0) ? pd : ERR_PTR(status);
+               if (status == 0) {
+                       return pd;
+               } else {
+                       kfree(pd);
+                       return ERR_PTR(status);
+               }
        }
  
  retry:
@@@ -679,7 -688,6 +688,6 @@@ err
                ocrdma_release_ucontext_pd(uctx);
        } else {
                status = _ocrdma_dealloc_pd(dev, pd);
-               kfree(pd);
        }
  exit:
        return ERR_PTR(status);
        return status;
  }
  
- struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector,
+ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev,
+                              const struct ib_cq_init_attr *attr,
                               struct ib_ucontext *ib_ctx,
                               struct ib_udata *udata)
  {
+       int entries = attr->cqe;
        struct ocrdma_cq *cq;
        struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
        struct ocrdma_ucontext *uctx = NULL;
        int status;
        struct ocrdma_create_cq_ureq ureq;
  
+       if (attr->flags)
+               return ERR_PTR(-EINVAL);
        if (udata) {
                if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
                        return ERR_PTR(-EFAULT);
@@@ -1721,20 -1734,18 +1734,20 @@@ int ocrdma_destroy_qp(struct ib_qp *ibq
        struct ocrdma_qp *qp;
        struct ocrdma_dev *dev;
        struct ib_qp_attr attrs;
 -      int attr_mask = IB_QP_STATE;
 +      int attr_mask;
        unsigned long flags;
  
        qp = get_ocrdma_qp(ibqp);
        dev = get_ocrdma_dev(ibqp->device);
  
 -      attrs.qp_state = IB_QPS_ERR;
        pd = qp->pd;
  
        /* change the QP state to ERROR */
 -      _ocrdma_modify_qp(ibqp, &attrs, attr_mask);
 -
 +      if (qp->state != OCRDMA_QPS_RST) {
 +              attrs.qp_state = IB_QPS_ERR;
 +              attr_mask = IB_QP_STATE;
 +              _ocrdma_modify_qp(ibqp, &attrs, attr_mask);
 +      }
        /* ensure that CQEs for newly created QP (whose id may be same with
         * one which just getting destroyed are same), dont get
         * discarded until the old CQEs are discarded.
index 575a072d765f65cc49190a3066218759bd3569cd,9e7b4927265c76eadcdc8507188a15e8e0d99a71..f3b7a34e10d81c019217917ac6ebce0462278b50
@@@ -65,8 -65,6 +65,8 @@@ static in
  isert_rdma_accept(struct isert_conn *isert_conn);
  struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
  
 +static void isert_release_work(struct work_struct *work);
 +
  static inline bool
  isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
  {
@@@ -80,7 -78,9 +80,9 @@@ isert_qp_event_callback(struct ib_even
  {
        struct isert_conn *isert_conn = context;
  
-       isert_err("conn %p event: %d\n", isert_conn, e->event);
+       isert_err("%s (%d): conn %p\n",
+                 ib_event_msg(e->event), e->event, isert_conn);
        switch (e->event) {
        case IB_EVENT_COMM_EST:
                rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST);
@@@ -318,15 -318,18 +320,18 @@@ isert_alloc_comps(struct isert_device *
        max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe);
  
        for (i = 0; i < device->comps_used; i++) {
+               struct ib_cq_init_attr cq_attr = {};
                struct isert_comp *comp = &device->comps[i];
  
                comp->device = device;
                INIT_WORK(&comp->work, isert_cq_work);
+               cq_attr.cqe = max_cqe;
+               cq_attr.comp_vector = i;
                comp->cq = ib_create_cq(device->ib_device,
                                        isert_cq_callback,
                                        isert_cq_event_callback,
                                        (void *)comp,
-                                       max_cqe, i);
+                                       &cq_attr);
                if (IS_ERR(comp->cq)) {
                        isert_err("Unable to allocate cq\n");
                        ret = PTR_ERR(comp->cq);
@@@ -549,11 -552,11 +554,11 @@@ isert_create_pi_ctx(struct fast_reg_des
        return 0;
  
  err_prot_mr:
 -      ib_dereg_mr(desc->pi_ctx->prot_mr);
 +      ib_dereg_mr(pi_ctx->prot_mr);
  err_prot_frpl:
 -      ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl);
 +      ib_free_fast_reg_page_list(pi_ctx->prot_frpl);
  err_pi_ctx:
 -      kfree(desc->pi_ctx);
 +      kfree(pi_ctx);
  
        return ret;
  }
@@@ -650,7 -653,6 +655,7 @@@ isert_init_conn(struct isert_conn *iser
        mutex_init(&isert_conn->mutex);
        spin_lock_init(&isert_conn->pool_lock);
        INIT_LIST_HEAD(&isert_conn->fr_pool);
 +      INIT_WORK(&isert_conn->release_work, isert_release_work);
  }
  
  static void
@@@ -900,7 -902,8 +905,8 @@@ static in
  isert_np_cma_handler(struct isert_np *isert_np,
                     enum rdma_cm_event_type event)
  {
-       isert_dbg("isert np %p, handling event %d\n", isert_np, event);
+       isert_dbg("%s (%d): isert np %p\n",
+                 rdma_event_msg(event), event, isert_np);
  
        switch (event) {
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
@@@ -928,7 -931,6 +934,7 @@@ isert_disconnected_handler(struct rdma_
  {
        struct isert_np *isert_np = cma_id->context;
        struct isert_conn *isert_conn;
 +      bool terminating = false;
  
        if (isert_np->np_cm_id == cma_id)
                return isert_np_cma_handler(cma_id->context, event);
        isert_conn = cma_id->qp->qp_context;
  
        mutex_lock(&isert_conn->mutex);
 +      terminating = (isert_conn->state == ISER_CONN_TERMINATING);
        isert_conn_terminate(isert_conn);
        mutex_unlock(&isert_conn->mutex);
  
        isert_info("conn %p completing wait\n", isert_conn);
        complete(&isert_conn->wait);
  
 +      if (terminating)
 +              goto out;
 +
 +      mutex_lock(&isert_np->np_accept_mutex);
 +      if (!list_empty(&isert_conn->accept_node)) {
 +              list_del_init(&isert_conn->accept_node);
 +              isert_put_conn(isert_conn);
 +              queue_work(isert_release_wq, &isert_conn->release_work);
 +      }
 +      mutex_unlock(&isert_np->np_accept_mutex);
 +
 +out:
        return 0;
  }
  
@@@ -974,7 -963,8 +980,8 @@@ isert_cma_handler(struct rdma_cm_id *cm
  {
        int ret = 0;
  
-       isert_info("event %d status %d id %p np %p\n", event->event,
+       isert_info("%s (%d): status %d id %p np %p\n",
+                  rdma_event_msg(event->event), event->event,
                   event->status, cma_id, cma_id->context);
  
        switch (event->event) {
@@@ -2108,10 -2098,13 +2115,13 @@@ isert_handle_wc(struct ib_wc *wc
                }
        } else {
                if (wc->status != IB_WC_WR_FLUSH_ERR)
-                       isert_err("wr id %llx status %d vend_err %x\n",
-                                 wc->wr_id, wc->status, wc->vendor_err);
+                       isert_err("%s (%d): wr id %llx vend_err %x\n",
+                                 ib_wc_status_msg(wc->status), wc->status,
+                                 wc->wr_id, wc->vendor_err);
                else
-                       isert_dbg("flush error: wr id %llx\n", wc->wr_id);
+                       isert_dbg("%s (%d): wr id %llx\n",
+                                 ib_wc_status_msg(wc->status), wc->status,
+                                 wc->wr_id);
  
                if (wc->wr_id != ISER_FASTREG_LI_WRID)
                        isert_cq_comp_err(isert_conn, wc);
@@@ -2397,6 -2390,7 +2407,6 @@@ isert_build_rdma_wr(struct isert_conn *
        page_off = offset % PAGE_SIZE;
  
        send_wr->sg_list = ib_sge;
 -      send_wr->num_sge = sg_nents;
        send_wr->wr_id = (uintptr_t)&isert_cmd->tx_desc;
        /*
         * Perform mapping of TCM scatterlist memory ib_sge dma_addr.
                          ib_sge->addr, ib_sge->length, ib_sge->lkey);
                page_off = 0;
                data_left -= ib_sge->length;
 +              if (!data_left)
 +                      break;
                ib_sge++;
                isert_dbg("Incrementing ib_sge pointer to %p\n", ib_sge);
        }
  
 +      send_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);
  
 -      return sg_nents;
 +      return send_wr->num_sge;
  }
  
  static int
@@@ -3385,6 -3376,7 +3395,6 @@@ static void isert_wait_conn(struct iscs
        isert_wait4flush(isert_conn);
        isert_wait4logout(isert_conn);
  
 -      INIT_WORK(&isert_conn->release_work, isert_release_work);
        queue_work(isert_release_wq, &isert_conn->release_work);
  }
  
@@@ -3392,7 -3384,6 +3402,7 @@@ static void isert_free_conn(struct iscs
  {
        struct isert_conn *isert_conn = conn->context;
  
 +      isert_wait4flush(isert_conn);
        isert_put_conn(isert_conn);
  }