IB/core: Ethernet L2 attributes in verbs/cm structures
[deliverable/linux.git] / drivers / infiniband / core / verbs.c
index d4f6ddf72ffa5add41bd392d6ed773386a93bdb7..7978394738a344bf3c5ed8aba5cadaa7701e9a5a 100644 (file)
@@ -44,6 +44,7 @@
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
+#include <rdma/ib_addr.h>
 
 int ib_rate_to_mult(enum ib_rate rate)
 {
@@ -192,8 +193,28 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
        u32 flow_class;
        u16 gid_index;
        int ret;
+       int is_eth = (rdma_port_get_link_layer(device, port_num) ==
+                       IB_LINK_LAYER_ETHERNET);
 
        memset(ah_attr, 0, sizeof *ah_attr);
+       if (is_eth) {
+               if (!(wc->wc_flags & IB_WC_GRH))
+                       return -EPROTOTYPE;
+
+               if (wc->wc_flags & IB_WC_WITH_SMAC &&
+                   wc->wc_flags & IB_WC_WITH_VLAN) {
+                       memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
+                       ah_attr->vlan_id = wc->vlan_id;
+               } else {
+                       ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
+                                       ah_attr->dmac, &ah_attr->vlan_id);
+                       if (ret)
+                               return ret;
+               }
+       } else {
+               ah_attr->vlan_id = 0xffff;
+       }
+
        ah_attr->dlid = wc->slid;
        ah_attr->sl = wc->sl;
        ah_attr->src_path_bits = wc->dlid_path_bits;
@@ -476,7 +497,9 @@ EXPORT_SYMBOL(ib_create_qp);
 static const struct {
        int                     valid;
        enum ib_qp_attr_mask    req_param[IB_QPT_MAX];
+       enum ib_qp_attr_mask    req_param_add_eth[IB_QPT_MAX];
        enum ib_qp_attr_mask    opt_param[IB_QPT_MAX];
+       enum ib_qp_attr_mask    opt_param_add_eth[IB_QPT_MAX];
 } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
        [IB_QPS_RESET] = {
                [IB_QPS_RESET] = { .valid = 1 },
@@ -557,6 +580,12 @@ static const struct {
                                                IB_QP_MAX_DEST_RD_ATOMIC        |
                                                IB_QP_MIN_RNR_TIMER),
                        },
+                       .req_param_add_eth = {
+                               [IB_QPT_RC]  = (IB_QP_SMAC),
+                               [IB_QPT_UC]  = (IB_QP_SMAC),
+                               [IB_QPT_XRC_INI]  = (IB_QP_SMAC),
+                               [IB_QPT_XRC_TGT]  = (IB_QP_SMAC)
+                       },
                        .opt_param = {
                                 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX               |
                                                 IB_QP_QKEY),
@@ -576,7 +605,21 @@ static const struct {
                                                 IB_QP_QKEY),
                                 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX               |
                                                 IB_QP_QKEY),
-                        }
+                        },
+                       .opt_param_add_eth = {
+                               [IB_QPT_RC]  = (IB_QP_ALT_SMAC                  |
+                                               IB_QP_VID                       |
+                                               IB_QP_ALT_VID),
+                               [IB_QPT_UC]  = (IB_QP_ALT_SMAC                  |
+                                               IB_QP_VID                       |
+                                               IB_QP_ALT_VID),
+                               [IB_QPT_XRC_INI]  = (IB_QP_ALT_SMAC                     |
+                                               IB_QP_VID                       |
+                                               IB_QP_ALT_VID),
+                               [IB_QPT_XRC_TGT]  = (IB_QP_ALT_SMAC                     |
+                                               IB_QP_VID                       |
+                                               IB_QP_ALT_VID)
+                       }
                }
        },
        [IB_QPS_RTR]   = {
@@ -779,7 +822,8 @@ static const struct {
 };
 
 int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
-                      enum ib_qp_type type, enum ib_qp_attr_mask mask)
+                      enum ib_qp_type type, enum ib_qp_attr_mask mask,
+                      enum rdma_link_layer ll)
 {
        enum ib_qp_attr_mask req_param, opt_param;
 
@@ -798,6 +842,13 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
        req_param = qp_state_table[cur_state][next_state].req_param[type];
        opt_param = qp_state_table[cur_state][next_state].opt_param[type];
 
+       if (ll == IB_LINK_LAYER_ETHERNET) {
+               req_param |= qp_state_table[cur_state][next_state].
+                       req_param_add_eth[type];
+               opt_param |= qp_state_table[cur_state][next_state].
+                       opt_param_add_eth[type];
+       }
+
        if ((mask & req_param) != req_param)
                return 0;
 
This page took 0.025395 seconds and 5 git commands to generate.