Merge branch 'for-4.2-misc' into k.o/for-4.2
authorDoug Ledford <dledford@redhat.com>
Tue, 2 Jun 2015 13:33:22 +0000 (09:33 -0400)
committerDoug Ledford <dledford@redhat.com>
Tue, 2 Jun 2015 13:33:22 +0000 (09:33 -0400)
1  2 
drivers/infiniband/core/cma.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
net/rds/ib_send.c
net/rds/rds.h

@@@ -65,34 -65,6 +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);
  
@@@ -377,35 -349,18 +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;
                        }
                }
        }
@@@ -475,10 -435,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;
  
@@@ -673,9 -633,10 +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)
@@@ -739,10 -700,11 +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);
@@@ -773,7 -735,8 +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;
  }
@@@ -968,9 -935,13 +968,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;
        }
  }
  
@@@ -1042,12 -1013,17 +1042,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;
 -              }
        }
  }
  
@@@ -1068,12 -1044,17 +1068,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);
@@@ -1619,6 -1600,7 +1619,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),
@@@ -1651,7 -1633,8 +1652,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,
@@@ -1992,15 -1975,26 +1993,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;
  
@@@ -2042,7 -2036,7 +2043,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)
@@@ -2074,7 -2068,7 +2075,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);
@@@ -2551,15 -2545,18 +2552,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;
                }
@@@ -2851,6 -2848,7 +2852,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),
@@@ -2895,15 -2893,20 +2897,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;
  
@@@ -3006,7 -3009,8 +3008,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;
@@@ -3069,7 -3077,8 +3071,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);
@@@ -3096,18 -3108,22 +3098,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;
  }
@@@ -3353,13 -3369,24 +3355,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);
@@@ -3387,15 -3414,19 +3389,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;
                }
        }
@@@ -1185,7 -1185,6 +1185,6 @@@ static struct ib_flow *mlx4_ib_create_f
                                            &mflow->reg_id[i].id);
                if (err)
                        goto err_create_flow;
-               i++;
                if (is_bonded) {
                        /* Application always sees one port so the mirror rule
                         * must be on port #2
                        j++;
                }
  
+               i++;
        }
  
        if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
                                               &mflow->reg_id[i].id);
                if (err)
                        goto err_create_flow;
-               i++;
                if (is_bonded) {
                        flow_attr->port = 2;
                        err = mlx4_ib_tunnel_steer_add(qp, flow_attr,
                        j++;
                }
                /* function to create mirror rule */
+               i++;
        }
  
        return &mflow->ibflow;
@@@ -2114,27 -2115,6 +2115,27 @@@ static void mlx4_ib_free_eqs(struct mlx
        kfree(ibdev->eq_table);
  }
  
 +static int mlx4_port_immutable(struct ib_device *ibdev, u8 port_num,
 +                             struct ib_port_immutable *immutable)
 +{
 +      struct ib_port_attr attr;
 +      int err;
 +
 +      err = mlx4_ib_query_port(ibdev, port_num, &attr);
 +      if (err)
 +              return err;
 +
 +      immutable->pkey_tbl_len = attr.pkey_tbl_len;
 +      immutable->gid_tbl_len = attr.gid_tbl_len;
 +
 +      if (mlx4_ib_port_link_layer(ibdev, port_num) == IB_LINK_LAYER_INFINIBAND)
 +              immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
 +      else
 +              immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
 +
 +      return 0;
 +}
 +
  static void *mlx4_ib_add(struct mlx4_dev *dev)
  {
        struct mlx4_ib_dev *ibdev;
        ibdev->ib_dev.attach_mcast      = mlx4_ib_mcg_attach;
        ibdev->ib_dev.detach_mcast      = mlx4_ib_mcg_detach;
        ibdev->ib_dev.process_mad       = mlx4_ib_process_mad;
 +      ibdev->ib_dev.get_port_immutable = mlx4_port_immutable;
  
        if (!mlx4_is_slave(ibdev->dev)) {
                ibdev->ib_dev.alloc_fmr         = mlx4_ib_fmr_alloc;
@@@ -1128,7 -1128,7 +1128,7 @@@ static int ipoib_neigh_hash_init(struc
  {
        struct ipoib_neigh_table *ntbl = &priv->ntbl;
        struct ipoib_neigh_hash *htbl;
-       struct ipoib_neigh **buckets;
+       struct ipoib_neigh __rcu **buckets;
        u32 size;
  
        clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
        htbl->size = size;
        htbl->mask = (size - 1);
        htbl->buckets = buckets;
-       ntbl->htbl = htbl;
+       RCU_INIT_POINTER(ntbl->htbl, htbl);
        htbl->ntbl = ntbl;
        atomic_set(&ntbl->entries, 0);
  
@@@ -1685,7 -1685,9 +1685,7 @@@ static void ipoib_add_one(struct ib_dev
        struct net_device *dev;
        struct ipoib_dev_priv *priv;
        int s, e, p;
 -
 -      if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
 -              return;
 +      int count = 0;
  
        dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
        if (!dev_list)
        }
  
        for (p = s; p <= e; ++p) {
 -              if (rdma_port_get_link_layer(device, p) != IB_LINK_LAYER_INFINIBAND)
 +              if (!rdma_protocol_ib(device, p))
                        continue;
                dev = ipoib_add_port("ib%d", device, p);
                if (!IS_ERR(dev)) {
                        priv = netdev_priv(dev);
                        list_add_tail(&priv->list, dev_list);
 +                      count++;
                }
        }
  
 +      if (!count) {
 +              kfree(dev_list);
 +              return;
 +      }
 +
        ib_set_client_data(device, &ipoib_client, dev_list);
  }
  
@@@ -1725,6 -1721,9 +1725,6 @@@ static void ipoib_remove_one(struct ib_
        struct ipoib_dev_priv *priv, *tmp;
        struct list_head *dev_list;
  
 -      if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
 -              return;
 -
        dev_list = ib_get_client_data(device, &ipoib_client);
        if (!dev_list)
                return;
diff --combined net/rds/ib_send.c
  #include "rds.h"
  #include "ib.h"
  
 -static char *rds_ib_wc_status_strings[] = {
 -#define RDS_IB_WC_STATUS_STR(foo) \
 -              [IB_WC_##foo] = __stringify(IB_WC_##foo)
 -      RDS_IB_WC_STATUS_STR(SUCCESS),
 -      RDS_IB_WC_STATUS_STR(LOC_LEN_ERR),
 -      RDS_IB_WC_STATUS_STR(LOC_QP_OP_ERR),
 -      RDS_IB_WC_STATUS_STR(LOC_EEC_OP_ERR),
 -      RDS_IB_WC_STATUS_STR(LOC_PROT_ERR),
 -      RDS_IB_WC_STATUS_STR(WR_FLUSH_ERR),
 -      RDS_IB_WC_STATUS_STR(MW_BIND_ERR),
 -      RDS_IB_WC_STATUS_STR(BAD_RESP_ERR),
 -      RDS_IB_WC_STATUS_STR(LOC_ACCESS_ERR),
 -      RDS_IB_WC_STATUS_STR(REM_INV_REQ_ERR),
 -      RDS_IB_WC_STATUS_STR(REM_ACCESS_ERR),
 -      RDS_IB_WC_STATUS_STR(REM_OP_ERR),
 -      RDS_IB_WC_STATUS_STR(RETRY_EXC_ERR),
 -      RDS_IB_WC_STATUS_STR(RNR_RETRY_EXC_ERR),
 -      RDS_IB_WC_STATUS_STR(LOC_RDD_VIOL_ERR),
 -      RDS_IB_WC_STATUS_STR(REM_INV_RD_REQ_ERR),
 -      RDS_IB_WC_STATUS_STR(REM_ABORT_ERR),
 -      RDS_IB_WC_STATUS_STR(INV_EECN_ERR),
 -      RDS_IB_WC_STATUS_STR(INV_EEC_STATE_ERR),
 -      RDS_IB_WC_STATUS_STR(FATAL_ERR),
 -      RDS_IB_WC_STATUS_STR(RESP_TIMEOUT_ERR),
 -      RDS_IB_WC_STATUS_STR(GENERAL_ERR),
 -#undef RDS_IB_WC_STATUS_STR
 -};
 -
 -char *rds_ib_wc_status_str(enum ib_wc_status status)
 -{
 -      return rds_str_array(rds_ib_wc_status_strings,
 -                           ARRAY_SIZE(rds_ib_wc_status_strings), status);
 -}
 -
  /*
   * Convert IB-specific error message to RDS error message and call core
   * completion handler.
@@@ -259,7 -293,7 +259,7 @@@ void rds_ib_send_cq_comp_handler(struc
        while (ib_poll_cq(cq, 1, &wc) > 0) {
                rdsdebug("wc wr_id 0x%llx status %u (%s) byte_len %u imm_data %u\n",
                         (unsigned long long)wc.wr_id, wc.status,
 -                       rds_ib_wc_status_str(wc.status), wc.byte_len,
 +                       ib_wc_status_msg(wc.status), wc.byte_len,
                         be32_to_cpu(wc.ex.imm_data));
                rds_ib_stats_inc(s_ib_tx_cq_event);
  
                        rds_ib_conn_error(conn, "send completion on %pI4 had status "
                                          "%u (%s), disconnecting and reconnecting\n",
                                          &conn->c_faddr, wc.status,
 -                                        rds_ib_wc_status_str(wc.status));
 +                                        ib_wc_status_msg(wc.status));
                }
        }
  }
@@@ -571,6 -605,8 +571,8 @@@ int rds_ib_xmit(struct rds_connection *
                }
  
                rds_message_addref(rm);
+               rm->data.op_dmasg = 0;
+               rm->data.op_dmaoff = 0;
                ic->i_data_op = &rm->data;
  
                /* Finalize the header */
        send = &ic->i_sends[pos];
        first = send;
        prev = NULL;
-       scat = &ic->i_data_op->op_sg[sg];
+       scat = &ic->i_data_op->op_sg[rm->data.op_dmasg];
        i = 0;
        do {
                unsigned int len = 0;
                /* Set up the data, if present */
                if (i < work_alloc
                    && scat != &rm->data.op_sg[rm->data.op_count]) {
-                       len = min(RDS_FRAG_SIZE, ib_sg_dma_len(dev, scat) - off);
+                       len = min(RDS_FRAG_SIZE,
+                               ib_sg_dma_len(dev, scat) - rm->data.op_dmaoff);
                        send->s_wr.num_sge = 2;
  
-                       send->s_sge[1].addr = ib_sg_dma_address(dev, scat) + off;
+                       send->s_sge[1].addr = ib_sg_dma_address(dev, scat);
+                       send->s_sge[1].addr += rm->data.op_dmaoff;
                        send->s_sge[1].length = len;
  
                        bytes_sent += len;
-                       off += len;
-                       if (off == ib_sg_dma_len(dev, scat)) {
+                       rm->data.op_dmaoff += len;
+                       if (rm->data.op_dmaoff == ib_sg_dma_len(dev, scat)) {
                                scat++;
-                               off = 0;
+                               rm->data.op_dmasg++;
+                               rm->data.op_dmaoff = 0;
                        }
                }
  
diff --combined net/rds/rds.h
@@@ -363,6 -363,8 +363,8 @@@ struct rds_message 
                        unsigned int            op_active:1;
                        unsigned int            op_nents;
                        unsigned int            op_count;
+                       unsigned int            op_dmasg;
+                       unsigned int            op_dmaoff;
                        struct scatterlist      *op_sg;
                } data;
        };
@@@ -575,6 -577,7 +577,6 @@@ struct rds_statistics 
  };
  
  /* af_rds.c */
 -char *rds_str_array(char **array, size_t elements, size_t index);
  void rds_sock_addref(struct rds_sock *rs);
  void rds_sock_put(struct rds_sock *rs);
  void rds_wake_sk_sleep(struct rds_sock *rs);