Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Parav Pandit and committed by
Jason Gunthorpe
a70c0739 8f974860

+118 -67
+55
drivers/infiniband/core/cache.c
··· 1250 1250 return ndev; 1251 1251 } 1252 1252 1253 + static 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 + */ 1278 + int 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 + } 1306 + EXPORT_SYMBOL(rdma_read_gid_l2_fields); 1307 + 1253 1308 static int config_non_roce_gid_cache(struct ib_device *device, 1254 1309 u8 port, int gid_tbl_len) 1255 1310 {
+12 -6
drivers/infiniband/hw/bnxt_re/ib_verbs.c
··· 360 360 struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev); 361 361 struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; 362 362 363 - if ((attr->ndev) && is_vlan_dev(attr->ndev)) 364 - vlan_id = vlan_dev_vlan_id(attr->ndev); 363 + rc = rdma_read_gid_l2_fields(attr, &vlan_id, NULL); 364 + if (rc) 365 + return rc; 365 366 366 367 rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid, 367 368 rdev->qplib_res.netdev->dev_addr, ··· 1638 1637 qp_attr->ah_attr.roce.dmac); 1639 1638 1640 1639 sgid_attr = qp_attr->ah_attr.grh.sgid_attr; 1641 - memcpy(qp->qplib_qp.smac, sgid_attr->ndev->dev_addr, 1642 - ETH_ALEN); 1640 + rc = rdma_read_gid_l2_fields(sgid_attr, NULL, 1641 + &qp->qplib_qp.smac[0]); 1642 + if (rc) 1643 + return rc; 1644 + 1643 1645 nw_type = rdma_gid_attr_network_type(sgid_attr); 1644 1646 switch (nw_type) { 1645 1647 case RDMA_NETWORK_IPV4: ··· 1861 1857 1862 1858 memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr)); 1863 1859 1864 - if (is_vlan_dev(sgid_attr->ndev)) 1865 - vlan_id = vlan_dev_vlan_id(sgid_attr->ndev); 1860 + rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL); 1861 + if (rc) 1862 + return rc; 1863 + 1866 1864 /* Get network header type for this GID */ 1867 1865 nw_type = rdma_gid_attr_network_type(sgid_attr); 1868 1866 switch (nw_type) {
+8 -6
drivers/infiniband/hw/hns/hns_roce_ah.c
··· 49 49 u16 vlan_tag = 0xffff; 50 50 const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr); 51 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 59 /* Get mac address */ 54 60 memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN); 55 61 56 - gid_attr = ah_attr->grh.sgid_attr; 57 - if (is_vlan_dev(gid_attr->ndev)) { 58 - vlan_tag = vlan_dev_vlan_id(gid_attr->ndev); 62 + if (vlan_tag < VLAN_CFI_MASK) { 59 63 vlan_en = true; 60 - } 61 - 62 - if (vlan_tag < 0x1000) 63 64 vlan_tag |= (rdma_ah_get_sl(ah_attr) & 64 65 HNS_ROCE_VLAN_SL_BIT_MASK) << 65 66 HNS_ROCE_VLAN_SL_SHIFT; 67 + } 66 68 67 69 ah->av.port_pd = cpu_to_le32(to_hr_pd(ibah->pd)->pdn | 68 70 (rdma_ah_get_port_num(ah_attr) <<
+5 -2
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
··· 37 37 #include <linux/types.h> 38 38 #include <net/addrconf.h> 39 39 #include <rdma/ib_addr.h> 40 + #include <rdma/ib_cache.h> 40 41 #include <rdma/ib_umem.h> 41 42 #include <rdma/uverbs_ioctl.h> 42 43 ··· 3985 3984 3986 3985 if (is_roce_protocol) { 3987 3986 gid_attr = attr->ah_attr.grh.sgid_attr; 3988 - vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev); 3987 + ret = rdma_read_gid_l2_fields(gid_attr, &vlan, NULL); 3988 + if (ret) 3989 + goto out; 3989 3990 } 3990 3991 3991 - if (is_vlan_dev(gid_attr->ndev)) { 3992 + if (vlan < VLAN_CFI_MASK) { 3992 3993 roce_set_bit(context->byte_76_srqn_op_en, 3993 3994 V2_QPC_BYTE_76_RQ_VLAN_EN_S, 1); 3994 3995 roce_set_bit(qpc_mask->byte_76_srqn_op_en,
+5 -3
drivers/infiniband/hw/mlx4/ah.c
··· 99 99 */ 100 100 gid_attr = ah_attr->grh.sgid_attr; 101 101 if (gid_attr) { 102 - if (is_vlan_dev(gid_attr->ndev)) 103 - vlan_tag = vlan_dev_vlan_id(gid_attr->ndev); 104 - memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN); 102 + ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag, 103 + &ah->av.eth.s_mac[0]); 104 + if (ret) 105 + return ret; 106 + 105 107 ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr); 106 108 if (ret < 0) 107 109 return ret;
+4 -2
drivers/infiniband/hw/mlx4/qp.c
··· 2248 2248 2249 2249 if (is_eth) { 2250 2250 gid_attr = attr->ah_attr.grh.sgid_attr; 2251 - vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev); 2252 - memcpy(smac, gid_attr->ndev->dev_addr, ETH_ALEN); 2251 + err = rdma_read_gid_l2_fields(gid_attr, &vlan, 2252 + &smac[0]); 2253 + if (err) 2254 + goto out; 2253 2255 } 2254 2256 2255 2257 if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
+6 -36
drivers/infiniband/hw/mlx5/main.c
··· 574 574 return err; 575 575 } 576 576 577 - struct mlx5_ib_vlan_info { 578 - u16 vlan_id; 579 - bool vlan; 580 - }; 581 - 582 - static 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 - 596 577 static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num, 597 578 unsigned int index, const union ib_gid *gid, 598 579 const struct ib_gid_attr *attr) 599 580 { 600 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 583 u8 roce_version = 0; 603 584 u8 roce_l3_type = 0; 604 585 u8 mac[ETH_ALEN]; 586 + int ret; 605 587 606 588 if (gid) { 607 589 gid_type = attr->gid_type; 608 - ether_addr_copy(mac, attr->ndev->dev_addr); 609 - 610 - if (is_vlan_dev(attr->ndev)) { 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 - } 590 + ret = rdma_read_gid_l2_fields(attr, &vlan_id, &mac[0]); 591 + if (ret) 592 + return ret; 623 593 } 624 594 625 595 switch (gid_type) { ··· 610 640 611 641 return mlx5_core_roce_gid_set(dev->mdev, index, roce_version, 612 642 roce_l3_type, gid->raw, mac, 613 - vlan_info.vlan, vlan_info.vlan_id, 643 + vlan_id < VLAN_CFI_MASK, vlan_id, 614 644 port_num); 615 645 } 616 646
+5 -4
drivers/infiniband/hw/ocrdma/ocrdma_ah.c
··· 175 175 if (atomic_cmpxchg(&dev->update_sl, 1, 0)) 176 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 183 status = ocrdma_alloc_av(dev, ah); 179 184 if (status) 180 185 goto av_err; 181 - 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 186 187 /* Get network header type for this GID */ 187 188 ah->hdr_type = rdma_gid_attr_network_type(sgid_attr);
+4 -3
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
··· 2496 2496 int status; 2497 2497 struct rdma_ah_attr *ah_attr = &attrs->ah_attr; 2498 2498 const struct ib_gid_attr *sgid_attr; 2499 - u32 vlan_id = 0xFFFF; 2499 + u16 vlan_id = 0xFFFF; 2500 2500 u8 mac_addr[6], hdr_type; 2501 2501 union { 2502 2502 struct sockaddr _sockaddr; ··· 2526 2526 sizeof(cmd->params.dgid)); 2527 2527 2528 2528 sgid_attr = ah_attr->grh.sgid_attr; 2529 - vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev); 2530 - memcpy(mac_addr, sgid_attr->ndev->dev_addr, ETH_ALEN); 2529 + status = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, &mac_addr[0]); 2530 + if (status) 2531 + return status; 2531 2532 2532 2533 qp->sgid_idx = grh->sgid_index; 2533 2534 memcpy(&cmd->params.sgid[0], &sgid_attr->gid.raw[0],
+7 -4
drivers/infiniband/hw/qedr/qedr_roce_cm.c
··· 397 397 bool has_udp = false; 398 398 int i; 399 399 400 + rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL); 401 + if (rc) 402 + return rc; 403 + 404 + if (vlan_id < VLAN_CFI_MASK) 405 + has_vlan = true; 406 + 400 407 send_size = 0; 401 408 for (i = 0; i < swr->num_sge; ++i) 402 409 send_size += swr->sg_list[i].length; 403 - 404 - vlan_id = rdma_vlan_dev_vlan_id(sgid_attr->ndev); 405 - if (vlan_id < VLAN_CFI_MASK) 406 - has_vlan = true; 407 410 408 411 has_udp = (sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP); 409 412 if (!has_udp) {
+4 -1
drivers/infiniband/hw/qedr/verbs.c
··· 1050 1050 enum rdma_network_type nw_type; 1051 1051 const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr); 1052 1052 u32 ipv4_addr; 1053 + int ret; 1053 1054 int i; 1054 1055 1055 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 1061 nw_type = rdma_gid_attr_network_type(gid_attr); 1059 1062 switch (nw_type) {
+3
include/rdma/ib_cache.h
··· 54 54 void *), 55 55 void *context); 56 56 57 + int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr, 58 + u16 *vlan_id, u8 *smac); 59 + 57 60 /** 58 61 * ib_get_cached_pkey - Returns a cached PKey table entry 59 62 * @device: The device to query.