aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorParav Pandit <parav@mellanox.com>2019-05-02 03:48:03 -0400
committerJason Gunthorpe <jgg@mellanox.com>2019-05-03 10:10:02 -0400
commita70c07397fd80dfeeaead15751ab71449b548826 (patch)
tree7510cecb45238f1f242e54e6c906e144a71a7a0a
parent8f9748602491295b305960cd2cd4976ad15cb04f (diff)
RDMA: Introduce and use GID attr helper to read RoCE L2 fields
Instead of RoCE drivers figuring out vlan, smac fields while working on QP/AH, provide a helper routine to read the L2 fields such as vlan_id and source mac address. This moves logic from mlx5 driver to core for wider usage for RoCE ports. This is a preparation patch to allow detaching netdev in subsequent patch. Signed-off-by: Parav Pandit <parav@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r--drivers/infiniband/core/cache.c55
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c18
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_ah.c14
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c7
-rw-r--r--drivers/infiniband/hw/mlx4/ah.c8
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c6
-rw-r--r--drivers/infiniband/hw/mlx5/main.c42
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_ah.c9
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c7
-rw-r--r--drivers/infiniband/hw/qedr/qedr_roce_cm.c11
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c5
-rw-r--r--include/rdma/ib_cache.h3
12 files changed, 118 insertions, 67 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 7499e7016e38..c164e377e563 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -1250,6 +1250,61 @@ struct net_device *rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr)
1250 return ndev; 1250 return ndev;
1251} 1251}
1252 1252
1253static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
1254{
1255 u16 *vlan_id = data;
1256
1257 if (is_vlan_dev(lower_dev))
1258 *vlan_id = vlan_dev_vlan_id(lower_dev);
1259
1260 /* We are interested only in first level vlan device, so
1261 * always return 1 to stop iterating over next level devices.
1262 */
1263 return 1;
1264}
1265
1266/**
1267 * rdma_read_gid_l2_fields - Read the vlan ID and source MAC address
1268 * of a GID entry.
1269 *
1270 * @attr: GID attribute pointer whose L2 fields to be read
1271 * @vlan_id: Pointer to vlan id to fill up if the GID entry has
1272 * vlan id. It is optional.
1273 * @smac: Pointer to smac to fill up for a GID entry. It is optional.
1274 *
1275 * rdma_read_gid_l2_fields() returns 0 on success and returns vlan id
1276 * (if gid entry has vlan) and source MAC, or returns error.
1277 */
1278int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
1279 u16 *vlan_id, u8 *smac)
1280{
1281 struct net_device *ndev;
1282
1283 ndev = attr->ndev;
1284 if (!ndev)
1285 return -EINVAL;
1286
1287 if (smac)
1288 ether_addr_copy(smac, ndev->dev_addr);
1289 if (vlan_id) {
1290 *vlan_id = 0xffff;
1291 if (is_vlan_dev(ndev)) {
1292 *vlan_id = vlan_dev_vlan_id(ndev);
1293 } else {
1294 /* If the netdev is upper device and if it's lower
1295 * device is vlan device, consider vlan id of the
1296 * the lower vlan device for this gid entry.
1297 */
1298 rcu_read_lock();
1299 netdev_walk_all_lower_dev_rcu(attr->ndev,
1300 get_lower_dev_vlan, vlan_id);
1301 rcu_read_unlock();
1302 }
1303 }
1304 return 0;
1305}
1306EXPORT_SYMBOL(rdma_read_gid_l2_fields);
1307
1253static int config_non_roce_gid_cache(struct ib_device *device, 1308static int config_non_roce_gid_cache(struct ib_device *device,
1254 u8 port, int gid_tbl_len) 1309 u8 port, int gid_tbl_len)
1255{ 1310{
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 3fcc77c03903..cde789cb691b 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -360,8 +360,9 @@ int bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context)
360 struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev); 360 struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
361 struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; 361 struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
362 362
363 if ((attr->ndev) && is_vlan_dev(attr->ndev)) 363 rc = rdma_read_gid_l2_fields(attr, &vlan_id, NULL);
364 vlan_id = vlan_dev_vlan_id(attr->ndev); 364 if (rc)
365 return rc;
365 366
366 rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid, 367 rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid,
367 rdev->qplib_res.netdev->dev_addr, 368 rdev->qplib_res.netdev->dev_addr,
@@ -1637,8 +1638,11 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
1637 qp_attr->ah_attr.roce.dmac); 1638 qp_attr->ah_attr.roce.dmac);
1638 1639
1639 sgid_attr = qp_attr->ah_attr.grh.sgid_attr; 1640 sgid_attr = qp_attr->ah_attr.grh.sgid_attr;
1640 memcpy(qp->qplib_qp.smac, sgid_attr->ndev->dev_addr, 1641 rc = rdma_read_gid_l2_fields(sgid_attr, NULL,
1641 ETH_ALEN); 1642 &qp->qplib_qp.smac[0]);
1643 if (rc)
1644 return rc;
1645
1642 nw_type = rdma_gid_attr_network_type(sgid_attr); 1646 nw_type = rdma_gid_attr_network_type(sgid_attr);
1643 switch (nw_type) { 1647 switch (nw_type) {
1644 case RDMA_NETWORK_IPV4: 1648 case RDMA_NETWORK_IPV4:
@@ -1857,8 +1861,10 @@ static int bnxt_re_build_qp1_send_v2(struct bnxt_re_qp *qp,
1857 1861
1858 memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr)); 1862 memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr));
1859 1863
1860 if (is_vlan_dev(sgid_attr->ndev)) 1864 rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
1861 vlan_id = vlan_dev_vlan_id(sgid_attr->ndev); 1865 if (rc)
1866 return rc;
1867
1862 /* Get network header type for this GID */ 1868 /* Get network header type for this GID */
1863 nw_type = rdma_gid_attr_network_type(sgid_attr); 1869 nw_type = rdma_gid_attr_network_type(sgid_attr);
1864 switch (nw_type) { 1870 switch (nw_type) {
diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c
index d9498313ea46..cdd2ac24fc2a 100644
--- a/drivers/infiniband/hw/hns/hns_roce_ah.c
+++ b/drivers/infiniband/hw/hns/hns_roce_ah.c
@@ -49,20 +49,22 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
49 u16 vlan_tag = 0xffff; 49 u16 vlan_tag = 0xffff;
50 const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr); 50 const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
51 bool vlan_en = false; 51 bool vlan_en = false;
52 int ret;
53
54 gid_attr = ah_attr->grh.sgid_attr;
55 ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag, NULL);
56 if (ret)
57 return ret;
52 58
53 /* Get mac address */ 59 /* Get mac address */
54 memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN); 60 memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
55 61
56 gid_attr = ah_attr->grh.sgid_attr; 62 if (vlan_tag < VLAN_CFI_MASK) {
57 if (is_vlan_dev(gid_attr->ndev)) {
58 vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
59 vlan_en = true; 63 vlan_en = true;
60 }
61
62 if (vlan_tag < 0x1000)
63 vlan_tag |= (rdma_ah_get_sl(ah_attr) & 64 vlan_tag |= (rdma_ah_get_sl(ah_attr) &
64 HNS_ROCE_VLAN_SL_BIT_MASK) << 65 HNS_ROCE_VLAN_SL_BIT_MASK) <<
65 HNS_ROCE_VLAN_SL_SHIFT; 66 HNS_ROCE_VLAN_SL_SHIFT;
67 }
66 68
67 ah->av.port_pd = cpu_to_le32(to_hr_pd(ibah->pd)->pdn | 69 ah->av.port_pd = cpu_to_le32(to_hr_pd(ibah->pd)->pdn |
68 (rdma_ah_get_port_num(ah_attr) << 70 (rdma_ah_get_port_num(ah_attr) <<
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index f155d2d0b8cd..b5392cb5b20f 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -37,6 +37,7 @@
37#include <linux/types.h> 37#include <linux/types.h>
38#include <net/addrconf.h> 38#include <net/addrconf.h>
39#include <rdma/ib_addr.h> 39#include <rdma/ib_addr.h>
40#include <rdma/ib_cache.h>
40#include <rdma/ib_umem.h> 41#include <rdma/ib_umem.h>
41#include <rdma/uverbs_ioctl.h> 42#include <rdma/uverbs_ioctl.h>
42 43
@@ -3984,10 +3985,12 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
3984 3985
3985 if (is_roce_protocol) { 3986 if (is_roce_protocol) {
3986 gid_attr = attr->ah_attr.grh.sgid_attr; 3987 gid_attr = attr->ah_attr.grh.sgid_attr;
3987 vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev); 3988 ret = rdma_read_gid_l2_fields(gid_attr, &vlan, NULL);
3989 if (ret)
3990 goto out;
3988 } 3991 }
3989 3992
3990 if (is_vlan_dev(gid_attr->ndev)) { 3993 if (vlan < VLAN_CFI_MASK) {
3991 roce_set_bit(context->byte_76_srqn_op_en, 3994 roce_set_bit(context->byte_76_srqn_op_en,
3992 V2_QPC_BYTE_76_RQ_VLAN_EN_S, 1); 3995 V2_QPC_BYTE_76_RQ_VLAN_EN_S, 1);
3993 roce_set_bit(qpc_mask->byte_76_srqn_op_en, 3996 roce_set_bit(qpc_mask->byte_76_srqn_op_en,
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index b53772ab2401..02a169f8027b 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -99,9 +99,11 @@ static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
99 */ 99 */
100 gid_attr = ah_attr->grh.sgid_attr; 100 gid_attr = ah_attr->grh.sgid_attr;
101 if (gid_attr) { 101 if (gid_attr) {
102 if (is_vlan_dev(gid_attr->ndev)) 102 ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag,
103 vlan_tag = vlan_dev_vlan_id(gid_attr->ndev); 103 &ah->av.eth.s_mac[0]);
104 memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN); 104 if (ret)
105 return ret;
106
105 ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr); 107 ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
106 if (ret < 0) 108 if (ret < 0)
107 return ret; 109 return ret;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 364e16b5f8e1..bb1c6eb31b32 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -2248,8 +2248,10 @@ static int __mlx4_ib_modify_qp(void *src, enum mlx4_ib_source_type src_type,
2248 2248
2249 if (is_eth) { 2249 if (is_eth) {
2250 gid_attr = attr->ah_attr.grh.sgid_attr; 2250 gid_attr = attr->ah_attr.grh.sgid_attr;
2251 vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev); 2251 err = rdma_read_gid_l2_fields(gid_attr, &vlan,
2252 memcpy(smac, gid_attr->ndev->dev_addr, ETH_ALEN); 2252 &smac[0]);
2253 if (err)
2254 goto out;
2253 } 2255 }
2254 2256
2255 if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path, 2257 if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 6135a0b285de..5ac24bce6e77 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -574,52 +574,22 @@ out:
574 return err; 574 return err;
575} 575}
576 576
577struct mlx5_ib_vlan_info {
578 u16 vlan_id;
579 bool vlan;
580};
581
582static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
583{
584 struct mlx5_ib_vlan_info *vlan_info = data;
585
586 if (is_vlan_dev(lower_dev)) {
587 vlan_info->vlan = true;
588 vlan_info->vlan_id = vlan_dev_vlan_id(lower_dev);
589 }
590 /* We are interested only in first level vlan device, so
591 * always return 1 to stop iterating over next level devices.
592 */
593 return 1;
594}
595
596static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num, 577static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num,
597 unsigned int index, const union ib_gid *gid, 578 unsigned int index, const union ib_gid *gid,
598 const struct ib_gid_attr *attr) 579 const struct ib_gid_attr *attr)
599{ 580{
600 enum ib_gid_type gid_type = IB_GID_TYPE_IB; 581 enum ib_gid_type gid_type = IB_GID_TYPE_IB;
601 struct mlx5_ib_vlan_info vlan_info = { }; 582 u16 vlan_id = 0xffff;
602 u8 roce_version = 0; 583 u8 roce_version = 0;
603 u8 roce_l3_type = 0; 584 u8 roce_l3_type = 0;
604 u8 mac[ETH_ALEN]; 585 u8 mac[ETH_ALEN];
586 int ret;
605 587
606 if (gid) { 588 if (gid) {
607 gid_type = attr->gid_type; 589 gid_type = attr->gid_type;
608 ether_addr_copy(mac, attr->ndev->dev_addr); 590 ret = rdma_read_gid_l2_fields(attr, &vlan_id, &mac[0]);
609 591 if (ret)
610 if (is_vlan_dev(attr->ndev)) { 592 return ret;
611 vlan_info.vlan = true;
612 vlan_info.vlan_id = vlan_dev_vlan_id(attr->ndev);
613 } else {
614 /* If the netdev is upper device and if it's lower
615 * lower device is vlan device, consider vlan id of
616 * the lower vlan device for this gid entry.
617 */
618 rcu_read_lock();
619 netdev_walk_all_lower_dev_rcu(attr->ndev,
620 get_lower_dev_vlan, &vlan_info);
621 rcu_read_unlock();
622 }
623 } 593 }
624 594
625 switch (gid_type) { 595 switch (gid_type) {
@@ -640,7 +610,7 @@ static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num,
640 610
641 return mlx5_core_roce_gid_set(dev->mdev, index, roce_version, 611 return mlx5_core_roce_gid_set(dev->mdev, index, roce_version,
642 roce_l3_type, gid->raw, mac, 612 roce_l3_type, gid->raw, mac,
643 vlan_info.vlan, vlan_info.vlan_id, 613 vlan_id < VLAN_CFI_MASK, vlan_id,
644 port_num); 614 port_num);
645} 615}
646 616
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index a17747cb086a..1d4ea135c28f 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -175,14 +175,15 @@ int ocrdma_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr, u32 flags,
175 if (atomic_cmpxchg(&dev->update_sl, 1, 0)) 175 if (atomic_cmpxchg(&dev->update_sl, 1, 0))
176 ocrdma_init_service_level(dev); 176 ocrdma_init_service_level(dev);
177 177
178 sgid_attr = attr->grh.sgid_attr;
179 status = rdma_read_gid_l2_fields(sgid_attr, &vlan_tag, NULL);
180 if (status)
181 return status;
182
178 status = ocrdma_alloc_av(dev, ah); 183 status = ocrdma_alloc_av(dev, ah);
179 if (status) 184 if (status)
180 goto av_err; 185 goto av_err;
181 186
182 sgid_attr = attr->grh.sgid_attr;
183 if (is_vlan_dev(sgid_attr->ndev))
184 vlan_tag = vlan_dev_vlan_id(sgid_attr->ndev);
185
186 /* Get network header type for this GID */ 187 /* Get network header type for this GID */
187 ah->hdr_type = rdma_gid_attr_network_type(sgid_attr); 188 ah->hdr_type = rdma_gid_attr_network_type(sgid_attr);
188 189
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 5d96b5a94583..32674b291f60 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -2496,7 +2496,7 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
2496 int status; 2496 int status;
2497 struct rdma_ah_attr *ah_attr = &attrs->ah_attr; 2497 struct rdma_ah_attr *ah_attr = &attrs->ah_attr;
2498 const struct ib_gid_attr *sgid_attr; 2498 const struct ib_gid_attr *sgid_attr;
2499 u32 vlan_id = 0xFFFF; 2499 u16 vlan_id = 0xFFFF;
2500 u8 mac_addr[6], hdr_type; 2500 u8 mac_addr[6], hdr_type;
2501 union { 2501 union {
2502 struct sockaddr _sockaddr; 2502 struct sockaddr _sockaddr;
@@ -2526,8 +2526,9 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
2526 sizeof(cmd->params.dgid)); 2526 sizeof(cmd->params.dgid));
2527 2527
2528 sgid_attr = ah_attr->grh.sgid_attr; 2528 sgid_attr = ah_attr->grh.sgid_attr;
2529 vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev); 2529 status = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, &mac_addr[0]);
2530 memcpy(mac_addr, sgid_attr->ndev->dev_addr, ETH_ALEN); 2530 if (status)
2531 return status;
2531 2532
2532 qp->sgid_idx = grh->sgid_index; 2533 qp->sgid_idx = grh->sgid_index;
2533 memcpy(&cmd->params.sgid[0], &sgid_attr->gid.raw[0], 2534 memcpy(&cmd->params.sgid[0], &sgid_attr->gid.raw[0],
diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.c b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
index e1ac2fd60bb1..f5542d703ef9 100644
--- a/drivers/infiniband/hw/qedr/qedr_roce_cm.c
+++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
@@ -397,14 +397,17 @@ static inline int qedr_gsi_build_header(struct qedr_dev *dev,
397 bool has_udp = false; 397 bool has_udp = false;
398 int i; 398 int i;
399 399
400 send_size = 0; 400 rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
401 for (i = 0; i < swr->num_sge; ++i) 401 if (rc)
402 send_size += swr->sg_list[i].length; 402 return rc;
403 403
404 vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev);
405 if (vlan_id < VLAN_CFI_MASK) 404 if (vlan_id < VLAN_CFI_MASK)
406 has_vlan = true; 405 has_vlan = true;
407 406
407 send_size = 0;
408 for (i = 0; i < swr->num_sge; ++i)
409 send_size += swr->sg_list[i].length;
410
408 has_udp = (sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP); 411 has_udp = (sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP);
409 if (!has_udp) { 412 if (!has_udp) {
410 /* RoCE v1 */ 413 /* RoCE v1 */
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 5e92b6229da2..e52d8761d681 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -1050,10 +1050,13 @@ static inline int get_gid_info_from_table(struct ib_qp *ibqp,
1050 enum rdma_network_type nw_type; 1050 enum rdma_network_type nw_type;
1051 const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr); 1051 const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
1052 u32 ipv4_addr; 1052 u32 ipv4_addr;
1053 int ret;
1053 int i; 1054 int i;
1054 1055
1055 gid_attr = grh->sgid_attr; 1056 gid_attr = grh->sgid_attr;
1056 qp_params->vlan_id = rdma_vlan_dev_vlan_id(gid_attr->ndev); 1057 ret = rdma_read_gid_l2_fields(gid_attr, &qp_params->vlan_id, NULL);
1058 if (ret)
1059 return ret;
1057 1060
1058 nw_type = rdma_gid_attr_network_type(gid_attr); 1061 nw_type = rdma_gid_attr_network_type(gid_attr);
1059 switch (nw_type) { 1062 switch (nw_type) {
diff --git a/include/rdma/ib_cache.h b/include/rdma/ib_cache.h
index 62e990b620aa..730a65ad8c74 100644
--- a/include/rdma/ib_cache.h
+++ b/include/rdma/ib_cache.h
@@ -54,6 +54,9 @@ const struct ib_gid_attr *rdma_find_gid_by_filter(
54 void *), 54 void *),
55 void *context); 55 void *context);
56 56
57int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
58 u16 *vlan_id, u8 *smac);
59
57/** 60/**
58 * ib_get_cached_pkey - Returns a cached PKey table entry 61 * ib_get_cached_pkey - Returns a cached PKey table entry
59 * @device: The device to query. 62 * @device: The device to query.